Auto merge of #130025 - Urgau:missing_docs-expect, r=petrochenkov
Also emit `missing_docs` lint with `--test` to fulfil expectations
This PR removes the "test harness" suppression of the `missing_docs` lint to be able to fulfil `#[expect]` (expectations) as it is now "relevant".
I think the goal was to maybe avoid false-positive while linting on public items under `#[cfg(test)]` but with effective visibility we should no longer have any false-positive.
Another possibility would be to query the lint level and only emit the lint if it's of expect level, but that is even more hacky.
Fixes https://github.com/rust-lang/rust/issues/130021
try-job: x86_64-gnu-aux
diff --git a/.gitmodules b/.gitmodules
index b5250d4..9268073 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -47,3 +47,7 @@
path = src/tools/rustc-perf
url = https://github.com/rust-lang/rustc-perf.git
shallow = true
+[submodule "src/tools/enzyme"]
+ path = src/tools/enzyme
+ url = https://github.com/EnzymeAD/Enzyme.git
+ shallow = true
diff --git a/Cargo.lock b/Cargo.lock
index d671419..81aecf1 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -4167,6 +4167,7 @@
"rustc_errors",
"rustc_feature",
"rustc_fluent_macro",
+ "rustc_index",
"rustc_lexer",
"rustc_macros",
"rustc_session",
diff --git a/RELEASES.md b/RELEASES.md
index 29c872e..b49470c 100644
--- a/RELEASES.md
+++ b/RELEASES.md
@@ -34,7 +34,6 @@
- [Add Tier 3 `std` Xtensa targets:](https://github.com/rust-lang/rust/pull/126380/) `xtensa-esp32-espidf`, `xtensa-esp32s2-espidf`, `xtensa-esp32s3-espidf`
- [Add Tier 3 i686 Redox OS target:](https://github.com/rust-lang/rust/pull/126192/) `i686-unknown-redox`
- [Promote `arm64ec-pc-windows-msvc` to Tier 2.](https://github.com/rust-lang/rust/pull/126039/)
- - [Promote `wasm32-wasip2` to Tier 2.](https://github.com/rust-lang/rust/pull/126967/)
- [Promote `loongarch64-unknown-linux-musl` to Tier 2 with host tools.](https://github.com/rust-lang/rust/pull/126298/)
- [Enable full tools and profiler for LoongArch Linux targets.](https://github.com/rust-lang/rust/pull/127078/)
- [Unconditionally warn on usage of `wasm32-wasi`.](https://github.com/rust-lang/rust/pull/126662/) (see compatibility note below)
@@ -100,6 +99,9 @@
The reason is that these types have different roles: `std::panic::PanicHookInfo` is the argument to the [panic hook](https://doc.rust-lang.org/stable/std/panic/fn.set_hook.html) in std context (where panics can have an arbitrary payload), while `core::panic::PanicInfo` is the argument to the [`#[panic_handler]`](https://doc.rust-lang.org/nomicon/panic-handler.html) in no_std context (where panics always carry a formatted *message*). Separating these types allows us to add more useful methods to these types, such as `std::panic::PanicHookInfo::payload_as_str()` and `core::panic::PanicInfo::message()`.
* The new sort implementations may panic if a type's implementation of [`Ord`](https://doc.rust-lang.org/std/cmp/trait.Ord.html) (or the given comparison function) does not implement a [total order](https://en.wikipedia.org/wiki/Total_order) as the trait requires. `Ord`'s supertraits (`PartialOrd`, `Eq`, and `PartialEq`) must also be consistent. The previous implementations would not "notice" any problem, but the new implementations have a good chance of detecting inconsistencies, throwing a panic rather than returning knowingly unsorted data.
+* [In very rare cases, a change in the internal evaluation order of the trait
+ solver may result in new fatal overflow errors.](https://github.com/rust-lang/rust/pull/126128)
+
<a id="1.81.0-Internal-Changes"></a>
diff --git a/compiler/rustc_ast/src/mut_visit.rs b/compiler/rustc_ast/src/mut_visit.rs
index 8a66894..7c8af6c 100644
--- a/compiler/rustc_ast/src/mut_visit.rs
+++ b/compiler/rustc_ast/src/mut_visit.rs
@@ -752,7 +752,7 @@ fn visit_lazy_tts<T: MutVisitor>(vis: &mut T, lazy_tts: &mut Option<LazyAttrToke
pub fn visit_token<T: MutVisitor>(vis: &mut T, t: &mut Token) {
let Token { kind, span } = t;
match kind {
- token::Ident(name, _ /*raw*/) | token::Lifetime(name) => {
+ token::Ident(name, _is_raw) | token::Lifetime(name, _is_raw) => {
let mut ident = Ident::new(*name, *span);
vis.visit_ident(&mut ident);
*name = ident.name;
@@ -762,7 +762,7 @@ pub fn visit_token<T: MutVisitor>(vis: &mut T, t: &mut Token) {
token::NtIdent(ident, _is_raw) => {
vis.visit_ident(ident);
}
- token::NtLifetime(ident) => {
+ token::NtLifetime(ident, _is_raw) => {
vis.visit_ident(ident);
}
token::Interpolated(nt) => {
diff --git a/compiler/rustc_ast/src/token.rs b/compiler/rustc_ast/src/token.rs
index f1dddb3..a0082a4 100644
--- a/compiler/rustc_ast/src/token.rs
+++ b/compiler/rustc_ast/src/token.rs
@@ -331,11 +331,11 @@ pub enum TokenKind {
/// Do not forget about `NtLifetime` when you want to match on lifetime identifiers.
/// It's recommended to use `Token::(lifetime,uninterpolate,uninterpolated_span)` to
/// treat regular and interpolated lifetime identifiers in the same way.
- Lifetime(Symbol),
+ Lifetime(Symbol, IdentIsRaw),
/// This identifier (and its span) is the lifetime passed to the
/// declarative macro. The span in the surrounding `Token` is the span of
/// the `lifetime` metavariable in the macro's RHS.
- NtLifetime(Ident),
+ 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.
@@ -458,7 +458,7 @@ pub fn from_ast_ident(ident: Ident) -> Self {
/// if they keep spans or perform edition checks.
pub fn uninterpolated_span(&self) -> Span {
match self.kind {
- NtIdent(ident, _) | NtLifetime(ident) => ident.span,
+ NtIdent(ident, _) | NtLifetime(ident, _) => ident.span,
Interpolated(ref nt) => nt.use_span(),
_ => self.span,
}
@@ -661,7 +661,9 @@ pub fn can_begin_string_literal(&self) -> bool {
pub fn uninterpolate(&self) -> Cow<'_, Token> {
match self.kind {
NtIdent(ident, is_raw) => Cow::Owned(Token::new(Ident(ident.name, is_raw), ident.span)),
- NtLifetime(ident) => Cow::Owned(Token::new(Lifetime(ident.name), ident.span)),
+ NtLifetime(ident, is_raw) => {
+ Cow::Owned(Token::new(Lifetime(ident.name, is_raw), ident.span))
+ }
_ => Cow::Borrowed(self),
}
}
@@ -679,11 +681,11 @@ pub fn ident(&self) -> Option<(Ident, IdentIsRaw)> {
/// Returns a lifetime identifier if this token is a lifetime.
#[inline]
- pub fn lifetime(&self) -> Option<Ident> {
+ pub fn lifetime(&self) -> Option<(Ident, IdentIsRaw)> {
// We avoid using `Token::uninterpolate` here because it's slow.
match self.kind {
- Lifetime(name) => Some(Ident::new(name, self.span)),
- NtLifetime(ident) => Some(ident),
+ Lifetime(name, is_raw) => Some((Ident::new(name, self.span), is_raw)),
+ NtLifetime(ident, is_raw) => Some((ident, is_raw)),
_ => None,
}
}
@@ -865,7 +867,7 @@ pub fn glue(&self, joint: &Token) -> Option<Token> {
_ => return None,
},
SingleQuote => match joint.kind {
- Ident(name, IdentIsRaw::No) => Lifetime(Symbol::intern(&format!("'{name}"))),
+ Ident(name, is_raw) => Lifetime(Symbol::intern(&format!("'{name}")), is_raw),
_ => return None,
},
diff --git a/compiler/rustc_ast/src/tokenstream.rs b/compiler/rustc_ast/src/tokenstream.rs
index 057b445..fc1dd2c 100644
--- a/compiler/rustc_ast/src/tokenstream.rs
+++ b/compiler/rustc_ast/src/tokenstream.rs
@@ -482,11 +482,11 @@ fn flatten_token(token: &Token, spacing: Spacing) -> TokenTree {
token::NtIdent(ident, is_raw) => {
TokenTree::Token(Token::new(token::Ident(ident.name, is_raw), ident.span), spacing)
}
- token::NtLifetime(ident) => TokenTree::Delimited(
+ token::NtLifetime(ident, is_raw) => TokenTree::Delimited(
DelimSpan::from_single(token.span),
DelimSpacing::new(Spacing::JointHidden, spacing),
Delimiter::Invisible,
- TokenStream::token_alone(token::Lifetime(ident.name), ident.span),
+ TokenStream::token_alone(token::Lifetime(ident.name, is_raw), ident.span),
),
token::Interpolated(ref nt) => TokenTree::Delimited(
DelimSpan::from_single(token.span),
diff --git a/compiler/rustc_ast_pretty/src/pprust/state.rs b/compiler/rustc_ast_pretty/src/pprust/state.rs
index c7ff39d..3b1449d 100644
--- a/compiler/rustc_ast_pretty/src/pprust/state.rs
+++ b/compiler/rustc_ast_pretty/src/pprust/state.rs
@@ -11,7 +11,9 @@
use ast::TraitBoundModifiers;
use rustc_ast::attr::AttrIdGenerator;
use rustc_ast::ptr::P;
-use rustc_ast::token::{self, BinOpToken, CommentKind, Delimiter, Nonterminal, Token, TokenKind};
+use rustc_ast::token::{
+ self, BinOpToken, CommentKind, Delimiter, IdentIsRaw, Nonterminal, Token, TokenKind,
+};
use rustc_ast::tokenstream::{Spacing, TokenStream, TokenTree};
use rustc_ast::util::classify;
use rustc_ast::util::comments::{Comment, CommentStyle};
@@ -947,8 +949,13 @@ fn token_kind_to_string_ext(
token::NtIdent(ident, is_raw) => {
IdentPrinter::for_ast_ident(ident, is_raw.into()).to_string().into()
}
- token::Lifetime(name) => name.to_string().into(),
- token::NtLifetime(ident) => ident.name.to_string().into(),
+
+ token::Lifetime(name, IdentIsRaw::No)
+ | token::NtLifetime(Ident { name, .. }, IdentIsRaw::No) => name.to_string().into(),
+ token::Lifetime(name, IdentIsRaw::Yes)
+ | token::NtLifetime(Ident { name, .. }, IdentIsRaw::Yes) => {
+ format!("'r#{}", &name.as_str()[1..]).into()
+ }
/* Other */
token::DocComment(comment_kind, attr_style, data) => {
diff --git a/compiler/rustc_borrowck/src/borrowck_errors.rs b/compiler/rustc_borrowck/src/borrowck_errors.rs
index 2c672db..3a7e407 100644
--- a/compiler/rustc_borrowck/src/borrowck_errors.rs
+++ b/compiler/rustc_borrowck/src/borrowck_errors.rs
@@ -8,7 +8,7 @@
use rustc_middle::ty::{self, Ty, TyCtxt};
use rustc_span::Span;
-impl<'infcx, 'tcx> crate::MirBorrowckCtxt<'_, '_, 'infcx, 'tcx> {
+impl<'infcx, 'tcx> crate::MirBorrowckCtxt<'_, 'infcx, 'tcx> {
pub(crate) fn dcx(&self) -> DiagCtxtHandle<'infcx> {
self.infcx.dcx()
}
diff --git a/compiler/rustc_borrowck/src/dataflow.rs b/compiler/rustc_borrowck/src/dataflow.rs
index 9bb6109..39994ad 100644
--- a/compiler/rustc_borrowck/src/dataflow.rs
+++ b/compiler/rustc_borrowck/src/dataflow.rs
@@ -15,24 +15,24 @@
use crate::{places_conflict, BorrowSet, PlaceConflictBias, PlaceExt, RegionInferenceContext};
/// The results of the dataflow analyses used by the borrow checker.
-pub(crate) struct BorrowckResults<'a, 'mir, 'tcx> {
- pub(crate) borrows: Results<'tcx, Borrows<'a, 'mir, 'tcx>>,
- pub(crate) uninits: Results<'tcx, MaybeUninitializedPlaces<'a, 'mir, 'tcx>>,
- pub(crate) ever_inits: Results<'tcx, EverInitializedPlaces<'a, 'mir, 'tcx>>,
+pub(crate) struct BorrowckResults<'a, 'tcx> {
+ pub(crate) borrows: Results<'tcx, Borrows<'a, 'tcx>>,
+ pub(crate) uninits: Results<'tcx, MaybeUninitializedPlaces<'a, 'tcx>>,
+ pub(crate) ever_inits: Results<'tcx, EverInitializedPlaces<'a, 'tcx>>,
}
/// The transient state of the dataflow analyses used by the borrow checker.
#[derive(Debug)]
-pub(crate) struct BorrowckFlowState<'a, 'mir, 'tcx> {
- pub(crate) borrows: <Borrows<'a, 'mir, 'tcx> as AnalysisDomain<'tcx>>::Domain,
- pub(crate) uninits: <MaybeUninitializedPlaces<'a, 'mir, 'tcx> as AnalysisDomain<'tcx>>::Domain,
- pub(crate) ever_inits: <EverInitializedPlaces<'a, 'mir, 'tcx> as AnalysisDomain<'tcx>>::Domain,
+pub(crate) struct BorrowckFlowState<'a, 'tcx> {
+ pub(crate) borrows: <Borrows<'a, 'tcx> as AnalysisDomain<'tcx>>::Domain,
+ pub(crate) uninits: <MaybeUninitializedPlaces<'a, 'tcx> as AnalysisDomain<'tcx>>::Domain,
+ pub(crate) ever_inits: <EverInitializedPlaces<'a, 'tcx> as AnalysisDomain<'tcx>>::Domain,
}
-impl<'a, 'mir, 'tcx> ResultsVisitable<'tcx> for BorrowckResults<'a, 'mir, 'tcx> {
+impl<'a, 'tcx> ResultsVisitable<'tcx> for BorrowckResults<'a, 'tcx> {
// All three analyses are forward, but we have to use just one here.
- type Direction = <Borrows<'a, 'mir, 'tcx> as AnalysisDomain<'tcx>>::Direction;
- type FlowState = BorrowckFlowState<'a, 'mir, 'tcx>;
+ type Direction = <Borrows<'a, 'tcx> as AnalysisDomain<'tcx>>::Direction;
+ type FlowState = BorrowckFlowState<'a, 'tcx>;
fn new_flow_state(&self, body: &mir::Body<'tcx>) -> Self::FlowState {
BorrowckFlowState {
@@ -106,10 +106,9 @@ pub struct BorrowIndex {}
/// `BorrowIndex`, and maps each such index to a `BorrowData`
/// describing the borrow. These indexes are used for representing the
/// borrows in compact bitvectors.
-pub struct Borrows<'a, 'mir, 'tcx> {
+pub struct Borrows<'a, 'tcx> {
tcx: TyCtxt<'tcx>,
- body: &'mir Body<'tcx>,
-
+ body: &'a Body<'tcx>,
borrow_set: &'a BorrowSet<'tcx>,
borrows_out_of_scope_at_location: FxIndexMap<Location, Vec<BorrowIndex>>,
}
@@ -389,10 +388,10 @@ fn loan_kill_location(
}
}
-impl<'a, 'mir, 'tcx> Borrows<'a, 'mir, 'tcx> {
+impl<'a, 'tcx> Borrows<'a, 'tcx> {
pub fn new(
tcx: TyCtxt<'tcx>,
- body: &'mir Body<'tcx>,
+ body: &'a Body<'tcx>,
regioncx: &RegionInferenceContext<'tcx>,
borrow_set: &'a BorrowSet<'tcx>,
) -> Self {
@@ -494,7 +493,7 @@ fn kill_borrows_on_place(&self, trans: &mut impl GenKill<BorrowIndex>, place: Pl
}
}
-impl<'tcx> rustc_mir_dataflow::AnalysisDomain<'tcx> for Borrows<'_, '_, 'tcx> {
+impl<'tcx> rustc_mir_dataflow::AnalysisDomain<'tcx> for Borrows<'_, 'tcx> {
type Domain = BitSet<BorrowIndex>;
const NAME: &'static str = "borrows";
@@ -517,7 +516,7 @@ fn initialize_start_block(&self, _: &mir::Body<'tcx>, _: &mut Self::Domain) {
/// region stops containing the CFG points reachable from the issuing location.
/// - we also kill loans of conflicting places when overwriting a shared path: e.g. borrows of
/// `a.b.c` when `a` is overwritten.
-impl<'tcx> rustc_mir_dataflow::GenKillAnalysis<'tcx> for Borrows<'_, '_, 'tcx> {
+impl<'tcx> rustc_mir_dataflow::GenKillAnalysis<'tcx> for Borrows<'_, 'tcx> {
type Idx = BorrowIndex;
fn domain_size(&self, _: &mir::Body<'tcx>) -> usize {
@@ -617,8 +616,8 @@ fn call_return_effect(
}
}
-impl DebugWithContext<Borrows<'_, '_, '_>> for BorrowIndex {
- fn fmt_with(&self, ctxt: &Borrows<'_, '_, '_>, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+impl DebugWithContext<Borrows<'_, '_>> for BorrowIndex {
+ fn fmt_with(&self, ctxt: &Borrows<'_, '_>, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{:?}", ctxt.location(*self))
}
}
diff --git a/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs
index 8a4e89d4..ee28e55 100644
--- a/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs
@@ -52,7 +52,7 @@ pub(crate) fn relate(expected: Ty<'tcx>, found: Ty<'tcx>) -> UniverseInfo<'tcx>
pub(crate) fn report_error(
&self,
- mbcx: &mut MirBorrowckCtxt<'_, '_, '_, 'tcx>,
+ mbcx: &mut MirBorrowckCtxt<'_, '_, 'tcx>,
placeholder: ty::PlaceholderRegion,
error_element: RegionElement,
cause: ObligationCause<'tcx>,
@@ -151,7 +151,7 @@ trait TypeOpInfo<'tcx> {
fn nice_error<'infcx>(
&self,
- mbcx: &mut MirBorrowckCtxt<'_, '_, 'infcx, 'tcx>,
+ mbcx: &mut MirBorrowckCtxt<'_, 'infcx, 'tcx>,
cause: ObligationCause<'tcx>,
placeholder_region: ty::Region<'tcx>,
error_region: Option<ty::Region<'tcx>>,
@@ -160,7 +160,7 @@ fn nice_error<'infcx>(
#[instrument(level = "debug", skip(self, mbcx))]
fn report_error(
&self,
- mbcx: &mut MirBorrowckCtxt<'_, '_, '_, 'tcx>,
+ mbcx: &mut MirBorrowckCtxt<'_, '_, 'tcx>,
placeholder: ty::PlaceholderRegion,
error_element: RegionElement,
cause: ObligationCause<'tcx>,
@@ -233,7 +233,7 @@ fn base_universe(&self) -> ty::UniverseIndex {
fn nice_error<'infcx>(
&self,
- mbcx: &mut MirBorrowckCtxt<'_, '_, 'infcx, 'tcx>,
+ mbcx: &mut MirBorrowckCtxt<'_, 'infcx, 'tcx>,
cause: ObligationCause<'tcx>,
placeholder_region: ty::Region<'tcx>,
error_region: Option<ty::Region<'tcx>>,
@@ -277,7 +277,7 @@ fn base_universe(&self) -> ty::UniverseIndex {
fn nice_error<'infcx>(
&self,
- mbcx: &mut MirBorrowckCtxt<'_, '_, 'infcx, 'tcx>,
+ mbcx: &mut MirBorrowckCtxt<'_, 'infcx, 'tcx>,
cause: ObligationCause<'tcx>,
placeholder_region: ty::Region<'tcx>,
error_region: Option<ty::Region<'tcx>>,
@@ -324,7 +324,7 @@ fn base_universe(&self) -> ty::UniverseIndex {
fn nice_error<'infcx>(
&self,
- mbcx: &mut MirBorrowckCtxt<'_, '_, 'infcx, 'tcx>,
+ mbcx: &mut MirBorrowckCtxt<'_, 'infcx, 'tcx>,
cause: ObligationCause<'tcx>,
placeholder_region: ty::Region<'tcx>,
error_region: Option<ty::Region<'tcx>>,
@@ -357,7 +357,7 @@ fn base_universe(&self) -> ty::UniverseIndex {
fn nice_error<'infcx>(
&self,
- mbcx: &mut MirBorrowckCtxt<'_, '_, 'infcx, 'tcx>,
+ mbcx: &mut MirBorrowckCtxt<'_, 'infcx, 'tcx>,
_cause: ObligationCause<'tcx>,
placeholder_region: ty::Region<'tcx>,
error_region: Option<ty::Region<'tcx>>,
diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
index c817b6f..a47518f 100644
--- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
@@ -69,7 +69,7 @@ enum StorageDeadOrDrop<'tcx> {
Destructor(Ty<'tcx>),
}
-impl<'infcx, 'tcx> MirBorrowckCtxt<'_, '_, 'infcx, 'tcx> {
+impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
pub(crate) fn report_use_of_moved_or_uninitialized(
&mut self,
location: Location,
@@ -4358,11 +4358,7 @@ enum AnnotatedBorrowFnSignature<'tcx> {
impl<'tcx> AnnotatedBorrowFnSignature<'tcx> {
/// Annotate the provided diagnostic with information about borrow from the fn signature that
/// helps explain.
- pub(crate) fn emit(
- &self,
- cx: &MirBorrowckCtxt<'_, '_, '_, 'tcx>,
- diag: &mut Diag<'_>,
- ) -> String {
+ pub(crate) fn emit(&self, cx: &MirBorrowckCtxt<'_, '_, 'tcx>, diag: &mut Diag<'_>) -> String {
match self {
&AnnotatedBorrowFnSignature::Closure { argument_ty, argument_span } => {
diag.span_label(
diff --git a/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs b/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs
index 91b02a3..419e72d 100644
--- a/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs
@@ -390,7 +390,7 @@ fn add_lifetime_bound_suggestion_to_diagnostic(
}
}
-impl<'tcx> MirBorrowckCtxt<'_, '_, '_, 'tcx> {
+impl<'tcx> MirBorrowckCtxt<'_, '_, 'tcx> {
fn free_region_constraint_info(
&self,
borrow_region: RegionVid,
@@ -662,9 +662,10 @@ fn was_captured_by_trait_object(&self, borrow: &BorrowData<'tcx>) -> bool {
// `&dyn Trait`
ty::Ref(_, ty, _) if ty.is_trait() => true,
// `Box<dyn Trait>`
- _ if ty.is_box() && ty.boxed_ty().is_trait() => {
+ _ if ty.boxed_ty().is_some_and(Ty::is_trait) => {
true
}
+
// `dyn Trait`
_ if ty.is_trait() => true,
// Anything else.
diff --git a/compiler/rustc_borrowck/src/diagnostics/mod.rs b/compiler/rustc_borrowck/src/diagnostics/mod.rs
index 5ab6696..e52ddfa 100644
--- a/compiler/rustc_borrowck/src/diagnostics/mod.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/mod.rs
@@ -68,7 +68,7 @@ pub(super) struct DescribePlaceOpt {
pub(super) struct IncludingTupleField(pub(super) bool);
-impl<'infcx, 'tcx> MirBorrowckCtxt<'_, '_, 'infcx, 'tcx> {
+impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
/// Adds a suggestion when a closure is invoked twice with a moved variable or when a closure
/// is moved after being invoked.
///
@@ -345,9 +345,9 @@ fn describe_field_from_ty(
variant_index: Option<VariantIdx>,
including_tuple_field: IncludingTupleField,
) -> Option<String> {
- if ty.is_box() {
+ if let Some(boxed_ty) = ty.boxed_ty() {
// If the type is a box, the field is described from the boxed type
- self.describe_field_from_ty(ty.boxed_ty(), field, variant_index, including_tuple_field)
+ self.describe_field_from_ty(boxed_ty, field, variant_index, including_tuple_field)
} else {
match *ty.kind() {
ty::Adt(def, _) => {
@@ -772,7 +772,7 @@ struct CapturedMessageOpt {
maybe_reinitialized_locations_is_empty: bool,
}
-impl<'infcx, 'tcx> MirBorrowckCtxt<'_, '_, 'infcx, 'tcx> {
+impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
/// Finds the spans associated to a move or copy of move_place at location.
pub(super) fn move_spans(
&self,
diff --git a/compiler/rustc_borrowck/src/diagnostics/move_errors.rs b/compiler/rustc_borrowck/src/diagnostics/move_errors.rs
index 3dab027..5a9eba3 100644
--- a/compiler/rustc_borrowck/src/diagnostics/move_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/move_errors.rs
@@ -93,7 +93,7 @@ enum GroupedMoveError<'tcx> {
},
}
-impl<'infcx, 'tcx> MirBorrowckCtxt<'_, '_, 'infcx, 'tcx> {
+impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
pub(crate) fn report_move_errors(&mut self) {
let grouped_errors = self.group_move_errors();
for error in grouped_errors {
diff --git a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs
index 337125f..6e3fac1 100644
--- a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs
@@ -32,7 +32,7 @@ pub(crate) enum AccessKind {
Mutate,
}
-impl<'infcx, 'tcx> MirBorrowckCtxt<'_, '_, 'infcx, 'tcx> {
+impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
pub(crate) fn report_mutability_error(
&mut self,
access_place: Place<'tcx>,
diff --git a/compiler/rustc_borrowck/src/diagnostics/outlives_suggestion.rs b/compiler/rustc_borrowck/src/diagnostics/outlives_suggestion.rs
index b205dc9f..bd0cf35 100644
--- a/compiler/rustc_borrowck/src/diagnostics/outlives_suggestion.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/outlives_suggestion.rs
@@ -76,7 +76,7 @@ fn region_name_is_suggestable(name: &RegionName) -> bool {
/// Returns a name for the region if it is suggestable. See `region_name_is_suggestable`.
fn region_vid_to_name(
&self,
- mbcx: &MirBorrowckCtxt<'_, '_, '_, '_>,
+ mbcx: &MirBorrowckCtxt<'_, '_, '_>,
region: RegionVid,
) -> Option<RegionName> {
mbcx.give_region_a_name(region).filter(Self::region_name_is_suggestable)
@@ -85,7 +85,7 @@ fn region_vid_to_name(
/// Compiles a list of all suggestions to be printed in the final big suggestion.
fn compile_all_suggestions(
&self,
- mbcx: &MirBorrowckCtxt<'_, '_, '_, '_>,
+ mbcx: &MirBorrowckCtxt<'_, '_, '_>,
) -> SmallVec<[SuggestedConstraint; 2]> {
let mut suggested = SmallVec::new();
@@ -161,7 +161,7 @@ pub(crate) fn collect_constraint(&mut self, fr: RegionVid, outlived_fr: RegionVi
/// Emit an intermediate note on the given `Diag` if the involved regions are suggestable.
pub(crate) fn intermediate_suggestion(
&mut self,
- mbcx: &MirBorrowckCtxt<'_, '_, '_, '_>,
+ mbcx: &MirBorrowckCtxt<'_, '_, '_>,
errci: &ErrorConstraintInfo<'_>,
diag: &mut Diag<'_>,
) {
@@ -180,7 +180,7 @@ pub(crate) fn intermediate_suggestion(
/// If there is a suggestion to emit, add a diagnostic to the buffer. This is the final
/// suggestion including all collected constraints.
- pub(crate) fn add_suggestion(&self, mbcx: &mut MirBorrowckCtxt<'_, '_, '_, '_>) {
+ pub(crate) fn add_suggestion(&self, mbcx: &mut MirBorrowckCtxt<'_, '_, '_>) {
// No constraints to add? Done.
if self.constraints_to_add.is_empty() {
debug!("No constraints to suggest.");
diff --git a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs
index d49d36d..57c3a08 100644
--- a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs
@@ -156,7 +156,7 @@ pub(crate) struct ErrorConstraintInfo<'tcx> {
pub(super) span: Span,
}
-impl<'infcx, 'tcx> MirBorrowckCtxt<'_, '_, 'infcx, 'tcx> {
+impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
/// Converts a region inference variable into a `ty::Region` that
/// we can use for error reporting. If `r` is universally bound,
/// then we use the name that we have on record for it. If `r` is
diff --git a/compiler/rustc_borrowck/src/diagnostics/region_name.rs b/compiler/rustc_borrowck/src/diagnostics/region_name.rs
index cb05812..58fcda2 100644
--- a/compiler/rustc_borrowck/src/diagnostics/region_name.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/region_name.rs
@@ -200,7 +200,7 @@ fn into_diag_arg(self) -> rustc_errors::DiagArgValue {
}
}
-impl<'tcx> MirBorrowckCtxt<'_, '_, '_, 'tcx> {
+impl<'tcx> MirBorrowckCtxt<'_, '_, 'tcx> {
pub(crate) fn mir_def_id(&self) -> hir::def_id::LocalDefId {
self.body.source.def_id().expect_local()
}
diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs
index ffb350b..d5f297a 100644
--- a/compiler/rustc_borrowck/src/lib.rs
+++ b/compiler/rustc_borrowck/src/lib.rs
@@ -304,11 +304,11 @@ fn do_mir_borrowck<'tcx>(
promoted_mbcx.report_move_errors();
diags = promoted_mbcx.diags;
- struct MoveVisitor<'a, 'b, 'mir, 'infcx, 'tcx> {
- ctxt: &'a mut MirBorrowckCtxt<'b, 'mir, 'infcx, 'tcx>,
+ struct MoveVisitor<'a, 'b, 'infcx, 'tcx> {
+ ctxt: &'a mut MirBorrowckCtxt<'b, 'infcx, 'tcx>,
}
- impl<'tcx> Visitor<'tcx> for MoveVisitor<'_, '_, '_, '_, 'tcx> {
+ impl<'tcx> Visitor<'tcx> for MoveVisitor<'_, '_, '_, 'tcx> {
fn visit_operand(&mut self, operand: &Operand<'tcx>, location: Location) {
if let Operand::Move(place) = operand {
self.ctxt.check_movable_place(location, *place);
@@ -522,10 +522,10 @@ fn deref(&self) -> &Self::Target {
}
}
-struct MirBorrowckCtxt<'a, 'mir, 'infcx, 'tcx> {
+struct MirBorrowckCtxt<'a, 'infcx, 'tcx> {
infcx: &'infcx BorrowckInferCtxt<'tcx>,
param_env: ParamEnv<'tcx>,
- body: &'mir Body<'tcx>,
+ body: &'a Body<'tcx>,
move_data: &'a MoveData<'tcx>,
/// Map from MIR `Location` to `LocationIndex`; created
@@ -599,16 +599,16 @@ struct MirBorrowckCtxt<'a, 'mir, 'infcx, 'tcx> {
// 2. loans made in overlapping scopes do not conflict
// 3. assignments do not affect things loaned out as immutable
// 4. moves do not affect things loaned out in any way
-impl<'a, 'mir, 'tcx, R> rustc_mir_dataflow::ResultsVisitor<'mir, 'tcx, R>
- for MirBorrowckCtxt<'a, 'mir, '_, 'tcx>
+impl<'a, 'tcx, R> rustc_mir_dataflow::ResultsVisitor<'a, 'tcx, R>
+ for MirBorrowckCtxt<'a, '_, 'tcx>
{
- type FlowState = Flows<'a, 'mir, 'tcx>;
+ type FlowState = Flows<'a, 'tcx>;
fn visit_statement_before_primary_effect(
&mut self,
_results: &mut R,
- flow_state: &Flows<'_, 'mir, 'tcx>,
- stmt: &'mir Statement<'tcx>,
+ flow_state: &Flows<'a, 'tcx>,
+ stmt: &'a Statement<'tcx>,
location: Location,
) {
debug!("MirBorrowckCtxt::process_statement({:?}, {:?}): {:?}", location, stmt, flow_state);
@@ -677,8 +677,8 @@ fn visit_statement_before_primary_effect(
fn visit_terminator_before_primary_effect(
&mut self,
_results: &mut R,
- flow_state: &Flows<'_, 'mir, 'tcx>,
- term: &'mir Terminator<'tcx>,
+ flow_state: &Flows<'a, 'tcx>,
+ term: &'a Terminator<'tcx>,
loc: Location,
) {
debug!("MirBorrowckCtxt::process_terminator({:?}, {:?}): {:?}", loc, term, flow_state);
@@ -794,8 +794,8 @@ fn visit_terminator_before_primary_effect(
fn visit_terminator_after_primary_effect(
&mut self,
_results: &mut R,
- flow_state: &Flows<'_, 'mir, 'tcx>,
- term: &'mir Terminator<'tcx>,
+ flow_state: &Flows<'a, 'tcx>,
+ term: &'a Terminator<'tcx>,
loc: Location,
) {
let span = term.source_info.span;
@@ -972,8 +972,8 @@ fn as_general_verb_in_past_tense(self) -> &'static str {
}
}
-impl<'mir, 'tcx> MirBorrowckCtxt<'_, 'mir, '_, 'tcx> {
- fn body(&self) -> &'mir Body<'tcx> {
+impl<'a, 'tcx> MirBorrowckCtxt<'a, '_, 'tcx> {
+ fn body(&self) -> &'a Body<'tcx> {
self.body
}
@@ -989,7 +989,7 @@ fn access_place(
place_span: (Place<'tcx>, Span),
kind: (AccessDepth, ReadOrWrite),
is_local_mutation_allowed: LocalMutationIsAllowed,
- flow_state: &Flows<'_, 'mir, 'tcx>,
+ flow_state: &Flows<'a, 'tcx>,
) {
let (sd, rw) = kind;
@@ -1039,7 +1039,7 @@ fn check_access_for_conflict(
place_span: (Place<'tcx>, Span),
sd: AccessDepth,
rw: ReadOrWrite,
- flow_state: &Flows<'_, 'mir, 'tcx>,
+ flow_state: &Flows<'a, 'tcx>,
) -> bool {
let mut error_reported = false;
let borrow_set = Rc::clone(&self.borrow_set);
@@ -1180,7 +1180,7 @@ fn mutate_place(
location: Location,
place_span: (Place<'tcx>, Span),
kind: AccessDepth,
- flow_state: &Flows<'_, 'mir, 'tcx>,
+ flow_state: &Flows<'a, 'tcx>,
) {
// Write of P[i] or *P requires P init'd.
self.check_if_assigned_path_is_moved(location, place_span, flow_state);
@@ -1197,8 +1197,8 @@ fn mutate_place(
fn consume_rvalue(
&mut self,
location: Location,
- (rvalue, span): (&'mir Rvalue<'tcx>, Span),
- flow_state: &Flows<'_, 'mir, 'tcx>,
+ (rvalue, span): (&'a Rvalue<'tcx>, Span),
+ flow_state: &Flows<'a, 'tcx>,
) {
match rvalue {
&Rvalue::Ref(_ /*rgn*/, bk, place) => {
@@ -1455,8 +1455,8 @@ fn propagate_closure_used_mut_upvar(&mut self, operand: &Operand<'tcx>) {
fn consume_operand(
&mut self,
location: Location,
- (operand, span): (&'mir Operand<'tcx>, Span),
- flow_state: &Flows<'_, 'mir, 'tcx>,
+ (operand, span): (&'a Operand<'tcx>, Span),
+ flow_state: &Flows<'a, 'tcx>,
) {
match *operand {
Operand::Copy(place) => {
@@ -1576,12 +1576,7 @@ fn check_for_local_borrow(&mut self, borrow: &BorrowData<'tcx>, yield_span: Span
}
}
- fn check_activations(
- &mut self,
- location: Location,
- span: Span,
- flow_state: &Flows<'_, 'mir, 'tcx>,
- ) {
+ fn check_activations(&mut self, location: Location, span: Span, flow_state: &Flows<'a, 'tcx>) {
// Two-phase borrow support: For each activation that is newly
// generated at this statement, check if it interferes with
// another borrow.
@@ -1744,7 +1739,7 @@ fn check_if_full_path_is_moved(
location: Location,
desired_action: InitializationRequiringAction,
place_span: (PlaceRef<'tcx>, Span),
- flow_state: &Flows<'_, 'mir, 'tcx>,
+ flow_state: &Flows<'a, 'tcx>,
) {
let maybe_uninits = &flow_state.uninits;
@@ -1849,7 +1844,7 @@ fn check_if_path_or_subpath_is_moved(
location: Location,
desired_action: InitializationRequiringAction,
place_span: (PlaceRef<'tcx>, Span),
- flow_state: &Flows<'_, 'mir, 'tcx>,
+ flow_state: &Flows<'a, 'tcx>,
) {
let maybe_uninits = &flow_state.uninits;
@@ -1948,7 +1943,7 @@ fn check_if_assigned_path_is_moved(
&mut self,
location: Location,
(place, span): (Place<'tcx>, Span),
- flow_state: &Flows<'_, 'mir, 'tcx>,
+ flow_state: &Flows<'a, 'tcx>,
) {
debug!("check_if_assigned_path_is_moved place: {:?}", place);
@@ -2009,12 +2004,12 @@ fn check_if_assigned_path_is_moved(
}
}
- fn check_parent_of_field<'mir, 'tcx>(
- this: &mut MirBorrowckCtxt<'_, 'mir, '_, 'tcx>,
+ fn check_parent_of_field<'a, 'tcx>(
+ this: &mut MirBorrowckCtxt<'a, '_, 'tcx>,
location: Location,
base: PlaceRef<'tcx>,
span: Span,
- flow_state: &Flows<'_, 'mir, 'tcx>,
+ flow_state: &Flows<'a, 'tcx>,
) {
// rust-lang/rust#21232: Until Rust allows reads from the
// initialized parts of partially initialized structs, we
@@ -2105,7 +2100,7 @@ fn check_access_permissions(
(place, span): (Place<'tcx>, Span),
kind: ReadOrWrite,
is_local_mutation_allowed: LocalMutationIsAllowed,
- flow_state: &Flows<'_, 'mir, 'tcx>,
+ flow_state: &Flows<'a, 'tcx>,
location: Location,
) -> bool {
debug!(
@@ -2221,7 +2216,7 @@ fn check_access_permissions(
fn is_local_ever_initialized(
&self,
local: Local,
- flow_state: &Flows<'_, 'mir, 'tcx>,
+ flow_state: &Flows<'a, 'tcx>,
) -> Option<InitIndex> {
let mpi = self.move_data.rev_lookup.find_local(local)?;
let ii = &self.move_data.init_path_map[mpi];
@@ -2229,7 +2224,7 @@ fn is_local_ever_initialized(
}
/// Adds the place into the used mutable variables set
- fn add_used_mut(&mut self, root_place: RootPlace<'tcx>, flow_state: &Flows<'_, 'mir, 'tcx>) {
+ fn add_used_mut(&mut self, root_place: RootPlace<'tcx>, flow_state: &Flows<'a, 'tcx>) {
match root_place {
RootPlace { place_local: local, place_projection: [], is_local_mutation_allowed } => {
// If the local may have been initialized, and it is now currently being
@@ -2484,7 +2479,7 @@ pub(crate) fn buffer_non_error(&mut self, diag: Diag<'infcx, ()>) {
}
}
- impl<'infcx, 'tcx> MirBorrowckCtxt<'_, '_, 'infcx, 'tcx> {
+ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
pub(crate) fn buffer_error(&mut self, diag: Diag<'infcx>) {
self.diags.buffer_error(diag);
}
@@ -2522,7 +2517,7 @@ pub(crate) fn buffer_mut_error(&mut self, span: Span, diag: Diag<'infcx>, count:
}
pub(crate) fn emit_errors(&mut self) -> Option<ErrorGuaranteed> {
- let mut res = None;
+ let mut res = self.infcx.tainted_by_errors();
// Buffer any move errors that we collected and de-duplicated.
for (_, (_, diag)) in std::mem::take(&mut self.diags.buffered_move_errors) {
diff --git a/compiler/rustc_borrowck/src/nll.rs b/compiler/rustc_borrowck/src/nll.rs
index 6525bef..8575eb9 100644
--- a/compiler/rustc_borrowck/src/nll.rs
+++ b/compiler/rustc_borrowck/src/nll.rs
@@ -75,14 +75,14 @@ pub(crate) fn replace_regions_in_mir<'tcx>(
/// Computes the (non-lexical) regions from the input MIR.
///
/// This may result in errors being reported.
-pub(crate) fn compute_regions<'cx, 'tcx>(
+pub(crate) fn compute_regions<'a, 'tcx>(
infcx: &BorrowckInferCtxt<'tcx>,
universal_regions: UniversalRegions<'tcx>,
body: &Body<'tcx>,
promoted: &IndexSlice<Promoted, Body<'tcx>>,
location_table: &LocationTable,
param_env: ty::ParamEnv<'tcx>,
- flow_inits: &mut ResultsCursor<'cx, 'tcx, MaybeInitializedPlaces<'_, 'cx, 'tcx>>,
+ flow_inits: &mut ResultsCursor<'a, 'tcx, MaybeInitializedPlaces<'a, 'tcx>>,
move_data: &MoveData<'tcx>,
borrow_set: &BorrowSet<'tcx>,
upvars: &[&ty::CapturedPlace<'tcx>],
@@ -301,13 +301,13 @@ pub(super) fn dump_nll_mir<'tcx>(
#[allow(rustc::diagnostic_outside_of_impl)]
#[allow(rustc::untranslatable_diagnostic)]
-pub(super) fn dump_annotation<'tcx, 'cx>(
- infcx: &'cx BorrowckInferCtxt<'tcx>,
+pub(super) fn dump_annotation<'tcx, 'infcx>(
+ infcx: &'infcx BorrowckInferCtxt<'tcx>,
body: &Body<'tcx>,
regioncx: &RegionInferenceContext<'tcx>,
closure_region_requirements: &Option<ClosureRegionRequirements<'tcx>>,
opaque_type_values: &FxIndexMap<LocalDefId, OpaqueHiddenType<'tcx>>,
- diags: &mut crate::diags::BorrowckDiags<'cx, 'tcx>,
+ diags: &mut crate::diags::BorrowckDiags<'infcx, 'tcx>,
) {
let tcx = infcx.tcx;
let base_def_id = tcx.typeck_root_def_id(body.source.def_id());
diff --git a/compiler/rustc_borrowck/src/prefixes.rs b/compiler/rustc_borrowck/src/prefixes.rs
index 39d8313..aeb8a6c 100644
--- a/compiler/rustc_borrowck/src/prefixes.rs
+++ b/compiler/rustc_borrowck/src/prefixes.rs
@@ -34,7 +34,7 @@ pub(super) enum PrefixSet {
Shallow,
}
-impl<'tcx> MirBorrowckCtxt<'_, '_, '_, 'tcx> {
+impl<'tcx> MirBorrowckCtxt<'_, '_, 'tcx> {
/// Returns an iterator over the prefixes of `place`
/// (inclusive) from longest to smallest, potentially
/// terminating the iteration early based on `kind`.
diff --git a/compiler/rustc_borrowck/src/type_check/liveness/mod.rs b/compiler/rustc_borrowck/src/type_check/liveness/mod.rs
index a24fd95e..79db8f4 100644
--- a/compiler/rustc_borrowck/src/type_check/liveness/mod.rs
+++ b/compiler/rustc_borrowck/src/type_check/liveness/mod.rs
@@ -30,11 +30,11 @@
///
/// N.B., this computation requires normalization; therefore, it must be
/// performed before
-pub(super) fn generate<'mir, 'tcx>(
+pub(super) fn generate<'a, 'tcx>(
typeck: &mut TypeChecker<'_, 'tcx>,
body: &Body<'tcx>,
elements: &Rc<DenseLocationMap>,
- flow_inits: &mut ResultsCursor<'mir, 'tcx, MaybeInitializedPlaces<'_, 'mir, 'tcx>>,
+ flow_inits: &mut ResultsCursor<'a, 'tcx, MaybeInitializedPlaces<'a, 'tcx>>,
move_data: &MoveData<'tcx>,
) {
debug!("liveness::generate");
diff --git a/compiler/rustc_borrowck/src/type_check/liveness/trace.rs b/compiler/rustc_borrowck/src/type_check/liveness/trace.rs
index 6186904..4d47863 100644
--- a/compiler/rustc_borrowck/src/type_check/liveness/trace.rs
+++ b/compiler/rustc_borrowck/src/type_check/liveness/trace.rs
@@ -37,11 +37,11 @@
/// DROP-LIVE set are to the liveness sets for regions found in the
/// `dropck_outlives` result of the variable's type (in particular,
/// this respects `#[may_dangle]` annotations).
-pub(super) fn trace<'mir, 'tcx>(
+pub(super) fn trace<'a, 'tcx>(
typeck: &mut TypeChecker<'_, 'tcx>,
body: &Body<'tcx>,
elements: &Rc<DenseLocationMap>,
- flow_inits: &mut ResultsCursor<'mir, 'tcx, MaybeInitializedPlaces<'_, 'mir, 'tcx>>,
+ flow_inits: &mut ResultsCursor<'a, 'tcx, MaybeInitializedPlaces<'a, 'tcx>>,
move_data: &MoveData<'tcx>,
relevant_live_locals: Vec<Local>,
boring_locals: Vec<Local>,
@@ -99,29 +99,29 @@ pub(super) fn trace<'mir, 'tcx>(
}
/// Contextual state for the type-liveness coroutine.
-struct LivenessContext<'a, 'me, 'typeck, 'flow, 'tcx> {
+struct LivenessContext<'a, 'typeck, 'b, 'tcx> {
/// Current type-checker, giving us our inference context etc.
- typeck: &'me mut TypeChecker<'typeck, 'tcx>,
+ typeck: &'a mut TypeChecker<'typeck, 'tcx>,
/// Defines the `PointIndex` mapping
- elements: &'me DenseLocationMap,
+ elements: &'a DenseLocationMap,
/// MIR we are analyzing.
- body: &'me Body<'tcx>,
+ body: &'a Body<'tcx>,
/// Mapping to/from the various indices used for initialization tracking.
- move_data: &'me MoveData<'tcx>,
+ move_data: &'a MoveData<'tcx>,
/// Cache for the results of `dropck_outlives` query.
drop_data: FxIndexMap<Ty<'tcx>, DropData<'tcx>>,
/// Results of dataflow tracking which variables (and paths) have been
/// initialized.
- flow_inits: &'me mut ResultsCursor<'flow, 'tcx, MaybeInitializedPlaces<'a, 'flow, 'tcx>>,
+ flow_inits: &'a mut ResultsCursor<'b, 'tcx, MaybeInitializedPlaces<'b, 'tcx>>,
/// Index indicating where each variable is assigned, used, or
/// dropped.
- local_use_map: &'me LocalUseMap,
+ local_use_map: &'a LocalUseMap,
}
struct DropData<'tcx> {
@@ -129,8 +129,8 @@ struct DropData<'tcx> {
region_constraint_data: Option<&'tcx QueryRegionConstraints<'tcx>>,
}
-struct LivenessResults<'a, 'me, 'typeck, 'flow, 'tcx> {
- cx: LivenessContext<'a, 'me, 'typeck, 'flow, 'tcx>,
+struct LivenessResults<'a, 'typeck, 'b, 'tcx> {
+ cx: LivenessContext<'a, 'typeck, 'b, 'tcx>,
/// Set of points that define the current local.
defs: BitSet<PointIndex>,
@@ -151,8 +151,8 @@ struct LivenessResults<'a, 'me, 'typeck, 'flow, 'tcx> {
stack: Vec<PointIndex>,
}
-impl<'a, 'me, 'typeck, 'flow, 'tcx> LivenessResults<'a, 'me, 'typeck, 'flow, 'tcx> {
- fn new(cx: LivenessContext<'a, 'me, 'typeck, 'flow, 'tcx>) -> Self {
+impl<'a, 'typeck, 'b, 'tcx> LivenessResults<'a, 'typeck, 'b, 'tcx> {
+ fn new(cx: LivenessContext<'a, 'typeck, 'b, 'tcx>) -> Self {
let num_points = cx.elements.num_points();
LivenessResults {
cx,
@@ -505,7 +505,7 @@ fn compute_drop_live_points_for_block(&mut self, mpi: MovePathIndex, term_point:
}
}
-impl<'tcx> LivenessContext<'_, '_, '_, '_, 'tcx> {
+impl<'tcx> LivenessContext<'_, '_, '_, 'tcx> {
/// Returns `true` if the local variable (or some part of it) is initialized at the current
/// cursor position. Callers should call one of the `seek` methods immediately before to point
/// the cursor to the desired location.
diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs
index 224f8d5..3e5a6ad 100644
--- a/compiler/rustc_borrowck/src/type_check/mod.rs
+++ b/compiler/rustc_borrowck/src/type_check/mod.rs
@@ -116,7 +116,7 @@ macro_rules! span_mirbug_and_err {
/// - `flow_inits` -- results of a maybe-init dataflow analysis
/// - `move_data` -- move-data constructed when performing the maybe-init dataflow analysis
/// - `elements` -- MIR region map
-pub(crate) fn type_check<'mir, 'tcx>(
+pub(crate) fn type_check<'a, 'tcx>(
infcx: &BorrowckInferCtxt<'tcx>,
param_env: ty::ParamEnv<'tcx>,
body: &Body<'tcx>,
@@ -125,7 +125,7 @@ pub(crate) fn type_check<'mir, 'tcx>(
location_table: &LocationTable,
borrow_set: &BorrowSet<'tcx>,
all_facts: &mut Option<AllFacts>,
- flow_inits: &mut ResultsCursor<'mir, 'tcx, MaybeInitializedPlaces<'_, 'mir, 'tcx>>,
+ flow_inits: &mut ResultsCursor<'a, 'tcx, MaybeInitializedPlaces<'a, 'tcx>>,
move_data: &MoveData<'tcx>,
elements: &Rc<DenseLocationMap>,
upvars: &[&ty::CapturedPlace<'tcx>],
@@ -1979,19 +1979,76 @@ fn check_rvalue(&mut self, body: &Body<'tcx>, rvalue: &Rvalue<'tcx>, location: L
match cast_kind {
CastKind::PointerCoercion(PointerCoercion::ReifyFnPointer) => {
- let fn_sig = op.ty(body, tcx).fn_sig(tcx);
+ let src_sig = op.ty(body, tcx).fn_sig(tcx);
+
+ // HACK: This shouldn't be necessary... We can remove this when we actually
+ // get binders with where clauses, then elaborate implied bounds into that
+ // binder, and implement a higher-ranked subtyping algorithm that actually
+ // respects these implied bounds.
+ //
+ // This protects against the case where we are casting from a higher-ranked
+ // fn item to a non-higher-ranked fn pointer, where the cast throws away
+ // implied bounds that would've needed to be checked at the call site. This
+ // only works when we're casting to a non-higher-ranked fn ptr, since
+ // placeholders in the target signature could have untracked implied
+ // bounds, resulting in incorrect errors.
+ //
+ // We check that this signature is WF before subtyping the signature with
+ // the target fn sig.
+ if src_sig.has_bound_regions()
+ && let ty::FnPtr(target_fn_tys, target_hdr) = *ty.kind()
+ && let target_sig = target_fn_tys.with(target_hdr)
+ && let Some(target_sig) = target_sig.no_bound_vars()
+ {
+ let src_sig = self.infcx.instantiate_binder_with_fresh_vars(
+ span,
+ BoundRegionConversionTime::HigherRankedType,
+ src_sig,
+ );
+ let src_ty = Ty::new_fn_ptr(self.tcx(), ty::Binder::dummy(src_sig));
+ self.prove_predicate(
+ ty::ClauseKind::WellFormed(src_ty.into()),
+ location.to_locations(),
+ ConstraintCategory::Cast { unsize_to: None },
+ );
+
+ let src_ty = self.normalize(src_ty, location);
+ if let Err(terr) = self.sub_types(
+ src_ty,
+ *ty,
+ location.to_locations(),
+ ConstraintCategory::Cast { unsize_to: None },
+ ) {
+ span_mirbug!(
+ self,
+ rvalue,
+ "equating {:?} with {:?} yields {:?}",
+ target_sig,
+ src_sig,
+ terr
+ );
+ };
+ }
+
+ let src_ty = Ty::new_fn_ptr(tcx, src_sig);
+ // HACK: We want to assert that the signature of the source fn is
+ // well-formed, because we don't enforce that via the WF of FnDef
+ // types normally. This should be removed when we improve the tracking
+ // of implied bounds of fn signatures.
+ self.prove_predicate(
+ ty::ClauseKind::WellFormed(src_ty.into()),
+ location.to_locations(),
+ ConstraintCategory::Cast { unsize_to: None },
+ );
// The type that we see in the fcx is like
// `foo::<'a, 'b>`, where `foo` is the path to a
// function definition. When we extract the
// signature, it comes from the `fn_sig` query,
// and hence may contain unnormalized results.
- let fn_sig = self.normalize(fn_sig, location);
-
- let ty_fn_ptr_from = Ty::new_fn_ptr(tcx, fn_sig);
-
+ let src_ty = self.normalize(src_ty, location);
if let Err(terr) = self.sub_types(
- ty_fn_ptr_from,
+ src_ty,
*ty,
location.to_locations(),
ConstraintCategory::Cast { unsize_to: None },
@@ -2000,7 +2057,7 @@ fn check_rvalue(&mut self, body: &Body<'tcx>, rvalue: &Rvalue<'tcx>, location: L
self,
rvalue,
"equating {:?} with {:?} yields {:?}",
- ty_fn_ptr_from,
+ src_ty,
ty,
terr
);
diff --git a/compiler/rustc_borrowck/src/universal_regions.rs b/compiler/rustc_borrowck/src/universal_regions.rs
index 9eabe81..c3edbcb 100644
--- a/compiler/rustc_borrowck/src/universal_regions.rs
+++ b/compiler/rustc_borrowck/src/universal_regions.rs
@@ -29,7 +29,8 @@
use rustc_middle::ty::fold::TypeFoldable;
use rustc_middle::ty::print::with_no_trimmed_paths;
use rustc_middle::ty::{
- self, GenericArgs, GenericArgsRef, InlineConstArgs, InlineConstArgsParts, RegionVid, Ty, TyCtxt,
+ self, GenericArgs, GenericArgsRef, InlineConstArgs, InlineConstArgsParts, RegionVid, Ty,
+ TyCtxt, TypeVisitableExt,
};
use rustc_middle::{bug, span_bug};
use rustc_span::symbol::{kw, sym};
@@ -422,8 +423,8 @@ pub(crate) fn tainted_by_errors(&self) -> Option<ErrorGuaranteed> {
}
}
-struct UniversalRegionsBuilder<'cx, 'tcx> {
- infcx: &'cx BorrowckInferCtxt<'tcx>,
+struct UniversalRegionsBuilder<'infcx, 'tcx> {
+ infcx: &'infcx BorrowckInferCtxt<'tcx>,
mir_def: LocalDefId,
param_env: ty::ParamEnv<'tcx>,
}
@@ -688,7 +689,8 @@ fn compute_inputs_and_output(
defining_ty: DefiningTy<'tcx>,
) -> ty::Binder<'tcx, &'tcx ty::List<Ty<'tcx>>> {
let tcx = self.infcx.tcx;
- match defining_ty {
+
+ let inputs_and_output = match defining_ty {
DefiningTy::Closure(def_id, args) => {
assert_eq!(self.mir_def.to_def_id(), def_id);
let closure_sig = args.as_closure().sig();
@@ -798,6 +800,7 @@ fn compute_inputs_and_output(
// "output" (the type of the constant).
assert_eq!(self.mir_def.to_def_id(), def_id);
let ty = tcx.type_of(self.mir_def).instantiate_identity();
+
let ty = indices.fold_to_region_vids(tcx, ty);
ty::Binder::dummy(tcx.mk_type_list(&[ty]))
}
@@ -807,7 +810,14 @@ fn compute_inputs_and_output(
let ty = args.as_inline_const().ty();
ty::Binder::dummy(tcx.mk_type_list(&[ty]))
}
+ };
+
+ // FIXME(#129952): We probably want a more principled approach here.
+ if let Err(terr) = inputs_and_output.skip_binder().error_reported() {
+ self.infcx.set_tainted_by_errors(terr);
}
+
+ inputs_and_output
}
}
diff --git a/compiler/rustc_borrowck/src/used_muts.rs b/compiler/rustc_borrowck/src/used_muts.rs
index 981e7da..bde07c0 100644
--- a/compiler/rustc_borrowck/src/used_muts.rs
+++ b/compiler/rustc_borrowck/src/used_muts.rs
@@ -7,7 +7,7 @@
use crate::MirBorrowckCtxt;
-impl<'tcx> MirBorrowckCtxt<'_, '_, '_, 'tcx> {
+impl<'tcx> MirBorrowckCtxt<'_, '_, 'tcx> {
/// Walks the MIR adding to the set of `used_mut` locals that will be ignored for the purposes
/// of the `unused_mut` lint.
///
@@ -46,13 +46,13 @@ pub(crate) fn gather_used_muts(
/// MIR visitor for collecting used mutable variables.
/// The 'visit lifetime represents the duration of the MIR walk.
-struct GatherUsedMutsVisitor<'visit, 'a, 'mir, 'infcx, 'tcx> {
+struct GatherUsedMutsVisitor<'a, 'b, 'infcx, 'tcx> {
temporary_used_locals: FxIndexSet<Local>,
- never_initialized_mut_locals: &'visit mut FxIndexSet<Local>,
- mbcx: &'visit mut MirBorrowckCtxt<'a, 'mir, 'infcx, 'tcx>,
+ never_initialized_mut_locals: &'a mut FxIndexSet<Local>,
+ mbcx: &'a mut MirBorrowckCtxt<'b, 'infcx, 'tcx>,
}
-impl GatherUsedMutsVisitor<'_, '_, '_, '_, '_> {
+impl GatherUsedMutsVisitor<'_, '_, '_, '_> {
fn remove_never_initialized_mut_locals(&mut self, into: Place<'_>) {
// Remove any locals that we found were initialized from the
// `never_initialized_mut_locals` set. At the end, the only remaining locals will
@@ -64,7 +64,7 @@ fn remove_never_initialized_mut_locals(&mut self, into: Place<'_>) {
}
}
-impl<'tcx> Visitor<'tcx> for GatherUsedMutsVisitor<'_, '_, '_, '_, 'tcx> {
+impl<'tcx> Visitor<'tcx> for GatherUsedMutsVisitor<'_, '_, '_, 'tcx> {
fn visit_terminator(&mut self, terminator: &Terminator<'tcx>, location: Location) {
debug!("visit_terminator: terminator={:?}", terminator);
match &terminator.kind {
diff --git a/compiler/rustc_builtin_macros/src/asm.rs b/compiler/rustc_builtin_macros/src/asm.rs
index ae2627d..e313016 100644
--- a/compiler/rustc_builtin_macros/src/asm.rs
+++ b/compiler/rustc_builtin_macros/src/asm.rs
@@ -812,6 +812,44 @@ pub(super) fn expand_asm<'cx>(
})
}
+pub(super) fn expand_naked_asm<'cx>(
+ ecx: &'cx mut ExtCtxt<'_>,
+ sp: Span,
+ tts: TokenStream,
+) -> MacroExpanderResult<'cx> {
+ ExpandResult::Ready(match parse_args(ecx, sp, tts, false) {
+ Ok(args) => {
+ let ExpandResult::Ready(mac) = expand_preparsed_asm(ecx, args) else {
+ return ExpandResult::Retry(());
+ };
+ let expr = match mac {
+ Ok(mut inline_asm) => {
+ // for future compatibility, we always set the NORETURN option.
+ //
+ // When we turn `asm!` into `naked_asm!` with this implementation, we can drop
+ // the `options(noreturn)`, which makes the upgrade smooth when `naked_asm!`
+ // starts disallowing the `noreturn` option in the future
+ inline_asm.options |= ast::InlineAsmOptions::NORETURN;
+
+ P(ast::Expr {
+ id: ast::DUMMY_NODE_ID,
+ kind: ast::ExprKind::InlineAsm(P(inline_asm)),
+ span: sp,
+ attrs: ast::AttrVec::new(),
+ tokens: None,
+ })
+ }
+ Err(guar) => DummyResult::raw_expr(sp, Some(guar)),
+ };
+ MacEager::expr(expr)
+ }
+ Err(err) => {
+ let guar = err.emit();
+ DummyResult::any(sp, guar)
+ }
+ })
+}
+
pub(super) fn expand_global_asm<'cx>(
ecx: &'cx mut ExtCtxt<'_>,
sp: Span,
diff --git a/compiler/rustc_builtin_macros/src/lib.rs b/compiler/rustc_builtin_macros/src/lib.rs
index 30e1c8d..ebe5e2b 100644
--- a/compiler/rustc_builtin_macros/src/lib.rs
+++ b/compiler/rustc_builtin_macros/src/lib.rs
@@ -94,6 +94,7 @@ pub fn register_builtin_macros(resolver: &mut dyn ResolverExpand) {
line: source_util::expand_line,
log_syntax: log_syntax::expand_log_syntax,
module_path: source_util::expand_mod,
+ naked_asm: asm::expand_naked_asm,
option_env: env::expand_option_env,
pattern_type: pattern_type::expand,
std_panic: edition_panic::expand_panic,
diff --git a/compiler/rustc_codegen_cranelift/Readme.md b/compiler/rustc_codegen_cranelift/Readme.md
index 6766e2f..18a840f 100644
--- a/compiler/rustc_codegen_cranelift/Readme.md
+++ b/compiler/rustc_codegen_cranelift/Readme.md
@@ -70,7 +70,7 @@
|AIX|❌[^xcoff]|N/A|N/A|❌[^xcoff]|
|Other unixes|❓|❓|❓|❓|
|macOS|✅|✅|N/A|N/A|
-|Windows|✅[^no-rustup]|❌|N/A|N/A|
+|Windows|✅|❌|N/A|N/A|
✅: Fully supported and tested
❓: Maybe supported, not tested
diff --git a/compiler/rustc_codegen_gcc/Cargo.lock b/compiler/rustc_codegen_gcc/Cargo.lock
index 915229f..0eb264f 100644
--- a/compiler/rustc_codegen_gcc/Cargo.lock
+++ b/compiler/rustc_codegen_gcc/Cargo.lock
@@ -12,63 +12,12 @@
]
[[package]]
-name = "bitflags"
-version = "1.3.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
-
-[[package]]
-name = "bitflags"
-version = "2.4.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b4682ae6287fcf752ecaabbfcc7b6f9b72aa33933dc23a554d853aea8eea8635"
-
-[[package]]
name = "boml"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "85fdb93f04c73bff54305fa437ffea5449c41edcaadfe882f35836206b166ac5"
[[package]]
-name = "cc"
-version = "1.0.79"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f"
-
-[[package]]
-name = "cfg-if"
-version = "1.0.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
-
-[[package]]
-name = "errno"
-version = "0.3.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4bcfec3a70f97c962c307b2d2c56e358cf1d00b558d74262b5f929ee8cc7e73a"
-dependencies = [
- "errno-dragonfly",
- "libc",
- "windows-sys",
-]
-
-[[package]]
-name = "errno-dragonfly"
-version = "0.1.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf"
-dependencies = [
- "cc",
- "libc",
-]
-
-[[package]]
-name = "fastrand"
-version = "2.0.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6999dc1837253364c2ebb0704ba97994bd874e8f195d665c50b7548f6ea92764"
-
-[[package]]
name = "fm"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -133,12 +82,6 @@
checksum = "89d92a4743f9a61002fae18374ed11e7973f530cb3a3255fb354818118b2203c"
[[package]]
-name = "linux-raw-sys"
-version = "0.4.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "57bcfdad1b858c2db7c38303a6d2ad4dfaf5eb53dfeb0910128b2c26d6158503"
-
-[[package]]
name = "memchr"
version = "2.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -155,24 +98,6 @@
]
[[package]]
-name = "object"
-version = "0.30.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "03b4680b86d9cfafba8fc491dc9b6df26b68cf40e9e6cd73909194759a63c385"
-dependencies = [
- "memchr",
-]
-
-[[package]]
-name = "redox_syscall"
-version = "0.3.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29"
-dependencies = [
- "bitflags 1.3.2",
-]
-
-[[package]]
name = "regex"
version = "1.8.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -196,22 +121,6 @@
"boml",
"gccjit",
"lang_tester",
- "object",
- "smallvec",
- "tempfile",
-]
-
-[[package]]
-name = "rustix"
-version = "0.38.8"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "19ed4fa021d81c8392ce04db050a3da9a60299050b7ae1cf482d862b54a7218f"
-dependencies = [
- "bitflags 2.4.0",
- "errno",
- "libc",
- "linux-raw-sys",
- "windows-sys",
]
[[package]]
@@ -224,25 +133,6 @@
]
[[package]]
-name = "smallvec"
-version = "1.10.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0"
-
-[[package]]
-name = "tempfile"
-version = "3.7.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dc02fddf48964c42031a0b3fe0428320ecf3a73c401040fc0096f97794310651"
-dependencies = [
- "cfg-if",
- "fastrand",
- "redox_syscall",
- "rustix",
- "windows-sys",
-]
-
-[[package]]
name = "termcolor"
version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -315,69 +205,3 @@
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
-
-[[package]]
-name = "windows-sys"
-version = "0.48.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9"
-dependencies = [
- "windows-targets",
-]
-
-[[package]]
-name = "windows-targets"
-version = "0.48.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "05d4b17490f70499f20b9e791dcf6a299785ce8af4d709018206dc5b4953e95f"
-dependencies = [
- "windows_aarch64_gnullvm",
- "windows_aarch64_msvc",
- "windows_i686_gnu",
- "windows_i686_msvc",
- "windows_x86_64_gnu",
- "windows_x86_64_gnullvm",
- "windows_x86_64_msvc",
-]
-
-[[package]]
-name = "windows_aarch64_gnullvm"
-version = "0.48.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc"
-
-[[package]]
-name = "windows_aarch64_msvc"
-version = "0.48.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b2ef27e0d7bdfcfc7b868b317c1d32c641a6fe4629c171b8928c7b08d98d7cf3"
-
-[[package]]
-name = "windows_i686_gnu"
-version = "0.48.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241"
-
-[[package]]
-name = "windows_i686_msvc"
-version = "0.48.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4542c6e364ce21bf45d69fdd2a8e455fa38d316158cfd43b3ac1c5b1b19f8e00"
-
-[[package]]
-name = "windows_x86_64_gnu"
-version = "0.48.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1"
-
-[[package]]
-name = "windows_x86_64_gnullvm"
-version = "0.48.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7896dbc1f41e08872e9d5e8f8baa8fdd2677f29468c4e156210174edc7f7b953"
-
-[[package]]
-name = "windows_x86_64_msvc"
-version = "0.48.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a"
diff --git a/compiler/rustc_codegen_gcc/Cargo.toml b/compiler/rustc_codegen_gcc/Cargo.toml
index 5caca63..44fb5ee 100644
--- a/compiler/rustc_codegen_gcc/Cargo.toml
+++ b/compiler/rustc_codegen_gcc/Cargo.toml
@@ -23,21 +23,11 @@
[dependencies]
gccjit = "2.1"
-
# Local copy.
#gccjit = { path = "../gccjit.rs" }
-object = { version = "0.30.1", default-features = false, features = [
- "std",
- "read",
-] }
-smallvec = { version = "1.6.1", features = ["union", "may_dangle"] }
-# TODO(antoyo): make tempfile optional.
-tempfile = "3.7.1"
-
[dev-dependencies]
lang_tester = "0.8.0"
-tempfile = "3.1.0"
boml = "0.3.1"
[profile.dev]
diff --git a/compiler/rustc_codegen_gcc/src/back/lto.rs b/compiler/rustc_codegen_gcc/src/back/lto.rs
index 6b2dbbb..c2adab7 100644
--- a/compiler/rustc_codegen_gcc/src/back/lto.rs
+++ b/compiler/rustc_codegen_gcc/src/back/lto.rs
@@ -272,7 +272,6 @@ fn fat_lto(
}*/
}
};
- let mut serialized_bitcode = Vec::new();
{
info!("using {:?} as a base module", module.name);
@@ -317,7 +316,6 @@ fn fat_lto(
unimplemented!("from uncompressed file")
}
}
- serialized_bitcode.push(bc_decoded);
}
save_temp_bitcode(cgcx, &module, "lto.input");
@@ -337,7 +335,7 @@ fn fat_lto(
// of now.
module.module_llvm.temp_dir = Some(tmp_path);
- Ok(LtoModuleCodegen::Fat { module, _serialized_bitcode: serialized_bitcode })
+ Ok(LtoModuleCodegen::Fat(module))
}
pub struct ModuleBuffer(PathBuf);
diff --git a/compiler/rustc_codegen_gcc/src/lib.rs b/compiler/rustc_codegen_gcc/src/lib.rs
index 94f0162..4de671a 100644
--- a/compiler/rustc_codegen_gcc/src/lib.rs
+++ b/compiler/rustc_codegen_gcc/src/lib.rs
@@ -24,6 +24,14 @@
#![deny(clippy::pattern_type_mismatch)]
#![allow(clippy::needless_lifetimes)]
+// Some "regular" crates we want to share with rustc
+extern crate object;
+extern crate smallvec;
+extern crate tempfile;
+#[macro_use]
+extern crate tracing;
+
+// The rustc crates we need
extern crate rustc_apfloat;
extern crate rustc_ast;
extern crate rustc_attr;
@@ -42,8 +50,6 @@
extern crate rustc_session;
extern crate rustc_span;
extern crate rustc_target;
-#[macro_use]
-extern crate tracing;
// This prevents duplicating functions and statics that are already part of the host rustc process.
#[allow(unused_extern_crates)]
diff --git a/compiler/rustc_codegen_llvm/src/attributes.rs b/compiler/rustc_codegen_llvm/src/attributes.rs
index 92a857c..9d4497d 100644
--- a/compiler/rustc_codegen_llvm/src/attributes.rs
+++ b/compiler/rustc_codegen_llvm/src/attributes.rs
@@ -411,26 +411,31 @@ pub(crate) fn llfn_attrs_from_instance<'ll, 'tcx>(
// the string "false". Now it is disabled by absence of the attribute.
to_add.push(llvm::CreateAttrStringValue(cx.llcx, "branch-target-enforcement", "false"));
}
- } else if llvm_util::get_version() >= (19, 0, 0) {
- // For non-naked functions, set branch protection attributes on aarch64.
- if let Some(BranchProtection { bti, pac_ret }) =
- cx.sess().opts.unstable_opts.branch_protection
- {
- assert!(cx.sess().target.arch == "aarch64");
- if bti {
- to_add.push(llvm::CreateAttrString(cx.llcx, "branch-target-enforcement"));
- }
- if let Some(PacRet { leaf, key }) = pac_ret {
- to_add.push(llvm::CreateAttrStringValue(
- cx.llcx,
- "sign-return-address",
- if leaf { "all" } else { "non-leaf" },
- ));
- to_add.push(llvm::CreateAttrStringValue(
- cx.llcx,
- "sign-return-address-key",
- if key == PAuthKey::A { "a_key" } else { "b_key" },
- ));
+ } else {
+ // Do not set sanitizer attributes for naked functions.
+ to_add.extend(sanitize_attrs(cx, codegen_fn_attrs.no_sanitize));
+
+ if llvm_util::get_version() >= (19, 0, 0) {
+ // For non-naked functions, set branch protection attributes on aarch64.
+ if let Some(BranchProtection { bti, pac_ret }) =
+ cx.sess().opts.unstable_opts.branch_protection
+ {
+ assert!(cx.sess().target.arch == "aarch64");
+ if bti {
+ to_add.push(llvm::CreateAttrString(cx.llcx, "branch-target-enforcement"));
+ }
+ if let Some(PacRet { leaf, key }) = pac_ret {
+ to_add.push(llvm::CreateAttrStringValue(
+ cx.llcx,
+ "sign-return-address",
+ if leaf { "all" } else { "non-leaf" },
+ ));
+ to_add.push(llvm::CreateAttrStringValue(
+ cx.llcx,
+ "sign-return-address-key",
+ if key == PAuthKey::A { "a_key" } else { "b_key" },
+ ));
+ }
}
}
}
@@ -485,7 +490,6 @@ pub(crate) fn llfn_attrs_from_instance<'ll, 'tcx>(
if let Some(backchain) = backchain_attr(cx) {
to_add.push(backchain);
}
- to_add.extend(sanitize_attrs(cx, codegen_fn_attrs.no_sanitize));
to_add.extend(patchable_function_entry_attrs(cx, codegen_fn_attrs.patchable_function_entry));
// Always annotate functions with the target-cpu they are compiled for.
diff --git a/compiler/rustc_codegen_llvm/src/back/lto.rs b/compiler/rustc_codegen_llvm/src/back/lto.rs
index aa6842c..09896b8 100644
--- a/compiler/rustc_codegen_llvm/src/back/lto.rs
+++ b/compiler/rustc_codegen_llvm/src/back/lto.rs
@@ -314,7 +314,6 @@ fn fat_lto(
}
}
};
- let mut serialized_bitcode = Vec::new();
{
let (llcx, llmod) = {
let llvm = &module.module_llvm;
@@ -342,9 +341,7 @@ fn fat_lto(
serialized_modules.sort_by(|module1, module2| module1.1.cmp(&module2.1));
// For all serialized bitcode files we parse them and link them in as we did
- // above, this is all mostly handled in C++. Like above, though, we don't
- // know much about the memory management here so we err on the side of being
- // save and persist everything with the original module.
+ // above, this is all mostly handled in C++.
let mut linker = Linker::new(llmod);
for (bc_decoded, name) in serialized_modules {
let _timer = cgcx
@@ -355,7 +352,6 @@ fn fat_lto(
info!("linking {:?}", name);
let data = bc_decoded.data();
linker.add(data).map_err(|()| write::llvm_err(dcx, LlvmError::LoadBitcode { name }))?;
- serialized_bitcode.push(bc_decoded);
}
drop(linker);
save_temp_bitcode(cgcx, &module, "lto.input");
@@ -372,7 +368,7 @@ fn fat_lto(
}
}
- Ok(LtoModuleCodegen::Fat { module, _serialized_bitcode: serialized_bitcode })
+ Ok(LtoModuleCodegen::Fat(module))
}
pub(crate) struct Linker<'a>(&'a mut llvm::Linker<'a>);
diff --git a/compiler/rustc_codegen_llvm/src/consts.rs b/compiler/rustc_codegen_llvm/src/consts.rs
index b143e28..d60122fc 100644
--- a/compiler/rustc_codegen_llvm/src/consts.rs
+++ b/compiler/rustc_codegen_llvm/src/consts.rs
@@ -390,7 +390,7 @@ fn codegen_static_item(&self, def_id: DefId) {
let val_llty = self.val_ty(v);
let g = self.get_static_inner(def_id, val_llty);
- let llty = self.val_ty(g);
+ let llty = llvm::LLVMGlobalGetValueType(g);
let g = if val_llty == llty {
g
diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs
index 17a9630..d231b10 100644
--- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs
+++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs
@@ -456,7 +456,7 @@ pub(crate) fn type_di_node<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>, t: Ty<'tcx>) ->
if def.is_box()
&& args.get(1).map_or(true, |arg| cx.layout_of(arg.expect_ty()).is_1zst()) =>
{
- build_pointer_or_reference_di_node(cx, t, t.boxed_ty(), unique_type_id)
+ build_pointer_or_reference_di_node(cx, t, t.expect_boxed_ty(), unique_type_id)
}
ty::FnDef(..) | ty::FnPtr(..) => build_subroutine_type_di_node(cx, unique_type_id),
ty::Closure(..) => build_closure_env_di_node(cx, unique_type_id),
diff --git a/compiler/rustc_codegen_llvm/src/intrinsic.rs b/compiler/rustc_codegen_llvm/src/intrinsic.rs
index a300f5f..05fb77a 100644
--- a/compiler/rustc_codegen_llvm/src/intrinsic.rs
+++ b/compiler/rustc_codegen_llvm/src/intrinsic.rs
@@ -187,9 +187,7 @@ fn codegen_intrinsic_call(
Some(instance),
)
}
- sym::likely => {
- self.call_intrinsic("llvm.expect.i1", &[args[0].immediate(), self.const_bool(true)])
- }
+ sym::likely => self.expect(args[0].immediate(), true),
sym::is_val_statically_known => {
let intrinsic_type = args[0].layout.immediate_llvm_type(self.cx);
let kind = self.type_kind(intrinsic_type);
@@ -210,8 +208,7 @@ fn codegen_intrinsic_call(
self.const_bool(false)
}
}
- sym::unlikely => self
- .call_intrinsic("llvm.expect.i1", &[args[0].immediate(), self.const_bool(false)]),
+ sym::unlikely => self.expect(args[0].immediate(), false),
sym::select_unpredictable => {
let cond = args[0].immediate();
assert_eq!(args[1].layout, args[2].layout);
@@ -604,11 +601,17 @@ fn abort(&mut self) {
}
fn assume(&mut self, val: Self::Value) {
- self.call_intrinsic("llvm.assume", &[val]);
+ if self.cx.sess().opts.optimize != rustc_session::config::OptLevel::No {
+ self.call_intrinsic("llvm.assume", &[val]);
+ }
}
fn expect(&mut self, cond: Self::Value, expected: bool) -> Self::Value {
- self.call_intrinsic("llvm.expect.i1", &[cond, self.const_bool(expected)])
+ if self.cx.sess().opts.optimize != rustc_session::config::OptLevel::No {
+ self.call_intrinsic("llvm.expect.i1", &[cond, self.const_bool(expected)])
+ } else {
+ cond
+ }
}
fn type_test(&mut self, pointer: Self::Value, typeid: Self::Value) -> Self::Value {
diff --git a/compiler/rustc_codegen_llvm/src/lib.rs b/compiler/rustc_codegen_llvm/src/lib.rs
index 6a303e1..7f26bbd 100644
--- a/compiler/rustc_codegen_llvm/src/lib.rs
+++ b/compiler/rustc_codegen_llvm/src/lib.rs
@@ -6,7 +6,6 @@
// tidy-alphabetical-start
#![allow(internal_features)]
-#![cfg_attr(bootstrap, feature(unsafe_extern_blocks))]
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
#![doc(rust_logo)]
#![feature(assert_matches)]
diff --git a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs
index 138cc32..3bf4d49 100644
--- a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs
+++ b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs
@@ -974,6 +974,7 @@ pub fn LLVMConstInBoundsGEP2<'a>(
pub fn LLVMGetAlignment(Global: &Value) -> c_uint;
pub fn LLVMSetAlignment(Global: &Value, Bytes: c_uint);
pub fn LLVMSetDLLStorageClass(V: &Value, C: DLLStorageClass);
+ pub fn LLVMGlobalGetValueType(Global: &Value) -> &Type;
// Operations on global variables
pub fn LLVMIsAGlobalVariable(GlobalVar: &Value) -> Option<&Value>;
diff --git a/compiler/rustc_codegen_llvm/src/llvm_util.rs b/compiler/rustc_codegen_llvm/src/llvm_util.rs
index 618602e..d55220b 100644
--- a/compiler/rustc_codegen_llvm/src/llvm_util.rs
+++ b/compiler/rustc_codegen_llvm/src/llvm_util.rs
@@ -353,9 +353,7 @@ pub fn target_features(sess: &Session, allow_unstable: bool) -> Vec<Symbol> {
None
}
})
- .filter(|feature| {
- RUSTC_SPECIAL_FEATURES.contains(feature) || features.contains(&Symbol::intern(feature))
- })
+ .filter(|feature| features.contains(&Symbol::intern(feature)))
.map(|feature| Symbol::intern(feature))
.collect()
}
diff --git a/compiler/rustc_codegen_ssa/src/back/lto.rs b/compiler/rustc_codegen_ssa/src/back/lto.rs
index 8b6f6b5..1e1e039 100644
--- a/compiler/rustc_codegen_ssa/src/back/lto.rs
+++ b/compiler/rustc_codegen_ssa/src/back/lto.rs
@@ -41,18 +41,14 @@ pub struct ThinShared<B: WriteBackendMethods> {
}
pub enum LtoModuleCodegen<B: WriteBackendMethods> {
- Fat {
- module: ModuleCodegen<B::Module>,
- _serialized_bitcode: Vec<SerializedModule<B::ModuleBuffer>>,
- },
-
+ Fat(ModuleCodegen<B::Module>),
Thin(ThinModule<B>),
}
impl<B: WriteBackendMethods> LtoModuleCodegen<B> {
pub fn name(&self) -> &str {
match *self {
- LtoModuleCodegen::Fat { .. } => "everything",
+ LtoModuleCodegen::Fat(_) => "everything",
LtoModuleCodegen::Thin(ref m) => m.name(),
}
}
@@ -68,7 +64,7 @@ pub unsafe fn optimize(
cgcx: &CodegenContext<B>,
) -> Result<ModuleCodegen<B::Module>, FatalError> {
match self {
- LtoModuleCodegen::Fat { mut module, .. } => {
+ LtoModuleCodegen::Fat(mut module) => {
B::optimize_fat(cgcx, &mut module)?;
Ok(module)
}
@@ -81,7 +77,7 @@ pub unsafe fn optimize(
pub fn cost(&self) -> u64 {
match *self {
// Only one module with fat LTO, so the cost doesn't matter.
- LtoModuleCodegen::Fat { .. } => 0,
+ LtoModuleCodegen::Fat(_) => 0,
LtoModuleCodegen::Thin(ref m) => m.cost(),
}
}
diff --git a/compiler/rustc_codegen_ssa/src/back/metadata.rs b/compiler/rustc_codegen_ssa/src/back/metadata.rs
index 9b5a797..0fd9d7f 100644
--- a/compiler/rustc_codegen_ssa/src/back/metadata.rs
+++ b/compiler/rustc_codegen_ssa/src/back/metadata.rs
@@ -372,27 +372,42 @@ pub(crate) fn create_object_file(sess: &Session) -> Option<write::Object<'static
Some(file)
}
-/// Since Xcode 15 Apple's LD requires object files to contain information about what they were
-/// built for (LC_BUILD_VERSION): the platform (macOS/watchOS etc), minimum OS version, and SDK
-/// version. This returns a `MachOBuildVersion` for the target.
+/// Mach-O files contain information about:
+/// - The platform/OS they were built for (macOS/watchOS/Mac Catalyst/iOS simulator etc).
+/// - The minimum OS version / deployment target.
+/// - The version of the SDK they were targetting.
+///
+/// In the past, this was accomplished using the LC_VERSION_MIN_MACOSX, LC_VERSION_MIN_IPHONEOS,
+/// LC_VERSION_MIN_TVOS or LC_VERSION_MIN_WATCHOS load commands, which each contain information
+/// about the deployment target and SDK version, and implicitly, by their presence, which OS they
+/// target. Simulator targets were determined if the architecture was x86_64, but there was e.g. a
+/// LC_VERSION_MIN_IPHONEOS present.
+///
+/// This is of course brittle and limited, so modern tooling emit the LC_BUILD_VERSION load
+/// command (which contains all three pieces of information in one) when the deployment target is
+/// high enough, or the target is something that wouldn't be encodable with the old load commands
+/// (such as Mac Catalyst, or Aarch64 iOS simulator).
+///
+/// Since Xcode 15, Apple's LD apparently requires object files to use this load command, so this
+/// returns the `MachOBuildVersion` for the target to do so.
fn macho_object_build_version_for_target(target: &Target) -> object::write::MachOBuildVersion {
/// The `object` crate demands "X.Y.Z encoded in nibbles as xxxx.yy.zz"
/// e.g. minOS 14.0 = 0x000E0000, or SDK 16.2 = 0x00100200
- fn pack_version((major, minor): (u32, u32)) -> u32 {
- (major << 16) | (minor << 8)
+ fn pack_version((major, minor, patch): (u16, u8, u8)) -> u32 {
+ let (major, minor, patch) = (major as u32, minor as u32, patch as u32);
+ (major << 16) | (minor << 8) | patch
}
let platform =
rustc_target::spec::current_apple_platform(target).expect("unknown Apple target OS");
- let min_os = rustc_target::spec::current_apple_deployment_target(target)
- .expect("unknown Apple target OS");
- let sdk =
+ let min_os = rustc_target::spec::current_apple_deployment_target(target);
+ let (sdk_major, sdk_minor) =
rustc_target::spec::current_apple_sdk_version(platform).expect("unknown Apple target OS");
let mut build_version = object::write::MachOBuildVersion::default();
build_version.platform = platform;
build_version.minos = pack_version(min_os);
- build_version.sdk = pack_version(sdk);
+ build_version.sdk = pack_version((sdk_major, sdk_minor, 0));
build_version
}
diff --git a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs
index d94c6f8..91fd990 100644
--- a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs
@@ -382,7 +382,7 @@ fn assume_scalar_range(
scalar: abi::Scalar,
backend_ty: Bx::Type,
) {
- if matches!(self.cx.sess().opts.optimize, OptLevel::No | OptLevel::Less)
+ if matches!(self.cx.sess().opts.optimize, OptLevel::No)
// For now, the critical niches are all over `Int`eger values.
// Should floating-point values or pointers ever get more complex
// niches, then this code will probably want to handle them too.
diff --git a/compiler/rustc_codegen_ssa/src/mir/statement.rs b/compiler/rustc_codegen_ssa/src/mir/statement.rs
index 2ef860f..73283ca 100644
--- a/compiler/rustc_codegen_ssa/src/mir/statement.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/statement.rs
@@ -1,6 +1,5 @@
use rustc_middle::mir::{self, NonDivergingIntrinsic};
use rustc_middle::span_bug;
-use rustc_session::config::OptLevel;
use tracing::instrument;
use super::{FunctionCx, LocalRef};
@@ -68,10 +67,8 @@ pub fn codegen_statement(&mut self, bx: &mut Bx, statement: &mir::Statement<'tcx
self.codegen_coverage(bx, kind, statement.source_info.scope);
}
mir::StatementKind::Intrinsic(box NonDivergingIntrinsic::Assume(ref op)) => {
- if !matches!(bx.tcx().sess.opts.optimize, OptLevel::No | OptLevel::Less) {
- let op_val = self.codegen_operand(bx, op);
- bx.assume(op_val.immediate());
- }
+ let op_val = self.codegen_operand(bx, op);
+ bx.assume(op_val.immediate());
}
mir::StatementKind::Intrinsic(box NonDivergingIntrinsic::CopyNonOverlapping(
mir::CopyNonOverlapping { ref count, ref src, ref dst },
diff --git a/compiler/rustc_const_eval/src/const_eval/eval_queries.rs b/compiler/rustc_const_eval/src/const_eval/eval_queries.rs
index 96b3ec6..7ccebd8 100644
--- a/compiler/rustc_const_eval/src/const_eval/eval_queries.rs
+++ b/compiler/rustc_const_eval/src/const_eval/eval_queries.rs
@@ -94,7 +94,7 @@ fn eval_body_using_ecx<'tcx, R: InterpretationResult<'tcx>>(
let intern_result = intern_const_alloc_recursive(ecx, intern_kind, &ret);
// Since evaluation had no errors, validate the resulting constant.
- const_validate_mplace(&ecx, &ret, cid)?;
+ const_validate_mplace(ecx, &ret, cid)?;
// Only report this after validation, as validaiton produces much better diagnostics.
// FIXME: ensure validation always reports this and stop making interning care about it.
@@ -391,7 +391,7 @@ fn eval_in_interpreter<'tcx, R: InterpretationResult<'tcx>>(
#[inline(always)]
fn const_validate_mplace<'tcx>(
- ecx: &InterpCx<'tcx, CompileTimeMachine<'tcx>>,
+ ecx: &mut InterpCx<'tcx, CompileTimeMachine<'tcx>>,
mplace: &MPlaceTy<'tcx>,
cid: GlobalId<'tcx>,
) -> Result<(), ErrorHandled> {
diff --git a/compiler/rustc_const_eval/src/const_eval/machine.rs b/compiler/rustc_const_eval/src/const_eval/machine.rs
index 9c1fef0..7405ca0 100644
--- a/compiler/rustc_const_eval/src/const_eval/machine.rs
+++ b/compiler/rustc_const_eval/src/const_eval/machine.rs
@@ -1,16 +1,16 @@
-use std::borrow::Borrow;
+use std::borrow::{Borrow, Cow};
use std::fmt;
use std::hash::Hash;
use std::ops::ControlFlow;
use rustc_ast::Mutability;
-use rustc_data_structures::fx::{FxIndexMap, IndexEntry};
+use rustc_data_structures::fx::{FxHashMap, FxIndexMap, IndexEntry};
use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_hir::{self as hir, LangItem, CRATE_HIR_ID};
use rustc_middle::mir::AssertMessage;
use rustc_middle::query::TyCtxtAt;
use rustc_middle::ty::layout::{FnAbiOf, TyAndLayout};
-use rustc_middle::ty::{self, TyCtxt};
+use rustc_middle::ty::{self, Ty, TyCtxt};
use rustc_middle::{bug, mir};
use rustc_span::symbol::{sym, Symbol};
use rustc_span::Span;
@@ -24,8 +24,8 @@
use crate::interpret::{
self, compile_time_machine, err_ub, throw_exhaust, throw_inval, throw_ub_custom, throw_unsup,
throw_unsup_format, AllocId, AllocRange, ConstAllocation, CtfeProvenance, FnArg, Frame,
- GlobalAlloc, ImmTy, InterpCx, InterpResult, MPlaceTy, OpTy, Pointer, PointerArithmetic, Scalar,
- StackPopCleanup,
+ GlobalAlloc, ImmTy, InterpCx, InterpResult, MPlaceTy, OpTy, Pointer, PointerArithmetic,
+ RangeSet, Scalar, StackPopCleanup,
};
/// When hitting this many interpreted terminators we emit a deny by default lint
@@ -65,6 +65,9 @@ pub struct CompileTimeMachine<'tcx> {
/// storing the result in the given `AllocId`.
/// Used to prevent reads from a static's base allocation, as that may allow for self-initialization loops.
pub(crate) static_root_ids: Option<(AllocId, LocalDefId)>,
+
+ /// A cache of "data range" computations for unions (i.e., the offsets of non-padding bytes).
+ union_data_ranges: FxHashMap<Ty<'tcx>, RangeSet>,
}
#[derive(Copy, Clone)]
@@ -99,6 +102,7 @@ pub(crate) fn new(
can_access_mut_global,
check_alignment,
static_root_ids: None,
+ union_data_ranges: FxHashMap::default(),
}
}
}
@@ -766,6 +770,19 @@ fn before_alloc_read(ecx: &InterpCx<'tcx, Self>, alloc_id: AllocId) -> InterpRes
}
Ok(())
}
+
+ fn cached_union_data_range<'e>(
+ ecx: &'e mut InterpCx<'tcx, Self>,
+ ty: Ty<'tcx>,
+ compute_range: impl FnOnce() -> RangeSet,
+ ) -> Cow<'e, RangeSet> {
+ if ecx.tcx.sess.opts.unstable_opts.extra_const_ub_checks {
+ Cow::Borrowed(ecx.machine.union_data_ranges.entry(ty).or_insert_with(compute_range))
+ } else {
+ // Don't bother caching, we're only doing one validation at the end anyway.
+ Cow::Owned(compute_range())
+ }
+ }
}
// Please do not add any code below the above `Machine` trait impl. I (oli-obk) plan more cleanups
diff --git a/compiler/rustc_const_eval/src/interpret/call.rs b/compiler/rustc_const_eval/src/interpret/call.rs
index 82438eb..568a9a3 100644
--- a/compiler/rustc_const_eval/src/interpret/call.rs
+++ b/compiler/rustc_const_eval/src/interpret/call.rs
@@ -189,7 +189,7 @@ fn layout_compat(
ty::Ref(_, ty, _) => *ty,
ty::RawPtr(ty, _) => *ty,
// We only accept `Box` with the default allocator.
- _ if ty.is_box_global(*self.tcx) => ty.boxed_ty(),
+ _ if ty.is_box_global(*self.tcx) => ty.expect_boxed_ty(),
_ => return Ok(None),
}))
};
diff --git a/compiler/rustc_const_eval/src/interpret/discriminant.rs b/compiler/rustc_const_eval/src/interpret/discriminant.rs
index 0008a15..de93ed8 100644
--- a/compiler/rustc_const_eval/src/interpret/discriminant.rs
+++ b/compiler/rustc_const_eval/src/interpret/discriminant.rs
@@ -7,7 +7,7 @@
use tracing::{instrument, trace};
use super::{
- err_ub, throw_ub, ImmTy, InterpCx, InterpResult, Machine, Readable, Scalar, Writeable,
+ err_ub, throw_ub, ImmTy, InterpCx, InterpResult, Machine, Projectable, Scalar, Writeable,
};
impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
@@ -60,7 +60,7 @@ pub fn write_discriminant(
#[instrument(skip(self), level = "trace")]
pub fn read_discriminant(
&self,
- op: &impl Readable<'tcx, M::Provenance>,
+ op: &impl Projectable<'tcx, M::Provenance>,
) -> InterpResult<'tcx, VariantIdx> {
let ty = op.layout().ty;
trace!("read_discriminant_value {:#?}", op.layout());
diff --git a/compiler/rustc_const_eval/src/interpret/machine.rs b/compiler/rustc_const_eval/src/interpret/machine.rs
index 6cfd7be..8cab3c3 100644
--- a/compiler/rustc_const_eval/src/interpret/machine.rs
+++ b/compiler/rustc_const_eval/src/interpret/machine.rs
@@ -10,6 +10,7 @@
use rustc_ast::{InlineAsmOptions, InlineAsmTemplatePiece};
use rustc_middle::query::TyCtxtAt;
use rustc_middle::ty::layout::TyAndLayout;
+use rustc_middle::ty::Ty;
use rustc_middle::{mir, ty};
use rustc_span::def_id::DefId;
use rustc_span::Span;
@@ -19,7 +20,7 @@
use super::{
throw_unsup, throw_unsup_format, AllocBytes, AllocId, AllocKind, AllocRange, Allocation,
ConstAllocation, CtfeProvenance, FnArg, Frame, ImmTy, InterpCx, InterpResult, MPlaceTy,
- MemoryKind, Misalignment, OpTy, PlaceTy, Pointer, Provenance, CTFE_ALLOC_SALT,
+ MemoryKind, Misalignment, OpTy, PlaceTy, Pointer, Provenance, RangeSet, CTFE_ALLOC_SALT,
};
/// Data returned by [`Machine::after_stack_pop`], and consumed by
@@ -578,6 +579,15 @@ fn get_global_alloc_salt(
ecx: &InterpCx<'tcx, Self>,
instance: Option<ty::Instance<'tcx>>,
) -> usize;
+
+ fn cached_union_data_range<'e>(
+ _ecx: &'e mut InterpCx<'tcx, Self>,
+ _ty: Ty<'tcx>,
+ compute_range: impl FnOnce() -> RangeSet,
+ ) -> Cow<'e, RangeSet> {
+ // Default to no caching.
+ Cow::Owned(compute_range())
+ }
}
/// A lot of the flexibility above is just needed for `Miri`, but all "compile-time" machines
diff --git a/compiler/rustc_const_eval/src/interpret/memory.rs b/compiler/rustc_const_eval/src/interpret/memory.rs
index 45a5eb9..d875884 100644
--- a/compiler/rustc_const_eval/src/interpret/memory.rs
+++ b/compiler/rustc_const_eval/src/interpret/memory.rs
@@ -8,9 +8,8 @@
use std::assert_matches::assert_matches;
use std::borrow::Cow;
-use std::cell::Cell;
use std::collections::VecDeque;
-use std::{fmt, ptr};
+use std::{fmt, mem, ptr};
use rustc_ast::Mutability;
use rustc_data_structures::fx::{FxHashSet, FxIndexMap};
@@ -118,7 +117,7 @@ pub struct Memory<'tcx, M: Machine<'tcx>> {
/// This stores whether we are currently doing reads purely for the purpose of validation.
/// Those reads do not trigger the machine's hooks for memory reads.
/// Needless to say, this must only be set with great care!
- validation_in_progress: Cell<bool>,
+ validation_in_progress: bool,
}
/// A reference to some allocation that was already bounds-checked for the given region
@@ -145,7 +144,7 @@ pub fn new() -> Self {
alloc_map: M::MemoryMap::default(),
extra_fn_ptr_map: FxIndexMap::default(),
dead_alloc_map: FxIndexMap::default(),
- validation_in_progress: Cell::new(false),
+ validation_in_progress: false,
}
}
@@ -682,7 +681,7 @@ pub fn get_ptr_alloc<'a>(
// We want to call the hook on *all* accesses that involve an AllocId, including zero-sized
// accesses. That means we cannot rely on the closure above or the `Some` branch below. We
// do this after `check_and_deref_ptr` to ensure some basic sanity has already been checked.
- if !self.memory.validation_in_progress.get() {
+ if !self.memory.validation_in_progress {
if let Ok((alloc_id, ..)) = self.ptr_try_get_alloc_id(ptr, size_i64) {
M::before_alloc_read(self, alloc_id)?;
}
@@ -690,7 +689,7 @@ pub fn get_ptr_alloc<'a>(
if let Some((alloc_id, offset, prov, alloc)) = ptr_and_alloc {
let range = alloc_range(offset, size);
- if !self.memory.validation_in_progress.get() {
+ if !self.memory.validation_in_progress {
M::before_memory_read(
self.tcx,
&self.machine,
@@ -766,11 +765,14 @@ pub fn get_ptr_alloc_mut<'a>(
let parts = self.get_ptr_access(ptr, size)?;
if let Some((alloc_id, offset, prov)) = parts {
let tcx = self.tcx;
+ let validation_in_progress = self.memory.validation_in_progress;
// FIXME: can we somehow avoid looking up the allocation twice here?
// We cannot call `get_raw_mut` inside `check_and_deref_ptr` as that would duplicate `&mut self`.
let (alloc, machine) = self.get_alloc_raw_mut(alloc_id)?;
let range = alloc_range(offset, size);
- M::before_memory_write(tcx, machine, &mut alloc.extra, (alloc_id, prov), range)?;
+ if !validation_in_progress {
+ M::before_memory_write(tcx, machine, &mut alloc.extra, (alloc_id, prov), range)?;
+ }
Ok(Some(AllocRefMut { alloc, range, tcx: *tcx, alloc_id }))
} else {
Ok(None)
@@ -1014,16 +1016,16 @@ pub fn find_leaked_allocations(
///
/// We do this so Miri's allocation access tracking does not show the validation
/// reads as spurious accesses.
- pub fn run_for_validation<R>(&self, f: impl FnOnce() -> R) -> R {
+ pub fn run_for_validation<R>(&mut self, f: impl FnOnce(&mut Self) -> R) -> R {
// This deliberately uses `==` on `bool` to follow the pattern
// `assert!(val.replace(new) == old)`.
assert!(
- self.memory.validation_in_progress.replace(true) == false,
+ mem::replace(&mut self.memory.validation_in_progress, true) == false,
"`validation_in_progress` was already set"
);
- let res = f();
+ let res = f(self);
assert!(
- self.memory.validation_in_progress.replace(false) == true,
+ mem::replace(&mut self.memory.validation_in_progress, false) == true,
"`validation_in_progress` was unset by someone else"
);
res
@@ -1115,6 +1117,10 @@ fn write_allocation_track_relocs<'tcx, Prov: Provenance, Extra, Bytes: AllocByte
impl<'tcx, 'a, Prov: Provenance, Extra, Bytes: AllocBytes>
AllocRefMut<'a, 'tcx, Prov, Extra, Bytes>
{
+ pub fn as_ref<'b>(&'b self) -> AllocRef<'b, 'tcx, Prov, Extra, Bytes> {
+ AllocRef { alloc: self.alloc, range: self.range, tcx: self.tcx, alloc_id: self.alloc_id }
+ }
+
/// `range` is relative to this allocation reference, not the base of the allocation.
pub fn write_scalar(&mut self, range: AllocRange, val: Scalar<Prov>) -> InterpResult<'tcx> {
let range = self.range.subrange(range);
@@ -1130,13 +1136,30 @@ pub fn write_ptr_sized(&mut self, offset: Size, val: Scalar<Prov>) -> InterpResu
self.write_scalar(alloc_range(offset, self.tcx.data_layout().pointer_size), val)
}
+ /// Mark the given sub-range (relative to this allocation reference) as uninitialized.
+ pub fn write_uninit(&mut self, range: AllocRange) -> InterpResult<'tcx> {
+ let range = self.range.subrange(range);
+ Ok(self
+ .alloc
+ .write_uninit(&self.tcx, range)
+ .map_err(|e| e.to_interp_error(self.alloc_id))?)
+ }
+
/// Mark the entire referenced range as uninitialized
- pub fn write_uninit(&mut self) -> InterpResult<'tcx> {
+ pub fn write_uninit_full(&mut self) -> InterpResult<'tcx> {
Ok(self
.alloc
.write_uninit(&self.tcx, self.range)
.map_err(|e| e.to_interp_error(self.alloc_id))?)
}
+
+ /// Remove all provenance in the reference range.
+ pub fn clear_provenance(&mut self) -> InterpResult<'tcx> {
+ Ok(self
+ .alloc
+ .clear_provenance(&self.tcx, self.range)
+ .map_err(|e| e.to_interp_error(self.alloc_id))?)
+ }
}
impl<'tcx, 'a, Prov: Provenance, Extra, Bytes: AllocBytes> AllocRef<'a, 'tcx, Prov, Extra, Bytes> {
@@ -1278,7 +1301,7 @@ pub fn mem_copy_repeatedly(
};
let src_alloc = self.get_alloc_raw(src_alloc_id)?;
let src_range = alloc_range(src_offset, size);
- assert!(!self.memory.validation_in_progress.get(), "we can't be copying during validation");
+ assert!(!self.memory.validation_in_progress, "we can't be copying during validation");
M::before_memory_read(
tcx,
&self.machine,
diff --git a/compiler/rustc_const_eval/src/interpret/mod.rs b/compiler/rustc_const_eval/src/interpret/mod.rs
index 511756e..561d681 100644
--- a/compiler/rustc_const_eval/src/interpret/mod.rs
+++ b/compiler/rustc_const_eval/src/interpret/mod.rs
@@ -33,11 +33,11 @@
pub use self::machine::{compile_time_machine, AllocMap, Machine, MayLeak, ReturnAction};
pub use self::memory::{AllocKind, AllocRef, AllocRefMut, FnVal, Memory, MemoryKind};
use self::operand::Operand;
-pub use self::operand::{ImmTy, Immediate, OpTy, Readable};
+pub use self::operand::{ImmTy, Immediate, OpTy};
pub use self::place::{MPlaceTy, MemPlaceMeta, PlaceTy, Writeable};
use self::place::{MemPlace, Place};
pub use self::projection::{OffsetMode, Projectable};
pub use self::stack::{Frame, FrameInfo, LocalState, StackPopCleanup, StackPopInfo};
pub(crate) use self::util::create_static_alloc;
-pub use self::validity::{CtfeValidationMode, RefTracking};
+pub use self::validity::{CtfeValidationMode, RangeSet, RefTracking};
pub use self::visitor::ValueVisitor;
diff --git a/compiler/rustc_const_eval/src/interpret/operand.rs b/compiler/rustc_const_eval/src/interpret/operand.rs
index 9a8ccaa..b906e34 100644
--- a/compiler/rustc_const_eval/src/interpret/operand.rs
+++ b/compiler/rustc_const_eval/src/interpret/operand.rs
@@ -111,6 +111,46 @@ pub fn to_scalar_and_meta(self) -> (Scalar<Prov>, MemPlaceMeta<Prov>) {
Immediate::Uninit => bug!("Got uninit where a scalar or scalar pair was expected"),
}
}
+
+ /// Assert that this immediate is a valid value for the given ABI.
+ pub fn assert_matches_abi(self, abi: Abi, cx: &impl HasDataLayout) {
+ match (self, abi) {
+ (Immediate::Scalar(scalar), Abi::Scalar(s)) => {
+ assert_eq!(scalar.size(), s.size(cx));
+ if !matches!(s.primitive(), abi::Pointer(..)) {
+ assert!(matches!(scalar, Scalar::Int(..)));
+ }
+ }
+ (Immediate::ScalarPair(a_val, b_val), Abi::ScalarPair(a, b)) => {
+ assert_eq!(a_val.size(), a.size(cx));
+ if !matches!(a.primitive(), abi::Pointer(..)) {
+ assert!(matches!(a_val, Scalar::Int(..)));
+ }
+ assert_eq!(b_val.size(), b.size(cx));
+ if !matches!(b.primitive(), abi::Pointer(..)) {
+ assert!(matches!(b_val, Scalar::Int(..)));
+ }
+ }
+ (Immediate::Uninit, _) => {}
+ _ => {
+ bug!("value {self:?} does not match ABI {abi:?})",)
+ }
+ }
+ }
+
+ pub fn clear_provenance<'tcx>(&mut self) -> InterpResult<'tcx> {
+ match self {
+ Immediate::Scalar(s) => {
+ s.clear_provenance()?;
+ }
+ Immediate::ScalarPair(a, b) => {
+ a.clear_provenance()?;
+ b.clear_provenance()?;
+ }
+ Immediate::Uninit => {}
+ }
+ Ok(())
+ }
}
// ScalarPair needs a type to interpret, so we often have an immediate and a type together
@@ -490,32 +530,6 @@ fn to_op<M: Machine<'tcx, Provenance = Prov>>(
}
}
-/// The `Readable` trait describes interpreter values that one can read from.
-pub trait Readable<'tcx, Prov: Provenance>: Projectable<'tcx, Prov> {
- fn as_mplace_or_imm(&self) -> Either<MPlaceTy<'tcx, Prov>, ImmTy<'tcx, Prov>>;
-}
-
-impl<'tcx, Prov: Provenance> Readable<'tcx, Prov> for OpTy<'tcx, Prov> {
- #[inline(always)]
- fn as_mplace_or_imm(&self) -> Either<MPlaceTy<'tcx, Prov>, ImmTy<'tcx, Prov>> {
- self.as_mplace_or_imm()
- }
-}
-
-impl<'tcx, Prov: Provenance> Readable<'tcx, Prov> for MPlaceTy<'tcx, Prov> {
- #[inline(always)]
- fn as_mplace_or_imm(&self) -> Either<MPlaceTy<'tcx, Prov>, ImmTy<'tcx, Prov>> {
- Left(self.clone())
- }
-}
-
-impl<'tcx, Prov: Provenance> Readable<'tcx, Prov> for ImmTy<'tcx, Prov> {
- #[inline(always)]
- fn as_mplace_or_imm(&self) -> Either<MPlaceTy<'tcx, Prov>, ImmTy<'tcx, Prov>> {
- Right(self.clone())
- }
-}
-
impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
/// Try reading an immediate in memory; this is interesting particularly for `ScalarPair`.
/// Returns `None` if the layout does not permit loading this as a value.
@@ -588,9 +602,9 @@ fn read_immediate_from_mplace_raw(
/// ConstProp needs it, though.
pub fn read_immediate_raw(
&self,
- src: &impl Readable<'tcx, M::Provenance>,
+ src: &impl Projectable<'tcx, M::Provenance>,
) -> InterpResult<'tcx, Either<MPlaceTy<'tcx, M::Provenance>, ImmTy<'tcx, M::Provenance>>> {
- Ok(match src.as_mplace_or_imm() {
+ Ok(match src.to_op(self)?.as_mplace_or_imm() {
Left(ref mplace) => {
if let Some(val) = self.read_immediate_from_mplace_raw(mplace)? {
Right(val)
@@ -608,7 +622,7 @@ pub fn read_immediate_raw(
#[inline(always)]
pub fn read_immediate(
&self,
- op: &impl Readable<'tcx, M::Provenance>,
+ op: &impl Projectable<'tcx, M::Provenance>,
) -> InterpResult<'tcx, ImmTy<'tcx, M::Provenance>> {
if !matches!(
op.layout().abi,
@@ -627,7 +641,7 @@ pub fn read_immediate(
/// Read a scalar from a place
pub fn read_scalar(
&self,
- op: &impl Readable<'tcx, M::Provenance>,
+ op: &impl Projectable<'tcx, M::Provenance>,
) -> InterpResult<'tcx, Scalar<M::Provenance>> {
Ok(self.read_immediate(op)?.to_scalar())
}
@@ -638,21 +652,21 @@ pub fn read_scalar(
/// Read a pointer from a place.
pub fn read_pointer(
&self,
- op: &impl Readable<'tcx, M::Provenance>,
+ op: &impl Projectable<'tcx, M::Provenance>,
) -> InterpResult<'tcx, Pointer<Option<M::Provenance>>> {
self.read_scalar(op)?.to_pointer(self)
}
/// Read a pointer-sized unsigned integer from a place.
pub fn read_target_usize(
&self,
- op: &impl Readable<'tcx, M::Provenance>,
+ op: &impl Projectable<'tcx, M::Provenance>,
) -> InterpResult<'tcx, u64> {
self.read_scalar(op)?.to_target_usize(self)
}
/// Read a pointer-sized signed integer from a place.
pub fn read_target_isize(
&self,
- op: &impl Readable<'tcx, M::Provenance>,
+ op: &impl Projectable<'tcx, M::Provenance>,
) -> InterpResult<'tcx, i64> {
self.read_scalar(op)?.to_target_isize(self)
}
@@ -717,7 +731,7 @@ pub fn place_to_op(
) -> InterpResult<'tcx, OpTy<'tcx, M::Provenance>> {
match place.as_mplace_or_local() {
Left(mplace) => Ok(mplace.into()),
- Right((local, offset, locals_addr)) => {
+ Right((local, offset, locals_addr, _)) => {
debug_assert!(place.layout.is_sized()); // only sized locals can ever be `Place::Local`.
debug_assert_eq!(locals_addr, self.frame().locals_addr());
let base = self.local_to_op(local, None)?;
diff --git a/compiler/rustc_const_eval/src/interpret/place.rs b/compiler/rustc_const_eval/src/interpret/place.rs
index 840f798..3b14142 100644
--- a/compiler/rustc_const_eval/src/interpret/place.rs
+++ b/compiler/rustc_const_eval/src/interpret/place.rs
@@ -15,7 +15,7 @@
use super::{
alloc_range, mir_assign_valid_types, AllocRef, AllocRefMut, CheckAlignMsg, CtfeProvenance,
ImmTy, Immediate, InterpCx, InterpResult, Machine, MemoryKind, Misalignment, OffsetMode, OpTy,
- Operand, Pointer, Projectable, Provenance, Readable, Scalar,
+ Operand, Pointer, Projectable, Provenance, Scalar,
};
#[derive(Copy, Clone, Hash, PartialEq, Eq, Debug)]
@@ -180,7 +180,8 @@ pub(super) enum Place<Prov: Provenance = CtfeProvenance> {
Ptr(MemPlace<Prov>),
/// To support alloc-free locals, we are able to write directly to a local. The offset indicates
- /// where in the local this place is located; if it is `None`, no projection has been applied.
+ /// where in the local this place is located; if it is `None`, no projection has been applied
+ /// and the type of the place is exactly the type of the local.
/// Such projections are meaningful even if the offset is 0, since they can change layouts.
/// (Without that optimization, we'd just always be a `MemPlace`.)
/// `Local` places always refer to the current stack frame, so they are unstable under
@@ -231,10 +232,12 @@ pub(super) fn place(&self) -> &Place<Prov> {
#[inline(always)]
pub fn as_mplace_or_local(
&self,
- ) -> Either<MPlaceTy<'tcx, Prov>, (mir::Local, Option<Size>, usize)> {
+ ) -> Either<MPlaceTy<'tcx, Prov>, (mir::Local, Option<Size>, usize, TyAndLayout<'tcx>)> {
match self.place {
Place::Ptr(mplace) => Left(MPlaceTy { mplace, layout: self.layout }),
- Place::Local { local, offset, locals_addr } => Right((local, offset, locals_addr)),
+ Place::Local { local, offset, locals_addr } => {
+ Right((local, offset, locals_addr, self.layout))
+ }
}
}
@@ -277,7 +280,7 @@ fn offset_with_meta<M: Machine<'tcx, Provenance = Prov>>(
) -> InterpResult<'tcx, Self> {
Ok(match self.as_mplace_or_local() {
Left(mplace) => mplace.offset_with_meta(offset, mode, meta, layout, ecx)?.into(),
- Right((local, old_offset, locals_addr)) => {
+ Right((local, old_offset, locals_addr, _)) => {
debug_assert!(layout.is_sized(), "unsized locals should live in memory");
assert_matches!(meta, MemPlaceMeta::None); // we couldn't store it anyway...
// `Place::Local` are always in-bounds of their surrounding local, so we can just
@@ -328,9 +331,7 @@ pub fn assert_mem_place(&self) -> MPlaceTy<'tcx, Prov> {
/// The `Weiteable` trait describes interpreter values that can be written to.
pub trait Writeable<'tcx, Prov: Provenance>: Projectable<'tcx, Prov> {
- fn as_mplace_or_local(
- &self,
- ) -> Either<MPlaceTy<'tcx, Prov>, (mir::Local, Option<Size>, usize, TyAndLayout<'tcx>)>;
+ fn to_place(&self) -> PlaceTy<'tcx, Prov>;
fn force_mplace<M: Machine<'tcx, Provenance = Prov>>(
&self,
@@ -340,11 +341,8 @@ fn force_mplace<M: Machine<'tcx, Provenance = Prov>>(
impl<'tcx, Prov: Provenance> Writeable<'tcx, Prov> for PlaceTy<'tcx, Prov> {
#[inline(always)]
- fn as_mplace_or_local(
- &self,
- ) -> Either<MPlaceTy<'tcx, Prov>, (mir::Local, Option<Size>, usize, TyAndLayout<'tcx>)> {
- self.as_mplace_or_local()
- .map_right(|(local, offset, locals_addr)| (local, offset, locals_addr, self.layout))
+ fn to_place(&self) -> PlaceTy<'tcx, Prov> {
+ self.clone()
}
#[inline(always)]
@@ -358,10 +356,8 @@ fn force_mplace<M: Machine<'tcx, Provenance = Prov>>(
impl<'tcx, Prov: Provenance> Writeable<'tcx, Prov> for MPlaceTy<'tcx, Prov> {
#[inline(always)]
- fn as_mplace_or_local(
- &self,
- ) -> Either<MPlaceTy<'tcx, Prov>, (mir::Local, Option<Size>, usize, TyAndLayout<'tcx>)> {
- Left(self.clone())
+ fn to_place(&self) -> PlaceTy<'tcx, Prov> {
+ self.clone().into()
}
#[inline(always)]
@@ -436,7 +432,7 @@ pub fn mplace_to_ref(
#[instrument(skip(self), level = "trace")]
pub fn deref_pointer(
&self,
- src: &impl Readable<'tcx, M::Provenance>,
+ src: &impl Projectable<'tcx, M::Provenance>,
) -> InterpResult<'tcx, MPlaceTy<'tcx, M::Provenance>> {
if src.layout().ty.is_box() {
// Derefer should have removed all Box derefs.
@@ -562,6 +558,40 @@ pub fn eval_place(
Ok(place)
}
+ /// Given a place, returns either the underlying mplace or a reference to where the value of
+ /// this place is stored.
+ fn as_mplace_or_mutable_local(
+ &mut self,
+ place: &PlaceTy<'tcx, M::Provenance>,
+ ) -> InterpResult<
+ 'tcx,
+ Either<MPlaceTy<'tcx, M::Provenance>, (&mut Immediate<M::Provenance>, TyAndLayout<'tcx>)>,
+ > {
+ Ok(match place.to_place().as_mplace_or_local() {
+ Left(mplace) => Left(mplace),
+ Right((local, offset, locals_addr, layout)) => {
+ if offset.is_some() {
+ // This has been projected to a part of this local, or had the type changed.
+ // FIMXE: there are cases where we could still avoid allocating an mplace.
+ Left(place.force_mplace(self)?)
+ } else {
+ debug_assert_eq!(locals_addr, self.frame().locals_addr());
+ debug_assert_eq!(self.layout_of_local(self.frame(), local, None)?, layout);
+ match self.frame_mut().locals[local].access_mut()? {
+ Operand::Indirect(mplace) => {
+ // The local is in memory.
+ Left(MPlaceTy { mplace: *mplace, layout })
+ }
+ Operand::Immediate(local_val) => {
+ // The local still has the optimized representation.
+ Right((local_val, layout))
+ }
+ }
+ }
+ }
+ })
+ }
+
/// Write an immediate to a place
#[inline(always)]
#[instrument(skip(self), level = "trace")]
@@ -574,9 +604,11 @@ pub fn write_immediate(
if M::enforce_validity(self, dest.layout()) {
// Data got changed, better make sure it matches the type!
+ // Also needed to reset padding.
self.validate_operand(
- &dest.to_op(self)?,
+ &dest.to_place(),
M::enforce_validity_recursively(self, dest.layout()),
+ /*reset_provenance_and_padding*/ true,
)?;
}
@@ -606,67 +638,27 @@ pub fn write_pointer(
/// Write an immediate to a place.
/// If you use this you are responsible for validating that things got copied at the
/// right type.
- fn write_immediate_no_validate(
+ pub(super) fn write_immediate_no_validate(
&mut self,
src: Immediate<M::Provenance>,
dest: &impl Writeable<'tcx, M::Provenance>,
) -> InterpResult<'tcx> {
assert!(dest.layout().is_sized(), "Cannot write unsized immediate data");
- // See if we can avoid an allocation. This is the counterpart to `read_immediate_raw`,
- // but not factored as a separate function.
- let mplace = match dest.as_mplace_or_local() {
- Right((local, offset, locals_addr, layout)) => {
- if offset.is_some() {
- // This has been projected to a part of this local. We could have complicated
- // logic to still keep this local as an `Operand`... but it's much easier to
- // just fall back to the indirect path.
- dest.force_mplace(self)?
- } else {
- debug_assert_eq!(locals_addr, self.frame().locals_addr());
- match self.frame_mut().locals[local].access_mut()? {
- Operand::Immediate(local_val) => {
- // Local can be updated in-place.
- *local_val = src;
- // Double-check that the value we are storing and the local fit to each other.
- // (*After* doing the update for borrow checker reasons.)
- if cfg!(debug_assertions) {
- let local_layout =
- self.layout_of_local(&self.frame(), local, None)?;
- match (src, local_layout.abi) {
- (Immediate::Scalar(scalar), Abi::Scalar(s)) => {
- assert_eq!(scalar.size(), s.size(self))
- }
- (
- Immediate::ScalarPair(a_val, b_val),
- Abi::ScalarPair(a, b),
- ) => {
- assert_eq!(a_val.size(), a.size(self));
- assert_eq!(b_val.size(), b.size(self));
- }
- (Immediate::Uninit, _) => {}
- (src, abi) => {
- bug!(
- "value {src:?} cannot be written into local with type {} (ABI {abi:?})",
- local_layout.ty
- )
- }
- };
- }
- return Ok(());
- }
- Operand::Indirect(mplace) => {
- // The local is in memory, go on below.
- MPlaceTy { mplace: *mplace, layout }
- }
- }
+ match self.as_mplace_or_mutable_local(&dest.to_place())? {
+ Right((local_val, local_layout)) => {
+ // Local can be updated in-place.
+ *local_val = src;
+ // Double-check that the value we are storing and the local fit to each other.
+ if cfg!(debug_assertions) {
+ src.assert_matches_abi(local_layout.abi, self);
}
}
- Left(mplace) => mplace, // already referring to memory
- };
-
- // This is already in memory, write there.
- self.write_immediate_to_mplace_no_validate(src, mplace.layout, mplace.mplace)
+ Left(mplace) => {
+ self.write_immediate_to_mplace_no_validate(src, mplace.layout, mplace.mplace)?;
+ }
+ }
+ Ok(())
}
/// Write an immediate to memory.
@@ -678,6 +670,9 @@ fn write_immediate_to_mplace_no_validate(
layout: TyAndLayout<'tcx>,
dest: MemPlace<M::Provenance>,
) -> InterpResult<'tcx> {
+ if cfg!(debug_assertions) {
+ value.assert_matches_abi(layout.abi, self);
+ }
// Note that it is really important that the type here is the right one, and matches the
// type things are read at. In case `value` is a `ScalarPair`, we don't do any magic here
// to handle padding properly, which is only correct if we never look at this data with the
@@ -691,15 +686,7 @@ fn write_immediate_to_mplace_no_validate(
match value {
Immediate::Scalar(scalar) => {
- let Abi::Scalar(s) = layout.abi else {
- span_bug!(
- self.cur_span(),
- "write_immediate_to_mplace: invalid Scalar layout: {layout:#?}",
- )
- };
- let size = s.size(&tcx);
- assert_eq!(size, layout.size, "abi::Scalar size does not match layout size");
- alloc.write_scalar(alloc_range(Size::ZERO, size), scalar)
+ alloc.write_scalar(alloc_range(Size::ZERO, scalar.size()), scalar)
}
Immediate::ScalarPair(a_val, b_val) => {
let Abi::ScalarPair(a, b) = layout.abi else {
@@ -709,18 +696,19 @@ fn write_immediate_to_mplace_no_validate(
layout
)
};
- let (a_size, b_size) = (a.size(&tcx), b.size(&tcx));
- let b_offset = a_size.align_to(b.align(&tcx).abi);
+ let b_offset = a.size(&tcx).align_to(b.align(&tcx).abi);
assert!(b_offset.bytes() > 0); // in `operand_field` we use the offset to tell apart the fields
// It is tempting to verify `b_offset` against `layout.fields.offset(1)`,
// but that does not work: We could be a newtype around a pair, then the
// fields do not match the `ScalarPair` components.
- alloc.write_scalar(alloc_range(Size::ZERO, a_size), a_val)?;
- alloc.write_scalar(alloc_range(b_offset, b_size), b_val)
+ alloc.write_scalar(alloc_range(Size::ZERO, a_val.size()), a_val)?;
+ alloc.write_scalar(alloc_range(b_offset, b_val.size()), b_val)?;
+ // We don't have to reset padding here, `write_immediate` will anyway do a validation run.
+ Ok(())
}
- Immediate::Uninit => alloc.write_uninit(),
+ Immediate::Uninit => alloc.write_uninit_full(),
}
}
@@ -728,35 +716,38 @@ pub fn write_uninit(
&mut self,
dest: &impl Writeable<'tcx, M::Provenance>,
) -> InterpResult<'tcx> {
- let mplace = match dest.as_mplace_or_local() {
- Left(mplace) => mplace,
- Right((local, offset, locals_addr, layout)) => {
- if offset.is_some() {
- // This has been projected to a part of this local. We could have complicated
- // logic to still keep this local as an `Operand`... but it's much easier to
- // just fall back to the indirect path.
- // FIXME: share the logic with `write_immediate_no_validate`.
- dest.force_mplace(self)?
- } else {
- debug_assert_eq!(locals_addr, self.frame().locals_addr());
- match self.frame_mut().locals[local].access_mut()? {
- Operand::Immediate(local) => {
- *local = Immediate::Uninit;
- return Ok(());
- }
- Operand::Indirect(mplace) => {
- // The local is in memory, go on below.
- MPlaceTy { mplace: *mplace, layout }
- }
- }
- }
+ match self.as_mplace_or_mutable_local(&dest.to_place())? {
+ Right((local_val, _local_layout)) => {
+ *local_val = Immediate::Uninit;
}
- };
- let Some(mut alloc) = self.get_place_alloc_mut(&mplace)? else {
- // Zero-sized access
- return Ok(());
- };
- alloc.write_uninit()?;
+ Left(mplace) => {
+ let Some(mut alloc) = self.get_place_alloc_mut(&mplace)? else {
+ // Zero-sized access
+ return Ok(());
+ };
+ alloc.write_uninit_full()?;
+ }
+ }
+ Ok(())
+ }
+
+ /// Remove all provenance in the given place.
+ pub fn clear_provenance(
+ &mut self,
+ dest: &impl Writeable<'tcx, M::Provenance>,
+ ) -> InterpResult<'tcx> {
+ match self.as_mplace_or_mutable_local(&dest.to_place())? {
+ Right((local_val, _local_layout)) => {
+ local_val.clear_provenance()?;
+ }
+ Left(mplace) => {
+ let Some(mut alloc) = self.get_place_alloc_mut(&mplace)? else {
+ // Zero-sized access
+ return Ok(());
+ };
+ alloc.clear_provenance()?;
+ }
+ }
Ok(())
}
@@ -768,7 +759,7 @@ pub fn write_uninit(
#[inline(always)]
pub(super) fn copy_op_no_dest_validation(
&mut self,
- src: &impl Readable<'tcx, M::Provenance>,
+ src: &impl Projectable<'tcx, M::Provenance>,
dest: &impl Writeable<'tcx, M::Provenance>,
) -> InterpResult<'tcx> {
self.copy_op_inner(
@@ -781,7 +772,7 @@ pub(super) fn copy_op_no_dest_validation(
#[inline(always)]
pub fn copy_op_allow_transmute(
&mut self,
- src: &impl Readable<'tcx, M::Provenance>,
+ src: &impl Projectable<'tcx, M::Provenance>,
dest: &impl Writeable<'tcx, M::Provenance>,
) -> InterpResult<'tcx> {
self.copy_op_inner(
@@ -794,7 +785,7 @@ pub fn copy_op_allow_transmute(
#[inline(always)]
pub fn copy_op(
&mut self,
- src: &impl Readable<'tcx, M::Provenance>,
+ src: &impl Projectable<'tcx, M::Provenance>,
dest: &impl Writeable<'tcx, M::Provenance>,
) -> InterpResult<'tcx> {
self.copy_op_inner(
@@ -808,28 +799,35 @@ pub fn copy_op(
#[instrument(skip(self), level = "trace")]
fn copy_op_inner(
&mut self,
- src: &impl Readable<'tcx, M::Provenance>,
+ src: &impl Projectable<'tcx, M::Provenance>,
dest: &impl Writeable<'tcx, M::Provenance>,
allow_transmute: bool,
validate_dest: bool,
) -> InterpResult<'tcx> {
- // Generally for transmutation, data must be valid both at the old and new type.
- // But if the types are the same, the 2nd validation below suffices.
- if src.layout().ty != dest.layout().ty && M::enforce_validity(self, src.layout()) {
- self.validate_operand(
- &src.to_op(self)?,
- M::enforce_validity_recursively(self, src.layout()),
- )?;
- }
+ // These are technically *two* typed copies: `src` is a not-yet-loaded value,
+ // so we're going a typed copy at `src` type from there to some intermediate storage.
+ // And then we're doing a second typed copy from that intermediate storage to `dest`.
+ // But as an optimization, we only make a single direct copy here.
// Do the actual copy.
self.copy_op_no_validate(src, dest, allow_transmute)?;
if validate_dest && M::enforce_validity(self, dest.layout()) {
- // Data got changed, better make sure it matches the type!
+ let dest = dest.to_place();
+ // Given that there were two typed copies, we have to ensure this is valid at both types,
+ // and we have to ensure this loses provenance and padding according to both types.
+ // But if the types are identical, we only do one pass.
+ if allow_transmute && src.layout().ty != dest.layout().ty {
+ self.validate_operand(
+ &dest.transmute(src.layout(), self)?,
+ M::enforce_validity_recursively(self, src.layout()),
+ /*reset_provenance_and_padding*/ true,
+ )?;
+ }
self.validate_operand(
- &dest.to_op(self)?,
+ &dest,
M::enforce_validity_recursively(self, dest.layout()),
+ /*reset_provenance_and_padding*/ true,
)?;
}
@@ -843,7 +841,7 @@ fn copy_op_inner(
#[instrument(skip(self), level = "trace")]
fn copy_op_no_validate(
&mut self,
- src: &impl Readable<'tcx, M::Provenance>,
+ src: &impl Projectable<'tcx, M::Provenance>,
dest: &impl Writeable<'tcx, M::Provenance>,
allow_transmute: bool,
) -> InterpResult<'tcx> {
diff --git a/compiler/rustc_const_eval/src/interpret/validity.rs b/compiler/rustc_const_eval/src/interpret/validity.rs
index 26b7251..fb24f98 100644
--- a/compiler/rustc_const_eval/src/interpret/validity.rs
+++ b/compiler/rustc_const_eval/src/interpret/validity.rs
@@ -4,6 +4,7 @@
//! That's useful because it means other passes (e.g. promotion) can rely on `const`s
//! to be const-safe.
+use std::borrow::Cow;
use std::fmt::Write;
use std::hash::Hash;
use std::num::NonZero;
@@ -16,22 +17,22 @@
use rustc_middle::bug;
use rustc_middle::mir::interpret::ValidationErrorKind::{self, *};
use rustc_middle::mir::interpret::{
- ExpectedKind, InterpError, InvalidMetaKind, Misalignment, PointerKind, Provenance,
+ alloc_range, ExpectedKind, InterpError, InvalidMetaKind, Misalignment, PointerKind, Provenance,
UnsupportedOpInfo, ValidationErrorInfo,
};
-use rustc_middle::ty::layout::{LayoutOf, TyAndLayout};
-use rustc_middle::ty::{self, Ty};
+use rustc_middle::ty::layout::{LayoutCx, LayoutOf, TyAndLayout};
+use rustc_middle::ty::{self, Ty, TyCtxt};
use rustc_span::symbol::{sym, Symbol};
use rustc_target::abi::{
- Abi, FieldIdx, Scalar as ScalarAbi, Size, VariantIdx, Variants, WrappingRange,
+ Abi, FieldIdx, FieldsShape, Scalar as ScalarAbi, Size, VariantIdx, Variants, WrappingRange,
};
use tracing::trace;
use super::machine::AllocMap;
use super::{
err_ub, format_interp_error, throw_ub, AllocId, AllocKind, CheckInAllocMsg, GlobalAlloc, ImmTy,
- Immediate, InterpCx, InterpResult, MPlaceTy, Machine, MemPlaceMeta, OpTy, Pointer, Projectable,
- Scalar, ValueVisitor,
+ Immediate, InterpCx, InterpResult, MPlaceTy, Machine, MemPlaceMeta, PlaceTy, Pointer,
+ Projectable, Scalar, ValueVisitor,
};
// for the validation errors
@@ -125,6 +126,7 @@ pub enum PathElem {
EnumTag,
CoroutineTag,
DynDowncast,
+ Vtable,
}
/// Extra things to check for during validation of CTFE results.
@@ -163,22 +165,22 @@ impl<T: Clone + Eq + Hash + std::fmt::Debug, PATH: Default> RefTracking<T, PATH>
pub fn empty() -> Self {
RefTracking { seen: FxHashSet::default(), todo: vec![] }
}
- pub fn new(op: T) -> Self {
+ pub fn new(val: T) -> Self {
let mut ref_tracking_for_consts =
- RefTracking { seen: FxHashSet::default(), todo: vec![(op.clone(), PATH::default())] };
- ref_tracking_for_consts.seen.insert(op);
+ RefTracking { seen: FxHashSet::default(), todo: vec![(val.clone(), PATH::default())] };
+ ref_tracking_for_consts.seen.insert(val);
ref_tracking_for_consts
}
pub fn next(&mut self) -> Option<(T, PATH)> {
self.todo.pop()
}
- fn track(&mut self, op: T, path: impl FnOnce() -> PATH) {
- if self.seen.insert(op.clone()) {
- trace!("Recursing below ptr {:#?}", op);
+ fn track(&mut self, val: T, path: impl FnOnce() -> PATH) {
+ if self.seen.insert(val.clone()) {
+ trace!("Recursing below ptr {:#?}", val);
let path = path();
// Remember to come back to this later.
- self.todo.push((op, path));
+ self.todo.push((val, path));
}
}
}
@@ -204,11 +206,62 @@ fn write_path(out: &mut String, path: &[PathElem]) {
// not the root.
Deref => write!(out, ".<deref>"),
DynDowncast => write!(out, ".<dyn-downcast>"),
+ Vtable => write!(out, ".<vtable>"),
}
.unwrap()
}
}
+/// Represents a set of `Size` values as a sorted list of ranges.
+// These are (offset, length) pairs, and they are sorted and mutually disjoint,
+// and never adjacent (i.e. there's always a gap between two of them).
+#[derive(Debug, Clone)]
+pub struct RangeSet(Vec<(Size, Size)>);
+
+impl RangeSet {
+ fn add_range(&mut self, offset: Size, size: Size) {
+ if size.bytes() == 0 {
+ // No need to track empty ranges.
+ return;
+ }
+ let v = &mut self.0;
+ // We scan for a partition point where the left partition is all the elements that end
+ // strictly before we start. Those are elements that are too "low" to merge with us.
+ let idx =
+ v.partition_point(|&(other_offset, other_size)| other_offset + other_size < offset);
+ // Now we want to either merge with the first element of the second partition, or insert ourselves before that.
+ if let Some(&(other_offset, other_size)) = v.get(idx)
+ && offset + size >= other_offset
+ {
+ // Their end is >= our start (otherwise it would not be in the 2nd partition) and
+ // our end is >= their start. This means we can merge the ranges.
+ let new_start = other_offset.min(offset);
+ let mut new_end = (other_offset + other_size).max(offset + size);
+ // We grew to the right, so merge with overlapping/adjacent elements.
+ // (We also may have grown to the left, but that can never make us adjacent with
+ // anything there since we selected the first such candidate via `partition_point`.)
+ let mut scan_right = 1;
+ while let Some(&(next_offset, next_size)) = v.get(idx + scan_right)
+ && new_end >= next_offset
+ {
+ // Increase our size to absorb the next element.
+ new_end = new_end.max(next_offset + next_size);
+ // Look at the next element.
+ scan_right += 1;
+ }
+ // Update the element we grew.
+ v[idx] = (new_start, new_end - new_start);
+ // Remove the elements we absorbed (if any).
+ if scan_right > 1 {
+ drop(v.drain((idx + 1)..(idx + scan_right)));
+ }
+ } else {
+ // Insert new element.
+ v.insert(idx, (offset, size));
+ }
+ }
+}
+
struct ValidityVisitor<'rt, 'tcx, M: Machine<'tcx>> {
/// The `path` may be pushed to, but the part that is present when a function
/// starts must not be changed! `visit_fields` and `visit_array` rely on
@@ -217,7 +270,17 @@ struct ValidityVisitor<'rt, 'tcx, M: Machine<'tcx>> {
ref_tracking: Option<&'rt mut RefTracking<MPlaceTy<'tcx, M::Provenance>, Vec<PathElem>>>,
/// `None` indicates this is not validating for CTFE (but for runtime).
ctfe_mode: Option<CtfeValidationMode>,
- ecx: &'rt InterpCx<'tcx, M>,
+ ecx: &'rt mut InterpCx<'tcx, M>,
+ /// Whether provenance should be reset outside of pointers (emulating the effect of a typed
+ /// copy).
+ reset_provenance_and_padding: bool,
+ /// This tracks which byte ranges in this value contain data; the remaining bytes are padding.
+ /// The ideal representation here would be pointer-length pairs, but to keep things more compact
+ /// we only store a (range) set of offsets -- the base pointer is the same throughout the entire
+ /// visit, after all.
+ /// If this is `Some`, then `reset_provenance_and_padding` must be true (but not vice versa:
+ /// we might not track data vs padding bytes if the operand isn't stored in memory anyway).
+ data_bytes: Option<RangeSet>,
}
impl<'rt, 'tcx, M: Machine<'tcx>> ValidityVisitor<'rt, 'tcx, M> {
@@ -287,8 +350,14 @@ fn aggregate_field_path_elem(&mut self, layout: TyAndLayout<'tcx>, field: usize)
// arrays/slices
ty::Array(..) | ty::Slice(..) => PathElem::ArrayElem(field),
+ // dyn* vtables
+ ty::Dynamic(_, _, ty::DynKind::DynStar) if field == 1 => PathElem::Vtable,
+
// dyn traits
- ty::Dynamic(..) => PathElem::DynDowncast,
+ ty::Dynamic(..) => {
+ assert_eq!(field, 0);
+ PathElem::DynDowncast
+ }
// nothing else has an aggregate layout
_ => bug!("aggregate_field_path_elem: got non-aggregate type {:?}", layout.ty),
@@ -314,11 +383,11 @@ fn with_elem<R>(
fn read_immediate(
&self,
- op: &OpTy<'tcx, M::Provenance>,
+ val: &PlaceTy<'tcx, M::Provenance>,
expected: ExpectedKind,
) -> InterpResult<'tcx, ImmTy<'tcx, M::Provenance>> {
Ok(try_validation!(
- self.ecx.read_immediate(op),
+ self.ecx.read_immediate(val),
self.path,
Ub(InvalidUninitBytes(None)) =>
Uninit { expected },
@@ -332,10 +401,40 @@ fn read_immediate(
fn read_scalar(
&self,
- op: &OpTy<'tcx, M::Provenance>,
+ val: &PlaceTy<'tcx, M::Provenance>,
expected: ExpectedKind,
) -> InterpResult<'tcx, Scalar<M::Provenance>> {
- Ok(self.read_immediate(op, expected)?.to_scalar())
+ Ok(self.read_immediate(val, expected)?.to_scalar())
+ }
+
+ fn deref_pointer(
+ &mut self,
+ val: &PlaceTy<'tcx, M::Provenance>,
+ expected: ExpectedKind,
+ ) -> InterpResult<'tcx, MPlaceTy<'tcx, M::Provenance>> {
+ // Not using `ecx.deref_pointer` since we want to use our `read_immediate` wrapper.
+ let imm = self.read_immediate(val, expected)?;
+ // Reset provenance: ensure slice tail metadata does not preserve provenance,
+ // and ensure all pointers do not preserve partial provenance.
+ if self.reset_provenance_and_padding {
+ if matches!(imm.layout.abi, Abi::Scalar(..)) {
+ // A thin pointer. If it has provenance, we don't have to do anything.
+ // If it does not, ensure we clear the provenance in memory.
+ if matches!(imm.to_scalar(), Scalar::Int(..)) {
+ self.ecx.clear_provenance(val)?;
+ }
+ } else {
+ // A wide pointer. This means we have to worry both about the pointer itself and the
+ // metadata. We do the lazy thing and just write back the value we got. Just
+ // clearing provenance in a targeted manner would be more efficient, but unless this
+ // is a perf hotspot it's just not worth the effort.
+ self.ecx.write_immediate_no_validate(*imm, val)?;
+ }
+ // The entire thing is data, not padding.
+ self.add_data_range_place(val);
+ }
+ // Now turn it into a place.
+ self.ecx.ref_to_mplace(&imm)
}
fn check_wide_ptr_meta(
@@ -376,11 +475,10 @@ fn check_wide_ptr_meta(
/// Check a reference or `Box`.
fn check_safe_pointer(
&mut self,
- value: &OpTy<'tcx, M::Provenance>,
+ value: &PlaceTy<'tcx, M::Provenance>,
ptr_kind: PointerKind,
) -> InterpResult<'tcx> {
- // Not using `deref_pointer` since we want to use our `read_immediate` wrapper.
- let place = self.ecx.ref_to_mplace(&self.read_immediate(value, ptr_kind.into())?)?;
+ let place = self.deref_pointer(value, ptr_kind.into())?;
// Handle wide pointers.
// Check metadata early, for better diagnostics
if place.layout.is_unsized() {
@@ -564,31 +662,39 @@ fn check_safe_pointer(
/// Note that not all of these have `FieldsShape::Primitive`, e.g. wide references.
fn try_visit_primitive(
&mut self,
- value: &OpTy<'tcx, M::Provenance>,
+ value: &PlaceTy<'tcx, M::Provenance>,
) -> InterpResult<'tcx, bool> {
// Go over all the primitive types
let ty = value.layout.ty;
match ty.kind() {
ty::Bool => {
- let value = self.read_scalar(value, ExpectedKind::Bool)?;
+ let scalar = self.read_scalar(value, ExpectedKind::Bool)?;
try_validation!(
- value.to_bool(),
+ scalar.to_bool(),
self.path,
Ub(InvalidBool(..)) => ValidationErrorKind::InvalidBool {
- value: format!("{value:x}"),
+ value: format!("{scalar:x}"),
}
);
+ if self.reset_provenance_and_padding {
+ self.ecx.clear_provenance(value)?;
+ self.add_data_range_place(value);
+ }
Ok(true)
}
ty::Char => {
- let value = self.read_scalar(value, ExpectedKind::Char)?;
+ let scalar = self.read_scalar(value, ExpectedKind::Char)?;
try_validation!(
- value.to_char(),
+ scalar.to_char(),
self.path,
Ub(InvalidChar(..)) => ValidationErrorKind::InvalidChar {
- value: format!("{value:x}"),
+ value: format!("{scalar:x}"),
}
);
+ if self.reset_provenance_and_padding {
+ self.ecx.clear_provenance(value)?;
+ self.add_data_range_place(value);
+ }
Ok(true)
}
ty::Float(_) | ty::Int(_) | ty::Uint(_) => {
@@ -602,11 +708,14 @@ fn try_visit_primitive(
ExpectedKind::Int
},
)?;
+ if self.reset_provenance_and_padding {
+ self.ecx.clear_provenance(value)?;
+ self.add_data_range_place(value);
+ }
Ok(true)
}
ty::RawPtr(..) => {
- let place =
- self.ecx.ref_to_mplace(&self.read_immediate(value, ExpectedKind::RawPtr)?)?;
+ let place = self.deref_pointer(value, ExpectedKind::RawPtr)?;
if place.layout.is_unsized() {
self.check_wide_ptr_meta(place.meta(), place.layout)?;
}
@@ -617,11 +726,11 @@ fn try_visit_primitive(
Ok(true)
}
ty::FnPtr(..) => {
- let value = self.read_scalar(value, ExpectedKind::FnPtr)?;
+ let scalar = self.read_scalar(value, ExpectedKind::FnPtr)?;
// If we check references recursively, also check that this points to a function.
if let Some(_) = self.ref_tracking {
- let ptr = value.to_pointer(self.ecx)?;
+ let ptr = scalar.to_pointer(self.ecx)?;
let _fn = try_validation!(
self.ecx.get_ptr_fn(ptr),
self.path,
@@ -631,10 +740,18 @@ fn try_visit_primitive(
// FIXME: Check if the signature matches
} else {
// Otherwise (for standalone Miri), we have to still check it to be non-null.
- if self.ecx.scalar_may_be_null(value)? {
+ if self.ecx.scalar_may_be_null(scalar)? {
throw_validation_failure!(self.path, NullFnPtr);
}
}
+ if self.reset_provenance_and_padding {
+ // Make sure we do not preserve partial provenance. This matches the thin
+ // pointer handling in `deref_pointer`.
+ if matches!(scalar, Scalar::Int(..)) {
+ self.ecx.clear_provenance(value)?;
+ }
+ self.add_data_range_place(value);
+ }
Ok(true)
}
ty::Never => throw_validation_failure!(self.path, NeverVal),
@@ -716,13 +833,178 @@ fn visit_scalar(
}
}
- fn in_mutable_memory(&self, op: &OpTy<'tcx, M::Provenance>) -> bool {
- if let Some(mplace) = op.as_mplace_or_imm().left() {
+ fn in_mutable_memory(&self, val: &PlaceTy<'tcx, M::Provenance>) -> bool {
+ if let Some(mplace) = val.as_mplace_or_local().left() {
if let Some(alloc_id) = mplace.ptr().provenance.and_then(|p| p.get_alloc_id()) {
- return mutability(self.ecx, alloc_id).is_mut();
+ mutability(self.ecx, alloc_id).is_mut()
+ } else {
+ // No memory at all.
+ false
+ }
+ } else {
+ // A local variable -- definitely mutable.
+ true
+ }
+ }
+
+ /// Add the given pointer-length pair to the "data" range of this visit.
+ fn add_data_range(&mut self, ptr: Pointer<Option<M::Provenance>>, size: Size) {
+ if let Some(data_bytes) = self.data_bytes.as_mut() {
+ // We only have to store the offset, the rest is the same for all pointers here.
+ let (_prov, offset) = ptr.into_parts();
+ // Add this.
+ data_bytes.add_range(offset, size);
+ };
+ }
+
+ /// Add the entire given place to the "data" range of this visit.
+ fn add_data_range_place(&mut self, place: &PlaceTy<'tcx, M::Provenance>) {
+ // Only sized places can be added this way.
+ debug_assert!(place.layout.abi.is_sized());
+ if let Some(data_bytes) = self.data_bytes.as_mut() {
+ let offset = Self::data_range_offset(self.ecx, place);
+ data_bytes.add_range(offset, place.layout.size);
+ }
+ }
+
+ /// Convert a place into the offset it starts at, for the purpose of data_range tracking.
+ /// Must only be called if `data_bytes` is `Some(_)`.
+ fn data_range_offset(ecx: &InterpCx<'tcx, M>, place: &PlaceTy<'tcx, M::Provenance>) -> Size {
+ // The presence of `data_bytes` implies that our place is in memory.
+ let ptr = ecx
+ .place_to_op(place)
+ .expect("place must be in memory")
+ .as_mplace_or_imm()
+ .expect_left("place must be in memory")
+ .ptr();
+ let (_prov, offset) = ptr.into_parts();
+ offset
+ }
+
+ fn reset_padding(&mut self, place: &PlaceTy<'tcx, M::Provenance>) -> InterpResult<'tcx> {
+ let Some(data_bytes) = self.data_bytes.as_mut() else { return Ok(()) };
+ // Our value must be in memory, otherwise we would not have set up `data_bytes`.
+ let mplace = self.ecx.force_allocation(place)?;
+ // Determine starting offset and size.
+ let (_prov, start_offset) = mplace.ptr().into_parts();
+ let (size, _align) = self
+ .ecx
+ .size_and_align_of_mplace(&mplace)?
+ .unwrap_or((mplace.layout.size, mplace.layout.align.abi));
+ // If there is no padding at all, we can skip the rest: check for
+ // a single data range covering the entire value.
+ if data_bytes.0 == &[(start_offset, size)] {
+ return Ok(());
+ }
+ // Get a handle for the allocation. Do this only once, to avoid looking up the same
+ // allocation over and over again. (Though to be fair, iterating the value already does
+ // exactly that.)
+ let Some(mut alloc) = self.ecx.get_ptr_alloc_mut(mplace.ptr(), size)? else {
+ // A ZST, no padding to clear.
+ return Ok(());
+ };
+ // Add a "finalizer" data range at the end, so that the iteration below finds all gaps
+ // between ranges.
+ data_bytes.0.push((start_offset + size, Size::ZERO));
+ // Iterate, and reset gaps.
+ let mut padding_cleared_until = start_offset;
+ for &(offset, size) in data_bytes.0.iter() {
+ assert!(
+ offset >= padding_cleared_until,
+ "reset_padding on {}: previous field ended at offset {}, next field starts at {} (and has a size of {} bytes)",
+ mplace.layout.ty,
+ (padding_cleared_until - start_offset).bytes(),
+ (offset - start_offset).bytes(),
+ size.bytes(),
+ );
+ if offset > padding_cleared_until {
+ // We found padding. Adjust the range to be relative to `alloc`, and make it uninit.
+ let padding_start = padding_cleared_until - start_offset;
+ let padding_size = offset - padding_cleared_until;
+ let range = alloc_range(padding_start, padding_size);
+ trace!("reset_padding on {}: resetting padding range {range:?}", mplace.layout.ty);
+ alloc.write_uninit(range)?;
+ }
+ padding_cleared_until = offset + size;
+ }
+ assert!(padding_cleared_until == start_offset + size);
+ Ok(())
+ }
+
+ /// Computes the data range of this union type:
+ /// which bytes are inside a field (i.e., not padding.)
+ fn union_data_range<'e>(
+ ecx: &'e mut InterpCx<'tcx, M>,
+ layout: TyAndLayout<'tcx>,
+ ) -> Cow<'e, RangeSet> {
+ assert!(layout.ty.is_union());
+ assert!(layout.abi.is_sized(), "there are no unsized unions");
+ let layout_cx = LayoutCx { tcx: *ecx.tcx, param_env: ecx.param_env };
+ return M::cached_union_data_range(ecx, layout.ty, || {
+ let mut out = RangeSet(Vec::new());
+ union_data_range_uncached(&layout_cx, layout, Size::ZERO, &mut out);
+ out
+ });
+
+ /// Helper for recursive traversal: add data ranges of the given type to `out`.
+ fn union_data_range_uncached<'tcx>(
+ cx: &LayoutCx<'tcx, TyCtxt<'tcx>>,
+ layout: TyAndLayout<'tcx>,
+ base_offset: Size,
+ out: &mut RangeSet,
+ ) {
+ // If this is a ZST, we don't contain any data. In particular, this helps us to quickly
+ // skip over huge arrays of ZST.
+ if layout.is_zst() {
+ return;
+ }
+ // Just recursively add all the fields of everything to the output.
+ match &layout.fields {
+ FieldsShape::Primitive => {
+ out.add_range(base_offset, layout.size);
+ }
+ &FieldsShape::Union(fields) => {
+ // Currently, all fields start at offset 0 (relative to `base_offset`).
+ for field in 0..fields.get() {
+ let field = layout.field(cx, field);
+ union_data_range_uncached(cx, field, base_offset, out);
+ }
+ }
+ &FieldsShape::Array { stride, count } => {
+ let elem = layout.field(cx, 0);
+
+ // Fast-path for large arrays of simple types that do not contain any padding.
+ if elem.abi.is_scalar() {
+ out.add_range(base_offset, elem.size * count);
+ } else {
+ for idx in 0..count {
+ // This repeats the same computation for every array element... but the alternative
+ // is to allocate temporary storage for a dedicated `out` set for the array element,
+ // and replicating that N times. Is that better?
+ union_data_range_uncached(cx, elem, base_offset + idx * stride, out);
+ }
+ }
+ }
+ FieldsShape::Arbitrary { offsets, .. } => {
+ for (field, &offset) in offsets.iter_enumerated() {
+ let field = layout.field(cx, field.as_usize());
+ union_data_range_uncached(cx, field, base_offset + offset, out);
+ }
+ }
+ }
+ // Don't forget potential other variants.
+ match &layout.variants {
+ Variants::Single { .. } => {
+ // Fully handled above.
+ }
+ Variants::Multiple { variants, .. } => {
+ for variant in variants.indices() {
+ let variant = layout.for_variant(cx, variant);
+ union_data_range_uncached(cx, variant, base_offset, out);
+ }
+ }
}
}
- false
}
}
@@ -774,7 +1056,7 @@ fn mutability<'tcx>(ecx: &InterpCx<'tcx, impl Machine<'tcx>>, alloc_id: AllocId)
}
impl<'rt, 'tcx, M: Machine<'tcx>> ValueVisitor<'tcx, M> for ValidityVisitor<'rt, 'tcx, M> {
- type V = OpTy<'tcx, M::Provenance>;
+ type V = PlaceTy<'tcx, M::Provenance>;
#[inline(always)]
fn ecx(&self) -> &InterpCx<'tcx, M> {
@@ -783,11 +1065,11 @@ fn ecx(&self) -> &InterpCx<'tcx, M> {
fn read_discriminant(
&mut self,
- op: &OpTy<'tcx, M::Provenance>,
+ val: &PlaceTy<'tcx, M::Provenance>,
) -> InterpResult<'tcx, VariantIdx> {
self.with_elem(PathElem::EnumTag, move |this| {
Ok(try_validation!(
- this.ecx.read_discriminant(op),
+ this.ecx.read_discriminant(val),
this.path,
Ub(InvalidTag(val)) => InvalidEnumTag {
value: format!("{val:x}"),
@@ -802,44 +1084,54 @@ fn read_discriminant(
#[inline]
fn visit_field(
&mut self,
- old_op: &OpTy<'tcx, M::Provenance>,
+ old_val: &PlaceTy<'tcx, M::Provenance>,
field: usize,
- new_op: &OpTy<'tcx, M::Provenance>,
+ new_val: &PlaceTy<'tcx, M::Provenance>,
) -> InterpResult<'tcx> {
- let elem = self.aggregate_field_path_elem(old_op.layout, field);
- self.with_elem(elem, move |this| this.visit_value(new_op))
+ let elem = self.aggregate_field_path_elem(old_val.layout, field);
+ self.with_elem(elem, move |this| this.visit_value(new_val))
}
#[inline]
fn visit_variant(
&mut self,
- old_op: &OpTy<'tcx, M::Provenance>,
+ old_val: &PlaceTy<'tcx, M::Provenance>,
variant_id: VariantIdx,
- new_op: &OpTy<'tcx, M::Provenance>,
+ new_val: &PlaceTy<'tcx, M::Provenance>,
) -> InterpResult<'tcx> {
- let name = match old_op.layout.ty.kind() {
+ let name = match old_val.layout.ty.kind() {
ty::Adt(adt, _) => PathElem::Variant(adt.variant(variant_id).name),
// Coroutines also have variants
ty::Coroutine(..) => PathElem::CoroutineState(variant_id),
- _ => bug!("Unexpected type with variant: {:?}", old_op.layout.ty),
+ _ => bug!("Unexpected type with variant: {:?}", old_val.layout.ty),
};
- self.with_elem(name, move |this| this.visit_value(new_op))
+ self.with_elem(name, move |this| this.visit_value(new_val))
}
#[inline(always)]
fn visit_union(
&mut self,
- op: &OpTy<'tcx, M::Provenance>,
+ val: &PlaceTy<'tcx, M::Provenance>,
_fields: NonZero<usize>,
) -> InterpResult<'tcx> {
// Special check for CTFE validation, preventing `UnsafeCell` inside unions in immutable memory.
if self.ctfe_mode.is_some_and(|c| !c.allow_immutable_unsafe_cell()) {
- if !op.layout.is_zst() && !op.layout.ty.is_freeze(*self.ecx.tcx, self.ecx.param_env) {
- if !self.in_mutable_memory(op) {
+ if !val.layout.is_zst() && !val.layout.ty.is_freeze(*self.ecx.tcx, self.ecx.param_env) {
+ if !self.in_mutable_memory(val) {
throw_validation_failure!(self.path, UnsafeCellInImmutable);
}
}
}
+ if self.reset_provenance_and_padding
+ && let Some(data_bytes) = self.data_bytes.as_mut()
+ {
+ let base_offset = Self::data_range_offset(self.ecx, val);
+ // Determine and add data range for this union.
+ let union_data_range = Self::union_data_range(self.ecx, val.layout);
+ for &(offset, size) in union_data_range.0.iter() {
+ data_bytes.add_range(base_offset + offset, size);
+ }
+ }
Ok(())
}
@@ -847,39 +1139,41 @@ fn visit_union(
fn visit_box(
&mut self,
_box_ty: Ty<'tcx>,
- op: &OpTy<'tcx, M::Provenance>,
+ val: &PlaceTy<'tcx, M::Provenance>,
) -> InterpResult<'tcx> {
- self.check_safe_pointer(op, PointerKind::Box)?;
+ self.check_safe_pointer(val, PointerKind::Box)?;
Ok(())
}
#[inline]
- fn visit_value(&mut self, op: &OpTy<'tcx, M::Provenance>) -> InterpResult<'tcx> {
- trace!("visit_value: {:?}, {:?}", *op, op.layout);
+ fn visit_value(&mut self, val: &PlaceTy<'tcx, M::Provenance>) -> InterpResult<'tcx> {
+ trace!("visit_value: {:?}, {:?}", *val, val.layout);
// Check primitive types -- the leaves of our recursive descent.
+ // This is called even for enum discriminants (which are "fields" of their enum),
+ // so for integer-typed discriminants the provenance reset will happen here.
// We assume that the Scalar validity range does not restrict these values
// any further than `try_visit_primitive` does!
- if self.try_visit_primitive(op)? {
+ if self.try_visit_primitive(val)? {
return Ok(());
}
// Special check preventing `UnsafeCell` in the inner part of constants
if self.ctfe_mode.is_some_and(|c| !c.allow_immutable_unsafe_cell()) {
- if !op.layout.is_zst()
- && let Some(def) = op.layout.ty.ty_adt_def()
+ if !val.layout.is_zst()
+ && let Some(def) = val.layout.ty.ty_adt_def()
&& def.is_unsafe_cell()
{
- if !self.in_mutable_memory(op) {
+ if !self.in_mutable_memory(val) {
throw_validation_failure!(self.path, UnsafeCellInImmutable);
}
}
}
// Recursively walk the value at its type. Apply optimizations for some large types.
- match op.layout.ty.kind() {
+ match val.layout.ty.kind() {
ty::Str => {
- let mplace = op.assert_mem_place(); // strings are unsized and hence never immediate
+ let mplace = val.assert_mem_place(); // strings are unsized and hence never immediate
let len = mplace.len(self.ecx)?;
try_validation!(
self.ecx.read_bytes_ptr_strip_provenance(mplace.ptr(), Size::from_bytes(len)),
@@ -889,11 +1183,10 @@ fn visit_value(&mut self, op: &OpTy<'tcx, M::Provenance>) -> InterpResult<'tcx>
);
}
ty::Array(tys, ..) | ty::Slice(tys)
- // This optimization applies for types that can hold arbitrary bytes (such as
- // integer and floating point types) or for structs or tuples with no fields.
- // FIXME(wesleywiser) This logic could be extended further to arbitrary structs
- // or tuples made up of integer/floating point types or inhabited ZSTs with no
- // padding.
+ // This optimization applies for types that can hold arbitrary non-provenance bytes (such as
+ // integer and floating point types).
+ // FIXME(wesleywiser) This logic could be extended further to arbitrary structs or
+ // tuples made up of integer/floating point types or inhabited ZSTs with no padding.
if matches!(tys.kind(), ty::Int(..) | ty::Uint(..) | ty::Float(..))
=>
{
@@ -901,18 +1194,19 @@ fn visit_value(&mut self, op: &OpTy<'tcx, M::Provenance>) -> InterpResult<'tcx>
// Optimized handling for arrays of integer/float type.
// This is the length of the array/slice.
- let len = op.len(self.ecx)?;
+ let len = val.len(self.ecx)?;
// This is the element type size.
let layout = self.ecx.layout_of(*tys)?;
// This is the size in bytes of the whole array. (This checks for overflow.)
let size = layout.size * len;
// If the size is 0, there is nothing to check.
- // (`size` can only be 0 of `len` is 0, and empty arrays are always valid.)
+ // (`size` can only be 0 if `len` is 0, and empty arrays are always valid.)
if size == Size::ZERO {
return Ok(());
}
- // Now that we definitely have a non-ZST array, we know it lives in memory.
- let mplace = match op.as_mplace_or_imm() {
+ // Now that we definitely have a non-ZST array, we know it lives in memory -- except it may
+ // be an uninitialized local variable, those are also "immediate".
+ let mplace = match val.to_op(self.ecx)?.as_mplace_or_imm() {
Left(mplace) => mplace,
Right(imm) => match *imm {
Immediate::Uninit =>
@@ -958,20 +1252,30 @@ fn visit_value(&mut self, op: &OpTy<'tcx, M::Provenance>) -> InterpResult<'tcx>
}
}
}
+
+ // Don't forget that these are all non-pointer types, and thus do not preserve
+ // provenance.
+ if self.reset_provenance_and_padding {
+ // We can't share this with above as above, we might be looking at read-only memory.
+ let mut alloc = self.ecx.get_ptr_alloc_mut(mplace.ptr(), size)?.expect("we already excluded size 0");
+ alloc.clear_provenance()?;
+ // Also, mark this as containing data, not padding.
+ self.add_data_range(mplace.ptr(), size);
+ }
}
// Fast path for arrays and slices of ZSTs. We only need to check a single ZST element
// of an array and not all of them, because there's only a single value of a specific
// ZST type, so either validation fails for all elements or none.
ty::Array(tys, ..) | ty::Slice(tys) if self.ecx.layout_of(*tys)?.is_zst() => {
// Validate just the first element (if any).
- if op.len(self.ecx)? > 0 {
- self.visit_field(op, 0, &self.ecx.project_index(op, 0)?)?;
+ if val.len(self.ecx)? > 0 {
+ self.visit_field(val, 0, &self.ecx.project_index(val, 0)?)?;
}
}
_ => {
// default handler
try_validation!(
- self.walk_value(op),
+ self.walk_value(val),
self.path,
// It's not great to catch errors here, since we can't give a very good path,
// but it's better than ICEing.
@@ -992,15 +1296,15 @@ fn visit_value(&mut self, op: &OpTy<'tcx, M::Provenance>) -> InterpResult<'tcx>
// FIXME: We could avoid some redundant checks here. For newtypes wrapping
// scalars, we do the same check on every "level" (e.g., first we check
// MyNewtype and then the scalar in there).
- match op.layout.abi {
+ match val.layout.abi {
Abi::Uninhabited => {
- let ty = op.layout.ty;
+ let ty = val.layout.ty;
throw_validation_failure!(self.path, UninhabitedVal { ty });
}
Abi::Scalar(scalar_layout) => {
if !scalar_layout.is_uninit_valid() {
// There is something to check here.
- let scalar = self.read_scalar(op, ExpectedKind::InitScalar)?;
+ let scalar = self.read_scalar(val, ExpectedKind::InitScalar)?;
self.visit_scalar(scalar, scalar_layout)?;
}
}
@@ -1010,7 +1314,7 @@ fn visit_value(&mut self, op: &OpTy<'tcx, M::Provenance>) -> InterpResult<'tcx>
// the other must be init.
if !a_layout.is_uninit_valid() && !b_layout.is_uninit_valid() {
let (a, b) =
- self.read_immediate(op, ExpectedKind::InitScalar)?.to_scalar_pair();
+ self.read_immediate(val, ExpectedKind::InitScalar)?.to_scalar_pair();
self.visit_scalar(a, a_layout)?;
self.visit_scalar(b, b_layout)?;
}
@@ -1031,19 +1335,34 @@ fn visit_value(&mut self, op: &OpTy<'tcx, M::Provenance>) -> InterpResult<'tcx>
impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
fn validate_operand_internal(
- &self,
- op: &OpTy<'tcx, M::Provenance>,
+ &mut self,
+ val: &PlaceTy<'tcx, M::Provenance>,
path: Vec<PathElem>,
ref_tracking: Option<&mut RefTracking<MPlaceTy<'tcx, M::Provenance>, Vec<PathElem>>>,
ctfe_mode: Option<CtfeValidationMode>,
+ reset_provenance_and_padding: bool,
) -> InterpResult<'tcx> {
- trace!("validate_operand_internal: {:?}, {:?}", *op, op.layout.ty);
+ trace!("validate_operand_internal: {:?}, {:?}", *val, val.layout.ty);
- // Construct a visitor
- let mut visitor = ValidityVisitor { path, ref_tracking, ctfe_mode, ecx: self };
-
- // Run it.
- match self.run_for_validation(|| visitor.visit_value(op)) {
+ // Run the visitor.
+ match self.run_for_validation(|ecx| {
+ let reset_padding = reset_provenance_and_padding && {
+ // Check if `val` is actually stored in memory. If not, padding is not even
+ // represented and we need not reset it.
+ ecx.place_to_op(val)?.as_mplace_or_imm().is_left()
+ };
+ let mut v = ValidityVisitor {
+ path,
+ ref_tracking,
+ ctfe_mode,
+ ecx,
+ reset_provenance_and_padding,
+ data_bytes: reset_padding.then_some(RangeSet(Vec::new())),
+ };
+ v.visit_value(val)?;
+ v.reset_padding(val)?;
+ InterpResult::Ok(())
+ }) {
Ok(()) => Ok(()),
// Pass through validation failures and "invalid program" issues.
Err(err)
@@ -1079,13 +1398,19 @@ fn validate_operand_internal(
/// - no `UnsafeCell` or non-ZST `&mut`.
#[inline(always)]
pub(crate) fn const_validate_operand(
- &self,
- op: &OpTy<'tcx, M::Provenance>,
+ &mut self,
+ val: &PlaceTy<'tcx, M::Provenance>,
path: Vec<PathElem>,
ref_tracking: &mut RefTracking<MPlaceTy<'tcx, M::Provenance>, Vec<PathElem>>,
ctfe_mode: CtfeValidationMode,
) -> InterpResult<'tcx> {
- self.validate_operand_internal(op, path, Some(ref_tracking), Some(ctfe_mode))
+ self.validate_operand_internal(
+ val,
+ path,
+ Some(ref_tracking),
+ Some(ctfe_mode),
+ /*reset_provenance*/ false,
+ )
}
/// This function checks the data at `op` to be runtime-valid.
@@ -1093,21 +1418,41 @@ pub(crate) fn const_validate_operand(
/// It will error if the bits at the destination do not match the ones described by the layout.
#[inline(always)]
pub fn validate_operand(
- &self,
- op: &OpTy<'tcx, M::Provenance>,
+ &mut self,
+ val: &PlaceTy<'tcx, M::Provenance>,
recursive: bool,
+ reset_provenance_and_padding: bool,
) -> InterpResult<'tcx> {
// Note that we *could* actually be in CTFE here with `-Zextra-const-ub-checks`, but it's
// still correct to not use `ctfe_mode`: that mode is for validation of the final constant
// value, it rules out things like `UnsafeCell` in awkward places.
if !recursive {
- return self.validate_operand_internal(op, vec![], None, None);
+ return self.validate_operand_internal(
+ val,
+ vec![],
+ None,
+ None,
+ reset_provenance_and_padding,
+ );
}
// Do a recursive check.
let mut ref_tracking = RefTracking::empty();
- self.validate_operand_internal(op, vec![], Some(&mut ref_tracking), None)?;
+ self.validate_operand_internal(
+ val,
+ vec![],
+ Some(&mut ref_tracking),
+ None,
+ reset_provenance_and_padding,
+ )?;
while let Some((mplace, path)) = ref_tracking.todo.pop() {
- self.validate_operand_internal(&mplace.into(), path, Some(&mut ref_tracking), None)?;
+ // Things behind reference do *not* have the provenance reset.
+ self.validate_operand_internal(
+ &mplace.into(),
+ path,
+ Some(&mut ref_tracking),
+ None,
+ /*reset_provenance_and_padding*/ false,
+ )?;
}
Ok(())
}
diff --git a/compiler/rustc_const_eval/src/interpret/visitor.rs b/compiler/rustc_const_eval/src/interpret/visitor.rs
index b02f12e..d8af67b 100644
--- a/compiler/rustc_const_eval/src/interpret/visitor.rs
+++ b/compiler/rustc_const_eval/src/interpret/visitor.rs
@@ -5,6 +5,7 @@
use rustc_index::IndexVec;
use rustc_middle::mir::interpret::InterpResult;
+use rustc_middle::ty::layout::LayoutOf;
use rustc_middle::ty::{self, Ty};
use rustc_target::abi::{FieldIdx, FieldsShape, VariantIdx, Variants};
use tracing::trace;
@@ -82,6 +83,7 @@ fn visit_variant(
self.visit_value(new_val)
}
+ /// Traversal logic; should not be overloaded.
fn walk_value(&mut self, v: &Self::V) -> InterpResult<'tcx> {
let ty = v.layout().ty;
trace!("walk_value: type: {ty}");
@@ -104,6 +106,17 @@ fn walk_value(&mut self, v: &Self::V) -> InterpResult<'tcx> {
// DynStar types. Very different from a dyn type (but strangely part of the
// same variant in `TyKind`): These are pairs where the 2nd component is the
// vtable, and the first component is the data (which must be ptr-sized).
+
+ // First make sure the vtable can be read at its type.
+ // The type of this vtable is fake, it claims to be a reference to some actual memory but that isn't true.
+ // So we transmute it to a raw pointer.
+ let raw_ptr_ty = Ty::new_mut_ptr(*self.ecx().tcx, self.ecx().tcx.types.unit);
+ let raw_ptr_ty = self.ecx().layout_of(raw_ptr_ty)?;
+ let vtable_field =
+ self.ecx().project_field(v, 1)?.transmute(raw_ptr_ty, self.ecx())?;
+ self.visit_field(v, 1, &vtable_field)?;
+
+ // Then unpack the first field, and continue.
let data = self.ecx().unpack_dyn_star(v, data)?;
return self.visit_field(v, 0, &data);
}
diff --git a/compiler/rustc_const_eval/src/util/check_validity_requirement.rs b/compiler/rustc_const_eval/src/util/check_validity_requirement.rs
index cbd1fde..611a8e1 100644
--- a/compiler/rustc_const_eval/src/util/check_validity_requirement.rs
+++ b/compiler/rustc_const_eval/src/util/check_validity_requirement.rs
@@ -4,7 +4,7 @@
use rustc_target::abi::{Abi, FieldsShape, Scalar, Variants};
use crate::const_eval::{CanAccessMutGlobal, CheckAlignment, CompileTimeMachine};
-use crate::interpret::{InterpCx, MemoryKind, OpTy};
+use crate::interpret::{InterpCx, MemoryKind};
/// Determines if this type permits "raw" initialization by just transmuting some memory into an
/// instance of `T`.
@@ -32,15 +32,15 @@ pub fn check_validity_requirement<'tcx>(
let layout_cx = LayoutCx { tcx, param_env: param_env_and_ty.param_env };
if kind == ValidityRequirement::Uninit || tcx.sess.opts.unstable_opts.strict_init_checks {
- might_permit_raw_init_strict(layout, &layout_cx, kind)
+ check_validity_requirement_strict(layout, &layout_cx, kind)
} else {
- might_permit_raw_init_lax(layout, &layout_cx, kind)
+ check_validity_requirement_lax(layout, &layout_cx, kind)
}
}
-/// Implements the 'strict' version of the `might_permit_raw_init` checks; see that function for
-/// details.
-fn might_permit_raw_init_strict<'tcx>(
+/// Implements the 'strict' version of the [`check_validity_requirement`] checks; see that function
+/// for details.
+fn check_validity_requirement_strict<'tcx>(
ty: TyAndLayout<'tcx>,
cx: &LayoutCx<'tcx, TyCtxt<'tcx>>,
kind: ValidityRequirement,
@@ -61,18 +61,24 @@ fn might_permit_raw_init_strict<'tcx>(
.expect("failed to write bytes for zero valid check");
}
- let ot: OpTy<'_, _> = allocated.into();
-
// Assume that if it failed, it's a validation failure.
// This does *not* actually check that references are dereferenceable, but since all types that
// require dereferenceability also require non-null, we don't actually get any false negatives
// due to this.
- Ok(cx.validate_operand(&ot, /*recursive*/ false).is_ok())
+ // The value we are validating is temporary and discarded at the end of this function, so
+ // there is no point in reseting provenance and padding.
+ Ok(cx
+ .validate_operand(
+ &allocated.into(),
+ /*recursive*/ false,
+ /*reset_provenance_and_padding*/ false,
+ )
+ .is_ok())
}
-/// Implements the 'lax' (default) version of the `might_permit_raw_init` checks; see that function for
-/// details.
-fn might_permit_raw_init_lax<'tcx>(
+/// Implements the 'lax' (default) version of the [`check_validity_requirement`] checks; see that
+/// function for details.
+fn check_validity_requirement_lax<'tcx>(
this: TyAndLayout<'tcx>,
cx: &LayoutCx<'tcx, TyCtxt<'tcx>>,
init_kind: ValidityRequirement,
@@ -137,7 +143,7 @@ fn might_permit_raw_init_lax<'tcx>(
}
FieldsShape::Arbitrary { offsets, .. } => {
for idx in 0..offsets.len() {
- if !might_permit_raw_init_lax(this.field(cx, idx), cx, init_kind)? {
+ if !check_validity_requirement_lax(this.field(cx, idx), cx, init_kind)? {
// We found a field that is unhappy with this kind of initialization.
return Ok(false);
}
diff --git a/compiler/rustc_data_structures/src/steal.rs b/compiler/rustc_data_structures/src/steal.rs
index 0f2c0ee..aaa95f6 100644
--- a/compiler/rustc_data_structures/src/steal.rs
+++ b/compiler/rustc_data_structures/src/steal.rs
@@ -57,6 +57,7 @@ pub fn steal(&self) -> T {
///
/// This should not be used within rustc as it leaks information not tracked
/// by the query system, breaking incremental compilation.
+ #[cfg_attr(not(bootstrap), rustc_lint_untracked_query_information)]
pub fn is_stolen(&self) -> bool {
self.value.borrow().is_none()
}
diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs
index cb2fa6e..1b7ca61 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(bootstrap, feature(unsafe_extern_blocks))]
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
#![doc(rust_logo)]
#![feature(decl_macro)]
@@ -862,9 +861,9 @@ fn print_crate_info(
use rustc_target::spec::current_apple_deployment_target;
if sess.target.is_like_osx {
- let (major, minor) = current_apple_deployment_target(&sess.target)
- .expect("unknown Apple target OS");
- println_info!("deployment_target={}", format!("{major}.{minor}"))
+ let (major, minor, patch) = current_apple_deployment_target(&sess.target);
+ let patch = if patch != 0 { format!(".{patch}") } else { String::new() };
+ println_info!("deployment_target={major}.{minor}{patch}")
} else {
#[allow(rustc::diagnostic_outside_of_impl)]
sess.dcx().fatal("only Apple targets currently support deployment version info")
diff --git a/compiler/rustc_expand/src/mbe/macro_parser.rs b/compiler/rustc_expand/src/mbe/macro_parser.rs
index 9011d02..501a241 100644
--- a/compiler/rustc_expand/src/mbe/macro_parser.rs
+++ b/compiler/rustc_expand/src/mbe/macro_parser.rs
@@ -398,8 +398,10 @@ pub(crate) enum NamedMatch {
fn token_name_eq(t1: &Token, t2: &Token) -> bool {
if let (Some((ident1, is_raw1)), Some((ident2, is_raw2))) = (t1.ident(), t2.ident()) {
ident1.name == ident2.name && is_raw1 == is_raw2
- } else if let (Some(ident1), Some(ident2)) = (t1.lifetime(), t2.lifetime()) {
- ident1.name == ident2.name
+ } else if let (Some((ident1, is_raw1)), Some((ident2, is_raw2))) =
+ (t1.lifetime(), t2.lifetime())
+ {
+ ident1.name == ident2.name && is_raw1 == is_raw2
} else {
t1.kind == t2.kind
}
diff --git a/compiler/rustc_expand/src/mbe/transcribe.rs b/compiler/rustc_expand/src/mbe/transcribe.rs
index b069105..39489a8 100644
--- a/compiler/rustc_expand/src/mbe/transcribe.rs
+++ b/compiler/rustc_expand/src/mbe/transcribe.rs
@@ -283,9 +283,9 @@ pub(super) fn transcribe<'a>(
let kind = token::NtIdent(*ident, *is_raw);
TokenTree::token_alone(kind, sp)
}
- MatchedSingle(ParseNtResult::Lifetime(ident)) => {
+ MatchedSingle(ParseNtResult::Lifetime(ident, is_raw)) => {
marker.visit_span(&mut sp);
- let kind = token::NtLifetime(*ident);
+ let kind = token::NtLifetime(*ident, *is_raw);
TokenTree::token_alone(kind, sp)
}
MatchedSingle(ParseNtResult::Nt(nt)) => {
diff --git a/compiler/rustc_expand/src/proc_macro_server.rs b/compiler/rustc_expand/src/proc_macro_server.rs
index 4ff5da1..5798bce 100644
--- a/compiler/rustc_expand/src/proc_macro_server.rs
+++ b/compiler/rustc_expand/src/proc_macro_server.rs
@@ -229,15 +229,16 @@ fn from_internal((stream, rustc): (TokenStream, &mut Rustc<'_, '_>)) -> Self {
span: ident.span,
})),
- Lifetime(name) => {
+ Lifetime(name, is_raw) => {
let ident = symbol::Ident::new(name, span).without_first_quote();
trees.extend([
TokenTree::Punct(Punct { ch: b'\'', joint: true, span }),
- TokenTree::Ident(Ident { sym: ident.name, is_raw: false, span }),
+ TokenTree::Ident(Ident { sym: ident.name, is_raw: is_raw.into(), span }),
]);
}
- NtLifetime(ident) => {
- let stream = TokenStream::token_alone(token::Lifetime(ident.name), ident.span);
+ NtLifetime(ident, is_raw) => {
+ let stream =
+ TokenStream::token_alone(token::Lifetime(ident.name, is_raw), ident.span);
trees.push(TokenTree::Group(Group {
delimiter: pm::Delimiter::None,
stream: Some(stream),
diff --git a/compiler/rustc_feature/src/accepted.rs b/compiler/rustc_feature/src/accepted.rs
index 9223c3c..8949fdf 100644
--- a/compiler/rustc_feature/src/accepted.rs
+++ b/compiler/rustc_feature/src/accepted.rs
@@ -61,7 +61,7 @@ macro_rules! declare_features {
/// Allows explicit discriminants on non-unit enum variants.
(accepted, arbitrary_enum_discriminant, "1.66.0", Some(60553)),
/// Allows using `const` operands in inline assembly.
- (accepted, asm_const, "CURRENT_RUSTC_VERSION", Some(93332)),
+ (accepted, asm_const, "1.82.0", Some(93332)),
/// Allows using `sym` operands in inline assembly.
(accepted, asm_sym, "1.66.0", Some(93333)),
/// Allows the definition of associated constants in `trait` or `impl` blocks.
@@ -116,7 +116,7 @@ macro_rules! declare_features {
/// Allows calling constructor functions in `const fn`.
(accepted, const_constructor, "1.40.0", Some(61456)),
/// Allows basic arithmetic on floating point types in a `const fn`.
- (accepted, const_fn_floating_point_arithmetic, "CURRENT_RUSTC_VERSION", Some(57241)),
+ (accepted, const_fn_floating_point_arithmetic, "1.82.0", Some(57241)),
/// Allows using and casting function pointers in a `const fn`.
(accepted, const_fn_fn_ptr_basics, "1.61.0", Some(57563)),
/// Allows trait bounds in `const fn`.
@@ -272,7 +272,7 @@ macro_rules! declare_features {
/// Allows calling `const unsafe fn` inside `unsafe` blocks in `const fn` functions.
(accepted, min_const_unsafe_fn, "1.33.0", Some(55607)),
/// Allows exhaustive pattern matching on uninhabited types when matched by value.
- (accepted, min_exhaustive_patterns, "CURRENT_RUSTC_VERSION", Some(119612)),
+ (accepted, min_exhaustive_patterns, "1.82.0", Some(119612)),
/// Allows using `Self` and associated types in struct expressions and patterns.
(accepted, more_struct_aliases, "1.16.0", Some(37544)),
/// Allows using the MOVBE target feature.
@@ -299,7 +299,7 @@ macro_rules! declare_features {
/// Allows `foo.rs` as an alternative to `foo/mod.rs`.
(accepted, non_modrs_mods, "1.30.0", Some(44660)),
/// Allows using multiple nested field accesses in offset_of!
- (accepted, offset_of_nested, "CURRENT_RUSTC_VERSION", Some(120140)),
+ (accepted, offset_of_nested, "1.82.0", Some(120140)),
/// Allows the use of or-patterns (e.g., `0 | 1`).
(accepted, or_patterns, "1.53.0", Some(54883)),
/// Allows using `+bundle,+whole-archive` link modifiers with native libs.
@@ -312,7 +312,7 @@ macro_rules! declare_features {
/// Allows parentheses in patterns.
(accepted, pattern_parentheses, "1.31.0", Some(51087)),
/// Allows `use<'a, 'b, A, B>` in `impl Trait + use<...>` for precise capture of generic args.
- (accepted, precise_capturing, "CURRENT_RUSTC_VERSION", Some(123432)),
+ (accepted, precise_capturing, "1.82.0", Some(123432)),
/// Allows procedural macros in `proc-macro` crates.
(accepted, proc_macro, "1.29.0", Some(38356)),
/// Allows multi-segment paths in attributes and derives.
@@ -326,7 +326,7 @@ macro_rules! declare_features {
/// Allows keywords to be escaped for use as identifiers.
(accepted, raw_identifiers, "1.30.0", Some(48589)),
/// Allows `&raw const $place_expr` and `&raw mut $place_expr` expressions.
- (accepted, raw_ref_op, "CURRENT_RUSTC_VERSION", Some(64490)),
+ (accepted, raw_ref_op, "1.82.0", Some(64490)),
/// Allows relaxing the coherence rules such that
/// `impl<T> ForeignTrait<LocalType> for ForeignType<T>` is permitted.
(accepted, re_rebalance_coherence, "1.41.0", Some(55437)),
@@ -399,11 +399,11 @@ macro_rules! declare_features {
/// Allows arbitrary delimited token streams in non-macro attributes.
(accepted, unrestricted_attribute_tokens, "1.34.0", Some(55208)),
/// Allows unsafe attributes.
- (accepted, unsafe_attributes, "CURRENT_RUSTC_VERSION", Some(123757)),
+ (accepted, unsafe_attributes, "1.82.0", Some(123757)),
/// The `unsafe_op_in_unsafe_fn` lint (allowed by default): no longer treat an unsafe function as an unsafe block.
(accepted, unsafe_block_in_unsafe_fn, "1.52.0", Some(71668)),
/// Allows unsafe on extern declarations and safety qualifiers over internal items.
- (accepted, unsafe_extern_blocks, "CURRENT_RUSTC_VERSION", Some(123743)),
+ (accepted, unsafe_extern_blocks, "1.82.0", Some(123743)),
/// Allows importing and reexporting macros with `use`,
/// enables macro modularization in general.
(accepted, use_extern_macros, "1.30.0", Some(35896)),
diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs
index e249192..3b7e0d8 100644
--- a/compiler/rustc_feature/src/builtin_attrs.rs
+++ b/compiler/rustc_feature/src/builtin_attrs.rs
@@ -793,6 +793,12 @@ pub struct BuiltinAttribute {
rustc_lint_query_instability, Normal, template!(Word),
WarnFollowing, EncodeCrossCrate::Yes, INTERNAL_UNSTABLE
),
+ // Used by the `rustc::untracked_query_information` lint to warn methods which
+ // might not be stable during incremental compilation.
+ rustc_attr!(
+ rustc_lint_untracked_query_information, Normal, template!(Word),
+ WarnFollowing, EncodeCrossCrate::Yes, INTERNAL_UNSTABLE
+ ),
// Used by the `rustc::diagnostic_outside_of_impl` lints to assist in changes to diagnostic
// APIs. Any function with this attribute will be checked by that lint.
rustc_attr!(
@@ -1180,3 +1186,11 @@ pub fn is_valid_for_get_attr(name: Symbol) -> bool {
}
map
});
+
+pub fn is_stable_diagnostic_attribute(sym: Symbol, features: &Features) -> bool {
+ match sym {
+ sym::on_unimplemented => true,
+ sym::do_not_recommend => features.do_not_recommend,
+ _ => false,
+ }
+}
diff --git a/compiler/rustc_feature/src/lib.rs b/compiler/rustc_feature/src/lib.rs
index adaaba3..fe12930 100644
--- a/compiler/rustc_feature/src/lib.rs
+++ b/compiler/rustc_feature/src/lib.rs
@@ -130,8 +130,9 @@ pub fn find_feature_issue(feature: Symbol, issue: GateIssue) -> Option<NonZero<u
pub use accepted::ACCEPTED_FEATURES;
pub use builtin_attrs::{
deprecated_attributes, encode_cross_crate, find_gated_cfg, is_builtin_attr_name,
- is_valid_for_get_attr, AttributeDuplicates, AttributeGate, AttributeSafety, AttributeTemplate,
- AttributeType, BuiltinAttribute, GatedCfg, BUILTIN_ATTRIBUTES, BUILTIN_ATTRIBUTE_MAP,
+ is_stable_diagnostic_attribute, is_valid_for_get_attr, AttributeDuplicates, AttributeGate,
+ AttributeSafety, AttributeTemplate, AttributeType, BuiltinAttribute, GatedCfg,
+ BUILTIN_ATTRIBUTES, BUILTIN_ATTRIBUTE_MAP,
};
pub use removed::REMOVED_FEATURES;
pub use unstable::{Features, INCOMPATIBLE_FEATURES, UNSTABLE_FEATURES};
diff --git a/compiler/rustc_feature/src/removed.rs b/compiler/rustc_feature/src/removed.rs
index b7f0ed5..3d7d877 100644
--- a/compiler/rustc_feature/src/removed.rs
+++ b/compiler/rustc_feature/src/removed.rs
@@ -83,7 +83,7 @@ macro_rules! declare_features {
(removed, custom_derive, "1.32.0", Some(29644),
Some("subsumed by `#[proc_macro_derive]`")),
/// Allows default type parameters to influence type inference.
- (removed, default_type_parameter_fallback, "CURRENT_RUSTC_VERSION", Some(27336),
+ (removed, default_type_parameter_fallback, "1.82.0", Some(27336),
Some("never properly implemented; requires significant design work")),
/// Allows using `#[doc(keyword = "...")]`.
(removed, doc_keyword, "1.28.0", Some(51315),
diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs
index fba6588..3254dab 100644
--- a/compiler/rustc_feature/src/unstable.rs
+++ b/compiler/rustc_feature/src/unstable.rs
@@ -208,7 +208,7 @@ pub fn internal(&self, feature: Symbol) -> bool {
/// Allows `#[link(..., cfg(..))]`; perma-unstable per #37406
(unstable, link_cfg, "1.14.0", None),
/// Allows using `?Trait` trait bounds in more contexts.
- (internal, more_maybe_bounds, "CURRENT_RUSTC_VERSION", None),
+ (internal, more_maybe_bounds, "1.82.0", None),
/// Allows the `multiple_supertrait_upcastable` lint.
(unstable, multiple_supertrait_upcastable, "1.69.0", None),
/// Allow negative trait bounds. This is an internal-only feature for testing the trait solver!
@@ -302,7 +302,7 @@ pub fn internal(&self, feature: Symbol) -> bool {
// FIXME: Document these and merge with the list below.
// Unstable `#[target_feature]` directives.
- (unstable, aarch64_unstable_target_feature, "CURRENT_RUSTC_VERSION", Some(44839)),
+ (unstable, aarch64_unstable_target_feature, "1.82.0", Some(44839)),
(unstable, aarch64_ver_target_feature, "1.27.0", Some(44839)),
(unstable, arm_target_feature, "1.27.0", Some(44839)),
(unstable, avx512_target_feature, "1.27.0", Some(44839)),
@@ -317,7 +317,7 @@ pub fn internal(&self, feature: Symbol) -> bool {
(unstable, prfchw_target_feature, "1.78.0", Some(44839)),
(unstable, riscv_target_feature, "1.45.0", Some(44839)),
(unstable, rtm_target_feature, "1.35.0", Some(44839)),
- (unstable, s390x_target_feature, "CURRENT_RUSTC_VERSION", Some(44839)),
+ (unstable, s390x_target_feature, "1.82.0", Some(44839)),
(unstable, sse4a_target_feature, "1.27.0", Some(44839)),
(unstable, tbm_target_feature, "1.27.0", Some(44839)),
(unstable, wasm_target_feature, "1.30.0", Some(44839)),
@@ -474,7 +474,7 @@ pub fn internal(&self, feature: Symbol) -> bool {
/// Allows the use of `#[ffi_pure]` on foreign functions.
(unstable, ffi_pure, "1.45.0", Some(58329)),
/// Controlling the behavior of fmt::Debug
- (unstable, fmt_debug, "CURRENT_RUSTC_VERSION", Some(129709)),
+ (unstable, fmt_debug, "1.82.0", Some(129709)),
/// Allows using `#[repr(align(...))]` on function items
(unstable, fn_align, "1.53.0", Some(82232)),
/// Support delegating implementation of functions to other already implemented functions.
@@ -586,8 +586,8 @@ pub fn internal(&self, feature: Symbol) -> bool {
/// Allows `extern "rust-cold"`.
(unstable, rust_cold_cc, "1.63.0", Some(97544)),
/// Allows use of x86 SHA512, SM3 and SM4 target-features and intrinsics
- (unstable, sha512_sm_x86, "CURRENT_RUSTC_VERSION", Some(126624)),
- /// Shorten the tail expression lifetime
+ (unstable, sha512_sm_x86, "1.82.0", Some(126624)),
+ /// Shortern the tail expression lifetime
(unstable, shorter_tail_lifetimes, "1.79.0", Some(123739)),
/// Allows the use of SIMD types in functions declared in `extern` blocks.
(unstable, simd_ffi, "1.0.0", Some(27731)),
@@ -625,7 +625,7 @@ pub fn internal(&self, feature: Symbol) -> bool {
(incomplete, unnamed_fields, "1.74.0", Some(49804)),
/// Allows const generic parameters to be defined with types that
/// are not `Sized`, e.g. `fn foo<const N: [u8]>() {`.
- (incomplete, unsized_const_params, "CURRENT_RUSTC_VERSION", Some(95174)),
+ (incomplete, unsized_const_params, "1.82.0", Some(95174)),
/// Allows unsized fn parameters.
(internal, unsized_fn_params, "1.49.0", Some(48055)),
/// Allows unsized rvalues at arguments and parameters.
diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs
index 57c47d2..b01c24c 100644
--- a/compiler/rustc_hir/src/hir.rs
+++ b/compiler/rustc_hir/src/hir.rs
@@ -168,6 +168,19 @@ pub fn suggestion_position(&self) -> (LifetimeSuggestionPosition, Span) {
(LifetimeSuggestionPosition::Normal, self.ident.span)
}
}
+
+ pub fn suggestion(&self, new_lifetime: &str) -> (Span, String) {
+ debug_assert!(new_lifetime.starts_with('\''));
+ let (pos, span) = self.suggestion_position();
+ let code = match pos {
+ LifetimeSuggestionPosition::Normal => format!("{new_lifetime}"),
+ LifetimeSuggestionPosition::Ampersand => format!("{new_lifetime} "),
+ LifetimeSuggestionPosition::ElidedPath => format!("<{new_lifetime}>"),
+ LifetimeSuggestionPosition::ElidedPathArgument => format!("{new_lifetime}, "),
+ LifetimeSuggestionPosition::ObjectDefault => format!("+ {new_lifetime}"),
+ };
+ (span, code)
+ }
}
/// A `Path` is essentially Rust's notion of a name; for instance,
diff --git a/compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs b/compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs
index bd8b43e..9fce927 100644
--- a/compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs
+++ b/compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs
@@ -93,7 +93,8 @@ fn check_def_id(
}
}
- if let Some(simp) = simplify_type(self.tcx, self_ty, TreatParams::AsCandidateKey) {
+ if let Some(simp) = simplify_type(self.tcx, self_ty, TreatParams::InstantiateWithInfer)
+ {
self.impls_map.incoherent_impls.entry(simp).or_default().push(impl_def_id);
} else {
bug!("unexpected self type: {:?}", self_ty);
@@ -132,7 +133,7 @@ fn check_primitive_impl(
}
}
- if let Some(simp) = simplify_type(self.tcx, ty, TreatParams::AsCandidateKey) {
+ if let Some(simp) = simplify_type(self.tcx, ty, TreatParams::InstantiateWithInfer) {
self.impls_map.incoherent_impls.entry(simp).or_default().push(impl_def_id);
} else {
bug!("unexpected primitive type: {:?}", ty);
diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs
index 9211180..ac99761 100644
--- a/compiler/rustc_hir_analysis/src/collect.rs
+++ b/compiler/rustc_hir_analysis/src/collect.rs
@@ -1698,8 +1698,6 @@ fn impl_trait_header(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<ty::ImplTrai
trait_ref: ty::EarlyBinder::bind(trait_ref),
safety: impl_.safety,
polarity: polarity_of_impl(tcx, def_id, impl_, item.span),
- do_not_recommend: tcx.features().do_not_recommend
- && tcx.has_attrs_with_path(def_id, &[sym::diagnostic, sym::do_not_recommend]),
}
})
}
diff --git a/compiler/rustc_hir_analysis/src/collect/generics_of.rs b/compiler/rustc_hir_analysis/src/collect/generics_of.rs
index be6c3f0..ba01ea3f 100644
--- a/compiler/rustc_hir_analysis/src/collect/generics_of.rs
+++ b/compiler/rustc_hir_analysis/src/collect/generics_of.rs
@@ -59,6 +59,12 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics {
let hir_id = tcx.local_def_id_to_hir_id(def_id);
let node = tcx.hir_node(hir_id);
+ if let Some(sig) = node.fn_sig()
+ && let Some(sig_id) = sig.decl.opt_delegation_sig_id()
+ {
+ return inherit_generics_for_delegation_item(tcx, def_id, sig_id);
+ }
+
let parent_def_id = match node {
Node::ImplItem(_)
| Node::TraitItem(_)
@@ -229,16 +235,6 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics {
// inherit the generics of the item.
Some(parent.to_def_id())
}
- ItemKind::Fn(sig, _, _) => {
- // For a delegation item inherit generics from callee.
- if let Some(sig_id) = sig.decl.opt_delegation_sig_id()
- && let Some(generics) =
- inherit_generics_for_delegation_item(tcx, def_id, sig_id)
- {
- return generics;
- }
- None
- }
_ => None,
},
_ => None,
diff --git a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs
index a47aaf2..7243e85 100644
--- a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs
+++ b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs
@@ -138,6 +138,12 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen
let hir_id = tcx.local_def_id_to_hir_id(def_id);
let node = tcx.hir_node(hir_id);
+ if let Some(sig) = node.fn_sig()
+ && let Some(sig_id) = sig.decl.opt_delegation_sig_id()
+ {
+ return inherit_predicates_for_delegation_item(tcx, def_id, sig_id);
+ }
+
let mut is_trait = None;
let mut is_default_impl_trait = None;
@@ -164,16 +170,6 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen
ItemKind::Trait(_, _, _, self_bounds, ..) | ItemKind::TraitAlias(_, self_bounds) => {
is_trait = Some(self_bounds);
}
-
- ItemKind::Fn(sig, _, _) => {
- // For a delegation item inherit predicates from callee.
- if let Some(sig_id) = sig.decl.opt_delegation_sig_id()
- && let Some(predicates) =
- inherit_predicates_for_delegation_item(tcx, def_id, sig_id)
- {
- return predicates;
- }
- }
_ => {}
}
};
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 fe46eb5..b4cbd1f 100644
--- a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs
+++ b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs
@@ -1191,23 +1191,7 @@ fn resolve_lifetime_ref(
(generics.span, "<'a>".to_owned())
};
- let lifetime_sugg = match lifetime_ref.suggestion_position() {
- (hir::LifetimeSuggestionPosition::Normal, span) => {
- (span, "'a".to_owned())
- }
- (hir::LifetimeSuggestionPosition::Ampersand, span) => {
- (span, "'a ".to_owned())
- }
- (hir::LifetimeSuggestionPosition::ElidedPath, span) => {
- (span, "<'a>".to_owned())
- }
- (hir::LifetimeSuggestionPosition::ElidedPathArgument, span) => {
- (span, "'a, ".to_owned())
- }
- (hir::LifetimeSuggestionPosition::ObjectDefault, span) => {
- (span, "+ 'a".to_owned())
- }
- };
+ let lifetime_sugg = lifetime_ref.suggestion("'a");
let suggestions = vec![lifetime_sugg, new_param_sugg];
diag.span_label(
diff --git a/compiler/rustc_hir_analysis/src/delegation.rs b/compiler/rustc_hir_analysis/src/delegation.rs
index 20aaa43..2c9f20b 100644
--- a/compiler/rustc_hir_analysis/src/delegation.rs
+++ b/compiler/rustc_hir_analysis/src/delegation.rs
@@ -1,3 +1,7 @@
+//! Support inheriting generic parameters and predicates for function delegation.
+//!
+//! For more information about delegation design, see the tracking issue #118212.
+
use std::assert_matches::debug_assert_matches;
use rustc_data_structures::fx::FxHashMap;
@@ -5,7 +9,7 @@
use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_middle::ty::fold::{TypeFoldable, TypeFolder, TypeSuperFoldable};
use rustc_middle::ty::{self, Ty, TyCtxt};
-use rustc_span::ErrorGuaranteed;
+use rustc_span::{ErrorGuaranteed, Span};
use rustc_type_ir::visit::TypeVisitableExt;
type RemapTable = FxHashMap<u32, u32>;
@@ -76,127 +80,381 @@ fn fn_kind<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> FnKind {
}
}
+/// Given the current context(caller and callee `FnKind`), it specifies
+/// the policy of predicates and generic parameters inheritance.
+#[derive(Clone, Copy, Debug, PartialEq)]
+enum InheritanceKind {
+ /// Copying all predicates and parameters, including those of the parent
+ /// container.
+ ///
+ /// Boolean value defines whether the `Self` parameter or `Self: Trait`
+ /// predicate are copied. It's always equal to `false` except when
+ /// delegating from a free function to a trait method.
+ ///
+ /// FIXME(fn_delegation): This often leads to type inference
+ /// errors. Support providing generic arguments or restrict use sites.
+ WithParent(bool),
+ /// The trait implementation should be compatible with the original trait.
+ /// Therefore, for trait implementations only the method's own parameters
+ /// and predicates are copied.
+ Own,
+}
+
+struct GenericsBuilder<'tcx> {
+ tcx: TyCtxt<'tcx>,
+ sig_id: DefId,
+ parent: Option<DefId>,
+ inh_kind: InheritanceKind,
+}
+
+impl<'tcx> GenericsBuilder<'tcx> {
+ fn new(tcx: TyCtxt<'tcx>, sig_id: DefId) -> GenericsBuilder<'tcx> {
+ GenericsBuilder { tcx, sig_id, parent: None, inh_kind: InheritanceKind::WithParent(false) }
+ }
+
+ fn with_parent(mut self, parent: DefId) -> Self {
+ self.parent = Some(parent);
+ self
+ }
+
+ fn with_inheritance_kind(mut self, inh_kind: InheritanceKind) -> Self {
+ self.inh_kind = inh_kind;
+ self
+ }
+
+ fn build(self) -> ty::Generics {
+ let mut own_params = vec![];
+
+ let sig_generics = self.tcx.generics_of(self.sig_id);
+ if let InheritanceKind::WithParent(has_self) = self.inh_kind
+ && let Some(parent_def_id) = sig_generics.parent
+ {
+ let sig_parent_generics = self.tcx.generics_of(parent_def_id);
+ own_params.append(&mut sig_parent_generics.own_params.clone());
+ if !has_self {
+ own_params.remove(0);
+ }
+ }
+ own_params.append(&mut sig_generics.own_params.clone());
+
+ // Lifetime parameters must be declared before type and const parameters.
+ // Therefore, When delegating from a free function to a associated function,
+ // generic parameters need to be reordered:
+ //
+ // trait Trait<'a, A> {
+ // fn foo<'b, B>(...) {...}
+ // }
+ //
+ // reuse Trait::foo;
+ // desugaring:
+ // fn foo<'a, 'b, This: Trait<'a, A>, A, B>(...) {
+ // Trait::foo(...)
+ // }
+ own_params.sort_by_key(|key| key.kind.is_ty_or_const());
+
+ let param_def_id_to_index =
+ own_params.iter().map(|param| (param.def_id, param.index)).collect();
+
+ let (parent_count, has_self) = if let Some(def_id) = self.parent {
+ let parent_generics = self.tcx.generics_of(def_id);
+ let parent_kind = self.tcx.def_kind(def_id);
+ (parent_generics.count(), parent_kind == DefKind::Trait)
+ } else {
+ (0, false)
+ };
+
+ for (idx, param) in own_params.iter_mut().enumerate() {
+ param.index = (idx + parent_count) as u32;
+ // FIXME(fn_delegation): Default parameters are not inherited, because they are
+ // not permitted in functions. Therefore, there are 2 options here:
+ //
+ // - We can create non-default generic parameters.
+ // - We can substitute default parameters into the signature.
+ //
+ // At the moment, first option has been selected as the most general.
+ if let ty::GenericParamDefKind::Type { has_default, .. }
+ | ty::GenericParamDefKind::Const { has_default, .. } = &mut param.kind
+ {
+ *has_default = false;
+ }
+ }
+
+ ty::Generics {
+ parent: self.parent,
+ parent_count,
+ own_params,
+ param_def_id_to_index,
+ has_self,
+ has_late_bound_regions: sig_generics.has_late_bound_regions,
+ host_effect_index: sig_generics.host_effect_index,
+ }
+ }
+}
+
+struct PredicatesBuilder<'tcx> {
+ tcx: TyCtxt<'tcx>,
+ sig_id: DefId,
+ parent: Option<DefId>,
+ inh_kind: InheritanceKind,
+ args: ty::GenericArgsRef<'tcx>,
+}
+
+impl<'tcx> PredicatesBuilder<'tcx> {
+ fn new(
+ tcx: TyCtxt<'tcx>,
+ args: ty::GenericArgsRef<'tcx>,
+ sig_id: DefId,
+ ) -> PredicatesBuilder<'tcx> {
+ PredicatesBuilder {
+ tcx,
+ sig_id,
+ parent: None,
+ inh_kind: InheritanceKind::WithParent(false),
+ args,
+ }
+ }
+
+ fn with_parent(mut self, parent: DefId) -> Self {
+ self.parent = Some(parent);
+ self
+ }
+
+ fn with_inheritance_kind(mut self, inh_kind: InheritanceKind) -> Self {
+ self.inh_kind = inh_kind;
+ self
+ }
+
+ fn build(self) -> ty::GenericPredicates<'tcx> {
+ struct PredicatesCollector<'tcx> {
+ tcx: TyCtxt<'tcx>,
+ preds: Vec<(ty::Clause<'tcx>, Span)>,
+ args: ty::GenericArgsRef<'tcx>,
+ }
+
+ impl<'tcx> PredicatesCollector<'tcx> {
+ fn new(tcx: TyCtxt<'tcx>, args: ty::GenericArgsRef<'tcx>) -> PredicatesCollector<'tcx> {
+ PredicatesCollector { tcx, preds: vec![], args }
+ }
+
+ fn with_own_preds(
+ mut self,
+ f: impl Fn(DefId) -> ty::GenericPredicates<'tcx>,
+ def_id: DefId,
+ ) -> Self {
+ let preds = f(def_id).instantiate_own(self.tcx, self.args);
+ self.preds.extend(preds);
+ self
+ }
+
+ fn with_preds(
+ mut self,
+ f: impl Fn(DefId) -> ty::GenericPredicates<'tcx> + Copy,
+ def_id: DefId,
+ ) -> Self {
+ let preds = f(def_id);
+ if let Some(parent_def_id) = preds.parent {
+ self = self.with_own_preds(f, parent_def_id);
+ }
+ self.with_own_preds(f, def_id)
+ }
+ }
+ let collector = PredicatesCollector::new(self.tcx, self.args);
+
+ // `explicit_predicates_of` is used here to avoid copying `Self: Trait` predicate.
+ // Note: `predicates_of` query can also add inferred outlives predicates, but that
+ // is not the case here as `sig_id` is either a trait or a function.
+ let preds = match self.inh_kind {
+ InheritanceKind::WithParent(false) => {
+ collector.with_preds(|def_id| self.tcx.explicit_predicates_of(def_id), self.sig_id)
+ }
+ InheritanceKind::WithParent(true) => {
+ collector.with_preds(|def_id| self.tcx.predicates_of(def_id), self.sig_id)
+ }
+ InheritanceKind::Own => {
+ collector.with_own_preds(|def_id| self.tcx.predicates_of(def_id), self.sig_id)
+ }
+ }
+ .preds;
+
+ ty::GenericPredicates {
+ parent: self.parent,
+ predicates: self.tcx.arena.alloc_from_iter(preds),
+ // FIXME(fn_delegation): Support effects.
+ effects_min_tys: ty::List::empty(),
+ }
+ }
+}
+
+struct GenericArgsBuilder<'tcx> {
+ tcx: TyCtxt<'tcx>,
+ remap_table: RemapTable,
+ sig_id: DefId,
+ def_id: LocalDefId,
+}
+
+impl<'tcx> GenericArgsBuilder<'tcx> {
+ fn new(tcx: TyCtxt<'tcx>, sig_id: DefId, def_id: LocalDefId) -> GenericArgsBuilder<'tcx> {
+ GenericArgsBuilder { tcx, remap_table: FxHashMap::default(), sig_id, def_id }
+ }
+
+ fn build_from_args(mut self, args: ty::GenericArgsRef<'tcx>) -> ty::GenericArgsRef<'tcx> {
+ let caller_generics = self.tcx.generics_of(self.def_id);
+ let callee_generics = self.tcx.generics_of(self.sig_id);
+
+ for caller_param in &caller_generics.own_params {
+ let callee_index =
+ callee_generics.param_def_id_to_index(self.tcx, caller_param.def_id).unwrap();
+ self.remap_table.insert(callee_index, caller_param.index);
+ }
+
+ let mut folder = ParamIndexRemapper { tcx: self.tcx, remap_table: self.remap_table };
+ args.fold_with(&mut folder)
+ }
+}
+
fn create_generic_args<'tcx>(
tcx: TyCtxt<'tcx>,
def_id: LocalDefId,
sig_id: DefId,
) -> ty::GenericArgsRef<'tcx> {
- let caller_generics = tcx.generics_of(def_id);
- let callee_generics = tcx.generics_of(sig_id);
+ let builder = GenericArgsBuilder::new(tcx, sig_id, def_id);
let caller_kind = fn_kind(tcx, def_id.into());
let callee_kind = fn_kind(tcx, sig_id);
- // FIXME(fn_delegation): Support generics on associated delegation items.
- // Error will be reported in `check_constraints`.
match (caller_kind, callee_kind) {
- (FnKind::Free, _) => {
- // Lifetime parameters must be declared before type and const parameters.
- // Therefore, When delegating from a free function to a associated function,
- // generic parameters need to be reordered:
- //
- // trait Trait<'a, A> {
- // fn foo<'b, B>(...) {...}
- // }
- //
- // reuse Trait::foo;
- // desugaring:
- // fn foo<'a, 'b, This: Trait<'a, A>, A, B>(...) {
- // Trait::foo(...)
- // }
- let mut remap_table = RemapTable::default();
- for caller_param in &caller_generics.own_params {
- let callee_index =
- callee_generics.param_def_id_to_index(tcx, caller_param.def_id).unwrap();
- remap_table.insert(callee_index, caller_param.index);
- }
- let mut folder = ParamIndexRemapper { tcx, remap_table };
- ty::GenericArgs::identity_for_item(tcx, sig_id).fold_with(&mut folder)
+ (FnKind::Free, FnKind::Free)
+ | (FnKind::Free, FnKind::AssocTrait)
+ | (FnKind::AssocInherentImpl, FnKind::Free)
+ | (FnKind::AssocTrait, FnKind::Free)
+ | (FnKind::AssocTrait, FnKind::AssocTrait) => {
+ let args = ty::GenericArgs::identity_for_item(tcx, sig_id);
+ builder.build_from_args(args)
}
- // FIXME(fn_delegation): Only `Self` param supported here.
- (FnKind::AssocTraitImpl, FnKind::AssocTrait)
- | (FnKind::AssocInherentImpl, FnKind::AssocTrait) => {
+
+ (FnKind::AssocTraitImpl, FnKind::AssocTrait) => {
+ let callee_generics = tcx.generics_of(sig_id);
+ let parent = tcx.parent(def_id.into());
+ let parent_args =
+ tcx.impl_trait_header(parent).unwrap().trait_ref.instantiate_identity().args;
+
+ let trait_args = ty::GenericArgs::identity_for_item(tcx, sig_id);
+ let method_args = tcx.mk_args_from_iter(trait_args.iter().skip(callee_generics.parent_count));
+ let method_args = builder.build_from_args(method_args);
+
+ tcx.mk_args_from_iter(parent_args.iter().chain(method_args))
+ }
+
+ (FnKind::AssocInherentImpl, FnKind::AssocTrait) => {
let parent = tcx.parent(def_id.into());
let self_ty = tcx.type_of(parent).instantiate_identity();
let generic_self_ty = ty::GenericArg::from(self_ty);
- tcx.mk_args_from_iter(std::iter::once(generic_self_ty))
+
+ let trait_args = ty::GenericArgs::identity_for_item(tcx, sig_id);
+ let trait_args = builder.build_from_args(trait_args);
+
+ let args = std::iter::once(generic_self_ty).chain(trait_args.iter().skip(1));
+ tcx.mk_args_from_iter(args)
}
- _ => ty::GenericArgs::identity_for_item(tcx, sig_id),
+
+ // For trait impl's `sig_id` is always equal to the corresponding trait method.
+ (FnKind::AssocTraitImpl, _)
+ | (_, FnKind::AssocTraitImpl)
+ // Delegation to inherent methods is not yet supported.
+ | (_, FnKind::AssocInherentImpl) => unreachable!(),
}
}
+// FIXME(fn_delegation): Move generics inheritance to the AST->HIR lowering.
+// For now, generic parameters are not propagated to the generated call,
+// which leads to inference errors:
+//
+// fn foo<T>(x: i32) {}
+//
+// reuse foo as bar;
+// desugaring:
+// fn bar<T>() {
+// foo::<_>() // ERROR: type annotations needed
+// }
pub(crate) fn inherit_generics_for_delegation_item<'tcx>(
tcx: TyCtxt<'tcx>,
def_id: LocalDefId,
sig_id: DefId,
-) -> Option<ty::Generics> {
- // FIXME(fn_delegation): Support generics on associated delegation items.
- // Error will be reported in `check_constraints`.
- if fn_kind(tcx, def_id.into()) != FnKind::Free {
- return None;
- }
+) -> ty::Generics {
+ let builder = GenericsBuilder::new(tcx, sig_id);
- let mut own_params = vec![];
+ let caller_kind = fn_kind(tcx, def_id.into());
+ let callee_kind = fn_kind(tcx, sig_id);
+ match (caller_kind, callee_kind) {
+ (FnKind::Free, FnKind::Free)
+ | (FnKind::Free, FnKind::AssocTrait) => builder.with_inheritance_kind(InheritanceKind::WithParent(true)).build(),
- let callee_generics = tcx.generics_of(sig_id);
- if let Some(parent_sig_id) = callee_generics.parent {
- let parent_sig_generics = tcx.generics_of(parent_sig_id);
- own_params.append(&mut parent_sig_generics.own_params.clone());
- }
- own_params.append(&mut callee_generics.own_params.clone());
-
- // Lifetimes go first.
- own_params.sort_by_key(|key| key.kind.is_ty_or_const());
-
- for (idx, param) in own_params.iter_mut().enumerate() {
- param.index = idx as u32;
- // Default parameters are not inherited: they are not allowed
- // in fn's.
- if let ty::GenericParamDefKind::Type { has_default, .. }
- | ty::GenericParamDefKind::Const { has_default, .. } = &mut param.kind
- {
- *has_default = false;
+ (FnKind::AssocTraitImpl, FnKind::AssocTrait) => {
+ builder
+ .with_parent(tcx.parent(def_id.into()))
+ .with_inheritance_kind(InheritanceKind::Own)
+ .build()
}
+
+ (FnKind::AssocInherentImpl, FnKind::AssocTrait)
+ | (FnKind::AssocTrait, FnKind::AssocTrait) => {
+ builder
+ .with_parent(tcx.parent(def_id.into()))
+ .build()
+ }
+
+ (FnKind::AssocInherentImpl, FnKind::Free)
+ | (FnKind::AssocTrait, FnKind::Free) => {
+ builder
+ .with_parent(tcx.parent(def_id.into()))
+ .build()
+ }
+
+ // For trait impl's `sig_id` is always equal to the corresponding trait method.
+ (FnKind::AssocTraitImpl, _)
+ | (_, FnKind::AssocTraitImpl)
+ // Delegation to inherent methods is not yet supported.
+ | (_, FnKind::AssocInherentImpl) => unreachable!(),
}
-
- let param_def_id_to_index =
- own_params.iter().map(|param| (param.def_id, param.index)).collect();
-
- Some(ty::Generics {
- parent: None,
- parent_count: 0,
- own_params,
- param_def_id_to_index,
- has_self: false,
- has_late_bound_regions: callee_generics.has_late_bound_regions,
- host_effect_index: callee_generics.host_effect_index,
- })
}
pub(crate) fn inherit_predicates_for_delegation_item<'tcx>(
tcx: TyCtxt<'tcx>,
def_id: LocalDefId,
sig_id: DefId,
-) -> Option<ty::GenericPredicates<'tcx>> {
- // FIXME(fn_delegation): Support generics on associated delegation items.
- // Error will be reported in `check_constraints`.
- if fn_kind(tcx, def_id.into()) != FnKind::Free {
- return None;
- }
-
- let callee_predicates = tcx.predicates_of(sig_id);
+) -> ty::GenericPredicates<'tcx> {
let args = create_generic_args(tcx, def_id, sig_id);
+ let builder = PredicatesBuilder::new(tcx, args, sig_id);
- let mut preds = vec![];
- if let Some(parent_id) = callee_predicates.parent {
- preds.extend(tcx.predicates_of(parent_id).instantiate_own(tcx, args));
+ let caller_kind = fn_kind(tcx, def_id.into());
+ let callee_kind = fn_kind(tcx, sig_id);
+ match (caller_kind, callee_kind) {
+ (FnKind::Free, FnKind::Free)
+ | (FnKind::Free, FnKind::AssocTrait) => {
+ builder.with_inheritance_kind(InheritanceKind::WithParent(true)).build()
+ }
+
+ (FnKind::AssocTraitImpl, FnKind::AssocTrait) => {
+ builder
+ .with_parent(tcx.parent(def_id.into()))
+ .with_inheritance_kind(InheritanceKind::Own)
+ .build()
+ }
+
+ (FnKind::AssocInherentImpl, FnKind::AssocTrait)
+ | (FnKind::AssocTrait, FnKind::AssocTrait)
+ | (FnKind::AssocInherentImpl, FnKind::Free)
+ | (FnKind::AssocTrait, FnKind::Free) => {
+ builder
+ .with_parent(tcx.parent(def_id.into()))
+ .build()
+ }
+
+ // For trait impl's `sig_id` is always equal to the corresponding trait method.
+ (FnKind::AssocTraitImpl, _)
+ | (_, FnKind::AssocTraitImpl)
+ // Delegation to inherent methods is not yet supported.
+ | (_, FnKind::AssocInherentImpl) => unreachable!(),
}
- preds.extend(callee_predicates.instantiate_own(tcx, args));
-
- Some(ty::GenericPredicates {
- parent: None,
- predicates: tcx.arena.alloc_from_iter(preds),
- effects_min_tys: ty::List::empty(),
- })
}
fn check_constraints<'tcx>(
@@ -224,19 +482,6 @@ fn check_constraints<'tcx>(
emit("recursive delegation is not supported yet");
}
- if fn_kind(tcx, def_id.into()) != FnKind::Free {
- let sig_generics = tcx.generics_of(sig_id);
- let parent = tcx.parent(def_id.into());
- let parent_generics = tcx.generics_of(parent);
-
- let parent_has_self = parent_generics.has_self as usize;
- let sig_has_self = sig_generics.has_self as usize;
-
- if sig_generics.count() > sig_has_self || parent_generics.count() > parent_has_self {
- emit("early bound generics are not supported for associated delegation items");
- }
- }
-
ret
}
diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/cmse.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/cmse.rs
index 1b73cec..5150db7 100644
--- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/cmse.rs
+++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/cmse.rs
@@ -72,8 +72,11 @@ fn is_valid_cmse_inputs<'tcx>(
let mut span = None;
let mut accum = 0u64;
- for (index, arg_def) in fn_sig.inputs().iter().enumerate() {
- let layout = tcx.layout_of(ParamEnv::reveal_all().and(*arg_def.skip_binder()))?;
+ // this type is only used for layout computation, which does not rely on regions
+ let fn_sig = tcx.instantiate_bound_regions_with_erased(fn_sig);
+
+ for (index, ty) in fn_sig.inputs().iter().enumerate() {
+ let layout = tcx.layout_of(ParamEnv::reveal_all().and(*ty))?;
let align = layout.layout.align().abi.bytes();
let size = layout.layout.size().bytes();
@@ -98,7 +101,10 @@ fn is_valid_cmse_output<'tcx>(
tcx: TyCtxt<'tcx>,
fn_sig: ty::PolyFnSig<'tcx>,
) -> Result<bool, &'tcx LayoutError<'tcx>> {
- let mut ret_ty = fn_sig.output().skip_binder();
+ // this type is only used for layout computation, which does not rely on regions
+ let fn_sig = tcx.instantiate_bound_regions_with_erased(fn_sig);
+
+ let mut ret_ty = fn_sig.output();
let layout = tcx.layout_of(ParamEnv::reveal_all().and(ret_ty))?;
let size = layout.layout.size().bytes();
diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs
index f0d47e5..9bad563 100644
--- a/compiler/rustc_hir_typeck/src/expr.rs
+++ b/compiler/rustc_hir_typeck/src/expr.rs
@@ -447,7 +447,7 @@ fn check_expr_addr_of(
// this time with enough precision to check that the value
// whose address was taken can actually be made to live as long
// as it needs to live.
- let region = self.next_region_var(infer::AddrOfRegion(expr.span));
+ let region = self.next_region_var(infer::BorrowRegion(expr.span));
Ty::new_ref(self.tcx, region, ty, mutbl)
}
}
diff --git a/compiler/rustc_hir_typeck/src/method/prelude_edition_lints.rs b/compiler/rustc_hir_typeck/src/method/prelude_edition_lints.rs
index 0790c6f..ac5e104 100644
--- a/compiler/rustc_hir_typeck/src/method/prelude_edition_lints.rs
+++ b/compiler/rustc_hir_typeck/src/method/prelude_edition_lints.rs
@@ -63,8 +63,7 @@ pub(super) fn lint_edition_dependent_dot_call(
// Instead, the problem is that the array-into_iter hack will no longer
// apply in Rust 2021.
(ARRAY_INTO_ITER, "2021")
- } else if self_ty.is_box()
- && self_ty.boxed_ty().is_slice()
+ } else if self_ty.boxed_ty().is_some_and(Ty::is_slice)
&& !span.at_least_rust_2024()
{
// In this case, it wasn't really a prelude addition that was the problem.
diff --git a/compiler/rustc_hir_typeck/src/method/probe.rs b/compiler/rustc_hir_typeck/src/method/probe.rs
index 2fdba84..3ba3429 100644
--- a/compiler/rustc_hir_typeck/src/method/probe.rs
+++ b/compiler/rustc_hir_typeck/src/method/probe.rs
@@ -715,7 +715,7 @@ fn assemble_probe(&mut self, self_ty: &Canonical<'tcx, QueryResponse<'tcx, Ty<'t
}
fn assemble_inherent_candidates_for_incoherent_ty(&mut self, self_ty: Ty<'tcx>) {
- let Some(simp) = simplify_type(self.tcx, self_ty, TreatParams::AsCandidateKey) else {
+ let Some(simp) = simplify_type(self.tcx, self_ty, TreatParams::InstantiateWithInfer) else {
bug!("unexpected incoherent type: {:?}", self_ty)
};
for &impl_def_id in self.tcx.incoherent_impls(simp).into_iter().flatten() {
@@ -1485,8 +1485,7 @@ fn consider_probe(
// Some trait methods are excluded for boxed slices before 2024.
// (`boxed_slice.into_iter()` wants a slice iterator for compatibility.)
- if self_ty.is_box()
- && self_ty.boxed_ty().is_slice()
+ if self_ty.boxed_ty().is_some_and(Ty::is_slice)
&& !method_name.span.at_least_rust_2024()
{
let trait_def = self.tcx.trait_def(poly_trait_ref.def_id());
diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs
index 9ea57e4..14ad583 100644
--- a/compiler/rustc_hir_typeck/src/method/suggest.rs
+++ b/compiler/rustc_hir_typeck/src/method/suggest.rs
@@ -2235,8 +2235,7 @@ fn suggest_associated_call_syntax(
let target_ty = self
.autoderef(sugg_span, rcvr_ty)
.find(|(rcvr_ty, _)| {
- DeepRejectCtxt::new(self.tcx, TreatParams::ForLookup)
- .types_may_unify(*rcvr_ty, impl_ty)
+ DeepRejectCtxt::relate_rigid_infer(self.tcx).types_may_unify(*rcvr_ty, impl_ty)
})
.map_or(impl_ty, |(ty, _)| ty)
.peel_refs();
@@ -2498,7 +2497,7 @@ fn report_failed_method_call_on_numerical_infer_var(
.into_iter()
.any(|info| self.associated_value(info.def_id, item_name).is_some());
let found_assoc = |ty: Ty<'tcx>| {
- simplify_type(tcx, ty, TreatParams::AsCandidateKey)
+ simplify_type(tcx, ty, TreatParams::InstantiateWithInfer)
.and_then(|simp| {
tcx.incoherent_impls(simp)
.into_iter()
@@ -3963,7 +3962,7 @@ enum Introducer {
// cases where a positive bound implies a negative impl.
(candidates, Vec::new())
} else if let Some(simp_rcvr_ty) =
- simplify_type(self.tcx, rcvr_ty, TreatParams::ForLookup)
+ simplify_type(self.tcx, rcvr_ty, TreatParams::AsRigid)
{
let mut potential_candidates = Vec::new();
let mut explicitly_negative = Vec::new();
@@ -3981,7 +3980,7 @@ enum Introducer {
.any(|header| {
let imp = header.trait_ref.instantiate_identity();
let imp_simp =
- simplify_type(self.tcx, imp.self_ty(), TreatParams::ForLookup);
+ simplify_type(self.tcx, imp.self_ty(), TreatParams::AsRigid);
imp_simp.is_some_and(|s| s == simp_rcvr_ty)
})
{
diff --git a/compiler/rustc_hir_typeck/src/upvar.rs b/compiler/rustc_hir_typeck/src/upvar.rs
index 5789e60..7688a63 100644
--- a/compiler/rustc_hir_typeck/src/upvar.rs
+++ b/compiler/rustc_hir_typeck/src/upvar.rs
@@ -39,7 +39,6 @@
use rustc_hir::def_id::LocalDefId;
use rustc_hir::intravisit::{self, Visitor};
use rustc_hir::HirId;
-use rustc_infer::infer::UpvarRegion;
use rustc_middle::hir::place::{Place, PlaceBase, PlaceWithHirId, Projection, ProjectionKind};
use rustc_middle::mir::FakeReadCause;
use rustc_middle::traits::ObligationCauseCode;
@@ -425,7 +424,11 @@ fn analyze_closure(
self.tcx,
upvar_ty,
capture,
- if needs_ref { Some(closure_env_region) } else { child_capture.region },
+ if needs_ref {
+ closure_env_region
+ } else {
+ self.tcx.lifetimes.re_erased
+ },
);
},
),
@@ -587,7 +590,12 @@ fn final_upvar_tys(&self, closure_id: LocalDefId) -> Vec<Ty<'tcx>> {
debug!(?captured_place.place, ?upvar_ty, ?capture, ?captured_place.mutability);
- apply_capture_kind_on_capture_ty(self.tcx, upvar_ty, capture, captured_place.region)
+ apply_capture_kind_on_capture_ty(
+ self.tcx,
+ upvar_ty,
+ capture,
+ self.tcx.lifetimes.re_erased,
+ )
})
.collect()
}
@@ -775,13 +783,8 @@ fn compute_min_captures(
let Some(min_cap_list) = root_var_min_capture_list.get_mut(&var_hir_id) else {
let mutability = self.determine_capture_mutability(&typeck_results, &place);
- let min_cap_list = vec![ty::CapturedPlace {
- var_ident,
- place,
- info: capture_info,
- mutability,
- region: None,
- }];
+ let min_cap_list =
+ vec![ty::CapturedPlace { var_ident, place, info: capture_info, mutability }];
root_var_min_capture_list.insert(var_hir_id, min_cap_list);
continue;
};
@@ -874,34 +877,12 @@ fn compute_min_captures(
// Only need to insert when we don't have an ancestor in the existing min capture list
if !ancestor_found {
let mutability = self.determine_capture_mutability(&typeck_results, &place);
- let captured_place = ty::CapturedPlace {
- var_ident,
- place,
- info: updated_capture_info,
- mutability,
- region: None,
- };
+ let captured_place =
+ ty::CapturedPlace { var_ident, place, info: updated_capture_info, mutability };
min_cap_list.push(captured_place);
}
}
- // For each capture that is determined to be captured by ref, add region info.
- for (_, captures) in &mut root_var_min_capture_list {
- for capture in captures {
- match capture.info.capture_kind {
- ty::UpvarCapture::ByRef(_) => {
- let PlaceBase::Upvar(upvar_id) = capture.place.base else {
- bug!("expected upvar")
- };
- let origin = UpvarRegion(upvar_id, closure_span);
- let upvar_region = self.next_region_var(origin);
- capture.region = Some(upvar_region);
- }
- _ => (),
- }
- }
- }
-
debug!(
"For closure={:?}, min_captures before sorting={:?}",
closure_def_id, root_var_min_capture_list
@@ -1195,7 +1176,7 @@ fn compute_2229_migrations_for_trait(
self.tcx,
ty,
max_capture_info.capture_kind,
- Some(self.tcx.lifetimes.re_erased),
+ self.tcx.lifetimes.re_erased,
)
}
};
@@ -1217,7 +1198,7 @@ fn compute_2229_migrations_for_trait(
self.tcx,
capture.place.ty(),
capture.info.capture_kind,
- Some(self.tcx.lifetimes.re_erased),
+ self.tcx.lifetimes.re_erased,
);
// Checks if a capture implements any of the auto traits
@@ -1935,13 +1916,11 @@ fn apply_capture_kind_on_capture_ty<'tcx>(
tcx: TyCtxt<'tcx>,
ty: Ty<'tcx>,
capture_kind: UpvarCapture,
- region: Option<ty::Region<'tcx>>,
+ region: ty::Region<'tcx>,
) -> Ty<'tcx> {
match capture_kind {
ty::UpvarCapture::ByValue => ty,
- ty::UpvarCapture::ByRef(kind) => {
- Ty::new_ref(tcx, region.unwrap(), ty, kind.to_mutbl_lossy())
- }
+ ty::UpvarCapture::ByRef(kind) => Ty::new_ref(tcx, region, ty, kind.to_mutbl_lossy()),
}
}
diff --git a/compiler/rustc_index/src/interval.rs b/compiler/rustc_index/src/interval.rs
index be028fe..34f541a 100644
--- a/compiler/rustc_index/src/interval.rs
+++ b/compiler/rustc_index/src/interval.rs
@@ -17,8 +17,8 @@
/// first value of the following element.
#[derive(Debug, Clone)]
pub struct IntervalSet<I> {
- // Start, end
- map: SmallVec<[(u32, u32); 4]>,
+ // Start, end (both inclusive)
+ map: SmallVec<[(u32, u32); 2]>,
domain: usize,
_data: PhantomData<I>,
}
diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs
index 234dc51..63a729b 100644
--- a/compiler/rustc_infer/src/infer/mod.rs
+++ b/compiler/rustc_infer/src/infer/mod.rs
@@ -458,8 +458,8 @@ pub enum RegionVariableOrigin {
PatternRegion(Span),
/// Regions created by `&` operator.
- ///
- AddrOfRegion(Span),
+ BorrowRegion(Span),
+
/// Regions created as part of an autoref of a method receiver.
Autoref(Span),
@@ -1741,7 +1741,7 @@ pub fn span(&self) -> Span {
match *self {
MiscVariable(a)
| PatternRegion(a)
- | AddrOfRegion(a)
+ | BorrowRegion(a)
| Autoref(a)
| Coercion(a)
| RegionParameterDefinition(a, ..)
diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs
index 42fed98..50422df 100644
--- a/compiler/rustc_interface/src/tests.rs
+++ b/compiler/rustc_interface/src/tests.rs
@@ -808,7 +808,7 @@ macro_rules! tracked {
tracked!(mir_opt_level, Some(4));
tracked!(move_size_limit, Some(4096));
tracked!(mutable_noalias, false);
- tracked!(next_solver, Some(NextSolverConfig { coherence: true, globally: false }));
+ tracked!(next_solver, NextSolverConfig { coherence: true, globally: true });
tracked!(no_generate_arange_section, true);
tracked!(no_jump_tables, true);
tracked!(no_link, true);
diff --git a/compiler/rustc_lexer/src/lib.rs b/compiler/rustc_lexer/src/lib.rs
index 31fdd2d..60aab66 100644
--- a/compiler/rustc_lexer/src/lib.rs
+++ b/compiler/rustc_lexer/src/lib.rs
@@ -91,6 +91,15 @@ pub enum TokenKind {
/// tokens.
UnknownPrefix,
+ /// An unknown prefix in a lifetime, like `'foo#`.
+ ///
+ /// Note that like above, only the `'` and prefix are included in the token
+ /// and not the separator.
+ UnknownPrefixLifetime,
+
+ /// `'r#lt`, which in edition < 2021 is split into several tokens: `'r # lt`.
+ RawLifetime,
+
/// Similar to the above, but *always* an error on every edition. This is used
/// for emoji identifier recovery, as those are not meant to be ever accepted.
InvalidPrefix,
@@ -677,9 +686,17 @@ fn lifetime_or_char(&mut self) -> TokenKind {
return Literal { kind, suffix_start };
}
+ if self.first() == 'r' && self.second() == '#' && is_id_start(self.third()) {
+ // Eat "r" and `#`, and identifier start characters.
+ self.bump();
+ self.bump();
+ self.bump();
+ self.eat_while(is_id_continue);
+ return RawLifetime;
+ }
+
// Either a lifetime or a character literal with
// length greater than 1.
-
let starts_with_number = self.first().is_ascii_digit();
// Skip the literal contents.
@@ -688,15 +705,17 @@ fn lifetime_or_char(&mut self) -> TokenKind {
self.bump();
self.eat_while(is_id_continue);
- // Check if after skipping literal contents we've met a closing
- // single quote (which means that user attempted to create a
- // string with single quotes).
- if self.first() == '\'' {
- self.bump();
- let kind = Char { terminated: true };
- Literal { kind, suffix_start: self.pos_within_token() }
- } else {
- Lifetime { starts_with_number }
+ match self.first() {
+ // Check if after skipping literal contents we've met a closing
+ // single quote (which means that user attempted to create a
+ // string with single quotes).
+ '\'' => {
+ self.bump();
+ let kind = Char { terminated: true };
+ Literal { kind, suffix_start: self.pos_within_token() }
+ }
+ '#' if !starts_with_number => UnknownPrefixLifetime,
+ _ => Lifetime { starts_with_number },
}
}
diff --git a/compiler/rustc_lint/messages.ftl b/compiler/rustc_lint/messages.ftl
index 3533459..7d4dee4 100644
--- a/compiler/rustc_lint/messages.ftl
+++ b/compiler/rustc_lint/messages.ftl
@@ -255,6 +255,7 @@
lint_elided_named_lifetime = elided lifetime has a name
.label_elided = this elided lifetime gets resolved as `{$name}`
.label_named = lifetime `{$name}` declared here
+ .suggestion = consider specifying it explicitly
lint_enum_intrinsics_mem_discriminant =
the return value of `mem::discriminant` is unspecified when called with a non-enum type
@@ -699,11 +700,18 @@
lint_query_instability = using `{$query}` can result in unstable query results
.note = if you believe this case to be fine, allow this lint and add a comment explaining your rationale
+lint_query_untracked = `{$method}` accesses information that is not tracked by the query system
+ .note = if you believe this case to be fine, allow this lint and add a comment explaining your rationale
+
lint_range_endpoint_out_of_range = range endpoint is out of range for `{$ty}`
lint_range_use_inclusive_range = use an inclusive range instead
+lint_raw_prefix = prefix `'r` is reserved
+ .label = reserved prefix
+ .suggestion = insert whitespace here to avoid this being parsed as a prefix in Rust 2021
+
lint_reason_must_be_string_literal = reason must be a string literal
lint_reason_must_come_last = reason in lint attribute must come last
diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs
index 5cb5195..7de92a4 100644
--- a/compiler/rustc_lint/src/builtin.rs
+++ b/compiler/rustc_lint/src/builtin.rs
@@ -1845,9 +1845,16 @@ fn check_tokens(&mut self, cx: &EarlyContext<'_>, tokens: &TokenStream) {
TokenTree::Token(token, _) => {
if let Some((ident, token::IdentIsRaw::No)) = token.ident() {
if !prev_dollar {
- self.check_ident_token(cx, UnderMacro(true), ident);
+ self.check_ident_token(cx, UnderMacro(true), ident, "");
}
- } else if *token == TokenKind::Dollar {
+ } else if let Some((ident, token::IdentIsRaw::No)) = token.lifetime() {
+ self.check_ident_token(
+ cx,
+ UnderMacro(true),
+ ident.without_first_quote(),
+ "'",
+ );
+ } else if token.kind == TokenKind::Dollar {
prev_dollar = true;
continue;
}
@@ -1863,6 +1870,7 @@ fn check_ident_token(
cx: &EarlyContext<'_>,
UnderMacro(under_macro): UnderMacro,
ident: Ident,
+ prefix: &'static str,
) {
let (lint, edition) = match ident.name {
kw::Async | kw::Await | kw::Try => (KEYWORD_IDENTS_2018, Edition::Edition2018),
@@ -1896,7 +1904,7 @@ fn check_ident_token(
cx.emit_span_lint(
lint,
ident.span,
- BuiltinKeywordIdents { kw: ident, next: edition, suggestion: ident.span },
+ BuiltinKeywordIdents { kw: ident, next: edition, suggestion: ident.span, prefix },
);
}
}
@@ -1909,7 +1917,11 @@ fn check_mac(&mut self, cx: &EarlyContext<'_>, mac: &ast::MacCall) {
self.check_tokens(cx, &mac.args.tokens);
}
fn check_ident(&mut self, cx: &EarlyContext<'_>, ident: Ident) {
- self.check_ident_token(cx, UnderMacro(false), ident);
+ if ident.name.as_str().starts_with('\'') {
+ self.check_ident_token(cx, UnderMacro(false), ident.without_first_quote(), "'");
+ } else {
+ self.check_ident_token(cx, UnderMacro(false), ident, "");
+ }
}
}
diff --git a/compiler/rustc_lint/src/context/diagnostics.rs b/compiler/rustc_lint/src/context/diagnostics.rs
index fd43afa..fd13c41 100644
--- a/compiler/rustc_lint/src/context/diagnostics.rs
+++ b/compiler/rustc_lint/src/context/diagnostics.rs
@@ -8,13 +8,13 @@
elided_lifetime_in_path_suggestion, Applicability, Diag, DiagArgValue, LintDiagnostic,
};
use rustc_middle::middle::stability;
-use rustc_session::lint::BuiltinLintDiag;
+use rustc_session::lint::{BuiltinLintDiag, ElidedLifetimeResolution};
use rustc_session::Session;
use rustc_span::symbol::kw;
use rustc_span::BytePos;
use tracing::debug;
-use crate::lints;
+use crate::lints::{self, ElidedNamedLifetime};
mod check_cfg;
@@ -172,6 +172,10 @@ pub(super) fn decorate_lint(sess: &Session, diagnostic: BuiltinLintDiag, diag: &
}
.decorate_lint(diag);
}
+ BuiltinLintDiag::RawPrefix(label_span) => {
+ lints::RawPrefix { label: label_span, suggestion: label_span.shrink_to_hi() }
+ .decorate_lint(diag);
+ }
BuiltinLintDiag::UnusedBuiltinAttribute { attr_name, macro_name, invoc_span } => {
lints::UnusedBuiltinAttribute { invoc_span, attr_name, macro_name }.decorate_lint(diag);
}
@@ -442,15 +446,14 @@ pub(super) fn decorate_lint(sess: &Session, diagnostic: BuiltinLintDiag, diag: &
BuiltinLintDiag::UnexpectedBuiltinCfg { cfg, cfg_name, controlled_by } => {
lints::UnexpectedBuiltinCfg { cfg, cfg_name, controlled_by }.decorate_lint(diag)
}
- BuiltinLintDiag::ElidedIsStatic { elided } => {
- lints::ElidedNamedLifetime { elided, name: kw::StaticLifetime, named_declaration: None }
- .decorate_lint(diag)
- }
- BuiltinLintDiag::ElidedIsParam { elided, param: (param_name, param_span) } => {
- lints::ElidedNamedLifetime {
- elided,
- name: param_name,
- named_declaration: Some(param_span),
+ BuiltinLintDiag::ElidedNamedLifetimes { elided: (span, kind), resolution } => {
+ match resolution {
+ ElidedLifetimeResolution::Static => {
+ ElidedNamedLifetime { span, kind, name: kw::StaticLifetime, declaration: None }
+ }
+ ElidedLifetimeResolution::Param(name, declaration) => {
+ ElidedNamedLifetime { span, kind, name, declaration: Some(declaration) }
+ }
}
.decorate_lint(diag)
}
diff --git a/compiler/rustc_lint/src/impl_trait_overcaptures.rs b/compiler/rustc_lint/src/impl_trait_overcaptures.rs
index 8824e1d..c43c650 100644
--- a/compiler/rustc_lint/src/impl_trait_overcaptures.rs
+++ b/compiler/rustc_lint/src/impl_trait_overcaptures.rs
@@ -1,19 +1,29 @@
-use rustc_data_structures::fx::FxIndexSet;
+use std::assert_matches::debug_assert_matches;
+use std::cell::LazyCell;
+
+use rustc_data_structures::fx::{FxHashMap, FxIndexMap, FxIndexSet};
use rustc_data_structures::unord::UnordSet;
use rustc_errors::{Applicability, LintDiagnostic};
use rustc_hir as hir;
use rustc_hir::def::DefKind;
use rustc_hir::def_id::{DefId, LocalDefId};
+use rustc_infer::infer::outlives::env::OutlivesEnvironment;
+use rustc_infer::infer::TyCtxtInferExt;
use rustc_macros::LintDiagnostic;
-use rustc_middle::bug;
use rustc_middle::middle::resolve_bound_vars::ResolvedArg;
+use rustc_middle::ty::relate::{
+ structurally_relate_consts, structurally_relate_tys, Relate, RelateResult, TypeRelation,
+};
use rustc_middle::ty::{
self, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor,
};
+use rustc_middle::{bug, span_bug};
use rustc_session::lint::FutureIncompatibilityReason;
use rustc_session::{declare_lint, declare_lint_pass};
use rustc_span::edition::Edition;
-use rustc_span::Span;
+use rustc_span::{Span, Symbol};
+use rustc_trait_selection::traits::outlives_bounds::InferCtxtExt;
+use rustc_trait_selection::traits::ObligationCtxt;
use crate::{fluent_generated as fluent, LateContext, LateLintPass};
@@ -119,20 +129,41 @@ fn check_trait_item(&mut self, cx: &LateContext<'tcx>, it: &'tcx hir::TraitItem<
}
}
+#[derive(PartialEq, Eq, Hash, Debug, Copy, Clone)]
+enum ParamKind {
+ // Early-bound var.
+ Early(Symbol, u32),
+ // Late-bound var on function, not within a binder. We can capture these.
+ Free(DefId, Symbol),
+ // Late-bound var in a binder. We can't capture these yet.
+ Late,
+}
+
fn check_fn(tcx: TyCtxt<'_>, parent_def_id: LocalDefId) {
let sig = tcx.fn_sig(parent_def_id).instantiate_identity();
- let mut in_scope_parameters = FxIndexSet::default();
+ let mut in_scope_parameters = FxIndexMap::default();
// Populate the in_scope_parameters list first with all of the generics in scope
let mut current_def_id = Some(parent_def_id.to_def_id());
while let Some(def_id) = current_def_id {
let generics = tcx.generics_of(def_id);
for param in &generics.own_params {
- in_scope_parameters.insert(param.def_id);
+ in_scope_parameters.insert(param.def_id, ParamKind::Early(param.name, param.index));
}
current_def_id = generics.parent;
}
+ for bound_var in sig.bound_vars() {
+ let ty::BoundVariableKind::Region(ty::BoundRegionKind::BrNamed(def_id, name)) = bound_var
+ else {
+ span_bug!(tcx.def_span(parent_def_id), "unexpected non-lifetime binder on fn sig");
+ };
+
+ in_scope_parameters.insert(def_id, ParamKind::Free(def_id, name));
+ }
+
+ let sig = tcx.liberate_late_bound_regions(parent_def_id.to_def_id(), sig);
+
// Then visit the signature to walk through all the binders (incl. the late-bound
// vars on the function itself, which we need to count too).
sig.visit_with(&mut VisitOpaqueTypes {
@@ -140,21 +171,45 @@ fn check_fn(tcx: TyCtxt<'_>, parent_def_id: LocalDefId) {
parent_def_id,
in_scope_parameters,
seen: Default::default(),
+ // Lazily compute these two, since they're likely a bit expensive.
+ variances: LazyCell::new(|| {
+ let mut functional_variances = FunctionalVariances {
+ tcx: tcx,
+ variances: FxHashMap::default(),
+ ambient_variance: ty::Covariant,
+ generics: tcx.generics_of(parent_def_id),
+ };
+ functional_variances.relate(sig, sig).unwrap();
+ functional_variances.variances
+ }),
+ outlives_env: LazyCell::new(|| {
+ let param_env = tcx.param_env(parent_def_id);
+ let infcx = tcx.infer_ctxt().build();
+ let ocx = ObligationCtxt::new(&infcx);
+ let assumed_wf_tys = ocx.assumed_wf_types(param_env, parent_def_id).unwrap_or_default();
+ let implied_bounds =
+ infcx.implied_bounds_tys_compat(param_env, parent_def_id, &assumed_wf_tys, false);
+ OutlivesEnvironment::with_bounds(param_env, implied_bounds)
+ }),
});
}
-struct VisitOpaqueTypes<'tcx> {
+struct VisitOpaqueTypes<'tcx, VarFn, OutlivesFn> {
tcx: TyCtxt<'tcx>,
parent_def_id: LocalDefId,
- in_scope_parameters: FxIndexSet<DefId>,
+ in_scope_parameters: FxIndexMap<DefId, ParamKind>,
+ variances: LazyCell<FxHashMap<DefId, ty::Variance>, VarFn>,
+ outlives_env: LazyCell<OutlivesEnvironment<'tcx>, OutlivesFn>,
seen: FxIndexSet<LocalDefId>,
}
-impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for VisitOpaqueTypes<'tcx> {
- fn visit_binder<T: TypeVisitable<TyCtxt<'tcx>>>(
- &mut self,
- t: &ty::Binder<'tcx, T>,
- ) -> Self::Result {
+impl<'tcx, VarFn, OutlivesFn> TypeVisitor<TyCtxt<'tcx>>
+ for VisitOpaqueTypes<'tcx, VarFn, OutlivesFn>
+where
+ VarFn: FnOnce() -> FxHashMap<DefId, ty::Variance>,
+ OutlivesFn: FnOnce() -> OutlivesEnvironment<'tcx>,
+{
+ fn visit_binder<T: TypeVisitable<TyCtxt<'tcx>>>(&mut self, t: &ty::Binder<'tcx, T>) {
// When we get into a binder, we need to add its own bound vars to the scope.
let mut added = vec![];
for arg in t.bound_vars() {
@@ -163,8 +218,8 @@ fn visit_binder<T: TypeVisitable<TyCtxt<'tcx>>>(
ty::BoundVariableKind::Region(ty::BoundRegionKind::BrNamed(def_id, ..))
| ty::BoundVariableKind::Ty(ty::BoundTyKind::Param(def_id, _)) => {
added.push(def_id);
- let unique = self.in_scope_parameters.insert(def_id);
- assert!(unique);
+ let unique = self.in_scope_parameters.insert(def_id, ParamKind::Late);
+ assert_eq!(unique, None);
}
_ => {
self.tcx.dcx().span_delayed_bug(
@@ -184,7 +239,7 @@ fn visit_binder<T: TypeVisitable<TyCtxt<'tcx>>>(
}
}
- fn visit_ty(&mut self, t: Ty<'tcx>) -> Self::Result {
+ fn visit_ty(&mut self, t: Ty<'tcx>) {
if !t.has_aliases() {
return;
}
@@ -207,89 +262,126 @@ fn visit_ty(&mut self, t: Ty<'tcx>) -> Self::Result {
&& let hir::OpaqueTyOrigin::FnReturn(parent_def_id) = opaque.origin
&& parent_def_id == self.parent_def_id
{
- // Compute the set of args that are captured by the opaque...
- let mut captured = FxIndexSet::default();
- let variances = self.tcx.variances_of(opaque_def_id);
- let mut current_def_id = Some(opaque_def_id.to_def_id());
- while let Some(def_id) = current_def_id {
- let generics = self.tcx.generics_of(def_id);
- for param in &generics.own_params {
- // A param is captured if it's invariant.
- if variances[param.index as usize] != ty::Invariant {
- continue;
- }
- // We need to turn all `ty::Param`/`ConstKind::Param` and
- // `ReEarlyParam`/`ReBound` into def ids.
- captured.insert(extract_def_id_from_arg(
- self.tcx,
- generics,
- opaque_ty.args[param.index as usize],
- ));
- }
- current_def_id = generics.parent;
- }
-
- // Compute the set of in scope params that are not captured. Get their spans,
- // since that's all we really care about them for emitting the diagnostic.
- let uncaptured_spans: Vec<_> = self
- .in_scope_parameters
- .iter()
- .filter(|def_id| !captured.contains(*def_id))
- .map(|def_id| self.tcx.def_span(def_id))
- .collect();
-
let opaque_span = self.tcx.def_span(opaque_def_id);
let new_capture_rules =
opaque_span.at_least_rust_2024() || self.tcx.features().lifetime_capture_rules_2024;
-
- // If we have uncaptured args, and if the opaque doesn't already have
- // `use<>` syntax on it, and we're < edition 2024, then warn the user.
if !new_capture_rules
&& !opaque.bounds.iter().any(|bound| matches!(bound, hir::GenericBound::Use(..)))
- && !uncaptured_spans.is_empty()
{
- let suggestion = if let Ok(snippet) =
- self.tcx.sess.source_map().span_to_snippet(opaque_span)
- && snippet.starts_with("impl ")
- {
- let (lifetimes, others): (Vec<_>, Vec<_>) = captured
- .into_iter()
- .partition(|def_id| self.tcx.def_kind(*def_id) == DefKind::LifetimeParam);
- // Take all lifetime params first, then all others (ty/ct).
- let generics: Vec<_> = lifetimes
- .into_iter()
- .chain(others)
- .map(|def_id| self.tcx.item_name(def_id).to_string())
- .collect();
- // Make sure that we're not trying to name any APITs
- if generics.iter().all(|name| !name.starts_with("impl ")) {
- Some((
- format!(" + use<{}>", generics.join(", ")),
- opaque_span.shrink_to_hi(),
- ))
+ // Compute the set of args that are captured by the opaque...
+ let mut captured = FxIndexSet::default();
+ let mut captured_regions = FxIndexSet::default();
+ let variances = self.tcx.variances_of(opaque_def_id);
+ let mut current_def_id = Some(opaque_def_id.to_def_id());
+ while let Some(def_id) = current_def_id {
+ let generics = self.tcx.generics_of(def_id);
+ for param in &generics.own_params {
+ // A param is captured if it's invariant.
+ if variances[param.index as usize] != ty::Invariant {
+ continue;
+ }
+
+ let arg = opaque_ty.args[param.index as usize];
+ // We need to turn all `ty::Param`/`ConstKind::Param` and
+ // `ReEarlyParam`/`ReBound` into def ids.
+ captured.insert(extract_def_id_from_arg(self.tcx, generics, arg));
+
+ captured_regions.extend(arg.as_region());
+ }
+ current_def_id = generics.parent;
+ }
+
+ // Compute the set of in scope params that are not captured.
+ let mut uncaptured_args: FxIndexSet<_> = self
+ .in_scope_parameters
+ .iter()
+ .filter(|&(def_id, _)| !captured.contains(def_id))
+ .collect();
+ // Remove the set of lifetimes that are in-scope that outlive some other captured
+ // lifetime and are contravariant (i.e. covariant in argument position).
+ uncaptured_args.retain(|&(def_id, kind)| {
+ let Some(ty::Bivariant | ty::Contravariant) = self.variances.get(def_id) else {
+ // Keep all covariant/invariant args. Also if variance is `None`,
+ // then that means it's either not a lifetime, or it didn't show up
+ // anywhere in the signature.
+ return true;
+ };
+ // We only computed variance of lifetimes...
+ debug_assert_matches!(self.tcx.def_kind(def_id), DefKind::LifetimeParam);
+ let uncaptured = match *kind {
+ ParamKind::Early(name, index) => ty::Region::new_early_param(
+ self.tcx,
+ ty::EarlyParamRegion { name, index },
+ ),
+ ParamKind::Free(def_id, name) => ty::Region::new_late_param(
+ self.tcx,
+ self.parent_def_id.to_def_id(),
+ ty::BoundRegionKind::BrNamed(def_id, name),
+ ),
+ // Totally ignore late bound args from binders.
+ ParamKind::Late => return true,
+ };
+ // Does this region outlive any captured region?
+ !captured_regions.iter().any(|r| {
+ self.outlives_env
+ .free_region_map()
+ .sub_free_regions(self.tcx, *r, uncaptured)
+ })
+ });
+
+ // If we have uncaptured args, and if the opaque doesn't already have
+ // `use<>` syntax on it, and we're < edition 2024, then warn the user.
+ if !uncaptured_args.is_empty() {
+ let suggestion = if let Ok(snippet) =
+ self.tcx.sess.source_map().span_to_snippet(opaque_span)
+ && snippet.starts_with("impl ")
+ {
+ let (lifetimes, others): (Vec<_>, Vec<_>) =
+ captured.into_iter().partition(|def_id| {
+ self.tcx.def_kind(*def_id) == DefKind::LifetimeParam
+ });
+ // Take all lifetime params first, then all others (ty/ct).
+ let generics: Vec<_> = lifetimes
+ .into_iter()
+ .chain(others)
+ .map(|def_id| self.tcx.item_name(def_id).to_string())
+ .collect();
+ // Make sure that we're not trying to name any APITs
+ if generics.iter().all(|name| !name.starts_with("impl ")) {
+ Some((
+ format!(" + use<{}>", generics.join(", ")),
+ opaque_span.shrink_to_hi(),
+ ))
+ } else {
+ None
+ }
} else {
None
- }
- } else {
- None
- };
+ };
- self.tcx.emit_node_span_lint(
- IMPL_TRAIT_OVERCAPTURES,
- self.tcx.local_def_id_to_hir_id(opaque_def_id),
- opaque_span,
- ImplTraitOvercapturesLint {
- self_ty: t,
- num_captured: uncaptured_spans.len(),
- uncaptured_spans,
- suggestion,
- },
- );
+ let uncaptured_spans: Vec<_> = uncaptured_args
+ .into_iter()
+ .map(|(def_id, _)| self.tcx.def_span(def_id))
+ .collect();
+
+ self.tcx.emit_node_span_lint(
+ IMPL_TRAIT_OVERCAPTURES,
+ self.tcx.local_def_id_to_hir_id(opaque_def_id),
+ opaque_span,
+ ImplTraitOvercapturesLint {
+ self_ty: t,
+ num_captured: uncaptured_spans.len(),
+ uncaptured_spans,
+ suggestion,
+ },
+ );
+ }
}
+
// Otherwise, if we are edition 2024, have `use<>` syntax, and
// have no uncaptured args, then we should warn to the user that
// it's redundant to capture all args explicitly.
- else if new_capture_rules
+ if new_capture_rules
&& let Some((captured_args, capturing_span)) =
opaque.bounds.iter().find_map(|bound| match *bound {
hir::GenericBound::Use(a, s) => Some((a, s)),
@@ -327,7 +419,7 @@ fn visit_ty(&mut self, t: Ty<'tcx>) -> Self::Result {
if self
.in_scope_parameters
.iter()
- .all(|def_id| explicitly_captured.contains(def_id))
+ .all(|(def_id, _)| explicitly_captured.contains(def_id))
{
self.tcx.emit_node_span_lint(
IMPL_TRAIT_REDUNDANT_CAPTURES,
@@ -396,7 +488,11 @@ fn extract_def_id_from_arg<'tcx>(
ty::ReBound(
_,
ty::BoundRegion { kind: ty::BoundRegionKind::BrNamed(def_id, ..), .. },
- ) => def_id,
+ )
+ | ty::ReLateParam(ty::LateParamRegion {
+ scope: _,
+ bound_region: ty::BoundRegionKind::BrNamed(def_id, ..),
+ }) => def_id,
_ => unreachable!(),
},
ty::GenericArgKind::Type(ty) => {
@@ -413,3 +509,106 @@ fn extract_def_id_from_arg<'tcx>(
}
}
}
+
+/// Computes the variances of regions that appear in the type, but considering
+/// late-bound regions too, which don't have their variance computed usually.
+///
+/// Like generalization, this is a unary operation implemented on top of the binary
+/// relation infrastructure, mostly because it's much easier to have the relation
+/// track the variance for you, rather than having to do it yourself.
+struct FunctionalVariances<'tcx> {
+ tcx: TyCtxt<'tcx>,
+ variances: FxHashMap<DefId, ty::Variance>,
+ ambient_variance: ty::Variance,
+ generics: &'tcx ty::Generics,
+}
+
+impl<'tcx> TypeRelation<TyCtxt<'tcx>> for FunctionalVariances<'tcx> {
+ fn cx(&self) -> TyCtxt<'tcx> {
+ self.tcx
+ }
+
+ fn relate_with_variance<T: ty::relate::Relate<TyCtxt<'tcx>>>(
+ &mut self,
+ variance: rustc_type_ir::Variance,
+ _: ty::VarianceDiagInfo<TyCtxt<'tcx>>,
+ a: T,
+ b: T,
+ ) -> RelateResult<'tcx, T> {
+ let old_variance = self.ambient_variance;
+ self.ambient_variance = self.ambient_variance.xform(variance);
+ self.relate(a, b).unwrap();
+ self.ambient_variance = old_variance;
+ Ok(a)
+ }
+
+ fn tys(&mut self, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> {
+ structurally_relate_tys(self, a, b).unwrap();
+ Ok(a)
+ }
+
+ fn regions(
+ &mut self,
+ a: ty::Region<'tcx>,
+ _: ty::Region<'tcx>,
+ ) -> RelateResult<'tcx, ty::Region<'tcx>> {
+ let def_id = match *a {
+ ty::ReEarlyParam(ebr) => self.generics.region_param(ebr, self.tcx).def_id,
+ ty::ReBound(
+ _,
+ ty::BoundRegion { kind: ty::BoundRegionKind::BrNamed(def_id, ..), .. },
+ )
+ | ty::ReLateParam(ty::LateParamRegion {
+ scope: _,
+ bound_region: ty::BoundRegionKind::BrNamed(def_id, ..),
+ }) => def_id,
+ _ => {
+ return Ok(a);
+ }
+ };
+
+ if let Some(variance) = self.variances.get_mut(&def_id) {
+ *variance = unify(*variance, self.ambient_variance);
+ } else {
+ self.variances.insert(def_id, self.ambient_variance);
+ }
+
+ Ok(a)
+ }
+
+ fn consts(
+ &mut self,
+ a: ty::Const<'tcx>,
+ b: ty::Const<'tcx>,
+ ) -> RelateResult<'tcx, ty::Const<'tcx>> {
+ structurally_relate_consts(self, a, b).unwrap();
+ Ok(a)
+ }
+
+ fn binders<T>(
+ &mut self,
+ a: ty::Binder<'tcx, T>,
+ b: ty::Binder<'tcx, T>,
+ ) -> RelateResult<'tcx, ty::Binder<'tcx, T>>
+ where
+ T: Relate<TyCtxt<'tcx>>,
+ {
+ self.relate(a.skip_binder(), b.skip_binder()).unwrap();
+ Ok(a)
+ }
+}
+
+/// What is the variance that satisfies the two variances?
+fn unify(a: ty::Variance, b: ty::Variance) -> ty::Variance {
+ match (a, b) {
+ // Bivariance is lattice bottom.
+ (ty::Bivariant, other) | (other, ty::Bivariant) => other,
+ // Invariant is lattice top.
+ (ty::Invariant, _) | (_, ty::Invariant) => ty::Invariant,
+ // If type is required to be covariant and contravariant, then it's invariant.
+ (ty::Contravariant, ty::Covariant) | (ty::Covariant, ty::Contravariant) => ty::Invariant,
+ // Otherwise, co + co = co, contra + contra = contra.
+ (ty::Contravariant, ty::Contravariant) => ty::Contravariant,
+ (ty::Covariant, ty::Covariant) => ty::Covariant,
+ }
+}
diff --git a/compiler/rustc_lint/src/internal.rs b/compiler/rustc_lint/src/internal.rs
index 2e8116b..9d637c1 100644
--- a/compiler/rustc_lint/src/internal.rs
+++ b/compiler/rustc_lint/src/internal.rs
@@ -17,8 +17,8 @@
use crate::lints::{
BadOptAccessDiag, DefaultHashTypesDiag, DiagOutOfImpl, LintPassByHand, NonExistentDocKeyword,
- NonGlobImportTypeIrInherent, QueryInstability, SpanUseEqCtxtDiag, TyQualified, TykindDiag,
- TykindKind, TypeIrInherentUsage, UntranslatableDiag,
+ NonGlobImportTypeIrInherent, QueryInstability, QueryUntracked, SpanUseEqCtxtDiag, TyQualified,
+ TykindDiag, TykindKind, TypeIrInherentUsage, UntranslatableDiag,
};
use crate::{EarlyContext, EarlyLintPass, LateContext, LateLintPass, LintContext};
@@ -88,7 +88,18 @@ fn typeck_results_of_method_fn<'tcx>(
report_in_external_macro: true
}
-declare_lint_pass!(QueryStability => [POTENTIAL_QUERY_INSTABILITY]);
+declare_tool_lint! {
+ /// The `untracked_query_information` lint detects use of methods which leak information not
+ /// tracked by the query system, such as whether a `Steal<T>` value has already been stolen. In
+ /// order not to break incremental compilation, such methods must be used very carefully or not
+ /// at all.
+ pub rustc::UNTRACKED_QUERY_INFORMATION,
+ Allow,
+ "require explicit opt-in when accessing information not tracked by the query system",
+ report_in_external_macro: true
+}
+
+declare_lint_pass!(QueryStability => [POTENTIAL_QUERY_INSTABILITY, UNTRACKED_QUERY_INFORMATION]);
impl LateLintPass<'_> for QueryStability {
fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) {
@@ -102,6 +113,13 @@ fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) {
QueryInstability { query: cx.tcx.item_name(def_id) },
);
}
+ if cx.tcx.has_attr(def_id, sym::rustc_lint_untracked_query_information) {
+ cx.emit_span_lint(
+ UNTRACKED_QUERY_INFORMATION,
+ span,
+ QueryUntracked { method: cx.tcx.item_name(def_id) },
+ );
+ }
}
}
}
diff --git a/compiler/rustc_lint/src/lib.rs b/compiler/rustc_lint/src/lib.rs
index c5a5c5b..a9627e9 100644
--- a/compiler/rustc_lint/src/lib.rs
+++ b/compiler/rustc_lint/src/lib.rs
@@ -30,6 +30,7 @@
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
#![doc(rust_logo)]
#![feature(array_windows)]
+#![feature(assert_matches)]
#![feature(box_patterns)]
#![feature(control_flow_enum)]
#![feature(extract_if)]
@@ -609,6 +610,7 @@ fn register_internals(store: &mut LintStore) {
vec![
LintId::of(DEFAULT_HASH_TYPES),
LintId::of(POTENTIAL_QUERY_INSTABILITY),
+ LintId::of(UNTRACKED_QUERY_INFORMATION),
LintId::of(USAGE_OF_TY_TYKIND),
LintId::of(PASS_BY_VALUE),
LintId::of(LINT_PASS_IMPL_WITHOUT_MACRO),
diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs
index 7ca282b..e49b102 100644
--- a/compiler/rustc_lint/src/lints.rs
+++ b/compiler/rustc_lint/src/lints.rs
@@ -9,7 +9,7 @@
};
use rustc_hir::def::Namespace;
use rustc_hir::def_id::DefId;
-use rustc_hir::{self as hir};
+use rustc_hir::{self as hir, MissingLifetimeKind};
use rustc_macros::{LintDiagnostic, Subdiagnostic};
use rustc_middle::ty::inhabitedness::InhabitedPredicate;
use rustc_middle::ty::{Clause, PolyExistentialTraitRef, Ty, TyCtxt};
@@ -363,8 +363,9 @@ pub(crate) enum BuiltinEllipsisInclusiveRangePatternsLint {
pub(crate) struct BuiltinKeywordIdents {
pub kw: Ident,
pub next: Edition,
- #[suggestion(code = "r#{kw}", applicability = "machine-applicable")]
+ #[suggestion(code = "{prefix}r#{kw}", applicability = "machine-applicable")]
pub suggestion: Span,
+ pub prefix: &'static str,
}
#[derive(LintDiagnostic)]
@@ -895,6 +896,13 @@ pub(crate) struct QueryInstability {
}
#[derive(LintDiagnostic)]
+#[diag(lint_query_untracked)]
+#[note]
+pub(crate) struct QueryUntracked {
+ pub method: Symbol,
+}
+
+#[derive(LintDiagnostic)]
#[diag(lint_span_use_eq_ctxt)]
pub(crate) struct SpanUseEqCtxtDiag;
@@ -2616,14 +2624,56 @@ pub(crate) struct ElidedLifetimesInPaths {
pub subdiag: ElidedLifetimeInPathSubdiag,
}
-#[derive(LintDiagnostic)]
-#[diag(lint_elided_named_lifetime)]
pub(crate) struct ElidedNamedLifetime {
- #[label(lint_label_elided)]
- pub elided: Span,
+ pub span: Span,
+ pub kind: MissingLifetimeKind,
pub name: Symbol,
- #[label(lint_label_named)]
- pub named_declaration: Option<Span>,
+ pub declaration: Option<Span>,
+}
+
+impl<G: EmissionGuarantee> LintDiagnostic<'_, G> for ElidedNamedLifetime {
+ fn decorate_lint(self, diag: &mut rustc_errors::Diag<'_, G>) {
+ let Self { span, kind, name, declaration } = self;
+ diag.primary_message(fluent::lint_elided_named_lifetime);
+ diag.arg("name", name);
+ diag.span_label(span, fluent::lint_label_elided);
+ if let Some(declaration) = declaration {
+ diag.span_label(declaration, fluent::lint_label_named);
+ }
+ // FIXME(GrigorenkoPV): this `if` and `return` should be removed,
+ // but currently this lint's suggestions can conflict with those of `clippy::needless_lifetimes`:
+ // https://github.com/rust-lang/rust/pull/129840#issuecomment-2323349119
+ // HACK: `'static` suggestions will never sonflict, emit only those for now.
+ if name != rustc_span::symbol::kw::StaticLifetime {
+ return;
+ }
+ match kind {
+ MissingLifetimeKind::Underscore => diag.span_suggestion_verbose(
+ span,
+ fluent::lint_suggestion,
+ format!("{name}"),
+ Applicability::MachineApplicable,
+ ),
+ MissingLifetimeKind::Ampersand => diag.span_suggestion_verbose(
+ span.shrink_to_hi(),
+ fluent::lint_suggestion,
+ format!("{name} "),
+ Applicability::MachineApplicable,
+ ),
+ MissingLifetimeKind::Comma => diag.span_suggestion_verbose(
+ span.shrink_to_hi(),
+ fluent::lint_suggestion,
+ format!("{name}, "),
+ Applicability::MachineApplicable,
+ ),
+ MissingLifetimeKind::Brackets => diag.span_suggestion_verbose(
+ span.shrink_to_hi(),
+ fluent::lint_suggestion,
+ format!("<{name}>"),
+ Applicability::MachineApplicable,
+ ),
+ };
+ }
}
#[derive(LintDiagnostic)]
@@ -2766,6 +2816,15 @@ pub(crate) struct ReservedPrefix {
}
#[derive(LintDiagnostic)]
+#[diag(lint_raw_prefix)]
+pub(crate) struct RawPrefix {
+ #[label]
+ pub label: Span,
+ #[suggestion(code = " ", applicability = "machine-applicable")]
+ pub suggestion: Span,
+}
+
+#[derive(LintDiagnostic)]
#[diag(lint_unused_builtin_attribute)]
pub(crate) struct UnusedBuiltinAttribute {
#[note]
diff --git a/compiler/rustc_lint/src/shadowed_into_iter.rs b/compiler/rustc_lint/src/shadowed_into_iter.rs
index bb9c7d8..bb12250 100644
--- a/compiler/rustc_lint/src/shadowed_into_iter.rs
+++ b/compiler/rustc_lint/src/shadowed_into_iter.rs
@@ -94,12 +94,9 @@ fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'tcx>) {
fn is_ref_to_array(ty: Ty<'_>) -> bool {
if let ty::Ref(_, pointee_ty, _) = *ty.kind() { pointee_ty.is_array() } else { false }
}
- fn is_boxed_slice(ty: Ty<'_>) -> bool {
- ty.is_box() && ty.boxed_ty().is_slice()
- }
fn is_ref_to_boxed_slice(ty: Ty<'_>) -> bool {
if let ty::Ref(_, pointee_ty, _) = *ty.kind() {
- is_boxed_slice(pointee_ty)
+ pointee_ty.boxed_ty().is_some_and(Ty::is_slice)
} else {
false
}
@@ -119,7 +116,7 @@ fn is_ref_to_boxed_slice(ty: Ty<'_>) -> bool {
.iter()
.copied()
.take_while(|ty| !is_ref_to_boxed_slice(*ty))
- .position(|ty| is_boxed_slice(ty))
+ .position(|ty| ty.boxed_ty().is_some_and(Ty::is_slice))
{
(BOXED_SLICE_INTO_ITER, "Box<[T]>", "2024", idx == 0)
} else {
diff --git a/compiler/rustc_lint/src/types.rs b/compiler/rustc_lint/src/types.rs
index f2f7c0e..b5e501b 100644
--- a/compiler/rustc_lint/src/types.rs
+++ b/compiler/rustc_lint/src/types.rs
@@ -1304,8 +1304,10 @@ fn check_type_for_ffi(
match *ty.kind() {
ty::Adt(def, args) => {
- if def.is_box() && matches!(self.mode, CItemKind::Definition) {
- if ty.boxed_ty().is_sized(tcx, self.cx.param_env) {
+ if let Some(boxed) = ty.boxed_ty()
+ && matches!(self.mode, CItemKind::Definition)
+ {
+ if boxed.is_sized(tcx, self.cx.param_env) {
return FfiSafe;
} else {
return FfiUnsafe {
diff --git a/compiler/rustc_lint/src/unused.rs b/compiler/rustc_lint/src/unused.rs
index 761d30b..b7f7b78 100644
--- a/compiler/rustc_lint/src/unused.rs
+++ b/compiler/rustc_lint/src/unused.rs
@@ -283,9 +283,8 @@ fn is_ty_must_use<'tcx>(
}
match *ty.kind() {
- ty::Adt(..) if ty.is_box() => {
- let boxed_ty = ty.boxed_ty();
- is_ty_must_use(cx, boxed_ty, expr, span)
+ ty::Adt(..) if let Some(boxed) = ty.boxed_ty() => {
+ is_ty_must_use(cx, boxed, expr, span)
.map(|inner| MustUsePath::Boxed(Box::new(inner)))
}
ty::Adt(def, args) if cx.tcx.is_lang_item(def.did(), LangItem::Pin) => {
diff --git a/compiler/rustc_lint_defs/src/lib.rs b/compiler/rustc_lint_defs/src/lib.rs
index 6ee3304..5c4b7e5 100644
--- a/compiler/rustc_lint_defs/src/lib.rs
+++ b/compiler/rustc_lint_defs/src/lib.rs
@@ -10,7 +10,7 @@
};
use rustc_error_messages::{DiagMessage, MultiSpan};
use rustc_hir::def::Namespace;
-use rustc_hir::{HashStableContext, HirId};
+use rustc_hir::{HashStableContext, HirId, MissingLifetimeKind};
use rustc_macros::{Decodable, Encodable, HashStable_Generic};
use rustc_span::edition::Edition;
use rustc_span::symbol::{Ident, MacroRulesNormalizedIdent};
@@ -556,6 +556,12 @@ pub enum DeprecatedSinceKind {
InVersion(String),
}
+#[derive(Debug)]
+pub enum ElidedLifetimeResolution {
+ Static,
+ Param(Symbol, Span),
+}
+
// This could be a closure, but then implementing derive trait
// becomes hacky (and it gets allocated).
#[derive(Debug)]
@@ -568,12 +574,9 @@ pub enum BuiltinLintDiag {
},
MacroExpandedMacroExportsAccessedByAbsolutePaths(Span),
ElidedLifetimesInPaths(usize, Span, bool, Span),
- ElidedIsStatic {
- elided: Span,
- },
- ElidedIsParam {
- elided: Span,
- param: (Symbol, Span),
+ ElidedNamedLifetimes {
+ elided: (Span, MissingLifetimeKind),
+ resolution: ElidedLifetimeResolution,
},
UnknownCrateTypes {
span: Span,
@@ -609,6 +612,8 @@ pub enum BuiltinLintDiag {
LegacyDeriveHelpers(Span),
OrPatternsBackCompat(Span, String),
ReservedPrefix(Span, String),
+ /// `'r#` in edition < 2021.
+ RawPrefix(Span),
TrailingMacro(bool, Ident),
BreakWithLabelAndLoop(Span),
UnicodeTextFlow(Span, String),
diff --git a/compiler/rustc_llvm/src/lib.rs b/compiler/rustc_llvm/src/lib.rs
index 3532d50..055d2bd 100644
--- a/compiler/rustc_llvm/src/lib.rs
+++ b/compiler/rustc_llvm/src/lib.rs
@@ -1,6 +1,5 @@
// tidy-alphabetical-start
#![allow(internal_features)]
-#![cfg_attr(bootstrap, feature(unsafe_attributes, unsafe_extern_blocks))]
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
#![doc(rust_logo)]
#![feature(rustdoc_internals)]
diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs
index c55583b..b617d52 100644
--- a/compiler/rustc_metadata/src/rmeta/encoder.rs
+++ b/compiler/rustc_metadata/src/rmeta/encoder.rs
@@ -9,6 +9,7 @@
use rustc_data_structures::memmap::{Mmap, MmapMut};
use rustc_data_structures::sync::{join, par_for_each_in, Lrc};
use rustc_data_structures::temp_dir::MaybeTempDir;
+use rustc_feature::Features;
use rustc_hir as hir;
use rustc_hir::def_id::{LocalDefId, LocalDefIdSet, CRATE_DEF_ID, CRATE_DEF_INDEX, LOCAL_CRATE};
use rustc_hir::definitions::DefPathData;
@@ -797,9 +798,10 @@ macro_rules! stat {
}
}
-struct AnalyzeAttrState {
+struct AnalyzeAttrState<'a> {
is_exported: bool,
is_doc_hidden: bool,
+ features: &'a Features,
}
/// Returns whether an attribute needs to be recorded in metadata, that is, if it's usable and
@@ -812,7 +814,7 @@ struct AnalyzeAttrState {
/// visibility: this is a piece of data that can be computed once per defid, and not once per
/// attribute. Some attributes would only be usable downstream if they are public.
#[inline]
-fn analyze_attr(attr: &Attribute, state: &mut AnalyzeAttrState) -> bool {
+fn analyze_attr(attr: &Attribute, state: &mut AnalyzeAttrState<'_>) -> bool {
let mut should_encode = false;
if !rustc_feature::encode_cross_crate(attr.name_or_empty()) {
// Attributes not marked encode-cross-crate don't need to be encoded for downstream crates.
@@ -837,6 +839,9 @@ fn analyze_attr(attr: &Attribute, state: &mut AnalyzeAttrState) -> bool {
}
}
}
+ } else if attr.path().starts_with(&[sym::diagnostic]) && attr.path().len() == 2 {
+ should_encode =
+ rustc_feature::is_stable_diagnostic_attribute(attr.path()[1], state.features);
} else {
should_encode = true;
}
@@ -1343,6 +1348,7 @@ fn encode_attrs(&mut self, def_id: LocalDefId) {
let mut state = AnalyzeAttrState {
is_exported: tcx.effective_visibilities(()).is_exported(def_id),
is_doc_hidden: false,
+ features: &tcx.features(),
};
let attr_iter = tcx
.hir()
@@ -2033,7 +2039,7 @@ fn encode_impls(&mut self) -> LazyArray<TraitImpls> {
let simplified_self_ty = fast_reject::simplify_type(
self.tcx,
trait_ref.self_ty(),
- TreatParams::AsCandidateKey,
+ TreatParams::InstantiateWithInfer,
);
trait_impls
.entry(trait_ref.def_id)
diff --git a/compiler/rustc_middle/src/lib.rs b/compiler/rustc_middle/src/lib.rs
index 2a85f85..fd6e2ad 100644
--- a/compiler/rustc_middle/src/lib.rs
+++ b/compiler/rustc_middle/src/lib.rs
@@ -28,7 +28,6 @@
#![allow(rustc::diagnostic_outside_of_impl)]
#![allow(rustc::potential_query_instability)]
#![allow(rustc::untranslatable_diagnostic)]
-#![cfg_attr(bootstrap, feature(min_exhaustive_patterns, unsafe_extern_blocks))]
#![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/interpret/allocation.rs b/compiler/rustc_middle/src/mir/interpret/allocation.rs
index 5fb8af5..cd56d0e 100644
--- a/compiler/rustc_middle/src/mir/interpret/allocation.rs
+++ b/compiler/rustc_middle/src/mir/interpret/allocation.rs
@@ -644,6 +644,12 @@ pub fn write_uninit(&mut self, cx: &impl HasDataLayout, range: AllocRange) -> Al
return Ok(());
}
+ /// Remove all provenance in the given memory range.
+ pub fn clear_provenance(&mut self, cx: &impl HasDataLayout, range: AllocRange) -> AllocResult {
+ self.provenance.clear(range, cx)?;
+ return Ok(());
+ }
+
/// Applies a previously prepared provenance copy.
/// The affected range, as defined in the parameters to `provenance().prepare_copy` is expected
/// to be clear of provenance.
diff --git a/compiler/rustc_middle/src/mir/interpret/value.rs b/compiler/rustc_middle/src/mir/interpret/value.rs
index 84c17b3..989f03d 100644
--- a/compiler/rustc_middle/src/mir/interpret/value.rs
+++ b/compiler/rustc_middle/src/mir/interpret/value.rs
@@ -307,6 +307,13 @@ pub fn try_to_scalar_int(self) -> Result<ScalarInt, Scalar<AllocId>> {
}
}
+ pub fn clear_provenance(&mut self) -> InterpResult<'tcx> {
+ if matches!(self, Scalar::Ptr(..)) {
+ *self = self.to_scalar_int()?.into();
+ }
+ Ok(())
+ }
+
#[inline(always)]
pub fn to_scalar_int(self) -> InterpResult<'tcx, ScalarInt> {
self.try_to_scalar_int().map_err(|_| err_unsup!(ReadPointerAsInt(None)).into())
diff --git a/compiler/rustc_middle/src/mir/pretty.rs b/compiler/rustc_middle/src/mir/pretty.rs
index 9906be6..a98e694 100644
--- a/compiler/rustc_middle/src/mir/pretty.rs
+++ b/compiler/rustc_middle/src/mir/pretty.rs
@@ -612,7 +612,9 @@ fn write_mir_sig(tcx: TyCtxt<'_>, body: &Body<'_>, w: &mut dyn io::Write) -> io:
let def_id = body.source.def_id();
let kind = tcx.def_kind(def_id);
let is_function = match kind {
- DefKind::Fn | DefKind::AssocFn | DefKind::Ctor(..) => true,
+ DefKind::Fn | DefKind::AssocFn | DefKind::Ctor(..) | DefKind::SyntheticCoroutineBody => {
+ true
+ }
_ => tcx.is_closure_like(def_id),
};
match (kind, body.source.promoted) {
diff --git a/compiler/rustc_middle/src/mir/syntax.rs b/compiler/rustc_middle/src/mir/syntax.rs
index 748ca04..22a4b68 100644
--- a/compiler/rustc_middle/src/mir/syntax.rs
+++ b/compiler/rustc_middle/src/mir/syntax.rs
@@ -1307,6 +1307,9 @@ pub enum Rvalue<'tcx> {
/// If the type of the place is an array, this is the array length. For slices (`[T]`, not
/// `&[T]`) this accesses the place's metadata to determine the length. This rvalue is
/// ill-formed for places of other types.
+ ///
+ /// This cannot be a `UnOp(PtrMetadata, _)` because that expects a value, and we only
+ /// have a place, and `UnOp(PtrMetadata, RawPtr(place))` is not a thing.
Len(Place<'tcx>),
/// Performs essentially all of the casts that can be performed via `as`.
diff --git a/compiler/rustc_middle/src/ty/closure.rs b/compiler/rustc_middle/src/ty/closure.rs
index 8eb3c01..809801c 100644
--- a/compiler/rustc_middle/src/ty/closure.rs
+++ b/compiler/rustc_middle/src/ty/closure.rs
@@ -88,9 +88,6 @@ pub struct CapturedPlace<'tcx> {
/// Represents if `place` can be mutated or not.
pub mutability: hir::Mutability,
-
- /// Region of the resulting reference if the upvar is captured by ref.
- pub region: Option<ty::Region<'tcx>>,
}
impl<'tcx> CapturedPlace<'tcx> {
diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs
index 2082806..56fcfe8 100644
--- a/compiler/rustc_middle/src/ty/context.rs
+++ b/compiler/rustc_middle/src/ty/context.rs
@@ -181,6 +181,10 @@ fn with_global_cache<R>(
}
}
+ fn evaluation_is_concurrent(&self) -> bool {
+ self.sess.threads() > 1
+ }
+
fn expand_abstract_consts<T: TypeFoldable<TyCtxt<'tcx>>>(self, t: T) -> T {
self.expand_abstract_consts(t)
}
@@ -426,7 +430,7 @@ fn for_each_relevant_impl(
let simp = ty::fast_reject::simplify_type(
tcx,
self_ty,
- ty::fast_reject::TreatParams::ForLookup,
+ ty::fast_reject::TreatParams::AsRigid,
)
.unwrap();
consider_impls_for_simplified_type(simp);
@@ -3128,11 +3132,11 @@ pub fn intrinsic(self, def_id: impl IntoQueryParam<DefId> + Copy) -> Option<ty::
}
pub fn next_trait_solver_globally(self) -> bool {
- self.sess.opts.unstable_opts.next_solver.map_or(false, |c| c.globally)
+ self.sess.opts.unstable_opts.next_solver.globally
}
pub fn next_trait_solver_in_coherence(self) -> bool {
- self.sess.opts.unstable_opts.next_solver.map_or(false, |c| c.coherence)
+ self.sess.opts.unstable_opts.next_solver.coherence
}
pub fn is_impl_trait_in_trait(self, def_id: DefId) -> bool {
@@ -3183,8 +3187,7 @@ pub fn needs_coroutine_by_move_body_def_id(self, def_id: LocalDefId) -> bool {
/// Whether this is a trait implementation that has `#[diagnostic::do_not_recommend]`
pub fn do_not_recommend_impl(self, def_id: DefId) -> bool {
- matches!(self.def_kind(def_id), DefKind::Impl { of_trait: true })
- && self.impl_trait_header(def_id).is_some_and(|header| header.do_not_recommend)
+ self.get_diagnostic_attr(def_id, sym::do_not_recommend).is_some()
}
}
diff --git a/compiler/rustc_middle/src/ty/fast_reject.rs b/compiler/rustc_middle/src/ty/fast_reject.rs
index 91344c4..2945a0b 100644
--- a/compiler/rustc_middle/src/ty/fast_reject.rs
+++ b/compiler/rustc_middle/src/ty/fast_reject.rs
@@ -3,6 +3,14 @@
use super::TyCtxt;
-pub type DeepRejectCtxt<'tcx> = rustc_type_ir::fast_reject::DeepRejectCtxt<TyCtxt<'tcx>>;
+pub type DeepRejectCtxt<
+ 'tcx,
+ const INSTANTIATE_LHS_WITH_INFER: bool,
+ const INSTANTIATE_RHS_WITH_INFER: bool,
+> = rustc_type_ir::fast_reject::DeepRejectCtxt<
+ TyCtxt<'tcx>,
+ INSTANTIATE_LHS_WITH_INFER,
+ INSTANTIATE_RHS_WITH_INFER,
+>;
pub type SimplifiedType = rustc_type_ir::fast_reject::SimplifiedType<DefId>;
diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs
index d0a9039..8cec8ea 100644
--- a/compiler/rustc_middle/src/ty/layout.rs
+++ b/compiler/rustc_middle/src/ty/layout.rs
@@ -1075,11 +1075,13 @@ fn ty_and_layout_pointee_info_at(
// the raw pointer, so size and align are set to the boxed type, but `pointee.safe`
// will still be `None`.
if let Some(ref mut pointee) = result {
- if offset.bytes() == 0 && this.ty.is_box() {
+ if offset.bytes() == 0
+ && let Some(boxed_ty) = this.ty.boxed_ty()
+ {
debug_assert!(pointee.safe.is_none());
let optimize = tcx.sess.opts.optimize != OptLevel::No;
pointee.safe = Some(PointerKind::Box {
- unpin: optimize && this.ty.boxed_ty().is_unpin(tcx, cx.param_env()),
+ unpin: optimize && boxed_ty.is_unpin(tcx, cx.param_env()),
global: this.ty.is_box_global(tcx),
});
}
diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs
index ee70a63..e637ced 100644
--- a/compiler/rustc_middle/src/ty/mod.rs
+++ b/compiler/rustc_middle/src/ty/mod.rs
@@ -263,7 +263,6 @@ pub struct ImplTraitHeader<'tcx> {
pub trait_ref: ty::EarlyBinder<'tcx, ty::TraitRef<'tcx>>,
pub polarity: ImplPolarity,
pub safety: hir::Safety,
- pub do_not_recommend: bool,
}
#[derive(Copy, Clone, PartialEq, Eq, Debug, TypeFoldable, TypeVisitable)]
@@ -1797,6 +1796,37 @@ pub fn get_attrs(
}
}
+ /// Get an attribute from the diagnostic attribute namespace
+ ///
+ /// This function requests an attribute with the following structure:
+ ///
+ /// `#[diagnostic::$attr]`
+ ///
+ /// This function performs feature checking, so if an attribute is returned
+ /// it can be used by the consumer
+ pub fn get_diagnostic_attr(
+ self,
+ did: impl Into<DefId>,
+ attr: Symbol,
+ ) -> Option<&'tcx ast::Attribute> {
+ let did: DefId = did.into();
+ if did.as_local().is_some() {
+ // it's a crate local item, we need to check feature flags
+ if rustc_feature::is_stable_diagnostic_attribute(attr, self.features()) {
+ self.get_attrs_by_path(did, &[sym::diagnostic, sym::do_not_recommend]).next()
+ } else {
+ None
+ }
+ } else {
+ // we filter out unstable diagnostic attributes before
+ // encoding attributes
+ debug_assert!(rustc_feature::encode_cross_crate(attr));
+ self.item_attrs(did)
+ .iter()
+ .find(|a| matches!(a.path().as_ref(), [sym::diagnostic, a] if *a == attr))
+ }
+ }
+
pub fn get_attrs_by_path<'attr>(
self,
did: DefId,
diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs
index 89ef30f..730ba26 100644
--- a/compiler/rustc_middle/src/ty/sty.rs
+++ b/compiler/rustc_middle/src/ty/sty.rs
@@ -1136,6 +1136,7 @@ pub fn is_unsafe_ptr(self) -> bool {
}
/// Tests if this is any kind of primitive pointer type (reference, raw pointer, fn pointer).
+ /// `Box` is *not* considered a pointer here!
#[inline]
pub fn is_any_ptr(self) -> bool {
self.is_ref() || self.is_unsafe_ptr() || self.is_fn_ptr()
@@ -1170,14 +1171,19 @@ pub fn is_box_global(self, tcx: TyCtxt<'tcx>) -> bool {
}
}
- /// Panics if called on any type other than `Box<T>`.
- pub fn boxed_ty(self) -> Ty<'tcx> {
+ pub fn boxed_ty(self) -> Option<Ty<'tcx>> {
match self.kind() {
- Adt(def, args) if def.is_box() => args.type_at(0),
- _ => bug!("`boxed_ty` is called on non-box type {:?}", self),
+ Adt(def, args) if def.is_box() => Some(args.type_at(0)),
+ _ => None,
}
}
+ /// Panics if called on any type other than `Box<T>`.
+ pub fn expect_boxed_ty(self) -> Ty<'tcx> {
+ self.boxed_ty()
+ .unwrap_or_else(|| bug!("`expect_boxed_ty` is called on non-box type {:?}", self))
+ }
+
/// A scalar type is one that denotes an atomic datum, with no sub-components.
/// (A RawPtr is scalar because it represents a non-managed pointer, so its
/// contents are abstract to rustc.)
@@ -1323,7 +1329,7 @@ fn visit_ty(&mut self, t: Ty<'tcx>) -> Self::Result {
/// Some types -- notably unsafe ptrs -- can only be dereferenced explicitly.
pub fn builtin_deref(self, explicit: bool) -> Option<Ty<'tcx>> {
match *self.kind() {
- Adt(def, _) if def.is_box() => Some(self.boxed_ty()),
+ _ if let Some(boxed) = self.boxed_ty() => Some(boxed),
Ref(_, ty, _) => Some(ty),
RawPtr(ty, _) if explicit => Some(ty),
_ => None,
diff --git a/compiler/rustc_middle/src/ty/trait_def.rs b/compiler/rustc_middle/src/ty/trait_def.rs
index dfb137f..82690f7 100644
--- a/compiler/rustc_middle/src/ty/trait_def.rs
+++ b/compiler/rustc_middle/src/ty/trait_def.rs
@@ -168,9 +168,9 @@ pub fn for_each_relevant_impl(
// whose outer level is not a parameter or projection. Especially for things like
// `T: Clone` this is incredibly useful as we would otherwise look at all the impls
// of `Clone` for `Option<T>`, `Vec<T>`, `ConcreteType` and so on.
- // Note that we're using `TreatParams::ForLookup` to query `non_blanket_impls` while using
- // `TreatParams::AsCandidateKey` while actually adding them.
- if let Some(simp) = fast_reject::simplify_type(self, self_ty, TreatParams::ForLookup) {
+ // Note that we're using `TreatParams::AsRigid` to query `non_blanket_impls` while using
+ // `TreatParams::InstantiateWithInfer` while actually adding them.
+ if let Some(simp) = fast_reject::simplify_type(self, self_ty, TreatParams::AsRigid) {
if let Some(impls) = impls.non_blanket_impls.get(&simp) {
for &impl_def_id in impls {
f(impl_def_id);
@@ -190,7 +190,9 @@ pub fn non_blanket_impls_for_ty(
self_ty: Ty<'tcx>,
) -> impl Iterator<Item = DefId> + 'tcx {
let impls = self.trait_impls_of(trait_def_id);
- if let Some(simp) = fast_reject::simplify_type(self, self_ty, TreatParams::AsCandidateKey) {
+ if let Some(simp) =
+ fast_reject::simplify_type(self, self_ty, TreatParams::InstantiateWithInfer)
+ {
if let Some(impls) = impls.non_blanket_impls.get(&simp) {
return impls.iter().copied();
}
@@ -239,7 +241,7 @@ pub(super) fn trait_impls_of_provider(tcx: TyCtxt<'_>, trait_id: DefId) -> Trait
let impl_self_ty = tcx.type_of(impl_def_id).instantiate_identity();
if let Some(simplified_self_ty) =
- fast_reject::simplify_type(tcx, impl_self_ty, TreatParams::AsCandidateKey)
+ fast_reject::simplify_type(tcx, impl_self_ty, TreatParams::InstantiateWithInfer)
{
impls.non_blanket_impls.entry(simplified_self_ty).or_default().push(impl_def_id);
} else {
diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs
index efbccca..d70ff82 100644
--- a/compiler/rustc_middle/src/ty/util.rs
+++ b/compiler/rustc_middle/src/ty/util.rs
@@ -1628,7 +1628,7 @@ pub fn determine<P>(self_arg_ty: Ty<'tcx>, is_self_ty: P) -> ExplicitSelf<'tcx>
_ if is_self_ty(self_arg_ty) => ByValue,
ty::Ref(region, ty, mutbl) if is_self_ty(ty) => ByReference(region, mutbl),
ty::RawPtr(ty, mutbl) if is_self_ty(ty) => ByRawPointer(mutbl),
- ty::Adt(def, _) if def.is_box() && is_self_ty(self_arg_ty.boxed_ty()) => ByBox,
+ _ if self_arg_ty.boxed_ty().is_some_and(is_self_ty) => ByBox,
_ => Other,
}
}
diff --git a/compiler/rustc_mir_dataflow/src/impls/initialized.rs b/compiler/rustc_mir_dataflow/src/impls/initialized.rs
index ddfd073..a889274 100644
--- a/compiler/rustc_mir_dataflow/src/impls/initialized.rs
+++ b/compiler/rustc_mir_dataflow/src/impls/initialized.rs
@@ -51,15 +51,15 @@
/// Similarly, at a given `drop` statement, the set-intersection
/// between this data and `MaybeUninitializedPlaces` yields the set of
/// places that would require a dynamic drop-flag at that statement.
-pub struct MaybeInitializedPlaces<'a, 'mir, 'tcx> {
+pub struct MaybeInitializedPlaces<'a, 'tcx> {
tcx: TyCtxt<'tcx>,
- body: &'mir Body<'tcx>,
+ body: &'a Body<'tcx>,
move_data: &'a MoveData<'tcx>,
skip_unreachable_unwind: bool,
}
-impl<'a, 'mir, 'tcx> MaybeInitializedPlaces<'a, 'mir, 'tcx> {
- pub fn new(tcx: TyCtxt<'tcx>, body: &'mir Body<'tcx>, move_data: &'a MoveData<'tcx>) -> Self {
+impl<'a, 'tcx> MaybeInitializedPlaces<'a, 'tcx> {
+ pub fn new(tcx: TyCtxt<'tcx>, body: &'a Body<'tcx>, move_data: &'a MoveData<'tcx>) -> Self {
MaybeInitializedPlaces { tcx, body, move_data, skip_unreachable_unwind: false }
}
@@ -85,7 +85,7 @@ pub fn is_unwind_dead(
}
}
-impl<'a, 'mir, 'tcx> HasMoveData<'tcx> for MaybeInitializedPlaces<'a, 'mir, 'tcx> {
+impl<'a, 'tcx> HasMoveData<'tcx> for MaybeInitializedPlaces<'a, 'tcx> {
fn move_data(&self) -> &MoveData<'tcx> {
self.move_data
}
@@ -126,17 +126,17 @@ fn move_data(&self) -> &MoveData<'tcx> {
/// Similarly, at a given `drop` statement, the set-intersection
/// between this data and `MaybeInitializedPlaces` yields the set of
/// places that would require a dynamic drop-flag at that statement.
-pub struct MaybeUninitializedPlaces<'a, 'mir, 'tcx> {
+pub struct MaybeUninitializedPlaces<'a, 'tcx> {
tcx: TyCtxt<'tcx>,
- body: &'mir Body<'tcx>,
+ body: &'a Body<'tcx>,
move_data: &'a MoveData<'tcx>,
mark_inactive_variants_as_uninit: bool,
skip_unreachable_unwind: BitSet<mir::BasicBlock>,
}
-impl<'a, 'mir, 'tcx> MaybeUninitializedPlaces<'a, 'mir, 'tcx> {
- pub fn new(tcx: TyCtxt<'tcx>, body: &'mir Body<'tcx>, move_data: &'a MoveData<'tcx>) -> Self {
+impl<'a, 'tcx> MaybeUninitializedPlaces<'a, 'tcx> {
+ pub fn new(tcx: TyCtxt<'tcx>, body: &'a Body<'tcx>, move_data: &'a MoveData<'tcx>) -> Self {
MaybeUninitializedPlaces {
tcx,
body,
@@ -165,7 +165,7 @@ pub fn skipping_unreachable_unwind(
}
}
-impl<'a, 'tcx> HasMoveData<'tcx> for MaybeUninitializedPlaces<'a, '_, 'tcx> {
+impl<'tcx> HasMoveData<'tcx> for MaybeUninitializedPlaces<'_, 'tcx> {
fn move_data(&self) -> &MoveData<'tcx> {
self.move_data
}
@@ -251,24 +251,24 @@ fn move_data(&self) -> &MoveData<'tcx> {
/// c = S; // {a, b, c, d }
/// }
/// ```
-pub struct EverInitializedPlaces<'a, 'mir, 'tcx> {
- body: &'mir Body<'tcx>,
+pub struct EverInitializedPlaces<'a, 'tcx> {
+ body: &'a Body<'tcx>,
move_data: &'a MoveData<'tcx>,
}
-impl<'a, 'mir, 'tcx> EverInitializedPlaces<'a, 'mir, 'tcx> {
- pub fn new(body: &'mir Body<'tcx>, move_data: &'a MoveData<'tcx>) -> Self {
+impl<'a, 'tcx> EverInitializedPlaces<'a, 'tcx> {
+ pub fn new(body: &'a Body<'tcx>, move_data: &'a MoveData<'tcx>) -> Self {
EverInitializedPlaces { body, move_data }
}
}
-impl<'a, 'tcx> HasMoveData<'tcx> for EverInitializedPlaces<'a, '_, 'tcx> {
+impl<'tcx> HasMoveData<'tcx> for EverInitializedPlaces<'_, 'tcx> {
fn move_data(&self) -> &MoveData<'tcx> {
self.move_data
}
}
-impl<'a, 'mir, 'tcx> MaybeInitializedPlaces<'a, 'mir, 'tcx> {
+impl<'a, 'tcx> MaybeInitializedPlaces<'a, 'tcx> {
fn update_bits(
trans: &mut impl GenKill<MovePathIndex>,
path: MovePathIndex,
@@ -281,7 +281,7 @@ fn update_bits(
}
}
-impl<'a, 'tcx> MaybeUninitializedPlaces<'a, '_, 'tcx> {
+impl<'tcx> MaybeUninitializedPlaces<'_, 'tcx> {
fn update_bits(
trans: &mut impl GenKill<MovePathIndex>,
path: MovePathIndex,
@@ -307,7 +307,7 @@ fn update_bits(
}
}
-impl<'tcx> AnalysisDomain<'tcx> for MaybeInitializedPlaces<'_, '_, 'tcx> {
+impl<'tcx> AnalysisDomain<'tcx> for MaybeInitializedPlaces<'_, 'tcx> {
/// There can be many more `MovePathIndex` than there are locals in a MIR body.
/// We use a chunked bitset to avoid paying too high a memory footprint.
type Domain = MaybeReachable<ChunkedBitSet<MovePathIndex>>;
@@ -329,7 +329,7 @@ fn initialize_start_block(&self, _: &mir::Body<'tcx>, state: &mut Self::Domain)
}
}
-impl<'tcx> GenKillAnalysis<'tcx> for MaybeInitializedPlaces<'_, '_, 'tcx> {
+impl<'tcx> GenKillAnalysis<'tcx> for MaybeInitializedPlaces<'_, 'tcx> {
type Idx = MovePathIndex;
fn domain_size(&self, _: &Body<'tcx>) -> usize {
@@ -442,7 +442,7 @@ fn switch_int_edge_effects<G: GenKill<Self::Idx>>(
}
}
-impl<'tcx> AnalysisDomain<'tcx> for MaybeUninitializedPlaces<'_, '_, 'tcx> {
+impl<'tcx> AnalysisDomain<'tcx> for MaybeUninitializedPlaces<'_, 'tcx> {
/// There can be many more `MovePathIndex` than there are locals in a MIR body.
/// We use a chunked bitset to avoid paying too high a memory footprint.
type Domain = ChunkedBitSet<MovePathIndex>;
@@ -466,7 +466,7 @@ fn initialize_start_block(&self, _: &mir::Body<'tcx>, state: &mut Self::Domain)
}
}
-impl<'tcx> GenKillAnalysis<'tcx> for MaybeUninitializedPlaces<'_, '_, 'tcx> {
+impl<'tcx> GenKillAnalysis<'tcx> for MaybeUninitializedPlaces<'_, 'tcx> {
type Idx = MovePathIndex;
fn domain_size(&self, _: &Body<'tcx>) -> usize {
@@ -643,7 +643,7 @@ fn call_return_effect(
}
}
-impl<'tcx> AnalysisDomain<'tcx> for EverInitializedPlaces<'_, '_, 'tcx> {
+impl<'tcx> AnalysisDomain<'tcx> for EverInitializedPlaces<'_, 'tcx> {
/// There can be many more `InitIndex` than there are locals in a MIR body.
/// We use a chunked bitset to avoid paying too high a memory footprint.
type Domain = ChunkedBitSet<InitIndex>;
@@ -662,7 +662,7 @@ fn initialize_start_block(&self, body: &mir::Body<'tcx>, state: &mut Self::Domai
}
}
-impl<'tcx> GenKillAnalysis<'tcx> for EverInitializedPlaces<'_, '_, 'tcx> {
+impl<'tcx> GenKillAnalysis<'tcx> for EverInitializedPlaces<'_, 'tcx> {
type Idx = InitIndex;
fn domain_size(&self, _: &Body<'tcx>) -> usize {
diff --git a/compiler/rustc_mir_dataflow/src/move_paths/builder.rs b/compiler/rustc_mir_dataflow/src/move_paths/builder.rs
index 1439072..87ea729 100644
--- a/compiler/rustc_mir_dataflow/src/move_paths/builder.rs
+++ b/compiler/rustc_mir_dataflow/src/move_paths/builder.rs
@@ -16,6 +16,7 @@
struct MoveDataBuilder<'a, 'tcx, F> {
body: &'a Body<'tcx>,
+ loc: Location,
tcx: TyCtxt<'tcx>,
param_env: ty::ParamEnv<'tcx>,
data: MoveData<'tcx>,
@@ -56,6 +57,7 @@ fn new(
MoveDataBuilder {
body,
+ loc: Location::START,
tcx,
param_env,
data: MoveData {
@@ -107,7 +109,7 @@ enum MovePathResult {
Error,
}
-impl<'b, 'a, 'tcx, F: Fn(Ty<'tcx>) -> bool> Gatherer<'b, 'a, 'tcx, F> {
+impl<'a, 'tcx, F: Fn(Ty<'tcx>) -> bool> MoveDataBuilder<'a, 'tcx, F> {
/// This creates a MovePath for a given place, returning an `MovePathError`
/// if that place can't be moved from.
///
@@ -116,7 +118,7 @@ impl<'b, 'a, 'tcx, F: Fn(Ty<'tcx>) -> bool> Gatherer<'b, 'a, 'tcx, F> {
///
/// Maybe we should have separate "borrowck" and "moveck" modes.
fn move_path_for(&mut self, place: Place<'tcx>) -> MovePathResult {
- let data = &mut self.builder.data;
+ let data = &mut self.data;
debug!("lookup({:?})", place);
let Some(mut base) = data.rev_lookup.find_local(place.local) else {
@@ -131,8 +133,8 @@ fn move_path_for(&mut self, place: Place<'tcx>) -> MovePathResult {
let mut union_path = None;
for (place_ref, elem) in data.rev_lookup.un_derefer.iter_projections(place.as_ref()) {
- let body = self.builder.body;
- let tcx = self.builder.tcx;
+ let body = self.body;
+ let tcx = self.tcx;
let place_ty = place_ref.ty(body, tcx).ty;
if place_ty.references_error() {
return MovePathResult::Error;
@@ -238,7 +240,7 @@ fn move_path_for(&mut self, place: Place<'tcx>) -> MovePathResult {
| ProjectionElem::Downcast(_, _) => (),
}
let elem_ty = PlaceTy::from_ty(place_ty).projection_ty(tcx, elem).ty;
- if !(self.builder.filter)(elem_ty) {
+ if !(self.filter)(elem_ty) {
return MovePathResult::Error;
}
if union_path.is_none() {
@@ -274,7 +276,7 @@ fn add_move_path(
data: MoveData { rev_lookup, move_paths, path_map, init_path_map, .. },
tcx,
..
- } = self.builder;
+ } = self;
*rev_lookup.projections.entry((base, elem.lift())).or_insert_with(move || {
new_move_path(move_paths, path_map, init_path_map, Some(base), mk_place(*tcx))
})
@@ -285,9 +287,7 @@ fn create_move_path(&mut self, place: Place<'tcx>) {
// drop), so this not being a valid move path is OK.
let _ = self.move_path_for(place);
}
-}
-impl<'a, 'tcx, F> MoveDataBuilder<'a, 'tcx, F> {
fn finalize(self) -> MoveData<'tcx> {
debug!("{}", {
debug!("moves for {:?}:", self.body.span);
@@ -317,12 +317,12 @@ pub(super) fn gather_moves<'tcx>(
for (bb, block) in body.basic_blocks.iter_enumerated() {
for (i, stmt) in block.statements.iter().enumerate() {
- let source = Location { block: bb, statement_index: i };
- builder.gather_statement(source, stmt);
+ builder.loc = Location { block: bb, statement_index: i };
+ builder.gather_statement(stmt);
}
- let terminator_loc = Location { block: bb, statement_index: block.statements.len() };
- builder.gather_terminator(terminator_loc, block.terminator());
+ builder.loc = Location { block: bb, statement_index: block.statements.len() };
+ builder.gather_terminator(block.terminator());
}
builder.finalize()
@@ -345,30 +345,14 @@ fn gather_args(&mut self) {
}
}
- fn gather_statement(&mut self, loc: Location, stmt: &Statement<'tcx>) {
- debug!("gather_statement({:?}, {:?})", loc, stmt);
- (Gatherer { builder: self, loc }).gather_statement(stmt);
- }
-
- fn gather_terminator(&mut self, loc: Location, term: &Terminator<'tcx>) {
- debug!("gather_terminator({:?}, {:?})", loc, term);
- (Gatherer { builder: self, loc }).gather_terminator(term);
- }
-}
-
-struct Gatherer<'b, 'a, 'tcx, F> {
- builder: &'b mut MoveDataBuilder<'a, 'tcx, F>,
- loc: Location,
-}
-
-impl<'b, 'a, 'tcx, F: Fn(Ty<'tcx>) -> bool> Gatherer<'b, 'a, 'tcx, F> {
fn gather_statement(&mut self, stmt: &Statement<'tcx>) {
+ debug!("gather_statement({:?}, {:?})", self.loc, stmt);
match &stmt.kind {
StatementKind::Assign(box (place, Rvalue::CopyForDeref(reffed))) => {
let local = place.as_local().unwrap();
- assert!(self.builder.body.local_decls[local].is_deref_temp());
+ assert!(self.body.local_decls[local].is_deref_temp());
- let rev_lookup = &mut self.builder.data.rev_lookup;
+ let rev_lookup = &mut self.data.rev_lookup;
rev_lookup.un_derefer.insert(local, reffed.as_ref());
let base_local = rev_lookup.un_derefer.deref_chain(local).first().unwrap().local;
@@ -380,7 +364,7 @@ fn gather_statement(&mut self, stmt: &Statement<'tcx>) {
// Box starts out uninitialized - need to create a separate
// move-path for the interior so it will be separate from
// the exterior.
- self.create_move_path(self.builder.tcx.mk_place_deref(*place));
+ self.create_move_path(self.tcx.mk_place_deref(*place));
self.gather_init(place.as_ref(), InitKind::Shallow);
} else {
self.gather_init(place.as_ref(), InitKind::Deep);
@@ -393,7 +377,7 @@ fn gather_statement(&mut self, stmt: &Statement<'tcx>) {
StatementKind::StorageLive(_) => {}
StatementKind::StorageDead(local) => {
// DerefTemp locals (results of CopyForDeref) don't actually move anything.
- if !self.builder.body.local_decls[*local].is_deref_temp() {
+ if !self.body.local_decls[*local].is_deref_temp() {
self.gather_move(Place::from(*local));
}
}
@@ -443,6 +427,7 @@ fn gather_rvalue(&mut self, rvalue: &Rvalue<'tcx>) {
}
fn gather_terminator(&mut self, term: &Terminator<'tcx>) {
+ debug!("gather_terminator({:?}, {:?})", self.loc, term);
match term.kind {
TerminatorKind::Goto { target: _ }
| TerminatorKind::FalseEdge { .. }
@@ -551,7 +536,7 @@ fn gather_move(&mut self, place: Place<'tcx>) {
// `ConstIndex` patterns. This is done to ensure that all move paths
// are disjoint, which is expected by drop elaboration.
let base_place =
- Place { local: place.local, projection: self.builder.tcx.mk_place_elems(base) };
+ Place { local: place.local, projection: self.tcx.mk_place_elems(base) };
let base_path = match self.move_path_for(base_place) {
MovePathResult::Path(path) => path,
MovePathResult::Union(path) => {
@@ -562,11 +547,9 @@ fn gather_move(&mut self, place: Place<'tcx>) {
return;
}
};
- let base_ty = base_place.ty(self.builder.body, self.builder.tcx).ty;
+ let base_ty = base_place.ty(self.body, self.tcx).ty;
let len: u64 = match base_ty.kind() {
- ty::Array(_, size) => {
- size.eval_target_usize(self.builder.tcx, self.builder.param_env)
- }
+ ty::Array(_, size) => size.eval_target_usize(self.tcx, self.param_env),
_ => bug!("from_end: false slice pattern of non-array type"),
};
for offset in from..to {
@@ -587,13 +570,13 @@ fn gather_move(&mut self, place: Place<'tcx>) {
}
fn record_move(&mut self, place: Place<'tcx>, path: MovePathIndex) {
- let move_out = self.builder.data.moves.push(MoveOut { path, source: self.loc });
+ let move_out = self.data.moves.push(MoveOut { path, source: self.loc });
debug!(
"gather_move({:?}, {:?}): adding move {:?} of {:?}",
self.loc, place, move_out, path
);
- self.builder.data.path_map[path].push(move_out);
- self.builder.data.loc_map[self.loc].push(move_out);
+ self.data.path_map[path].push(move_out);
+ self.data.loc_map[self.loc].push(move_out);
}
fn gather_init(&mut self, place: PlaceRef<'tcx>, kind: InitKind) {
@@ -604,13 +587,13 @@ fn gather_init(&mut self, place: PlaceRef<'tcx>, kind: InitKind) {
// Check if we are assigning into a field of a union, if so, lookup the place
// of the union so it is marked as initialized again.
if let Some((place_base, ProjectionElem::Field(_, _))) = place.last_projection() {
- if place_base.ty(self.builder.body, self.builder.tcx).ty.is_union() {
+ if place_base.ty(self.body, self.tcx).ty.is_union() {
place = place_base;
}
}
- if let LookupResult::Exact(path) = self.builder.data.rev_lookup.find(place) {
- let init = self.builder.data.inits.push(Init {
+ if let LookupResult::Exact(path) = self.data.rev_lookup.find(place) {
+ let init = self.data.inits.push(Init {
location: InitLocation::Statement(self.loc),
path,
kind,
@@ -621,8 +604,8 @@ fn gather_init(&mut self, place: PlaceRef<'tcx>, kind: InitKind) {
self.loc, place, init, path
);
- self.builder.data.init_path_map[path].push(init);
- self.builder.data.init_loc_map[self.loc].push(init);
+ self.data.init_path_map[path].push(init);
+ self.data.init_loc_map[self.loc].push(init);
}
}
}
diff --git a/compiler/rustc_mir_dataflow/src/value_analysis.rs b/compiler/rustc_mir_dataflow/src/value_analysis.rs
index 2b20a35..0540436 100644
--- a/compiler/rustc_mir_dataflow/src/value_analysis.rs
+++ b/compiler/rustc_mir_dataflow/src/value_analysis.rs
@@ -923,14 +923,14 @@ fn cache_preorder_invoke(&mut self, root: PlaceIndex) {
}
}
-struct PlaceCollector<'a, 'b, 'tcx> {
+struct PlaceCollector<'a, 'tcx> {
tcx: TyCtxt<'tcx>,
- body: &'b Body<'tcx>,
+ body: &'a Body<'tcx>,
map: &'a mut Map<'tcx>,
assignments: FxIndexSet<(PlaceIndex, PlaceIndex)>,
}
-impl<'tcx> PlaceCollector<'_, '_, 'tcx> {
+impl<'tcx> PlaceCollector<'_, 'tcx> {
#[tracing::instrument(level = "trace", skip(self))]
fn register_place(&mut self, place: Place<'tcx>) -> Option<PlaceIndex> {
// Create a place for this projection.
@@ -967,7 +967,7 @@ fn register_place(&mut self, place: Place<'tcx>) -> Option<PlaceIndex> {
}
}
-impl<'tcx> Visitor<'tcx> for PlaceCollector<'_, '_, 'tcx> {
+impl<'tcx> Visitor<'tcx> for PlaceCollector<'_, 'tcx> {
#[tracing::instrument(level = "trace", skip(self))]
fn visit_place(&mut self, place: &Place<'tcx>, ctxt: PlaceContext, _: Location) {
if !ctxt.is_use() {
diff --git a/compiler/rustc_mir_transform/src/abort_unwinding_calls.rs b/compiler/rustc_mir_transform/src/abort_unwinding_calls.rs
index e4bc6b3..8291df9 100644
--- a/compiler/rustc_mir_transform/src/abort_unwinding_calls.rs
+++ b/compiler/rustc_mir_transform/src/abort_unwinding_calls.rs
@@ -20,7 +20,7 @@
/// This forces all unwinds, in panic=abort mode happening in foreign code, to
/// trigger a process abort.
#[derive(PartialEq)]
-pub struct AbortUnwindingCalls;
+pub(super) struct AbortUnwindingCalls;
impl<'tcx> crate::MirPass<'tcx> for AbortUnwindingCalls {
fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
@@ -50,9 +50,7 @@ fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
// with a function call, and whose function we're calling may unwind.
// This will filter to functions with `extern "C-unwind"` ABIs, for
// example.
- let mut calls_to_terminate = Vec::new();
- let mut cleanups_to_remove = Vec::new();
- for (id, block) in body.basic_blocks.iter_enumerated() {
+ for block in body.basic_blocks.as_mut() {
if block.is_cleanup {
continue;
}
@@ -61,7 +59,7 @@ fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
let call_can_unwind = match &terminator.kind {
TerminatorKind::Call { func, .. } => {
- let ty = func.ty(body, tcx);
+ let ty = func.ty(&body.local_decls, tcx);
let sig = ty.fn_sig(tcx);
let fn_def_id = match ty.kind() {
ty::FnPtr(..) => None,
@@ -86,31 +84,20 @@ fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
_ => continue,
};
- // If this function call can't unwind, then there's no need for it
- // to have a landing pad. This means that we can remove any cleanup
- // registered for it.
if !call_can_unwind {
- cleanups_to_remove.push(id);
- continue;
+ // If this function call can't unwind, then there's no need for it
+ // to have a landing pad. This means that we can remove any cleanup
+ // registered for it.
+ let cleanup = block.terminator_mut().unwind_mut().unwrap();
+ *cleanup = UnwindAction::Unreachable;
+ } else if !body_can_unwind {
+ // Otherwise if this function can unwind, then if the outer function
+ // can also unwind there's nothing to do. If the outer function
+ // can't unwind, however, we need to change the landing pad for this
+ // function call to one that aborts.
+ let cleanup = block.terminator_mut().unwind_mut().unwrap();
+ *cleanup = UnwindAction::Terminate(UnwindTerminateReason::Abi);
}
-
- // Otherwise if this function can unwind, then if the outer function
- // can also unwind there's nothing to do. If the outer function
- // can't unwind, however, we need to change the landing pad for this
- // function call to one that aborts.
- if !body_can_unwind {
- calls_to_terminate.push(id);
- }
- }
-
- for id in calls_to_terminate {
- let cleanup = body.basic_blocks_mut()[id].terminator_mut().unwind_mut().unwrap();
- *cleanup = UnwindAction::Terminate(UnwindTerminateReason::Abi);
- }
-
- for id in cleanups_to_remove {
- let cleanup = body.basic_blocks_mut()[id].terminator_mut().unwind_mut().unwrap();
- *cleanup = UnwindAction::Unreachable;
}
// We may have invalidated some `cleanup` blocks so clean those up now.
diff --git a/compiler/rustc_mir_transform/src/add_call_guards.rs b/compiler/rustc_mir_transform/src/add_call_guards.rs
index 78e850d..18a0746 100644
--- a/compiler/rustc_mir_transform/src/add_call_guards.rs
+++ b/compiler/rustc_mir_transform/src/add_call_guards.rs
@@ -4,11 +4,11 @@
use tracing::debug;
#[derive(PartialEq)]
-pub enum AddCallGuards {
+pub(super) enum AddCallGuards {
AllCallEdges,
CriticalCallEdges,
}
-pub use self::AddCallGuards::*;
+pub(super) use self::AddCallGuards::*;
/**
* Breaks outgoing critical edges for call terminators in the MIR.
@@ -37,7 +37,7 @@ fn run_pass(&self, _tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
}
impl AddCallGuards {
- pub fn add_call_guards(&self, body: &mut Body<'_>) {
+ pub(super) fn add_call_guards(&self, body: &mut Body<'_>) {
let mut pred_count: IndexVec<_, _> =
body.basic_blocks.predecessors().iter().map(|ps| ps.len()).collect();
pred_count[START_BLOCK] += 1;
diff --git a/compiler/rustc_mir_transform/src/add_moves_for_packed_drops.rs b/compiler/rustc_mir_transform/src/add_moves_for_packed_drops.rs
index 4a8196a..47572d8 100644
--- a/compiler/rustc_mir_transform/src/add_moves_for_packed_drops.rs
+++ b/compiler/rustc_mir_transform/src/add_moves_for_packed_drops.rs
@@ -35,7 +35,7 @@
///
/// The storage instructions are required to avoid stack space
/// blowup.
-pub struct AddMovesForPackedDrops;
+pub(super) struct AddMovesForPackedDrops;
impl<'tcx> crate::MirPass<'tcx> for AddMovesForPackedDrops {
fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
@@ -44,7 +44,7 @@ fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
}
}
-pub fn add_moves_for_packed_drops<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
+fn add_moves_for_packed_drops<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
let patch = add_moves_for_packed_drops_patch(tcx, body);
patch.apply(body);
}
diff --git a/compiler/rustc_mir_transform/src/add_retag.rs b/compiler/rustc_mir_transform/src/add_retag.rs
index 2e12064..794e85f 100644
--- a/compiler/rustc_mir_transform/src/add_retag.rs
+++ b/compiler/rustc_mir_transform/src/add_retag.rs
@@ -8,7 +8,7 @@
use rustc_middle::mir::*;
use rustc_middle::ty::{self, Ty, TyCtxt};
-pub struct AddRetag;
+pub(super) struct AddRetag;
/// Determine whether this type may contain a reference (or box), and thus needs retagging.
/// We will only recurse `depth` times into Tuples/ADTs to bound the cost of this.
diff --git a/compiler/rustc_mir_transform/src/add_subtyping_projections.rs b/compiler/rustc_mir_transform/src/add_subtyping_projections.rs
index 369f6c6..ab6bf18 100644
--- a/compiler/rustc_mir_transform/src/add_subtyping_projections.rs
+++ b/compiler/rustc_mir_transform/src/add_subtyping_projections.rs
@@ -1,15 +1,14 @@
-use rustc_index::IndexVec;
use rustc_middle::mir::patch::MirPatch;
use rustc_middle::mir::visit::MutVisitor;
use rustc_middle::mir::*;
use rustc_middle::ty::TyCtxt;
-pub struct Subtyper;
+pub(super) struct Subtyper;
-pub struct SubTypeChecker<'a, 'tcx> {
+struct SubTypeChecker<'a, 'tcx> {
tcx: TyCtxt<'tcx>,
patcher: MirPatch<'tcx>,
- local_decls: &'a IndexVec<Local, LocalDecl<'tcx>>,
+ local_decls: &'a LocalDecls<'tcx>,
}
impl<'a, 'tcx> MutVisitor<'tcx> for SubTypeChecker<'a, 'tcx> {
@@ -52,7 +51,7 @@ fn visit_assign(
// // gets transformed to
// let temp: rval_ty = rval;
// let place: place_ty = temp as place_ty;
-pub fn subtype_finder<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
+fn subtype_finder<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
let patch = MirPatch::new(body);
let mut checker = SubTypeChecker { tcx, patcher: patch, local_decls: &body.local_decls };
diff --git a/compiler/rustc_mir_transform/src/check_alignment.rs b/compiler/rustc_mir_transform/src/check_alignment.rs
index 2e072aa..e1d5152 100644
--- a/compiler/rustc_mir_transform/src/check_alignment.rs
+++ b/compiler/rustc_mir_transform/src/check_alignment.rs
@@ -7,7 +7,7 @@
use rustc_session::Session;
use tracing::{debug, trace};
-pub struct CheckAlignment;
+pub(super) struct CheckAlignment;
impl<'tcx> crate::MirPass<'tcx> for CheckAlignment {
fn is_enabled(&self, sess: &Session) -> bool {
diff --git a/compiler/rustc_mir_transform/src/check_const_item_mutation.rs b/compiler/rustc_mir_transform/src/check_const_item_mutation.rs
index fb03323..234ed82 100644
--- a/compiler/rustc_mir_transform/src/check_const_item_mutation.rs
+++ b/compiler/rustc_mir_transform/src/check_const_item_mutation.rs
@@ -8,7 +8,7 @@
use crate::errors;
-pub struct CheckConstItemMutation;
+pub(super) struct CheckConstItemMutation;
impl<'tcx> crate::MirLint<'tcx> for CheckConstItemMutation {
fn run_lint(&self, tcx: TyCtxt<'tcx>, body: &Body<'tcx>) {
diff --git a/compiler/rustc_mir_transform/src/check_packed_ref.rs b/compiler/rustc_mir_transform/src/check_packed_ref.rs
index 2f957de..1922d4f 100644
--- a/compiler/rustc_mir_transform/src/check_packed_ref.rs
+++ b/compiler/rustc_mir_transform/src/check_packed_ref.rs
@@ -5,7 +5,7 @@
use crate::{errors, util};
-pub struct CheckPackedRef;
+pub(super) struct CheckPackedRef;
impl<'tcx> crate::MirLint<'tcx> for CheckPackedRef {
fn run_lint(&self, tcx: TyCtxt<'tcx>, body: &Body<'tcx>) {
diff --git a/compiler/rustc_mir_transform/src/cleanup_post_borrowck.rs b/compiler/rustc_mir_transform/src/cleanup_post_borrowck.rs
index 2f3be1e..97ce16c 100644
--- a/compiler/rustc_mir_transform/src/cleanup_post_borrowck.rs
+++ b/compiler/rustc_mir_transform/src/cleanup_post_borrowck.rs
@@ -21,7 +21,7 @@
use rustc_middle::ty::adjustment::PointerCoercion;
use rustc_middle::ty::TyCtxt;
-pub struct CleanupPostBorrowck;
+pub(super) struct CleanupPostBorrowck;
impl<'tcx> crate::MirPass<'tcx> for CleanupPostBorrowck {
fn run_pass(&self, _tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
diff --git a/compiler/rustc_mir_transform/src/copy_prop.rs b/compiler/rustc_mir_transform/src/copy_prop.rs
index 85d25ca..dc4ee58 100644
--- a/compiler/rustc_mir_transform/src/copy_prop.rs
+++ b/compiler/rustc_mir_transform/src/copy_prop.rs
@@ -17,7 +17,7 @@
/// where each of the locals is only assigned once.
///
/// We want to replace all those locals by `_a`, either copied or moved.
-pub struct CopyProp;
+pub(super) struct CopyProp;
impl<'tcx> crate::MirPass<'tcx> for CopyProp {
fn is_enabled(&self, sess: &rustc_session::Session) -> bool {
diff --git a/compiler/rustc_mir_transform/src/coroutine.rs b/compiler/rustc_mir_transform/src/coroutine.rs
index eefb748..90243cd 100644
--- a/compiler/rustc_mir_transform/src/coroutine.rs
+++ b/compiler/rustc_mir_transform/src/coroutine.rs
@@ -53,7 +53,7 @@
mod by_move_body;
use std::{iter, ops};
-pub use by_move_body::coroutine_by_move_body_def_id;
+pub(super) use by_move_body::coroutine_by_move_body_def_id;
use rustc_data_structures::fx::FxHashSet;
use rustc_errors::pluralize;
use rustc_hir as hir;
@@ -85,7 +85,7 @@
use crate::deref_separator::deref_finder;
use crate::{abort_unwinding_calls, errors, pass_manager as pm, simplify};
-pub struct StateTransform;
+pub(super) struct StateTransform;
struct RenameLocalVisitor<'tcx> {
from: Local,
@@ -872,9 +872,9 @@ fn compute_storage_conflicts<'mir, 'tcx>(
storage_conflicts
}
-struct StorageConflictVisitor<'mir, 'tcx, 's> {
- body: &'mir Body<'tcx>,
- saved_locals: &'s CoroutineSavedLocals,
+struct StorageConflictVisitor<'a, 'tcx> {
+ body: &'a Body<'tcx>,
+ saved_locals: &'a CoroutineSavedLocals,
// FIXME(tmandry): Consider using sparse bitsets here once we have good
// benchmarks for coroutines.
local_conflicts: BitMatrix<Local, Local>,
@@ -882,8 +882,8 @@ struct StorageConflictVisitor<'mir, 'tcx, 's> {
eligible_storage_live: BitSet<Local>,
}
-impl<'mir, 'tcx, R> rustc_mir_dataflow::ResultsVisitor<'mir, 'tcx, R>
- for StorageConflictVisitor<'mir, 'tcx, '_>
+impl<'a, 'tcx, R> rustc_mir_dataflow::ResultsVisitor<'a, 'tcx, R>
+ for StorageConflictVisitor<'a, 'tcx>
{
type FlowState = BitSet<Local>;
@@ -891,7 +891,7 @@ fn visit_statement_before_primary_effect(
&mut self,
_results: &mut R,
state: &Self::FlowState,
- _statement: &'mir Statement<'tcx>,
+ _statement: &'a Statement<'tcx>,
loc: Location,
) {
self.apply_state(state, loc);
@@ -901,14 +901,14 @@ fn visit_terminator_before_primary_effect(
&mut self,
_results: &mut R,
state: &Self::FlowState,
- _terminator: &'mir Terminator<'tcx>,
+ _terminator: &'a Terminator<'tcx>,
loc: Location,
) {
self.apply_state(state, loc);
}
}
-impl StorageConflictVisitor<'_, '_, '_> {
+impl StorageConflictVisitor<'_, '_> {
fn apply_state(&mut self, flow_state: &BitSet<Local>, loc: Location) {
// Ignore unreachable blocks.
if let TerminatorKind::Unreachable = self.body.basic_blocks[loc.block].terminator().kind {
@@ -1199,7 +1199,7 @@ fn insert_panic_block<'tcx>(
message: AssertMessage<'tcx>,
) -> BasicBlock {
let assert_block = BasicBlock::new(body.basic_blocks.len());
- let term = TerminatorKind::Assert {
+ let kind = TerminatorKind::Assert {
cond: Operand::Constant(Box::new(ConstOperand {
span: body.span,
user_ty: None,
@@ -1211,14 +1211,7 @@ fn insert_panic_block<'tcx>(
unwind: UnwindAction::Continue,
};
- let source_info = SourceInfo::outermost(body.span);
- body.basic_blocks_mut().push(BasicBlockData {
- statements: Vec::new(),
- terminator: Some(Terminator { source_info, kind: term }),
- is_cleanup: false,
- });
-
- assert_block
+ insert_term_block(body, kind)
}
fn can_return<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>, param_env: ty::ParamEnv<'tcx>) -> bool {
diff --git a/compiler/rustc_mir_transform/src/coroutine/by_move_body.rs b/compiler/rustc_mir_transform/src/coroutine/by_move_body.rs
index ebe8d2e..6476f3c 100644
--- a/compiler/rustc_mir_transform/src/coroutine/by_move_body.rs
+++ b/compiler/rustc_mir_transform/src/coroutine/by_move_body.rs
@@ -82,12 +82,17 @@
use rustc_span::symbol::kw;
use rustc_target::abi::{FieldIdx, VariantIdx};
-pub fn coroutine_by_move_body_def_id<'tcx>(
+pub(crate) fn coroutine_by_move_body_def_id<'tcx>(
tcx: TyCtxt<'tcx>,
coroutine_def_id: LocalDefId,
) -> DefId {
let body = tcx.mir_built(coroutine_def_id).borrow();
+ // If the typeck results are tainted, no need to make a by-ref body.
+ if body.tainted_by_errors.is_some() {
+ return coroutine_def_id.to_def_id();
+ }
+
let Some(hir::CoroutineKind::Desugared(_, hir::CoroutineSource::Closure)) =
tcx.coroutine_kind(coroutine_def_id)
else {
@@ -98,7 +103,9 @@ pub fn coroutine_by_move_body_def_id<'tcx>(
// the MIR body will be constructed well.
let coroutine_ty = body.local_decls[ty::CAPTURE_STRUCT_LOCAL].ty;
- let ty::Coroutine(_, args) = *coroutine_ty.kind() else { bug!("{body:#?}") };
+ let ty::Coroutine(_, args) = *coroutine_ty.kind() else {
+ bug!("tried to create by-move body of non-coroutine receiver");
+ };
let args = args.as_coroutine();
let coroutine_kind = args.kind_ty().to_opt_closure_kind().unwrap();
@@ -107,7 +114,7 @@ pub fn coroutine_by_move_body_def_id<'tcx>(
let ty::CoroutineClosure(_, parent_args) =
*tcx.type_of(parent_def_id).instantiate_identity().kind()
else {
- bug!();
+ bug!("coroutine's parent was not a coroutine-closure");
};
if parent_args.references_error() {
return coroutine_def_id.to_def_id();
@@ -207,11 +214,12 @@ pub fn coroutine_by_move_body_def_id<'tcx>(
let mut by_move_body = body.clone();
MakeByMoveBody { tcx, field_remapping, by_move_coroutine_ty }.visit_body(&mut by_move_body);
- dump_mir(tcx, false, "coroutine_by_move", &0, &by_move_body, |_, _| Ok(()));
- let body_def = tcx.create_def(coroutine_def_id, kw::Empty, DefKind::SyntheticCoroutineBody);
+ // This will always be `{closure#1}`, since the original coroutine is `{closure#0}`.
+ let body_def = tcx.create_def(parent_def_id, kw::Empty, DefKind::SyntheticCoroutineBody);
by_move_body.source =
mir::MirSource::from_instance(InstanceKind::Item(body_def.def_id().to_def_id()));
+ dump_mir(tcx, false, "built", &"after", &by_move_body, |_, _| Ok(()));
// Inherited from the by-ref coroutine.
body_def.codegen_fn_attrs(tcx.codegen_fn_attrs(coroutine_def_id).clone());
diff --git a/compiler/rustc_mir_transform/src/cost_checker.rs b/compiler/rustc_mir_transform/src/cost_checker.rs
index a1c1422..59b4035 100644
--- a/compiler/rustc_mir_transform/src/cost_checker.rs
+++ b/compiler/rustc_mir_transform/src/cost_checker.rs
@@ -12,7 +12,7 @@
/// Verify that the callee body is compatible with the caller.
#[derive(Clone)]
-pub(crate) struct CostChecker<'b, 'tcx> {
+pub(super) struct CostChecker<'b, 'tcx> {
tcx: TyCtxt<'tcx>,
param_env: ParamEnv<'tcx>,
penalty: usize,
@@ -22,7 +22,7 @@ pub(crate) struct CostChecker<'b, 'tcx> {
}
impl<'b, 'tcx> CostChecker<'b, 'tcx> {
- pub fn new(
+ pub(super) fn new(
tcx: TyCtxt<'tcx>,
param_env: ParamEnv<'tcx>,
instance: Option<ty::Instance<'tcx>>,
@@ -36,7 +36,7 @@ pub fn new(
/// Needed because the `CostChecker` is used sometimes for just blocks,
/// and even the full `Inline` doesn't call `visit_body`, so there's nowhere
/// to put this logic in the visitor.
- pub fn add_function_level_costs(&mut self) {
+ pub(super) fn add_function_level_costs(&mut self) {
fn is_call_like(bbd: &BasicBlockData<'_>) -> bool {
use TerminatorKind::*;
match bbd.terminator().kind {
@@ -64,7 +64,7 @@ fn is_call_like(bbd: &BasicBlockData<'_>) -> bool {
}
}
- pub fn cost(&self) -> usize {
+ pub(super) fn cost(&self) -> usize {
usize::saturating_sub(self.penalty, self.bonus)
}
diff --git a/compiler/rustc_mir_transform/src/coverage/mod.rs b/compiler/rustc_mir_transform/src/coverage/mod.rs
index 4edba61..042f589 100644
--- a/compiler/rustc_mir_transform/src/coverage/mod.rs
+++ b/compiler/rustc_mir_transform/src/coverage/mod.rs
@@ -1,4 +1,4 @@
-pub mod query;
+pub(super) mod query;
mod counters;
mod graph;
@@ -32,7 +32,7 @@
/// Inserts `StatementKind::Coverage` statements that either instrument the binary with injected
/// counters, via intrinsic `llvm.instrprof.increment`, and/or inject metadata used during codegen
/// to construct the coverage map.
-pub struct InstrumentCoverage;
+pub(super) struct InstrumentCoverage;
impl<'tcx> crate::MirPass<'tcx> for InstrumentCoverage {
fn is_enabled(&self, sess: &rustc_session::Session) -> bool {
diff --git a/compiler/rustc_mir_transform/src/coverage/spans.rs b/compiler/rustc_mir_transform/src/coverage/spans.rs
index fcc7745..b904b0d 100644
--- a/compiler/rustc_mir_transform/src/coverage/spans.rs
+++ b/compiler/rustc_mir_transform/src/coverage/spans.rs
@@ -3,7 +3,7 @@
use rustc_data_structures::captures::Captures;
use rustc_data_structures::fx::FxHashSet;
use rustc_middle::mir;
-use rustc_span::Span;
+use rustc_span::{DesugaringKind, ExpnKind, MacroKind, Span};
use tracing::{debug, debug_span, instrument};
use crate::coverage::graph::{BasicCoverageBlock, CoverageGraph};
@@ -25,7 +25,7 @@ pub(super) fn extract_refined_covspans(
// First, perform the passes that need macro information.
covspans.sort_by(|a, b| basic_coverage_blocks.cmp_in_dominator_order(a.bcb, b.bcb));
- remove_unwanted_macro_spans(&mut covspans);
+ remove_unwanted_expansion_spans(&mut covspans);
split_visible_macro_spans(&mut covspans);
// We no longer need the extra information in `SpanFromMir`, so convert to `Covspan`.
@@ -76,18 +76,24 @@ pub(super) fn extract_refined_covspans(
/// invocation, which is unhelpful. Keeping only the first such span seems to
/// give better mappings, so remove the others.
///
+/// Similarly, `await` expands to a branch on the discriminant of `Poll`, which
+/// leads to incorrect coverage if the `Future` is immediately ready (#98712).
+///
/// (The input spans should be sorted in BCB dominator order, so that the
/// retained "first" span is likely to dominate the others.)
-fn remove_unwanted_macro_spans(covspans: &mut Vec<SpanFromMir>) {
- let mut seen_macro_spans = FxHashSet::default();
- covspans.retain(|covspan| {
- // Ignore (retain) non-macro-expansion spans.
- if covspan.visible_macro.is_none() {
- return true;
- }
+fn remove_unwanted_expansion_spans(covspans: &mut Vec<SpanFromMir>) {
+ let mut deduplicated_spans = FxHashSet::default();
- // Retain only the first macro-expanded covspan with this span.
- seen_macro_spans.insert(covspan.span)
+ covspans.retain(|covspan| {
+ match covspan.expn_kind {
+ // Retain only the first await-related or macro-expanded covspan with this span.
+ Some(ExpnKind::Desugaring(kind)) if kind == DesugaringKind::Await => {
+ deduplicated_spans.insert(covspan.span)
+ }
+ Some(ExpnKind::Macro(MacroKind::Bang, _)) => deduplicated_spans.insert(covspan.span),
+ // Ignore (retain) other spans.
+ _ => true,
+ }
});
}
@@ -99,7 +105,9 @@ fn split_visible_macro_spans(covspans: &mut Vec<SpanFromMir>) {
let mut extra_spans = vec![];
covspans.retain(|covspan| {
- let Some(visible_macro) = covspan.visible_macro else { return true };
+ let Some(ExpnKind::Macro(MacroKind::Bang, visible_macro)) = covspan.expn_kind else {
+ return true;
+ };
let split_len = visible_macro.as_str().len() as u32 + 1;
let (before, after) = covspan.span.split_at(split_len);
@@ -111,8 +119,8 @@ fn split_visible_macro_spans(covspans: &mut Vec<SpanFromMir>) {
return true;
}
- extra_spans.push(SpanFromMir::new(before, covspan.visible_macro, covspan.bcb));
- extra_spans.push(SpanFromMir::new(after, covspan.visible_macro, covspan.bcb));
+ extra_spans.push(SpanFromMir::new(before, covspan.expn_kind.clone(), covspan.bcb));
+ extra_spans.push(SpanFromMir::new(after, covspan.expn_kind.clone(), covspan.bcb));
false // Discard the original covspan that we just split.
});
diff --git a/compiler/rustc_mir_transform/src/coverage/spans/from_mir.rs b/compiler/rustc_mir_transform/src/coverage/spans/from_mir.rs
index 32bd25b..7f5765c 100644
--- a/compiler/rustc_mir_transform/src/coverage/spans/from_mir.rs
+++ b/compiler/rustc_mir_transform/src/coverage/spans/from_mir.rs
@@ -3,13 +3,13 @@
use rustc_middle::mir::{
self, FakeReadCause, Statement, StatementKind, Terminator, TerminatorKind,
};
-use rustc_span::{Span, Symbol};
+use rustc_span::{ExpnKind, Span};
use crate::coverage::graph::{
BasicCoverageBlock, BasicCoverageBlockData, CoverageGraph, START_BCB,
};
use crate::coverage::spans::Covspan;
-use crate::coverage::unexpand::unexpand_into_body_span_with_visible_macro;
+use crate::coverage::unexpand::unexpand_into_body_span_with_expn_kind;
use crate::coverage::ExtractedHirInfo;
pub(crate) struct ExtractedCovspans {
@@ -60,7 +60,7 @@ fn bcb_to_initial_coverage_spans<'a, 'tcx>(
let data = &mir_body[bb];
let unexpand = move |expn_span| {
- unexpand_into_body_span_with_visible_macro(expn_span, body_span)
+ unexpand_into_body_span_with_expn_kind(expn_span, body_span)
// Discard any spans that fill the entire body, because they tend
// to represent compiler-inserted code, e.g. implicitly returning `()`.
.filter(|(span, _)| !span.source_equal(body_span))
@@ -68,9 +68,9 @@ fn bcb_to_initial_coverage_spans<'a, 'tcx>(
let mut extract_statement_span = |statement| {
let expn_span = filtered_statement_span(statement)?;
- let (span, visible_macro) = unexpand(expn_span)?;
+ let (span, expn_kind) = unexpand(expn_span)?;
- initial_covspans.push(SpanFromMir::new(span, visible_macro, bcb));
+ initial_covspans.push(SpanFromMir::new(span, expn_kind, bcb));
Some(())
};
for statement in data.statements.iter() {
@@ -79,9 +79,9 @@ fn bcb_to_initial_coverage_spans<'a, 'tcx>(
let mut extract_terminator_span = |terminator| {
let expn_span = filtered_terminator_span(terminator)?;
- let (span, visible_macro) = unexpand(expn_span)?;
+ let (span, expn_kind) = unexpand(expn_span)?;
- initial_covspans.push(SpanFromMir::new(span, visible_macro, bcb));
+ initial_covspans.push(SpanFromMir::new(span, expn_kind, bcb));
Some(())
};
extract_terminator_span(data.terminator());
@@ -214,7 +214,7 @@ pub(crate) struct SpanFromMir {
/// With the exception of `fn_sig_span`, this should always be contained
/// within `body_span`.
pub(crate) span: Span,
- pub(crate) visible_macro: Option<Symbol>,
+ pub(crate) expn_kind: Option<ExpnKind>,
pub(crate) bcb: BasicCoverageBlock,
}
@@ -223,12 +223,12 @@ fn for_fn_sig(fn_sig_span: Span) -> Self {
Self::new(fn_sig_span, None, START_BCB)
}
- pub(crate) fn new(span: Span, visible_macro: Option<Symbol>, bcb: BasicCoverageBlock) -> Self {
- Self { span, visible_macro, bcb }
+ pub(crate) fn new(span: Span, expn_kind: Option<ExpnKind>, bcb: BasicCoverageBlock) -> Self {
+ Self { span, expn_kind, bcb }
}
pub(crate) fn into_covspan(self) -> Covspan {
- let Self { span, visible_macro: _, bcb } = self;
+ let Self { span, expn_kind: _, bcb } = self;
Covspan { span, bcb }
}
}
diff --git a/compiler/rustc_mir_transform/src/coverage/unexpand.rs b/compiler/rustc_mir_transform/src/coverage/unexpand.rs
index 8cde291..cb86154 100644
--- a/compiler/rustc_mir_transform/src/coverage/unexpand.rs
+++ b/compiler/rustc_mir_transform/src/coverage/unexpand.rs
@@ -1,4 +1,4 @@
-use rustc_span::{ExpnKind, MacroKind, Span, Symbol};
+use rustc_span::{ExpnKind, Span};
/// Walks through the expansion ancestors of `original_span` to find a span that
/// is contained in `body_span` and has the same [syntax context] as `body_span`.
@@ -13,20 +13,15 @@ pub(crate) fn unexpand_into_body_span(original_span: Span, body_span: Span) -> O
///
/// If the returned span represents a bang-macro invocation (e.g. `foo!(..)`),
/// the returned symbol will be the name of that macro (e.g. `foo`).
-pub(crate) fn unexpand_into_body_span_with_visible_macro(
+pub(crate) fn unexpand_into_body_span_with_expn_kind(
original_span: Span,
body_span: Span,
-) -> Option<(Span, Option<Symbol>)> {
+) -> Option<(Span, Option<ExpnKind>)> {
let (span, prev) = unexpand_into_body_span_with_prev(original_span, body_span)?;
- let visible_macro = prev
- .map(|prev| match prev.ctxt().outer_expn_data().kind {
- ExpnKind::Macro(MacroKind::Bang, name) => Some(name),
- _ => None,
- })
- .flatten();
+ let expn_kind = prev.map(|prev| prev.ctxt().outer_expn_data().kind);
- Some((span, visible_macro))
+ Some((span, expn_kind))
}
/// Walks through the expansion ancestors of `original_span` to find a span that
diff --git a/compiler/rustc_mir_transform/src/cross_crate_inline.rs b/compiler/rustc_mir_transform/src/cross_crate_inline.rs
index 50aaed0..ce109ef 100644
--- a/compiler/rustc_mir_transform/src/cross_crate_inline.rs
+++ b/compiler/rustc_mir_transform/src/cross_crate_inline.rs
@@ -10,7 +10,7 @@
use crate::{inline, pass_manager as pm};
-pub fn provide(providers: &mut Providers) {
+pub(super) fn provide(providers: &mut Providers) {
providers.cross_crate_inlinable = cross_crate_inlinable;
}
diff --git a/compiler/rustc_mir_transform/src/ctfe_limit.rs b/compiler/rustc_mir_transform/src/ctfe_limit.rs
index ea473b6..bd58b1b 100644
--- a/compiler/rustc_mir_transform/src/ctfe_limit.rs
+++ b/compiler/rustc_mir_transform/src/ctfe_limit.rs
@@ -8,7 +8,7 @@
use rustc_middle::ty::TyCtxt;
use tracing::instrument;
-pub struct CtfeLimit;
+pub(super) struct CtfeLimit;
impl<'tcx> crate::MirPass<'tcx> for CtfeLimit {
#[instrument(skip(self, _tcx, body))]
diff --git a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs
index 46f7408..79f12be 100644
--- a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs
+++ b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs
@@ -26,7 +26,7 @@
const BLOCK_LIMIT: usize = 100;
const PLACE_LIMIT: usize = 100;
-pub struct DataflowConstProp;
+pub(super) struct DataflowConstProp;
impl<'tcx> crate::MirPass<'tcx> for DataflowConstProp {
fn is_enabled(&self, sess: &rustc_session::Session) -> bool {
@@ -332,7 +332,7 @@ fn handle_switch_int<'mir>(
}
impl<'a, 'tcx> ConstAnalysis<'a, 'tcx> {
- pub fn new(tcx: TyCtxt<'tcx>, body: &'a Body<'tcx>, map: Map<'tcx>) -> Self {
+ fn new(tcx: TyCtxt<'tcx>, body: &'a Body<'tcx>, map: Map<'tcx>) -> Self {
let param_env = tcx.param_env_reveal_all_normalized(body.source.def_id());
Self {
map,
@@ -838,14 +838,14 @@ fn process_projection_elem(
}
}
-struct OperandCollector<'tcx, 'map, 'locals, 'a> {
+struct OperandCollector<'a, 'locals, 'tcx> {
state: &'a State<FlatSet<Scalar>>,
visitor: &'a mut Collector<'tcx, 'locals>,
- ecx: &'map mut InterpCx<'tcx, DummyMachine>,
- map: &'map Map<'tcx>,
+ ecx: &'a mut InterpCx<'tcx, DummyMachine>,
+ map: &'a Map<'tcx>,
}
-impl<'tcx> Visitor<'tcx> for OperandCollector<'tcx, '_, '_, '_> {
+impl<'tcx> Visitor<'tcx> for OperandCollector<'_, '_, 'tcx> {
fn visit_projection_elem(
&mut self,
_: PlaceRef<'tcx>,
diff --git a/compiler/rustc_mir_transform/src/dead_store_elimination.rs b/compiler/rustc_mir_transform/src/dead_store_elimination.rs
index 9081a2e..65c0375 100644
--- a/compiler/rustc_mir_transform/src/dead_store_elimination.rs
+++ b/compiler/rustc_mir_transform/src/dead_store_elimination.rs
@@ -28,7 +28,7 @@
///
/// The `borrowed` set must be a `BitSet` of all the locals that are ever borrowed in this body. It
/// can be generated via the [`borrowed_locals`] function.
-pub fn eliminate<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
+fn eliminate<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
let borrowed_locals = borrowed_locals(body);
// If the user requests complete debuginfo, mark the locals that appear in it as live, so
@@ -127,7 +127,7 @@ pub fn eliminate<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
}
}
-pub enum DeadStoreElimination {
+pub(super) enum DeadStoreElimination {
Initial,
Final,
}
diff --git a/compiler/rustc_mir_transform/src/deduce_param_attrs.rs b/compiler/rustc_mir_transform/src/deduce_param_attrs.rs
index 71af099..e870a71 100644
--- a/compiler/rustc_mir_transform/src/deduce_param_attrs.rs
+++ b/compiler/rustc_mir_transform/src/deduce_param_attrs.rs
@@ -150,7 +150,7 @@ fn type_will_always_be_passed_directly(ty: Ty<'_>) -> bool {
/// body of the function instead of just the signature. These can be useful for optimization
/// purposes on a best-effort basis. We compute them here and store them into the crate metadata so
/// dependent crates can use them.
-pub fn deduced_param_attrs<'tcx>(
+pub(super) fn deduced_param_attrs<'tcx>(
tcx: TyCtxt<'tcx>,
def_id: LocalDefId,
) -> &'tcx [DeducedParamAttrs] {
diff --git a/compiler/rustc_mir_transform/src/deduplicate_blocks.rs b/compiler/rustc_mir_transform/src/deduplicate_blocks.rs
index be50c1d..c8179d5 100644
--- a/compiler/rustc_mir_transform/src/deduplicate_blocks.rs
+++ b/compiler/rustc_mir_transform/src/deduplicate_blocks.rs
@@ -13,7 +13,7 @@
use super::simplify::simplify_cfg;
-pub struct DeduplicateBlocks;
+pub(super) struct DeduplicateBlocks;
impl<'tcx> crate::MirPass<'tcx> for DeduplicateBlocks {
fn is_enabled(&self, sess: &rustc_session::Session) -> bool {
diff --git a/compiler/rustc_mir_transform/src/deref_separator.rs b/compiler/rustc_mir_transform/src/deref_separator.rs
index a878f77..ad7ccef 100644
--- a/compiler/rustc_mir_transform/src/deref_separator.rs
+++ b/compiler/rustc_mir_transform/src/deref_separator.rs
@@ -1,16 +1,15 @@
-use rustc_index::IndexVec;
use rustc_middle::mir::patch::MirPatch;
use rustc_middle::mir::visit::NonUseContext::VarDebugInfo;
use rustc_middle::mir::visit::{MutVisitor, PlaceContext};
use rustc_middle::mir::*;
use rustc_middle::ty::TyCtxt;
-pub struct Derefer;
+pub(super) struct Derefer;
-pub struct DerefChecker<'a, 'tcx> {
+struct DerefChecker<'a, 'tcx> {
tcx: TyCtxt<'tcx>,
patcher: MirPatch<'tcx>,
- local_decls: &'a IndexVec<Local, LocalDecl<'tcx>>,
+ local_decls: &'a LocalDecls<'tcx>,
}
impl<'a, 'tcx> MutVisitor<'tcx> for DerefChecker<'a, 'tcx> {
@@ -67,7 +66,7 @@ fn visit_place(&mut self, place: &mut Place<'tcx>, cntxt: PlaceContext, loc: Loc
}
}
-pub fn deref_finder<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
+pub(super) fn deref_finder<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
let patch = MirPatch::new(body);
let mut checker = DerefChecker { tcx, patcher: patch, local_decls: &body.local_decls };
diff --git a/compiler/rustc_mir_transform/src/dest_prop.rs b/compiler/rustc_mir_transform/src/dest_prop.rs
index 8940a21..175097e 100644
--- a/compiler/rustc_mir_transform/src/dest_prop.rs
+++ b/compiler/rustc_mir_transform/src/dest_prop.rs
@@ -146,7 +146,7 @@
use rustc_mir_dataflow::Analysis;
use tracing::{debug, trace};
-pub struct DestinationPropagation;
+pub(super) struct DestinationPropagation;
impl<'tcx> crate::MirPass<'tcx> for DestinationPropagation {
fn is_enabled(&self, sess: &rustc_session::Session) -> bool {
@@ -163,7 +163,8 @@ fn is_enabled(&self, sess: &rustc_session::Session) -> bool {
fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
let def_id = body.source.def_id();
- let mut allocations = Allocations::default();
+ let mut candidates = Candidates::default();
+ let mut write_info = WriteInfo::default();
trace!(func = ?tcx.def_path_str(def_id));
let borrowed = rustc_mir_dataflow::impls::borrowed_locals(body);
@@ -191,12 +192,7 @@ fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
loop {
// PERF: Can we do something smarter than recalculating the candidates and liveness
// results?
- let mut candidates = find_candidates(
- body,
- &borrowed,
- &mut allocations.candidates,
- &mut allocations.candidates_reverse,
- );
+ candidates.reset_and_find(body, &borrowed);
trace!(?candidates);
dest_prop_mir_dump(tcx, body, &points, &live, round_count);
@@ -204,7 +200,7 @@ fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
&mut candidates,
&points,
&live,
- &mut allocations.write_info,
+ &mut write_info,
body,
);
@@ -253,20 +249,8 @@ fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
}
}
-/// Container for the various allocations that we need.
-///
-/// We store these here and hand out `&mut` access to them, instead of dropping and recreating them
-/// frequently. Everything with a `&'alloc` lifetime points into here.
-#[derive(Default)]
-struct Allocations {
- candidates: FxIndexMap<Local, Vec<Local>>,
- candidates_reverse: FxIndexMap<Local, Vec<Local>>,
- write_info: WriteInfo,
- // PERF: Do this for `MaybeLiveLocals` allocations too.
-}
-
-#[derive(Debug)]
-struct Candidates<'alloc> {
+#[derive(Debug, Default)]
+struct Candidates {
/// The set of candidates we are considering in this optimization.
///
/// We will always merge the key into at most one of its values.
@@ -281,11 +265,12 @@ struct Candidates<'alloc> {
///
/// We will still report that we would like to merge `_1` and `_2` in an attempt to allow us to
/// remove that assignment.
- c: &'alloc mut FxIndexMap<Local, Vec<Local>>,
+ c: FxIndexMap<Local, Vec<Local>>,
+
/// A reverse index of the `c` set; if the `c` set contains `a => Place { local: b, proj }`,
/// then this contains `b => a`.
// PERF: Possibly these should be `SmallVec`s?
- reverse: &'alloc mut FxIndexMap<Local, Vec<Local>>,
+ reverse: FxIndexMap<Local, Vec<Local>>,
}
//////////////////////////////////////////////////////////
@@ -358,19 +343,40 @@ fn visit_statement(&mut self, statement: &mut Statement<'tcx>, location: Locatio
//
// This section enforces bullet point 2
-struct FilterInformation<'a, 'body, 'alloc, 'tcx> {
- body: &'body Body<'tcx>,
+struct FilterInformation<'a, 'tcx> {
+ body: &'a Body<'tcx>,
points: &'a DenseLocationMap,
live: &'a SparseIntervalMatrix<Local, PointIndex>,
- candidates: &'a mut Candidates<'alloc>,
- write_info: &'alloc mut WriteInfo,
+ candidates: &'a mut Candidates,
+ write_info: &'a mut WriteInfo,
at: Location,
}
// We first implement some utility functions which we will expose removing candidates according to
// different needs. Throughout the liveness filtering, the `candidates` are only ever accessed
// through these methods, and not directly.
-impl<'alloc> Candidates<'alloc> {
+impl Candidates {
+ /// Collects the candidates for merging.
+ ///
+ /// This is responsible for enforcing the first and third bullet point.
+ fn reset_and_find<'tcx>(&mut self, body: &Body<'tcx>, borrowed: &BitSet<Local>) {
+ self.c.clear();
+ self.reverse.clear();
+ let mut visitor = FindAssignments { body, candidates: &mut self.c, borrowed };
+ visitor.visit_body(body);
+ // Deduplicate candidates.
+ for (_, cands) in self.c.iter_mut() {
+ cands.sort();
+ cands.dedup();
+ }
+ // Generate the reverse map.
+ for (src, cands) in self.c.iter() {
+ for dest in cands.iter().copied() {
+ self.reverse.entry(dest).or_default().push(*src);
+ }
+ }
+ }
+
/// Just `Vec::retain`, but the condition is inverted and we add debugging output
fn vec_filter_candidates(
src: Local,
@@ -445,7 +451,7 @@ enum CandidateFilter {
Remove,
}
-impl<'a, 'body, 'alloc, 'tcx> FilterInformation<'a, 'body, 'alloc, 'tcx> {
+impl<'a, 'tcx> FilterInformation<'a, 'tcx> {
/// Filters the set of candidates to remove those that conflict.
///
/// The steps we take are exactly those that are outlined at the top of the file. For each
@@ -463,12 +469,12 @@ impl<'a, 'body, 'alloc, 'tcx> FilterInformation<'a, 'body, 'alloc, 'tcx> {
/// before the statement/terminator will correctly report locals that are read in the
/// statement/terminator to be live. We are additionally conservative by treating all written to
/// locals as also being read from.
- fn filter_liveness<'b>(
- candidates: &mut Candidates<'alloc>,
+ fn filter_liveness(
+ candidates: &mut Candidates,
points: &DenseLocationMap,
live: &SparseIntervalMatrix<Local, PointIndex>,
- write_info_alloc: &'alloc mut WriteInfo,
- body: &'b Body<'tcx>,
+ write_info: &mut WriteInfo,
+ body: &Body<'tcx>,
) {
let mut this = FilterInformation {
body,
@@ -477,7 +483,7 @@ fn filter_liveness<'b>(
candidates,
// We don't actually store anything at this scope, we just keep things here to be able
// to reuse the allocation.
- write_info: write_info_alloc,
+ write_info,
// Doesn't matter what we put here, will be overwritten before being used
at: Location::START,
};
@@ -734,40 +740,13 @@ fn places_to_candidate_pair<'tcx>(
Some((a, b))
}
-/// Collects the candidates for merging
-///
-/// This is responsible for enforcing the first and third bullet point.
-fn find_candidates<'alloc, 'tcx>(
- body: &Body<'tcx>,
- borrowed: &BitSet<Local>,
- candidates: &'alloc mut FxIndexMap<Local, Vec<Local>>,
- candidates_reverse: &'alloc mut FxIndexMap<Local, Vec<Local>>,
-) -> Candidates<'alloc> {
- candidates.clear();
- candidates_reverse.clear();
- let mut visitor = FindAssignments { body, candidates, borrowed };
- visitor.visit_body(body);
- // Deduplicate candidates
- for (_, cands) in candidates.iter_mut() {
- cands.sort();
- cands.dedup();
- }
- // Generate the reverse map
- for (src, cands) in candidates.iter() {
- for dest in cands.iter().copied() {
- candidates_reverse.entry(dest).or_default().push(*src);
- }
- }
- Candidates { c: candidates, reverse: candidates_reverse }
-}
-
-struct FindAssignments<'a, 'alloc, 'tcx> {
+struct FindAssignments<'a, 'tcx> {
body: &'a Body<'tcx>,
- candidates: &'alloc mut FxIndexMap<Local, Vec<Local>>,
+ candidates: &'a mut FxIndexMap<Local, Vec<Local>>,
borrowed: &'a BitSet<Local>,
}
-impl<'tcx> Visitor<'tcx> for FindAssignments<'_, '_, 'tcx> {
+impl<'tcx> Visitor<'tcx> for FindAssignments<'_, 'tcx> {
fn visit_statement(&mut self, statement: &Statement<'tcx>, _: Location) {
if let StatementKind::Assign(box (
lhs,
@@ -819,9 +798,9 @@ fn is_local_required(local: Local, body: &Body<'_>) -> bool {
/////////////////////////////////////////////////////////
// MIR Dump
-fn dest_prop_mir_dump<'body, 'tcx>(
+fn dest_prop_mir_dump<'tcx>(
tcx: TyCtxt<'tcx>,
- body: &'body Body<'tcx>,
+ body: &Body<'tcx>,
points: &DenseLocationMap,
live: &SparseIntervalMatrix<Local, PointIndex>,
round: usize,
diff --git a/compiler/rustc_mir_transform/src/dump_mir.rs b/compiler/rustc_mir_transform/src/dump_mir.rs
index 06ae1b4..1640d34 100644
--- a/compiler/rustc_mir_transform/src/dump_mir.rs
+++ b/compiler/rustc_mir_transform/src/dump_mir.rs
@@ -7,7 +7,7 @@
use rustc_middle::ty::TyCtxt;
use rustc_session::config::{OutFileName, OutputType};
-pub struct Marker(pub &'static str);
+pub(super) struct Marker(pub &'static str);
impl<'tcx> crate::MirPass<'tcx> for Marker {
fn name(&self) -> &'static str {
diff --git a/compiler/rustc_mir_transform/src/early_otherwise_branch.rs b/compiler/rustc_mir_transform/src/early_otherwise_branch.rs
index 1c54cd7..3884321 100644
--- a/compiler/rustc_mir_transform/src/early_otherwise_branch.rs
+++ b/compiler/rustc_mir_transform/src/early_otherwise_branch.rs
@@ -90,7 +90,7 @@
/// | ... |
/// =================
/// ```
-pub struct EarlyOtherwiseBranch;
+pub(super) struct EarlyOtherwiseBranch;
impl<'tcx> crate::MirPass<'tcx> for EarlyOtherwiseBranch {
fn is_enabled(&self, sess: &rustc_session::Session) -> bool {
@@ -310,42 +310,28 @@ fn verify_candidate_branch<'tcx>(
) -> bool {
// In order for the optimization to be correct, the branch must...
// ...have exactly one statement
- let [statement] = branch.statements.as_slice() else {
- return false;
- };
- // ...assign the discriminant of `place` in that statement
- let StatementKind::Assign(boxed) = &statement.kind else { return false };
- let (discr_place, Rvalue::Discriminant(from_place)) = &**boxed else { return false };
- if *from_place != place {
- return false;
+ if let [statement] = branch.statements.as_slice()
+ // ...assign the discriminant of `place` in that statement
+ && let StatementKind::Assign(boxed) = &statement.kind
+ && let (discr_place, Rvalue::Discriminant(from_place)) = &**boxed
+ && *from_place == place
+ // ...make that assignment to a local
+ && discr_place.projection.is_empty()
+ // ...terminate on a `SwitchInt` that invalidates that local
+ && let TerminatorKind::SwitchInt { discr: switch_op, targets, .. } =
+ &branch.terminator().kind
+ && *switch_op == Operand::Move(*discr_place)
+ // ...fall through to `destination` if the switch misses
+ && destination == targets.otherwise()
+ // ...have a branch for value `value`
+ && let mut iter = targets.iter()
+ && let Some((target_value, _)) = iter.next()
+ && target_value == value
+ // ...and have no more branches
+ && iter.next().is_none()
+ {
+ true
+ } else {
+ false
}
- // ...make that assignment to a local
- if discr_place.projection.len() != 0 {
- return false;
- }
- // ...terminate on a `SwitchInt` that invalidates that local
- let TerminatorKind::SwitchInt { discr: switch_op, targets, .. } = &branch.terminator().kind
- else {
- return false;
- };
- if *switch_op != Operand::Move(*discr_place) {
- return false;
- }
- // ...fall through to `destination` if the switch misses
- if destination != targets.otherwise() {
- return false;
- }
- // ...have a branch for value `value`
- let mut iter = targets.iter();
- let Some((target_value, _)) = iter.next() else {
- return false;
- };
- if target_value != value {
- return false;
- }
- // ...and have no more branches
- if let Some(_) = iter.next() {
- return false;
- }
- true
}
diff --git a/compiler/rustc_mir_transform/src/elaborate_box_derefs.rs b/compiler/rustc_mir_transform/src/elaborate_box_derefs.rs
index 5dd82f4..367a8c0 100644
--- a/compiler/rustc_mir_transform/src/elaborate_box_derefs.rs
+++ b/compiler/rustc_mir_transform/src/elaborate_box_derefs.rs
@@ -11,7 +11,7 @@
use rustc_target::abi::FieldIdx;
/// Constructs the types used when accessing a Box's pointer
-pub fn build_ptr_tys<'tcx>(
+fn build_ptr_tys<'tcx>(
tcx: TyCtxt<'tcx>,
pointee: Ty<'tcx>,
unique_did: DefId,
@@ -26,7 +26,7 @@ pub fn build_ptr_tys<'tcx>(
}
/// Constructs the projection needed to access a Box's pointer
-pub fn build_projection<'tcx>(
+pub(super) fn build_projection<'tcx>(
unique_ty: Ty<'tcx>,
nonnull_ty: Ty<'tcx>,
ptr_ty: Ty<'tcx>,
@@ -62,11 +62,13 @@ fn visit_place(
let base_ty = self.local_decls[place.local].ty;
// Derefer ensures that derefs are always the first projection
- if place.projection.first() == Some(&PlaceElem::Deref) && base_ty.is_box() {
+ if let Some(PlaceElem::Deref) = place.projection.first()
+ && let Some(boxed_ty) = base_ty.boxed_ty()
+ {
let source_info = self.local_decls[place.local].source_info;
let (unique_ty, nonnull_ty, ptr_ty) =
- build_ptr_tys(tcx, base_ty.boxed_ty(), self.unique_did, self.nonnull_did);
+ build_ptr_tys(tcx, boxed_ty, self.unique_did, self.nonnull_did);
let ptr_local = self.patch.new_temp(ptr_ty, source_info.span);
@@ -86,66 +88,65 @@ fn visit_place(
}
}
-pub struct ElaborateBoxDerefs;
+pub(super) struct ElaborateBoxDerefs;
impl<'tcx> crate::MirPass<'tcx> for ElaborateBoxDerefs {
fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
- if let Some(def_id) = tcx.lang_items().owned_box() {
- let unique_did = tcx.adt_def(def_id).non_enum_variant().fields[FieldIdx::ZERO].did;
+ // If box is not present, this pass doesn't need to do anything.
+ let Some(def_id) = tcx.lang_items().owned_box() else { return };
- let Some(nonnull_def) = tcx.type_of(unique_did).instantiate_identity().ty_adt_def()
- else {
- span_bug!(tcx.def_span(unique_did), "expected Box to contain Unique")
- };
+ let unique_did = tcx.adt_def(def_id).non_enum_variant().fields[FieldIdx::ZERO].did;
- let nonnull_did = nonnull_def.non_enum_variant().fields[FieldIdx::ZERO].did;
+ let Some(nonnull_def) = tcx.type_of(unique_did).instantiate_identity().ty_adt_def() else {
+ span_bug!(tcx.def_span(unique_did), "expected Box to contain Unique")
+ };
- let patch = MirPatch::new(body);
+ let nonnull_did = nonnull_def.non_enum_variant().fields[FieldIdx::ZERO].did;
- let local_decls = &mut body.local_decls;
+ let patch = MirPatch::new(body);
- let mut visitor =
- ElaborateBoxDerefVisitor { tcx, unique_did, nonnull_did, local_decls, patch };
+ let local_decls = &mut body.local_decls;
- for (block, data) in body.basic_blocks.as_mut_preserves_cfg().iter_enumerated_mut() {
- visitor.visit_basic_block_data(block, data);
- }
+ let mut visitor =
+ ElaborateBoxDerefVisitor { tcx, unique_did, nonnull_did, local_decls, patch };
- visitor.patch.apply(body);
+ for (block, data) in body.basic_blocks.as_mut_preserves_cfg().iter_enumerated_mut() {
+ visitor.visit_basic_block_data(block, data);
+ }
- for debug_info in body.var_debug_info.iter_mut() {
- if let VarDebugInfoContents::Place(place) = &mut debug_info.value {
- let mut new_projections: Option<Vec<_>> = None;
+ visitor.patch.apply(body);
- for (base, elem) in place.iter_projections() {
- let base_ty = base.ty(&body.local_decls, tcx).ty;
+ for debug_info in body.var_debug_info.iter_mut() {
+ if let VarDebugInfoContents::Place(place) = &mut debug_info.value {
+ let mut new_projections: Option<Vec<_>> = None;
- if elem == PlaceElem::Deref && base_ty.is_box() {
- // Clone the projections before us, since now we need to mutate them.
- let new_projections =
- new_projections.get_or_insert_with(|| base.projection.to_vec());
+ for (base, elem) in place.iter_projections() {
+ let base_ty = base.ty(&body.local_decls, tcx).ty;
- let (unique_ty, nonnull_ty, ptr_ty) =
- build_ptr_tys(tcx, base_ty.boxed_ty(), unique_did, nonnull_did);
+ if let PlaceElem::Deref = elem
+ && let Some(boxed_ty) = base_ty.boxed_ty()
+ {
+ // Clone the projections before us, since now we need to mutate them.
+ let new_projections =
+ new_projections.get_or_insert_with(|| base.projection.to_vec());
- new_projections.extend_from_slice(&build_projection(
- unique_ty, nonnull_ty, ptr_ty,
- ));
- new_projections.push(PlaceElem::Deref);
- } else if let Some(new_projections) = new_projections.as_mut() {
- // Keep building up our projections list once we've started it.
- new_projections.push(elem);
- }
- }
+ let (unique_ty, nonnull_ty, ptr_ty) =
+ build_ptr_tys(tcx, boxed_ty, unique_did, nonnull_did);
- // Store the mutated projections if we actually changed something.
- if let Some(new_projections) = new_projections {
- place.projection = tcx.mk_place_elems(&new_projections);
+ new_projections
+ .extend_from_slice(&build_projection(unique_ty, nonnull_ty, ptr_ty));
+ new_projections.push(PlaceElem::Deref);
+ } else if let Some(new_projections) = new_projections.as_mut() {
+ // Keep building up our projections list once we've started it.
+ new_projections.push(elem);
}
}
+
+ // Store the mutated projections if we actually changed something.
+ if let Some(new_projections) = new_projections {
+ place.projection = tcx.mk_place_elems(&new_projections);
+ }
}
- } else {
- // box is not present, this pass doesn't need to do anything
}
}
}
diff --git a/compiler/rustc_mir_transform/src/elaborate_drops.rs b/compiler/rustc_mir_transform/src/elaborate_drops.rs
index f4a951e..cb72979 100644
--- a/compiler/rustc_mir_transform/src/elaborate_drops.rs
+++ b/compiler/rustc_mir_transform/src/elaborate_drops.rs
@@ -47,7 +47,7 @@
/// }
/// }
/// ```
-pub struct ElaborateDrops;
+pub(super) struct ElaborateDrops;
impl<'tcx> crate::MirPass<'tcx> for ElaborateDrops {
#[instrument(level = "trace", skip(self, tcx, body))]
@@ -98,9 +98,9 @@ fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
/// Records unwind edges which are known to be unreachable, because they are in `drop` terminators
/// that can't drop anything.
#[instrument(level = "trace", skip(body, flow_inits), ret)]
-fn compute_dead_unwinds<'mir, 'tcx>(
- body: &'mir Body<'tcx>,
- flow_inits: &mut ResultsCursor<'mir, 'tcx, MaybeInitializedPlaces<'_, 'mir, 'tcx>>,
+fn compute_dead_unwinds<'a, 'tcx>(
+ body: &'a Body<'tcx>,
+ flow_inits: &mut ResultsCursor<'a, 'tcx, MaybeInitializedPlaces<'a, 'tcx>>,
) -> BitSet<BasicBlock> {
// We only need to do this pass once, because unwind edges can only
// reach cleanup blocks, which can't have unwind edges themselves.
@@ -121,12 +121,12 @@ fn compute_dead_unwinds<'mir, 'tcx>(
dead_unwinds
}
-struct InitializationData<'a, 'mir, 'tcx> {
- inits: ResultsCursor<'mir, 'tcx, MaybeInitializedPlaces<'a, 'mir, 'tcx>>,
- uninits: ResultsCursor<'mir, 'tcx, MaybeUninitializedPlaces<'a, 'mir, 'tcx>>,
+struct InitializationData<'a, 'tcx> {
+ inits: ResultsCursor<'a, 'tcx, MaybeInitializedPlaces<'a, 'tcx>>,
+ uninits: ResultsCursor<'a, 'tcx, MaybeUninitializedPlaces<'a, 'tcx>>,
}
-impl InitializationData<'_, '_, '_> {
+impl InitializationData<'_, '_> {
fn seek_before(&mut self, loc: Location) {
self.inits.seek_before_primary_effect(loc);
self.uninits.seek_before_primary_effect(loc);
@@ -137,45 +137,35 @@ fn maybe_live_dead(&self, path: MovePathIndex) -> (bool, bool) {
}
}
-struct Elaborator<'a, 'b, 'mir, 'tcx> {
- ctxt: &'a mut ElaborateDropsCtxt<'b, 'mir, 'tcx>,
-}
-
-impl fmt::Debug for Elaborator<'_, '_, '_, '_> {
- fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result {
- Ok(())
- }
-}
-
-impl<'a, 'tcx> DropElaborator<'a, 'tcx> for Elaborator<'a, '_, '_, 'tcx> {
+impl<'a, 'tcx> DropElaborator<'a, 'tcx> for ElaborateDropsCtxt<'a, 'tcx> {
type Path = MovePathIndex;
fn patch(&mut self) -> &mut MirPatch<'tcx> {
- &mut self.ctxt.patch
+ &mut self.patch
}
fn body(&self) -> &'a Body<'tcx> {
- self.ctxt.body
+ self.body
}
fn tcx(&self) -> TyCtxt<'tcx> {
- self.ctxt.tcx
+ self.tcx
}
fn param_env(&self) -> ty::ParamEnv<'tcx> {
- self.ctxt.param_env()
+ self.param_env()
}
#[instrument(level = "debug", skip(self), ret)]
fn drop_style(&self, path: Self::Path, mode: DropFlagMode) -> DropStyle {
let ((maybe_live, maybe_dead), multipart) = match mode {
- DropFlagMode::Shallow => (self.ctxt.init_data.maybe_live_dead(path), false),
+ DropFlagMode::Shallow => (self.init_data.maybe_live_dead(path), false),
DropFlagMode::Deep => {
let mut some_live = false;
let mut some_dead = false;
let mut children_count = 0;
- on_all_children_bits(self.ctxt.move_data(), path, |child| {
- let (live, dead) = self.ctxt.init_data.maybe_live_dead(child);
+ on_all_children_bits(self.move_data(), path, |child| {
+ let (live, dead) = self.init_data.maybe_live_dead(child);
debug!("elaborate_drop: state({:?}) = {:?}", child, (live, dead));
some_live |= live;
some_dead |= dead;
@@ -195,25 +185,25 @@ fn drop_style(&self, path: Self::Path, mode: DropFlagMode) -> DropStyle {
fn clear_drop_flag(&mut self, loc: Location, path: Self::Path, mode: DropFlagMode) {
match mode {
DropFlagMode::Shallow => {
- self.ctxt.set_drop_flag(loc, path, DropFlagState::Absent);
+ self.set_drop_flag(loc, path, DropFlagState::Absent);
}
DropFlagMode::Deep => {
- on_all_children_bits(self.ctxt.move_data(), path, |child| {
- self.ctxt.set_drop_flag(loc, child, DropFlagState::Absent)
+ on_all_children_bits(self.move_data(), path, |child| {
+ self.set_drop_flag(loc, child, DropFlagState::Absent)
});
}
}
}
fn field_subpath(&self, path: Self::Path, field: FieldIdx) -> Option<Self::Path> {
- rustc_mir_dataflow::move_path_children_matching(self.ctxt.move_data(), path, |e| match e {
+ rustc_mir_dataflow::move_path_children_matching(self.move_data(), path, |e| match e {
ProjectionElem::Field(idx, _) => idx == field,
_ => false,
})
}
fn array_subpath(&self, path: Self::Path, index: u64, size: u64) -> Option<Self::Path> {
- rustc_mir_dataflow::move_path_children_matching(self.ctxt.move_data(), path, |e| match e {
+ rustc_mir_dataflow::move_path_children_matching(self.move_data(), path, |e| match e {
ProjectionElem::ConstantIndex { offset, min_length, from_end } => {
debug_assert!(size == min_length, "min_length should be exact for arrays");
assert!(!from_end, "from_end should not be used for array element ConstantIndex");
@@ -224,34 +214,40 @@ fn array_subpath(&self, path: Self::Path, index: u64, size: u64) -> Option<Self:
}
fn deref_subpath(&self, path: Self::Path) -> Option<Self::Path> {
- rustc_mir_dataflow::move_path_children_matching(self.ctxt.move_data(), path, |e| {
+ rustc_mir_dataflow::move_path_children_matching(self.move_data(), path, |e| {
e == ProjectionElem::Deref
})
}
fn downcast_subpath(&self, path: Self::Path, variant: VariantIdx) -> Option<Self::Path> {
- rustc_mir_dataflow::move_path_children_matching(self.ctxt.move_data(), path, |e| match e {
+ rustc_mir_dataflow::move_path_children_matching(self.move_data(), path, |e| match e {
ProjectionElem::Downcast(_, idx) => idx == variant,
_ => false,
})
}
fn get_drop_flag(&mut self, path: Self::Path) -> Option<Operand<'tcx>> {
- self.ctxt.drop_flag(path).map(Operand::Copy)
+ self.drop_flag(path).map(Operand::Copy)
}
}
-struct ElaborateDropsCtxt<'a, 'mir, 'tcx> {
+struct ElaborateDropsCtxt<'a, 'tcx> {
tcx: TyCtxt<'tcx>,
- body: &'mir Body<'tcx>,
+ body: &'a Body<'tcx>,
env: &'a MoveDataParamEnv<'tcx>,
- init_data: InitializationData<'a, 'mir, 'tcx>,
+ init_data: InitializationData<'a, 'tcx>,
drop_flags: IndexVec<MovePathIndex, Option<Local>>,
patch: MirPatch<'tcx>,
}
-impl<'b, 'mir, 'tcx> ElaborateDropsCtxt<'b, 'mir, 'tcx> {
- fn move_data(&self) -> &'b MoveData<'tcx> {
+impl fmt::Debug for ElaborateDropsCtxt<'_, '_> {
+ fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ Ok(())
+ }
+}
+
+impl<'a, 'tcx> ElaborateDropsCtxt<'a, 'tcx> {
+ fn move_data(&self) -> &'a MoveData<'tcx> {
&self.env.move_data
}
@@ -370,15 +366,7 @@ fn elaborate_drops(&mut self) {
}
};
self.init_data.seek_before(self.body.terminator_loc(bb));
- elaborate_drop(
- &mut Elaborator { ctxt: self },
- terminator.source_info,
- place,
- path,
- target,
- unwind,
- bb,
- )
+ elaborate_drop(self, terminator.source_info, place, path, target, unwind, bb)
}
LookupResult::Parent(None) => {}
LookupResult::Parent(Some(_)) => {
diff --git a/compiler/rustc_mir_transform/src/errors.rs b/compiler/rustc_mir_transform/src/errors.rs
index 2703dc5..9a93c3a 100644
--- a/compiler/rustc_mir_transform/src/errors.rs
+++ b/compiler/rustc_mir_transform/src/errors.rs
@@ -64,7 +64,7 @@ fn decorate_lint<'b>(self, diag: &'b mut Diag<'a, ()>) {
}
impl AssertLintKind {
- pub fn lint(&self) -> &'static Lint {
+ pub(crate) fn lint(&self) -> &'static Lint {
match self {
AssertLintKind::ArithmeticOverflow => lint::builtin::ARITHMETIC_OVERFLOW,
AssertLintKind::UnconditionalPanic => lint::builtin::UNCONDITIONAL_PANIC,
diff --git a/compiler/rustc_mir_transform/src/function_item_references.rs b/compiler/rustc_mir_transform/src/function_item_references.rs
index 199fd0f..0efaa17 100644
--- a/compiler/rustc_mir_transform/src/function_item_references.rs
+++ b/compiler/rustc_mir_transform/src/function_item_references.rs
@@ -11,7 +11,7 @@
use crate::errors;
-pub struct FunctionItemReferences;
+pub(super) struct FunctionItemReferences;
impl<'tcx> crate::MirLint<'tcx> for FunctionItemReferences {
fn run_lint(&self, tcx: TyCtxt<'tcx>, body: &Body<'tcx>) {
diff --git a/compiler/rustc_mir_transform/src/gvn.rs b/compiler/rustc_mir_transform/src/gvn.rs
index df0fcc4..e5d2b13 100644
--- a/compiler/rustc_mir_transform/src/gvn.rs
+++ b/compiler/rustc_mir_transform/src/gvn.rs
@@ -109,7 +109,7 @@
use crate::ssa::{AssignedValue, SsaLocals};
-pub struct GVN;
+pub(super) struct GVN;
impl<'tcx> crate::MirPass<'tcx> for GVN {
fn is_enabled(&self, sess: &rustc_session::Session) -> bool {
diff --git a/compiler/rustc_mir_transform/src/inline.rs b/compiler/rustc_mir_transform/src/inline.rs
index 6cc7e0e..03ef808 100644
--- a/compiler/rustc_mir_transform/src/inline.rs
+++ b/compiler/rustc_mir_transform/src/inline.rs
@@ -32,9 +32,11 @@
const TOP_DOWN_DEPTH_LIMIT: usize = 5;
+// Made public so that `mir_drops_elaborated_and_const_checked` can be overridden
+// by custom rustc drivers, running all the steps by themselves. See #114628.
pub struct Inline;
-#[derive(Copy, Clone, Debug)]
+#[derive(Clone, Debug)]
struct CallSite<'tcx> {
callee: Instance<'tcx>,
fn_sig: ty::PolyFnSig<'tcx>,
@@ -156,7 +158,6 @@ fn process_blocks(&mut self, caller_body: &mut Body<'tcx>, blocks: Range<BasicBl
match self.try_inlining(caller_body, &callsite) {
Err(reason) => {
debug!("not-inlined {} [{}]", callsite.callee, reason);
- continue;
}
Ok(new_blocks) => {
debug!("inlined {}", callsite.callee);
@@ -638,7 +639,7 @@ fn dest_needs_borrow(place: Place<'_>) -> bool {
);
let dest_ty = dest.ty(caller_body, self.tcx);
let temp =
- Place::from(self.new_call_temp(caller_body, &callsite, dest_ty, return_block));
+ Place::from(self.new_call_temp(caller_body, callsite, dest_ty, return_block));
caller_body[callsite.block].statements.push(Statement {
source_info: callsite.source_info,
kind: StatementKind::Assign(Box::new((temp, dest))),
@@ -657,7 +658,7 @@ fn dest_needs_borrow(place: Place<'_>) -> bool {
true,
self.new_call_temp(
caller_body,
- &callsite,
+ callsite,
destination.ty(caller_body, self.tcx).ty,
return_block,
),
@@ -665,7 +666,7 @@ fn dest_needs_borrow(place: Place<'_>) -> bool {
};
// Copy the arguments if needed.
- let args = self.make_call_args(args, &callsite, caller_body, &callee_body, return_block);
+ let args = self.make_call_args(args, callsite, caller_body, &callee_body, return_block);
let mut integrator = Integrator {
args: &args,
diff --git a/compiler/rustc_mir_transform/src/instsimplify.rs b/compiler/rustc_mir_transform/src/instsimplify.rs
index 4fbfa74..a9591bf 100644
--- a/compiler/rustc_mir_transform/src/instsimplify.rs
+++ b/compiler/rustc_mir_transform/src/instsimplify.rs
@@ -13,13 +13,13 @@
use crate::simplify::simplify_duplicate_switch_targets;
use crate::take_array;
-pub enum InstSimplify {
+pub(super) enum InstSimplify {
BeforeInline,
AfterSimplifyCfg,
}
impl InstSimplify {
- pub fn name(&self) -> &'static str {
+ fn name(&self) -> &'static str {
match self {
InstSimplify::BeforeInline => "InstSimplify-before-inline",
InstSimplify::AfterSimplifyCfg => "InstSimplify-after-simplifycfg",
diff --git a/compiler/rustc_mir_transform/src/jump_threading.rs b/compiler/rustc_mir_transform/src/jump_threading.rs
index 02dd56e..e950c2c 100644
--- a/compiler/rustc_mir_transform/src/jump_threading.rs
+++ b/compiler/rustc_mir_transform/src/jump_threading.rs
@@ -55,7 +55,7 @@
use crate::cost_checker::CostChecker;
-pub struct JumpThreading;
+pub(super) struct JumpThreading;
const MAX_BACKTRACK: usize = 5;
const MAX_COST: usize = 100;
diff --git a/compiler/rustc_mir_transform/src/known_panics_lint.rs b/compiler/rustc_mir_transform/src/known_panics_lint.rs
index 61405fb..e964310 100644
--- a/compiler/rustc_mir_transform/src/known_panics_lint.rs
+++ b/compiler/rustc_mir_transform/src/known_panics_lint.rs
@@ -26,7 +26,7 @@
use crate::errors::{AssertLint, AssertLintKind};
-pub struct KnownPanicsLint;
+pub(super) struct KnownPanicsLint;
impl<'tcx> crate::MirLint<'tcx> for KnownPanicsLint {
fn run_lint(&self, tcx: TyCtxt<'tcx>, body: &Body<'tcx>) {
@@ -852,7 +852,7 @@ fn visit_basic_block_data(&mut self, block: BasicBlock, data: &BasicBlockData<'t
/// The mode that `ConstProp` is allowed to run in for a given `Local`.
#[derive(Clone, Copy, Debug, PartialEq)]
-pub enum ConstPropMode {
+enum ConstPropMode {
/// The `Local` can be propagated into and reads of this `Local` can also be propagated.
FullConstProp,
/// The `Local` can only be propagated into and from its own block.
@@ -864,7 +864,7 @@ pub enum ConstPropMode {
/// A visitor that determines locals in a MIR body
/// that can be const propagated
-pub struct CanConstProp {
+struct CanConstProp {
can_const_prop: IndexVec<Local, ConstPropMode>,
// False at the beginning. Once set, no more assignments are allowed to that local.
found_assignment: BitSet<Local>,
@@ -872,7 +872,7 @@ pub struct CanConstProp {
impl CanConstProp {
/// Returns true if `local` can be propagated
- pub fn check<'tcx>(
+ fn check<'tcx>(
tcx: TyCtxt<'tcx>,
param_env: ParamEnv<'tcx>,
body: &Body<'tcx>,
diff --git a/compiler/rustc_mir_transform/src/large_enums.rs b/compiler/rustc_mir_transform/src/large_enums.rs
index f02ba71..f61cf23 100644
--- a/compiler/rustc_mir_transform/src/large_enums.rs
+++ b/compiler/rustc_mir_transform/src/large_enums.rs
@@ -23,7 +23,7 @@
/// In summary, what this does is at runtime determine which enum variant is active,
/// and instead of copying all the bytes of the largest possible variant,
/// copy only the bytes for the currently active variant.
-pub struct EnumSizeOpt {
+pub(super) struct EnumSizeOpt {
pub(crate) discrepancy: u64,
}
diff --git a/compiler/rustc_mir_transform/src/lib.rs b/compiler/rustc_mir_transform/src/lib.rs
index 62e73ba..0bbbf04 100644
--- a/compiler/rustc_mir_transform/src/lib.rs
+++ b/compiler/rustc_mir_transform/src/lib.rs
@@ -11,6 +11,7 @@
#![feature(round_char_boundary)]
#![feature(try_blocks)]
#![feature(yeet_expr)]
+#![warn(unreachable_pub)]
// tidy-alphabetical-end
use hir::ConstContext;
@@ -72,6 +73,8 @@
mod ffi_unwind_calls;
mod function_item_references;
mod gvn;
+// Made public so that `mir_drops_elaborated_and_const_checked` can be overridden
+// by custom rustc drivers, running all the steps by themselves. See #114628.
pub mod inline;
mod instsimplify;
mod jump_threading;
@@ -459,8 +462,8 @@ fn mir_drops_elaborated_and_const_checked(tcx: TyCtxt<'_>, def: LocalDefId) -> &
tcx.alloc_steal_mir(body)
}
-// Made public such that `mir_drops_elaborated_and_const_checked` can be overridden
-// by custom rustc drivers, running all the steps by themselves.
+// Made public so that `mir_drops_elaborated_and_const_checked` can be overridden
+// by custom rustc drivers, running all the steps by themselves. See #114628.
pub fn run_analysis_to_runtime_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
assert!(body.phase == MirPhase::Analysis(AnalysisPhase::Initial));
let did = body.source.def_id();
diff --git a/compiler/rustc_mir_transform/src/lint.rs b/compiler/rustc_mir_transform/src/lint.rs
index 7460680..2373399 100644
--- a/compiler/rustc_mir_transform/src/lint.rs
+++ b/compiler/rustc_mir_transform/src/lint.rs
@@ -13,7 +13,7 @@
use rustc_mir_dataflow::storage::always_storage_live_locals;
use rustc_mir_dataflow::{Analysis, ResultsCursor};
-pub fn lint_body<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>, when: String) {
+pub(super) fn lint_body<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>, when: String) {
let always_live_locals = &always_storage_live_locals(body);
let maybe_storage_live = MaybeStorageLive::new(Cow::Borrowed(always_live_locals))
diff --git a/compiler/rustc_mir_transform/src/lower_intrinsics.rs b/compiler/rustc_mir_transform/src/lower_intrinsics.rs
index 55eec33..6d63560 100644
--- a/compiler/rustc_mir_transform/src/lower_intrinsics.rs
+++ b/compiler/rustc_mir_transform/src/lower_intrinsics.rs
@@ -7,7 +7,7 @@
use crate::take_array;
-pub struct LowerIntrinsics;
+pub(super) struct LowerIntrinsics;
impl<'tcx> crate::MirPass<'tcx> for LowerIntrinsics {
fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
@@ -35,20 +35,19 @@ fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
terminator.kind = TerminatorKind::Goto { target };
}
sym::forget => {
- if let Some(target) = *target {
- block.statements.push(Statement {
- source_info: terminator.source_info,
- kind: StatementKind::Assign(Box::new((
- *destination,
- Rvalue::Use(Operand::Constant(Box::new(ConstOperand {
- span: terminator.source_info.span,
- user_ty: None,
- const_: Const::zero_sized(tcx.types.unit),
- }))),
- ))),
- });
- terminator.kind = TerminatorKind::Goto { target };
- }
+ let target = target.unwrap();
+ block.statements.push(Statement {
+ source_info: terminator.source_info,
+ kind: StatementKind::Assign(Box::new((
+ *destination,
+ Rvalue::Use(Operand::Constant(Box::new(ConstOperand {
+ span: terminator.source_info.span,
+ user_ty: None,
+ const_: Const::zero_sized(tcx.types.unit),
+ }))),
+ ))),
+ });
+ terminator.kind = TerminatorKind::Goto { target };
}
sym::copy_nonoverlapping => {
let target = target.unwrap();
@@ -121,43 +120,41 @@ fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
terminator.kind = TerminatorKind::Goto { target };
}
sym::add_with_overflow | sym::sub_with_overflow | sym::mul_with_overflow => {
- if let Some(target) = *target {
- let Ok([lhs, rhs]) = take_array(args) else {
- bug!("Wrong arguments for {} intrinsic", intrinsic.name);
- };
- let bin_op = match intrinsic.name {
- sym::add_with_overflow => BinOp::AddWithOverflow,
- sym::sub_with_overflow => BinOp::SubWithOverflow,
- sym::mul_with_overflow => BinOp::MulWithOverflow,
- _ => bug!("unexpected intrinsic"),
- };
- block.statements.push(Statement {
- source_info: terminator.source_info,
- kind: StatementKind::Assign(Box::new((
- *destination,
- Rvalue::BinaryOp(bin_op, Box::new((lhs.node, rhs.node))),
- ))),
- });
- terminator.kind = TerminatorKind::Goto { target };
- }
+ let target = target.unwrap();
+ let Ok([lhs, rhs]) = take_array(args) else {
+ bug!("Wrong arguments for {} intrinsic", intrinsic.name);
+ };
+ let bin_op = match intrinsic.name {
+ sym::add_with_overflow => BinOp::AddWithOverflow,
+ sym::sub_with_overflow => BinOp::SubWithOverflow,
+ sym::mul_with_overflow => BinOp::MulWithOverflow,
+ _ => bug!("unexpected intrinsic"),
+ };
+ block.statements.push(Statement {
+ source_info: terminator.source_info,
+ kind: StatementKind::Assign(Box::new((
+ *destination,
+ Rvalue::BinaryOp(bin_op, Box::new((lhs.node, rhs.node))),
+ ))),
+ });
+ terminator.kind = TerminatorKind::Goto { target };
}
sym::size_of | sym::min_align_of => {
- if let Some(target) = *target {
- let tp_ty = generic_args.type_at(0);
- let null_op = match intrinsic.name {
- sym::size_of => NullOp::SizeOf,
- sym::min_align_of => NullOp::AlignOf,
- _ => bug!("unexpected intrinsic"),
- };
- block.statements.push(Statement {
- source_info: terminator.source_info,
- kind: StatementKind::Assign(Box::new((
- *destination,
- Rvalue::NullaryOp(null_op, tp_ty),
- ))),
- });
- terminator.kind = TerminatorKind::Goto { target };
- }
+ let target = target.unwrap();
+ let tp_ty = generic_args.type_at(0);
+ let null_op = match intrinsic.name {
+ sym::size_of => NullOp::SizeOf,
+ sym::min_align_of => NullOp::AlignOf,
+ _ => bug!("unexpected intrinsic"),
+ };
+ block.statements.push(Statement {
+ source_info: terminator.source_info,
+ kind: StatementKind::Assign(Box::new((
+ *destination,
+ Rvalue::NullaryOp(null_op, tp_ty),
+ ))),
+ });
+ terminator.kind = TerminatorKind::Goto { target };
}
sym::read_via_copy => {
let Ok([arg]) = take_array(args) else {
@@ -219,17 +216,23 @@ fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
terminator.kind = TerminatorKind::Goto { target };
}
sym::discriminant_value => {
- if let (Some(target), Some(arg)) = (*target, args[0].node.place()) {
- let arg = tcx.mk_place_deref(arg);
- block.statements.push(Statement {
- source_info: terminator.source_info,
- kind: StatementKind::Assign(Box::new((
- *destination,
- Rvalue::Discriminant(arg),
- ))),
- });
- terminator.kind = TerminatorKind::Goto { target };
- }
+ let target = target.unwrap();
+ let Ok([arg]) = take_array(args) else {
+ span_bug!(
+ terminator.source_info.span,
+ "Wrong arguments for discriminant_value intrinsic"
+ );
+ };
+ let arg = arg.node.place().unwrap();
+ let arg = tcx.mk_place_deref(arg);
+ block.statements.push(Statement {
+ source_info: terminator.source_info,
+ kind: StatementKind::Assign(Box::new((
+ *destination,
+ Rvalue::Discriminant(arg),
+ ))),
+ });
+ terminator.kind = TerminatorKind::Goto { target };
}
sym::offset => {
let target = target.unwrap();
@@ -267,7 +270,6 @@ fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
Rvalue::Cast(CastKind::Transmute, arg.node, dst_ty),
))),
});
-
if let Some(target) = *target {
terminator.kind = TerminatorKind::Goto { target };
} else {
@@ -299,7 +301,6 @@ fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
Rvalue::Aggregate(Box::new(kind), fields.into()),
))),
});
-
terminator.kind = TerminatorKind::Goto { target };
}
sym::ptr_metadata => {
diff --git a/compiler/rustc_mir_transform/src/lower_slice_len.rs b/compiler/rustc_mir_transform/src/lower_slice_len.rs
index 555309a..ca59d4d 100644
--- a/compiler/rustc_mir_transform/src/lower_slice_len.rs
+++ b/compiler/rustc_mir_transform/src/lower_slice_len.rs
@@ -5,7 +5,7 @@
use rustc_middle::mir::*;
use rustc_middle::ty::TyCtxt;
-pub struct LowerSliceLenCalls;
+pub(super) struct LowerSliceLenCalls;
impl<'tcx> crate::MirPass<'tcx> for LowerSliceLenCalls {
fn is_enabled(&self, sess: &rustc_session::Session) -> bool {
@@ -17,7 +17,7 @@ fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
}
}
-pub fn lower_slice_len_calls<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
+fn lower_slice_len_calls<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
let language_items = tcx.lang_items();
let Some(slice_len_fn_item_def_id) = language_items.slice_len_fn() else {
// there is no lang item to compare to :)
diff --git a/compiler/rustc_mir_transform/src/match_branches.rs b/compiler/rustc_mir_transform/src/match_branches.rs
index 233b39f..2a2616b 100644
--- a/compiler/rustc_mir_transform/src/match_branches.rs
+++ b/compiler/rustc_mir_transform/src/match_branches.rs
@@ -10,7 +10,7 @@
use super::simplify::simplify_cfg;
-pub struct MatchBranchSimplification;
+pub(super) struct MatchBranchSimplification;
impl<'tcx> crate::MirPass<'tcx> for MatchBranchSimplification {
fn is_enabled(&self, sess: &rustc_session::Session) -> bool {
diff --git a/compiler/rustc_mir_transform/src/mentioned_items.rs b/compiler/rustc_mir_transform/src/mentioned_items.rs
index 41ce03c..7f9d0a5 100644
--- a/compiler/rustc_mir_transform/src/mentioned_items.rs
+++ b/compiler/rustc_mir_transform/src/mentioned_items.rs
@@ -5,7 +5,7 @@
use rustc_session::Session;
use rustc_span::source_map::Spanned;
-pub struct MentionedItems;
+pub(super) struct MentionedItems;
struct MentionedItemsVisitor<'a, 'tcx> {
tcx: TyCtxt<'tcx>,
diff --git a/compiler/rustc_mir_transform/src/multiple_return_terminators.rs b/compiler/rustc_mir_transform/src/multiple_return_terminators.rs
index 1b4972d..b6d6ef5 100644
--- a/compiler/rustc_mir_transform/src/multiple_return_terminators.rs
+++ b/compiler/rustc_mir_transform/src/multiple_return_terminators.rs
@@ -7,7 +7,7 @@
use crate::simplify;
-pub struct MultipleReturnTerminators;
+pub(super) struct MultipleReturnTerminators;
impl<'tcx> crate::MirPass<'tcx> for MultipleReturnTerminators {
fn is_enabled(&self, sess: &rustc_session::Session) -> bool {
diff --git a/compiler/rustc_mir_transform/src/nrvo.rs b/compiler/rustc_mir_transform/src/nrvo.rs
index 94573a9..98fa149 100644
--- a/compiler/rustc_mir_transform/src/nrvo.rs
+++ b/compiler/rustc_mir_transform/src/nrvo.rs
@@ -30,7 +30,7 @@
///
/// [#47954]: https://github.com/rust-lang/rust/pull/47954
/// [#71003]: https://github.com/rust-lang/rust/pull/71003
-pub struct RenameReturnPlace;
+pub(super) struct RenameReturnPlace;
impl<'tcx> crate::MirPass<'tcx> for RenameReturnPlace {
fn is_enabled(&self, sess: &rustc_session::Session) -> bool {
diff --git a/compiler/rustc_mir_transform/src/pass_manager.rs b/compiler/rustc_mir_transform/src/pass_manager.rs
index 28d4e1a..60ece5e 100644
--- a/compiler/rustc_mir_transform/src/pass_manager.rs
+++ b/compiler/rustc_mir_transform/src/pass_manager.rs
@@ -269,12 +269,7 @@ pub(super) fn validate_body<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>, when
validate::Validator { when, mir_phase: body.phase }.run_pass(tcx, body);
}
-pub(super) fn dump_mir_for_pass<'tcx>(
- tcx: TyCtxt<'tcx>,
- body: &Body<'tcx>,
- pass_name: &str,
- is_after: bool,
-) {
+fn dump_mir_for_pass<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>, pass_name: &str, is_after: bool) {
mir::dump_mir(
tcx,
true,
diff --git a/compiler/rustc_mir_transform/src/prettify.rs b/compiler/rustc_mir_transform/src/prettify.rs
index ad71c62..ef011d2 100644
--- a/compiler/rustc_mir_transform/src/prettify.rs
+++ b/compiler/rustc_mir_transform/src/prettify.rs
@@ -15,7 +15,7 @@
///
/// Thus after this pass, all the successors of a block are later than it in the
/// `IndexVec`, unless that successor is a back-edge (such as from a loop).
-pub struct ReorderBasicBlocks;
+pub(super) struct ReorderBasicBlocks;
impl<'tcx> crate::MirPass<'tcx> for ReorderBasicBlocks {
fn is_enabled(&self, _session: &Session) -> bool {
@@ -43,7 +43,7 @@ fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
/// assigned or referenced will have a smaller number.
///
/// (Does not reorder arguments nor the [`RETURN_PLACE`].)
-pub struct ReorderLocals;
+pub(super) struct ReorderLocals;
impl<'tcx> crate::MirPass<'tcx> for ReorderLocals {
fn is_enabled(&self, _session: &Session) -> bool {
@@ -135,8 +135,8 @@ fn visit_local(&mut self, l: Local, context: PlaceContext, _location: Location)
}
struct LocalUpdater<'tcx> {
- pub map: IndexVec<Local, Local>,
- pub tcx: TyCtxt<'tcx>,
+ map: IndexVec<Local, Local>,
+ tcx: TyCtxt<'tcx>,
}
impl<'tcx> MutVisitor<'tcx> for LocalUpdater<'tcx> {
diff --git a/compiler/rustc_mir_transform/src/promote_consts.rs b/compiler/rustc_mir_transform/src/promote_consts.rs
index cf0a569..65309f6 100644
--- a/compiler/rustc_mir_transform/src/promote_consts.rs
+++ b/compiler/rustc_mir_transform/src/promote_consts.rs
@@ -37,7 +37,7 @@
/// After this pass is run, `promoted_fragments` will hold the MIR body corresponding to each
/// newly created `Constant`.
#[derive(Default)]
-pub struct PromoteTemps<'tcx> {
+pub(super) struct PromoteTemps<'tcx> {
pub promoted_fragments: Cell<IndexVec<Promoted, Body<'tcx>>>,
}
diff --git a/compiler/rustc_mir_transform/src/ref_prop.rs b/compiler/rustc_mir_transform/src/ref_prop.rs
index 4a447d2..25b9878 100644
--- a/compiler/rustc_mir_transform/src/ref_prop.rs
+++ b/compiler/rustc_mir_transform/src/ref_prop.rs
@@ -70,7 +70,7 @@
///
/// For immutable borrows, we do not need to preserve such uniqueness property,
/// so we perform all the possible instantiations without removing the `_1 = &_2` statement.
-pub struct ReferencePropagation;
+pub(super) struct ReferencePropagation;
impl<'tcx> crate::MirPass<'tcx> for ReferencePropagation {
fn is_enabled(&self, sess: &rustc_session::Session) -> bool {
diff --git a/compiler/rustc_mir_transform/src/remove_noop_landing_pads.rs b/compiler/rustc_mir_transform/src/remove_noop_landing_pads.rs
index ccba8d0..37197c3 100644
--- a/compiler/rustc_mir_transform/src/remove_noop_landing_pads.rs
+++ b/compiler/rustc_mir_transform/src/remove_noop_landing_pads.rs
@@ -8,7 +8,7 @@
/// A pass that removes noop landing pads and replaces jumps to them with
/// `UnwindAction::Continue`. This is important because otherwise LLVM generates
/// terrible code for these.
-pub struct RemoveNoopLandingPads;
+pub(super) struct RemoveNoopLandingPads;
impl<'tcx> crate::MirPass<'tcx> for RemoveNoopLandingPads {
fn is_enabled(&self, sess: &rustc_session::Session) -> bool {
diff --git a/compiler/rustc_mir_transform/src/remove_place_mention.rs b/compiler/rustc_mir_transform/src/remove_place_mention.rs
index 5801fde..71399eb 100644
--- a/compiler/rustc_mir_transform/src/remove_place_mention.rs
+++ b/compiler/rustc_mir_transform/src/remove_place_mention.rs
@@ -4,7 +4,7 @@
use rustc_middle::ty::TyCtxt;
use tracing::trace;
-pub struct RemovePlaceMention;
+pub(super) struct RemovePlaceMention;
impl<'tcx> crate::MirPass<'tcx> for RemovePlaceMention {
fn is_enabled(&self, sess: &rustc_session::Session) -> bool {
diff --git a/compiler/rustc_mir_transform/src/remove_storage_markers.rs b/compiler/rustc_mir_transform/src/remove_storage_markers.rs
index 329b30d..3ecb4a8 100644
--- a/compiler/rustc_mir_transform/src/remove_storage_markers.rs
+++ b/compiler/rustc_mir_transform/src/remove_storage_markers.rs
@@ -4,7 +4,7 @@
use rustc_middle::ty::TyCtxt;
use tracing::trace;
-pub struct RemoveStorageMarkers;
+pub(super) struct RemoveStorageMarkers;
impl<'tcx> crate::MirPass<'tcx> for RemoveStorageMarkers {
fn is_enabled(&self, sess: &rustc_session::Session) -> bool {
diff --git a/compiler/rustc_mir_transform/src/remove_uninit_drops.rs b/compiler/rustc_mir_transform/src/remove_uninit_drops.rs
index aafe971..c58f492 100644
--- a/compiler/rustc_mir_transform/src/remove_uninit_drops.rs
+++ b/compiler/rustc_mir_transform/src/remove_uninit_drops.rs
@@ -14,7 +14,7 @@
/// like [#90770].
///
/// [#90770]: https://github.com/rust-lang/rust/issues/90770
-pub struct RemoveUninitDrops;
+pub(super) struct RemoveUninitDrops;
impl<'tcx> crate::MirPass<'tcx> for RemoveUninitDrops {
fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
diff --git a/compiler/rustc_mir_transform/src/remove_unneeded_drops.rs b/compiler/rustc_mir_transform/src/remove_unneeded_drops.rs
index 43109aa..28925ba 100644
--- a/compiler/rustc_mir_transform/src/remove_unneeded_drops.rs
+++ b/compiler/rustc_mir_transform/src/remove_unneeded_drops.rs
@@ -10,7 +10,7 @@
use super::simplify::simplify_cfg;
-pub struct RemoveUnneededDrops;
+pub(super) struct RemoveUnneededDrops;
impl<'tcx> crate::MirPass<'tcx> for RemoveUnneededDrops {
fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
diff --git a/compiler/rustc_mir_transform/src/remove_zsts.rs b/compiler/rustc_mir_transform/src/remove_zsts.rs
index 9aa46bd..f13bb1c 100644
--- a/compiler/rustc_mir_transform/src/remove_zsts.rs
+++ b/compiler/rustc_mir_transform/src/remove_zsts.rs
@@ -4,7 +4,7 @@
use rustc_middle::mir::*;
use rustc_middle::ty::{self, Ty, TyCtxt};
-pub struct RemoveZsts;
+pub(super) struct RemoveZsts;
impl<'tcx> crate::MirPass<'tcx> for RemoveZsts {
fn is_enabled(&self, sess: &rustc_session::Session) -> bool {
diff --git a/compiler/rustc_mir_transform/src/required_consts.rs b/compiler/rustc_mir_transform/src/required_consts.rs
index 50637e2..ebcf5b5 100644
--- a/compiler/rustc_mir_transform/src/required_consts.rs
+++ b/compiler/rustc_mir_transform/src/required_consts.rs
@@ -1,7 +1,7 @@
use rustc_middle::mir::visit::Visitor;
use rustc_middle::mir::{traversal, Body, ConstOperand, Location};
-pub struct RequiredConstsVisitor<'a, 'tcx> {
+pub(super) struct RequiredConstsVisitor<'a, 'tcx> {
required_consts: &'a mut Vec<ConstOperand<'tcx>>,
}
@@ -10,7 +10,7 @@ fn new(required_consts: &'a mut Vec<ConstOperand<'tcx>>) -> Self {
RequiredConstsVisitor { required_consts }
}
- pub fn compute_required_consts(body: &mut Body<'tcx>) {
+ pub(super) fn compute_required_consts(body: &mut Body<'tcx>) {
let mut required_consts = Vec::new();
let mut required_consts_visitor = RequiredConstsVisitor::new(&mut required_consts);
for (bb, bb_data) in traversal::reverse_postorder(&body) {
diff --git a/compiler/rustc_mir_transform/src/reveal_all.rs b/compiler/rustc_mir_transform/src/reveal_all.rs
index 29312a9..3db962b 100644
--- a/compiler/rustc_mir_transform/src/reveal_all.rs
+++ b/compiler/rustc_mir_transform/src/reveal_all.rs
@@ -4,7 +4,7 @@
use rustc_middle::mir::*;
use rustc_middle::ty::{self, Ty, TyCtxt};
-pub struct RevealAll;
+pub(super) struct RevealAll;
impl<'tcx> crate::MirPass<'tcx> for RevealAll {
fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
diff --git a/compiler/rustc_mir_transform/src/shim.rs b/compiler/rustc_mir_transform/src/shim.rs
index 8c70e42..cf8ef58 100644
--- a/compiler/rustc_mir_transform/src/shim.rs
+++ b/compiler/rustc_mir_transform/src/shim.rs
@@ -26,7 +26,7 @@
mod async_destructor_ctor;
-pub fn provide(providers: &mut Providers) {
+pub(super) fn provide(providers: &mut Providers) {
providers.mir_shims = make_shim;
}
@@ -331,7 +331,7 @@ fn new_body<'tcx>(
body
}
-pub struct DropShimElaborator<'a, 'tcx> {
+pub(super) struct DropShimElaborator<'a, 'tcx> {
pub body: &'a Body<'tcx>,
pub patch: MirPatch<'tcx>,
pub tcx: TyCtxt<'tcx>,
@@ -913,7 +913,7 @@ fn build_call_shim<'tcx>(
body
}
-pub fn build_adt_ctor(tcx: TyCtxt<'_>, ctor_id: DefId) -> Body<'_> {
+pub(super) fn build_adt_ctor(tcx: TyCtxt<'_>, ctor_id: DefId) -> Body<'_> {
debug_assert!(tcx.is_constructor(ctor_id));
let param_env = tcx.param_env_reveal_all_normalized(ctor_id);
diff --git a/compiler/rustc_mir_transform/src/shim/async_destructor_ctor.rs b/compiler/rustc_mir_transform/src/shim/async_destructor_ctor.rs
index 50810f2..c88953a 100644
--- a/compiler/rustc_mir_transform/src/shim/async_destructor_ctor.rs
+++ b/compiler/rustc_mir_transform/src/shim/async_destructor_ctor.rs
@@ -23,7 +23,7 @@
use super::{local_decls_for_sig, new_body};
-pub fn build_async_destructor_ctor_shim<'tcx>(
+pub(super) fn build_async_destructor_ctor_shim<'tcx>(
tcx: TyCtxt<'tcx>,
def_id: DefId,
ty: Option<Ty<'tcx>>,
diff --git a/compiler/rustc_mir_transform/src/simplify.rs b/compiler/rustc_mir_transform/src/simplify.rs
index 1478b86..cb8e1df 100644
--- a/compiler/rustc_mir_transform/src/simplify.rs
+++ b/compiler/rustc_mir_transform/src/simplify.rs
@@ -35,7 +35,7 @@
use smallvec::SmallVec;
use tracing::{debug, trace};
-pub enum SimplifyCfg {
+pub(super) enum SimplifyCfg {
Initial,
PromoteConsts,
RemoveFalseEdges,
@@ -50,7 +50,7 @@ pub enum SimplifyCfg {
}
impl SimplifyCfg {
- pub fn name(&self) -> &'static str {
+ fn name(&self) -> &'static str {
match self {
SimplifyCfg::Initial => "SimplifyCfg-initial",
SimplifyCfg::PromoteConsts => "SimplifyCfg-promote-consts",
@@ -66,7 +66,7 @@ pub fn name(&self) -> &'static str {
}
}
-pub(crate) fn simplify_cfg(body: &mut Body<'_>) {
+pub(super) fn simplify_cfg(body: &mut Body<'_>) {
CfgSimplifier::new(body).simplify();
remove_dead_blocks(body);
@@ -85,13 +85,13 @@ fn run_pass(&self, _: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
}
}
-pub struct CfgSimplifier<'a, 'tcx> {
+struct CfgSimplifier<'a, 'tcx> {
basic_blocks: &'a mut IndexSlice<BasicBlock, BasicBlockData<'tcx>>,
pred_count: IndexVec<BasicBlock, u32>,
}
impl<'a, 'tcx> CfgSimplifier<'a, 'tcx> {
- pub fn new(body: &'a mut Body<'tcx>) -> Self {
+ fn new(body: &'a mut Body<'tcx>) -> Self {
let mut pred_count = IndexVec::from_elem(0u32, &body.basic_blocks);
// we can't use mir.predecessors() here because that counts
@@ -111,7 +111,7 @@ pub fn new(body: &'a mut Body<'tcx>) -> Self {
CfgSimplifier { basic_blocks, pred_count }
}
- pub fn simplify(mut self) {
+ fn simplify(mut self) {
self.strip_nops();
// Vec of the blocks that should be merged. We store the indices here, instead of the
@@ -280,7 +280,7 @@ fn strip_nops(&mut self) {
}
}
-pub fn simplify_duplicate_switch_targets(terminator: &mut Terminator<'_>) {
+pub(super) fn simplify_duplicate_switch_targets(terminator: &mut Terminator<'_>) {
if let TerminatorKind::SwitchInt { targets, .. } = &mut terminator.kind {
let otherwise = targets.otherwise();
if targets.iter().any(|t| t.1 == otherwise) {
@@ -292,7 +292,7 @@ pub fn simplify_duplicate_switch_targets(terminator: &mut Terminator<'_>) {
}
}
-pub(crate) fn remove_dead_blocks(body: &mut Body<'_>) {
+pub(super) fn remove_dead_blocks(body: &mut Body<'_>) {
let should_deduplicate_unreachable = |bbdata: &BasicBlockData<'_>| {
// CfgSimplifier::simplify leaves behind some unreachable basic blocks without a
// terminator. Those blocks will be deleted by remove_dead_blocks, but we run just
@@ -360,7 +360,7 @@ pub(crate) fn remove_dead_blocks(body: &mut Body<'_>) {
}
}
-pub enum SimplifyLocals {
+pub(super) enum SimplifyLocals {
BeforeConstProp,
AfterGVN,
Final,
@@ -385,7 +385,7 @@ fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
}
}
-pub fn remove_unused_definitions<'tcx>(body: &mut Body<'tcx>) {
+pub(super) fn remove_unused_definitions<'tcx>(body: &mut Body<'tcx>) {
// First, we're going to get a count of *actual* uses for every `Local`.
let mut used_locals = UsedLocals::new(body);
@@ -397,7 +397,7 @@ pub fn remove_unused_definitions<'tcx>(body: &mut Body<'tcx>) {
remove_unused_definitions_helper(&mut used_locals, body);
}
-pub fn simplify_locals<'tcx>(body: &mut Body<'tcx>, tcx: TyCtxt<'tcx>) {
+fn simplify_locals<'tcx>(body: &mut Body<'tcx>, tcx: TyCtxt<'tcx>) {
// First, we're going to get a count of *actual* uses for every `Local`.
let mut used_locals = UsedLocals::new(body);
diff --git a/compiler/rustc_mir_transform/src/simplify_branches.rs b/compiler/rustc_mir_transform/src/simplify_branches.rs
index 5a014bb..e83b472 100644
--- a/compiler/rustc_mir_transform/src/simplify_branches.rs
+++ b/compiler/rustc_mir_transform/src/simplify_branches.rs
@@ -2,10 +2,11 @@
use rustc_middle::ty::TyCtxt;
use tracing::trace;
-pub enum SimplifyConstCondition {
+pub(super) enum SimplifyConstCondition {
AfterConstProp,
Final,
}
+
/// A pass that replaces a branch with a goto when its condition is known.
impl<'tcx> crate::MirPass<'tcx> for SimplifyConstCondition {
fn name(&self) -> &'static str {
diff --git a/compiler/rustc_mir_transform/src/simplify_comparison_integral.rs b/compiler/rustc_mir_transform/src/simplify_comparison_integral.rs
index bd30ecc..644bcb5 100644
--- a/compiler/rustc_mir_transform/src/simplify_comparison_integral.rs
+++ b/compiler/rustc_mir_transform/src/simplify_comparison_integral.rs
@@ -23,7 +23,7 @@
/// ```ignore (MIR)
/// switchInt(_4) -> [43i32: bb3, otherwise: bb2];
/// ```
-pub struct SimplifyComparisonIntegral;
+pub(super) struct SimplifyComparisonIntegral;
impl<'tcx> crate::MirPass<'tcx> for SimplifyComparisonIntegral {
fn is_enabled(&self, sess: &rustc_session::Session) -> bool {
diff --git a/compiler/rustc_mir_transform/src/single_use_consts.rs b/compiler/rustc_mir_transform/src/single_use_consts.rs
index 64a9287..2605926 100644
--- a/compiler/rustc_mir_transform/src/single_use_consts.rs
+++ b/compiler/rustc_mir_transform/src/single_use_consts.rs
@@ -19,7 +19,7 @@
///
/// It also removes *never*-used constants, since it had all the information
/// needed to do that too, including updating the debug info.
-pub struct SingleUseConsts;
+pub(super) struct SingleUseConsts;
impl<'tcx> crate::MirPass<'tcx> for SingleUseConsts {
fn is_enabled(&self, sess: &rustc_session::Session) -> bool {
diff --git a/compiler/rustc_mir_transform/src/sroa.rs b/compiler/rustc_mir_transform/src/sroa.rs
index 3c5ccc0..e6dd2cf 100644
--- a/compiler/rustc_mir_transform/src/sroa.rs
+++ b/compiler/rustc_mir_transform/src/sroa.rs
@@ -11,7 +11,7 @@
use rustc_target::abi::{FieldIdx, FIRST_VARIANT};
use tracing::{debug, instrument};
-pub struct ScalarReplacementOfAggregates;
+pub(super) struct ScalarReplacementOfAggregates;
impl<'tcx> crate::MirPass<'tcx> for ScalarReplacementOfAggregates {
fn is_enabled(&self, sess: &rustc_session::Session) -> bool {
diff --git a/compiler/rustc_mir_transform/src/ssa.rs b/compiler/rustc_mir_transform/src/ssa.rs
index c125476..cf8622c 100644
--- a/compiler/rustc_mir_transform/src/ssa.rs
+++ b/compiler/rustc_mir_transform/src/ssa.rs
@@ -16,7 +16,7 @@
use rustc_middle::ty::{ParamEnv, TyCtxt};
use tracing::{debug, instrument, trace};
-pub struct SsaLocals {
+pub(super) struct SsaLocals {
/// Assignments to each local. This defines whether the local is SSA.
assignments: IndexVec<Local, Set1<DefLocation>>,
/// We visit the body in reverse postorder, to ensure each local is assigned before it is used.
@@ -32,14 +32,18 @@ pub struct SsaLocals {
borrowed_locals: BitSet<Local>,
}
-pub enum AssignedValue<'a, 'tcx> {
+pub(super) enum AssignedValue<'a, 'tcx> {
Arg,
Rvalue(&'a mut Rvalue<'tcx>),
Terminator,
}
impl SsaLocals {
- pub fn new<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>, param_env: ParamEnv<'tcx>) -> SsaLocals {
+ pub(super) fn new<'tcx>(
+ tcx: TyCtxt<'tcx>,
+ body: &Body<'tcx>,
+ param_env: ParamEnv<'tcx>,
+ ) -> SsaLocals {
let assignment_order = Vec::with_capacity(body.local_decls.len());
let assignments = IndexVec::from_elem(Set1::Empty, &body.local_decls);
@@ -101,25 +105,25 @@ pub fn new<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>, param_env: ParamEnv<'tcx>
ssa
}
- pub fn num_locals(&self) -> usize {
+ pub(super) fn num_locals(&self) -> usize {
self.assignments.len()
}
- pub fn locals(&self) -> impl Iterator<Item = Local> {
+ pub(super) fn locals(&self) -> impl Iterator<Item = Local> {
self.assignments.indices()
}
- pub fn is_ssa(&self, local: Local) -> bool {
+ pub(super) fn is_ssa(&self, local: Local) -> bool {
matches!(self.assignments[local], Set1::One(_))
}
/// Return the number of uses if a local that are not "Deref".
- pub fn num_direct_uses(&self, local: Local) -> u32 {
+ pub(super) fn num_direct_uses(&self, local: Local) -> u32 {
self.direct_uses[local]
}
#[inline]
- pub fn assignment_dominates(
+ pub(super) fn assignment_dominates(
&self,
dominators: &Dominators<BasicBlock>,
local: Local,
@@ -131,7 +135,7 @@ pub fn assignment_dominates(
}
}
- pub fn assignments<'a, 'tcx>(
+ pub(super) fn assignments<'a, 'tcx>(
&'a self,
body: &'a Body<'tcx>,
) -> impl Iterator<Item = (Local, &'a Rvalue<'tcx>, Location)> + 'a {
@@ -148,7 +152,7 @@ pub fn assignments<'a, 'tcx>(
})
}
- pub fn for_each_assignment_mut<'tcx>(
+ pub(super) fn for_each_assignment_mut<'tcx>(
&self,
basic_blocks: &mut IndexSlice<BasicBlock, BasicBlockData<'tcx>>,
mut f: impl FnMut(Local, AssignedValue<'_, 'tcx>, Location),
@@ -194,17 +198,17 @@ pub fn for_each_assignment_mut<'tcx>(
/// _d => _a // transitively through _c
///
/// Exception: we do not see through the return place, as it cannot be instantiated.
- pub fn copy_classes(&self) -> &IndexSlice<Local, Local> {
+ pub(super) fn copy_classes(&self) -> &IndexSlice<Local, Local> {
&self.copy_classes
}
/// Set of SSA locals that are immutably borrowed.
- pub fn borrowed_locals(&self) -> &BitSet<Local> {
+ pub(super) fn borrowed_locals(&self) -> &BitSet<Local> {
&self.borrowed_locals
}
/// Make a property uniform on a copy equivalence class by removing elements.
- pub fn meet_copy_equivalence(&self, property: &mut BitSet<Local>) {
+ pub(super) fn meet_copy_equivalence(&self, property: &mut BitSet<Local>) {
// Consolidate to have a local iff all its copies are.
//
// `copy_classes` defines equivalence classes between locals. The `local`s that recursively
diff --git a/compiler/rustc_mir_transform/src/unreachable_enum_branching.rs b/compiler/rustc_mir_transform/src/unreachable_enum_branching.rs
index 51a3226..6957394 100644
--- a/compiler/rustc_mir_transform/src/unreachable_enum_branching.rs
+++ b/compiler/rustc_mir_transform/src/unreachable_enum_branching.rs
@@ -12,7 +12,7 @@
use rustc_target::abi::{Abi, Variants};
use tracing::trace;
-pub struct UnreachableEnumBranching;
+pub(super) struct UnreachableEnumBranching;
fn get_discriminant_local(terminator: &TerminatorKind<'_>) -> Option<Local> {
if let TerminatorKind::SwitchInt { discr: Operand::Move(p), .. } = terminator {
diff --git a/compiler/rustc_mir_transform/src/unreachable_prop.rs b/compiler/rustc_mir_transform/src/unreachable_prop.rs
index b8da86f..c60cbae 100644
--- a/compiler/rustc_mir_transform/src/unreachable_prop.rs
+++ b/compiler/rustc_mir_transform/src/unreachable_prop.rs
@@ -10,7 +10,7 @@
use rustc_middle::ty::{self, TyCtxt};
use rustc_target::abi::Size;
-pub struct UnreachablePropagation;
+pub(super) struct UnreachablePropagation;
impl crate::MirPass<'_> for UnreachablePropagation {
fn is_enabled(&self, sess: &rustc_session::Session) -> bool {
diff --git a/compiler/rustc_mir_transform/src/validate.rs b/compiler/rustc_mir_transform/src/validate.rs
index 69e2592..18865c7 100644
--- a/compiler/rustc_mir_transform/src/validate.rs
+++ b/compiler/rustc_mir_transform/src/validate.rs
@@ -1,6 +1,7 @@
//! Validates the MIR to ensure that invariants are upheld.
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
+use rustc_hir as hir;
use rustc_hir::LangItem;
use rustc_index::bit_set::BitSet;
use rustc_index::IndexVec;
@@ -25,7 +26,7 @@ enum EdgeKind {
Normal,
}
-pub struct Validator {
+pub(super) struct Validator {
/// Describes at which point in the pipeline this validation is happening.
pub when: String,
/// The phase for which we are upholding the dialect. If the given phase forbids a specific
@@ -530,7 +531,7 @@ fn visit_source_scope(&mut self, scope: SourceScope) {
///
/// `caller_body` is used to detect cycles in MIR inlining and MIR validation before
/// `optimized_mir` is available.
-pub fn validate_types<'tcx>(
+pub(super) fn validate_types<'tcx>(
tcx: TyCtxt<'tcx>,
mir_phase: MirPhase,
param_env: ty::ParamEnv<'tcx>,
@@ -714,7 +715,17 @@ fn visit_projection_elem(
// since we may be in the process of computing this MIR in the
// first place.
let layout = if def_id == self.caller_body.source.def_id() {
- // FIXME: This is not right for async closures.
+ self.caller_body.coroutine_layout_raw()
+ } else if let Some(hir::CoroutineKind::Desugared(
+ _,
+ hir::CoroutineSource::Closure,
+ )) = self.tcx.coroutine_kind(def_id)
+ && let ty::ClosureKind::FnOnce =
+ args.as_coroutine().kind_ty().to_opt_closure_kind().unwrap()
+ && self.caller_body.source.def_id()
+ == self.tcx.coroutine_by_move_body_def_id(def_id)
+ {
+ // Same if this is the by-move body of a coroutine-closure.
self.caller_body.coroutine_layout_raw()
} else {
self.tcx.coroutine_layout(def_id, args.as_coroutine().kind_ty())
diff --git a/compiler/rustc_monomorphize/src/collector.rs b/compiler/rustc_monomorphize/src/collector.rs
index 8515ab4..093697a 100644
--- a/compiler/rustc_monomorphize/src/collector.rs
+++ b/compiler/rustc_monomorphize/src/collector.rs
@@ -1041,8 +1041,11 @@ fn find_vtable_types_for_unsizing<'tcx>(
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::Adt(def_a, _), &ty::Adt(def_b, _)) if def_a.is_box() && def_b.is_box() => {
- ptr_vtable(source_ty.boxed_ty(), target_ty.boxed_ty())
+ (_, _)
+ if let Some(source_boxed) = source_ty.boxed_ty()
+ && let Some(target_boxed) = target_ty.boxed_ty() =>
+ {
+ ptr_vtable(source_boxed, target_boxed)
}
// T as dyn* Trait
diff --git a/compiler/rustc_monomorphize/src/lib.rs b/compiler/rustc_monomorphize/src/lib.rs
index b22e8e3..91101dd 100644
--- a/compiler/rustc_monomorphize/src/lib.rs
+++ b/compiler/rustc_monomorphize/src/lib.rs
@@ -1,5 +1,7 @@
// tidy-alphabetical-start
#![feature(array_windows)]
+#![feature(if_let_guard)]
+#![feature(let_chains)]
#![warn(unreachable_pub)]
// tidy-alphabetical-end
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 c7a9846..17b6ec7 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
@@ -3,7 +3,7 @@
mod opaque_types;
mod weak_types;
-use rustc_type_ir::fast_reject::{DeepRejectCtxt, TreatParams};
+use rustc_type_ir::fast_reject::DeepRejectCtxt;
use rustc_type_ir::inherent::*;
use rustc_type_ir::lang_items::TraitSolverLangItem;
use rustc_type_ir::{self as ty, Interner, NormalizesTo, Upcast as _};
@@ -106,6 +106,12 @@ fn probe_and_match_goal_against_assumption(
if let Some(projection_pred) = assumption.as_projection_clause() {
if projection_pred.projection_def_id() == goal.predicate.def_id() {
let cx = ecx.cx();
+ if !DeepRejectCtxt::relate_rigid_rigid(ecx.cx()).args_may_unify(
+ goal.predicate.alias.args,
+ projection_pred.skip_binder().projection_term.args,
+ ) {
+ return Err(NoSolution);
+ }
ecx.probe_trait_candidate(source).enter(|ecx| {
let assumption_projection_pred =
ecx.instantiate_binder_with_infer(projection_pred);
@@ -144,7 +150,7 @@ fn consider_impl_candidate(
let goal_trait_ref = goal.predicate.alias.trait_ref(cx);
let impl_trait_ref = cx.impl_trait_ref(impl_def_id);
- if !DeepRejectCtxt::new(ecx.cx(), TreatParams::ForLookup).args_may_unify(
+ if !DeepRejectCtxt::relate_rigid_infer(ecx.cx()).args_may_unify(
goal.predicate.alias.trait_ref(cx).args,
impl_trait_ref.skip_binder().args,
) {
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 67b001d..683d8da 100644
--- a/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs
+++ b/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs
@@ -2,7 +2,7 @@
use rustc_ast_ir::Movability;
use rustc_type_ir::data_structures::IndexSet;
-use rustc_type_ir::fast_reject::{DeepRejectCtxt, TreatParams};
+use rustc_type_ir::fast_reject::DeepRejectCtxt;
use rustc_type_ir::inherent::*;
use rustc_type_ir::lang_items::TraitSolverLangItem;
use rustc_type_ir::visit::TypeVisitableExt as _;
@@ -47,7 +47,7 @@ fn consider_impl_candidate(
let cx = ecx.cx();
let impl_trait_ref = cx.impl_trait_ref(impl_def_id);
- if !DeepRejectCtxt::new(ecx.cx(), TreatParams::ForLookup)
+ if !DeepRejectCtxt::relate_rigid_infer(ecx.cx())
.args_may_unify(goal.predicate.trait_ref.args, impl_trait_ref.skip_binder().args)
{
return Err(NoSolution);
@@ -124,6 +124,13 @@ fn probe_and_match_goal_against_assumption(
if trait_clause.def_id() == goal.predicate.def_id()
&& trait_clause.polarity() == goal.predicate.polarity
{
+ if !DeepRejectCtxt::relate_rigid_rigid(ecx.cx()).args_may_unify(
+ goal.predicate.trait_ref.args,
+ trait_clause.skip_binder().trait_ref.args,
+ ) {
+ return Err(NoSolution);
+ }
+
ecx.probe_trait_candidate(source).enter(|ecx| {
let assumption_trait_pred = ecx.instantiate_binder_with_infer(trait_clause);
ecx.eq(
diff --git a/compiler/rustc_parse/Cargo.toml b/compiler/rustc_parse/Cargo.toml
index b338961..c59ae48 100644
--- a/compiler/rustc_parse/Cargo.toml
+++ b/compiler/rustc_parse/Cargo.toml
@@ -12,6 +12,7 @@
rustc_errors = { path = "../rustc_errors" }
rustc_feature = { path = "../rustc_feature" }
rustc_fluent_macro = { path = "../rustc_fluent_macro" }
+rustc_index = { path = "../rustc_index" }
rustc_lexer = { path = "../rustc_lexer" }
rustc_macros = { path = "../rustc_macros" }
rustc_session = { path = "../rustc_session" }
diff --git a/compiler/rustc_parse/messages.ftl b/compiler/rustc_parse/messages.ftl
index 8e8d91c..ec9a676 100644
--- a/compiler/rustc_parse/messages.ftl
+++ b/compiler/rustc_parse/messages.ftl
@@ -381,6 +381,7 @@
*[false] unicode
} escape
+
parse_invalid_comparison_operator = invalid comparison operator `{$invalid}`
.use_instead = `{$invalid}` is not a valid comparison operator, use `{$correct}`
.spaceship_operator_invalid = `<=>` is not a valid comparison operator, use `std::cmp::Ordering`
@@ -581,6 +582,11 @@
.suggestion_add_trait = add a trait here
.suggestion_remove_for = for an inherent impl, drop this `for`
+parse_misspelled_kw = {$is_incorrect_case ->
+ [true] write keyword `{$similar_kw}` in lowercase
+ *[false] there is a keyword `{$similar_kw}` with a similar name
+}
+
parse_modifier_lifetime = `{$modifier}` may only modify trait bounds, not lifetime bounds
.suggestion = remove the `{$modifier}`
diff --git a/compiler/rustc_parse/src/lexer/mod.rs b/compiler/rustc_parse/src/lexer/mod.rs
index f309390..b7232ff 100644
--- a/compiler/rustc_parse/src/lexer/mod.rs
+++ b/compiler/rustc_parse/src/lexer/mod.rs
@@ -13,7 +13,6 @@
};
use rustc_session::lint::BuiltinLintDiag;
use rustc_session::parse::ParseSess;
-use rustc_span::edition::Edition;
use rustc_span::symbol::Symbol;
use rustc_span::{BytePos, Pos, Span};
use tracing::debug;
@@ -188,9 +187,7 @@ fn next_token(&mut self) -> (Token, bool) {
preceded_by_whitespace = true;
continue;
}
- rustc_lexer::TokenKind::Ident => {
- self.ident(start)
- }
+ rustc_lexer::TokenKind::Ident => self.ident(start),
rustc_lexer::TokenKind::RawIdent => {
let sym = nfc_normalize(self.str_from(start + BytePos(2)));
let span = self.mk_sp(start, self.pos);
@@ -205,20 +202,31 @@ fn next_token(&mut self) -> (Token, bool) {
self.report_unknown_prefix(start);
self.ident(start)
}
- rustc_lexer::TokenKind::InvalidIdent
- | rustc_lexer::TokenKind::InvalidPrefix
+ rustc_lexer::TokenKind::UnknownPrefixLifetime => {
+ self.report_unknown_prefix(start);
+ // Include the leading `'` in the real identifier, for macro
+ // expansion purposes. See #12512 for the gory details of why
+ // this is necessary.
+ let lifetime_name = self.str_from(start);
+ self.last_lifetime = Some(self.mk_sp(start, start + BytePos(1)));
+ let ident = Symbol::intern(lifetime_name);
+ token::Lifetime(ident, IdentIsRaw::No)
+ }
+ rustc_lexer::TokenKind::InvalidIdent | rustc_lexer::TokenKind::InvalidPrefix
// Do not recover an identifier with emoji if the codepoint is a confusable
// with a recoverable substitution token, like `➖`.
- if !UNICODE_ARRAY
- .iter()
- .any(|&(c, _, _)| {
- let sym = self.str_from(start);
- sym.chars().count() == 1 && c == sym.chars().next().unwrap()
- }) =>
+ if !UNICODE_ARRAY.iter().any(|&(c, _, _)| {
+ let sym = self.str_from(start);
+ sym.chars().count() == 1 && c == sym.chars().next().unwrap()
+ }) =>
{
let sym = nfc_normalize(self.str_from(start));
let span = self.mk_sp(start, self.pos);
- self.psess.bad_unicode_identifiers.borrow_mut().entry(sym).or_default()
+ self.psess
+ .bad_unicode_identifiers
+ .borrow_mut()
+ .entry(sym)
+ .or_default()
.push(span);
token::Ident(sym, IdentIsRaw::No)
}
@@ -249,9 +257,9 @@ fn next_token(&mut self) -> (Token, bool) {
let suffix = if suffix_start < self.pos {
let string = self.str_from(suffix_start);
if string == "_" {
- self
- .dcx()
- .emit_err(errors::UnderscoreLiteralSuffix { span: self.mk_sp(suffix_start, self.pos) });
+ self.dcx().emit_err(errors::UnderscoreLiteralSuffix {
+ span: self.mk_sp(suffix_start, self.pos),
+ });
None
} else {
Some(Symbol::intern(string))
@@ -269,12 +277,47 @@ fn next_token(&mut self) -> (Token, bool) {
self.last_lifetime = Some(self.mk_sp(start, start + BytePos(1)));
if starts_with_number {
let span = self.mk_sp(start, self.pos);
- self.dcx().struct_err("lifetimes cannot start with a number")
+ self.dcx()
+ .struct_err("lifetimes cannot start with a number")
.with_span(span)
.stash(span, StashKey::LifetimeIsChar);
}
let ident = Symbol::intern(lifetime_name);
- token::Lifetime(ident)
+ token::Lifetime(ident, IdentIsRaw::No)
+ }
+ rustc_lexer::TokenKind::RawLifetime => {
+ self.last_lifetime = Some(self.mk_sp(start, start + BytePos(1)));
+
+ let ident_start = start + BytePos(3);
+ let prefix_span = self.mk_sp(start, ident_start);
+
+ if prefix_span.at_least_rust_2021() {
+ let lifetime_name_without_tick = self.str_from(ident_start);
+ // Put the `'` back onto the lifetime name.
+ let mut lifetime_name = String::with_capacity(lifetime_name_without_tick.len() + 1);
+ lifetime_name.push('\'');
+ lifetime_name += lifetime_name_without_tick;
+ let sym = Symbol::intern(&lifetime_name);
+
+ token::Lifetime(sym, IdentIsRaw::Yes)
+ } else {
+ // Otherwise, this should be parsed like `'r`. Warn about it though.
+ self.psess.buffer_lint(
+ RUST_2021_PREFIXES_INCOMPATIBLE_SYNTAX,
+ prefix_span,
+ ast::CRATE_NODE_ID,
+ BuiltinLintDiag::RawPrefix(prefix_span),
+ );
+
+ // Reset the state so we just lex the `'r`.
+ let lt_start = start + BytePos(2);
+ self.pos = lt_start;
+ self.cursor = Cursor::new(&str_before[2 as usize..]);
+
+ let lifetime_name = self.str_from(start);
+ let ident = Symbol::intern(lifetime_name);
+ token::Lifetime(ident, IdentIsRaw::No)
+ }
}
rustc_lexer::TokenKind::Semi => token::Semi,
rustc_lexer::TokenKind::Comma => token::Comma,
@@ -331,16 +374,19 @@ fn next_token(&mut self) -> (Token, bool) {
// first remove compound tokens like `<<` from `rustc_lexer`, and then add
// fancier error recovery to it, as there will be less overall work to do this
// way.
- let (token, sugg) = unicode_chars::check_for_substitution(self, start, c, repeats+1);
+ let (token, sugg) =
+ unicode_chars::check_for_substitution(self, start, c, repeats + 1);
self.dcx().emit_err(errors::UnknownTokenStart {
span: self.mk_sp(start, self.pos + Pos::from_usize(repeats * c.len_utf8())),
escaped: escaped_char(c),
sugg,
- null: if c == '\x00' {Some(errors::UnknownTokenNull)} else {None},
+ null: if c == '\x00' { Some(errors::UnknownTokenNull) } else { None },
repeat: if repeats > 0 {
swallow_next_invalid = repeats;
Some(errors::UnknownTokenRepeat { repeats })
- } else {None}
+ } else {
+ None
+ },
});
if let Some(token) = token {
@@ -699,7 +745,7 @@ fn report_unknown_prefix(&self, start: BytePos) {
let expn_data = prefix_span.ctxt().outer_expn_data();
- if expn_data.edition >= Edition::Edition2021 {
+ if expn_data.edition.at_least_rust_2021() {
// In Rust 2021, this is a hard error.
let sugg = if prefix == "rb" {
Some(errors::UnknownPrefixSugg::UseBr(prefix_span))
diff --git a/compiler/rustc_parse/src/parser/attr_wrapper.rs b/compiler/rustc_parse/src/parser/attr_wrapper.rs
index 49df281..205cca8 100644
--- a/compiler/rustc_parse/src/parser/attr_wrapper.rs
+++ b/compiler/rustc_parse/src/parser/attr_wrapper.rs
@@ -1,3 +1,4 @@
+use std::borrow::Cow;
use std::{iter, mem};
use rustc_ast::token::{Delimiter, Token, TokenKind};
@@ -6,6 +7,7 @@
Spacing, ToAttrTokenStream,
};
use rustc_ast::{self as ast, AttrVec, Attribute, HasAttrs, HasTokens};
+use rustc_data_structures::fx::FxHashSet;
use rustc_errors::PResult;
use rustc_session::parse::ParseSess;
use rustc_span::{sym, Span, DUMMY_SP};
@@ -134,9 +136,8 @@ fn to_attr_token_stream(&self) -> AttrTokenStream {
node_replacements.array_windows()
{
assert!(
- node_range.0.end <= next_node_range.0.start
- || node_range.0.end >= next_node_range.0.end,
- "Node ranges should be disjoint or nested: ({:?}, {:?}) ({:?}, {:?})",
+ node_range.0.end <= next_node_range.0.start,
+ "Node ranges should be disjoint: ({:?}, {:?}) ({:?}, {:?})",
node_range,
tokens,
next_node_range,
@@ -144,20 +145,8 @@ fn to_attr_token_stream(&self) -> AttrTokenStream {
);
}
- // Process the replace ranges, starting from the highest start
- // position and working our way back. If have tokens like:
- //
- // `#[cfg(FALSE)] struct Foo { #[cfg(FALSE)] field: bool }`
- //
- // Then we will generate replace ranges for both
- // the `#[cfg(FALSE)] field: bool` and the entire
- // `#[cfg(FALSE)] struct Foo { #[cfg(FALSE)] field: bool }`
- //
- // By starting processing from the replace range with the greatest
- // start position, we ensure that any (outer) replace range which
- // encloses another (inner) replace range will fully overwrite the
- // inner range's replacement.
- for (node_range, target) in node_replacements.into_iter().rev() {
+ // Process the replace ranges.
+ for (node_range, target) in node_replacements.into_iter() {
assert!(
!node_range.0.is_empty(),
"Cannot replace an empty node range: {:?}",
@@ -234,6 +223,8 @@ pub(super) fn collect_tokens<R: HasAttrs + HasTokens>(
force_collect: ForceCollect,
f: impl FnOnce(&mut Self, AttrVec) -> PResult<'a, (R, Trailing, UsePreAttrPos)>,
) -> PResult<'a, R> {
+ let possible_capture_mode = self.capture_cfg;
+
// We must collect if anything could observe the collected tokens, i.e.
// if any of the following conditions hold.
// - We are force collecting tokens (because force collection requires
@@ -244,9 +235,9 @@ pub(super) fn collect_tokens<R: HasAttrs + HasTokens>(
// - Our target supports custom inner attributes (custom
// inner attribute invocation might require token capturing).
|| R::SUPPORTS_CUSTOM_INNER_ATTRS
- // - We are in `capture_cfg` mode (which requires tokens if
+ // - We are in "possible capture mode" (which requires tokens if
// the parsed node has `#[cfg]` or `#[cfg_attr]` attributes).
- || self.capture_cfg;
+ || possible_capture_mode;
if !needs_collection {
return Ok(f(self, attrs.attrs)?.0);
}
@@ -267,18 +258,48 @@ pub(super) fn collect_tokens<R: HasAttrs + HasTokens>(
res?
};
- // When we're not in `capture_cfg` mode, then skip collecting and
- // return early if either of the following conditions hold.
// - `None`: Our target doesn't support tokens at all (e.g. `NtIdent`).
+ // - `Some(None)`: Our target supports tokens and has none.
// - `Some(Some(_))`: Our target already has tokens set (e.g. we've
- // parsed something like `#[my_attr] $item`). The actual parsing code
- // takes care of prepending any attributes to the nonterminal, so we
- // don't need to modify the already captured tokens.
+ // parsed something like `#[my_attr] $item`).
+ let ret_can_hold_tokens = matches!(ret.tokens_mut(), Some(None));
+
+ // Ignore any attributes we've previously processed. This happens when
+ // an inner call to `collect_tokens` returns an AST node and then an
+ // outer call ends up with the same AST node without any additional
+ // wrapping layer.
+ let mut seen_indices = FxHashSet::default();
+ for (i, attr) in ret.attrs().iter().enumerate() {
+ let is_unseen = self.capture_state.seen_attrs.insert(attr.id);
+ if !is_unseen {
+ seen_indices.insert(i);
+ }
+ }
+ let ret_attrs: Cow<'_, [Attribute]> =
+ if seen_indices.is_empty() {
+ Cow::Borrowed(ret.attrs())
+ } else {
+ let ret_attrs =
+ ret.attrs()
+ .iter()
+ .enumerate()
+ .filter_map(|(i, attr)| {
+ if seen_indices.contains(&i) { None } else { Some(attr.clone()) }
+ })
+ .collect();
+ Cow::Owned(ret_attrs)
+ };
+
+ // When we're not in "definite capture mode", then skip collecting and
+ // return early if `ret` doesn't support tokens or already has some.
//
// Note that this check is independent of `force_collect`. There's no
// need to collect tokens when we don't support tokens or already have
// tokens.
- if !self.capture_cfg && matches!(ret.tokens_mut(), None | Some(Some(_))) {
+ let definite_capture_mode = self.capture_cfg
+ && matches!(self.capture_state.capturing, Capturing::Yes)
+ && has_cfg_or_cfg_attr(&ret_attrs);
+ if !definite_capture_mode && !ret_can_hold_tokens {
return Ok(ret);
}
@@ -297,12 +318,12 @@ pub(super) fn collect_tokens<R: HasAttrs + HasTokens>(
// outer and inner attributes. So this check is more precise than
// the earlier `needs_tokens` check, and we don't need to
// check `R::SUPPORTS_CUSTOM_INNER_ATTRS`.)
- || needs_tokens(ret.attrs())
- // - We are in `capture_cfg` mode and there are `#[cfg]` or
- // `#[cfg_attr]` attributes. (During normal non-`capture_cfg`
- // parsing, we don't need any special capturing for those
- // attributes, because they're builtin.)
- || (self.capture_cfg && has_cfg_or_cfg_attr(ret.attrs()));
+ || needs_tokens(&ret_attrs)
+ // - We are in "definite capture mode", which requires that there
+ // are `#[cfg]` or `#[cfg_attr]` attributes. (During normal
+ // non-`capture_cfg` parsing, we don't need any special capturing
+ // for those attributes, because they're builtin.)
+ || definite_capture_mode;
if !needs_collection {
return Ok(ret);
}
@@ -336,7 +357,7 @@ pub(super) fn collect_tokens<R: HasAttrs + HasTokens>(
// `Parser::parse_inner_attributes`, and pair them in a `ParserReplacement` with `None`,
// which means the relevant tokens will be removed. (More details below.)
let mut inner_attr_parser_replacements = Vec::new();
- for attr in ret.attrs() {
+ for attr in ret_attrs.iter() {
if attr.style == ast::AttrStyle::Inner {
if let Some(inner_attr_parser_range) =
self.capture_state.inner_attr_parser_ranges.remove(&attr.id)
@@ -359,11 +380,10 @@ pub(super) fn collect_tokens<R: HasAttrs + HasTokens>(
// from `ParserRange` form to `NodeRange` form. We will perform the actual
// replacement only when we convert the `LazyAttrTokenStream` to an
// `AttrTokenStream`.
- self.capture_state.parser_replacements
- [parser_replacements_start..parser_replacements_end]
- .iter()
- .cloned()
- .chain(inner_attr_parser_replacements.iter().cloned())
+ self.capture_state
+ .parser_replacements
+ .drain(parser_replacements_start..parser_replacements_end)
+ .chain(inner_attr_parser_replacements.into_iter())
.map(|(parser_range, data)| {
(NodeRange::new(parser_range, collect_pos.start_pos), data)
})
@@ -399,20 +419,12 @@ pub(super) fn collect_tokens<R: HasAttrs + HasTokens>(
break_last_token: self.break_last_token,
node_replacements,
});
+ let mut tokens_used = false;
- // If we support tokens and don't already have them, store the newly captured tokens.
- if let Some(target_tokens @ None) = ret.tokens_mut() {
- *target_tokens = Some(tokens.clone());
- }
-
- // If `capture_cfg` is set and we're inside a recursive call to
- // `collect_tokens`, then we need to register a replace range if we
- // have `#[cfg]` or `#[cfg_attr]`. This allows us to run eager
- // cfg-expansion on the captured token stream.
- if self.capture_cfg
- && matches!(self.capture_state.capturing, Capturing::Yes)
- && has_cfg_or_cfg_attr(ret.attrs())
- {
+ // If in "definite capture mode" we need to register a replace range
+ // for the `#[cfg]` and/or `#[cfg_attr]` attrs. This allows us to run
+ // eager cfg-expansion on the captured token stream.
+ if definite_capture_mode {
assert!(!self.break_last_token, "Should not have unglued last token with cfg attr");
// What is the status here when parsing the example code at the top of this method?
@@ -429,7 +441,9 @@ pub(super) fn collect_tokens<R: HasAttrs + HasTokens>(
// cfg-expand this AST node.
let start_pos =
if has_outer_attrs { attrs.start_pos.unwrap() } else { collect_pos.start_pos };
- let target = AttrsTarget { attrs: ret.attrs().iter().cloned().collect(), tokens };
+ let target =
+ AttrsTarget { attrs: ret_attrs.iter().cloned().collect(), tokens: tokens.clone() };
+ tokens_used = true;
self.capture_state
.parser_replacements
.push((ParserRange(start_pos..end_pos), Some(target)));
@@ -438,7 +452,16 @@ pub(super) fn collect_tokens<R: HasAttrs + HasTokens>(
// the outermost call to this method.
self.capture_state.parser_replacements.clear();
self.capture_state.inner_attr_parser_ranges.clear();
+ self.capture_state.seen_attrs.clear();
}
+
+ // If we support tokens and don't already have them, store the newly captured tokens.
+ if let Some(target_tokens @ None) = ret.tokens_mut() {
+ tokens_used = true;
+ *target_tokens = Some(tokens);
+ }
+
+ assert!(tokens_used); // check we didn't create `tokens` unnecessarily
Ok(ret)
}
}
@@ -510,9 +533,11 @@ struct FrameData {
}
/// Tokens are needed if:
-/// - any non-single-segment attributes (other than doc comments) are present; or
-/// - any `cfg_attr` attributes are present;
-/// - any single-segment, non-builtin attributes are present.
+/// - any non-single-segment attributes (other than doc comments) are present,
+/// e.g. `rustfmt::skip`; or
+/// - any `cfg_attr` attributes are present; or
+/// - any single-segment, non-builtin attributes are present, e.g. `derive`,
+/// `test`, `global_allocator`.
fn needs_tokens(attrs: &[ast::Attribute]) -> bool {
attrs.iter().any(|attr| match attr.ident() {
None => !attr.is_doc_comment(),
diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs
index fcdc10c..f6f6682 100644
--- a/compiler/rustc_parse/src/parser/diagnostics.rs
+++ b/compiler/rustc_parse/src/parser/diagnostics.rs
@@ -19,8 +19,9 @@
Subdiagnostic,
};
use rustc_session::errors::ExprParenthesesNeeded;
+use rustc_span::edit_distance::find_best_match_for_name;
use rustc_span::source_map::Spanned;
-use rustc_span::symbol::{kw, sym, Ident};
+use rustc_span::symbol::{kw, sym, AllKeywords, Ident};
use rustc_span::{BytePos, Span, SpanSnippetError, Symbol, DUMMY_SP};
use thin_vec::{thin_vec, ThinVec};
use tracing::{debug, trace};
@@ -203,6 +204,37 @@ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
}
}
+#[derive(Debug, rustc_macros::Subdiagnostic)]
+#[suggestion(
+ parse_misspelled_kw,
+ applicability = "machine-applicable",
+ code = "{similar_kw}",
+ style = "verbose"
+)]
+struct MisspelledKw {
+ similar_kw: String,
+ #[primary_span]
+ span: Span,
+ is_incorrect_case: bool,
+}
+
+/// Checks if the given `lookup` identifier is similar to any keyword symbol in `candidates`.
+fn find_similar_kw(lookup: Ident, candidates: &[Symbol]) -> Option<MisspelledKw> {
+ let lowercase = lookup.name.as_str().to_lowercase();
+ let lowercase_sym = Symbol::intern(&lowercase);
+ if candidates.contains(&lowercase_sym) {
+ Some(MisspelledKw { similar_kw: lowercase, span: lookup.span, is_incorrect_case: true })
+ } else if let Some(similar_sym) = find_best_match_for_name(candidates, lookup.name, None) {
+ Some(MisspelledKw {
+ similar_kw: similar_sym.to_string(),
+ span: lookup.span,
+ is_incorrect_case: false,
+ })
+ } else {
+ None
+ }
+}
+
struct MultiSugg {
msg: String,
patches: Vec<(Span, String)>,
@@ -638,9 +670,9 @@ fn is_ident_eq_keyword(found: &TokenKind, expected: &TokenType) -> bool {
let concat = Symbol::intern(&format!("{prev}{cur}"));
let ident = Ident::new(concat, DUMMY_SP);
if ident.is_used_keyword() || ident.is_reserved() || ident.is_raw_guess() {
- let span = self.prev_token.span.to(self.token.span);
+ let concat_span = self.prev_token.span.to(self.token.span);
err.span_suggestion_verbose(
- span,
+ concat_span,
format!("consider removing the space to spell keyword `{concat}`"),
concat,
Applicability::MachineApplicable,
@@ -741,9 +773,55 @@ fn is_ident_eq_keyword(found: &TokenKind, expected: &TokenType) -> bool {
err.span_label(sp, label_exp);
err.span_label(self.token.span, "unexpected token");
}
+
+ // Check for misspelled keywords if there are no suggestions added to the diagnostic.
+ if err.suggestions.as_ref().is_ok_and(|code_suggestions| code_suggestions.is_empty()) {
+ self.check_for_misspelled_kw(&mut err, &expected);
+ }
Err(err)
}
+ /// 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]) {
+ let Some((curr_ident, _)) = self.token.ident() else {
+ return;
+ };
+ let expected_tokens: &[TokenType] =
+ expected.len().checked_sub(10).map_or(&expected, |index| &expected[index..]);
+ let expected_keywords: Vec<Symbol> = expected_tokens
+ .iter()
+ .filter_map(|token| if let TokenType::Keyword(kw) = token { Some(*kw) } else { None })
+ .collect();
+
+ // When there are a few keywords in the last ten elements of `self.expected_tokens` and the current
+ // token is an identifier, it's probably a misspelled keyword.
+ // This handles code like `async Move {}`, misspelled `if` in match guard, misspelled `else` in `if`-`else`
+ // and mispelled `where` in a where clause.
+ if !expected_keywords.is_empty()
+ && !curr_ident.is_used_keyword()
+ && let Some(misspelled_kw) = find_similar_kw(curr_ident, &expected_keywords)
+ {
+ err.subdiagnostic(misspelled_kw);
+ } else if let Some((prev_ident, _)) = self.prev_token.ident()
+ && !prev_ident.is_used_keyword()
+ {
+ // We generate a list of all keywords at runtime rather than at compile time
+ // so that it gets generated only when the diagnostic needs it.
+ // Also, it is unlikely that this list is generated multiple times because the
+ // parser halts after execution hits this path.
+ let all_keywords = AllKeywords::new().collect_used(|| prev_ident.span.edition());
+
+ // Otherwise, check the previous token with all the keywords as possible candidates.
+ // This handles code like `Struct Human;` and `While a < b {}`.
+ // We check the previous token only when the current token is an identifier to avoid false
+ // positives like suggesting keyword `for` for `extern crate foo {}`.
+ if let Some(misspelled_kw) = find_similar_kw(prev_ident, &all_keywords) {
+ err.subdiagnostic(misspelled_kw);
+ }
+ }
+ }
+
/// The user has written `#[attr] expr` which is unsupported. (#106020)
pub(super) fn attr_on_non_tail_expr(&self, expr: &Expr) -> ErrorGuaranteed {
// Missing semicolon typo error.
@@ -846,6 +924,7 @@ pub(super) fn attr_on_non_tail_expr(&self, expr: &Expr) -> ErrorGuaranteed {
);
}
}
+
err.emit()
}
diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs
index 84684e8..ecc4cd9 100644
--- a/compiler/rustc_parse/src/parser/expr.rs
+++ b/compiler/rustc_parse/src/parser/expr.rs
@@ -2050,7 +2050,7 @@ fn handle_missing_lit<L>(
};
// On an error path, eagerly consider a lifetime to be an unclosed character lit, if that
// makes sense.
- if let Some(ident) = self.token.lifetime()
+ if let Some((ident, IdentIsRaw::No)) = self.token.lifetime()
&& could_be_unclosed_char_literal(ident)
{
let lt = self.expect_lifetime();
@@ -2925,9 +2925,9 @@ fn parse_expr_loop(&mut self, opt_label: Option<Label>, lo: Span) -> PResult<'a,
}
pub(crate) fn eat_label(&mut self) -> Option<Label> {
- if let Some(ident) = self.token.lifetime() {
+ if let Some((ident, is_raw)) = self.token.lifetime() {
// Disallow `'fn`, but with a better error message than `expect_lifetime`.
- if ident.without_first_quote().is_reserved() {
+ if matches!(is_raw, IdentIsRaw::No) && ident.without_first_quote().is_reserved() {
self.dcx().emit_err(errors::InvalidLabel { span: ident.span, name: ident.name });
}
diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs
index 61e3fa2..3ee6e74 100644
--- a/compiler/rustc_parse/src/parser/mod.rs
+++ b/compiler/rustc_parse/src/parser/mod.rs
@@ -35,6 +35,7 @@
use rustc_data_structures::fx::FxHashMap;
use rustc_data_structures::sync::Lrc;
use rustc_errors::{Applicability, Diag, FatalError, MultiSpan, PResult};
+use rustc_index::interval::IntervalSet;
use rustc_session::parse::ParseSess;
use rustc_span::symbol::{kw, sym, Ident, Symbol};
use rustc_span::{Span, DUMMY_SP};
@@ -183,7 +184,7 @@ pub struct Parser<'a> {
// This type is used a lot, e.g. it's cloned when matching many declarative macro rules with nonterminals. Make sure
// it doesn't unintentionally get bigger.
#[cfg(target_pointer_width = "64")]
-rustc_data_structures::static_assert_size!(Parser<'_>, 256);
+rustc_data_structures::static_assert_size!(Parser<'_>, 288);
/// Stores span information about a closure.
#[derive(Clone, Debug)]
@@ -238,7 +239,8 @@ impl NodeRange {
// is the position of the function's start token. This gives
// `NodeRange(10..15)`.
fn new(ParserRange(parser_range): ParserRange, start_pos: u32) -> NodeRange {
- assert!(parser_range.start >= start_pos && parser_range.end >= start_pos);
+ assert!(!parser_range.is_empty());
+ assert!(parser_range.start >= start_pos);
NodeRange((parser_range.start - start_pos)..(parser_range.end - start_pos))
}
}
@@ -260,6 +262,9 @@ struct CaptureState {
capturing: Capturing,
parser_replacements: Vec<ParserReplacement>,
inner_attr_parser_ranges: FxHashMap<AttrId, ParserRange>,
+ // `IntervalSet` is good for perf because attrs are mostly added to this
+ // set in contiguous ranges.
+ seen_attrs: IntervalSet<AttrId>,
}
/// Iterator over a `TokenStream` that produces `Token`s. It's a bit odd that
@@ -457,6 +462,7 @@ pub fn new(
capturing: Capturing::No,
parser_replacements: Vec::new(),
inner_attr_parser_ranges: Default::default(),
+ seen_attrs: IntervalSet::new(u32::MAX as usize),
},
current_closure: None,
recovery: Recovery::Allowed,
@@ -1666,7 +1672,7 @@ enum FlatToken {
pub enum ParseNtResult {
Tt(TokenTree),
Ident(Ident, IdentIsRaw),
- Lifetime(Ident),
+ Lifetime(Ident, IdentIsRaw),
/// This case will eventually be removed, along with `Token::Interpolate`.
Nt(Lrc<Nonterminal>),
diff --git a/compiler/rustc_parse/src/parser/nonterminal.rs b/compiler/rustc_parse/src/parser/nonterminal.rs
index e66d0df..44b169c 100644
--- a/compiler/rustc_parse/src/parser/nonterminal.rs
+++ b/compiler/rustc_parse/src/parser/nonterminal.rs
@@ -88,7 +88,7 @@ fn may_be_ident(nt: &token::Nonterminal) -> bool {
},
NonterminalKind::Pat(pat_kind) => token.can_begin_pattern(pat_kind),
NonterminalKind::Lifetime => match &token.kind {
- token::Lifetime(_) | token::NtLifetime(..) => true,
+ token::Lifetime(..) | token::NtLifetime(..) => true,
_ => false,
},
NonterminalKind::TT | NonterminalKind::Item | NonterminalKind::Stmt => {
@@ -171,9 +171,9 @@ pub fn parse_nonterminal(&mut self, kind: NonterminalKind) -> PResult<'a, ParseN
NonterminalKind::Lifetime => {
// We want to keep `'keyword` parsing, just like `keyword` is still
// an ident for nonterminal purposes.
- return if let Some(ident) = self.token.lifetime() {
+ return if let Some((ident, is_raw)) = self.token.lifetime() {
self.bump();
- Ok(ParseNtResult::Lifetime(ident))
+ Ok(ParseNtResult::Lifetime(ident, is_raw))
} else {
Err(self.dcx().create_err(UnexpectedNonterminal::Lifetime {
span: self.token.span,
diff --git a/compiler/rustc_parse/src/parser/pat.rs b/compiler/rustc_parse/src/parser/pat.rs
index f87b564..cbd35ff 100644
--- a/compiler/rustc_parse/src/parser/pat.rs
+++ b/compiler/rustc_parse/src/parser/pat.rs
@@ -1,6 +1,6 @@
use rustc_ast::mut_visit::{walk_pat, MutVisitor};
use rustc_ast::ptr::P;
-use rustc_ast::token::{self, BinOpToken, Delimiter, Token};
+use rustc_ast::token::{self, BinOpToken, Delimiter, IdentIsRaw, Token};
use rustc_ast::{
self as ast, AttrVec, BindingMode, ByRef, Expr, ExprKind, MacCall, Mutability, Pat, PatField,
PatFieldsRest, PatKind, Path, QSelf, RangeEnd, RangeSyntax,
@@ -548,7 +548,7 @@ fn parse_pat_with_range_pat(
None => PatKind::Path(qself, path),
}
}
- } else if let Some(lt) = self.token.lifetime()
+ } else if let Some((lt, IdentIsRaw::No)) = self.token.lifetime()
// In pattern position, we're totally fine with using "next token isn't colon"
// as a heuristic. We could probably just always try to recover if it's a lifetime,
// because we never have `'a: label {}` in a pattern position anyways, but it does
@@ -689,7 +689,7 @@ fn ban_pat_range_if_ambiguous(&self, pat: &Pat) {
/// Parse `&pat` / `&mut pat`.
fn parse_pat_deref(&mut self, expected: Option<Expected>) -> PResult<'a, PatKind> {
self.expect_and()?;
- if let Some(lifetime) = self.token.lifetime() {
+ if let Some((lifetime, _)) = self.token.lifetime() {
self.bump(); // `'a`
self.dcx().emit_err(UnexpectedLifetimeInPattern {
diff --git a/compiler/rustc_parse/src/parser/ty.rs b/compiler/rustc_parse/src/parser/ty.rs
index 52f0b1c..dd1cc75 100644
--- a/compiler/rustc_parse/src/parser/ty.rs
+++ b/compiler/rustc_parse/src/parser/ty.rs
@@ -1,5 +1,5 @@
use rustc_ast::ptr::P;
-use rustc_ast::token::{self, BinOpToken, Delimiter, Token, TokenKind};
+use rustc_ast::token::{self, BinOpToken, Delimiter, IdentIsRaw, Token, TokenKind};
use rustc_ast::util::case::Case;
use rustc_ast::{
self as ast, BareFnTy, BoundAsyncness, BoundConstness, BoundPolarity, FnRetTy, GenericBound,
@@ -1285,8 +1285,9 @@ pub(super) fn check_lifetime(&mut self) -> bool {
/// Parses a single lifetime `'a` or panics.
pub(super) fn expect_lifetime(&mut self) -> Lifetime {
- if let Some(ident) = self.token.lifetime() {
- if ident.without_first_quote().is_reserved()
+ if let Some((ident, is_raw)) = self.token.lifetime() {
+ if matches!(is_raw, IdentIsRaw::No)
+ && ident.without_first_quote().is_reserved()
&& ![kw::UnderscoreLifetime, kw::StaticLifetime].contains(&ident.name)
{
self.dcx().emit_err(errors::KeywordLifetime { span: ident.span });
diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs
index 21478a4..e41f89a 100644
--- a/compiler/rustc_passes/src/check_attr.rs
+++ b/compiler/rustc_passes/src/check_attr.rs
@@ -125,7 +125,9 @@ fn check_attributes(
[sym::inline, ..] => self.check_inline(hir_id, attr, span, target),
[sym::coverage, ..] => self.check_coverage(attr, span, target),
[sym::optimize, ..] => self.check_optimize(hir_id, attr, target),
- [sym::no_sanitize, ..] => self.check_no_sanitize(hir_id, attr, span, target),
+ [sym::no_sanitize, ..] => {
+ self.check_applied_to_fn_or_method(hir_id, attr, span, target)
+ }
[sym::non_exhaustive, ..] => self.check_non_exhaustive(hir_id, attr, span, target),
[sym::marker, ..] => self.check_marker(hir_id, attr, span, target),
[sym::target_feature, ..] => {
@@ -166,10 +168,13 @@ fn check_attributes(
self.check_rustc_legacy_const_generics(hir_id, attr, span, target, item)
}
[sym::rustc_lint_query_instability, ..] => {
- self.check_rustc_lint_query_instability(hir_id, attr, span, target)
+ self.check_applied_to_fn_or_method(hir_id, attr, span, target)
+ }
+ [sym::rustc_lint_untracked_query_information, ..] => {
+ self.check_applied_to_fn_or_method(hir_id, attr, span, target)
}
[sym::rustc_lint_diagnostics, ..] => {
- self.check_rustc_lint_diagnostics(hir_id, attr, span, target)
+ self.check_applied_to_fn_or_method(hir_id, attr, span, target)
}
[sym::rustc_lint_opt_ty, ..] => self.check_rustc_lint_opt_ty(attr, span, target),
[sym::rustc_lint_opt_deny_field_access, ..] => {
@@ -452,11 +457,6 @@ fn check_optimize(&self, hir_id: HirId, attr: &Attribute, target: Target) {
}
}
- /// Checks that `#[no_sanitize(..)]` is applied to a function or method.
- fn check_no_sanitize(&self, hir_id: HirId, attr: &Attribute, span: Span, target: Target) {
- self.check_applied_to_fn_or_method(hir_id, attr, span, target)
- }
-
fn check_generic_attr(
&self,
hir_id: HirId,
@@ -1635,30 +1635,6 @@ fn check_applied_to_fn_or_method(
}
}
- /// Checks that the `#[rustc_lint_query_instability]` attribute is only applied to a function
- /// or method.
- fn check_rustc_lint_query_instability(
- &self,
- hir_id: HirId,
- attr: &Attribute,
- span: Span,
- target: Target,
- ) {
- self.check_applied_to_fn_or_method(hir_id, attr, span, target)
- }
-
- /// Checks that the `#[rustc_lint_diagnostics]` attribute is only applied to a function or
- /// method.
- fn check_rustc_lint_diagnostics(
- &self,
- hir_id: HirId,
- attr: &Attribute,
- span: Span,
- target: Target,
- ) {
- self.check_applied_to_fn_or_method(hir_id, attr, span, target)
- }
-
/// Checks that the `#[rustc_lint_opt_ty]` attribute is only applied to a struct.
fn check_rustc_lint_opt_ty(&self, attr: &Attribute, span: Span, target: Target) {
match target {
diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs
index 79c4245..917cb81 100644
--- a/compiler/rustc_resolve/src/late.rs
+++ b/compiler/rustc_resolve/src/late.rs
@@ -2062,7 +2062,10 @@ fn record_lifetime_res(
lint::builtin::ELIDED_NAMED_LIFETIMES,
missing.id_for_lint,
missing.span,
- BuiltinLintDiag::ElidedIsStatic { elided: missing.span },
+ BuiltinLintDiag::ElidedNamedLifetimes {
+ elided: (missing.span, missing.kind),
+ resolution: lint::ElidedLifetimeResolution::Static,
+ },
);
}
}
@@ -2072,9 +2075,12 @@ fn record_lifetime_res(
lint::builtin::ELIDED_NAMED_LIFETIMES,
missing.id_for_lint,
missing.span,
- BuiltinLintDiag::ElidedIsParam {
- elided: missing.span,
- param: (tcx.item_name(param.into()), tcx.source_span(param)),
+ BuiltinLintDiag::ElidedNamedLifetimes {
+ elided: (missing.span, missing.kind),
+ resolution: lint::ElidedLifetimeResolution::Param(
+ tcx.item_name(param.into()),
+ tcx.source_span(param),
+ ),
},
);
}
diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs
index 908d50a..f3e3b36 100644
--- a/compiler/rustc_session/src/config.rs
+++ b/compiler/rustc_session/src/config.rs
@@ -842,6 +842,11 @@ pub struct NextSolverConfig {
/// This is only `true` if `coherence` is also enabled.
pub globally: bool,
}
+impl Default for NextSolverConfig {
+ fn default() -> Self {
+ NextSolverConfig { coherence: true, globally: false }
+ }
+}
#[derive(Clone)]
pub enum Input {
diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs
index 45339c2..a57dc80 100644
--- a/compiler/rustc_session/src/options.rs
+++ b/compiler/rustc_session/src/options.rs
@@ -403,7 +403,7 @@ mod desc {
pub(crate) const parse_unpretty: &str = "`string` or `string=string`";
pub(crate) const parse_treat_err_as_bug: &str = "either no value or a non-negative number";
pub(crate) const parse_next_solver_config: &str =
- "a comma separated list of solver configurations: `globally` (default), and `coherence`";
+ "either `globally` (when used without an argument), `coherence` (default) or `no`";
pub(crate) const parse_lto: &str =
"either a boolean (`yes`, `no`, `on`, `off`, etc), `thin`, `fat`, or omitted";
pub(crate) const parse_linker_plugin_lto: &str =
@@ -1105,27 +1105,16 @@ pub(crate) fn parse_treat_err_as_bug(
}
}
- pub(crate) fn parse_next_solver_config(
- slot: &mut Option<NextSolverConfig>,
- v: Option<&str>,
- ) -> bool {
+ pub(crate) fn parse_next_solver_config(slot: &mut NextSolverConfig, v: Option<&str>) -> bool {
if let Some(config) = v {
- let mut coherence = false;
- let mut globally = true;
- for c in config.split(',') {
- match c {
- "globally" => globally = true,
- "coherence" => {
- globally = false;
- coherence = true;
- }
- _ => return false,
- }
- }
-
- *slot = Some(NextSolverConfig { coherence: coherence || globally, globally });
+ *slot = match config {
+ "no" => NextSolverConfig { coherence: false, globally: false },
+ "coherence" => NextSolverConfig { coherence: true, globally: false },
+ "globally" => NextSolverConfig { coherence: true, globally: true },
+ _ => return false,
+ };
} else {
- *slot = Some(NextSolverConfig { coherence: true, globally: true });
+ *slot = NextSolverConfig { coherence: true, globally: true };
}
true
@@ -1878,7 +1867,7 @@ pub(crate) fn parse_mir_include_spans(slot: &mut MirIncludeSpans, v: Option<&str
"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)"),
- next_solver: Option<NextSolverConfig> = (None, parse_next_solver_config, [TRACKED],
+ 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],
"dump facts from NLL analysis into side files (default: no)"),
diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs
index db4f44e..d5240a0 100644
--- a/compiler/rustc_span/src/symbol.rs
+++ b/compiler/rustc_span/src/symbol.rs
@@ -20,7 +20,8 @@
// The proc macro code for this is in `compiler/rustc_macros/src/symbols.rs`.
symbols! {
- // If you modify this list, adjust `is_special` and `is_used_keyword`/`is_unused_keyword`.
+ // If you modify this list, adjust `is_special`, `is_used_keyword`/`is_unused_keyword`
+ // and `AllKeywords`.
// But this should rarely be necessary if the keywords are kept in alphabetic order.
Keywords {
// Special reserved identifiers used internally for elided lifetimes,
@@ -1255,6 +1256,7 @@
mut_preserve_binding_mode_2024,
mut_ref,
naked,
+ naked_asm,
naked_functions,
name,
names,
@@ -1655,6 +1657,7 @@
rustc_lint_opt_deny_field_access,
rustc_lint_opt_ty,
rustc_lint_query_instability,
+ rustc_lint_untracked_query_information,
rustc_macro_transparency,
rustc_main,
rustc_mir,
@@ -2579,3 +2582,42 @@ pub fn is_raw_guess(self) -> bool {
self.name.can_be_raw() && self.is_reserved()
}
}
+
+/// An iterator over all the keywords in Rust.
+#[derive(Copy, Clone)]
+pub struct AllKeywords {
+ curr_idx: u32,
+ end_idx: u32,
+}
+
+impl AllKeywords {
+ /// Initialize a new iterator over all the keywords.
+ ///
+ /// *Note:* Please update this if a new keyword is added beyond the current
+ /// range.
+ pub fn new() -> Self {
+ AllKeywords { curr_idx: kw::Empty.as_u32(), end_idx: kw::Yeet.as_u32() }
+ }
+
+ /// Collect all the keywords in a given edition into a vector.
+ pub fn collect_used(&self, edition: impl Copy + FnOnce() -> Edition) -> Vec<Symbol> {
+ self.filter(|&keyword| {
+ keyword.is_used_keyword_always() || keyword.is_used_keyword_conditional(edition)
+ })
+ .collect()
+ }
+}
+
+impl Iterator for AllKeywords {
+ type Item = Symbol;
+
+ fn next(&mut self) -> Option<Self::Item> {
+ if self.curr_idx <= self.end_idx {
+ let keyword = Symbol::new(self.curr_idx);
+ self.curr_idx += 1;
+ Some(keyword)
+ } else {
+ None
+ }
+ }
+}
diff --git a/compiler/rustc_target/src/lib.rs b/compiler/rustc_target/src/lib.rs
index d7c66d6..2121c41 100644
--- a/compiler/rustc_target/src/lib.rs
+++ b/compiler/rustc_target/src/lib.rs
@@ -9,7 +9,6 @@
// tidy-alphabetical-start
#![allow(internal_features)]
-#![cfg_attr(bootstrap, feature(min_exhaustive_patterns))]
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
#![doc(rust_logo)]
#![feature(assert_matches)]
diff --git a/compiler/rustc_target/src/spec/base/apple/mod.rs b/compiler/rustc_target/src/spec/base/apple/mod.rs
index b752a34..b1fe49f 100644
--- a/compiler/rustc_target/src/spec/base/apple/mod.rs
+++ b/compiler/rustc_target/src/spec/base/apple/mod.rs
@@ -1,5 +1,6 @@
use std::borrow::Cow;
use std::env;
+use std::num::ParseIntError;
use crate::spec::{
add_link_args, add_link_args_iter, cvs, Cc, DebuginfoKind, FramePointer, LinkArgs,
@@ -39,6 +40,25 @@ fn target_name(self) -> &'static str {
}
}
+ /// The architecture name to forward to the linker.
+ fn ld_arch(self) -> &'static str {
+ // Supported architecture names can be found in the source:
+ // https://github.com/apple-oss-distributions/ld64/blob/ld64-951.9/src/abstraction/MachOFileAbstraction.hpp#L578-L648
+ match self {
+ Armv7k => "armv7k",
+ Armv7s => "armv7s",
+ Arm64 => "arm64",
+ Arm64e => "arm64e",
+ Arm64_32 => "arm64_32",
+ // ld64 doesn't understand i686, so fall back to i386 instead
+ //
+ // Same story when linking with cc, since that ends up invoking ld64.
+ I386 | I686 => "i386",
+ X86_64 => "x86_64",
+ X86_64h => "x86_64h",
+ }
+ }
+
pub(crate) fn target_arch(self) -> Cow<'static, str> {
Cow::Borrowed(match self {
Armv7k | Armv7s => "arm",
@@ -97,53 +117,85 @@ fn target_abi(self) -> &'static str {
}
fn pre_link_args(os: &'static str, arch: Arch, abi: TargetAbi) -> LinkArgs {
+ // From the man page for ld64 (`man ld`):
+ // > The linker accepts universal (multiple-architecture) input files,
+ // > but always creates a "thin" (single-architecture), standard Mach-O
+ // > output file. The architecture for the output file is specified using
+ // > the -arch option.
+ //
+ // The linker has heuristics to determine the desired architecture, but to
+ // be safe, and to avoid a warning, we set the architecture explicitly.
+ let mut args =
+ TargetOptions::link_args(LinkerFlavor::Darwin(Cc::No, Lld::No), &["-arch", arch.ld_arch()]);
+
+ // From the man page for ld64 (`man ld`):
+ // > This is set to indicate the platform, oldest supported version of
+ // > that platform that output is to be used on, and the SDK that the
+ // > output was built against. platform [...] may be one of the following
+ // > strings:
+ // > - macos
+ // > - ios
+ // > - tvos
+ // > - watchos
+ // > - bridgeos
+ // > - visionos
+ // > - xros
+ // > - mac-catalyst
+ // > - ios-simulator
+ // > - tvos-simulator
+ // > - watchos-simulator
+ // > - visionos-simulator
+ // > - xros-simulator
+ // > - driverkit
+ //
+ // Like with `-arch`, the linker can figure out the platform versions
+ // itself from the binaries being linked, but to be safe, we specify the
+ // desired versions here explicitly.
let platform_name: StaticCow<str> = match abi {
TargetAbi::Normal => os.into(),
TargetAbi::Simulator => format!("{os}-simulator").into(),
TargetAbi::MacCatalyst => "mac-catalyst".into(),
};
-
let min_version: StaticCow<str> = {
- let (major, minor) = match os {
- "ios" => ios_deployment_target(arch, abi.target_abi()),
- "tvos" => tvos_deployment_target(),
- "watchos" => watchos_deployment_target(),
- "visionos" => visionos_deployment_target(),
- "macos" => macos_deployment_target(arch),
- _ => unreachable!(),
- };
- format!("{major}.{minor}").into()
+ let (major, minor, patch) = deployment_target(os, arch, abi);
+ format!("{major}.{minor}.{patch}").into()
};
+ // Lie about the SDK version, we don't know it here
let sdk_version = min_version.clone();
-
- let mut args = TargetOptions::link_args(
- LinkerFlavor::Darwin(Cc::No, Lld::No),
- &["-arch", arch.target_name(), "-platform_version"],
- );
add_link_args_iter(
&mut args,
LinkerFlavor::Darwin(Cc::No, Lld::No),
- [platform_name, min_version, sdk_version].into_iter(),
+ ["-platform_version".into(), platform_name, min_version, sdk_version].into_iter(),
);
+
if abi != TargetAbi::MacCatalyst {
+ // CC forwards the `-arch` to the linker, so we use the same value
+ // here intentionally.
add_link_args(
&mut args,
LinkerFlavor::Darwin(Cc::Yes, Lld::No),
- &["-arch", arch.target_name()],
+ &["-arch", arch.ld_arch()],
);
} else {
add_link_args_iter(
&mut args,
LinkerFlavor::Darwin(Cc::Yes, Lld::No),
- ["-target".into(), mac_catalyst_llvm_target(arch).into()].into_iter(),
+ ["-target".into(), llvm_target(os, arch, abi)].into_iter(),
);
}
args
}
-pub(crate) fn opts(os: &'static str, arch: Arch, abi: TargetAbi) -> TargetOptions {
- TargetOptions {
+/// Get the base target options, LLVM target and `target_arch` from the three
+/// things that uniquely identify Rust's Apple targets: The OS, the
+/// architecture, and the ABI.
+pub(crate) fn base(
+ os: &'static str,
+ arch: Arch,
+ abi: TargetAbi,
+) -> (TargetOptions, StaticCow<str>, StaticCow<str>) {
+ let opts = TargetOptions {
abi: abi.target_abi().into(),
os: os.into(),
cpu: arch.target_cpu(abi).into(),
@@ -193,10 +245,11 @@ pub(crate) fn opts(os: &'static str, arch: Arch, abi: TargetAbi) -> TargetOption
link_env: Cow::Borrowed(&[(Cow::Borrowed("ZERO_AR_DATE"), Cow::Borrowed("1"))]),
..Default::default()
- }
+ };
+ (opts, llvm_target(os, arch, abi), arch.target_arch())
}
-pub fn sdk_version(platform: u32) -> Option<(u32, u32)> {
+pub fn sdk_version(platform: u32) -> Option<(u16, u8)> {
// NOTE: These values are from an arbitrary point in time but shouldn't make it into the final
// binary since the final link command will have the current SDK version passed to it.
match platform {
@@ -230,58 +283,108 @@ pub fn platform(target: &Target) -> Option<u32> {
})
}
-pub fn deployment_target(target: &Target) -> Option<(u32, u32)> {
- let (major, minor) = match &*target.os {
- "macos" => {
- // This does not need to be specific. It just needs to handle x86 vs M1.
- let arch = match target.arch.as_ref() {
- "x86" | "x86_64" => X86_64,
- "arm64e" => Arm64e,
- _ => Arm64,
- };
- macos_deployment_target(arch)
- }
- "ios" => {
- let arch = match target.arch.as_ref() {
- "arm64e" => Arm64e,
- _ => Arm64,
- };
- ios_deployment_target(arch, &target.abi)
- }
- "watchos" => watchos_deployment_target(),
- "tvos" => tvos_deployment_target(),
- "visionos" => visionos_deployment_target(),
- _ => return None,
+/// Hack for calling `deployment_target` outside of this module.
+pub fn deployment_target_for_target(target: &Target) -> (u16, u8, u8) {
+ let arch = if target.llvm_target.starts_with("arm64e") {
+ Arch::Arm64e
+ } else if target.arch == "aarch64" {
+ Arch::Arm64
+ } else {
+ // Dummy architecture, only used by `deployment_target` anyhow
+ Arch::X86_64
+ };
+ let abi = match &*target.abi {
+ "macabi" => TargetAbi::MacCatalyst,
+ "sim" => TargetAbi::Simulator,
+ "" => TargetAbi::Normal,
+ abi => unreachable!("invalid abi '{abi}' for Apple target"),
+ };
+ deployment_target(&target.os, arch, abi)
+}
+
+/// Get the deployment target based on the standard environment variables, or
+/// fall back to a sane default.
+fn deployment_target(os: &str, arch: Arch, abi: TargetAbi) -> (u16, u8, u8) {
+ // When bumping a version in here, remember to update the platform-support
+ // docs too.
+ //
+ // NOTE: If you are looking for the default deployment target, prefer
+ // `rustc --print deployment-target`, as the default here may change in
+ // future `rustc` versions.
+
+ // Minimum operating system versions currently supported by `rustc`.
+ let os_min = match os {
+ "macos" => (10, 12, 0),
+ "ios" => (10, 0, 0),
+ "tvos" => (10, 0, 0),
+ "watchos" => (5, 0, 0),
+ "visionos" => (1, 0, 0),
+ _ => unreachable!("tried to get deployment target for non-Apple platform"),
};
- Some((major, minor))
-}
+ // On certain targets it makes sense to raise the minimum OS version.
+ let min = match (os, arch, abi) {
+ // Use 11.0 on Aarch64 as that's the earliest version with M1 support.
+ ("macos", Arch::Arm64 | Arch::Arm64e, _) => (11, 0, 0),
+ ("ios", Arch::Arm64e, _) => (14, 0, 0),
+ // Mac Catalyst defaults to 13.1 in Clang.
+ ("ios", _, TargetAbi::MacCatalyst) => (13, 1, 0),
+ _ => os_min,
+ };
-fn from_set_deployment_target(var_name: &str) -> Option<(u32, u32)> {
- let deployment_target = env::var(var_name).ok()?;
- let (unparsed_major, unparsed_minor) = deployment_target.split_once('.')?;
- let (major, minor) = (unparsed_major.parse().ok()?, unparsed_minor.parse().ok()?);
+ // The environment variable used to fetch the deployment target.
+ let env_var = match os {
+ "macos" => "MACOSX_DEPLOYMENT_TARGET",
+ "ios" => "IPHONEOS_DEPLOYMENT_TARGET",
+ "watchos" => "WATCHOS_DEPLOYMENT_TARGET",
+ "tvos" => "TVOS_DEPLOYMENT_TARGET",
+ "visionos" => "XROS_DEPLOYMENT_TARGET",
+ _ => unreachable!("tried to get deployment target env var for non-Apple platform"),
+ };
- Some((major, minor))
-}
-
-fn macos_default_deployment_target(arch: Arch) -> (u32, u32) {
- match arch {
- Arm64 | Arm64e => (11, 0),
- _ => (10, 12),
+ if let Ok(deployment_target) = env::var(env_var) {
+ match parse_version(&deployment_target) {
+ // It is common that the deployment target is set too low, e.g. on
+ // macOS Aarch64 to also target older x86_64, the user may set a
+ // lower deployment target than supported.
+ //
+ // To avoid such issues, we silently raise the deployment target
+ // here.
+ // FIXME: We want to show a warning when `version < os_min`.
+ Ok(version) => version.max(min),
+ // FIXME: Report erroneous environment variable to user.
+ Err(_) => min,
+ }
+ } else {
+ min
}
}
-fn macos_deployment_target(arch: Arch) -> (u32, u32) {
- // If you are looking for the default deployment target, prefer `rustc --print deployment-target`.
- // Note: If bumping this version, remember to update it in the rustc/platform-support docs.
- from_set_deployment_target("MACOSX_DEPLOYMENT_TARGET")
- .unwrap_or_else(|| macos_default_deployment_target(arch))
-}
-
-pub(crate) fn macos_llvm_target(arch: Arch) -> String {
- let (major, minor) = macos_deployment_target(arch);
- format!("{}-apple-macosx{}.{}.0", arch.target_name(), major, minor)
+/// Generate the target triple that we need to pass to LLVM and/or Clang.
+fn llvm_target(os: &str, arch: Arch, abi: TargetAbi) -> StaticCow<str> {
+ // The target triple depends on the deployment target, and is required to
+ // enable features such as cross-language LTO, and for picking the right
+ // Mach-O commands.
+ //
+ // Certain optimizations also depend on the deployment target.
+ let (major, minor, patch) = deployment_target(os, arch, abi);
+ let arch = arch.target_name();
+ // Convert to the "canonical" OS name used by LLVM:
+ // https://github.com/llvm/llvm-project/blob/llvmorg-18.1.8/llvm/lib/TargetParser/Triple.cpp#L236-L282
+ let os = match os {
+ "macos" => "macosx",
+ "ios" => "ios",
+ "watchos" => "watchos",
+ "tvos" => "tvos",
+ "visionos" => "xros",
+ _ => unreachable!("tried to get LLVM target OS for non-Apple platform"),
+ };
+ let environment = match abi {
+ TargetAbi::Normal => "",
+ TargetAbi::MacCatalyst => "-macabi",
+ TargetAbi::Simulator => "-simulator",
+ };
+ format!("{arch}-apple-{os}{major}.{minor}.{patch}{environment}").into()
}
fn link_env_remove(os: &'static str) -> StaticCow<[StaticCow<str>]> {
@@ -321,83 +424,19 @@ fn link_env_remove(os: &'static str) -> StaticCow<[StaticCow<str>]> {
}
}
-fn ios_deployment_target(arch: Arch, abi: &str) -> (u32, u32) {
- // If you are looking for the default deployment target, prefer `rustc --print deployment-target`.
- // Note: If bumping this version, remember to update it in the rustc/platform-support docs.
- let (major, minor) = match (arch, abi) {
- (Arm64e, _) => (14, 0),
- // Mac Catalyst defaults to 13.1 in Clang.
- (_, "macabi") => (13, 1),
- _ => (10, 0),
- };
- from_set_deployment_target("IPHONEOS_DEPLOYMENT_TARGET").unwrap_or((major, minor))
-}
-
-pub(crate) fn ios_llvm_target(arch: Arch) -> String {
- // Modern iOS tooling extracts information about deployment target
- // from LC_BUILD_VERSION. This load command will only be emitted when
- // we build with a version specific `llvm_target`, with the version
- // set high enough. Luckily one LC_BUILD_VERSION is enough, for Xcode
- // to pick it up (since std and core are still built with the fallback
- // of version 7.0 and hence emit the old LC_IPHONE_MIN_VERSION).
- let (major, minor) = ios_deployment_target(arch, "");
- format!("{}-apple-ios{}.{}.0", arch.target_name(), major, minor)
-}
-
-pub(crate) fn mac_catalyst_llvm_target(arch: Arch) -> String {
- let (major, minor) = ios_deployment_target(arch, "macabi");
- format!("{}-apple-ios{}.{}.0-macabi", arch.target_name(), major, minor)
-}
-
-pub(crate) fn ios_sim_llvm_target(arch: Arch) -> String {
- let (major, minor) = ios_deployment_target(arch, "sim");
- format!("{}-apple-ios{}.{}.0-simulator", arch.target_name(), major, minor)
-}
-
-fn tvos_deployment_target() -> (u32, u32) {
- // If you are looking for the default deployment target, prefer `rustc --print deployment-target`.
- // Note: If bumping this version, remember to update it in the rustc platform-support docs.
- from_set_deployment_target("TVOS_DEPLOYMENT_TARGET").unwrap_or((10, 0))
-}
-
-pub(crate) fn tvos_llvm_target(arch: Arch) -> String {
- let (major, minor) = tvos_deployment_target();
- format!("{}-apple-tvos{}.{}.0", arch.target_name(), major, minor)
-}
-
-pub(crate) fn tvos_sim_llvm_target(arch: Arch) -> String {
- let (major, minor) = tvos_deployment_target();
- format!("{}-apple-tvos{}.{}.0-simulator", arch.target_name(), major, minor)
-}
-
-fn watchos_deployment_target() -> (u32, u32) {
- // If you are looking for the default deployment target, prefer `rustc --print deployment-target`.
- // Note: If bumping this version, remember to update it in the rustc platform-support docs.
- from_set_deployment_target("WATCHOS_DEPLOYMENT_TARGET").unwrap_or((5, 0))
-}
-
-pub(crate) fn watchos_llvm_target(arch: Arch) -> String {
- let (major, minor) = watchos_deployment_target();
- format!("{}-apple-watchos{}.{}.0", arch.target_name(), major, minor)
-}
-
-pub(crate) fn watchos_sim_llvm_target(arch: Arch) -> String {
- let (major, minor) = watchos_deployment_target();
- format!("{}-apple-watchos{}.{}.0-simulator", arch.target_name(), major, minor)
-}
-
-fn visionos_deployment_target() -> (u32, u32) {
- // If you are looking for the default deployment target, prefer `rustc --print deployment-target`.
- // Note: If bumping this version, remember to update it in the rustc platform-support docs.
- from_set_deployment_target("XROS_DEPLOYMENT_TARGET").unwrap_or((1, 0))
-}
-
-pub(crate) fn visionos_llvm_target(arch: Arch) -> String {
- let (major, minor) = visionos_deployment_target();
- format!("{}-apple-visionos{}.{}.0", arch.target_name(), major, minor)
-}
-
-pub(crate) fn visionos_sim_llvm_target(arch: Arch) -> String {
- let (major, minor) = visionos_deployment_target();
- format!("{}-apple-visionos{}.{}.0-simulator", arch.target_name(), major, minor)
+/// Parse an OS version triple (SDK version or deployment target).
+///
+/// The size of the returned numbers here are limited by Mach-O's
+/// `LC_BUILD_VERSION`.
+fn parse_version(version: &str) -> Result<(u16, u8, u8), ParseIntError> {
+ if let Some((major, minor)) = version.split_once('.') {
+ let major = major.parse()?;
+ if let Some((minor, patch)) = minor.split_once('.') {
+ Ok((major, minor.parse()?, patch.parse()?))
+ } else {
+ Ok((major, minor.parse()?, 0))
+ }
+ } else {
+ Ok((version.parse()?, 0, 0))
+ }
}
diff --git a/compiler/rustc_target/src/spec/base/apple/tests.rs b/compiler/rustc_target/src/spec/base/apple/tests.rs
index 7a985ad..d55b44e 100644
--- a/compiler/rustc_target/src/spec/base/apple/tests.rs
+++ b/compiler/rustc_target/src/spec/base/apple/tests.rs
@@ -1,3 +1,4 @@
+use super::parse_version;
use crate::spec::targets::{
aarch64_apple_darwin, aarch64_apple_ios_sim, aarch64_apple_visionos_sim,
aarch64_apple_watchos_sim, i686_apple_darwin, x86_64_apple_darwin, x86_64_apple_ios,
@@ -42,3 +43,11 @@ fn macos_link_environment_unmodified() {
);
}
}
+
+#[test]
+fn test_parse_version() {
+ assert_eq!(parse_version("10"), Ok((10, 0, 0)));
+ assert_eq!(parse_version("10.12"), Ok((10, 12, 0)));
+ assert_eq!(parse_version("10.12.6"), Ok((10, 12, 6)));
+ assert_eq!(parse_version("9999.99.99"), Ok((9999, 99, 99)));
+}
diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs
index 6abd8a0..c3e7f74 100644
--- a/compiler/rustc_target/src/spec/mod.rs
+++ b/compiler/rustc_target/src/spec/mod.rs
@@ -60,8 +60,8 @@
mod base;
pub use base::apple::{
- deployment_target as current_apple_deployment_target, platform as current_apple_platform,
- sdk_version as current_apple_sdk_version,
+ deployment_target_for_target as current_apple_deployment_target,
+ platform as current_apple_platform, sdk_version as current_apple_sdk_version,
};
pub use base::avr_gnu::ef_avr_arch;
@@ -1645,6 +1645,7 @@ fn $module() {
("x86_64-unknown-haiku", x86_64_unknown_haiku),
("i686-unknown-hurd-gnu", i686_unknown_hurd_gnu),
+ ("x86_64-unknown-hurd-gnu", x86_64_unknown_hurd_gnu),
("aarch64-apple-darwin", aarch64_apple_darwin),
("arm64e-apple-darwin", arm64e_apple_darwin),
diff --git a/compiler/rustc_target/src/spec/targets/aarch64_apple_darwin.rs b/compiler/rustc_target/src/spec/targets/aarch64_apple_darwin.rs
index 912392c..1061633 100644
--- a/compiler/rustc_target/src/spec/targets/aarch64_apple_darwin.rs
+++ b/compiler/rustc_target/src/spec/targets/aarch64_apple_darwin.rs
@@ -1,20 +1,10 @@
-use crate::spec::base::apple::{macos_llvm_target, opts, Arch, TargetAbi};
+use crate::spec::base::apple::{base, Arch, TargetAbi};
use crate::spec::{FramePointer, SanitizerSet, Target, TargetOptions};
pub(crate) fn target() -> Target {
- let arch = Arch::Arm64;
- let mut base = opts("macos", arch, TargetAbi::Normal);
- base.cpu = "apple-m1".into();
- base.max_atomic_width = Some(128);
-
- // FIXME: The leak sanitizer currently fails the tests, see #88132.
- base.supported_sanitizers = SanitizerSet::ADDRESS | SanitizerSet::CFI | SanitizerSet::THREAD;
-
+ let (opts, llvm_target, arch) = base("macos", Arch::Arm64, TargetAbi::Normal);
Target {
- // Clang automatically chooses a more specific target based on
- // MACOSX_DEPLOYMENT_TARGET. To enable cross-language LTO to work
- // correctly, we do too.
- llvm_target: macos_llvm_target(arch).into(),
+ llvm_target,
metadata: crate::spec::TargetMetadata {
description: Some("ARM64 macOS (11.0+, Big Sur+)".into()),
tier: Some(1),
@@ -23,11 +13,15 @@ pub(crate) fn target() -> Target {
},
pointer_width: 64,
data_layout: "e-m:o-i64:64-i128:128-n32:64-S128-Fn32".into(),
- arch: arch.target_arch(),
+ arch,
options: TargetOptions {
mcount: "\u{1}mcount".into(),
frame_pointer: FramePointer::NonLeaf,
- ..base
+ cpu: "apple-m1".into(),
+ max_atomic_width: Some(128),
+ // FIXME: The leak sanitizer currently fails the tests, see #88132.
+ supported_sanitizers: SanitizerSet::ADDRESS | SanitizerSet::CFI | SanitizerSet::THREAD,
+ ..opts
},
}
}
diff --git a/compiler/rustc_target/src/spec/targets/aarch64_apple_ios.rs b/compiler/rustc_target/src/spec/targets/aarch64_apple_ios.rs
index 7f3a86f..caeb9a1 100644
--- a/compiler/rustc_target/src/spec/targets/aarch64_apple_ios.rs
+++ b/compiler/rustc_target/src/spec/targets/aarch64_apple_ios.rs
@@ -1,17 +1,10 @@
-use crate::spec::base::apple::{ios_llvm_target, opts, Arch, TargetAbi};
+use crate::spec::base::apple::{base, Arch, TargetAbi};
use crate::spec::{FramePointer, SanitizerSet, Target, TargetOptions};
pub(crate) fn target() -> Target {
- let arch = Arch::Arm64;
- let mut base = opts("ios", arch, TargetAbi::Normal);
- base.supported_sanitizers = SanitizerSet::ADDRESS | SanitizerSet::THREAD;
-
+ let (opts, llvm_target, arch) = base("ios", Arch::Arm64, TargetAbi::Normal);
Target {
- // Clang automatically chooses a more specific target based on
- // IPHONEOS_DEPLOYMENT_TARGET.
- // This is required for the target to pick the right
- // MACH-O commands, so we do too.
- llvm_target: ios_llvm_target(arch).into(),
+ llvm_target,
metadata: crate::spec::TargetMetadata {
description: Some("ARM64 iOS".into()),
tier: Some(2),
@@ -20,12 +13,13 @@ pub(crate) fn target() -> Target {
},
pointer_width: 64,
data_layout: "e-m:o-i64:64-i128:128-n32:64-S128-Fn32".into(),
- arch: arch.target_arch(),
+ arch,
options: TargetOptions {
features: "+neon,+fp-armv8,+apple-a7".into(),
max_atomic_width: Some(128),
frame_pointer: FramePointer::NonLeaf,
- ..base
+ supported_sanitizers: SanitizerSet::ADDRESS | SanitizerSet::THREAD,
+ ..opts
},
}
}
diff --git a/compiler/rustc_target/src/spec/targets/aarch64_apple_ios_macabi.rs b/compiler/rustc_target/src/spec/targets/aarch64_apple_ios_macabi.rs
index e60eeda..eee9eca 100644
--- a/compiler/rustc_target/src/spec/targets/aarch64_apple_ios_macabi.rs
+++ b/compiler/rustc_target/src/spec/targets/aarch64_apple_ios_macabi.rs
@@ -1,13 +1,10 @@
-use crate::spec::base::apple::{mac_catalyst_llvm_target, opts, Arch, TargetAbi};
+use crate::spec::base::apple::{base, Arch, TargetAbi};
use crate::spec::{FramePointer, SanitizerSet, Target, TargetOptions};
pub(crate) fn target() -> Target {
- let arch = Arch::Arm64;
- let mut base = opts("ios", arch, TargetAbi::MacCatalyst);
- base.supported_sanitizers = SanitizerSet::ADDRESS | SanitizerSet::LEAK | SanitizerSet::THREAD;
-
+ let (opts, llvm_target, arch) = base("ios", Arch::Arm64, TargetAbi::MacCatalyst);
Target {
- llvm_target: mac_catalyst_llvm_target(arch).into(),
+ llvm_target,
metadata: crate::spec::TargetMetadata {
description: Some("Apple Catalyst on ARM64".into()),
tier: Some(2),
@@ -16,12 +13,13 @@ pub(crate) fn target() -> Target {
},
pointer_width: 64,
data_layout: "e-m:o-i64:64-i128:128-n32:64-S128-Fn32".into(),
- arch: arch.target_arch(),
+ arch,
options: TargetOptions {
features: "+neon,+fp-armv8,+apple-a12".into(),
max_atomic_width: Some(128),
frame_pointer: FramePointer::NonLeaf,
- ..base
+ supported_sanitizers: SanitizerSet::ADDRESS | SanitizerSet::LEAK | SanitizerSet::THREAD,
+ ..opts
},
}
}
diff --git a/compiler/rustc_target/src/spec/targets/aarch64_apple_ios_sim.rs b/compiler/rustc_target/src/spec/targets/aarch64_apple_ios_sim.rs
index d605e22..ee58038 100644
--- a/compiler/rustc_target/src/spec/targets/aarch64_apple_ios_sim.rs
+++ b/compiler/rustc_target/src/spec/targets/aarch64_apple_ios_sim.rs
@@ -1,17 +1,10 @@
-use crate::spec::base::apple::{ios_sim_llvm_target, opts, Arch, TargetAbi};
+use crate::spec::base::apple::{base, Arch, TargetAbi};
use crate::spec::{FramePointer, SanitizerSet, Target, TargetOptions};
pub(crate) fn target() -> Target {
- let arch = Arch::Arm64;
- let mut base = opts("ios", arch, TargetAbi::Simulator);
- base.supported_sanitizers = SanitizerSet::ADDRESS | SanitizerSet::THREAD;
-
+ let (opts, llvm_target, arch) = base("ios", Arch::Arm64, TargetAbi::Simulator);
Target {
- // Clang automatically chooses a more specific target based on
- // IPHONEOS_DEPLOYMENT_TARGET.
- // This is required for the simulator target to pick the right
- // MACH-O commands, so we do too.
- llvm_target: ios_sim_llvm_target(arch).into(),
+ llvm_target,
metadata: crate::spec::TargetMetadata {
description: Some("Apple iOS Simulator on ARM64".into()),
tier: Some(2),
@@ -20,12 +13,13 @@ pub(crate) fn target() -> Target {
},
pointer_width: 64,
data_layout: "e-m:o-i64:64-i128:128-n32:64-S128-Fn32".into(),
- arch: arch.target_arch(),
+ arch,
options: TargetOptions {
features: "+neon,+fp-armv8,+apple-a7".into(),
max_atomic_width: Some(128),
frame_pointer: FramePointer::NonLeaf,
- ..base
+ supported_sanitizers: SanitizerSet::ADDRESS | SanitizerSet::THREAD,
+ ..opts
},
}
}
diff --git a/compiler/rustc_target/src/spec/targets/aarch64_apple_tvos.rs b/compiler/rustc_target/src/spec/targets/aarch64_apple_tvos.rs
index fc774ab..baca863 100644
--- a/compiler/rustc_target/src/spec/targets/aarch64_apple_tvos.rs
+++ b/compiler/rustc_target/src/spec/targets/aarch64_apple_tvos.rs
@@ -1,10 +1,10 @@
-use crate::spec::base::apple::{opts, tvos_llvm_target, Arch, TargetAbi};
+use crate::spec::base::apple::{base, Arch, TargetAbi};
use crate::spec::{FramePointer, Target, TargetOptions};
pub(crate) fn target() -> Target {
- let arch = Arch::Arm64;
+ let (opts, llvm_target, arch) = base("tvos", Arch::Arm64, TargetAbi::Normal);
Target {
- llvm_target: tvos_llvm_target(arch).into(),
+ llvm_target,
metadata: crate::spec::TargetMetadata {
description: Some("ARM64 tvOS".into()),
tier: Some(3),
@@ -13,12 +13,12 @@ pub(crate) fn target() -> Target {
},
pointer_width: 64,
data_layout: "e-m:o-i64:64-i128:128-n32:64-S128-Fn32".into(),
- arch: arch.target_arch(),
+ arch,
options: TargetOptions {
features: "+neon,+fp-armv8,+apple-a7".into(),
max_atomic_width: Some(128),
frame_pointer: FramePointer::NonLeaf,
- ..opts("tvos", arch, TargetAbi::Normal)
+ ..opts
},
}
}
diff --git a/compiler/rustc_target/src/spec/targets/aarch64_apple_tvos_sim.rs b/compiler/rustc_target/src/spec/targets/aarch64_apple_tvos_sim.rs
index 8e8bb1e..1a48f8c 100644
--- a/compiler/rustc_target/src/spec/targets/aarch64_apple_tvos_sim.rs
+++ b/compiler/rustc_target/src/spec/targets/aarch64_apple_tvos_sim.rs
@@ -1,10 +1,10 @@
-use crate::spec::base::apple::{opts, tvos_sim_llvm_target, Arch, TargetAbi};
+use crate::spec::base::apple::{base, Arch, TargetAbi};
use crate::spec::{FramePointer, Target, TargetOptions};
pub(crate) fn target() -> Target {
- let arch = Arch::Arm64;
+ let (opts, llvm_target, arch) = base("tvos", Arch::Arm64, TargetAbi::Simulator);
Target {
- llvm_target: tvos_sim_llvm_target(arch).into(),
+ llvm_target,
metadata: crate::spec::TargetMetadata {
description: Some("ARM64 tvOS Simulator".into()),
tier: Some(3),
@@ -13,12 +13,12 @@ pub(crate) fn target() -> Target {
},
pointer_width: 64,
data_layout: "e-m:o-i64:64-i128:128-n32:64-S128-Fn32".into(),
- arch: arch.target_arch(),
+ arch,
options: TargetOptions {
features: "+neon,+fp-armv8,+apple-a7".into(),
max_atomic_width: Some(128),
frame_pointer: FramePointer::NonLeaf,
- ..opts("tvos", arch, TargetAbi::Simulator)
+ ..opts
},
}
}
diff --git a/compiler/rustc_target/src/spec/targets/aarch64_apple_visionos.rs b/compiler/rustc_target/src/spec/targets/aarch64_apple_visionos.rs
index 16c7d72..1424126 100644
--- a/compiler/rustc_target/src/spec/targets/aarch64_apple_visionos.rs
+++ b/compiler/rustc_target/src/spec/targets/aarch64_apple_visionos.rs
@@ -1,13 +1,10 @@
-use crate::spec::base::apple::{opts, visionos_llvm_target, Arch, TargetAbi};
+use crate::spec::base::apple::{base, Arch, TargetAbi};
use crate::spec::{FramePointer, SanitizerSet, Target, TargetOptions};
pub(crate) fn target() -> Target {
- let arch = Arch::Arm64;
- let mut base = opts("visionos", arch, TargetAbi::Normal);
- base.supported_sanitizers = SanitizerSet::ADDRESS | SanitizerSet::THREAD;
-
+ let (opts, llvm_target, arch) = base("visionos", Arch::Arm64, TargetAbi::Normal);
Target {
- llvm_target: visionos_llvm_target(arch).into(),
+ llvm_target,
metadata: crate::spec::TargetMetadata {
description: Some("ARM64 Apple visionOS".into()),
tier: Some(3),
@@ -16,12 +13,13 @@ pub(crate) fn target() -> Target {
},
pointer_width: 64,
data_layout: "e-m:o-i64:64-i128:128-n32:64-S128-Fn32".into(),
- arch: arch.target_arch(),
+ arch,
options: TargetOptions {
features: "+neon,+fp-armv8,+apple-a16".into(),
max_atomic_width: Some(128),
frame_pointer: FramePointer::NonLeaf,
- ..base
+ supported_sanitizers: SanitizerSet::ADDRESS | SanitizerSet::THREAD,
+ ..opts
},
}
}
diff --git a/compiler/rustc_target/src/spec/targets/aarch64_apple_visionos_sim.rs b/compiler/rustc_target/src/spec/targets/aarch64_apple_visionos_sim.rs
index 42973e0..d7226e0 100644
--- a/compiler/rustc_target/src/spec/targets/aarch64_apple_visionos_sim.rs
+++ b/compiler/rustc_target/src/spec/targets/aarch64_apple_visionos_sim.rs
@@ -1,13 +1,10 @@
-use crate::spec::base::apple::{opts, visionos_sim_llvm_target, Arch, TargetAbi};
+use crate::spec::base::apple::{base, Arch, TargetAbi};
use crate::spec::{FramePointer, SanitizerSet, Target, TargetOptions};
pub(crate) fn target() -> Target {
- let arch = Arch::Arm64;
- let mut base = opts("visionos", arch, TargetAbi::Simulator);
- base.supported_sanitizers = SanitizerSet::ADDRESS | SanitizerSet::THREAD;
-
+ let (opts, llvm_target, arch) = base("visionos", Arch::Arm64, TargetAbi::Simulator);
Target {
- llvm_target: visionos_sim_llvm_target(arch).into(),
+ llvm_target,
metadata: crate::spec::TargetMetadata {
description: Some("ARM64 Apple visionOS simulator".into()),
tier: Some(3),
@@ -16,12 +13,13 @@ pub(crate) fn target() -> Target {
},
pointer_width: 64,
data_layout: "e-m:o-i64:64-i128:128-n32:64-S128-Fn32".into(),
- arch: arch.target_arch(),
+ arch,
options: TargetOptions {
features: "+neon,+fp-armv8,+apple-a16".into(),
max_atomic_width: Some(128),
frame_pointer: FramePointer::NonLeaf,
- ..base
+ supported_sanitizers: SanitizerSet::ADDRESS | SanitizerSet::THREAD,
+ ..opts
},
}
}
diff --git a/compiler/rustc_target/src/spec/targets/aarch64_apple_watchos.rs b/compiler/rustc_target/src/spec/targets/aarch64_apple_watchos.rs
index 03fc251..1940a56 100644
--- a/compiler/rustc_target/src/spec/targets/aarch64_apple_watchos.rs
+++ b/compiler/rustc_target/src/spec/targets/aarch64_apple_watchos.rs
@@ -1,10 +1,10 @@
-use crate::spec::base::apple::{opts, Arch, TargetAbi};
+use crate::spec::base::apple::{base, Arch, TargetAbi};
use crate::spec::{Target, TargetOptions};
pub(crate) fn target() -> Target {
- let base = opts("watchos", Arch::Arm64, TargetAbi::Normal);
+ let (opts, llvm_target, arch) = base("watchos", Arch::Arm64, TargetAbi::Normal);
Target {
- llvm_target: "aarch64-apple-watchos".into(),
+ llvm_target,
metadata: crate::spec::TargetMetadata {
description: Some("ARM64 Apple WatchOS".into()),
tier: Some(3),
@@ -13,13 +13,13 @@ pub(crate) fn target() -> Target {
},
pointer_width: 64,
data_layout: "e-m:o-i64:64-i128:128-n32:64-S128-Fn32".into(),
- arch: "aarch64".into(),
+ arch,
options: TargetOptions {
features: "+v8a,+neon,+fp-armv8,+apple-a7".into(),
max_atomic_width: Some(128),
dynamic_linking: false,
position_independent_executables: true,
- ..base
+ ..opts
},
}
}
diff --git a/compiler/rustc_target/src/spec/targets/aarch64_apple_watchos_sim.rs b/compiler/rustc_target/src/spec/targets/aarch64_apple_watchos_sim.rs
index 13e2b96..6beef11 100644
--- a/compiler/rustc_target/src/spec/targets/aarch64_apple_watchos_sim.rs
+++ b/compiler/rustc_target/src/spec/targets/aarch64_apple_watchos_sim.rs
@@ -1,14 +1,10 @@
-use crate::spec::base::apple::{opts, watchos_sim_llvm_target, Arch, TargetAbi};
+use crate::spec::base::apple::{base, Arch, TargetAbi};
use crate::spec::{FramePointer, Target, TargetOptions};
pub(crate) fn target() -> Target {
- let arch = Arch::Arm64;
+ let (opts, llvm_target, arch) = base("watchos", Arch::Arm64, TargetAbi::Simulator);
Target {
- // Clang automatically chooses a more specific target based on
- // WATCHOS_DEPLOYMENT_TARGET.
- // This is required for the simulator target to pick the right
- // MACH-O commands, so we do too.
- llvm_target: watchos_sim_llvm_target(arch).into(),
+ llvm_target,
metadata: crate::spec::TargetMetadata {
description: Some("ARM64 Apple WatchOS Simulator".into()),
tier: Some(3),
@@ -17,12 +13,12 @@ pub(crate) fn target() -> Target {
},
pointer_width: 64,
data_layout: "e-m:o-i64:64-i128:128-n32:64-S128-Fn32".into(),
- arch: arch.target_arch(),
+ arch,
options: TargetOptions {
features: "+neon,+fp-armv8,+apple-a7".into(),
max_atomic_width: Some(128),
frame_pointer: FramePointer::NonLeaf,
- ..opts("watchos", arch, TargetAbi::Simulator)
+ ..opts
},
}
}
diff --git a/compiler/rustc_target/src/spec/targets/arm64_32_apple_watchos.rs b/compiler/rustc_target/src/spec/targets/arm64_32_apple_watchos.rs
index f292ee7..e9f4d93 100644
--- a/compiler/rustc_target/src/spec/targets/arm64_32_apple_watchos.rs
+++ b/compiler/rustc_target/src/spec/targets/arm64_32_apple_watchos.rs
@@ -1,11 +1,10 @@
-use crate::spec::base::apple::{opts, watchos_llvm_target, Arch, TargetAbi};
+use crate::spec::base::apple::{base, Arch, TargetAbi};
use crate::spec::{Target, TargetOptions};
pub(crate) fn target() -> Target {
- let arch = Arch::Arm64_32;
- let base = opts("watchos", arch, TargetAbi::Normal);
+ let (opts, llvm_target, arch) = base("watchos", Arch::Arm64_32, TargetAbi::Normal);
Target {
- llvm_target: watchos_llvm_target(arch).into(),
+ llvm_target,
metadata: crate::spec::TargetMetadata {
description: Some("Arm Apple WatchOS 64-bit with 32-bit pointers".into()),
tier: Some(3),
@@ -14,13 +13,13 @@ pub(crate) fn target() -> Target {
},
pointer_width: 32,
data_layout: "e-m:o-p:32:32-i64:64-i128:128-n32:64-S128-Fn32".into(),
- arch: "aarch64".into(),
+ arch,
options: TargetOptions {
features: "+v8a,+neon,+fp-armv8,+apple-a7".into(),
max_atomic_width: Some(128),
dynamic_linking: false,
position_independent_executables: true,
- ..base
+ ..opts
},
}
}
diff --git a/compiler/rustc_target/src/spec/targets/arm64e_apple_darwin.rs b/compiler/rustc_target/src/spec/targets/arm64e_apple_darwin.rs
index e86b835..4f7c945 100644
--- a/compiler/rustc_target/src/spec/targets/arm64e_apple_darwin.rs
+++ b/compiler/rustc_target/src/spec/targets/arm64e_apple_darwin.rs
@@ -1,20 +1,10 @@
-use crate::spec::base::apple::{macos_llvm_target, opts, Arch, TargetAbi};
+use crate::spec::base::apple::{base, Arch, TargetAbi};
use crate::spec::{FramePointer, SanitizerSet, Target, TargetOptions};
pub(crate) fn target() -> Target {
- let arch = Arch::Arm64e;
- let mut base = opts("macos", arch, TargetAbi::Normal);
- base.cpu = "apple-m1".into();
- base.max_atomic_width = Some(128);
-
- // FIXME: The leak sanitizer currently fails the tests, see #88132.
- base.supported_sanitizers = SanitizerSet::ADDRESS | SanitizerSet::CFI | SanitizerSet::THREAD;
-
+ let (opts, llvm_target, arch) = base("macos", Arch::Arm64e, TargetAbi::Normal);
Target {
- // Clang automatically chooses a more specific target based on
- // MACOSX_DEPLOYMENT_TARGET. To enable cross-language LTO to work
- // correctly, we do too.
- llvm_target: macos_llvm_target(arch).into(),
+ llvm_target,
metadata: crate::spec::TargetMetadata {
description: Some("ARM64e Apple Darwin".into()),
tier: Some(3),
@@ -23,11 +13,15 @@ pub(crate) fn target() -> Target {
},
pointer_width: 64,
data_layout: "e-m:o-i64:64-i128:128-n32:64-S128-Fn32".into(),
- arch: arch.target_arch(),
+ arch,
options: TargetOptions {
mcount: "\u{1}mcount".into(),
frame_pointer: FramePointer::NonLeaf,
- ..base
+ cpu: "apple-m1".into(),
+ max_atomic_width: Some(128),
+ // FIXME: The leak sanitizer currently fails the tests, see #88132.
+ supported_sanitizers: SanitizerSet::ADDRESS | SanitizerSet::CFI | SanitizerSet::THREAD,
+ ..opts
},
}
}
diff --git a/compiler/rustc_target/src/spec/targets/arm64e_apple_ios.rs b/compiler/rustc_target/src/spec/targets/arm64e_apple_ios.rs
index fcb850f..8f192fe 100644
--- a/compiler/rustc_target/src/spec/targets/arm64e_apple_ios.rs
+++ b/compiler/rustc_target/src/spec/targets/arm64e_apple_ios.rs
@@ -1,17 +1,10 @@
-use crate::spec::base::apple::{ios_llvm_target, opts, Arch, TargetAbi};
+use crate::spec::base::apple::{base, Arch, TargetAbi};
use crate::spec::{FramePointer, SanitizerSet, Target, TargetOptions};
pub(crate) fn target() -> Target {
- let arch = Arch::Arm64e;
- let mut base = opts("ios", arch, TargetAbi::Normal);
- base.supported_sanitizers = SanitizerSet::ADDRESS | SanitizerSet::THREAD;
-
+ let (opts, llvm_target, arch) = base("ios", Arch::Arm64e, TargetAbi::Normal);
Target {
- // Clang automatically chooses a more specific target based on
- // IPHONEOS_DEPLOYMENT_TARGET.
- // This is required for the target to pick the right
- // MACH-O commands, so we do too.
- llvm_target: ios_llvm_target(arch).into(),
+ llvm_target,
metadata: crate::spec::TargetMetadata {
description: Some("ARM64e Apple iOS".into()),
tier: Some(3),
@@ -20,12 +13,13 @@ pub(crate) fn target() -> Target {
},
pointer_width: 64,
data_layout: "e-m:o-i64:64-i128:128-n32:64-S128-Fn32".into(),
- arch: arch.target_arch(),
+ arch,
options: TargetOptions {
features: "+neon,+fp-armv8,+apple-a12,+v8.3a,+pauth".into(),
max_atomic_width: Some(128),
frame_pointer: FramePointer::NonLeaf,
- ..base
+ supported_sanitizers: SanitizerSet::ADDRESS | SanitizerSet::THREAD,
+ ..opts
},
}
}
diff --git a/compiler/rustc_target/src/spec/targets/armv7k_apple_watchos.rs b/compiler/rustc_target/src/spec/targets/armv7k_apple_watchos.rs
index 35de6b3..8fe27f6 100644
--- a/compiler/rustc_target/src/spec/targets/armv7k_apple_watchos.rs
+++ b/compiler/rustc_target/src/spec/targets/armv7k_apple_watchos.rs
@@ -1,10 +1,10 @@
-use crate::spec::base::apple::{opts, Arch, TargetAbi};
+use crate::spec::base::apple::{base, Arch, TargetAbi};
use crate::spec::{Target, TargetOptions};
pub(crate) fn target() -> Target {
- let arch = Arch::Armv7k;
+ let (opts, llvm_target, arch) = base("watchos", Arch::Armv7k, TargetAbi::Normal);
Target {
- llvm_target: "armv7k-apple-watchos".into(),
+ llvm_target,
metadata: crate::spec::TargetMetadata {
description: Some("Armv7-A Apple WatchOS".into()),
tier: Some(3),
@@ -13,13 +13,13 @@ pub(crate) fn target() -> Target {
},
pointer_width: 32,
data_layout: "e-m:o-p:32:32-Fi8-i64:64-a:0:32-n32-S128".into(),
- arch: arch.target_arch(),
+ arch,
options: TargetOptions {
features: "+v7,+vfp4,+neon".into(),
max_atomic_width: Some(64),
dynamic_linking: false,
position_independent_executables: true,
- ..opts("watchos", arch, TargetAbi::Normal)
+ ..opts
},
}
}
diff --git a/compiler/rustc_target/src/spec/targets/armv7s_apple_ios.rs b/compiler/rustc_target/src/spec/targets/armv7s_apple_ios.rs
index 41eaa79..deee698 100644
--- a/compiler/rustc_target/src/spec/targets/armv7s_apple_ios.rs
+++ b/compiler/rustc_target/src/spec/targets/armv7s_apple_ios.rs
@@ -1,10 +1,10 @@
-use crate::spec::base::apple::{ios_llvm_target, opts, Arch, TargetAbi};
+use crate::spec::base::apple::{base, Arch, TargetAbi};
use crate::spec::{Target, TargetOptions};
pub(crate) fn target() -> Target {
- let arch = Arch::Armv7s;
+ let (opts, llvm_target, arch) = base("ios", Arch::Armv7s, TargetAbi::Normal);
Target {
- llvm_target: ios_llvm_target(arch).into(),
+ llvm_target,
metadata: crate::spec::TargetMetadata {
description: Some("Armv7-A Apple-A6 Apple iOS".into()),
tier: Some(3),
@@ -13,11 +13,11 @@ pub(crate) fn target() -> Target {
},
pointer_width: 32,
data_layout: "e-m:o-p:32:32-Fi8-f64:32:64-v64:32:64-v128:32:128-a:0:32-n32-S32".into(),
- arch: arch.target_arch(),
+ arch,
options: TargetOptions {
features: "+v7,+vfp4,+neon".into(),
max_atomic_width: Some(64),
- ..opts("ios", arch, TargetAbi::Normal)
+ ..opts
},
}
}
diff --git a/compiler/rustc_target/src/spec/targets/i386_apple_ios.rs b/compiler/rustc_target/src/spec/targets/i386_apple_ios.rs
index 263393f..dc14cb3 100644
--- a/compiler/rustc_target/src/spec/targets/i386_apple_ios.rs
+++ b/compiler/rustc_target/src/spec/targets/i386_apple_ios.rs
@@ -1,17 +1,12 @@
-use crate::spec::base::apple::{ios_sim_llvm_target, opts, Arch, TargetAbi};
+use crate::spec::base::apple::{base, Arch, TargetAbi};
use crate::spec::{Target, TargetOptions};
pub(crate) fn target() -> Target {
- let arch = Arch::I386;
// i386-apple-ios is a simulator target, even though it isn't declared
// that way in the target name like the other ones...
- let abi = TargetAbi::Simulator;
+ let (opts, llvm_target, arch) = base("ios", Arch::I386, TargetAbi::Simulator);
Target {
- // Clang automatically chooses a more specific target based on
- // IPHONEOS_DEPLOYMENT_TARGET.
- // This is required for the target to pick the right
- // MACH-O commands, so we do too.
- llvm_target: ios_sim_llvm_target(arch).into(),
+ llvm_target,
metadata: crate::spec::TargetMetadata {
description: Some("32-bit x86 iOS".into()),
tier: Some(3),
@@ -22,7 +17,7 @@ pub(crate) fn target() -> Target {
data_layout: "e-m:o-p:32:32-p270:32:32-p271:32:32-p272:64:64-\
i128:128-f64:32:64-f80:128-n8:16:32-S128"
.into(),
- arch: arch.target_arch(),
- options: TargetOptions { max_atomic_width: Some(64), ..opts("ios", arch, abi) },
+ arch,
+ options: TargetOptions { max_atomic_width: Some(64), ..opts },
}
}
diff --git a/compiler/rustc_target/src/spec/targets/i686_apple_darwin.rs b/compiler/rustc_target/src/spec/targets/i686_apple_darwin.rs
index f173e8b..67afe35 100644
--- a/compiler/rustc_target/src/spec/targets/i686_apple_darwin.rs
+++ b/compiler/rustc_target/src/spec/targets/i686_apple_darwin.rs
@@ -1,21 +1,12 @@
-use crate::spec::base::apple::{macos_llvm_target, opts, Arch, TargetAbi};
+use crate::spec::base::apple::{base, Arch, TargetAbi};
use crate::spec::{Cc, FramePointer, LinkerFlavor, Lld, Target, TargetOptions};
pub(crate) fn target() -> Target {
- // ld64 only understands i386 and not i686
- let arch = Arch::I386;
- let mut base = opts("macos", arch, TargetAbi::Normal);
- base.max_atomic_width = Some(64);
- base.add_pre_link_args(LinkerFlavor::Darwin(Cc::Yes, Lld::No), &["-m32"]);
- base.frame_pointer = FramePointer::Always;
+ let (mut opts, llvm_target, arch) = base("macos", Arch::I686, TargetAbi::Normal);
+ opts.add_pre_link_args(LinkerFlavor::Darwin(Cc::Yes, Lld::No), &["-m32"]);
Target {
- // Clang automatically chooses a more specific target based on
- // MACOSX_DEPLOYMENT_TARGET. To enable cross-language LTO to work
- // correctly, we do too.
- //
- // While ld64 doesn't understand i686, LLVM does.
- llvm_target: macos_llvm_target(Arch::I686).into(),
+ llvm_target,
metadata: crate::spec::TargetMetadata {
description: Some("32-bit macOS (10.12+, Sierra+)".into()),
tier: Some(3),
@@ -26,7 +17,12 @@ pub(crate) fn target() -> Target {
data_layout: "e-m:o-p:32:32-p270:32:32-p271:32:32-p272:64:64-\
i128:128-f64:32:64-f80:128-n8:16:32-S128"
.into(),
- arch: arch.target_arch(),
- options: TargetOptions { mcount: "\u{1}mcount".into(), ..base },
+ arch,
+ options: TargetOptions {
+ mcount: "\u{1}mcount".into(),
+ max_atomic_width: Some(64),
+ frame_pointer: FramePointer::Always,
+ ..opts
+ },
}
}
diff --git a/compiler/rustc_target/src/spec/targets/wasm32_wasip2.rs b/compiler/rustc_target/src/spec/targets/wasm32_wasip2.rs
index 40f026c..876aa70 100644
--- a/compiler/rustc_target/src/spec/targets/wasm32_wasip2.rs
+++ b/compiler/rustc_target/src/spec/targets/wasm32_wasip2.rs
@@ -1,6 +1,6 @@
//! The `wasm32-wasip2` target is the next evolution of the
//! wasm32-wasi target. While the wasi specification is still under
-//! active development, the {review 2 iteration is considered an "island
+//! active development, the preview 2 iteration is considered an "island
//! of stability" that should allow users to rely on it indefinitely.
//!
//! The `wasi` target is a proposal to define a standardized set of WebAssembly
diff --git a/compiler/rustc_target/src/spec/targets/x86_64_apple_darwin.rs b/compiler/rustc_target/src/spec/targets/x86_64_apple_darwin.rs
index 7bf1802..e7f14aa 100644
--- a/compiler/rustc_target/src/spec/targets/x86_64_apple_darwin.rs
+++ b/compiler/rustc_target/src/spec/targets/x86_64_apple_darwin.rs
@@ -1,20 +1,11 @@
-use crate::spec::base::apple::{macos_llvm_target, opts, Arch, TargetAbi};
+use crate::spec::base::apple::{base, Arch, TargetAbi};
use crate::spec::{Cc, FramePointer, LinkerFlavor, Lld, SanitizerSet, Target, TargetOptions};
pub(crate) fn target() -> Target {
- let arch = Arch::X86_64;
- let mut base = opts("macos", arch, TargetAbi::Normal);
- base.max_atomic_width = Some(128); // penryn+ supports cmpxchg16b
- base.frame_pointer = FramePointer::Always;
- base.add_pre_link_args(LinkerFlavor::Darwin(Cc::Yes, Lld::No), &["-m64"]);
- base.supported_sanitizers =
- SanitizerSet::ADDRESS | SanitizerSet::CFI | SanitizerSet::LEAK | SanitizerSet::THREAD;
-
+ let (mut opts, llvm_target, arch) = base("macos", Arch::X86_64, TargetAbi::Normal);
+ opts.add_pre_link_args(LinkerFlavor::Darwin(Cc::Yes, Lld::No), &["-m64"]);
Target {
- // Clang automatically chooses a more specific target based on
- // MACOSX_DEPLOYMENT_TARGET. To enable cross-language LTO to work
- // correctly, we do too.
- llvm_target: macos_llvm_target(arch).into(),
+ llvm_target,
metadata: crate::spec::TargetMetadata {
description: Some("64-bit macOS (10.12+, Sierra+)".into()),
tier: Some(1),
@@ -24,7 +15,16 @@ pub(crate) fn target() -> Target {
pointer_width: 64,
data_layout:
"e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128".into(),
- arch: arch.target_arch(),
- options: TargetOptions { mcount: "\u{1}mcount".into(), ..base },
+ arch,
+ options: TargetOptions {
+ mcount: "\u{1}mcount".into(),
+ max_atomic_width: Some(128), // penryn+ supports cmpxchg16b
+ frame_pointer: FramePointer::Always,
+ supported_sanitizers: SanitizerSet::ADDRESS
+ | SanitizerSet::CFI
+ | SanitizerSet::LEAK
+ | SanitizerSet::THREAD,
+ ..opts
+ },
}
}
diff --git a/compiler/rustc_target/src/spec/targets/x86_64_apple_ios.rs b/compiler/rustc_target/src/spec/targets/x86_64_apple_ios.rs
index 76a0bb1..847c4f0 100644
--- a/compiler/rustc_target/src/spec/targets/x86_64_apple_ios.rs
+++ b/compiler/rustc_target/src/spec/targets/x86_64_apple_ios.rs
@@ -1,15 +1,12 @@
-use crate::spec::base::apple::{ios_sim_llvm_target, opts, Arch, TargetAbi};
+use crate::spec::base::apple::{base, Arch, TargetAbi};
use crate::spec::{SanitizerSet, Target, TargetOptions};
pub(crate) fn target() -> Target {
- let arch = Arch::X86_64;
// x86_64-apple-ios is a simulator target, even though it isn't declared
// that way in the target name like the other ones...
- let mut base = opts("ios", arch, TargetAbi::Simulator);
- base.supported_sanitizers = SanitizerSet::ADDRESS | SanitizerSet::THREAD;
-
+ let (opts, llvm_target, arch) = base("ios", Arch::X86_64, TargetAbi::Simulator);
Target {
- llvm_target: ios_sim_llvm_target(arch).into(),
+ llvm_target,
metadata: crate::spec::TargetMetadata {
description: Some("64-bit x86 iOS".into()),
tier: Some(2),
@@ -19,7 +16,11 @@ pub(crate) fn target() -> Target {
pointer_width: 64,
data_layout:
"e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128".into(),
- arch: arch.target_arch(),
- options: TargetOptions { max_atomic_width: Some(128), ..base },
+ arch,
+ options: TargetOptions {
+ max_atomic_width: Some(128),
+ supported_sanitizers: SanitizerSet::ADDRESS | SanitizerSet::THREAD,
+ ..opts
+ },
}
}
diff --git a/compiler/rustc_target/src/spec/targets/x86_64_apple_ios_macabi.rs b/compiler/rustc_target/src/spec/targets/x86_64_apple_ios_macabi.rs
index f66efbb..042079f 100644
--- a/compiler/rustc_target/src/spec/targets/x86_64_apple_ios_macabi.rs
+++ b/compiler/rustc_target/src/spec/targets/x86_64_apple_ios_macabi.rs
@@ -1,13 +1,10 @@
-use crate::spec::base::apple::{mac_catalyst_llvm_target, opts, Arch, TargetAbi};
+use crate::spec::base::apple::{base, Arch, TargetAbi};
use crate::spec::{SanitizerSet, Target, TargetOptions};
pub(crate) fn target() -> Target {
- let arch = Arch::X86_64;
- let mut base = opts("ios", arch, TargetAbi::MacCatalyst);
- base.supported_sanitizers = SanitizerSet::ADDRESS | SanitizerSet::LEAK | SanitizerSet::THREAD;
-
+ let (opts, llvm_target, arch) = base("ios", Arch::X86_64, TargetAbi::MacCatalyst);
Target {
- llvm_target: mac_catalyst_llvm_target(arch).into(),
+ llvm_target,
metadata: crate::spec::TargetMetadata {
description: Some("Apple Catalyst on x86_64".into()),
tier: Some(2),
@@ -17,7 +14,11 @@ pub(crate) fn target() -> Target {
pointer_width: 64,
data_layout:
"e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128".into(),
- arch: arch.target_arch(),
- options: TargetOptions { max_atomic_width: Some(128), ..base },
+ arch,
+ options: TargetOptions {
+ max_atomic_width: Some(128),
+ supported_sanitizers: SanitizerSet::ADDRESS | SanitizerSet::LEAK | SanitizerSet::THREAD,
+ ..opts
+ },
}
}
diff --git a/compiler/rustc_target/src/spec/targets/x86_64_apple_tvos.rs b/compiler/rustc_target/src/spec/targets/x86_64_apple_tvos.rs
index f9d5f6e..9470860 100644
--- a/compiler/rustc_target/src/spec/targets/x86_64_apple_tvos.rs
+++ b/compiler/rustc_target/src/spec/targets/x86_64_apple_tvos.rs
@@ -1,13 +1,12 @@
-use crate::spec::base::apple::{opts, tvos_sim_llvm_target, Arch, TargetAbi};
+use crate::spec::base::apple::{base, Arch, TargetAbi};
use crate::spec::{Target, TargetOptions};
pub(crate) fn target() -> Target {
- let arch = Arch::X86_64;
// x86_64-apple-tvos is a simulator target, even though it isn't declared
// that way in the target name like the other ones...
- let abi = TargetAbi::Simulator;
+ let (opts, llvm_target, arch) = base("tvos", Arch::X86_64, TargetAbi::Simulator);
Target {
- llvm_target: tvos_sim_llvm_target(arch).into(),
+ llvm_target,
metadata: crate::spec::TargetMetadata {
description: Some("x86 64-bit tvOS".into()),
tier: Some(3),
@@ -17,7 +16,7 @@ pub(crate) fn target() -> Target {
pointer_width: 64,
data_layout:
"e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128".into(),
- arch: arch.target_arch(),
- options: TargetOptions { max_atomic_width: Some(128), ..opts("tvos", arch, abi) },
+ arch,
+ options: TargetOptions { max_atomic_width: Some(128), ..opts },
}
}
diff --git a/compiler/rustc_target/src/spec/targets/x86_64_apple_watchos_sim.rs b/compiler/rustc_target/src/spec/targets/x86_64_apple_watchos_sim.rs
index 1fced10..1dab959 100644
--- a/compiler/rustc_target/src/spec/targets/x86_64_apple_watchos_sim.rs
+++ b/compiler/rustc_target/src/spec/targets/x86_64_apple_watchos_sim.rs
@@ -1,10 +1,10 @@
-use crate::spec::base::apple::{opts, watchos_sim_llvm_target, Arch, TargetAbi};
+use crate::spec::base::apple::{base, Arch, TargetAbi};
use crate::spec::{Target, TargetOptions};
pub(crate) fn target() -> Target {
- let arch = Arch::X86_64;
+ let (opts, llvm_target, arch) = base("watchos", Arch::X86_64, TargetAbi::Simulator);
Target {
- llvm_target: watchos_sim_llvm_target(arch).into(),
+ llvm_target,
metadata: crate::spec::TargetMetadata {
description: Some("x86 64-bit Apple WatchOS simulator".into()),
tier: Some(3),
@@ -14,10 +14,7 @@ pub(crate) fn target() -> Target {
pointer_width: 64,
data_layout:
"e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128".into(),
- arch: arch.target_arch(),
- options: TargetOptions {
- max_atomic_width: Some(128),
- ..opts("watchos", arch, TargetAbi::Simulator)
- },
+ arch,
+ options: TargetOptions { max_atomic_width: Some(128), ..opts },
}
}
diff --git a/compiler/rustc_target/src/spec/targets/x86_64_unknown_hurd_gnu.rs b/compiler/rustc_target/src/spec/targets/x86_64_unknown_hurd_gnu.rs
new file mode 100644
index 0000000..6461ece
--- /dev/null
+++ b/compiler/rustc_target/src/spec/targets/x86_64_unknown_hurd_gnu.rs
@@ -0,0 +1,26 @@
+use crate::spec::{base, Cc, LinkerFlavor, Lld, StackProbeType, Target};
+
+pub(crate) fn target() -> Target {
+ let mut base = base::hurd_gnu::opts();
+ base.cpu = "x86-64".into();
+ base.plt_by_default = false;
+ base.max_atomic_width = Some(64);
+ base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-m64"]);
+ base.stack_probes = StackProbeType::Inline;
+ base.supports_xray = true;
+
+ Target {
+ llvm_target: "x86_64-unknown-hurd-gnu".into(),
+ metadata: crate::spec::TargetMetadata {
+ description: Some("64-bit GNU/Hurd".into()),
+ tier: Some(3),
+ host_tools: Some(true),
+ std: Some(true),
+ },
+ 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/spec/targets/x86_64h_apple_darwin.rs b/compiler/rustc_target/src/spec/targets/x86_64h_apple_darwin.rs
index 9b9ffe4..f44bc66 100644
--- a/compiler/rustc_target/src/spec/targets/x86_64h_apple_darwin.rs
+++ b/compiler/rustc_target/src/spec/targets/x86_64h_apple_darwin.rs
@@ -1,13 +1,12 @@
-use crate::spec::base::apple::{macos_llvm_target, opts, Arch, TargetAbi};
+use crate::spec::base::apple::{base, Arch, TargetAbi};
use crate::spec::{Cc, FramePointer, LinkerFlavor, Lld, SanitizerSet, Target, TargetOptions};
pub(crate) fn target() -> Target {
- let arch = Arch::X86_64h;
- let mut base = opts("macos", arch, TargetAbi::Normal);
- base.max_atomic_width = Some(128);
- base.frame_pointer = FramePointer::Always;
- base.add_pre_link_args(LinkerFlavor::Darwin(Cc::Yes, Lld::No), &["-m64"]);
- base.supported_sanitizers =
+ let (mut opts, llvm_target, arch) = base("macos", Arch::X86_64h, TargetAbi::Normal);
+ opts.max_atomic_width = Some(128);
+ opts.frame_pointer = FramePointer::Always;
+ opts.add_pre_link_args(LinkerFlavor::Darwin(Cc::Yes, Lld::No), &["-m64"]);
+ opts.supported_sanitizers =
SanitizerSet::ADDRESS | SanitizerSet::CFI | SanitizerSet::LEAK | SanitizerSet::THREAD;
// x86_64h is core2-avx without a few of the features which would otherwise
@@ -20,19 +19,16 @@ pub(crate) fn target() -> Target {
// It would be nice if this were not the case, but fixing it seems tricky
// (and given that the main use-case for this target is for use in universal
// binaries, probably not that important).
- base.features = "-rdrnd,-aes,-pclmul,-rtm,-fsgsbase".into();
+ opts.features = "-rdrnd,-aes,-pclmul,-rtm,-fsgsbase".into();
// Double-check that the `cpu` is what we expect (if it's not the list above
// may need updating).
assert_eq!(
- base.cpu, "core-avx2",
+ opts.cpu, "core-avx2",
"you need to adjust the feature list in x86_64h-apple-darwin if you change this",
);
Target {
- // Clang automatically chooses a more specific target based on
- // MACOSX_DEPLOYMENT_TARGET. To enable cross-language LTO to work
- // correctly, we do too.
- llvm_target: macos_llvm_target(arch).into(),
+ llvm_target,
metadata: crate::spec::TargetMetadata {
description: Some("macOS with late-gen Intel (at least Haswell)".into()),
tier: Some(3),
@@ -42,7 +38,7 @@ pub(crate) fn target() -> Target {
pointer_width: 64,
data_layout:
"e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128".into(),
- arch: arch.target_arch(),
- options: TargetOptions { mcount: "\u{1}mcount".into(), ..base },
+ arch,
+ options: TargetOptions { mcount: "\u{1}mcount".into(), ..opts },
}
}
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 bff2a18..65d2151 100644
--- a/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs
+++ b/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs
@@ -348,8 +348,7 @@ fn note_error_origin(
}
}
if let Some(ty::error::ExpectedFound { found, .. }) = exp_found
- && ty.is_box()
- && ty.boxed_ty() == found
+ && ty.boxed_ty() == Some(found)
&& let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span)
{
err.span_suggestion(
diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs
index a93b633..cf9891f 100644
--- a/compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs
+++ b/compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs
@@ -1296,6 +1296,9 @@ fn visit_expr(&mut self, expr: &'tcx Expr<'tcx>) {
&& let Some(def_id) = self.typeck_results.type_dependent_def_id(expr.hir_id)
&& self.tecx.tcx.trait_of_item(def_id).is_some()
&& !has_impl_trait(def_id)
+ // FIXME(fn_delegation): In delegation item argument spans are equal to last path
+ // segment. This leads to ICE's when emitting `multipart_suggestion`.
+ && tcx.hir().opt_delegation_sig_id(expr.hir_id.owner.def_id).is_none()
{
let successor =
method_args.get(0).map_or_else(|| (")", span.hi()), |arg| (", ", arg.span.lo()));
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 db71331..7bfc647 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
@@ -4,7 +4,7 @@
use rustc_hir::def::DefKind;
use rustc_middle::traits::{ObligationCause, ObligationCauseCode};
use rustc_middle::ty::error::{ExpectedFound, TypeError};
-use rustc_middle::ty::fast_reject::{DeepRejectCtxt, TreatParams};
+use rustc_middle::ty::fast_reject::DeepRejectCtxt;
use rustc_middle::ty::print::{FmtPrinter, Printer};
use rustc_middle::ty::{self, suggest_constraining_type_param, Ty};
use rustc_span::def_id::DefId;
@@ -317,7 +317,7 @@ fn foo(&self, x: T) -> T { x }
{
let mut has_matching_impl = false;
tcx.for_each_relevant_impl(def_id, values.found, |did| {
- if DeepRejectCtxt::new(tcx, TreatParams::ForLookup)
+ if DeepRejectCtxt::relate_rigid_infer(tcx)
.types_may_unify(values.found, tcx.type_of(did).skip_binder())
{
has_matching_impl = true;
@@ -338,7 +338,7 @@ fn foo(&self, x: T) -> T { x }
{
let mut has_matching_impl = false;
tcx.for_each_relevant_impl(def_id, values.expected, |did| {
- if DeepRejectCtxt::new(tcx, TreatParams::ForLookup)
+ if DeepRejectCtxt::relate_rigid_infer(tcx)
.types_may_unify(values.expected, tcx.type_of(did).skip_binder())
{
has_matching_impl = true;
@@ -358,7 +358,7 @@ fn foo(&self, x: T) -> T { x }
{
let mut has_matching_impl = false;
tcx.for_each_relevant_impl(def_id, values.found, |did| {
- if DeepRejectCtxt::new(tcx, TreatParams::ForLookup)
+ if DeepRejectCtxt::relate_rigid_infer(tcx)
.types_may_unify(values.found, tcx.type_of(did).skip_binder())
{
has_matching_impl = true;
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 e4a4ec1..38d06f5 100644
--- a/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs
+++ b/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs
@@ -625,11 +625,19 @@ pub(super) fn report_placeholder_failure(
if let ObligationCauseCode::WhereClause(_, span)
| ObligationCauseCode::WhereClauseInExpr(_, span, ..) =
&trace.cause.code().peel_derives()
- && !span.is_dummy()
{
let span = *span;
- self.report_concrete_failure(generic_param_scope, placeholder_origin, sub, sup)
- .with_span_note(span, "the lifetime requirement is introduced here")
+ let mut err = self.report_concrete_failure(
+ generic_param_scope,
+ placeholder_origin,
+ sub,
+ sup,
+ );
+ if !span.is_dummy() {
+ err =
+ err.with_span_note(span, "the lifetime requirement is introduced here");
+ }
+ err
} else {
unreachable!(
"control flow ensures we have a `BindingObligation` or `WhereClauseInExpr` here..."
@@ -844,18 +852,7 @@ struct LifetimeReplaceVisitor<'tcx, 'a> {
impl<'hir, 'tcx> hir::intravisit::Visitor<'hir> for LifetimeReplaceVisitor<'tcx, '_> {
fn visit_lifetime(&mut self, lt: &'hir hir::Lifetime) {
if lt.res == self.needle {
- let (pos, span) = lt.suggestion_position();
- let new_lt = &self.new_lt;
- let sugg = match pos {
- hir::LifetimeSuggestionPosition::Normal => format!("{new_lt}"),
- hir::LifetimeSuggestionPosition::Ampersand => format!("{new_lt} "),
- hir::LifetimeSuggestionPosition::ElidedPath => format!("<{new_lt}>"),
- hir::LifetimeSuggestionPosition::ElidedPathArgument => {
- format!("{new_lt}, ")
- }
- hir::LifetimeSuggestionPosition::ObjectDefault => format!("+ {new_lt}"),
- };
- self.add_lt_suggs.push((span, sugg));
+ self.add_lt_suggs.push(lt.suggestion(self.new_lt));
}
}
@@ -1018,7 +1015,7 @@ fn report_inference_failure(&self, var_origin: RegionVariableOrigin) -> Diag<'_>
let var_description = match var_origin {
infer::MiscVariable(_) => String::new(),
infer::PatternRegion(_) => " for pattern".to_string(),
- infer::AddrOfRegion(_) => " for borrow expression".to_string(),
+ infer::BorrowRegion(_) => " for borrow expression".to_string(),
infer::Autoref(_) => " for autoref".to_string(),
infer::Coercion(_) => " for automatic coercion".to_string(),
infer::BoundRegion(_, br, infer::FnCall) => {
diff --git a/compiler/rustc_trait_selection/src/traits/coherence.rs b/compiler/rustc_trait_selection/src/traits/coherence.rs
index 8b55f84..bafe1ff 100644
--- a/compiler/rustc_trait_selection/src/traits/coherence.rs
+++ b/compiler/rustc_trait_selection/src/traits/coherence.rs
@@ -15,7 +15,7 @@
use rustc_middle::traits::query::NoSolution;
use rustc_middle::traits::solve::{CandidateSource, Certainty, Goal};
use rustc_middle::traits::specialization_graph::OverlapMode;
-use rustc_middle::ty::fast_reject::{DeepRejectCtxt, TreatParams};
+use rustc_middle::ty::fast_reject::DeepRejectCtxt;
use rustc_middle::ty::visit::{TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor};
use rustc_middle::ty::{self, Ty, TyCtxt};
pub use rustc_next_trait_solver::coherence::*;
@@ -96,7 +96,7 @@ pub fn overlapping_impls(
// Before doing expensive operations like entering an inference context, do
// a quick check via fast_reject to tell if the impl headers could possibly
// unify.
- let drcx = DeepRejectCtxt::new(tcx, TreatParams::AsCandidateKey);
+ let drcx = DeepRejectCtxt::relate_infer_infer(tcx);
let impl1_ref = tcx.impl_trait_ref(impl1_def_id);
let impl2_ref = tcx.impl_trait_ref(impl2_def_id);
let may_overlap = match (impl1_ref, impl2_ref) {
diff --git a/compiler/rustc_trait_selection/src/traits/engine.rs b/compiler/rustc_trait_selection/src/traits/engine.rs
index de1d4ef..c8811bc 100644
--- a/compiler/rustc_trait_selection/src/traits/engine.rs
+++ b/compiler/rustc_trait_selection/src/traits/engine.rs
@@ -35,10 +35,8 @@ fn new(infcx: &InferCtxt<'tcx>) -> Box<Self> {
if infcx.next_trait_solver() {
Box::new(NextFulfillmentCtxt::new(infcx))
} else {
- let new_solver_globally =
- infcx.tcx.sess.opts.unstable_opts.next_solver.map_or(false, |c| c.globally);
assert!(
- !new_solver_globally,
+ !infcx.tcx.next_trait_solver_globally(),
"using old solver even though new solver is enabled globally"
);
Box::new(FulfillmentContext::new(infcx))
diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs
index 4702fd8..630acc9 100644
--- a/compiler/rustc_trait_selection/src/traits/project.rs
+++ b/compiler/rustc_trait_selection/src/traits/project.rs
@@ -13,6 +13,7 @@
use rustc_middle::traits::select::OverflowError;
pub use rustc_middle::traits::Reveal;
use rustc_middle::traits::{BuiltinImplSource, ImplSource, ImplSourceUserDefinedData};
+use rustc_middle::ty::fast_reject::DeepRejectCtxt;
use rustc_middle::ty::fold::TypeFoldable;
use rustc_middle::ty::visit::{MaxUniverse, TypeVisitable, TypeVisitableExt};
use rustc_middle::ty::{self, Term, Ty, TyCtxt, Upcast};
@@ -886,6 +887,7 @@ fn assemble_candidates_from_predicates<'cx, 'tcx>(
potentially_unnormalized_candidates: bool,
) {
let infcx = selcx.infcx;
+ let drcx = DeepRejectCtxt::relate_rigid_rigid(selcx.tcx());
for predicate in env_predicates {
let bound_predicate = predicate.kind();
if let ty::ClauseKind::Projection(data) = predicate.kind().skip_binder() {
@@ -894,6 +896,12 @@ fn assemble_candidates_from_predicates<'cx, 'tcx>(
continue;
}
+ if !drcx
+ .args_may_unify(obligation.predicate.args, data.skip_binder().projection_term.args)
+ {
+ continue;
+ }
+
let is_match = infcx.probe(|_| {
selcx.match_projection_projections(
obligation,
diff --git a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs
index 96faa52..77efc2f 100644
--- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs
@@ -13,7 +13,7 @@
use rustc_data_structures::fx::{FxHashSet, FxIndexSet};
use rustc_hir as hir;
use rustc_infer::traits::{Obligation, ObligationCause, PolyTraitObligation, SelectionError};
-use rustc_middle::ty::fast_reject::{DeepRejectCtxt, TreatParams};
+use rustc_middle::ty::fast_reject::DeepRejectCtxt;
use rustc_middle::ty::{self, ToPolyTraitRef, Ty, TypeVisitableExt};
use rustc_middle::{bug, span_bug};
use tracing::{debug, instrument, trace};
@@ -248,11 +248,17 @@ fn assemble_candidates_from_caller_bounds<'o>(
.filter(|p| p.def_id() == stack.obligation.predicate.def_id())
.filter(|p| p.polarity() == stack.obligation.predicate.polarity());
+ let drcx = DeepRejectCtxt::relate_rigid_rigid(self.tcx());
+ let obligation_args = stack.obligation.predicate.skip_binder().trait_ref.args;
// Keep only those bounds which may apply, and propagate overflow if it occurs.
for bound in bounds {
+ let bound_trait_ref = bound.map_bound(|t| t.trait_ref);
+ if !drcx.args_may_unify(obligation_args, bound_trait_ref.skip_binder().args) {
+ continue;
+ }
// FIXME(oli-obk): it is suspicious that we are dropping the constness and
// polarity here.
- let wc = self.where_clause_may_apply(stack, bound.map_bound(|t| t.trait_ref))?;
+ let wc = self.where_clause_may_apply(stack, bound_trait_ref)?;
if wc.may_apply() {
candidates.vec.push(ParamCandidate(bound));
}
@@ -581,7 +587,7 @@ fn assemble_candidates_from_impls(
return;
}
- let drcx = DeepRejectCtxt::new(self.tcx(), TreatParams::ForLookup);
+ let drcx = DeepRejectCtxt::relate_rigid_infer(self.tcx());
let obligation_args = obligation.predicate.skip_binder().trait_ref.args;
self.tcx().for_each_relevant_impl(
obligation.predicate.def_id(),
diff --git a/compiler/rustc_trait_selection/src/traits/specialize/specialization_graph.rs b/compiler/rustc_trait_selection/src/traits/specialize/specialization_graph.rs
index 0fdaf40..13620f4 100644
--- a/compiler/rustc_trait_selection/src/traits/specialize/specialization_graph.rs
+++ b/compiler/rustc_trait_selection/src/traits/specialize/specialization_graph.rs
@@ -41,7 +41,7 @@ impl<'tcx> Children {
fn insert_blindly(&mut self, tcx: TyCtxt<'tcx>, impl_def_id: DefId) {
let trait_ref = tcx.impl_trait_ref(impl_def_id).unwrap().skip_binder();
if let Some(st) =
- fast_reject::simplify_type(tcx, trait_ref.self_ty(), TreatParams::AsCandidateKey)
+ fast_reject::simplify_type(tcx, trait_ref.self_ty(), TreatParams::InstantiateWithInfer)
{
debug!("insert_blindly: impl_def_id={:?} st={:?}", impl_def_id, st);
self.non_blanket_impls.entry(st).or_default().push(impl_def_id)
@@ -58,7 +58,7 @@ fn remove_existing(&mut self, tcx: TyCtxt<'tcx>, impl_def_id: DefId) {
let trait_ref = tcx.impl_trait_ref(impl_def_id).unwrap().skip_binder();
let vec: &mut Vec<DefId>;
if let Some(st) =
- fast_reject::simplify_type(tcx, trait_ref.self_ty(), TreatParams::AsCandidateKey)
+ fast_reject::simplify_type(tcx, trait_ref.self_ty(), TreatParams::InstantiateWithInfer)
{
debug!("remove_existing: impl_def_id={:?} st={:?}", impl_def_id, st);
vec = self.non_blanket_impls.get_mut(&st).unwrap();
@@ -279,7 +279,7 @@ fn insert(
let mut parent = trait_def_id;
let mut last_lint = None;
let simplified =
- fast_reject::simplify_type(tcx, trait_ref.self_ty(), TreatParams::AsCandidateKey);
+ fast_reject::simplify_type(tcx, trait_ref.self_ty(), TreatParams::InstantiateWithInfer);
// Descend the specialization tree, where `parent` is the current parent node.
loop {
diff --git a/compiler/rustc_transmute/src/layout/nfa.rs b/compiler/rustc_transmute/src/layout/nfa.rs
index 5db5a8f..3b49c59 100644
--- a/compiler/rustc_transmute/src/layout/nfa.rs
+++ b/compiler/rustc_transmute/src/layout/nfa.rs
@@ -87,8 +87,6 @@ pub(crate) fn from_ref(r: R) -> Self {
pub(crate) fn from_tree(tree: Tree<!, R>) -> Result<Self, Uninhabited> {
Ok(match tree {
Tree::Byte(b) => Self::from_byte(b),
- #[cfg(bootstrap)]
- Tree::Def(..) => unreachable!(),
Tree::Ref(r) => Self::from_ref(r),
Tree::Alt(alts) => {
let mut alts = alts.into_iter().map(Self::from_tree);
diff --git a/compiler/rustc_ty_utils/src/layout.rs b/compiler/rustc_ty_utils/src/layout.rs
index 234e1a6..c23a7fe 100644
--- a/compiler/rustc_ty_utils/src/layout.rs
+++ b/compiler/rustc_ty_utils/src/layout.rs
@@ -1001,7 +1001,13 @@ fn coroutine_layout<'tcx>(
},
fields: outer_fields,
abi,
- largest_niche: prefix.largest_niche,
+ // Suppress niches inside coroutines. If the niche is inside a field that is aliased (due to
+ // self-referentiality), getting the discriminant can cause aliasing violations.
+ // `UnsafeCell` blocks niches for the same reason, but we don't yet have `UnsafePinned` that
+ // would do the same for us here.
+ // See <https://github.com/rust-lang/rust/issues/63818>, <https://github.com/rust-lang/miri/issues/3780>.
+ // FIXME: Remove when <https://github.com/rust-lang/rust/issues/125735> is implemented and aliased coroutine fields are wrapped in `UnsafePinned`.
+ largest_niche: None,
size,
align,
max_repr_align: None,
diff --git a/compiler/rustc_type_ir/src/elaborate.rs b/compiler/rustc_type_ir/src/elaborate.rs
index 433c444..f30419c 100644
--- a/compiler/rustc_type_ir/src/elaborate.rs
+++ b/compiler/rustc_type_ir/src/elaborate.rs
@@ -237,7 +237,7 @@ pub fn supertrait_def_ids<I: Interner>(
cx: I,
trait_def_id: I::DefId,
) -> impl Iterator<Item = I::DefId> {
- let mut set: HashSet<I::DefId> = HashSet::default();
+ let mut set = HashSet::default();
let mut stack = vec![trait_def_id];
set.insert(trait_def_id);
diff --git a/compiler/rustc_type_ir/src/fast_reject.rs b/compiler/rustc_type_ir/src/fast_reject.rs
index fab4a09..2c8e47b 100644
--- a/compiler/rustc_type_ir/src/fast_reject.rs
+++ b/compiler/rustc_type_ir/src/fast_reject.rs
@@ -74,13 +74,13 @@ fn to_stable_hash_key(&self, hcx: &HCX) -> Fingerprint {
pub enum TreatParams {
/// Treat parameters as infer vars. This is the correct mode for caching
/// an impl's type for lookup.
- AsCandidateKey,
+ InstantiateWithInfer,
/// Treat parameters as placeholders in the given environment. This is the
/// correct mode for *lookup*, as during candidate selection.
///
/// This also treats projections with inference variables as infer vars
/// since they could be further normalized.
- ForLookup,
+ AsRigid,
}
/// Tries to simplify a type by only returning the outermost injective¹ layer, if one exists.
@@ -140,18 +140,16 @@ pub fn simplify_type<I: Interner>(
}
ty::Placeholder(..) => Some(SimplifiedType::Placeholder),
ty::Param(_) => match treat_params {
- TreatParams::ForLookup => Some(SimplifiedType::Placeholder),
- TreatParams::AsCandidateKey => None,
+ TreatParams::AsRigid => Some(SimplifiedType::Placeholder),
+ TreatParams::InstantiateWithInfer => None,
},
ty::Alias(..) => match treat_params {
// When treating `ty::Param` as a placeholder, projections also
// don't unify with anything else as long as they are fully normalized.
// FIXME(-Znext-solver): Can remove this `if` and always simplify to `Placeholder`
// when the new solver is enabled by default.
- TreatParams::ForLookup if !ty.has_non_region_infer() => {
- Some(SimplifiedType::Placeholder)
- }
- TreatParams::ForLookup | TreatParams::AsCandidateKey => None,
+ TreatParams::AsRigid if !ty.has_non_region_infer() => Some(SimplifiedType::Placeholder),
+ TreatParams::AsRigid | TreatParams::InstantiateWithInfer => None,
},
ty::Foreign(def_id) => Some(SimplifiedType::Foreign(def_id)),
ty::Error(_) => Some(SimplifiedType::Error),
@@ -173,29 +171,49 @@ pub fn def(self) -> Option<DefId> {
}
}
-/// Given generic arguments from an obligation and an impl,
-/// could these two be unified after replacing parameters in the
-/// the impl with inference variables.
+/// Given generic arguments, could they be unified after
+/// replacing parameters with inference variables or placeholders.
+/// This behavior is toggled using the const generics.
///
-/// For obligations, parameters won't be replaced by inference
-/// variables and only unify with themselves. We treat them
-/// the same way we treat placeholders.
+/// We use this to quickly reject impl/wc candidates without needing
+/// to instantiate generic arguments/having to enter a probe.
///
/// We also use this function during coherence. For coherence the
/// impls only have to overlap for some value, so we treat parameters
-/// on both sides like inference variables. This behavior is toggled
-/// using the `treat_obligation_params` field.
+/// on both sides like inference variables.
#[derive(Debug, Clone, Copy)]
-pub struct DeepRejectCtxt<I: Interner> {
- treat_obligation_params: TreatParams,
+pub struct DeepRejectCtxt<
+ I: Interner,
+ const INSTANTIATE_LHS_WITH_INFER: bool,
+ const INSTANTIATE_RHS_WITH_INFER: bool,
+> {
_interner: PhantomData<I>,
}
-impl<I: Interner> DeepRejectCtxt<I> {
- pub fn new(_interner: I, treat_obligation_params: TreatParams) -> Self {
- DeepRejectCtxt { treat_obligation_params, _interner: PhantomData }
+impl<I: Interner> DeepRejectCtxt<I, false, false> {
+ /// Treat parameters in both the lhs and the rhs as rigid.
+ pub fn relate_rigid_rigid(_interner: I) -> DeepRejectCtxt<I, false, false> {
+ DeepRejectCtxt { _interner: PhantomData }
}
+}
+impl<I: Interner> DeepRejectCtxt<I, true, true> {
+ /// Treat parameters in both the lhs and the rhs as infer vars.
+ pub fn relate_infer_infer(_interner: I) -> DeepRejectCtxt<I, true, true> {
+ DeepRejectCtxt { _interner: PhantomData }
+ }
+}
+
+impl<I: Interner> DeepRejectCtxt<I, false, true> {
+ /// Treat parameters in the lhs as rigid, and in rhs as infer vars.
+ pub fn relate_rigid_infer(_interner: I) -> DeepRejectCtxt<I, false, true> {
+ DeepRejectCtxt { _interner: PhantomData }
+ }
+}
+
+impl<I: Interner, const INSTANTIATE_LHS_WITH_INFER: bool, const INSTANTIATE_RHS_WITH_INFER: bool>
+ DeepRejectCtxt<I, INSTANTIATE_LHS_WITH_INFER, INSTANTIATE_RHS_WITH_INFER>
+{
pub fn args_may_unify(
self,
obligation_args: I::GenericArgs,
@@ -216,11 +234,18 @@ pub fn args_may_unify(
})
}
- pub fn types_may_unify(self, obligation_ty: I::Ty, impl_ty: I::Ty) -> bool {
- match impl_ty.kind() {
- // Start by checking whether the type in the impl may unify with
+ pub fn types_may_unify(self, lhs: I::Ty, rhs: I::Ty) -> bool {
+ match rhs.kind() {
+ // Start by checking whether the `rhs` type may unify with
// pretty much everything. Just return `true` in that case.
- ty::Param(_) | ty::Error(_) | ty::Alias(..) => return true,
+ ty::Param(_) => {
+ if INSTANTIATE_RHS_WITH_INFER {
+ return true;
+ }
+ }
+ ty::Error(_) | ty::Alias(..) | ty::Bound(..) => return true,
+ ty::Infer(var) => return self.var_and_ty_may_unify(var, lhs),
+
// These types only unify with inference variables or their own
// variant.
ty::Bool
@@ -238,108 +263,48 @@ pub fn types_may_unify(self, obligation_ty: I::Ty, impl_ty: I::Ty) -> bool {
| ty::Ref(..)
| ty::Never
| ty::Tuple(..)
+ | ty::FnDef(..)
| ty::FnPtr(..)
- | ty::Foreign(..) => debug_assert!(impl_ty.is_known_rigid()),
- ty::FnDef(..)
| ty::Closure(..)
| ty::CoroutineClosure(..)
| ty::Coroutine(..)
| ty::CoroutineWitness(..)
- | ty::Placeholder(..)
- | ty::Bound(..)
- | ty::Infer(_) => panic!("unexpected impl_ty: {impl_ty:?}"),
- }
+ | ty::Foreign(_)
+ | ty::Placeholder(_) => {}
+ };
- let k = impl_ty.kind();
- match obligation_ty.kind() {
- // Purely rigid types, use structural equivalence.
- ty::Bool
- | ty::Char
- | ty::Int(_)
- | ty::Uint(_)
- | ty::Float(_)
- | ty::Str
- | ty::Never
- | ty::Foreign(_) => obligation_ty == impl_ty,
- ty::Ref(_, obl_ty, obl_mutbl) => match k {
- ty::Ref(_, impl_ty, impl_mutbl) => {
- obl_mutbl == impl_mutbl && self.types_may_unify(obl_ty, impl_ty)
+ // For purely rigid types, use structural equivalence.
+ match lhs.kind() {
+ ty::Ref(_, lhs_ty, lhs_mutbl) => match rhs.kind() {
+ ty::Ref(_, rhs_ty, rhs_mutbl) => {
+ lhs_mutbl == rhs_mutbl && self.types_may_unify(lhs_ty, rhs_ty)
}
_ => false,
},
- ty::Adt(obl_def, obl_args) => match k {
- ty::Adt(impl_def, impl_args) => {
- obl_def == impl_def && self.args_may_unify(obl_args, impl_args)
+
+ ty::Adt(lhs_def, lhs_args) => match rhs.kind() {
+ ty::Adt(rhs_def, rhs_args) => {
+ lhs_def == rhs_def && self.args_may_unify(lhs_args, rhs_args)
}
_ => false,
},
- ty::Pat(obl_ty, _) => {
- // FIXME(pattern_types): take pattern into account
- matches!(k, ty::Pat(impl_ty, _) if self.types_may_unify(obl_ty, impl_ty))
+
+ // Depending on the value of const generics, we either treat generic parameters
+ // like placeholders or like inference variables.
+ ty::Param(lhs) => {
+ INSTANTIATE_LHS_WITH_INFER
+ || match rhs.kind() {
+ ty::Param(rhs) => lhs == rhs,
+ _ => false,
+ }
}
- ty::Slice(obl_ty) => {
- matches!(k, ty::Slice(impl_ty) if self.types_may_unify(obl_ty, impl_ty))
+
+ // Placeholder types don't unify with anything on their own.
+ ty::Placeholder(lhs) => {
+ matches!(rhs.kind(), ty::Placeholder(rhs) if lhs == rhs)
}
- ty::Array(obl_ty, obl_len) => match k {
- ty::Array(impl_ty, impl_len) => {
- self.types_may_unify(obl_ty, impl_ty)
- && self.consts_may_unify(obl_len, impl_len)
- }
- _ => false,
- },
- ty::Tuple(obl) => match k {
- ty::Tuple(imp) => {
- obl.len() == imp.len()
- && iter::zip(obl.iter(), imp.iter())
- .all(|(obl, imp)| self.types_may_unify(obl, imp))
- }
- _ => false,
- },
- ty::RawPtr(obl_ty, obl_mutbl) => match k {
- ty::RawPtr(imp_ty, imp_mutbl) => {
- obl_mutbl == imp_mutbl && self.types_may_unify(obl_ty, imp_ty)
- }
- _ => false,
- },
- ty::Dynamic(obl_preds, ..) => {
- // Ideally we would walk the existential predicates here or at least
- // compare their length. But considering that the relevant `Relate` impl
- // actually sorts and deduplicates these, that doesn't work.
- matches!(k, ty::Dynamic(impl_preds, ..) if
- obl_preds.principal_def_id() == impl_preds.principal_def_id()
- )
- }
- ty::FnPtr(obl_sig_tys, obl_hdr) => match k {
- ty::FnPtr(impl_sig_tys, impl_hdr) => {
- let obl_sig_tys = obl_sig_tys.skip_binder().inputs_and_output;
- let impl_sig_tys = impl_sig_tys.skip_binder().inputs_and_output;
- obl_hdr == impl_hdr
- && obl_sig_tys.len() == impl_sig_tys.len()
- && iter::zip(obl_sig_tys.iter(), impl_sig_tys.iter())
- .all(|(obl, imp)| self.types_may_unify(obl, imp))
- }
- _ => false,
- },
-
- // Impls cannot contain these types as these cannot be named directly.
- ty::FnDef(..) | ty::Closure(..) | ty::CoroutineClosure(..) | ty::Coroutine(..) => false,
-
- // Placeholder types don't unify with anything on their own
- ty::Placeholder(..) | ty::Bound(..) => false,
-
- // Depending on the value of `treat_obligation_params`, we either
- // treat generic parameters like placeholders or like inference variables.
- ty::Param(_) => match self.treat_obligation_params {
- TreatParams::ForLookup => false,
- TreatParams::AsCandidateKey => true,
- },
-
- ty::Infer(ty::IntVar(_)) => impl_ty.is_integral(),
-
- ty::Infer(ty::FloatVar(_)) => impl_ty.is_floating_point(),
-
- ty::Infer(_) => true,
+ ty::Infer(var) => self.var_and_ty_may_unify(var, rhs),
// As we're walking the whole type, it may encounter projections
// inside of binders and what not, so we're just going to assume that
@@ -348,49 +313,167 @@ pub fn types_may_unify(self, obligation_ty: I::Ty, impl_ty: I::Ty) -> bool {
// Looking forward to lazy normalization this is the safer strategy anyways.
ty::Alias(..) => true,
- ty::Error(_) => true,
+ ty::Int(_)
+ | ty::Uint(_)
+ | ty::Float(_)
+ | ty::Str
+ | ty::Bool
+ | ty::Char
+ | ty::Never
+ | ty::Foreign(_) => lhs == rhs,
- ty::CoroutineWitness(..) => {
- panic!("unexpected obligation type: {:?}", obligation_ty)
+ ty::Tuple(lhs) => match rhs.kind() {
+ ty::Tuple(rhs) => {
+ lhs.len() == rhs.len()
+ && iter::zip(lhs.iter(), rhs.iter())
+ .all(|(lhs, rhs)| self.types_may_unify(lhs, rhs))
+ }
+ _ => false,
+ },
+
+ ty::Array(lhs_ty, lhs_len) => match rhs.kind() {
+ ty::Array(rhs_ty, rhs_len) => {
+ self.types_may_unify(lhs_ty, rhs_ty) && self.consts_may_unify(lhs_len, rhs_len)
+ }
+ _ => false,
+ },
+
+ ty::RawPtr(lhs_ty, lhs_mutbl) => match rhs.kind() {
+ ty::RawPtr(rhs_ty, rhs_mutbl) => {
+ lhs_mutbl == rhs_mutbl && self.types_may_unify(lhs_ty, rhs_ty)
+ }
+ _ => false,
+ },
+
+ ty::Slice(lhs_ty) => {
+ matches!(rhs.kind(), ty::Slice(rhs_ty) if self.types_may_unify(lhs_ty, rhs_ty))
}
+
+ ty::Dynamic(lhs_preds, ..) => {
+ // Ideally we would walk the existential predicates here or at least
+ // compare their length. But considering that the relevant `Relate` impl
+ // actually sorts and deduplicates these, that doesn't work.
+ matches!(rhs.kind(), ty::Dynamic(rhs_preds, ..) if
+ lhs_preds.principal_def_id() == rhs_preds.principal_def_id()
+ )
+ }
+
+ ty::FnPtr(lhs_sig_tys, lhs_hdr) => match rhs.kind() {
+ ty::FnPtr(rhs_sig_tys, rhs_hdr) => {
+ let lhs_sig_tys = lhs_sig_tys.skip_binder().inputs_and_output;
+ let rhs_sig_tys = rhs_sig_tys.skip_binder().inputs_and_output;
+
+ lhs_hdr == rhs_hdr
+ && lhs_sig_tys.len() == rhs_sig_tys.len()
+ && iter::zip(lhs_sig_tys.iter(), rhs_sig_tys.iter())
+ .all(|(lhs, rhs)| self.types_may_unify(lhs, rhs))
+ }
+ _ => false,
+ },
+
+ ty::Bound(..) => true,
+
+ ty::FnDef(lhs_def_id, lhs_args) => match rhs.kind() {
+ ty::FnDef(rhs_def_id, rhs_args) => {
+ lhs_def_id == rhs_def_id && self.args_may_unify(lhs_args, rhs_args)
+ }
+ _ => false,
+ },
+
+ ty::Closure(lhs_def_id, lhs_args) => match rhs.kind() {
+ ty::Closure(rhs_def_id, rhs_args) => {
+ lhs_def_id == rhs_def_id && self.args_may_unify(lhs_args, rhs_args)
+ }
+ _ => false,
+ },
+
+ ty::CoroutineClosure(lhs_def_id, lhs_args) => match rhs.kind() {
+ ty::CoroutineClosure(rhs_def_id, rhs_args) => {
+ lhs_def_id == rhs_def_id && self.args_may_unify(lhs_args, rhs_args)
+ }
+ _ => false,
+ },
+
+ ty::Coroutine(lhs_def_id, lhs_args) => match rhs.kind() {
+ ty::Coroutine(rhs_def_id, rhs_args) => {
+ lhs_def_id == rhs_def_id && self.args_may_unify(lhs_args, rhs_args)
+ }
+ _ => false,
+ },
+
+ ty::CoroutineWitness(lhs_def_id, lhs_args) => match rhs.kind() {
+ ty::CoroutineWitness(rhs_def_id, rhs_args) => {
+ lhs_def_id == rhs_def_id && self.args_may_unify(lhs_args, rhs_args)
+ }
+ _ => false,
+ },
+
+ ty::Pat(lhs_ty, _) => {
+ // FIXME(pattern_types): take pattern into account
+ matches!(rhs.kind(), ty::Pat(rhs_ty, _) if self.types_may_unify(lhs_ty, rhs_ty))
+ }
+
+ ty::Error(..) => true,
}
}
- pub fn consts_may_unify(self, obligation_ct: I::Const, impl_ct: I::Const) -> bool {
- let impl_val = match impl_ct.kind() {
+ pub fn consts_may_unify(self, lhs: I::Const, rhs: I::Const) -> bool {
+ match rhs.kind() {
+ ty::ConstKind::Param(_) => {
+ if INSTANTIATE_RHS_WITH_INFER {
+ return true;
+ }
+ }
+
ty::ConstKind::Expr(_)
- | ty::ConstKind::Param(_)
| ty::ConstKind::Unevaluated(_)
- | ty::ConstKind::Error(_) => {
+ | ty::ConstKind::Error(_)
+ | ty::ConstKind::Infer(_)
+ | ty::ConstKind::Bound(..) => {
return true;
}
- ty::ConstKind::Value(_, impl_val) => impl_val,
- ty::ConstKind::Infer(_) | ty::ConstKind::Bound(..) | ty::ConstKind::Placeholder(_) => {
- panic!("unexpected impl arg: {:?}", impl_ct)
- }
+
+ ty::ConstKind::Value(..) | ty::ConstKind::Placeholder(_) => {}
};
- match obligation_ct.kind() {
- ty::ConstKind::Param(_) => match self.treat_obligation_params {
- TreatParams::ForLookup => false,
- TreatParams::AsCandidateKey => true,
+ match lhs.kind() {
+ ty::ConstKind::Value(_, lhs_val) => match rhs.kind() {
+ ty::ConstKind::Value(_, rhs_val) => lhs_val == rhs_val,
+ _ => false,
},
+ ty::ConstKind::Param(lhs) => {
+ INSTANTIATE_LHS_WITH_INFER
+ || match rhs.kind() {
+ ty::ConstKind::Param(rhs) => lhs == rhs,
+ _ => false,
+ }
+ }
+
// Placeholder consts don't unify with anything on their own
- ty::ConstKind::Placeholder(_) => false,
+ ty::ConstKind::Placeholder(lhs) => {
+ matches!(rhs.kind(), ty::ConstKind::Placeholder(rhs) if lhs == rhs)
+ }
// As we don't necessarily eagerly evaluate constants,
// they might unify with any value.
ty::ConstKind::Expr(_) | ty::ConstKind::Unevaluated(_) | ty::ConstKind::Error(_) => {
true
}
- ty::ConstKind::Value(_, obl_val) => obl_val == impl_val,
- ty::ConstKind::Infer(_) => true,
+ ty::ConstKind::Infer(_) | ty::ConstKind::Bound(..) => true,
+ }
+ }
- ty::ConstKind::Bound(..) => {
- panic!("unexpected obl const: {:?}", obligation_ct)
- }
+ fn var_and_ty_may_unify(self, var: ty::InferTy, ty: I::Ty) -> bool {
+ if !ty.is_known_rigid() {
+ return true;
+ }
+
+ match var {
+ ty::IntVar(_) => ty.is_integral(),
+ ty::FloatVar(_) => ty.is_floating_point(),
+ _ => true,
}
}
}
diff --git a/compiler/rustc_type_ir/src/fold.rs b/compiler/rustc_type_ir/src/fold.rs
index f49aa34..64ce6fd 100644
--- a/compiler/rustc_type_ir/src/fold.rs
+++ b/compiler/rustc_type_ir/src/fold.rs
@@ -91,8 +91,6 @@ pub trait TypeFoldable<I: Interner>: TypeVisitable<I> {
fn fold_with<F: TypeFolder<I>>(self, folder: &mut F) -> Self {
match self.try_fold_with(folder) {
Ok(t) => t,
- #[cfg(bootstrap)]
- Err(e) => match e {},
}
}
}
@@ -116,8 +114,6 @@ fn try_super_fold_with<F: FallibleTypeFolder<I>>(
fn super_fold_with<F: TypeFolder<I>>(self, folder: &mut F) -> Self {
match self.try_super_fold_with(folder) {
Ok(t) => t,
- #[cfg(bootstrap)]
- Err(e) => match e {},
}
}
}
diff --git a/compiler/rustc_type_ir/src/interner.rs b/compiler/rustc_type_ir/src/interner.rs
index f2492ed..8dec213 100644
--- a/compiler/rustc_type_ir/src/interner.rs
+++ b/compiler/rustc_type_ir/src/interner.rs
@@ -137,6 +137,8 @@ fn with_global_cache<R>(
f: impl FnOnce(&mut search_graph::GlobalCache<Self>) -> R,
) -> R;
+ fn evaluation_is_concurrent(&self) -> bool;
+
fn expand_abstract_consts<T: TypeFoldable<Self>>(self, t: T) -> T;
type GenericsOf: GenericsOf<Self>;
@@ -404,4 +406,7 @@ fn with_global_cache<R>(
) -> R {
I::with_global_cache(self, mode, f)
}
+ fn evaluation_is_concurrent(&self) -> bool {
+ self.evaluation_is_concurrent()
+ }
}
diff --git a/compiler/rustc_type_ir/src/search_graph/global_cache.rs b/compiler/rustc_type_ir/src/search_graph/global_cache.rs
index 47f7cef..0ce927b 100644
--- a/compiler/rustc_type_ir/src/search_graph/global_cache.rs
+++ b/compiler/rustc_type_ir/src/search_graph/global_cache.rs
@@ -44,22 +44,28 @@ pub(super) fn insert(
cx: X,
input: X::Input,
- result: X::Result,
+ origin_result: X::Result,
dep_node: X::DepNodeIndex,
additional_depth: usize,
encountered_overflow: bool,
nested_goals: NestedGoals<X>,
) {
- let result = cx.mk_tracked(result, dep_node);
+ let result = cx.mk_tracked(origin_result, dep_node);
let entry = self.map.entry(input).or_default();
if encountered_overflow {
let with_overflow = WithOverflow { nested_goals, result };
let prev = entry.with_overflow.insert(additional_depth, with_overflow);
- assert!(prev.is_none());
+ if let Some(prev) = &prev {
+ assert!(cx.evaluation_is_concurrent());
+ assert_eq!(cx.get_tracked(&prev.result), origin_result);
+ }
} else {
let prev = entry.success.replace(Success { additional_depth, nested_goals, result });
- assert!(prev.is_none());
+ if let Some(prev) = &prev {
+ assert!(cx.evaluation_is_concurrent());
+ assert_eq!(cx.get_tracked(&prev.result), origin_result);
+ }
}
}
diff --git a/compiler/rustc_type_ir/src/search_graph/mod.rs b/compiler/rustc_type_ir/src/search_graph/mod.rs
index 418139c..ac4d079 100644
--- a/compiler/rustc_type_ir/src/search_graph/mod.rs
+++ b/compiler/rustc_type_ir/src/search_graph/mod.rs
@@ -53,6 +53,8 @@ fn with_global_cache<R>(
mode: SolverMode,
f: impl FnOnce(&mut GlobalCache<Self>) -> R,
) -> R;
+
+ fn evaluation_is_concurrent(&self) -> bool;
}
pub trait Delegate {
diff --git a/config.example.toml b/config.example.toml
index 13f7693..2b5e9ae 100644
--- a/config.example.toml
+++ b/config.example.toml
@@ -42,6 +42,9 @@
# Unless you're developing for a target where Rust CI doesn't build a compiler
# toolchain or changing LLVM locally, you probably want to leave this enabled.
#
+# Set this to `true` to download if CI llvm available otherwise it builds
+# from `src/llvm-project`.
+#
# Set this to `"if-unchanged"` to download only if the llvm-project has not
# been modified. You can also use this if you are unsure whether you're on a
# tier 1 target. All tier 1 targets are currently supported.
@@ -78,6 +81,9 @@
# Indicates whether the LLVM plugin is enabled or not
#plugins = false
+# Wheter to build Enzyme as AutoDiff backend.
+#enzyme = false
+
# Indicates whether ccache is used when building LLVM. Set to `true` to use the first `ccache` in
# PATH, or set an absolute path to use a specific version.
#ccache = false
@@ -233,7 +239,7 @@
# Instead of downloading the src/stage0 version of cargo-clippy specified,
# use this cargo-clippy binary instead as the stage0 snapshot cargo-clippy.
#
-# Note that this option should be used with the same toolchain as the `rustc` option above.
+# Note that this option should be used with the same toolchain as the `rustc` option above.
# Otherwise, clippy is likely to fail due to a toolchain conflict.
#cargo-clippy = "/path/to/cargo-clippy"
@@ -638,7 +644,7 @@
#stack-protector = "none"
# Prints each test name as it is executed, to help debug issues in the test harness itself.
-#verbose-tests = false
+#verbose-tests = if is_verbose { true } else { false }
# Flag indicating whether tests are compiled with optimizations (the -O flag).
#optimize-tests = true
diff --git a/library/alloc/src/boxed.rs b/library/alloc/src/boxed.rs
index a924fea..6dc7547 100644
--- a/library/alloc/src/boxed.rs
+++ b/library/alloc/src/boxed.rs
@@ -272,7 +272,7 @@ pub fn new(x: T) -> Self {
/// assert_eq!(*five, 5)
/// ```
#[cfg(not(no_global_oom_handling))]
- #[stable(feature = "new_uninit", since = "CURRENT_RUSTC_VERSION")]
+ #[stable(feature = "new_uninit", since = "1.82.0")]
#[must_use]
#[inline]
pub fn new_uninit() -> Box<mem::MaybeUninit<T>> {
@@ -663,7 +663,7 @@ impl<T> Box<[T]> {
/// assert_eq!(*values, [1, 2, 3])
/// ```
#[cfg(not(no_global_oom_handling))]
- #[stable(feature = "new_uninit", since = "CURRENT_RUSTC_VERSION")]
+ #[stable(feature = "new_uninit", since = "1.82.0")]
#[must_use]
pub fn new_uninit_slice(len: usize) -> Box<[mem::MaybeUninit<T>]> {
unsafe { RawVec::with_capacity(len).into_box(len) }
@@ -930,7 +930,7 @@ impl<T, A: Allocator> Box<mem::MaybeUninit<T>, A> {
///
/// assert_eq!(*five, 5)
/// ```
- #[stable(feature = "new_uninit", since = "CURRENT_RUSTC_VERSION")]
+ #[stable(feature = "new_uninit", since = "1.82.0")]
#[inline]
pub unsafe fn assume_init(self) -> Box<T, A> {
let (raw, alloc) = Box::into_raw_with_allocator(self);
@@ -1003,7 +1003,7 @@ impl<T, A: Allocator> Box<[mem::MaybeUninit<T>], A> {
///
/// assert_eq!(*values, [1, 2, 3])
/// ```
- #[stable(feature = "new_uninit", since = "CURRENT_RUSTC_VERSION")]
+ #[stable(feature = "new_uninit", since = "1.82.0")]
#[inline]
pub unsafe fn assume_init(self) -> Box<[T], A> {
let (raw, alloc) = Box::into_raw_with_allocator(self);
diff --git a/library/alloc/src/collections/binary_heap/mod.rs b/library/alloc/src/collections/binary_heap/mod.rs
index 8870137..fe9f101 100644
--- a/library/alloc/src/collections/binary_heap/mod.rs
+++ b/library/alloc/src/collections/binary_heap/mod.rs
@@ -1433,7 +1433,7 @@ pub struct Iter<'a, T: 'a> {
iter: slice::Iter<'a, T>,
}
-#[stable(feature = "default_iters_sequel", since = "CURRENT_RUSTC_VERSION")]
+#[stable(feature = "default_iters_sequel", since = "1.82.0")]
impl<T> Default for Iter<'_, T> {
/// Creates an empty `binary_heap::Iter`.
///
diff --git a/library/alloc/src/collections/btree/map.rs b/library/alloc/src/collections/btree/map.rs
index c790857..60e08b4 100644
--- a/library/alloc/src/collections/btree/map.rs
+++ b/library/alloc/src/collections/btree/map.rs
@@ -2016,7 +2016,7 @@ fn default() -> Self {
}
}
-#[stable(feature = "default_iters_sequel", since = "CURRENT_RUSTC_VERSION")]
+#[stable(feature = "default_iters_sequel", since = "1.82.0")]
impl<K, V> Default for RangeMut<'_, K, V> {
/// Creates an empty `btree_map::RangeMut`.
///
@@ -2064,7 +2064,7 @@ fn len(&self) -> usize {
#[stable(feature = "fused", since = "1.26.0")]
impl<K, V> FusedIterator for ValuesMut<'_, K, V> {}
-#[stable(feature = "default_iters_sequel", since = "CURRENT_RUSTC_VERSION")]
+#[stable(feature = "default_iters_sequel", since = "1.82.0")]
impl<K, V> Default for ValuesMut<'_, K, V> {
/// Creates an empty `btree_map::ValuesMut`.
///
diff --git a/library/alloc/src/collections/vec_deque/into_iter.rs b/library/alloc/src/collections/vec_deque/into_iter.rs
index 7be3de1..2b09a5e 100644
--- a/library/alloc/src/collections/vec_deque/into_iter.rs
+++ b/library/alloc/src/collections/vec_deque/into_iter.rs
@@ -121,8 +121,6 @@ fn fold<B, F>(mut self, init: B, mut f: F) -> B
{
match self.try_fold(init, |b, item| Ok::<B, !>(f(b, item))) {
Ok(b) => b,
- #[cfg(bootstrap)]
- Err(e) => match e {},
}
}
@@ -243,8 +241,6 @@ fn rfold<B, F>(mut self, init: B, mut f: F) -> B
{
match self.try_rfold(init, |b, item| Ok::<B, !>(f(b, item))) {
Ok(b) => b,
- #[cfg(bootstrap)]
- Err(e) => match e {},
}
}
}
diff --git a/library/alloc/src/collections/vec_deque/iter.rs b/library/alloc/src/collections/vec_deque/iter.rs
index 67b5b91..6922ea9 100644
--- a/library/alloc/src/collections/vec_deque/iter.rs
+++ b/library/alloc/src/collections/vec_deque/iter.rs
@@ -28,7 +28,7 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
}
}
-#[stable(feature = "default_iters_sequel", since = "CURRENT_RUSTC_VERSION")]
+#[stable(feature = "default_iters_sequel", since = "1.82.0")]
impl<T> Default for Iter<'_, T> {
/// Creates an empty `vec_deque::Iter`.
///
@@ -73,7 +73,7 @@ fn next(&mut self) -> Option<&'a T> {
fn advance_by(&mut self, n: usize) -> Result<(), NonZero<usize>> {
let remaining = self.i1.advance_by(n);
match remaining {
- Ok(()) => return Ok(()),
+ Ok(()) => Ok(()),
Err(n) => {
mem::swap(&mut self.i1, &mut self.i2);
self.i1.advance_by(n.get())
@@ -144,7 +144,7 @@ fn next_back(&mut self) -> Option<&'a T> {
fn advance_back_by(&mut self, n: usize) -> Result<(), NonZero<usize>> {
match self.i2.advance_back_by(n) {
- Ok(()) => return Ok(()),
+ Ok(()) => Ok(()),
Err(n) => {
mem::swap(&mut self.i1, &mut self.i2);
self.i2.advance_back_by(n.get())
diff --git a/library/alloc/src/collections/vec_deque/iter_mut.rs b/library/alloc/src/collections/vec_deque/iter_mut.rs
index 2726e3e..84b7410 100644
--- a/library/alloc/src/collections/vec_deque/iter_mut.rs
+++ b/library/alloc/src/collections/vec_deque/iter_mut.rs
@@ -28,7 +28,7 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
}
}
-#[stable(feature = "default_iters_sequel", since = "CURRENT_RUSTC_VERSION")]
+#[stable(feature = "default_iters_sequel", since = "1.82.0")]
impl<T> Default for IterMut<'_, T> {
/// Creates an empty `vec_deque::IterMut`.
///
@@ -64,7 +64,7 @@ fn next(&mut self) -> Option<&'a mut T> {
fn advance_by(&mut self, n: usize) -> Result<(), NonZero<usize>> {
match self.i1.advance_by(n) {
- Ok(()) => return Ok(()),
+ Ok(()) => Ok(()),
Err(remaining) => {
mem::swap(&mut self.i1, &mut self.i2);
self.i1.advance_by(remaining.get())
@@ -135,7 +135,7 @@ fn next_back(&mut self) -> Option<&'a mut T> {
fn advance_back_by(&mut self, n: usize) -> Result<(), NonZero<usize>> {
match self.i2.advance_back_by(n) {
- Ok(()) => return Ok(()),
+ Ok(()) => Ok(()),
Err(remaining) => {
mem::swap(&mut self.i1, &mut self.i2);
self.i2.advance_back_by(remaining.get())
diff --git a/library/alloc/src/rc.rs b/library/alloc/src/rc.rs
index 1b31a78..88c7a12 100644
--- a/library/alloc/src/rc.rs
+++ b/library/alloc/src/rc.rs
@@ -517,7 +517,7 @@ pub fn new_cyclic<F>(data_fn: F) -> Rc<T>
/// assert_eq!(*five, 5)
/// ```
#[cfg(not(no_global_oom_handling))]
- #[stable(feature = "new_uninit", since = "CURRENT_RUSTC_VERSION")]
+ #[stable(feature = "new_uninit", since = "1.82.0")]
#[must_use]
pub fn new_uninit() -> Rc<mem::MaybeUninit<T>> {
unsafe {
@@ -980,7 +980,7 @@ impl<T> Rc<[T]> {
/// assert_eq!(*values, [1, 2, 3])
/// ```
#[cfg(not(no_global_oom_handling))]
- #[stable(feature = "new_uninit", since = "CURRENT_RUSTC_VERSION")]
+ #[stable(feature = "new_uninit", since = "1.82.0")]
#[must_use]
pub fn new_uninit_slice(len: usize) -> Rc<[mem::MaybeUninit<T>]> {
unsafe { Rc::from_ptr(Rc::allocate_for_slice(len)) }
@@ -1127,7 +1127,7 @@ impl<T, A: Allocator> Rc<mem::MaybeUninit<T>, A> {
///
/// assert_eq!(*five, 5)
/// ```
- #[stable(feature = "new_uninit", since = "CURRENT_RUSTC_VERSION")]
+ #[stable(feature = "new_uninit", since = "1.82.0")]
#[inline]
pub unsafe fn assume_init(self) -> Rc<T, A> {
let (ptr, alloc) = Rc::into_inner_with_allocator(self);
@@ -1167,7 +1167,7 @@ impl<T, A: Allocator> Rc<[mem::MaybeUninit<T>], A> {
///
/// assert_eq!(*values, [1, 2, 3])
/// ```
- #[stable(feature = "new_uninit", since = "CURRENT_RUSTC_VERSION")]
+ #[stable(feature = "new_uninit", since = "1.82.0")]
#[inline]
pub unsafe fn assume_init(self) -> Rc<[T], A> {
let (ptr, alloc) = Rc::into_inner_with_allocator(self);
diff --git a/library/alloc/src/sync.rs b/library/alloc/src/sync.rs
index 024a794..43684f3 100644
--- a/library/alloc/src/sync.rs
+++ b/library/alloc/src/sync.rs
@@ -520,7 +520,7 @@ pub fn new_cyclic<F>(data_fn: F) -> Arc<T>
/// ```
#[cfg(not(no_global_oom_handling))]
#[inline]
- #[stable(feature = "new_uninit", since = "CURRENT_RUSTC_VERSION")]
+ #[stable(feature = "new_uninit", since = "1.82.0")]
#[must_use]
pub fn new_uninit() -> Arc<mem::MaybeUninit<T>> {
unsafe {
@@ -1115,7 +1115,7 @@ impl<T> Arc<[T]> {
/// ```
#[cfg(not(no_global_oom_handling))]
#[inline]
- #[stable(feature = "new_uninit", since = "CURRENT_RUSTC_VERSION")]
+ #[stable(feature = "new_uninit", since = "1.82.0")]
#[must_use]
pub fn new_uninit_slice(len: usize) -> Arc<[mem::MaybeUninit<T>]> {
unsafe { Arc::from_ptr(Arc::allocate_for_slice(len)) }
@@ -1262,7 +1262,7 @@ impl<T, A: Allocator> Arc<mem::MaybeUninit<T>, A> {
///
/// assert_eq!(*five, 5)
/// ```
- #[stable(feature = "new_uninit", since = "CURRENT_RUSTC_VERSION")]
+ #[stable(feature = "new_uninit", since = "1.82.0")]
#[must_use = "`self` will be dropped if the result is not used"]
#[inline]
pub unsafe fn assume_init(self) -> Arc<T, A> {
@@ -1303,7 +1303,7 @@ impl<T, A: Allocator> Arc<[mem::MaybeUninit<T>], A> {
///
/// assert_eq!(*values, [1, 2, 3])
/// ```
- #[stable(feature = "new_uninit", since = "CURRENT_RUSTC_VERSION")]
+ #[stable(feature = "new_uninit", since = "1.82.0")]
#[must_use = "`self` will be dropped if the result is not used"]
#[inline]
pub unsafe fn assume_init(self) -> Arc<[T], A> {
diff --git a/library/alloc/src/vec/in_place_collect.rs b/library/alloc/src/vec/in_place_collect.rs
index d119e6c..ec0ab8e 100644
--- a/library/alloc/src/vec/in_place_collect.rs
+++ b/library/alloc/src/vec/in_place_collect.rs
@@ -208,7 +208,7 @@ const fn needs_realloc<SRC, DEST>(src_cap: usize, dst_cap: usize) -> bool {
// type layouts don't guarantee a fit, so do a runtime check to see if
// the allocations happen to match
- return src_cap > 0 && src_cap * mem::size_of::<SRC>() != dst_cap * mem::size_of::<DEST>();
+ src_cap > 0 && src_cap * mem::size_of::<SRC>() != dst_cap * mem::size_of::<DEST>()
}
/// This provides a shorthand for the source type since local type aliases aren't a thing.
diff --git a/library/alloc/src/vec/into_iter.rs b/library/alloc/src/vec/into_iter.rs
index fad8aba..92c5e36 100644
--- a/library/alloc/src/vec/into_iter.rs
+++ b/library/alloc/src/vec/into_iter.rs
@@ -288,11 +288,11 @@ fn count(self) -> usize {
// Safety: `len` is larger than the array size. Copy a fixed amount here to fully initialize
// the array.
- return unsafe {
+ unsafe {
ptr::copy_nonoverlapping(self.ptr.as_ptr(), raw_ary.as_mut_ptr() as *mut T, N);
self.ptr = self.ptr.add(N);
Ok(raw_ary.transpose().assume_init())
- };
+ }
}
fn fold<B, F>(mut self, mut accum: B, mut f: F) -> B
diff --git a/library/core/src/arch.rs b/library/core/src/arch.rs
index d681bd1..be734d1 100644
--- a/library/core/src/arch.rs
+++ b/library/core/src/arch.rs
@@ -4,15 +4,6 @@
#[stable(feature = "simd_arch", since = "1.27.0")]
pub use crate::core_arch::arch::*;
-#[cfg(bootstrap)]
-#[allow(dead_code)]
-#[unstable(feature = "sha512_sm_x86", issue = "126624")]
-fn dummy() {
- // AArch64 also has a target feature named `sm4`, so we need `#![feature(sha512_sm_x86)]` in lib.rs
- // But as the bootstrap compiler doesn't know about this feature yet, we need to convert it to a
- // library feature until bootstrap gets bumped
-}
-
/// Inline assembly.
///
/// Refer to [Rust By Example] for a usage guide and the [reference] for
@@ -26,6 +17,20 @@ fn dummy() {
/* compiler built-in */
}
+/// Inline assembly used in combination with `#[naked]` functions.
+///
+/// Refer to [Rust By Example] for a usage guide and the [reference] for
+/// detailed information about the syntax and available options.
+///
+/// [Rust By Example]: https://doc.rust-lang.org/nightly/rust-by-example/unsafe/asm.html
+/// [reference]: https://doc.rust-lang.org/nightly/reference/inline-assembly.html
+#[unstable(feature = "naked_functions", issue = "90957")]
+#[rustc_builtin_macro]
+#[cfg(not(bootstrap))]
+pub macro naked_asm("assembly template", $(operands,)* $(options($(option),*))?) {
+ /* compiler built-in */
+}
+
/// Module-level inline assembly.
///
/// Refer to [Rust By Example] for a usage guide and the [reference] for
diff --git a/library/core/src/cell.rs b/library/core/src/cell.rs
index 5dd9721..a3a471a 100644
--- a/library/core/src/cell.rs
+++ b/library/core/src/cell.rs
@@ -306,7 +306,7 @@
/// See the [module-level documentation](self) for more.
#[stable(feature = "rust1", since = "1.0.0")]
#[repr(transparent)]
-#[cfg_attr(not(bootstrap), rustc_pub_transparent)]
+#[rustc_pub_transparent]
pub struct Cell<T: ?Sized> {
value: UnsafeCell<T>,
}
@@ -2056,7 +2056,7 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
#[lang = "unsafe_cell"]
#[stable(feature = "rust1", since = "1.0.0")]
#[repr(transparent)]
-#[cfg_attr(not(bootstrap), rustc_pub_transparent)]
+#[rustc_pub_transparent]
pub struct UnsafeCell<T: ?Sized> {
value: T,
}
@@ -2299,7 +2299,7 @@ pub(crate) const fn primitive_into_inner(self) -> *mut T {
/// See [`UnsafeCell`] for details.
#[unstable(feature = "sync_unsafe_cell", issue = "95439")]
#[repr(transparent)]
-#[cfg_attr(not(bootstrap), rustc_pub_transparent)]
+#[rustc_pub_transparent]
pub struct SyncUnsafeCell<T: ?Sized> {
value: UnsafeCell<T>,
}
diff --git a/library/core/src/char/methods.rs b/library/core/src/char/methods.rs
index 41a1966..113a2d6 100644
--- a/library/core/src/char/methods.rs
+++ b/library/core/src/char/methods.rs
@@ -15,7 +15,6 @@ impl char {
/// for you:
///
/// ```
- /// #![feature(char_min)]
/// let dist = u32::from(char::MAX) - u32::from(char::MIN);
/// let size = (char::MIN..=char::MAX).count() as u32;
/// assert!(size < dist);
@@ -29,7 +28,6 @@ impl char {
/// # Examples
///
/// ```
- /// #![feature(char_min)]
/// # fn something_which_returns_char() -> char { 'a' }
/// let c: char = something_which_returns_char();
/// assert!(char::MIN <= c);
@@ -37,7 +35,7 @@ impl char {
/// let value_at_min = u32::from(char::MIN);
/// assert_eq!(char::from_u32(value_at_min), Some('\0'));
/// ```
- #[unstable(feature = "char_min", issue = "114298")]
+ #[stable(feature = "char_min", since = "CURRENT_RUSTC_VERSION")]
pub const MIN: char = '\0';
/// The highest valid code point a `char` can have, `'\u{10FFFF}'`.
@@ -48,7 +46,6 @@ impl char {
/// for you:
///
/// ```
- /// #![feature(char_min)]
/// let dist = u32::from(char::MAX) - u32::from(char::MIN);
/// let size = (char::MIN..=char::MAX).count() as u32;
/// assert!(size < dist);
diff --git a/library/core/src/clone.rs b/library/core/src/clone.rs
index 2150463..c5f8bd7 100644
--- a/library/core/src/clone.rs
+++ b/library/core/src/clone.rs
@@ -161,7 +161,7 @@ pub trait Clone: Sized {
#[must_use = "cloning is often expensive and is not expected to have side effects"]
// Clone::clone is special because the compiler generates MIR to implement it for some types.
// See InstanceKind::CloneShim.
- #[cfg_attr(not(bootstrap), lang = "clone_fn")]
+ #[lang = "clone_fn"]
fn clone(&self) -> Self;
/// Performs copy-assignment from `source`.
diff --git a/library/core/src/default.rs b/library/core/src/default.rs
index 5cacedc..4c30290 100644
--- a/library/core/src/default.rs
+++ b/library/core/src/default.rs
@@ -103,7 +103,7 @@
/// ```
#[cfg_attr(not(test), rustc_diagnostic_item = "Default")]
#[stable(feature = "rust1", since = "1.0.0")]
-#[cfg_attr(not(bootstrap), rustc_trivial_field_reads)]
+#[rustc_trivial_field_reads]
pub trait Default: Sized {
/// Returns the "default value" for a type.
///
diff --git a/library/core/src/future/ready.rs b/library/core/src/future/ready.rs
index 6f6da8c..b562ad4 100644
--- a/library/core/src/future/ready.rs
+++ b/library/core/src/future/ready.rs
@@ -39,7 +39,7 @@ impl<T> Ready<T> {
/// let a = future::ready(1);
/// assert_eq!(a.into_inner(), 1);
/// ```
- #[stable(feature = "ready_into_inner", since = "CURRENT_RUSTC_VERSION")]
+ #[stable(feature = "ready_into_inner", since = "1.82.0")]
#[must_use]
#[inline]
pub fn into_inner(self) -> T {
diff --git a/library/core/src/intrinsics.rs b/library/core/src/intrinsics.rs
index 8cb9accd..7870a62 100644
--- a/library/core/src/intrinsics.rs
+++ b/library/core/src/intrinsics.rs
@@ -1020,7 +1020,6 @@ pub const fn unlikely(b: bool) -> bool {
/// any safety invariants.
///
/// This intrinsic does not have a stable counterpart.
-#[cfg(not(bootstrap))]
#[unstable(feature = "core_intrinsics", issue = "none")]
#[rustc_intrinsic]
#[rustc_nounwind]
@@ -1030,12 +1029,6 @@ pub fn select_unpredictable<T>(b: bool, true_val: T, false_val: T) -> T {
if b { true_val } else { false_val }
}
-#[cfg(bootstrap)]
-#[inline]
-pub fn select_unpredictable<T>(b: bool, true_val: T, false_val: T) -> T {
- if b { true_val } else { false_val }
-}
-
extern "rust-intrinsic" {
/// Executes a breakpoint trap, for inspection by a debugger.
///
diff --git a/library/core/src/iter/adapters/take.rs b/library/core/src/iter/adapters/take.rs
index 4c8f9fe..b96335f 100644
--- a/library/core/src/iter/adapters/take.rs
+++ b/library/core/src/iter/adapters/take.rs
@@ -318,7 +318,7 @@ fn spec_for_each<F: FnMut(Self::Item)>(mut self, mut f: F) {
}
}
-#[stable(feature = "exact_size_take_repeat", since = "CURRENT_RUSTC_VERSION")]
+#[stable(feature = "exact_size_take_repeat", since = "1.82.0")]
impl<T: Clone> DoubleEndedIterator for Take<crate::iter::Repeat<T>> {
#[inline]
fn next_back(&mut self) -> Option<Self::Item> {
@@ -361,14 +361,14 @@ fn advance_back_by(&mut self, n: usize) -> Result<(), NonZero<usize>> {
// because we have no way to return value of nth invocation of repeater followed
// by n-1st without remembering all results.
-#[stable(feature = "exact_size_take_repeat", since = "CURRENT_RUSTC_VERSION")]
+#[stable(feature = "exact_size_take_repeat", since = "1.82.0")]
impl<T: Clone> ExactSizeIterator for Take<crate::iter::Repeat<T>> {
fn len(&self) -> usize {
self.n
}
}
-#[stable(feature = "exact_size_take_repeat", since = "CURRENT_RUSTC_VERSION")]
+#[stable(feature = "exact_size_take_repeat", since = "1.82.0")]
impl<F: FnMut() -> A, A> ExactSizeIterator for Take<crate::iter::RepeatWith<F>> {
fn len(&self) -> usize {
self.n
diff --git a/library/core/src/iter/mod.rs b/library/core/src/iter/mod.rs
index 5dad9e1..387963d 100644
--- a/library/core/src/iter/mod.rs
+++ b/library/core/src/iter/mod.rs
@@ -436,7 +436,7 @@ fn $fold<AAA, FFF>(mut self, init: AAA, fold: FFF) -> AAA
pub use self::sources::{once_with, OnceWith};
#[stable(feature = "rust1", since = "1.0.0")]
pub use self::sources::{repeat, Repeat};
-#[stable(feature = "iter_repeat_n", since = "CURRENT_RUSTC_VERSION")]
+#[stable(feature = "iter_repeat_n", since = "1.82.0")]
pub use self::sources::{repeat_n, RepeatN};
#[stable(feature = "iterator_repeat_with", since = "1.28.0")]
pub use self::sources::{repeat_with, RepeatWith};
diff --git a/library/core/src/iter/sources.rs b/library/core/src/iter/sources.rs
index 55901e1..2c726fb 100644
--- a/library/core/src/iter/sources.rs
+++ b/library/core/src/iter/sources.rs
@@ -24,7 +24,7 @@
pub use self::once_with::{once_with, OnceWith};
#[stable(feature = "rust1", since = "1.0.0")]
pub use self::repeat::{repeat, Repeat};
-#[stable(feature = "iter_repeat_n", since = "CURRENT_RUSTC_VERSION")]
+#[stable(feature = "iter_repeat_n", since = "1.82.0")]
pub use self::repeat_n::{repeat_n, RepeatN};
#[stable(feature = "iterator_repeat_with", since = "1.28.0")]
pub use self::repeat_with::{repeat_with, RepeatWith};
diff --git a/library/core/src/iter/sources/repeat_n.rs b/library/core/src/iter/sources/repeat_n.rs
index 2e247a3..9c06219 100644
--- a/library/core/src/iter/sources/repeat_n.rs
+++ b/library/core/src/iter/sources/repeat_n.rs
@@ -56,7 +56,7 @@
/// assert_eq!(None, it.next());
/// ```
#[inline]
-#[stable(feature = "iter_repeat_n", since = "CURRENT_RUSTC_VERSION")]
+#[stable(feature = "iter_repeat_n", since = "1.82.0")]
pub fn repeat_n<T: Clone>(element: T, count: usize) -> RepeatN<T> {
let mut element = ManuallyDrop::new(element);
@@ -75,7 +75,7 @@ pub fn repeat_n<T: Clone>(element: T, count: usize) -> RepeatN<T> {
/// This `struct` is created by the [`repeat_n()`] function.
/// See its documentation for more.
#[derive(Clone, Debug)]
-#[stable(feature = "iter_repeat_n", since = "CURRENT_RUSTC_VERSION")]
+#[stable(feature = "iter_repeat_n", since = "1.82.0")]
pub struct RepeatN<A> {
count: usize,
// Invariant: has been dropped iff count == 0.
@@ -99,14 +99,14 @@ fn take_element(&mut self) -> Option<A> {
}
}
-#[stable(feature = "iter_repeat_n", since = "CURRENT_RUSTC_VERSION")]
+#[stable(feature = "iter_repeat_n", since = "1.82.0")]
impl<A> Drop for RepeatN<A> {
fn drop(&mut self) {
self.take_element();
}
}
-#[stable(feature = "iter_repeat_n", since = "CURRENT_RUSTC_VERSION")]
+#[stable(feature = "iter_repeat_n", since = "1.82.0")]
impl<A: Clone> Iterator for RepeatN<A> {
type Item = A;
@@ -154,14 +154,14 @@ fn count(self) -> usize {
}
}
-#[stable(feature = "iter_repeat_n", since = "CURRENT_RUSTC_VERSION")]
+#[stable(feature = "iter_repeat_n", since = "1.82.0")]
impl<A: Clone> ExactSizeIterator for RepeatN<A> {
fn len(&self) -> usize {
self.count
}
}
-#[stable(feature = "iter_repeat_n", since = "CURRENT_RUSTC_VERSION")]
+#[stable(feature = "iter_repeat_n", since = "1.82.0")]
impl<A: Clone> DoubleEndedIterator for RepeatN<A> {
#[inline]
fn next_back(&mut self) -> Option<A> {
@@ -179,12 +179,12 @@ fn nth_back(&mut self, n: usize) -> Option<A> {
}
}
-#[stable(feature = "iter_repeat_n", since = "CURRENT_RUSTC_VERSION")]
+#[stable(feature = "iter_repeat_n", since = "1.82.0")]
impl<A: Clone> FusedIterator for RepeatN<A> {}
#[unstable(feature = "trusted_len", issue = "37572")]
unsafe impl<A: Clone> TrustedLen for RepeatN<A> {}
-#[stable(feature = "iter_repeat_n", since = "CURRENT_RUSTC_VERSION")]
+#[stable(feature = "iter_repeat_n", since = "1.82.0")]
impl<A: Clone> UncheckedIterator for RepeatN<A> {
#[inline]
unsafe fn next_unchecked(&mut self) -> Self::Item {
diff --git a/library/core/src/iter/traits/iterator.rs b/library/core/src/iter/traits/iterator.rs
index 50a2d95..8352486 100644
--- a/library/core/src/iter/traits/iterator.rs
+++ b/library/core/src/iter/traits/iterator.rs
@@ -3953,7 +3953,7 @@ fn ge<I>(self, other: I) -> bool
/// assert!(![0.0, 1.0, f32::NAN].iter().is_sorted());
/// ```
#[inline]
- #[stable(feature = "is_sorted", since = "CURRENT_RUSTC_VERSION")]
+ #[stable(feature = "is_sorted", since = "1.82.0")]
#[rustc_do_not_const_check]
fn is_sorted(self) -> bool
where
@@ -3980,7 +3980,7 @@ fn is_sorted(self) -> bool
/// assert!(std::iter::empty::<i32>().is_sorted_by(|a, b| false));
/// assert!(std::iter::empty::<i32>().is_sorted_by(|a, b| true));
/// ```
- #[stable(feature = "is_sorted", since = "CURRENT_RUSTC_VERSION")]
+ #[stable(feature = "is_sorted", since = "1.82.0")]
#[rustc_do_not_const_check]
fn is_sorted_by<F>(mut self, compare: F) -> bool
where
@@ -4025,7 +4025,7 @@ fn check<'a, T>(
/// assert!(![-2i32, -1, 0, 3].iter().is_sorted_by_key(|n| n.abs()));
/// ```
#[inline]
- #[stable(feature = "is_sorted", since = "CURRENT_RUSTC_VERSION")]
+ #[stable(feature = "is_sorted", since = "1.82.0")]
#[rustc_do_not_const_check]
fn is_sorted_by_key<F, K>(self, f: F) -> bool
where
diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs
index e60bcf3..bda38254 100644
--- a/library/core/src/lib.rs
+++ b/library/core/src/lib.rs
@@ -107,7 +107,6 @@
//
// Library features:
// tidy-alphabetical-start
-#![cfg_attr(bootstrap, feature(offset_of_nested))]
#![feature(array_ptr_get)]
#![feature(asm_experimental_arch)]
#![feature(const_align_of_val)]
@@ -122,7 +121,6 @@
#![feature(const_cell_into_inner)]
#![feature(const_eval_select)]
#![feature(const_exact_div)]
-#![feature(const_float_bits_conv)]
#![feature(const_float_classify)]
#![feature(const_fmt_arguments_new)]
#![feature(const_hash)]
@@ -166,6 +164,8 @@
#![feature(coverage_attribute)]
#![feature(do_not_recommend)]
#![feature(duration_consts_float)]
+#![feature(f128_const)]
+#![feature(f16_const)]
#![feature(internal_impls_macro)]
#![feature(ip)]
#![feature(is_ascii_octdigit)]
@@ -192,9 +192,6 @@
//
// Language features:
// tidy-alphabetical-start
-#![cfg_attr(bootstrap, feature(asm_const))]
-#![cfg_attr(bootstrap, feature(const_fn_floating_point_arithmetic))]
-#![cfg_attr(bootstrap, feature(min_exhaustive_patterns))]
#![feature(abi_unadjusted)]
#![feature(adt_const_params)]
#![feature(allow_internal_unsafe)]
diff --git a/library/core/src/marker.rs b/library/core/src/marker.rs
index 5654f5a..fd41b80 100644
--- a/library/core/src/marker.rs
+++ b/library/core/src/marker.rs
@@ -288,8 +288,19 @@ pub trait StructuralPartialEq {
/// }
/// ```
///
-/// There is a small difference between the two: the `derive` strategy will also place a `Copy`
-/// bound on type parameters, which isn't always desired.
+/// There is a small difference between the two. The `derive` strategy will also place a `Copy`
+/// bound on type parameters:
+///
+/// ```
+/// #[derive(Clone)]
+/// struct MyStruct<T>(T);
+///
+/// impl<T: Copy> Copy for MyStruct<T> { }
+/// ```
+///
+/// This isn't always desired. For example, shared references (`&T`) can be copied regardless of
+/// whether `T` is `Copy`. Likewise, a generic struct containing markers such as [`PhantomData`]
+/// could potentially be duplicated with a bit-wise copy.
///
/// ## What's the difference between `Copy` and `Clone`?
///
@@ -992,7 +1003,7 @@ pub trait ConstParamTy_: UnsizedConstParamTy + StructuralPartialEq + Eq {}
/* compiler built-in */
}
-#[cfg_attr(not(bootstrap), lang = "unsized_const_param_ty")]
+#[lang = "unsized_const_param_ty"]
#[unstable(feature = "unsized_const_params", issue = "95174")]
#[diagnostic::on_unimplemented(message = "`{Self}` can't be used as a const parameter type")]
/// A marker for types which can be used as types of `const` generic parameters.
@@ -1002,10 +1013,9 @@ pub trait ConstParamTy_: UnsizedConstParamTy + StructuralPartialEq + Eq {}
pub trait UnsizedConstParamTy: StructuralPartialEq + Eq {}
/// Derive macro generating an impl of the trait `ConstParamTy`.
-#[cfg(not(bootstrap))]
-#[cfg_attr(not(bootstrap), rustc_builtin_macro)]
-#[cfg_attr(not(bootstrap), allow_internal_unstable(unsized_const_params))]
-#[cfg_attr(not(bootstrap), unstable(feature = "unsized_const_params", issue = "95174"))]
+#[rustc_builtin_macro]
+#[allow_internal_unstable(unsized_const_params)]
+#[unstable(feature = "unsized_const_params", issue = "95174")]
pub macro UnsizedConstParamTy($item:item) {
/* compiler built-in */
}
@@ -1021,14 +1031,6 @@ pub trait UnsizedConstParamTy: StructuralPartialEq + Eq {}
(),
{T: ConstParamTy_, const N: usize} [T; N],
}
-#[cfg(bootstrap)]
-marker_impls! {
- #[unstable(feature = "adt_const_params", issue = "95174")]
- ConstParamTy_ for
- str,
- {T: ConstParamTy_} [T],
- {T: ConstParamTy_ + ?Sized} &T,
-}
marker_impls! {
#[unstable(feature = "unsized_const_params", issue = "95174")]
diff --git a/library/core/src/mem/manually_drop.rs b/library/core/src/mem/manually_drop.rs
index be5cee2..3e47785 100644
--- a/library/core/src/mem/manually_drop.rs
+++ b/library/core/src/mem/manually_drop.rs
@@ -47,7 +47,7 @@
#[lang = "manually_drop"]
#[derive(Copy, Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[repr(transparent)]
-#[cfg_attr(not(bootstrap), rustc_pub_transparent)]
+#[rustc_pub_transparent]
pub struct ManuallyDrop<T: ?Sized> {
value: T,
}
diff --git a/library/core/src/mem/maybe_uninit.rs b/library/core/src/mem/maybe_uninit.rs
index c308def..4be2e5e 100644
--- a/library/core/src/mem/maybe_uninit.rs
+++ b/library/core/src/mem/maybe_uninit.rs
@@ -237,7 +237,7 @@
#[lang = "maybe_uninit"]
#[derive(Copy)]
#[repr(transparent)]
-#[cfg_attr(not(bootstrap), rustc_pub_transparent)]
+#[rustc_pub_transparent]
pub union MaybeUninit<T> {
uninit: (),
value: ManuallyDrop<T>,
diff --git a/library/core/src/mem/mod.rs b/library/core/src/mem/mod.rs
index fed484a..414262f 100644
--- a/library/core/src/mem/mod.rs
+++ b/library/core/src/mem/mod.rs
@@ -1326,7 +1326,6 @@ impl<T> SizedTypeProperties for T {}
/// # Examples
///
/// ```
-/// # #![cfg_attr(bootstrap, feature(offset_of_nested))]
/// #![feature(offset_of_enum)]
///
/// use std::mem;
diff --git a/library/core/src/mem/transmutability.rs b/library/core/src/mem/transmutability.rs
index cda999a..7fa3c33 100644
--- a/library/core/src/mem/transmutability.rs
+++ b/library/core/src/mem/transmutability.rs
@@ -43,8 +43,7 @@
/// conversions that extend the bits of `Src` with trailing padding to fill
/// trailing uninitialized bytes of `Self`; e.g.:
///
-#[cfg_attr(bootstrap, doc = "```rust,ignore not runnable on bootstrap")]
-#[cfg_attr(not(bootstrap), doc = "```rust")]
+/// ```rust
/// #![feature(transmutability)]
///
/// use core::mem::{Assume, TransmuteFrom};
@@ -151,8 +150,7 @@ pub struct Assume {
/// When `false`, [`TransmuteFrom`] is not implemented for transmutations
/// that might violate the alignment requirements of references; e.g.:
///
- #[cfg_attr(bootstrap, doc = "```rust,ignore not runnable on bootstrap")]
- #[cfg_attr(not(bootstrap), doc = "```compile_fail,E0277")]
+ /// ```compile_fail,E0277
/// #![feature(transmutability)]
/// use core::mem::{align_of, TransmuteFrom};
///
@@ -171,8 +169,7 @@ pub struct Assume {
/// that references in the transmuted value satisfy the alignment
/// requirements of their referent types; e.g.:
///
- #[cfg_attr(bootstrap, doc = "```rust,ignore not runnable on bootstrap")]
- #[cfg_attr(not(bootstrap), doc = "```rust")]
+ /// ```rust
/// #![feature(pointer_is_aligned_to, transmutability)]
/// use core::mem::{align_of, Assume, TransmuteFrom};
///
@@ -203,8 +200,7 @@ pub struct Assume {
/// that might violate the library safety invariants of the destination
/// type; e.g.:
///
- #[cfg_attr(bootstrap, doc = "```rust,ignore not runnable on bootstrap")]
- #[cfg_attr(not(bootstrap), doc = "```compile_fail,E0277")]
+ /// ```compile_fail,E0277
/// #![feature(transmutability)]
/// use core::mem::TransmuteFrom;
///
@@ -225,8 +221,7 @@ pub struct Assume {
/// that undefined behavior does not arise from using the transmuted value;
/// e.g.:
///
- #[cfg_attr(bootstrap, doc = "```rust,ignore not runnable on bootstrap")]
- #[cfg_attr(not(bootstrap), doc = "```rust")]
+ /// ```rust
/// #![feature(transmutability)]
/// use core::mem::{Assume, TransmuteFrom};
///
@@ -254,8 +249,7 @@ pub struct Assume {
/// that might violate the language-level bit-validity invariant of the
/// destination type; e.g.:
///
- #[cfg_attr(bootstrap, doc = "```rust,ignore not runnable on bootstrap")]
- #[cfg_attr(not(bootstrap), doc = "```compile_fail,E0277")]
+ /// ```compile_fail,E0277
/// #![feature(transmutability)]
/// use core::mem::TransmuteFrom;
///
@@ -271,8 +265,7 @@ pub struct Assume {
/// that the value being transmuted is a bit-valid instance of the
/// transmuted value; e.g.:
///
- #[cfg_attr(bootstrap, doc = "```rust,ignore not runnable on bootstrap")]
- #[cfg_attr(not(bootstrap), doc = "```rust")]
+ /// ```rust
/// #![feature(transmutability)]
/// use core::mem::{Assume, TransmuteFrom};
///
@@ -335,9 +328,7 @@ impl Assume {
/// This is especially useful for extending [`Assume`] in generic contexts;
/// e.g.:
///
- #[cfg_attr(bootstrap, doc = "```rust,ignore not runnable on bootstrap")]
- #[cfg_attr(not(bootstrap), doc = "```rust")]
- #[unstable(feature = "transmutability", issue = "99571")]
+ /// ```rust
/// #![feature(
/// adt_const_params,
/// generic_const_exprs,
@@ -379,6 +370,7 @@ impl Assume {
/// try_transmute_ref::<_, _, { Assume::NOTHING }>(src)
/// };
///```
+ #[unstable(feature = "transmutability", issue = "99571")]
pub const fn and(self, other_assumptions: Self) -> Self {
Self {
alignment: self.alignment || other_assumptions.alignment,
@@ -390,8 +382,7 @@ pub const fn and(self, other_assumptions: Self) -> Self {
/// Remove `other_assumptions` the obligations of `self`; e.g.:
///
- #[cfg_attr(bootstrap, doc = "```rust,ignore not runnable on bootstrap")]
- #[cfg_attr(not(bootstrap), doc = "```rust")]
+ /// ```rust
/// #![feature(transmutability)]
/// use core::mem::Assume;
///
diff --git a/library/core/src/num/error.rs b/library/core/src/num/error.rs
index b8e22a8..6ef2fdd 100644
--- a/library/core/src/num/error.rs
+++ b/library/core/src/num/error.rs
@@ -113,7 +113,7 @@ pub enum IntErrorKind {
impl ParseIntError {
/// Outputs the detailed cause of parsing an integer failing.
#[must_use]
- #[rustc_const_stable(feature = "const_int_from_str", since = "CURRENT_RUSTC_VERSION")]
+ #[rustc_const_stable(feature = "const_int_from_str", since = "1.82.0")]
#[stable(feature = "int_error_matching", since = "1.55.0")]
pub const fn kind(&self) -> &IntErrorKind {
&self.kind
diff --git a/library/core/src/num/f128.rs b/library/core/src/num/f128.rs
index d4236e4..1959628 100644
--- a/library/core/src/num/f128.rs
+++ b/library/core/src/num/f128.rs
@@ -914,7 +914,7 @@ pub unsafe fn to_int_unchecked<Int>(self) -> Int
/// ```
#[inline]
#[unstable(feature = "f128", issue = "116909")]
- #[rustc_const_unstable(feature = "const_float_bits_conv", issue = "72447")]
+ #[rustc_const_unstable(feature = "f128_const", issue = "116909")]
#[must_use = "this returns the result of the operation, without modifying the original"]
pub const fn to_bits(self) -> u128 {
// SAFETY: `u128` is a plain old datatype so we can always transmute to it.
@@ -963,7 +963,7 @@ pub const fn to_bits(self) -> u128 {
#[inline]
#[must_use]
#[unstable(feature = "f128", issue = "116909")]
- #[rustc_const_unstable(feature = "const_float_bits_conv", issue = "72447")]
+ #[rustc_const_unstable(feature = "f128_const", issue = "116909")]
pub const fn from_bits(v: u128) -> Self {
// It turns out the safety issues with sNaN were overblown! Hooray!
// SAFETY: `u128` is a plain old datatype so we can always transmute from it.
@@ -990,7 +990,7 @@ pub const fn from_bits(v: u128) -> Self {
/// ```
#[inline]
#[unstable(feature = "f128", issue = "116909")]
- #[rustc_const_unstable(feature = "const_float_bits_conv", issue = "72447")]
+ #[rustc_const_unstable(feature = "f128_const", issue = "116909")]
#[must_use = "this returns the result of the operation, without modifying the original"]
pub const fn to_be_bytes(self) -> [u8; 16] {
self.to_bits().to_be_bytes()
@@ -1016,7 +1016,7 @@ pub const fn from_bits(v: u128) -> Self {
/// ```
#[inline]
#[unstable(feature = "f128", issue = "116909")]
- #[rustc_const_unstable(feature = "const_float_bits_conv", issue = "72447")]
+ #[rustc_const_unstable(feature = "f128_const", issue = "116909")]
#[must_use = "this returns the result of the operation, without modifying the original"]
pub const fn to_le_bytes(self) -> [u8; 16] {
self.to_bits().to_le_bytes()
@@ -1053,7 +1053,7 @@ pub const fn from_bits(v: u128) -> Self {
/// ```
#[inline]
#[unstable(feature = "f128", issue = "116909")]
- #[rustc_const_unstable(feature = "const_float_bits_conv", issue = "72447")]
+ #[rustc_const_unstable(feature = "f128_const", issue = "116909")]
#[must_use = "this returns the result of the operation, without modifying the original"]
pub const fn to_ne_bytes(self) -> [u8; 16] {
self.to_bits().to_ne_bytes()
@@ -1081,7 +1081,7 @@ pub const fn from_bits(v: u128) -> Self {
#[inline]
#[must_use]
#[unstable(feature = "f128", issue = "116909")]
- #[rustc_const_unstable(feature = "const_float_bits_conv", issue = "72447")]
+ #[rustc_const_unstable(feature = "f128_const", issue = "116909")]
pub const fn from_be_bytes(bytes: [u8; 16]) -> Self {
Self::from_bits(u128::from_be_bytes(bytes))
}
@@ -1108,7 +1108,7 @@ pub const fn from_bits(v: u128) -> Self {
#[inline]
#[must_use]
#[unstable(feature = "f128", issue = "116909")]
- #[rustc_const_unstable(feature = "const_float_bits_conv", issue = "72447")]
+ #[rustc_const_unstable(feature = "f128_const", issue = "116909")]
pub const fn from_le_bytes(bytes: [u8; 16]) -> Self {
Self::from_bits(u128::from_le_bytes(bytes))
}
@@ -1145,7 +1145,7 @@ pub const fn from_bits(v: u128) -> Self {
#[inline]
#[must_use]
#[unstable(feature = "f128", issue = "116909")]
- #[rustc_const_unstable(feature = "const_float_bits_conv", issue = "72447")]
+ #[rustc_const_unstable(feature = "f128_const", issue = "116909")]
pub const fn from_ne_bytes(bytes: [u8; 16]) -> Self {
Self::from_bits(u128::from_ne_bytes(bytes))
}
diff --git a/library/core/src/num/f16.rs b/library/core/src/num/f16.rs
index 1e2f841..9252e8c 100644
--- a/library/core/src/num/f16.rs
+++ b/library/core/src/num/f16.rs
@@ -925,7 +925,7 @@ pub unsafe fn to_int_unchecked<Int>(self) -> Int
/// ```
#[inline]
#[unstable(feature = "f16", issue = "116909")]
- #[rustc_const_unstable(feature = "const_float_bits_conv", issue = "72447")]
+ #[rustc_const_unstable(feature = "f16_const", issue = "116909")]
#[must_use = "this returns the result of the operation, without modifying the original"]
pub const fn to_bits(self) -> u16 {
// SAFETY: `u16` is a plain old datatype so we can always transmute to it.
@@ -973,7 +973,7 @@ pub const fn to_bits(self) -> u16 {
#[inline]
#[must_use]
#[unstable(feature = "f16", issue = "116909")]
- #[rustc_const_unstable(feature = "const_float_bits_conv", issue = "72447")]
+ #[rustc_const_unstable(feature = "f16_const", issue = "116909")]
pub const fn from_bits(v: u16) -> Self {
// It turns out the safety issues with sNaN were overblown! Hooray!
// SAFETY: `u16` is a plain old datatype so we can always transmute from it.
@@ -999,7 +999,7 @@ pub const fn from_bits(v: u16) -> Self {
/// ```
#[inline]
#[unstable(feature = "f16", issue = "116909")]
- #[rustc_const_unstable(feature = "const_float_bits_conv", issue = "72447")]
+ #[rustc_const_unstable(feature = "f16_const", issue = "116909")]
#[must_use = "this returns the result of the operation, without modifying the original"]
pub const fn to_be_bytes(self) -> [u8; 2] {
self.to_bits().to_be_bytes()
@@ -1024,7 +1024,7 @@ pub const fn from_bits(v: u16) -> Self {
/// ```
#[inline]
#[unstable(feature = "f16", issue = "116909")]
- #[rustc_const_unstable(feature = "const_float_bits_conv", issue = "72447")]
+ #[rustc_const_unstable(feature = "f16_const", issue = "116909")]
#[must_use = "this returns the result of the operation, without modifying the original"]
pub const fn to_le_bytes(self) -> [u8; 2] {
self.to_bits().to_le_bytes()
@@ -1062,7 +1062,7 @@ pub const fn from_bits(v: u16) -> Self {
/// ```
#[inline]
#[unstable(feature = "f16", issue = "116909")]
- #[rustc_const_unstable(feature = "const_float_bits_conv", issue = "72447")]
+ #[rustc_const_unstable(feature = "f16_const", issue = "116909")]
#[must_use = "this returns the result of the operation, without modifying the original"]
pub const fn to_ne_bytes(self) -> [u8; 2] {
self.to_bits().to_ne_bytes()
@@ -1086,7 +1086,7 @@ pub const fn from_bits(v: u16) -> Self {
#[inline]
#[must_use]
#[unstable(feature = "f16", issue = "116909")]
- #[rustc_const_unstable(feature = "const_float_bits_conv", issue = "72447")]
+ #[rustc_const_unstable(feature = "f16_const", issue = "116909")]
pub const fn from_be_bytes(bytes: [u8; 2]) -> Self {
Self::from_bits(u16::from_be_bytes(bytes))
}
@@ -1109,7 +1109,7 @@ pub const fn from_bits(v: u16) -> Self {
#[inline]
#[must_use]
#[unstable(feature = "f16", issue = "116909")]
- #[rustc_const_unstable(feature = "const_float_bits_conv", issue = "72447")]
+ #[rustc_const_unstable(feature = "f16_const", issue = "116909")]
pub const fn from_le_bytes(bytes: [u8; 2]) -> Self {
Self::from_bits(u16::from_le_bytes(bytes))
}
@@ -1143,7 +1143,7 @@ pub const fn from_bits(v: u16) -> Self {
#[inline]
#[must_use]
#[unstable(feature = "f16", issue = "116909")]
- #[rustc_const_unstable(feature = "const_float_bits_conv", issue = "72447")]
+ #[rustc_const_unstable(feature = "f16_const", issue = "116909")]
pub const fn from_ne_bytes(bytes: [u8; 2]) -> Self {
Self::from_bits(u16::from_ne_bytes(bytes))
}
diff --git a/library/core/src/num/f32.rs b/library/core/src/num/f32.rs
index c1adcc7..2bc8972 100644
--- a/library/core/src/num/f32.rs
+++ b/library/core/src/num/f32.rs
@@ -1115,7 +1115,7 @@ pub unsafe fn to_int_unchecked<Int>(self) -> Int
#[must_use = "this returns the result of the operation, \
without modifying the original"]
#[stable(feature = "float_bits_conv", since = "1.20.0")]
- #[rustc_const_unstable(feature = "const_float_bits_conv", issue = "72447")]
+ #[rustc_const_stable(feature = "const_float_bits_conv", since = "CURRENT_RUSTC_VERSION")]
#[inline]
pub const fn to_bits(self) -> u32 {
// SAFETY: `u32` is a plain old datatype so we can always transmute to it.
@@ -1159,7 +1159,7 @@ pub const fn to_bits(self) -> u32 {
/// assert_eq!(v, 12.5);
/// ```
#[stable(feature = "float_bits_conv", since = "1.20.0")]
- #[rustc_const_unstable(feature = "const_float_bits_conv", issue = "72447")]
+ #[rustc_const_stable(feature = "const_float_bits_conv", since = "CURRENT_RUSTC_VERSION")]
#[must_use]
#[inline]
pub const fn from_bits(v: u32) -> Self {
@@ -1183,7 +1183,7 @@ pub const fn from_bits(v: u32) -> Self {
#[must_use = "this returns the result of the operation, \
without modifying the original"]
#[stable(feature = "float_to_from_bytes", since = "1.40.0")]
- #[rustc_const_unstable(feature = "const_float_bits_conv", issue = "72447")]
+ #[rustc_const_stable(feature = "const_float_bits_conv", since = "CURRENT_RUSTC_VERSION")]
#[inline]
pub const fn to_be_bytes(self) -> [u8; 4] {
self.to_bits().to_be_bytes()
@@ -1204,7 +1204,7 @@ pub const fn from_bits(v: u32) -> Self {
#[must_use = "this returns the result of the operation, \
without modifying the original"]
#[stable(feature = "float_to_from_bytes", since = "1.40.0")]
- #[rustc_const_unstable(feature = "const_float_bits_conv", issue = "72447")]
+ #[rustc_const_stable(feature = "const_float_bits_conv", since = "CURRENT_RUSTC_VERSION")]
#[inline]
pub const fn to_le_bytes(self) -> [u8; 4] {
self.to_bits().to_le_bytes()
@@ -1238,7 +1238,7 @@ pub const fn from_bits(v: u32) -> Self {
#[must_use = "this returns the result of the operation, \
without modifying the original"]
#[stable(feature = "float_to_from_bytes", since = "1.40.0")]
- #[rustc_const_unstable(feature = "const_float_bits_conv", issue = "72447")]
+ #[rustc_const_stable(feature = "const_float_bits_conv", since = "CURRENT_RUSTC_VERSION")]
#[inline]
pub const fn to_ne_bytes(self) -> [u8; 4] {
self.to_bits().to_ne_bytes()
@@ -1256,7 +1256,7 @@ pub const fn from_bits(v: u32) -> Self {
/// assert_eq!(value, 12.5);
/// ```
#[stable(feature = "float_to_from_bytes", since = "1.40.0")]
- #[rustc_const_unstable(feature = "const_float_bits_conv", issue = "72447")]
+ #[rustc_const_stable(feature = "const_float_bits_conv", since = "CURRENT_RUSTC_VERSION")]
#[must_use]
#[inline]
pub const fn from_be_bytes(bytes: [u8; 4]) -> Self {
@@ -1275,7 +1275,7 @@ pub const fn from_bits(v: u32) -> Self {
/// assert_eq!(value, 12.5);
/// ```
#[stable(feature = "float_to_from_bytes", since = "1.40.0")]
- #[rustc_const_unstable(feature = "const_float_bits_conv", issue = "72447")]
+ #[rustc_const_stable(feature = "const_float_bits_conv", since = "CURRENT_RUSTC_VERSION")]
#[must_use]
#[inline]
pub const fn from_le_bytes(bytes: [u8; 4]) -> Self {
@@ -1305,7 +1305,7 @@ pub const fn from_bits(v: u32) -> Self {
/// assert_eq!(value, 12.5);
/// ```
#[stable(feature = "float_to_from_bytes", since = "1.40.0")]
- #[rustc_const_unstable(feature = "const_float_bits_conv", issue = "72447")]
+ #[rustc_const_stable(feature = "const_float_bits_conv", since = "CURRENT_RUSTC_VERSION")]
#[must_use]
#[inline]
pub const fn from_ne_bytes(bytes: [u8; 4]) -> Self {
diff --git a/library/core/src/num/f64.rs b/library/core/src/num/f64.rs
index e640677..b3f5be9 100644
--- a/library/core/src/num/f64.rs
+++ b/library/core/src/num/f64.rs
@@ -1111,7 +1111,7 @@ pub unsafe fn to_int_unchecked<Int>(self) -> Int
#[must_use = "this returns the result of the operation, \
without modifying the original"]
#[stable(feature = "float_bits_conv", since = "1.20.0")]
- #[rustc_const_unstable(feature = "const_float_bits_conv", issue = "72447")]
+ #[rustc_const_stable(feature = "const_float_bits_conv", since = "CURRENT_RUSTC_VERSION")]
#[inline]
pub const fn to_bits(self) -> u64 {
// SAFETY: `u64` is a plain old datatype so we can always transmute to it.
@@ -1155,7 +1155,7 @@ pub const fn to_bits(self) -> u64 {
/// assert_eq!(v, 12.5);
/// ```
#[stable(feature = "float_bits_conv", since = "1.20.0")]
- #[rustc_const_unstable(feature = "const_float_bits_conv", issue = "72447")]
+ #[rustc_const_stable(feature = "const_float_bits_conv", since = "CURRENT_RUSTC_VERSION")]
#[must_use]
#[inline]
pub const fn from_bits(v: u64) -> Self {
@@ -1179,7 +1179,7 @@ pub const fn from_bits(v: u64) -> Self {
#[must_use = "this returns the result of the operation, \
without modifying the original"]
#[stable(feature = "float_to_from_bytes", since = "1.40.0")]
- #[rustc_const_unstable(feature = "const_float_bits_conv", issue = "72447")]
+ #[rustc_const_stable(feature = "const_float_bits_conv", since = "CURRENT_RUSTC_VERSION")]
#[inline]
pub const fn to_be_bytes(self) -> [u8; 8] {
self.to_bits().to_be_bytes()
@@ -1200,7 +1200,7 @@ pub const fn from_bits(v: u64) -> Self {
#[must_use = "this returns the result of the operation, \
without modifying the original"]
#[stable(feature = "float_to_from_bytes", since = "1.40.0")]
- #[rustc_const_unstable(feature = "const_float_bits_conv", issue = "72447")]
+ #[rustc_const_stable(feature = "const_float_bits_conv", since = "CURRENT_RUSTC_VERSION")]
#[inline]
pub const fn to_le_bytes(self) -> [u8; 8] {
self.to_bits().to_le_bytes()
@@ -1234,7 +1234,7 @@ pub const fn from_bits(v: u64) -> Self {
#[must_use = "this returns the result of the operation, \
without modifying the original"]
#[stable(feature = "float_to_from_bytes", since = "1.40.0")]
- #[rustc_const_unstable(feature = "const_float_bits_conv", issue = "72447")]
+ #[rustc_const_stable(feature = "const_float_bits_conv", since = "CURRENT_RUSTC_VERSION")]
#[inline]
pub const fn to_ne_bytes(self) -> [u8; 8] {
self.to_bits().to_ne_bytes()
@@ -1252,7 +1252,7 @@ pub const fn from_bits(v: u64) -> Self {
/// assert_eq!(value, 12.5);
/// ```
#[stable(feature = "float_to_from_bytes", since = "1.40.0")]
- #[rustc_const_unstable(feature = "const_float_bits_conv", issue = "72447")]
+ #[rustc_const_stable(feature = "const_float_bits_conv", since = "CURRENT_RUSTC_VERSION")]
#[must_use]
#[inline]
pub const fn from_be_bytes(bytes: [u8; 8]) -> Self {
@@ -1271,7 +1271,7 @@ pub const fn from_bits(v: u64) -> Self {
/// assert_eq!(value, 12.5);
/// ```
#[stable(feature = "float_to_from_bytes", since = "1.40.0")]
- #[rustc_const_unstable(feature = "const_float_bits_conv", issue = "72447")]
+ #[rustc_const_stable(feature = "const_float_bits_conv", since = "CURRENT_RUSTC_VERSION")]
#[must_use]
#[inline]
pub const fn from_le_bytes(bytes: [u8; 8]) -> Self {
@@ -1301,7 +1301,7 @@ pub const fn from_bits(v: u64) -> Self {
/// assert_eq!(value, 12.5);
/// ```
#[stable(feature = "float_to_from_bytes", since = "1.40.0")]
- #[rustc_const_unstable(feature = "const_float_bits_conv", issue = "72447")]
+ #[rustc_const_stable(feature = "const_float_bits_conv", since = "CURRENT_RUSTC_VERSION")]
#[must_use]
#[inline]
pub const fn from_ne_bytes(bytes: [u8; 8]) -> Self {
diff --git a/library/core/src/num/int_macros.rs b/library/core/src/num/int_macros.rs
index 878a911..7241b3f 100644
--- a/library/core/src/num/int_macros.rs
+++ b/library/core/src/num/int_macros.rs
@@ -3023,8 +3023,16 @@ pub const fn rem_euclid(self, rhs: Self) -> Self {
pub const fn div_floor(self, rhs: Self) -> Self {
let d = self / rhs;
let r = self % rhs;
- if (r > 0 && rhs < 0) || (r < 0 && rhs > 0) {
- d - 1
+
+ // If the remainder is non-zero, we need to subtract one if the
+ // signs of self and rhs differ, as this means we rounded upwards
+ // instead of downwards. We do this branchlessly by creating a mask
+ // which is all-ones iff the signs differ, and 0 otherwise. Then by
+ // adding this mask (which corresponds to the signed value -1), we
+ // get our correction.
+ let correction = (self ^ rhs) >> (Self::BITS - 1);
+ if r != 0 {
+ d + correction
} else {
d
}
@@ -3059,8 +3067,12 @@ pub const fn div_floor(self, rhs: Self) -> Self {
pub const fn div_ceil(self, rhs: Self) -> Self {
let d = self / rhs;
let r = self % rhs;
- if (r > 0 && rhs > 0) || (r < 0 && rhs < 0) {
- d + 1
+
+ // When remainder is non-zero we have a.div_ceil(b) == 1 + a.div_floor(b),
+ // so we can re-use the algorithm from div_floor, just adding 1.
+ let correction = 1 + ((self ^ rhs) >> (Self::BITS - 1));
+ if r != 0 {
+ d + correction
} else {
d
}
diff --git a/library/core/src/num/mod.rs b/library/core/src/num/mod.rs
index e9e5324..37c9db7 100644
--- a/library/core/src/num/mod.rs
+++ b/library/core/src/num/mod.rs
@@ -1385,7 +1385,7 @@ fn from_str(src: &str) -> Result<Self, ParseIntError> {
#[doc(hidden)]
#[inline(always)]
#[unstable(issue = "none", feature = "std_internals")]
-#[rustc_const_stable(feature = "const_int_from_str", since = "CURRENT_RUSTC_VERSION")]
+#[rustc_const_stable(feature = "const_int_from_str", since = "1.82.0")]
pub const fn can_not_overflow<T>(radix: u32, is_signed_ty: bool, digits: &[u8]) -> bool {
radix <= 16 && digits.len() <= mem::size_of::<T>() * 2 - is_signed_ty as usize
}
@@ -1435,7 +1435,7 @@ impl $int_ty {
#[doc = concat!("assert_eq!(", stringify!($int_ty), "::from_str_radix(\"A\", 16), Ok(10));")]
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
- #[rustc_const_stable(feature = "const_int_from_str", since = "CURRENT_RUSTC_VERSION")]
+ #[rustc_const_stable(feature = "const_int_from_str", since = "1.82.0")]
pub const fn from_str_radix(src: &str, radix: u32) -> Result<$int_ty, ParseIntError> {
use self::IntErrorKind::*;
use self::ParseIntError as PIE;
@@ -1565,7 +1565,7 @@ impl $size {
#[doc = concat!("assert_eq!(", stringify!($size), "::from_str_radix(\"A\", 16), Ok(10));")]
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
- #[rustc_const_stable(feature = "const_int_from_str", since = "CURRENT_RUSTC_VERSION")]
+ #[rustc_const_stable(feature = "const_int_from_str", since = "1.82.0")]
pub const fn from_str_radix(src: &str, radix: u32) -> Result<$size, ParseIntError> {
match <$t>::from_str_radix(src, radix) {
Ok(x) => Ok(x as $size),
diff --git a/library/core/src/option.rs b/library/core/src/option.rs
index 50cb22b7..ff48575 100644
--- a/library/core/src/option.rs
+++ b/library/core/src/option.rs
@@ -667,7 +667,7 @@ pub const fn is_none(&self) -> bool {
/// ```
#[must_use]
#[inline]
- #[stable(feature = "is_none_or", since = "CURRENT_RUSTC_VERSION")]
+ #[stable(feature = "is_none_or", since = "1.82.0")]
pub fn is_none_or(self, f: impl FnOnce(T) -> bool) -> bool {
match self {
None => true,
@@ -1338,9 +1338,8 @@ pub fn as_deref_mut(&mut self) -> Option<&mut T::Target>
/// assert_eq!(x.iter().next(), None);
/// ```
#[inline]
- #[rustc_const_unstable(feature = "const_option", issue = "67441")]
#[stable(feature = "rust1", since = "1.0.0")]
- pub const fn iter(&self) -> Iter<'_, T> {
+ pub fn iter(&self) -> Iter<'_, T> {
Iter { inner: Item { opt: self.as_ref() } }
}
@@ -1894,7 +1893,7 @@ pub const fn copied(self) -> Option<T>
where
T: Copy,
{
- // FIXME: this implementation, which sidesteps using `Option::map` since it's not const
+ // FIXME(const-hack): this implementation, which sidesteps using `Option::map` since it's not const
// ready yet, should be reverted when possible to avoid code repetition
match self {
Some(&v) => Some(v),
@@ -1942,7 +1941,7 @@ impl<T> Option<&mut T> {
/// ```
#[must_use = "`self` will be dropped if the result is not used"]
#[stable(feature = "copied", since = "1.35.0")]
- #[rustc_const_unstable(feature = "const_option_ext", issue = "91930")]
+ #[rustc_const_unstable(feature = "const_option", issue = "67441")]
pub const fn copied(self) -> Option<T>
where
T: Copy,
diff --git a/library/core/src/pin.rs b/library/core/src/pin.rs
index 65f6bfb..9c13662 100644
--- a/library/core/src/pin.rs
+++ b/library/core/src/pin.rs
@@ -1084,7 +1084,7 @@
#[lang = "pin"]
#[fundamental]
#[repr(transparent)]
-#[cfg_attr(not(bootstrap), rustc_pub_transparent)]
+#[rustc_pub_transparent]
#[derive(Copy, Clone)]
pub struct Pin<Ptr> {
// FIXME(#93176): this field is made `#[unstable] #[doc(hidden)] pub` to:
diff --git a/library/core/src/ptr/const_ptr.rs b/library/core/src/ptr/const_ptr.rs
index 3b635e2..3b45d46 100644
--- a/library/core/src/ptr/const_ptr.rs
+++ b/library/core/src/ptr/const_ptr.rs
@@ -40,15 +40,17 @@ fn runtime_impl(ptr: *const u8) -> bool {
#[inline]
const fn const_impl(ptr: *const u8) -> bool {
- // Compare via a cast to a thin pointer, so fat pointers are only
- // considering their "data" part for null-ness.
match (ptr).guaranteed_eq(null_mut()) {
- None => false,
Some(res) => res,
+ // To remain maximally convervative, we stop execution when we don't
+ // know whether the pointer is null or not.
+ // We can *not* return `false` here, that would be unsound in `NonNull::new`!
+ None => panic!("null-ness of this pointer cannot be determined in const context"),
}
}
- #[allow(unused_unsafe)]
+ // Compare via a cast to a thin pointer, so fat pointers are only
+ // considering their "data" part for null-ness.
const_eval_select((self as *const u8,), const_impl, runtime_impl)
}
@@ -268,7 +270,7 @@ pub const fn to_raw_parts(self) -> (*const (), <T as super::Pointee>::Metadata)
/// }
/// ```
#[stable(feature = "ptr_as_ref", since = "1.9.0")]
- #[rustc_const_unstable(feature = "const_ptr_as_ref", issue = "91822")]
+ #[rustc_const_unstable(feature = "const_ptr_is_null", issue = "74939")]
#[inline]
pub const unsafe fn as_ref<'a>(self) -> Option<&'a T> {
// SAFETY: the caller must guarantee that `self` is valid
@@ -300,7 +302,7 @@ pub const fn to_raw_parts(self) -> (*const (), <T as super::Pointee>::Metadata)
/// ```
// FIXME: mention it in the docs for `as_ref` and `as_uninit_ref` once stabilized.
#[unstable(feature = "ptr_as_ref_unchecked", issue = "122034")]
- #[rustc_const_unstable(feature = "const_ptr_as_ref", issue = "91822")]
+ #[rustc_const_unstable(feature = "ptr_as_ref_unchecked", issue = "122034")]
#[inline]
#[must_use]
pub const unsafe fn as_ref_unchecked<'a>(self) -> &'a T {
@@ -334,7 +336,7 @@ pub const fn to_raw_parts(self) -> (*const (), <T as super::Pointee>::Metadata)
/// ```
#[inline]
#[unstable(feature = "ptr_as_uninit", issue = "75402")]
- #[rustc_const_unstable(feature = "const_ptr_as_ref", issue = "91822")]
+ #[rustc_const_unstable(feature = "ptr_as_uninit", issue = "75402")]
pub const unsafe fn as_uninit_ref<'a>(self) -> Option<&'a MaybeUninit<T>>
where
T: Sized,
@@ -1662,7 +1664,7 @@ pub unsafe fn get_unchecked<I>(self, index: I) -> *const I::Output
/// [allocated object]: crate::ptr#allocated-object
#[inline]
#[unstable(feature = "ptr_as_uninit", issue = "75402")]
- #[rustc_const_unstable(feature = "const_ptr_as_ref", issue = "91822")]
+ #[rustc_const_unstable(feature = "ptr_as_uninit", issue = "75402")]
pub const unsafe fn as_uninit_slice<'a>(self) -> Option<&'a [MaybeUninit<T>]> {
if self.is_null() {
None
diff --git a/library/core/src/ptr/metadata.rs b/library/core/src/ptr/metadata.rs
index ccc9f87..76a0e2b 100644
--- a/library/core/src/ptr/metadata.rs
+++ b/library/core/src/ptr/metadata.rs
@@ -187,14 +187,14 @@ pub fn size_of(self) -> usize {
// Consider a reference like `&(i32, dyn Send)`: the vtable will only store the size of the
// `Send` part!
// SAFETY: DynMetadata always contains a valid vtable pointer
- return unsafe { crate::intrinsics::vtable_size(self.vtable_ptr() as *const ()) };
+ unsafe { crate::intrinsics::vtable_size(self.vtable_ptr() as *const ()) }
}
/// Returns the alignment of the type associated with this vtable.
#[inline]
pub fn align_of(self) -> usize {
// SAFETY: DynMetadata always contains a valid vtable pointer
- return unsafe { crate::intrinsics::vtable_align(self.vtable_ptr() as *const ()) };
+ unsafe { crate::intrinsics::vtable_align(self.vtable_ptr() as *const ()) }
}
/// Returns the size and alignment together as a `Layout`
diff --git a/library/core/src/ptr/mod.rs b/library/core/src/ptr/mod.rs
index d7ed4ed..08d06ca 100644
--- a/library/core/src/ptr/mod.rs
+++ b/library/core/src/ptr/mod.rs
@@ -2277,6 +2277,14 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
/// `addr_of!(expr)` is equivalent to `&raw const expr`. The macro is *soft-deprecated*;
/// use `&raw const` instead.
///
+/// It is still an open question under which conditions writing through an `addr_of!`-created
+/// pointer is permitted. If the place `expr` evaluates to is based on a raw pointer, then the
+/// result of `addr_of!` inherits all permissions from that raw pointer. However, if the place is
+/// based on a reference, local variable, or `static`, then until all details are decided, the same
+/// rules as for shared references apply: it is UB to write through a pointer created with this
+/// operation, except for bytes located inside an `UnsafeCell`. Use `&raw mut` (or [`addr_of_mut`])
+/// to create a raw pointer that definitely permits mutation.
+///
/// Creating a reference with `&`/`&mut` is only allowed if the pointer is properly aligned
/// and points to initialized data. For cases where those requirements do not hold,
/// raw pointers should be used instead. However, `&expr as *const _` creates a reference
diff --git a/library/core/src/ptr/mut_ptr.rs b/library/core/src/ptr/mut_ptr.rs
index 42975cc..ddb9195 100644
--- a/library/core/src/ptr/mut_ptr.rs
+++ b/library/core/src/ptr/mut_ptr.rs
@@ -33,22 +33,7 @@ impl<T: ?Sized> *mut T {
#[rustc_diagnostic_item = "ptr_is_null"]
#[inline]
pub const fn is_null(self) -> bool {
- #[inline]
- fn runtime_impl(ptr: *mut u8) -> bool {
- ptr.addr() == 0
- }
-
- #[inline]
- const fn const_impl(ptr: *mut u8) -> bool {
- // Compare via a cast to a thin pointer, so fat pointers are only
- // considering their "data" part for null-ness.
- match (ptr).guaranteed_eq(null_mut()) {
- None => false,
- Some(res) => res,
- }
- }
-
- const_eval_select((self as *mut u8,), const_impl, runtime_impl)
+ self.cast_const().is_null()
}
/// Casts to a pointer of another type.
@@ -276,7 +261,7 @@ pub const fn to_raw_parts(self) -> (*mut (), <T as super::Pointee>::Metadata) {
/// }
/// ```
#[stable(feature = "ptr_as_ref", since = "1.9.0")]
- #[rustc_const_unstable(feature = "const_ptr_as_ref", issue = "91822")]
+ #[rustc_const_unstable(feature = "const_ptr_is_null", issue = "74939")]
#[inline]
pub const unsafe fn as_ref<'a>(self) -> Option<&'a T> {
// SAFETY: the caller must guarantee that `self` is valid for a
@@ -310,7 +295,7 @@ pub const fn to_raw_parts(self) -> (*mut (), <T as super::Pointee>::Metadata) {
/// ```
// FIXME: mention it in the docs for `as_ref` and `as_uninit_ref` once stabilized.
#[unstable(feature = "ptr_as_ref_unchecked", issue = "122034")]
- #[rustc_const_unstable(feature = "const_ptr_as_ref", issue = "91822")]
+ #[rustc_const_unstable(feature = "ptr_as_ref_unchecked", issue = "122034")]
#[inline]
#[must_use]
pub const unsafe fn as_ref_unchecked<'a>(self) -> &'a T {
@@ -349,7 +334,7 @@ pub const fn to_raw_parts(self) -> (*mut (), <T as super::Pointee>::Metadata) {
/// ```
#[inline]
#[unstable(feature = "ptr_as_uninit", issue = "75402")]
- #[rustc_const_unstable(feature = "const_ptr_as_ref", issue = "91822")]
+ #[rustc_const_unstable(feature = "ptr_as_uninit", issue = "75402")]
pub const unsafe fn as_uninit_ref<'a>(self) -> Option<&'a MaybeUninit<T>>
where
T: Sized,
@@ -595,7 +580,7 @@ pub fn mask(self, mask: usize) -> *mut T {
/// println!("{s:?}"); // It'll print: "[4, 2, 3]".
/// ```
#[stable(feature = "ptr_as_ref", since = "1.9.0")]
- #[rustc_const_unstable(feature = "const_ptr_as_ref", issue = "91822")]
+ #[rustc_const_unstable(feature = "const_ptr_is_null", issue = "74939")]
#[inline]
pub const unsafe fn as_mut<'a>(self) -> Option<&'a mut T> {
// SAFETY: the caller must guarantee that `self` is be valid for
@@ -631,7 +616,7 @@ pub fn mask(self, mask: usize) -> *mut T {
/// ```
// FIXME: mention it in the docs for `as_mut` and `as_uninit_mut` once stabilized.
#[unstable(feature = "ptr_as_ref_unchecked", issue = "122034")]
- #[rustc_const_unstable(feature = "const_ptr_as_ref", issue = "91822")]
+ #[rustc_const_unstable(feature = "ptr_as_ref_unchecked", issue = "122034")]
#[inline]
#[must_use]
pub const unsafe fn as_mut_unchecked<'a>(self) -> &'a mut T {
@@ -654,7 +639,7 @@ pub fn mask(self, mask: usize) -> *mut T {
/// the pointer is [convertible to a reference](crate::ptr#pointer-to-reference-conversion).
#[inline]
#[unstable(feature = "ptr_as_uninit", issue = "75402")]
- #[rustc_const_unstable(feature = "const_ptr_as_ref", issue = "91822")]
+ #[rustc_const_unstable(feature = "ptr_as_uninit", issue = "75402")]
pub const unsafe fn as_uninit_mut<'a>(self) -> Option<&'a mut MaybeUninit<T>>
where
T: Sized,
@@ -2031,7 +2016,7 @@ pub unsafe fn get_unchecked_mut<I>(self, index: I) -> *mut I::Output
/// [allocated object]: crate::ptr#allocated-object
#[inline]
#[unstable(feature = "ptr_as_uninit", issue = "75402")]
- #[rustc_const_unstable(feature = "const_ptr_as_ref", issue = "91822")]
+ #[rustc_const_unstable(feature = "ptr_as_uninit", issue = "75402")]
pub const unsafe fn as_uninit_slice<'a>(self) -> Option<&'a [MaybeUninit<T>]> {
if self.is_null() {
None
@@ -2083,7 +2068,7 @@ pub unsafe fn get_unchecked_mut<I>(self, index: I) -> *mut I::Output
/// [allocated object]: crate::ptr#allocated-object
#[inline]
#[unstable(feature = "ptr_as_uninit", issue = "75402")]
- #[rustc_const_unstable(feature = "const_ptr_as_ref", issue = "91822")]
+ #[rustc_const_unstable(feature = "ptr_as_uninit", issue = "75402")]
pub const unsafe fn as_uninit_slice_mut<'a>(self) -> Option<&'a mut [MaybeUninit<T>]> {
if self.is_null() {
None
diff --git a/library/core/src/ptr/non_null.rs b/library/core/src/ptr/non_null.rs
index b1429ff..673acc2 100644
--- a/library/core/src/ptr/non_null.rs
+++ b/library/core/src/ptr/non_null.rs
@@ -133,7 +133,7 @@ pub const fn dangling() -> Self {
#[inline]
#[must_use]
#[unstable(feature = "ptr_as_uninit", issue = "75402")]
- #[rustc_const_unstable(feature = "const_ptr_as_ref", issue = "91822")]
+ #[rustc_const_unstable(feature = "ptr_as_uninit", issue = "75402")]
pub const unsafe fn as_uninit_ref<'a>(self) -> &'a MaybeUninit<T> {
// SAFETY: the caller must guarantee that `self` meets all the
// requirements for a reference.
@@ -157,7 +157,7 @@ pub const fn dangling() -> Self {
#[inline]
#[must_use]
#[unstable(feature = "ptr_as_uninit", issue = "75402")]
- #[rustc_const_unstable(feature = "const_ptr_as_ref", issue = "91822")]
+ #[rustc_const_unstable(feature = "ptr_as_uninit", issue = "75402")]
pub const unsafe fn as_uninit_mut<'a>(self) -> &'a mut MaybeUninit<T> {
// SAFETY: the caller must guarantee that `self` meets all the
// requirements for a reference.
@@ -1563,7 +1563,7 @@ pub const fn as_mut_ptr(self) -> *mut T {
#[inline]
#[must_use]
#[unstable(feature = "ptr_as_uninit", issue = "75402")]
- #[rustc_const_unstable(feature = "const_ptr_as_ref", issue = "91822")]
+ #[rustc_const_unstable(feature = "ptr_as_uninit", issue = "75402")]
pub const unsafe fn as_uninit_slice<'a>(self) -> &'a [MaybeUninit<T>] {
// SAFETY: the caller must uphold the safety contract for `as_uninit_slice`.
unsafe { slice::from_raw_parts(self.cast().as_ptr(), self.len()) }
@@ -1628,7 +1628,7 @@ pub const fn as_mut_ptr(self) -> *mut T {
#[inline]
#[must_use]
#[unstable(feature = "ptr_as_uninit", issue = "75402")]
- #[rustc_const_unstable(feature = "const_ptr_as_ref", issue = "91822")]
+ #[rustc_const_unstable(feature = "ptr_as_uninit", issue = "75402")]
pub const unsafe fn as_uninit_slice_mut<'a>(self) -> &'a mut [MaybeUninit<T>] {
// SAFETY: the caller must uphold the safety contract for `as_uninit_slice_mut`.
unsafe { slice::from_raw_parts_mut(self.cast().as_ptr(), self.len()) }
diff --git a/library/core/src/result.rs b/library/core/src/result.rs
index 73b11f8..02f6f78 100644
--- a/library/core/src/result.rs
+++ b/library/core/src/result.rs
@@ -1535,11 +1535,17 @@ impl<T, E> Result<&T, E> {
/// ```
#[inline]
#[stable(feature = "result_copied", since = "1.59.0")]
- pub fn copied(self) -> Result<T, E>
+ #[rustc_const_unstable(feature = "const_result", issue = "82814")]
+ pub const fn copied(self) -> Result<T, E>
where
T: Copy,
{
- self.map(|&t| t)
+ // FIXME(const-hack): this implementation, which sidesteps using `Result::map` since it's not const
+ // ready yet, should be reverted when possible to avoid code repetition
+ match self {
+ Ok(&v) => Ok(v),
+ Err(e) => Err(e),
+ }
}
/// Maps a `Result<&T, E>` to a `Result<T, E>` by cloning the contents of the
@@ -1579,11 +1585,17 @@ impl<T, E> Result<&mut T, E> {
/// ```
#[inline]
#[stable(feature = "result_copied", since = "1.59.0")]
- pub fn copied(self) -> Result<T, E>
+ #[rustc_const_unstable(feature = "const_result", issue = "82814")]
+ pub const fn copied(self) -> Result<T, E>
where
T: Copy,
{
- self.map(|&mut t| t)
+ // FIXME(const-hack): this implementation, which sidesteps using `Result::map` since it's not const
+ // ready yet, should be reverted when possible to avoid code repetition
+ match self {
+ Ok(&mut v) => Ok(v),
+ Err(e) => Err(e),
+ }
}
/// Maps a `Result<&mut T, E>` to a `Result<T, E>` by cloning the contents of the
diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs
index c791849..166189f 100644
--- a/library/core/src/slice/mod.rs
+++ b/library/core/src/slice/mod.rs
@@ -4088,7 +4088,7 @@ pub fn as_simd_mut<const LANES: usize>(&mut self) -> (&mut [T], &mut [Simd<T, LA
/// assert!(![0.0, 1.0, f32::NAN].is_sorted());
/// ```
#[inline]
- #[stable(feature = "is_sorted", since = "CURRENT_RUSTC_VERSION")]
+ #[stable(feature = "is_sorted", since = "1.82.0")]
#[must_use]
pub fn is_sorted(&self) -> bool
where
@@ -4115,7 +4115,7 @@ pub fn is_sorted(&self) -> bool
/// assert!(empty.is_sorted_by(|a, b| false));
/// assert!(empty.is_sorted_by(|a, b| true));
/// ```
- #[stable(feature = "is_sorted", since = "CURRENT_RUSTC_VERSION")]
+ #[stable(feature = "is_sorted", since = "1.82.0")]
#[must_use]
pub fn is_sorted_by<'a, F>(&'a self, mut compare: F) -> bool
where
@@ -4139,7 +4139,7 @@ pub fn is_sorted_by<'a, F>(&'a self, mut compare: F) -> bool
/// assert!(![-2i32, -1, 0, 3].is_sorted_by_key(|n| n.abs()));
/// ```
#[inline]
- #[stable(feature = "is_sorted", since = "CURRENT_RUSTC_VERSION")]
+ #[stable(feature = "is_sorted", since = "1.82.0")]
#[must_use]
pub fn is_sorted_by_key<'a, F, K>(&'a self, f: F) -> bool
where
diff --git a/library/core/src/str/iter.rs b/library/core/src/str/iter.rs
index 681ec79..d9301a8 100644
--- a/library/core/src/str/iter.rs
+++ b/library/core/src/str/iter.rs
@@ -269,7 +269,7 @@ pub fn as_str(&self) -> &'a str {
/// ```
#[inline]
#[must_use]
- #[stable(feature = "char_indices_offset", since = "CURRENT_RUSTC_VERSION")]
+ #[stable(feature = "char_indices_offset", since = "1.82.0")]
pub fn offset(&self) -> usize {
self.front_offset
}
diff --git a/library/core/src/str/mod.rs b/library/core/src/str/mod.rs
index cf9f1bf..e947686 100644
--- a/library/core/src/str/mod.rs
+++ b/library/core/src/str/mod.rs
@@ -338,9 +338,10 @@ pub const fn as_bytes(&self) -> &[u8] {
/// assert_eq!("🍔∈🌏", s);
/// ```
#[stable(feature = "str_mut_extras", since = "1.20.0")]
+ #[rustc_const_unstable(feature = "const_str_as_mut", issue = "130086")]
#[must_use]
#[inline(always)]
- pub unsafe fn as_bytes_mut(&mut self) -> &mut [u8] {
+ pub const unsafe fn as_bytes_mut(&mut self) -> &mut [u8] {
// SAFETY: the cast from `&str` to `&[u8]` is safe since `str`
// has the same layout as `&[u8]` (only std can make this guarantee).
// The pointer dereference is safe since it comes from a mutable reference which
@@ -383,10 +384,11 @@ pub const fn as_ptr(&self) -> *const u8 {
/// It is your responsibility to make sure that the string slice only gets
/// modified in a way that it remains valid UTF-8.
#[stable(feature = "str_as_mut_ptr", since = "1.36.0")]
+ #[rustc_const_unstable(feature = "const_str_as_mut", issue = "130086")]
#[rustc_never_returns_null_ptr]
#[must_use]
#[inline(always)]
- pub fn as_mut_ptr(&mut self) -> *mut u8 {
+ pub const fn as_mut_ptr(&mut self) -> *mut u8 {
self as *mut str as *mut u8
}
diff --git a/library/core/src/str/pattern.rs b/library/core/src/str/pattern.rs
index 2f1096d..9f1294d 100644
--- a/library/core/src/str/pattern.rs
+++ b/library/core/src/str/pattern.rs
@@ -1814,7 +1814,7 @@ fn simd_contains(needle: &str, haystack: &str) -> Option<bool> {
}
mask &= !(1 << trailing);
}
- return false;
+ false
};
let test_chunk = |idx| -> u16 {
@@ -1830,7 +1830,7 @@ fn simd_contains(needle: &str, haystack: &str) -> Option<bool> {
let both = eq_first.bitand(eq_last);
let mask = both.to_bitmask() as u16;
- return mask;
+ mask
};
let mut i = 0;
diff --git a/library/core/src/task/wake.rs b/library/core/src/task/wake.rs
index 6924b3c..5e559ad 100644
--- a/library/core/src/task/wake.rs
+++ b/library/core/src/task/wake.rs
@@ -234,7 +234,7 @@ pub struct Context<'a> {
impl<'a> Context<'a> {
/// Creates a new `Context` from a [`&Waker`](Waker).
#[stable(feature = "futures_api", since = "1.36.0")]
- #[rustc_const_stable(feature = "const_waker", since = "CURRENT_RUSTC_VERSION")]
+ #[rustc_const_stable(feature = "const_waker", since = "1.82.0")]
#[must_use]
#[inline]
pub const fn from_waker(waker: &'a Waker) -> Self {
@@ -245,7 +245,7 @@ pub const fn from_waker(waker: &'a Waker) -> Self {
#[inline]
#[must_use]
#[stable(feature = "futures_api", since = "1.36.0")]
- #[rustc_const_stable(feature = "const_waker", since = "CURRENT_RUSTC_VERSION")]
+ #[rustc_const_stable(feature = "const_waker", since = "1.82.0")]
pub const fn waker(&self) -> &'a Waker {
&self.waker
}
@@ -321,7 +321,7 @@ impl<'a> ContextBuilder<'a> {
/// Creates a ContextBuilder from a Waker.
#[inline]
#[unstable(feature = "local_waker", issue = "118959")]
- #[rustc_const_stable(feature = "const_waker", since = "CURRENT_RUSTC_VERSION")]
+ #[rustc_const_stable(feature = "const_waker", since = "1.82.0")]
pub const fn from_waker(waker: &'a Waker) -> Self {
// SAFETY: LocalWaker is just Waker without thread safety
let local_waker = unsafe { transmute(waker) };
@@ -379,7 +379,7 @@ pub const fn ext(self, data: &'a mut dyn Any) -> Self {
/// Builds the `Context`.
#[inline]
#[unstable(feature = "local_waker", issue = "118959")]
- #[rustc_const_stable(feature = "const_waker", since = "CURRENT_RUSTC_VERSION")]
+ #[rustc_const_stable(feature = "const_waker", since = "1.82.0")]
pub const fn build(self) -> Context<'a> {
let ContextBuilder { waker, local_waker, ext, _marker, _marker2 } = self;
Context { waker, local_waker, ext: AssertUnwindSafe(ext), _marker, _marker2 }
@@ -538,7 +538,7 @@ pub fn will_wake(&self, other: &Waker) -> bool {
#[inline]
#[must_use]
#[stable(feature = "futures_api", since = "1.36.0")]
- #[rustc_const_stable(feature = "const_waker", since = "CURRENT_RUSTC_VERSION")]
+ #[rustc_const_stable(feature = "const_waker", since = "1.82.0")]
pub const unsafe fn from_raw(waker: RawWaker) -> Waker {
Waker { waker }
}
diff --git a/library/core/src/time.rs b/library/core/src/time.rs
index 0390bb5..c19eeed 100644
--- a/library/core/src/time.rs
+++ b/library/core/src/time.rs
@@ -250,7 +250,7 @@ pub const fn from_secs(secs: u64) -> Duration {
/// ```
/// use std::time::Duration;
///
- /// let duration = Duration::from_millis(2569);
+ /// let duration = Duration::from_millis(2_569);
///
/// assert_eq!(2, duration.as_secs());
/// assert_eq!(569_000_000, duration.subsec_nanos());
@@ -279,7 +279,7 @@ pub const fn from_millis(millis: u64) -> Duration {
/// let duration = Duration::from_micros(1_000_002);
///
/// assert_eq!(1, duration.as_secs());
- /// assert_eq!(2000, duration.subsec_nanos());
+ /// assert_eq!(2_000, duration.subsec_nanos());
/// ```
#[stable(feature = "duration_from_micros", since = "1.27.0")]
#[must_use]
@@ -472,7 +472,7 @@ pub const fn is_zero(&self) -> bool {
/// ```
/// use std::time::Duration;
///
- /// let duration = Duration::new(5, 730023852);
+ /// let duration = Duration::new(5, 730_023_852);
/// assert_eq!(duration.as_secs(), 5);
/// ```
///
@@ -501,7 +501,7 @@ pub const fn as_secs(&self) -> u64 {
/// ```
/// use std::time::Duration;
///
- /// let duration = Duration::from_millis(5432);
+ /// let duration = Duration::from_millis(5_432);
/// assert_eq!(duration.as_secs(), 5);
/// assert_eq!(duration.subsec_millis(), 432);
/// ```
@@ -547,7 +547,7 @@ pub const fn subsec_micros(&self) -> u32 {
/// ```
/// use std::time::Duration;
///
- /// let duration = Duration::from_millis(5010);
+ /// let duration = Duration::from_millis(5_010);
/// assert_eq!(duration.as_secs(), 5);
/// assert_eq!(duration.subsec_nanos(), 10_000_000);
/// ```
@@ -566,8 +566,8 @@ pub const fn subsec_nanos(&self) -> u32 {
/// ```
/// use std::time::Duration;
///
- /// let duration = Duration::new(5, 730023852);
- /// assert_eq!(duration.as_millis(), 5730);
+ /// let duration = Duration::new(5, 730_023_852);
+ /// assert_eq!(duration.as_millis(), 5_730);
/// ```
#[stable(feature = "duration_as_u128", since = "1.33.0")]
#[rustc_const_stable(feature = "duration_as_u128", since = "1.33.0")]
@@ -584,8 +584,8 @@ pub const fn as_millis(&self) -> u128 {
/// ```
/// use std::time::Duration;
///
- /// let duration = Duration::new(5, 730023852);
- /// assert_eq!(duration.as_micros(), 5730023);
+ /// let duration = Duration::new(5, 730_023_852);
+ /// assert_eq!(duration.as_micros(), 5_730_023);
/// ```
#[stable(feature = "duration_as_u128", since = "1.33.0")]
#[rustc_const_stable(feature = "duration_as_u128", since = "1.33.0")]
@@ -602,8 +602,8 @@ pub const fn as_micros(&self) -> u128 {
/// ```
/// use std::time::Duration;
///
- /// let duration = Duration::new(5, 730023852);
- /// assert_eq!(duration.as_nanos(), 5730023852);
+ /// let duration = Duration::new(5, 730_023_852);
+ /// assert_eq!(duration.as_nanos(), 5_730_023_852);
/// ```
#[stable(feature = "duration_as_u128", since = "1.33.0")]
#[rustc_const_stable(feature = "duration_as_u128", since = "1.33.0")]
@@ -879,7 +879,7 @@ pub const fn as_secs_f32(&self) -> f32 {
/// use std::time::Duration;
///
/// let dur = Duration::new(2, 345_678_000);
- /// assert_eq!(dur.as_millis_f64(), 2345.678);
+ /// assert_eq!(dur.as_millis_f64(), 2_345.678);
/// ```
#[unstable(feature = "duration_millis_float", issue = "122451")]
#[must_use]
@@ -900,7 +900,7 @@ pub const fn as_millis_f64(&self) -> f64 {
/// use std::time::Duration;
///
/// let dur = Duration::new(2, 345_678_000);
- /// assert_eq!(dur.as_millis_f32(), 2345.678);
+ /// assert_eq!(dur.as_millis_f32(), 2_345.678);
/// ```
#[unstable(feature = "duration_millis_float", issue = "122451")]
#[must_use]
@@ -1017,7 +1017,7 @@ pub fn mul_f64(self, rhs: f64) -> Duration {
///
/// let dur = Duration::new(2, 700_000_000);
/// assert_eq!(dur.mul_f32(3.14), Duration::new(8, 478_000_641));
- /// assert_eq!(dur.mul_f32(3.14e5), Duration::new(847800, 0));
+ /// assert_eq!(dur.mul_f32(3.14e5), Duration::new(847_800, 0));
/// ```
#[stable(feature = "duration_float", since = "1.38.0")]
#[must_use = "this returns the result of the operation, \
diff --git a/library/core/src/tuple.rs b/library/core/src/tuple.rs
index 9ec92e2..206b5b9 100644
--- a/library/core/src/tuple.rs
+++ b/library/core/src/tuple.rs
@@ -154,7 +154,7 @@ fn from(tuple: ($(${ignore($T)} T,)+)) -> Self {
// Otherwise, it hides the docs entirely.
macro_rules! maybe_tuple_doc {
($a:ident @ #[$meta:meta] $item:item) => {
- #[cfg_attr(not(bootstrap), doc(fake_variadic))]
+ #[doc(fake_variadic)]
#[doc = "This trait is implemented for tuples up to twelve items long."]
#[$meta]
$item
diff --git a/library/core/tests/lib.rs b/library/core/tests/lib.rs
index 96fc621..dbceb8a 100644
--- a/library/core/tests/lib.rs
+++ b/library/core/tests/lib.rs
@@ -1,5 +1,4 @@
// tidy-alphabetical-start
-#![cfg_attr(bootstrap, feature(offset_of_nested))]
#![cfg_attr(target_has_atomic = "128", feature(integer_atomics))]
#![cfg_attr(test, feature(cfg_match))]
#![feature(alloc_layout_extra)]
diff --git a/library/core/tests/mem.rs b/library/core/tests/mem.rs
index b7eee10..f3b4387 100644
--- a/library/core/tests/mem.rs
+++ b/library/core/tests/mem.rs
@@ -773,15 +773,20 @@ struct Foo {
#[test]
fn const_maybe_uninit_zeroed() {
// Sanity check for `MaybeUninit::zeroed` in a realistic const situation (plugin array term)
+
+ // It is crucial that this type has no padding!
#[repr(C)]
struct Foo {
- a: Option<&'static str>,
+ a: Option<&'static u8>,
b: Bar,
c: f32,
+ _pad: u32,
d: *const u8,
}
+
#[repr(C)]
struct Bar(usize);
+
struct FooPtr(*const Foo);
unsafe impl Sync for FooPtr {}
diff --git a/library/panic_unwind/src/seh.rs b/library/panic_unwind/src/seh.rs
index 82c248c..070c119 100644
--- a/library/panic_unwind/src/seh.rs
+++ b/library/panic_unwind/src/seh.rs
@@ -157,9 +157,6 @@ pub fn new(ptr: *mut u8) -> Self {
// going to be cross-lang LTOed anyway. However, using expose is shorter and
// requires less unsafe.
let addr: usize = ptr.expose_provenance();
- #[cfg(bootstrap)]
- let image_base = unsafe { addr_of!(__ImageBase) }.addr();
- #[cfg(not(bootstrap))]
let image_base = addr_of!(__ImageBase).addr();
let offset: usize = addr - image_base;
Self(offset as u32)
@@ -253,9 +250,6 @@ pub struct _TypeDescriptor {
// This is fine since the MSVC runtime uses string comparison on the type name
// to match TypeDescriptors rather than pointer equality.
static mut TYPE_DESCRIPTOR: _TypeDescriptor = _TypeDescriptor {
- #[cfg(bootstrap)]
- pVFTable: unsafe { addr_of!(TYPE_INFO_VTABLE) } as *const _,
- #[cfg(not(bootstrap))]
pVFTable: addr_of!(TYPE_INFO_VTABLE) as *const _,
spare: core::ptr::null_mut(),
name: TYPE_NAME,
diff --git a/library/std/src/env.rs b/library/std/src/env.rs
index e06a851..2891613 100644
--- a/library/std/src/env.rs
+++ b/library/std/src/env.rs
@@ -354,12 +354,8 @@ fn description(&self) -> &str {
/// }
/// assert_eq!(env::var(key), Ok("VALUE".to_string()));
/// ```
-#[cfg_attr(bootstrap, rustc_deprecated_safe_2024)]
-#[cfg_attr(
- not(bootstrap),
- rustc_deprecated_safe_2024(
- audit_that = "the environment access only happens in single-threaded code"
- )
+#[rustc_deprecated_safe_2024(
+ audit_that = "the environment access only happens in single-threaded code"
)]
#[stable(feature = "env", since = "1.0.0")]
pub unsafe fn set_var<K: AsRef<OsStr>, V: AsRef<OsStr>>(key: K, value: V) {
@@ -424,12 +420,8 @@ pub unsafe fn set_var<K: AsRef<OsStr>, V: AsRef<OsStr>>(key: K, value: V) {
/// }
/// assert!(env::var(key).is_err());
/// ```
-#[cfg_attr(bootstrap, rustc_deprecated_safe_2024)]
-#[cfg_attr(
- not(bootstrap),
- rustc_deprecated_safe_2024(
- audit_that = "the environment access only happens in single-threaded code"
- )
+#[rustc_deprecated_safe_2024(
+ audit_that = "the environment access only happens in single-threaded code"
)]
#[stable(feature = "env", since = "1.0.0")]
pub unsafe fn remove_var<K: AsRef<OsStr>>(key: K) {
diff --git a/library/std/src/ffi/os_str.rs b/library/std/src/ffi/os_str.rs
index 918eec2..99bea67 100644
--- a/library/std/src/ffi/os_str.rs
+++ b/library/std/src/ffi/os_str.rs
@@ -852,7 +852,7 @@ pub fn to_str(&self) -> Option<&str> {
/// Converts an `OsStr` to a <code>[Cow]<[str]></code>.
///
- /// Any non-Unicode sequences are replaced with
+ /// Any non-UTF-8 sequences are replaced with
/// [`U+FFFD REPLACEMENT CHARACTER`][U+FFFD].
///
/// [U+FFFD]: crate::char::REPLACEMENT_CHARACTER
diff --git a/library/std/src/fs/tests.rs b/library/std/src/fs/tests.rs
index 13028c4..fb8dd2b 100644
--- a/library/std/src/fs/tests.rs
+++ b/library/std/src/fs/tests.rs
@@ -1,7 +1,5 @@
use rand::RngCore;
-#[cfg(target_os = "macos")]
-use crate::ffi::{c_char, c_int};
use crate::fs::{self, File, FileTimes, OpenOptions};
use crate::io::prelude::*;
use crate::io::{BorrowedBuf, ErrorKind, SeekFrom};
@@ -16,8 +14,6 @@
use crate::os::windows::fs::{junction_point, symlink_dir, symlink_file, OpenOptionsExt};
use crate::path::Path;
use crate::sync::Arc;
-#[cfg(target_os = "macos")]
-use crate::sys::weak::weak;
use crate::sys_common::io::test::{tmpdir, TempDir};
use crate::time::{Duration, Instant, SystemTime};
use crate::{env, str, thread};
@@ -80,17 +76,6 @@ pub fn got_symlink_permission(tmpdir: &TempDir) -> bool {
}
}
-#[cfg(target_os = "macos")]
-fn able_to_not_follow_symlinks_while_hard_linking() -> bool {
- weak!(fn linkat(c_int, *const c_char, c_int, *const c_char, c_int) -> c_int);
- linkat.get().is_some()
-}
-
-#[cfg(not(target_os = "macos"))]
-fn able_to_not_follow_symlinks_while_hard_linking() -> bool {
- return true;
-}
-
#[test]
fn file_test_io_smoke_test() {
let message = "it's alright. have a good time";
@@ -1456,9 +1441,6 @@ fn symlink_hard_link() {
if !got_symlink_permission(&tmpdir) {
return;
};
- if !able_to_not_follow_symlinks_while_hard_linking() {
- return;
- }
// Create "file", a file.
check!(fs::File::create(tmpdir.join("file")));
diff --git a/library/std/src/io/error.rs b/library/std/src/io/error.rs
index e8ae1d9..6ecd946 100644
--- a/library/std/src/io/error.rs
+++ b/library/std/src/io/error.rs
@@ -223,10 +223,10 @@ pub enum ErrorKind {
#[stable(feature = "rust1", since = "1.0.0")]
ConnectionReset,
/// The remote host is not reachable.
- #[unstable(feature = "io_error_more", issue = "86442")]
+ #[stable(feature = "io_error_a_bit_more", since = "CURRENT_RUSTC_VERSION")]
HostUnreachable,
/// The network containing the remote host is not reachable.
- #[unstable(feature = "io_error_more", issue = "86442")]
+ #[stable(feature = "io_error_a_bit_more", since = "CURRENT_RUSTC_VERSION")]
NetworkUnreachable,
/// The connection was aborted (terminated) by the remote server.
#[stable(feature = "rust1", since = "1.0.0")]
@@ -243,7 +243,7 @@ pub enum ErrorKind {
#[stable(feature = "rust1", since = "1.0.0")]
AddrNotAvailable,
/// The system's networking is down.
- #[unstable(feature = "io_error_more", issue = "86442")]
+ #[stable(feature = "io_error_a_bit_more", since = "CURRENT_RUSTC_VERSION")]
NetworkDown,
/// The operation failed because a pipe was closed.
#[stable(feature = "rust1", since = "1.0.0")]
@@ -259,18 +259,18 @@ pub enum ErrorKind {
///
/// For example, a filesystem path was specified where one of the intermediate directory
/// components was, in fact, a plain file.
- #[unstable(feature = "io_error_more", issue = "86442")]
+ #[stable(feature = "io_error_a_bit_more", since = "CURRENT_RUSTC_VERSION")]
NotADirectory,
/// The filesystem object is, unexpectedly, a directory.
///
/// A directory was specified when a non-directory was expected.
- #[unstable(feature = "io_error_more", issue = "86442")]
+ #[stable(feature = "io_error_a_bit_more", since = "CURRENT_RUSTC_VERSION")]
IsADirectory,
/// A non-empty directory was specified where an empty directory was expected.
- #[unstable(feature = "io_error_more", issue = "86442")]
+ #[stable(feature = "io_error_a_bit_more", since = "CURRENT_RUSTC_VERSION")]
DirectoryNotEmpty,
/// The filesystem or storage medium is read-only, but a write operation was attempted.
- #[unstable(feature = "io_error_more", issue = "86442")]
+ #[stable(feature = "io_error_a_bit_more", since = "CURRENT_RUSTC_VERSION")]
ReadOnlyFilesystem,
/// Loop in the filesystem or IO subsystem; often, too many levels of symbolic links.
///
@@ -285,7 +285,7 @@ pub enum ErrorKind {
///
/// With some network filesystems, notably NFS, an open file (or directory) can be invalidated
/// by problems with the network or server.
- #[unstable(feature = "io_error_more", issue = "86442")]
+ #[stable(feature = "io_error_a_bit_more", since = "CURRENT_RUSTC_VERSION")]
StaleNetworkFileHandle,
/// A parameter was incorrect.
#[stable(feature = "rust1", since = "1.0.0")]
@@ -319,13 +319,13 @@ pub enum ErrorKind {
/// The underlying storage (typically, a filesystem) is full.
///
/// This does not include out of quota errors.
- #[unstable(feature = "io_error_more", issue = "86442")]
+ #[stable(feature = "io_error_a_bit_more", since = "CURRENT_RUSTC_VERSION")]
StorageFull,
/// Seek on unseekable file.
///
/// Seeking was attempted on an open file handle which is not suitable for seeking - for
/// example, on Unix, a named pipe opened with `File::open`.
- #[unstable(feature = "io_error_more", issue = "86442")]
+ #[stable(feature = "io_error_a_bit_more", since = "CURRENT_RUSTC_VERSION")]
NotSeekable,
/// Filesystem quota was exceeded.
#[unstable(feature = "io_error_more", issue = "86442")]
@@ -335,22 +335,22 @@ pub enum ErrorKind {
/// This might arise from a hard limit of the underlying filesystem or file access API, or from
/// an administratively imposed resource limitation. Simple disk full, and out of quota, have
/// their own errors.
- #[unstable(feature = "io_error_more", issue = "86442")]
+ #[stable(feature = "io_error_a_bit_more", since = "CURRENT_RUSTC_VERSION")]
FileTooLarge,
/// Resource is busy.
- #[unstable(feature = "io_error_more", issue = "86442")]
+ #[stable(feature = "io_error_a_bit_more", since = "CURRENT_RUSTC_VERSION")]
ResourceBusy,
/// Executable file is busy.
///
/// An attempt was made to write to a file which is also in use as a running program. (Not all
/// operating systems detect this situation.)
- #[unstable(feature = "io_error_more", issue = "86442")]
+ #[stable(feature = "io_error_a_bit_more", since = "CURRENT_RUSTC_VERSION")]
ExecutableFileBusy,
/// Deadlock (avoided).
///
/// A file locking operation would result in deadlock. This situation is typically detected, if
/// at all, on a best-effort basis.
- #[unstable(feature = "io_error_more", issue = "86442")]
+ #[stable(feature = "io_error_a_bit_more", since = "CURRENT_RUSTC_VERSION")]
Deadlock,
/// Cross-device or cross-filesystem (hard) link or rename.
#[unstable(feature = "io_error_more", issue = "86442")]
@@ -358,7 +358,7 @@ pub enum ErrorKind {
/// Too many (hard) links to the same filesystem object.
///
/// The filesystem does not support making so many hardlinks to the same file.
- #[unstable(feature = "io_error_more", issue = "86442")]
+ #[stable(feature = "io_error_a_bit_more", since = "CURRENT_RUSTC_VERSION")]
TooManyLinks,
/// A filename was invalid.
///
@@ -369,7 +369,7 @@ pub enum ErrorKind {
///
/// When trying to run an external program, a system or process limit on the size of the
/// arguments would have been exceeded.
- #[unstable(feature = "io_error_more", issue = "86442")]
+ #[stable(feature = "io_error_a_bit_more", since = "CURRENT_RUSTC_VERSION")]
ArgumentListTooLong,
/// This operation was interrupted.
///
diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs
index 606d756..60969af 100644
--- a/library/std/src/lib.rs
+++ b/library/std/src/lib.rs
@@ -272,7 +272,6 @@
//
// Language features:
// tidy-alphabetical-start
-#![cfg_attr(bootstrap, feature(min_exhaustive_patterns))]
#![feature(alloc_error_handler)]
#![feature(allocator_internals)]
#![feature(allow_internal_unsafe)]
diff --git a/library/std/src/os/unix/process.rs b/library/std/src/os/unix/process.rs
index 4620244..9aadd94 100644
--- a/library/std/src/os/unix/process.rs
+++ b/library/std/src/os/unix/process.rs
@@ -118,11 +118,7 @@ unsafe fn pre_exec<F>(&mut self, f: F) -> &mut process::Command
/// [`pre_exec`]: CommandExt::pre_exec
#[stable(feature = "process_exec", since = "1.15.0")]
#[deprecated(since = "1.37.0", note = "should be unsafe, use `pre_exec` instead")]
- #[cfg_attr(bootstrap, rustc_deprecated_safe_2024)]
- #[cfg_attr(
- not(bootstrap),
- rustc_deprecated_safe_2024(audit_that = "the closure is async-signal-safe")
- )]
+ #[rustc_deprecated_safe_2024(audit_that = "the closure is async-signal-safe")]
unsafe fn before_exec<F>(&mut self, f: F) -> &mut process::Command
where
F: FnMut() -> io::Result<()> + Send + Sync + 'static,
diff --git a/library/std/src/panicking.rs b/library/std/src/panicking.rs
index 1c972d3..336e34d 100644
--- a/library/std/src/panicking.rs
+++ b/library/std/src/panicking.rs
@@ -23,8 +23,8 @@
use crate::panic::{BacktraceStyle, PanicHookInfo};
use crate::sync::atomic::{AtomicBool, Ordering};
use crate::sync::{PoisonError, RwLock};
-use crate::sys::backtrace;
use crate::sys::stdio::panic_output;
+use crate::sys::{backtrace, dbg};
use crate::{fmt, intrinsics, process, thread};
// Binary interface to the panic runtime that the standard library depends on.
@@ -859,6 +859,14 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
#[cfg_attr(not(test), rustc_std_internal_symbol)]
#[cfg(not(feature = "panic_immediate_abort"))]
fn rust_panic(msg: &mut dyn PanicPayload) -> ! {
+ // Break into the debugger if it is attached.
+ // The return value is not currently used.
+ //
+ // This function isn't used anywhere else, and
+ // using inside `#[panic_handler]` doesn't seem
+ // to count, so a warning is issued.
+ let _ = dbg::breakpoint_if_debugging();
+
let code = unsafe { __rust_start_panic(msg) };
rtabort!("failed to initiate panic, error {code}")
}
@@ -866,6 +874,14 @@ fn rust_panic(msg: &mut dyn PanicPayload) -> ! {
#[cfg_attr(not(test), rustc_std_internal_symbol)]
#[cfg(feature = "panic_immediate_abort")]
fn rust_panic(_: &mut dyn PanicPayload) -> ! {
+ // Break into the debugger if it is attached.
+ // The return value is not currently used.
+ //
+ // This function isn't used anywhere else, and
+ // using inside `#[panic_handler]` doesn't seem
+ // to count, so a warning is issued.
+ let _ = dbg::breakpoint_if_debugging();
+
unsafe {
crate::intrinsics::abort();
}
diff --git a/library/std/src/path.rs b/library/std/src/path.rs
index 9eaa0e0..506ad44 100644
--- a/library/std/src/path.rs
+++ b/library/std/src/path.rs
@@ -2200,7 +2200,7 @@ pub fn to_str(&self) -> Option<&str> {
/// Converts a `Path` to a [`Cow<str>`].
///
- /// Any non-Unicode sequences are replaced with
+ /// Any non-UTF-8 sequences are replaced with
/// [`U+FFFD REPLACEMENT CHARACTER`][U+FFFD].
///
/// [U+FFFD]: super::char::REPLACEMENT_CHARACTER
diff --git a/library/std/src/sync/condvar.rs b/library/std/src/sync/condvar.rs
index 08d46f3..e41cbc1 100644
--- a/library/std/src/sync/condvar.rs
+++ b/library/std/src/sync/condvar.rs
@@ -195,8 +195,11 @@ pub fn wait<'a, T>(&self, guard: MutexGuard<'a, T>) -> LockResult<MutexGuard<'a,
if poisoned { Err(PoisonError::new(guard)) } else { Ok(guard) }
}
- /// Blocks the current thread until this condition variable receives a
- /// notification and the provided condition is false.
+ /// Blocks the current thread until the provided condition becomes false.
+ ///
+ /// `condition` is checked immediately; if not met (returns `true`), this
+ /// will [`wait`] for the next notification then check again. This repeats
+ /// until `condition` returns `false`, in which case this function returns.
///
/// This function will atomically unlock the mutex specified (represented by
/// `guard`) and block the current thread. This means that any calls
@@ -210,6 +213,7 @@ pub fn wait<'a, T>(&self, guard: MutexGuard<'a, T>) -> LockResult<MutexGuard<'a,
/// poisoned when this thread re-acquires the lock. For more information,
/// see information about [poisoning] on the [`Mutex`] type.
///
+ /// [`wait`]: Self::wait
/// [`notify_one`]: Self::notify_one
/// [`notify_all`]: Self::notify_all
/// [poisoning]: super::Mutex#poisoning
diff --git a/library/std/src/sys/dbg.rs b/library/std/src/sys/dbg.rs
new file mode 100644
index 0000000..a6e78db
--- /dev/null
+++ b/library/std/src/sys/dbg.rs
@@ -0,0 +1,229 @@
+//! Debugging aids.
+
+/// Presence of a debugger. The debugger being concerned
+/// is expected to use the OS API to debug this process.
+#[derive(Copy, Clone, Debug)]
+#[allow(unused)]
+pub(crate) enum DebuggerPresence {
+ /// The debugger is attached to this process.
+ Detected,
+ /// The debugger is not attached to this process.
+ NotDetected,
+}
+
+#[cfg(target_os = "windows")]
+mod os {
+ use super::DebuggerPresence;
+
+ #[link(name = "kernel32")]
+ extern "system" {
+ fn IsDebuggerPresent() -> i32;
+ }
+
+ pub(super) fn is_debugger_present() -> Option<DebuggerPresence> {
+ // SAFETY: No state is shared between threads. The call reads
+ // a field from the Thread Environment Block using the OS API
+ // as required by the documentation.
+ if unsafe { IsDebuggerPresent() } != 0 {
+ Some(DebuggerPresence::Detected)
+ } else {
+ Some(DebuggerPresence::NotDetected)
+ }
+ }
+}
+
+#[cfg(any(target_vendor = "apple", target_os = "freebsd"))]
+mod os {
+ use libc::{c_int, sysctl, CTL_KERN, KERN_PROC, KERN_PROC_PID};
+
+ use super::DebuggerPresence;
+ use crate::io::{Cursor, Read, Seek, SeekFrom};
+ use crate::process;
+
+ const P_TRACED: i32 = 0x00000800;
+
+ // The assumption is that the kernel structures available to the
+ // user space may not shrink or repurpose the existing fields over
+ // time. The kernels normally adhere to that for the backward
+ // compatibility of the user space.
+
+ // The macOS 14.5 SDK comes with a header `MacOSX14.5.sdk/usr/include/sys/sysctl.h`
+ // that defines `struct kinfo_proc` be of `648` bytes on the 64-bit system. That has
+ // not changed since macOS 10.13 (released in 2017) at least, validated by building
+ // a C program in XCode while changing the build target. Apple provides this example
+ // for reference: https://developer.apple.com/library/archive/qa/qa1361/_index.html.
+ #[cfg(target_vendor = "apple")]
+ const KINFO_PROC_SIZE: usize = if cfg!(target_pointer_width = "64") { 648 } else { 492 };
+ #[cfg(target_vendor = "apple")]
+ const KINFO_PROC_FLAGS_OFFSET: u64 = if cfg!(target_pointer_width = "64") { 32 } else { 16 };
+
+ // Works for FreeBSD stable (13.3, 13.4) and current (14.0, 14.1).
+ // The size of the structure has stayed the same for a long time,
+ // at least since 2005:
+ // https://lists.freebsd.org/pipermail/freebsd-stable/2005-November/019899.html
+ #[cfg(target_os = "freebsd")]
+ const KINFO_PROC_SIZE: usize = if cfg!(target_pointer_width = "64") { 1088 } else { 768 };
+ #[cfg(target_os = "freebsd")]
+ const KINFO_PROC_FLAGS_OFFSET: u64 = if cfg!(target_pointer_width = "64") { 368 } else { 296 };
+
+ pub(super) fn is_debugger_present() -> Option<DebuggerPresence> {
+ debug_assert_ne!(KINFO_PROC_SIZE, 0);
+
+ let mut flags = [0u8; 4]; // `ki_flag` under FreeBSD and `p_flag` under macOS.
+ let mut mib = [CTL_KERN, KERN_PROC, KERN_PROC_PID, process::id() as c_int];
+ let mut info_size = KINFO_PROC_SIZE;
+ let mut kinfo_proc = [0u8; KINFO_PROC_SIZE];
+
+ // SAFETY: No state is shared with other threads. The sysctl call
+ // is safe according to the documentation.
+ if unsafe {
+ sysctl(
+ mib.as_mut_ptr(),
+ mib.len() as u32,
+ kinfo_proc.as_mut_ptr().cast(),
+ &mut info_size,
+ core::ptr::null_mut(),
+ 0,
+ )
+ } != 0
+ {
+ return None;
+ }
+ debug_assert_eq!(info_size, KINFO_PROC_SIZE);
+
+ let mut reader = Cursor::new(kinfo_proc);
+ reader.seek(SeekFrom::Start(KINFO_PROC_FLAGS_OFFSET)).ok()?;
+ reader.read_exact(&mut flags).ok()?;
+ // Just in case, not limiting this to the little-endian systems.
+ let flags = i32::from_ne_bytes(flags);
+
+ if flags & P_TRACED != 0 {
+ Some(DebuggerPresence::Detected)
+ } else {
+ Some(DebuggerPresence::NotDetected)
+ }
+ }
+}
+
+#[cfg(target_os = "linux")]
+mod os {
+ use super::DebuggerPresence;
+ use crate::fs::File;
+ use crate::io::Read;
+
+ pub(super) fn is_debugger_present() -> Option<DebuggerPresence> {
+ // This function is crafted with the following goals:
+ // * Memory efficiency: It avoids crashing the panicking process due to
+ // out-of-memory (OOM) conditions by not using large heap buffers or
+ // allocating significant stack space, which could lead to stack overflow.
+ // * Minimal binary size: The function uses a minimal set of facilities
+ // from the standard library to avoid increasing the resulting binary size.
+ //
+ // To achieve these goals, the function does not use `[std::io::BufReader]`
+ // and instead reads the file byte by byte using a sliding window approach.
+ // It's important to note that the "/proc/self/status" pseudo-file is synthesized
+ // by the Virtual File System (VFS), meaning it is not read from a slow or
+ // non-volatile storage medium so buffering might not be as beneficial because
+ // all data is read from memory, though this approach does incur a syscall for
+ // each byte read.
+ //
+ // We cannot make assumptions about the file size or the position of the
+ // target prefix ("TracerPid:"), so the function does not use
+ // `[std::fs::read_to_string]` thus not employing UTF-8 to ASCII checking,
+ // conversion, or parsing as we're looking for an ASCII prefix.
+ //
+ // These condiderations make the function deviate from the familiar concise pattern
+ // of searching for a string in a text file.
+
+ fn read_byte(file: &mut File) -> Option<u8> {
+ let mut buffer = [0];
+ file.read_exact(&mut buffer).ok()?;
+ Some(buffer[0])
+ }
+
+ // The ASCII prefix of the datum we're interested in.
+ const TRACER_PID: &[u8] = b"TracerPid:\t";
+
+ let mut file = File::open("/proc/self/status").ok()?;
+ let mut matched = 0;
+
+ // Look for the `TRACER_PID` prefix.
+ while let Some(byte) = read_byte(&mut file) {
+ if byte == TRACER_PID[matched] {
+ matched += 1;
+ if matched == TRACER_PID.len() {
+ break;
+ }
+ } else {
+ matched = 0;
+ }
+ }
+
+ // Was the prefix found?
+ if matched != TRACER_PID.len() {
+ return None;
+ }
+
+ // It was; get the ASCII representation of the first digit
+ // of the PID. That is enough to see if there is a debugger
+ // attached as the kernel does not pad the PID on the left
+ // with the leading zeroes.
+ let byte = read_byte(&mut file)?;
+ if byte.is_ascii_digit() && byte != b'0' {
+ Some(DebuggerPresence::Detected)
+ } else {
+ Some(DebuggerPresence::NotDetected)
+ }
+ }
+}
+
+#[cfg(not(any(
+ target_os = "windows",
+ target_vendor = "apple",
+ target_os = "freebsd",
+ target_os = "linux"
+)))]
+mod os {
+ pub(super) fn is_debugger_present() -> Option<super::DebuggerPresence> {
+ None
+ }
+}
+
+/// Detect the debugger presence.
+///
+/// The code does not try to detect the debugger at all costs (e.g., when anti-debugger
+/// tricks are at play), it relies on the interfaces provided by the OS.
+///
+/// Return value:
+/// * `None`: it's not possible to conclude whether the debugger is attached to this
+/// process or not. When checking for the presence of the debugger, the detection logic
+/// encountered an issue, such as the OS API throwing an error or the feature not being
+/// implemented.
+/// * `Some(DebuggerPresence::Detected)`: yes, the debugger is attached
+/// to this process.
+/// * `Some(DebuggerPresence::NotDetected)`: no, the debugger is not
+/// attached to this process.
+pub(crate) fn is_debugger_present() -> Option<DebuggerPresence> {
+ if cfg!(miri) { None } else { os::is_debugger_present() }
+}
+
+/// Execute the breakpoint instruction if the debugger presence is detected.
+/// Useful for breaking into the debugger without the need to set a breakpoint
+/// in the debugger.
+///
+/// Note that there is a race between attaching or detaching the debugger, and running the
+/// breakpoint instruction. This is nonetheless memory-safe, like [`crate::process::abort`]
+/// is. In case the debugger is attached and the function is about
+/// to run the breakpoint instruction yet right before that the debugger detaches, the
+/// process will crash due to running the breakpoint instruction and the debugger not
+/// handling the trap exception.
+pub(crate) fn breakpoint_if_debugging() -> Option<DebuggerPresence> {
+ let debugger_present = is_debugger_present();
+ if let Some(DebuggerPresence::Detected) = debugger_present {
+ // SAFETY: Executing the breakpoint instruction. No state is shared
+ // or modified by this code.
+ unsafe { core::intrinsics::breakpoint() };
+ }
+
+ debugger_present
+}
diff --git a/library/std/src/sys/mod.rs b/library/std/src/sys/mod.rs
index 1ef17dd..96d6f2c 100644
--- a/library/std/src/sys/mod.rs
+++ b/library/std/src/sys/mod.rs
@@ -11,6 +11,7 @@
pub mod anonymous_pipe;
pub mod backtrace;
pub mod cmath;
+pub mod dbg;
pub mod exit_guard;
pub mod os_str;
pub mod path;
diff --git a/library/std/src/sys/pal/unix/linux/pidfd.rs b/library/std/src/sys/pal/unix/linux/pidfd.rs
index 7474f80..7874443 100644
--- a/library/std/src/sys/pal/unix/linux/pidfd.rs
+++ b/library/std/src/sys/pal/unix/linux/pidfd.rs
@@ -13,7 +13,7 @@
impl PidFd {
pub fn kill(&self) -> io::Result<()> {
- return cvt(unsafe {
+ cvt(unsafe {
libc::syscall(
libc::SYS_pidfd_send_signal,
self.0.as_raw_fd(),
@@ -22,7 +22,7 @@ pub fn kill(&self) -> io::Result<()> {
0,
)
})
- .map(drop);
+ .map(drop)
}
pub fn wait(&self) -> io::Result<ExitStatus> {
@@ -30,7 +30,7 @@ pub fn wait(&self) -> io::Result<ExitStatus> {
cvt(unsafe {
libc::waitid(libc::P_PIDFD, self.0.as_raw_fd() as u32, &mut siginfo, libc::WEXITED)
})?;
- return Ok(ExitStatus::from_waitid_siginfo(siginfo));
+ Ok(ExitStatus::from_waitid_siginfo(siginfo))
}
pub fn try_wait(&self) -> io::Result<Option<ExitStatus>> {
@@ -45,9 +45,10 @@ pub fn try_wait(&self) -> io::Result<Option<ExitStatus>> {
)
})?;
if unsafe { siginfo.si_pid() } == 0 {
- return Ok(None);
+ Ok(None)
+ } else {
+ Ok(Some(ExitStatus::from_waitid_siginfo(siginfo)))
}
- return Ok(Some(ExitStatus::from_waitid_siginfo(siginfo)));
}
}
diff --git a/library/std/src/sys/pal/unix/stack_overflow.rs b/library/std/src/sys/pal/unix/stack_overflow.rs
index 9ff44b5..728ce8d 100644
--- a/library/std/src/sys/pal/unix/stack_overflow.rs
+++ b/library/std/src/sys/pal/unix/stack_overflow.rs
@@ -32,7 +32,8 @@ fn drop(&mut self) {
target_os = "macos",
target_os = "netbsd",
target_os = "openbsd",
- target_os = "solaris"
+ target_os = "solaris",
+ target_os = "illumos",
))]
mod imp {
#[cfg(not(all(target_os = "linux", target_env = "gnu")))]
@@ -280,7 +281,7 @@ fn sigstack_size() -> usize {
libc::SIGSTKSZ
}
- #[cfg(target_os = "solaris")]
+ #[cfg(any(target_os = "solaris", target_os = "illumos"))]
unsafe fn get_stack_start() -> Option<*mut libc::c_void> {
let mut current_stack: libc::stack_t = crate::mem::zeroed();
assert_eq!(libc::stack_getbounds(&mut current_stack), 0);
@@ -486,7 +487,12 @@ unsafe fn install_main_guard_default(page_size: usize) -> Option<Range<usize>> {
Some(guardaddr..guardaddr + page_size)
}
- #[cfg(any(target_os = "macos", target_os = "openbsd", target_os = "solaris"))]
+ #[cfg(any(
+ target_os = "macos",
+ target_os = "openbsd",
+ target_os = "solaris",
+ target_os = "illumos",
+ ))]
// FIXME: I am probably not unsafe.
unsafe fn current_guard() -> Option<Range<usize>> {
let stackptr = get_stack_start()?;
@@ -569,7 +575,8 @@ unsafe fn current_guard() -> Option<Range<usize>> {
target_os = "macos",
target_os = "netbsd",
target_os = "openbsd",
- target_os = "solaris"
+ target_os = "solaris",
+ target_os = "illumos",
)))]
mod imp {
pub unsafe fn init() {}
diff --git a/library/std/src/sys/pal/wasi/fs.rs b/library/std/src/sys/pal/wasi/fs.rs
index 88b1e54..e1c61ca 100644
--- a/library/std/src/sys/pal/wasi/fs.rs
+++ b/library/std/src/sys/pal/wasi/fs.rs
@@ -265,7 +265,7 @@ impl OpenOptions {
pub fn new() -> OpenOptions {
let mut base = OpenOptions::default();
base.dirflags = wasi::LOOKUPFLAGS_SYMLINK_FOLLOW;
- return base;
+ base
}
pub fn read(&mut self, read: bool) {
@@ -382,7 +382,7 @@ fn rights_base(&self) -> wasi::Rights {
base |= wasi::RIGHTS_PATH_UNLINK_FILE;
base |= wasi::RIGHTS_POLL_FD_READWRITE;
- return base;
+ base
}
fn rights_inheriting(&self) -> wasi::Rights {
diff --git a/library/std/src/sys/pal/wasi/helpers.rs b/library/std/src/sys/pal/wasi/helpers.rs
index d047bf2..37ef178 100644
--- a/library/std/src/sys/pal/wasi/helpers.rs
+++ b/library/std/src/sys/pal/wasi/helpers.rs
@@ -115,7 +115,7 @@ pub fn hashmap_random_keys() -> (u64, u64) {
let len = mem::size_of_val(&ret);
wasi::random_get(base, len).expect("random_get failure");
}
- return ret;
+ ret
}
#[inline]
diff --git a/library/std/src/thread/mod.rs b/library/std/src/thread/mod.rs
index e29c28f..0fc63c5 100644
--- a/library/std/src/thread/mod.rs
+++ b/library/std/src/thread/mod.rs
@@ -432,7 +432,7 @@ pub fn spawn<F, T>(self, f: F) -> io::Result<JoinHandle<T>>
/// ```
///
/// [`io::Result`]: crate::io::Result
- #[stable(feature = "thread_spawn_unchecked", since = "CURRENT_RUSTC_VERSION")]
+ #[stable(feature = "thread_spawn_unchecked", since = "1.82.0")]
pub unsafe fn spawn_unchecked<F, T>(self, f: F) -> io::Result<JoinHandle<T>>
where
F: FnOnce() -> T,
diff --git a/library/windows_targets/src/lib.rs b/library/windows_targets/src/lib.rs
index 1965b6c..395cd6a4 100644
--- a/library/windows_targets/src/lib.rs
+++ b/library/windows_targets/src/lib.rs
@@ -38,4 +38,5 @@
#[link(name = "ntdll")]
#[link(name = "userenv")]
#[link(name = "ws2_32")]
+#[link(name = "dbghelp")] // required for backtrace-rs symbolization
extern "C" {}
diff --git a/src/bootstrap/bootstrap.py b/src/bootstrap/bootstrap.py
index 71f69e0..666df490 100644
--- a/src/bootstrap/bootstrap.py
+++ b/src/bootstrap/bootstrap.py
@@ -106,22 +106,29 @@
try:
if (probably_big or verbose) and "GITHUB_ACTIONS" not in os.environ:
- option = "-#"
+ option = "--progress-bar"
else:
- option = "-s"
+ option = "--silent"
# If curl is not present on Win32, we should not sys.exit
# but raise `CalledProcessError` or `OSError` instead
require(["curl", "--version"], exception=platform_is_win32())
extra_flags = []
if curl_version() > (7, 70):
extra_flags = [ "--retry-all-errors" ]
+ # options should be kept in sync with
+ # src/bootstrap/src/core/download.rs
+ # for consistency.
+ # they are also more compreprensivly explained in that file.
run(["curl", option] + extra_flags + [
- "-L", # Follow redirect.
- "-y", "30", "-Y", "10", # timeout if speed is < 10 bytes/sec for > 30 seconds
- "--connect-timeout", "30", # timeout if cannot connect within 30 seconds
- "-o", path,
+ # Follow redirect.
+ "--location",
+ # timeout if speed is < 10 bytes/sec for > 30 seconds
+ "--speed-time", "30", "--speed-limit", "10",
+ # timeout if cannot connect within 30 seconds
+ "--connect-timeout", "30",
+ "--output", path,
"--continue-at", "-",
- "--retry", "3", "-SRf", url],
+ "--retry", "3", "--show-error", "--remote-time", "--fail", url],
verbose=verbose,
exception=True, # Will raise RuntimeError on failure
)
diff --git a/src/bootstrap/configure.py b/src/bootstrap/configure.py
index 768aac9..49d5646 100755
--- a/src/bootstrap/configure.py
+++ b/src/bootstrap/configure.py
@@ -71,6 +71,7 @@
# channel, etc.
o("optimize-llvm", "llvm.optimize", "build optimized LLVM")
o("llvm-assertions", "llvm.assertions", "build LLVM with assertions")
+o("llvm-enzyme", "llvm.enzyme", "build LLVM with enzyme")
o("llvm-plugins", "llvm.plugins", "build LLVM with plugin interface")
o("debug-assertions", "rust.debug-assertions", "build with debugging assertions")
o("debug-assertions-std", "rust.debug-assertions-std", "build the standard library with debugging assertions")
diff --git a/src/bootstrap/defaults/config.compiler.toml b/src/bootstrap/defaults/config.compiler.toml
index 789586b..147939d2 100644
--- a/src/bootstrap/defaults/config.compiler.toml
+++ b/src/bootstrap/defaults/config.compiler.toml
@@ -27,4 +27,5 @@
# Enable warnings during the LLVM compilation (when LLVM is changed, causing a compilation)
enable-warnings = true
# Will download LLVM from CI if available on your platform.
-download-ci-llvm = "if-unchanged"
+# If you intend to modify `src/llvm-project`, use `"if-unchanged"` or `false` instead.
+download-ci-llvm = true
diff --git a/src/bootstrap/download-ci-llvm-stamp b/src/bootstrap/download-ci-llvm-stamp
index 9090153..42cecbf 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/129116
+Last change is for: https://github.com/rust-lang/rust/pull/129788
diff --git a/src/bootstrap/src/core/build_steps/check.rs b/src/bootstrap/src/core/build_steps/check.rs
index 7f7faf0..ba12e64 100644
--- a/src/bootstrap/src/core/build_steps/check.rs
+++ b/src/bootstrap/src/core/build_steps/check.rs
@@ -228,7 +228,7 @@ fn run(self, builder: &Builder<'_>) {
self.override_build_kind.unwrap_or(builder.kind),
);
- rustc_cargo(builder, &mut cargo, target, &compiler);
+ rustc_cargo(builder, &mut cargo, target, &compiler, &self.crates);
// 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/clippy.rs b/src/bootstrap/src/core/build_steps/clippy.rs
index a2bb03c..a099235 100644
--- a/src/bootstrap/src/core/build_steps/clippy.rs
+++ b/src/bootstrap/src/core/build_steps/clippy.rs
@@ -197,7 +197,7 @@ fn run(self, builder: &Builder<'_>) {
Kind::Clippy,
);
- rustc_cargo(builder, &mut cargo, target, &compiler);
+ rustc_cargo(builder, &mut cargo, target, &compiler, &self.crates);
// Explicitly pass -p for all compiler crates -- this will force cargo
// to also lint the tests/benches/examples for these crates, rather
diff --git a/src/bootstrap/src/core/build_steps/compile.rs b/src/bootstrap/src/core/build_steps/compile.rs
index eef5480..102c9fd 100644
--- a/src/bootstrap/src/core/build_steps/compile.rs
+++ b/src/bootstrap/src/core/build_steps/compile.rs
@@ -931,7 +931,12 @@ fn run(self, builder: &Builder<'_>) -> u32 {
// NOTE: the ABI of the beta compiler is different from the ABI of the downloaded compiler,
// so its artifacts can't be reused.
if builder.download_rustc() && compiler.stage != 0 {
- builder.ensure(Sysroot { compiler, force_recompile: false });
+ let sysroot = builder.ensure(Sysroot { compiler, force_recompile: false });
+ cp_rustc_component_to_ci_sysroot(
+ builder,
+ &sysroot,
+ builder.config.ci_rustc_dev_contents(),
+ );
return compiler.stage;
}
@@ -983,7 +988,7 @@ fn run(self, builder: &Builder<'_>) -> u32 {
Kind::Build,
);
- rustc_cargo(builder, &mut cargo, target, &compiler);
+ rustc_cargo(builder, &mut cargo, target, &compiler, &self.crates);
// NB: all RUSTFLAGS should be added to `rustc_cargo()` so they will be
// consistently applied by check/doc/test modes too.
@@ -1042,10 +1047,11 @@ pub fn rustc_cargo(
cargo: &mut Cargo,
target: TargetSelection,
compiler: &Compiler,
+ crates: &[String],
) {
cargo
.arg("--features")
- .arg(builder.rustc_features(builder.kind, target))
+ .arg(builder.rustc_features(builder.kind, target, crates))
.arg("--manifest-path")
.arg(builder.src.join("compiler/rustc/Cargo.toml"));
@@ -1189,6 +1195,10 @@ pub fn rustc_cargo_env(
cargo.env("RUSTC_VERIFY_LLVM_IR", "1");
}
+ if builder.config.llvm_enzyme {
+ cargo.rustflag("--cfg=llvm_enzyme");
+ }
+
// Note that this is disabled if LLVM itself is disabled or we're in a check
// build. If we are in a check build we still go ahead here presuming we've
// detected that LLVM is already built and good to go which helps prevent
@@ -1784,6 +1794,24 @@ fn run(self, builder: &Builder<'_>) -> Compiler {
// use that to bootstrap this compiler forward.
let mut build_compiler = builder.compiler(target_compiler.stage - 1, builder.config.build);
+ // Build enzyme
+ let enzyme_install = if builder.config.llvm_enzyme {
+ Some(builder.ensure(llvm::Enzyme { target: build_compiler.host }))
+ } else {
+ None
+ };
+
+ if let Some(enzyme_install) = enzyme_install {
+ let lib_ext = std::env::consts::DLL_EXTENSION;
+ let src_lib = enzyme_install.join("build/Enzyme/libEnzyme-19").with_extension(lib_ext);
+ let libdir = builder.sysroot_libdir(build_compiler, build_compiler.host);
+ let target_libdir = builder.sysroot_libdir(target_compiler, target_compiler.host);
+ let dst_lib = libdir.join("libEnzyme-19").with_extension(lib_ext);
+ let target_dst_lib = target_libdir.join("libEnzyme-19").with_extension(lib_ext);
+ builder.copy_link(&src_lib, &dst_lib);
+ builder.copy_link(&src_lib, &target_dst_lib);
+ }
+
// Build the libraries for this compiler to link to (i.e., the libraries
// it uses at runtime). NOTE: Crates the target compiler compiles don't
// link to these. (FIXME: Is that correct? It seems to be correct most
@@ -1884,7 +1912,7 @@ fn run(self, builder: &Builder<'_>) -> Compiler {
// delegates to the `rust-lld` binary for linking and then runs
// logic to create the final binary. This is used by the
// `wasm32-wasip2` target of Rust.
- if builder.build_wasm_component_ld() {
+ if builder.tool_enabled("wasm-component-ld") {
let wasm_component_ld_exe =
builder.ensure(crate::core::build_steps::tool::WasmComponentLd {
compiler: build_compiler,
diff --git a/src/bootstrap/src/core/build_steps/dist.rs b/src/bootstrap/src/core/build_steps/dist.rs
index 4957de2..b0bd187 100644
--- a/src/bootstrap/src/core/build_steps/dist.rs
+++ b/src/bootstrap/src/core/build_steps/dist.rs
@@ -473,7 +473,7 @@ fn prepare_image(builder: &Builder<'_>, compiler: Compiler, image: &Path) {
);
}
}
- if builder.build_wasm_component_ld() {
+ if builder.tool_enabled("wasm-component-ld") {
let src_dir = builder.sysroot_libdir(compiler, host).parent().unwrap().join("bin");
let ld = exe("wasm-component-ld", compiler.host);
builder.copy_link(&src_dir.join(&ld), &dst_dir.join(&ld));
@@ -1348,18 +1348,9 @@ fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
return None;
}
- if self.backend == "cranelift" {
- if !target_supports_cranelift_backend(self.compiler.host) {
- builder.info("target not supported by rustc_codegen_cranelift. skipping");
- return None;
- }
-
- if self.compiler.host.is_windows() {
- builder.info(
- "dist currently disabled for windows by rustc_codegen_cranelift. skipping",
- );
- return None;
- }
+ if self.backend == "cranelift" && !target_supports_cranelift_backend(self.compiler.host) {
+ builder.info("target not supported by rustc_codegen_cranelift. skipping");
+ return None;
}
let compiler = self.compiler;
diff --git a/src/bootstrap/src/core/build_steps/doc.rs b/src/bootstrap/src/core/build_steps/doc.rs
index ffb617c..73d9e3f 100644
--- a/src/bootstrap/src/core/build_steps/doc.rs
+++ b/src/bootstrap/src/core/build_steps/doc.rs
@@ -826,7 +826,7 @@ fn run(self, builder: &Builder<'_>) {
// see https://github.com/rust-lang/rust/pull/122066#issuecomment-1983049222
// cargo.rustdocflag("--generate-link-to-definition");
- compile::rustc_cargo(builder, &mut cargo, target, &compiler);
+ compile::rustc_cargo(builder, &mut cargo, target, &compiler, &self.crates);
cargo.arg("-Zskip-rustdoc-fingerprint");
// Only include compiler crates, no dependencies of those, such as `libc`.
@@ -1186,6 +1186,9 @@ fn run(self, builder: &Builder<'_>) {
cmd.arg("--rustc");
cmd.arg(&rustc);
cmd.arg("--rustc-target").arg(self.target.rustc_target_arg());
+ if let Some(target_linker) = builder.linker(self.target) {
+ cmd.arg("--rustc-linker").arg(target_linker);
+ }
if builder.is_verbose() {
cmd.arg("--verbose");
}
diff --git a/src/bootstrap/src/core/build_steps/llvm.rs b/src/bootstrap/src/core/build_steps/llvm.rs
index e1eea31..442638d 100644
--- a/src/bootstrap/src/core/build_steps/llvm.rs
+++ b/src/bootstrap/src/core/build_steps/llvm.rs
@@ -529,6 +529,7 @@ fn run(self, builder: &Builder<'_>) -> LlvmResult {
}
};
+ // FIXME(ZuseZ4): Do we need that for Enzyme too?
// When building LLVM with LLVM_LINK_LLVM_DYLIB for macOS, an unversioned
// libLLVM.dylib will be built. However, llvm-config will still look
// for a versioned path like libLLVM-14.dylib. Manually create a symbolic
@@ -849,6 +850,100 @@ fn get_var(var_base: &str, host: &str, target: &str) -> Option<OsString> {
.or_else(|| env::var_os(var_base))
}
+#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
+pub struct Enzyme {
+ pub target: TargetSelection,
+}
+
+impl Step for Enzyme {
+ type Output = PathBuf;
+ const ONLY_HOSTS: bool = true;
+
+ fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
+ run.path("src/tools/enzyme/enzyme")
+ }
+
+ fn make_run(run: RunConfig<'_>) {
+ run.builder.ensure(Enzyme { target: run.target });
+ }
+
+ /// Compile Enzyme for `target`.
+ fn run(self, builder: &Builder<'_>) -> PathBuf {
+ builder.require_submodule(
+ "src/tools/enzyme",
+ Some("The Enzyme sources are required for autodiff."),
+ );
+ if builder.config.dry_run() {
+ let out_dir = builder.enzyme_out(self.target);
+ return out_dir;
+ }
+ let target = self.target;
+
+ let LlvmResult { llvm_config, .. } = builder.ensure(Llvm { target: self.target });
+
+ static STAMP_HASH_MEMO: OnceLock<String> = OnceLock::new();
+ let smart_stamp_hash = STAMP_HASH_MEMO.get_or_init(|| {
+ generate_smart_stamp_hash(
+ builder,
+ &builder.config.src.join("src/tools/enzyme"),
+ builder.enzyme_info.sha().unwrap_or_default(),
+ )
+ });
+
+ let out_dir = builder.enzyme_out(target);
+ let stamp = out_dir.join("enzyme-finished-building");
+ let stamp = HashStamp::new(stamp, Some(smart_stamp_hash));
+
+ if stamp.is_done() {
+ if stamp.hash.is_none() {
+ builder.info(
+ "Could not determine the Enzyme submodule commit hash. \
+ Assuming that an Enzyme rebuild is not necessary.",
+ );
+ builder.info(&format!(
+ "To force Enzyme to rebuild, remove the file `{}`",
+ stamp.path.display()
+ ));
+ }
+ return out_dir;
+ }
+
+ builder.info(&format!("Building Enzyme for {}", target));
+ t!(stamp.remove());
+ let _time = helpers::timeit(builder);
+ t!(fs::create_dir_all(&out_dir));
+
+ builder
+ .config
+ .update_submodule(Path::new("src").join("tools").join("enzyme").to_str().unwrap());
+ let mut cfg = cmake::Config::new(builder.src.join("src/tools/enzyme/enzyme/"));
+ // FIXME(ZuseZ4): Find a nicer way to use Enzyme Debug builds
+ //cfg.profile("Debug");
+ //cfg.define("CMAKE_BUILD_TYPE", "Debug");
+ configure_cmake(builder, target, &mut cfg, true, LdFlags::default(), &[]);
+
+ // Re-use the same flags as llvm to control the level of debug information
+ // generated for lld.
+ let profile = match (builder.config.llvm_optimize, builder.config.llvm_release_debuginfo) {
+ (false, _) => "Debug",
+ (true, false) => "Release",
+ (true, true) => "RelWithDebInfo",
+ };
+
+ cfg.out_dir(&out_dir)
+ .profile(profile)
+ .env("LLVM_CONFIG_REAL", &llvm_config)
+ .define("LLVM_ENABLE_ASSERTIONS", "ON")
+ .define("ENZYME_EXTERNAL_SHARED_LIB", "ON")
+ .define("LLVM_DIR", builder.llvm_out(target));
+
+ cfg.build();
+
+ t!(stamp.write());
+ out_dir
+ }
+}
+
#[derive(Debug, Clone, Hash, PartialEq, Eq)]
pub struct Lld {
pub target: TargetSelection,
diff --git a/src/bootstrap/src/core/build_steps/test.rs b/src/bootstrap/src/core/build_steps/test.rs
index a8e1254..83f6561 100644
--- a/src/bootstrap/src/core/build_steps/test.rs
+++ b/src/bootstrap/src/core/build_steps/test.rs
@@ -2690,7 +2690,7 @@ fn run(self, builder: &Builder<'_>) {
}
}
Mode::Rustc => {
- compile::rustc_cargo(builder, &mut cargo, target, &compiler);
+ compile::rustc_cargo(builder, &mut cargo, target, &compiler, &self.crates);
}
_ => panic!("can only test libraries"),
};
@@ -3529,11 +3529,13 @@ fn make_run(run: RunConfig<'_>) {
fn run(self, builder: &Builder<'_>) {
let bootstrap_host = builder.config.build;
- let compiler = builder.compiler(0, bootstrap_host);
+ let compiler = builder.compiler(builder.top_stage, bootstrap_host);
let path = self.path.to_str().unwrap();
let crate_name = self.path.components().last().unwrap().as_os_str().to_str().unwrap();
- builder.ensure(compile::Std::new(compiler, self.host));
+ if !builder.download_rustc() {
+ builder.ensure(compile::Std::new(compiler, self.host));
+ }
// Run any unit tests in the crate
let cargo_test = tool::prepare_tool_cargo(
diff --git a/src/bootstrap/src/core/build_steps/tool.rs b/src/bootstrap/src/core/build_steps/tool.rs
index 3a1eb43..3c2d791 100644
--- a/src/bootstrap/src/core/build_steps/tool.rs
+++ b/src/bootstrap/src/core/build_steps/tool.rs
@@ -693,14 +693,7 @@ impl Step for Cargo {
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
let builder = run.builder;
- run.path("src/tools/cargo").default_condition(
- builder.config.extended
- && builder.config.tools.as_ref().map_or(
- true,
- // If `tools` is set, search list for this tool.
- |tools| tools.iter().any(|tool| tool == "cargo"),
- ),
- )
+ run.path("src/tools/cargo").default_condition(builder.tool_enabled("cargo"))
}
fn make_run(run: RunConfig<'_>) {
@@ -772,14 +765,7 @@ impl Step for RustAnalyzer {
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
let builder = run.builder;
- run.path("src/tools/rust-analyzer").default_condition(
- builder.config.extended
- && builder
- .config
- .tools
- .as_ref()
- .map_or(true, |tools| tools.iter().any(|tool| tool == "rust-analyzer")),
- )
+ run.path("src/tools/rust-analyzer").default_condition(builder.tool_enabled("rust-analyzer"))
}
fn make_run(run: RunConfig<'_>) {
@@ -821,12 +807,8 @@ fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
run.path("src/tools/rust-analyzer")
.path("src/tools/rust-analyzer/crates/proc-macro-srv-cli")
.default_condition(
- builder.config.extended
- && builder.config.tools.as_ref().map_or(true, |tools| {
- tools.iter().any(|tool| {
- tool == "rust-analyzer" || tool == "rust-analyzer-proc-macro-srv"
- })
- }),
+ builder.tool_enabled("rust-analyzer")
+ || builder.tool_enabled("rust-analyzer-proc-macro-srv"),
)
}
@@ -874,16 +856,8 @@ impl Step for LlvmBitcodeLinker {
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
let builder = run.builder;
- run.path("src/tools/llvm-bitcode-linker").default_condition(
- builder.config.extended
- && builder
- .config
- .tools
- .as_ref()
- .map_or(builder.build.unstable_features(), |tools| {
- tools.iter().any(|tool| tool == "llvm-bitcode-linker")
- }),
- )
+ run.path("src/tools/llvm-bitcode-linker")
+ .default_condition(builder.tool_enabled("llvm-bitcode-linker"))
}
fn make_run(run: RunConfig<'_>) {
diff --git a/src/bootstrap/src/core/builder.rs b/src/bootstrap/src/core/builder.rs
index 304fe8d..1e87798 100644
--- a/src/bootstrap/src/core/builder.rs
+++ b/src/bootstrap/src/core/builder.rs
@@ -798,6 +798,7 @@ macro_rules! describe {
tool::Miri,
tool::CargoMiri,
llvm::Lld,
+ llvm::Enzyme,
llvm::CrtBeginEnd,
tool::RustdocGUITest,
tool::OptimizedDist,
@@ -1588,6 +1589,12 @@ fn cargo(
rustflags.arg(sysroot_str);
}
+ // https://rust-lang.zulipchat.com/#narrow/stream/182449-t-compiler.2Fhelp/topic/.E2.9C.94.20link.20new.20library.20into.20stage1.2Frustc
+ if self.config.llvm_enzyme {
+ rustflags.arg("-l");
+ rustflags.arg("Enzyme-19");
+ }
+
let use_new_symbol_mangling = match self.config.rust_new_symbol_mangling {
Some(setting) => {
// If an explicit setting is given, use that
@@ -2456,7 +2463,16 @@ pub fn new(
cmd_kind: Kind,
) -> Cargo {
let mut cargo = builder.cargo(compiler, mode, source_type, target, cmd_kind);
- cargo.configure_linker(builder);
+
+ match cmd_kind {
+ // No need to configure the target linker for these command types,
+ // as they don't invoke rustc at all.
+ Kind::Clean | Kind::Suggest | Kind::Format | Kind::Setup => {}
+ _ => {
+ cargo.configure_linker(builder);
+ }
+ }
+
cargo
}
diff --git a/src/bootstrap/src/core/config/config.rs b/src/bootstrap/src/core/config/config.rs
index f7cc9ee..f509712 100644
--- a/src/bootstrap/src/core/config/config.rs
+++ b/src/bootstrap/src/core/config/config.rs
@@ -221,6 +221,7 @@ pub struct Config {
// llvm codegen options
pub llvm_assertions: bool,
pub llvm_tests: bool,
+ pub llvm_enzyme: bool,
pub llvm_plugins: bool,
pub llvm_optimize: bool,
pub llvm_thin_lto: bool,
@@ -898,6 +899,7 @@ struct Llvm {
release_debuginfo: Option<bool> = "release-debuginfo",
assertions: Option<bool> = "assertions",
tests: Option<bool> = "tests",
+ enzyme: Option<bool> = "enzyme",
plugins: Option<bool> = "plugins",
ccache: Option<StringOrBool> = "ccache",
static_libstdcpp: Option<bool> = "static-libstdcpp",
@@ -1214,13 +1216,23 @@ pub fn default_opts() -> Config {
}
}
+ pub(crate) fn get_builder_toml(&self, build_name: &str) -> Result<TomlConfig, toml::de::Error> {
+ if self.dry_run() {
+ return Ok(TomlConfig::default());
+ }
+
+ let builder_config_path =
+ self.out.join(self.build.triple).join(build_name).join(BUILDER_CONFIG_FILENAME);
+ Self::get_toml(&builder_config_path)
+ }
+
#[cfg(test)]
- fn get_toml(_: &Path) -> Result<TomlConfig, toml::de::Error> {
+ pub(crate) fn get_toml(_: &Path) -> Result<TomlConfig, toml::de::Error> {
Ok(TomlConfig::default())
}
#[cfg(not(test))]
- fn get_toml(file: &Path) -> Result<TomlConfig, toml::de::Error> {
+ pub(crate) fn get_toml(file: &Path) -> Result<TomlConfig, toml::de::Error> {
let contents =
t!(fs::read_to_string(file), format!("config file {} not found", file.display()));
// Deserialize to Value and then TomlConfig to prevent the Deserialize impl of
@@ -1588,6 +1600,9 @@ fn get_table(option: &str) -> Result<TomlConfig, toml::de::Error> {
config.verbose = cmp::max(config.verbose, flags.verbose as usize);
+ // Verbose flag is a good default for `rust.verbose-tests`.
+ config.verbose_tests = config.is_verbose();
+
if let Some(install) = toml.install {
let Install { prefix, sysconfdir, docdir, bindir, libdir, mandir, datadir } = install;
config.prefix = prefix.map(PathBuf::from);
@@ -1603,6 +1618,7 @@ fn get_table(option: &str) -> Result<TomlConfig, toml::de::Error> {
// we'll infer default values for them later
let mut llvm_assertions = None;
let mut llvm_tests = None;
+ let mut llvm_enzyme = None;
let mut llvm_plugins = None;
let mut debug = None;
let mut debug_assertions = None;
@@ -1722,6 +1738,8 @@ fn get_table(option: &str) -> Result<TomlConfig, toml::de::Error> {
config.llvm_tools_enabled = llvm_tools.unwrap_or(true);
config.rustc_parallel =
parallel_compiler.unwrap_or(config.channel == "dev" || config.channel == "nightly");
+ config.llvm_enzyme =
+ llvm_enzyme.unwrap_or(config.channel == "dev" || config.channel == "nightly");
config.rustc_default_linker = default_linker;
config.musl_root = musl_root.map(PathBuf::from);
config.save_toolstates = save_toolstates.map(PathBuf::from);
@@ -1806,6 +1824,7 @@ fn get_table(option: &str) -> Result<TomlConfig, toml::de::Error> {
release_debuginfo,
assertions,
tests,
+ enzyme,
plugins,
ccache,
static_libstdcpp,
@@ -1839,6 +1858,7 @@ fn get_table(option: &str) -> Result<TomlConfig, toml::de::Error> {
set(&mut config.ninja_in_file, ninja);
llvm_assertions = assertions;
llvm_tests = tests;
+ llvm_enzyme = enzyme;
llvm_plugins = plugins;
set(&mut config.llvm_optimize, optimize_toml);
set(&mut config.llvm_thin_lto, thin_lto);
@@ -1901,34 +1921,9 @@ fn get_table(option: &str) -> Result<TomlConfig, toml::de::Error> {
"HELP: To use `llvm.libzstd` for LLVM/LLD builds, set `download-ci-llvm` option to false."
);
}
-
- // None of the LLVM options, except assertions, are supported
- // when using downloaded LLVM. We could just ignore these but
- // that's potentially confusing, so force them to not be
- // explicitly set. The defaults and CI defaults don't
- // necessarily match but forcing people to match (somewhat
- // arbitrary) CI configuration locally seems bad/hard.
- check_ci_llvm!(optimize_toml);
- check_ci_llvm!(thin_lto);
- check_ci_llvm!(release_debuginfo);
- check_ci_llvm!(targets);
- check_ci_llvm!(experimental_targets);
- check_ci_llvm!(clang_cl);
- check_ci_llvm!(version_suffix);
- check_ci_llvm!(cflags);
- check_ci_llvm!(cxxflags);
- check_ci_llvm!(ldflags);
- check_ci_llvm!(use_libcxx);
- check_ci_llvm!(use_linker);
- check_ci_llvm!(allow_old_toolchain);
- check_ci_llvm!(polly);
- check_ci_llvm!(clang);
- check_ci_llvm!(build_config);
- check_ci_llvm!(plugins);
}
- // NOTE: can never be hit when downloading from CI, since we call `check_ci_llvm!(thin_lto)` above.
- if config.llvm_thin_lto && link_shared.is_none() {
+ if !config.llvm_from_ci && config.llvm_thin_lto && link_shared.is_none() {
// If we're building with ThinLTO on, by default we want to link
// to LLVM shared, to avoid re-doing ThinLTO (which happens in
// the link step) with each stage.
@@ -2055,6 +2050,7 @@ fn get_table(option: &str) -> Result<TomlConfig, toml::de::Error> {
config.llvm_assertions = llvm_assertions.unwrap_or(false);
config.llvm_tests = llvm_tests.unwrap_or(false);
+ config.llvm_enzyme = llvm_enzyme.unwrap_or(false);
config.llvm_plugins = llvm_plugins.unwrap_or(false);
config.rust_optimize = optimize.unwrap_or(RustOptimize::Bool(true));
@@ -2366,10 +2362,7 @@ pub(crate) fn download_rustc_commit(&self) -> Option<&str> {
self.download_ci_rustc(commit);
if let Some(config_path) = &self.config {
- let builder_config_path =
- self.out.join(self.build.triple).join("ci-rustc").join(BUILDER_CONFIG_FILENAME);
-
- let ci_config_toml = match Self::get_toml(&builder_config_path) {
+ let ci_config_toml = match self.get_builder_toml("ci-rustc") {
Ok(ci_config_toml) => ci_config_toml,
Err(e) if e.to_string().contains("unknown field") => {
println!("WARNING: CI rustc has some fields that are no longer supported in bootstrap; download-rustc will be disabled.");
@@ -2377,7 +2370,7 @@ pub(crate) fn download_rustc_commit(&self) -> Option<&str> {
return None;
},
Err(e) => {
- eprintln!("ERROR: Failed to parse CI rustc config at '{}': {e}", builder_config_path.display());
+ eprintln!("ERROR: Failed to parse CI rustc config.toml: {e}");
exit!(2);
},
};
@@ -2773,7 +2766,8 @@ fn parse_download_ci_llvm(
);
}
- b
+ // If download-ci-llvm=true we also want to check that CI llvm is available
+ b && llvm::is_ci_llvm_available(self, asserts)
}
Some(StringOrBool::String(s)) if s == "if-unchanged" => if_unchanged(),
Some(StringOrBool::String(other)) => {
@@ -2838,6 +2832,109 @@ pub fn last_modified_commit(
}
}
+/// Compares the current `Llvm` options against those in the CI LLVM builder and detects any incompatible options.
+/// It does this by destructuring the `Llvm` instance to make sure every `Llvm` field is covered and not missing.
+#[cfg(not(feature = "bootstrap-self-test"))]
+pub(crate) fn check_incompatible_options_for_ci_llvm(
+ current_config_toml: TomlConfig,
+ ci_config_toml: TomlConfig,
+) -> Result<(), String> {
+ macro_rules! err {
+ ($current:expr, $expected:expr) => {
+ if let Some(current) = &$current {
+ if Some(current) != $expected.as_ref() {
+ return Err(format!(
+ "ERROR: Setting `llvm.{}` is incompatible with `llvm.download-ci-llvm`. \
+ Current value: {:?}, Expected value(s): {}{:?}",
+ stringify!($expected).replace("_", "-"),
+ $current,
+ if $expected.is_some() { "None/" } else { "" },
+ $expected,
+ ));
+ };
+ };
+ };
+ }
+
+ macro_rules! warn {
+ ($current:expr, $expected:expr) => {
+ if let Some(current) = &$current {
+ if Some(current) != $expected.as_ref() {
+ println!(
+ "WARNING: `llvm.{}` has no effect with `llvm.download-ci-llvm`. \
+ Current value: {:?}, Expected value(s): {}{:?}",
+ stringify!($expected).replace("_", "-"),
+ $current,
+ if $expected.is_some() { "None/" } else { "" },
+ $expected,
+ );
+ };
+ };
+ };
+ }
+
+ let (Some(current_llvm_config), Some(ci_llvm_config)) =
+ (current_config_toml.llvm, ci_config_toml.llvm)
+ else {
+ return Ok(());
+ };
+
+ let Llvm {
+ optimize,
+ thin_lto,
+ release_debuginfo,
+ assertions: _,
+ tests: _,
+ plugins,
+ ccache: _,
+ static_libstdcpp: _,
+ libzstd,
+ ninja: _,
+ targets,
+ experimental_targets,
+ link_jobs: _,
+ link_shared: _,
+ version_suffix,
+ clang_cl,
+ cflags,
+ cxxflags,
+ ldflags,
+ use_libcxx,
+ use_linker,
+ allow_old_toolchain,
+ polly,
+ clang,
+ enable_warnings,
+ download_ci_llvm: _,
+ build_config,
+ enzyme,
+ } = ci_llvm_config;
+
+ err!(current_llvm_config.optimize, optimize);
+ err!(current_llvm_config.thin_lto, thin_lto);
+ err!(current_llvm_config.release_debuginfo, release_debuginfo);
+ err!(current_llvm_config.libzstd, libzstd);
+ err!(current_llvm_config.targets, targets);
+ err!(current_llvm_config.experimental_targets, experimental_targets);
+ err!(current_llvm_config.clang_cl, clang_cl);
+ err!(current_llvm_config.version_suffix, version_suffix);
+ err!(current_llvm_config.cflags, cflags);
+ err!(current_llvm_config.cxxflags, cxxflags);
+ err!(current_llvm_config.ldflags, ldflags);
+ err!(current_llvm_config.use_libcxx, use_libcxx);
+ err!(current_llvm_config.use_linker, use_linker);
+ err!(current_llvm_config.allow_old_toolchain, allow_old_toolchain);
+ err!(current_llvm_config.polly, polly);
+ err!(current_llvm_config.clang, clang);
+ err!(current_llvm_config.build_config, build_config);
+ err!(current_llvm_config.plugins, plugins);
+ err!(current_llvm_config.enzyme, enzyme);
+
+ warn!(current_llvm_config.enable_warnings, enable_warnings);
+
+ Ok(())
+}
+
/// Compares the current Rust options against those in the CI rustc builder and detects any incompatible options.
/// It does this by destructuring the `Rust` instance to make sure every `Rust` field is covered and not missing.
fn check_incompatible_options_for_ci_rustc(
diff --git a/src/bootstrap/src/core/config/flags.rs b/src/bootstrap/src/core/config/flags.rs
index c3f1740..effc5f5 100644
--- a/src/bootstrap/src/core/config/flags.rs
+++ b/src/bootstrap/src/core/config/flags.rs
@@ -143,9 +143,6 @@ pub struct Flags {
/// Unless you know exactly what you are doing, you probably don't need this.
pub bypass_bootstrap_lock: bool,
- /// whether rebuilding llvm should be skipped, overriding `skip-rebuld` in config.toml
- #[arg(global = true, long, value_name = "VALUE")]
- pub llvm_skip_rebuild: Option<bool>,
/// generate PGO profile with rustc build
#[arg(global = true, value_hint = clap::ValueHint::FilePath, long, value_name = "PROFILE")]
pub rust_profile_generate: Option<String>,
diff --git a/src/bootstrap/src/core/config/tests.rs b/src/bootstrap/src/core/config/tests.rs
index 219c5a6..f54a5d3 100644
--- a/src/bootstrap/src/core/config/tests.rs
+++ b/src/bootstrap/src/core/config/tests.rs
@@ -317,3 +317,12 @@ fn order_of_clippy_rules() {
assert_eq!(expected, actual);
}
+
+#[test]
+fn verbose_tests_default_value() {
+ let config = Config::parse(Flags::parse(&["build".into(), "compiler".into()]));
+ assert_eq!(config.verbose_tests, false);
+
+ let config = Config::parse(Flags::parse(&["build".into(), "compiler".into(), "-v".into()]));
+ assert_eq!(config.verbose_tests, true);
+}
diff --git a/src/bootstrap/src/core/download.rs b/src/bootstrap/src/core/download.rs
index 1e3f8da..d8b39ac 100644
--- a/src/bootstrap/src/core/download.rs
+++ b/src/bootstrap/src/core/download.rs
@@ -228,25 +228,42 @@ fn download_file(&self, url: &str, dest_path: &Path, help_on_error: &str) {
fn download_http_with_retries(&self, tempfile: &Path, url: &str, help_on_error: &str) {
println!("downloading {url}");
// Try curl. If that fails and we are on windows, fallback to PowerShell.
+ // options should be kept in sync with
+ // src/bootstrap/src/core/download.rs
+ // for consistency
let mut curl = command("curl");
curl.args([
- "-y",
+ // follow redirect
+ "--location",
+ // timeout if speed is < 10 bytes/sec for > 30 seconds
+ "--speed-time",
"30",
- "-Y",
- "10", // timeout if speed is < 10 bytes/sec for > 30 seconds
+ "--speed-limit",
+ "10",
+ // timeout if cannot connect within 30 seconds
"--connect-timeout",
- "30", // timeout if cannot connect within 30 seconds
- "-o",
+ "30",
+ // output file
+ "--output",
tempfile.to_str().unwrap(),
+ // if there is an error, don't restart the download,
+ // instead continue where it left off.
"--continue-at",
"-",
+ // retry up to 3 times. note that this means a maximum of 4
+ // attempts will be made, since the first attempt isn't a *re*try.
"--retry",
"3",
- "-SRf",
+ // show errors, even if --silent is specified
+ "--show-error",
+ // set timestamp of downloaded file to that of the server
+ "--remote-time",
+ // fail on non-ok http status
+ "--fail",
]);
// Don't print progress in CI; the \r wrapping looks bad and downloads don't take long enough for progress to be useful.
if CiEnv::is_ci() {
- curl.arg("-s");
+ curl.arg("--silent");
} else {
curl.arg("--progress-bar");
}
@@ -299,6 +316,7 @@ fn unpack(&self, tarball: &Path, dst: &Path, pattern: &str) {
let mut tar = tar::Archive::new(decompressor);
let is_ci_rustc = dst.ends_with("ci-rustc");
+ let is_ci_llvm = dst.ends_with("ci-llvm");
// `compile::Sysroot` needs to know the contents of the `rustc-dev` tarball to avoid adding
// it to the sysroot unless it was explicitly requested. But parsing the 100 MB tarball is slow.
@@ -315,7 +333,9 @@ fn unpack(&self, tarball: &Path, dst: &Path, pattern: &str) {
let mut short_path = t!(original_path.strip_prefix(directory_prefix));
let is_builder_config = short_path.to_str() == Some(BUILDER_CONFIG_FILENAME);
- if !(short_path.starts_with(pattern) || (is_ci_rustc && is_builder_config)) {
+ if !(short_path.starts_with(pattern)
+ || ((is_ci_rustc || is_ci_llvm) && is_builder_config))
+ {
continue;
}
short_path = short_path.strip_prefix(pattern).unwrap_or(short_path);
@@ -700,17 +720,22 @@ pub(crate) fn maybe_download_ci_llvm(&self) {}
#[cfg(not(feature = "bootstrap-self-test"))]
pub(crate) fn maybe_download_ci_llvm(&self) {
+ use build_helper::exit;
+
use crate::core::build_steps::llvm::detect_llvm_sha;
+ use crate::core::config::check_incompatible_options_for_ci_llvm;
if !self.llvm_from_ci {
return;
}
+
let llvm_root = self.ci_llvm_root();
let llvm_stamp = llvm_root.join(".llvm-stamp");
let llvm_sha = detect_llvm_sha(self, self.rust_info.is_managed_git_subrepository());
let key = format!("{}{}", llvm_sha, self.llvm_assertions);
if program_out_of_date(&llvm_stamp, &key) && !self.dry_run() {
self.download_ci_llvm(&llvm_sha);
+
if self.should_fix_bins_and_dylibs() {
for entry in t!(fs::read_dir(llvm_root.join("bin"))) {
self.fix_bin_or_dylib(&t!(entry).path());
@@ -743,6 +768,26 @@ pub(crate) fn maybe_download_ci_llvm(&self) {
t!(fs::write(llvm_stamp, key));
}
+
+ if let Some(config_path) = &self.config {
+ let current_config_toml = Self::get_toml(config_path).unwrap();
+
+ match self.get_builder_toml("ci-llvm") {
+ Ok(ci_config_toml) => {
+ t!(check_incompatible_options_for_ci_llvm(current_config_toml, ci_config_toml));
+ }
+ Err(e) if e.to_string().contains("unknown field") => {
+ println!(
+ "WARNING: CI LLVM has some fields that are no longer supported in bootstrap; download-ci-llvm will be disabled."
+ );
+ println!("HELP: Consider rebasing to a newer commit if available.");
+ }
+ Err(e) => {
+ eprintln!("ERROR: Failed to parse CI LLVM config.toml: {e}");
+ exit!(2);
+ }
+ };
+ };
}
#[cfg(not(feature = "bootstrap-self-test"))]
diff --git a/src/bootstrap/src/core/metadata.rs b/src/bootstrap/src/core/metadata.rs
index 1016607..d665544 100644
--- a/src/bootstrap/src/core/metadata.rs
+++ b/src/bootstrap/src/core/metadata.rs
@@ -1,3 +1,4 @@
+use std::collections::BTreeMap;
use std::path::PathBuf;
use serde_derive::Deserialize;
@@ -21,6 +22,7 @@ struct Package {
manifest_path: String,
dependencies: Vec<Dependency>,
targets: Vec<Target>,
+ features: BTreeMap<String, Vec<String>>,
}
/// For more information, see the output of
@@ -51,7 +53,13 @@ pub fn build(build: &mut Build) {
.map(|dep| dep.name)
.collect();
let has_lib = package.targets.iter().any(|t| t.kind.iter().any(|k| k == "lib"));
- let krate = Crate { name: name.clone(), deps, path, has_lib };
+ let krate = Crate {
+ name: name.clone(),
+ deps,
+ path,
+ has_lib,
+ features: package.features.keys().cloned().collect(),
+ };
let relative_path = krate.local_path(build);
build.crates.insert(name.clone(), krate);
let existing_path = build.crate_paths.insert(relative_path, name);
diff --git a/src/bootstrap/src/lib.rs b/src/bootstrap/src/lib.rs
index 5751c39..780024e 100644
--- a/src/bootstrap/src/lib.rs
+++ b/src/bootstrap/src/lib.rs
@@ -77,6 +77,9 @@
#[allow(clippy::type_complexity)] // It's fine for hard-coded list and type is explained above.
const EXTRA_CHECK_CFGS: &[(Option<Mode>, &str, Option<&[&'static str]>)] = &[
(None, "bootstrap", None),
+ (Some(Mode::Rustc), "llvm_enzyme", None),
+ (Some(Mode::Codegen), "llvm_enzyme", None),
+ (Some(Mode::ToolRustc), "llvm_enzyme", None),
(Some(Mode::Rustc), "parallel_compiler", None),
(Some(Mode::ToolRustc), "parallel_compiler", None),
(Some(Mode::ToolRustc), "rust_analyzer", None),
@@ -140,6 +143,7 @@ pub struct Build {
clippy_info: GitInfo,
miri_info: GitInfo,
rustfmt_info: GitInfo,
+ enzyme_info: GitInfo,
in_tree_llvm_info: GitInfo,
local_rebuild: bool,
fail_fast: bool,
@@ -183,6 +187,7 @@ struct Crate {
deps: HashSet<String>,
path: PathBuf,
has_lib: bool,
+ features: Vec<String>,
}
impl Crate {
@@ -306,6 +311,7 @@ pub fn new(mut config: Config) -> Build {
let clippy_info = GitInfo::new(omit_git_hash, &src.join("src/tools/clippy"));
let miri_info = GitInfo::new(omit_git_hash, &src.join("src/tools/miri"));
let rustfmt_info = GitInfo::new(omit_git_hash, &src.join("src/tools/rustfmt"));
+ let enzyme_info = GitInfo::new(omit_git_hash, &src.join("src/tools/enzyme"));
// we always try to use git for LLVM builds
let in_tree_llvm_info = GitInfo::new(false, &src.join("src/llvm-project"));
@@ -332,14 +338,20 @@ pub fn new(mut config: Config) -> Build {
.trim()
.to_string();
- let initial_libdir = initial_target_dir
- .parent()
- .unwrap()
- .parent()
- .unwrap()
- .strip_prefix(&initial_sysroot)
- .unwrap()
- .to_path_buf();
+ // FIXME(Zalathar): Determining this path occasionally fails locally for
+ // unknown reasons, so we print some extra context to help track down why.
+ let find_initial_libdir = || {
+ let initial_libdir =
+ initial_target_dir.parent()?.parent()?.strip_prefix(&initial_sysroot).ok()?;
+ Some(initial_libdir.to_path_buf())
+ };
+ let Some(initial_libdir) = find_initial_libdir() else {
+ panic!(
+ "couldn't determine `initial_libdir` \
+ from target dir {initial_target_dir:?} \
+ and sysroot {initial_sysroot:?}"
+ )
+ };
let version = std::fs::read_to_string(src.join("src").join("version"))
.expect("failed to read src/version");
@@ -393,6 +405,7 @@ pub fn new(mut config: Config) -> Build {
clippy_info,
miri_info,
rustfmt_info,
+ enzyme_info,
in_tree_llvm_info,
cc: RefCell::new(HashMap::new()),
cxx: RefCell::new(HashMap::new()),
@@ -666,16 +679,24 @@ fn std_features(&self, target: TargetSelection) -> String {
}
/// Gets the space-separated set of activated features for the compiler.
- fn rustc_features(&self, kind: Kind, target: TargetSelection) -> String {
+ fn rustc_features(&self, kind: Kind, target: TargetSelection, crates: &[String]) -> String {
+ let possible_features_by_crates: HashSet<_> = crates
+ .iter()
+ .flat_map(|krate| &self.crates[krate].features)
+ .map(std::ops::Deref::deref)
+ .collect();
+ let check = |feature: &str| -> bool {
+ crates.is_empty() || possible_features_by_crates.contains(feature)
+ };
let mut features = vec![];
- if self.config.jemalloc {
+ if self.config.jemalloc && check("jemalloc") {
features.push("jemalloc");
}
- if self.config.llvm_enabled(target) || kind == Kind::Check {
+ if (self.config.llvm_enabled(target) || kind == Kind::Check) && check("llvm") {
features.push("llvm");
}
// keep in sync with `bootstrap/compile.rs:rustc_cargo_env`
- if self.config.rustc_parallel {
+ if self.config.rustc_parallel && check("rustc_use_parallel_compiler") {
features.push("rustc_use_parallel_compiler");
}
if self.config.rust_randomize_layout {
@@ -687,7 +708,7 @@ fn rustc_features(&self, kind: Kind, target: TargetSelection) -> String {
// which is everything (including debug/trace/etc.)
// if its unset, if debug_assertions is on, then debug_logging will also be on
// as well as tracing *ignoring* this feature when debug_assertions is on
- if !self.config.rust_debug_logging {
+ if !self.config.rust_debug_logging && check("max_level_info") {
features.push("max_level_info");
}
@@ -740,6 +761,10 @@ fn llvm_out(&self, target: TargetSelection) -> PathBuf {
}
}
+ fn enzyme_out(&self, target: TargetSelection) -> PathBuf {
+ self.out.join(&*target.triple).join("enzyme")
+ }
+
fn lld_out(&self, target: TargetSelection) -> PathBuf {
self.out.join(target).join("lld")
}
@@ -1382,16 +1407,17 @@ fn default_wasi_runner(&self) -> Option<String> {
None
}
- /// Returns whether it's requested that `wasm-component-ld` is built as part
- /// of the sysroot. This is done either with the `extended` key in
- /// `config.toml` or with the `tools` set.
- fn build_wasm_component_ld(&self) -> bool {
- if self.config.extended {
- return true;
+ /// Returns whether the specified tool is configured as part of this build.
+ ///
+ /// This requires that both the `extended` key is set and the `tools` key is
+ /// either unset or specifically contains the specified tool.
+ fn tool_enabled(&self, tool: &str) -> bool {
+ if !self.config.extended {
+ return false;
}
match &self.config.tools {
- Some(set) => set.contains("wasm-component-ld"),
- None => false,
+ Some(set) => set.contains(tool),
+ None => true,
}
}
diff --git a/src/bootstrap/src/utils/cc_detect.rs b/src/bootstrap/src/utils/cc_detect.rs
index 29e6b74..c39415e 100644
--- a/src/bootstrap/src/utils/cc_detect.rs
+++ b/src/bootstrap/src/utils/cc_detect.rs
@@ -87,15 +87,28 @@ fn new_cc_build(build: &Build, target: TargetSelection) -> cc::Build {
}
pub fn find(build: &Build) {
- // For all targets we're going to need a C compiler for building some shims
- // and such as well as for being a linker for Rust code.
- let targets = build
- .targets
- .iter()
- .chain(&build.hosts)
- .cloned()
- .chain(iter::once(build.build))
- .collect::<HashSet<_>>();
+ let targets: HashSet<_> = match build.config.cmd {
+ // We don't need to check cross targets for these commands.
+ crate::Subcommand::Clean { .. }
+ | crate::Subcommand::Suggest { .. }
+ | crate::Subcommand::Format { .. }
+ | crate::Subcommand::Setup { .. } => {
+ build.hosts.iter().cloned().chain(iter::once(build.build)).collect()
+ }
+
+ _ => {
+ // For all targets we're going to need a C compiler for building some shims
+ // and such as well as for being a linker for Rust code.
+ build
+ .targets
+ .iter()
+ .chain(&build.hosts)
+ .cloned()
+ .chain(iter::once(build.build))
+ .collect()
+ }
+ };
+
for target in targets.into_iter() {
find_target(build, target);
}
diff --git a/src/bootstrap/src/utils/change_tracker.rs b/src/bootstrap/src/utils/change_tracker.rs
index 3fec2d9..99bcc6e 100644
--- a/src/bootstrap/src/utils/change_tracker.rs
+++ b/src/bootstrap/src/utils/change_tracker.rs
@@ -245,4 +245,14 @@ pub fn human_readable_changes(changes: &[ChangeInfo]) -> String {
severity: ChangeSeverity::Warning,
summary: "Removed `rust.split-debuginfo` as it was deprecated long time ago.",
},
+ ChangeInfo {
+ change_id: 129176,
+ severity: ChangeSeverity::Info,
+ summary: "New option `llvm.enzyme` to control whether the llvm based autodiff tool (Enzyme) is built.",
+ },
+ ChangeInfo {
+ change_id: 129473,
+ severity: ChangeSeverity::Warning,
+ summary: "`download-ci-llvm = true` now checks if CI llvm is available and has become the default for the compiler profile",
+ },
];
diff --git a/src/bootstrap/src/utils/render_tests.rs b/src/bootstrap/src/utils/render_tests.rs
index b8aebc2..eb2c825 100644
--- a/src/bootstrap/src/utils/render_tests.rs
+++ b/src/bootstrap/src/utils/render_tests.rs
@@ -88,6 +88,9 @@ struct Renderer<'a> {
builder: &'a Builder<'a>,
tests_count: Option<usize>,
executed_tests: usize,
+ /// Number of tests that were skipped due to already being up-to-date
+ /// (i.e. no relevant changes occurred since they last ran).
+ up_to_date_tests: usize,
terse_tests_in_line: usize,
}
@@ -100,6 +103,7 @@ fn new(stdout: ChildStdout, builder: &'a Builder<'a>) -> Self {
builder,
tests_count: None,
executed_tests: 0,
+ up_to_date_tests: 0,
terse_tests_in_line: 0,
}
}
@@ -127,6 +131,12 @@ fn render_all(mut self) {
}
}
}
+
+ if self.up_to_date_tests > 0 {
+ let n = self.up_to_date_tests;
+ let s = if n > 1 { "s" } else { "" };
+ println!("help: ignored {n} up-to-date test{s}; use `--force-rerun` to prevent this\n");
+ }
}
/// Renders the stdout characters one by one
@@ -149,6 +159,11 @@ fn stream_all(mut self) {
fn render_test_outcome(&mut self, outcome: Outcome<'_>, test: &TestOutcome) {
self.executed_tests += 1;
+ // Keep this in sync with the "up-to-date" ignore message inserted by compiletest.
+ if let Outcome::Ignored { reason: Some("up-to-date") } = outcome {
+ self.up_to_date_tests += 1;
+ }
+
#[cfg(feature = "build-metrics")]
self.builder.metrics.record_test(
&test.name,
diff --git a/src/ci/docker/host-x86_64/x86_64-gnu-tools/checktools.sh b/src/ci/docker/host-x86_64/x86_64-gnu-tools/checktools.sh
index a5a5acc..303a2f2 100755
--- a/src/ci/docker/host-x86_64/x86_64-gnu-tools/checktools.sh
+++ b/src/ci/docker/host-x86_64/x86_64-gnu-tools/checktools.sh
@@ -58,8 +58,9 @@
# Strangely, Linux targets do not work here. cargo always says
# "error: cannot produce cdylib for ... as the target ... does not support these crate types".
# Only run "pass" tests, which is quite a bit faster.
- python3 "$X_PY" test --stage 2 src/tools/miri --target aarch64-apple-darwin --test-args pass
- python3 "$X_PY" test --stage 2 src/tools/miri --target i686-pc-windows-gnu --test-args pass
+ #FIXME: Re-enable this once CI issues are fixed
+ #python3 "$X_PY" test --stage 2 src/tools/miri --target aarch64-apple-darwin --test-args pass
+ #python3 "$X_PY" test --stage 2 src/tools/miri --target i686-pc-windows-gnu --test-args pass
;;
*)
echo "FATAL: unexpected host $HOST_TARGET"
@@ -68,6 +69,10 @@
esac
# Also smoke-test `x.py miri`. This doesn't run any actual tests (that would take too long),
# but it ensures that the crates build properly when tested with Miri.
-python3 "$X_PY" miri --stage 2 library/core --test-args notest
-python3 "$X_PY" miri --stage 2 library/alloc --test-args notest
-python3 "$X_PY" miri --stage 2 library/std --test-args notest
+
+#FIXME: Re-enable this for msvc once CI issues are fixed
+if [ "$HOST_TARGET" != "x86_64-pc-windows-msvc" ]; then
+ python3 "$X_PY" miri --stage 2 library/core --test-args notest
+ python3 "$X_PY" miri --stage 2 library/alloc --test-args notest
+ python3 "$X_PY" miri --stage 2 library/std --test-args notest
+fi
diff --git a/src/ci/github-actions/jobs.yml b/src/ci/github-actions/jobs.yml
index 4de44c6..41d3b31 100644
--- a/src/ci/github-actions/jobs.yml
+++ b/src/ci/github-actions/jobs.yml
@@ -373,6 +373,18 @@
DEPLOY_TOOLSTATES_JSON: toolstates-windows.json
<<: *job-windows-8c
+ # Temporary builder to workaround CI issues
+ - image: x86_64-msvc-ext2
+ env:
+ SCRIPT: >
+ python x.py test --stage 2 src/tools/miri --target aarch64-apple-darwin --test-args pass &&
+ python x.py test --stage 2 src/tools/miri --target i686-pc-windows-gnu --test-args pass &&
+ python x.py miri --stage 2 library/core --test-args notest &&
+ python x.py miri --stage 2 library/alloc --test-args notest &&
+ python x.py miri --stage 2 library/std --test-args notest
+ RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc --enable-lld
+ <<: *job-windows-8c
+
# 32/64-bit MinGW builds.
#
# We are using MinGW with POSIX threads since LLVM requires
@@ -418,6 +430,7 @@
--set rust.codegen-units=1
SCRIPT: python x.py build --set rust.debug=true opt-dist && PGO_HOST=x86_64-pc-windows-msvc ./build/x86_64-pc-windows-msvc/stage0-tools-bin/opt-dist windows-ci -- python x.py dist bootstrap --include-default-paths
DIST_REQUIRE_ALL_TOOLS: 1
+ CODEGEN_BACKENDS: llvm,cranelift
<<: *job-windows-8c
- image: dist-i686-msvc
@@ -430,6 +443,7 @@
--enable-profiler
SCRIPT: python x.py dist bootstrap --include-default-paths
DIST_REQUIRE_ALL_TOOLS: 1
+ CODEGEN_BACKENDS: llvm,cranelift
<<: *job-windows-8c
- image: dist-aarch64-msvc
@@ -454,6 +468,7 @@
NO_DOWNLOAD_CI_LLVM: 1
SCRIPT: python x.py dist bootstrap --include-default-paths
DIST_REQUIRE_ALL_TOOLS: 1
+ CODEGEN_BACKENDS: llvm,cranelift
<<: *job-windows-8c
- image: dist-x86_64-mingw
@@ -466,6 +481,7 @@
# incompatible with LLVM downloads today).
NO_DOWNLOAD_CI_LLVM: 1
DIST_REQUIRE_ALL_TOOLS: 1
+ CODEGEN_BACKENDS: llvm,cranelift
<<: *job-windows-8c
- image: dist-x86_64-msvc-alt
diff --git a/src/ci/scripts/install-mingw.sh b/src/ci/scripts/install-mingw.sh
index 31aa378..91eab2e 100755
--- a/src/ci/scripts/install-mingw.sh
+++ b/src/ci/scripts/install-mingw.sh
@@ -6,8 +6,8 @@
source "$(cd "$(dirname "$0")" && pwd)/../shared.sh"
-MINGW_ARCHIVE_32="i686-12.2.0-release-posix-dwarf-rt_v10-rev0.7z"
-MINGW_ARCHIVE_64="x86_64-12.2.0-release-posix-seh-rt_v10-rev0.7z"
+MINGW_ARCHIVE_32="i686-14.1.0-release-posix-dwarf-msvcrt-rt_v12-rev0.7z"
+MINGW_ARCHIVE_64="x86_64-14.1.0-release-posix-seh-msvcrt-rt_v12-rev0.7z"
if isWindows && isKnownToBeMingwBuild; then
case "${CI_JOB_NAME}" in
diff --git a/src/doc/edition-guide b/src/doc/edition-guide
index eeba2cb..b3ca7ad 160000
--- a/src/doc/edition-guide
+++ b/src/doc/edition-guide
@@ -1 +1 @@
-Subproject commit eeba2cb9c37ab74118a4fb5e5233f7397e4a91f8
+Subproject commit b3ca7ade0f87d7e3fb538776defc5b2cc4188172
diff --git a/src/doc/embedded-book b/src/doc/embedded-book
index ff5d61d..dbae36b 160000
--- a/src/doc/embedded-book
+++ b/src/doc/embedded-book
@@ -1 +1 @@
-Subproject commit ff5d61d56f11e1986bfa9652c6aff7731576c37d
+Subproject commit dbae36bf3f8410aa4313b3bad42e374735d48a9d
diff --git a/src/doc/reference b/src/doc/reference
index 0668397..687faf9 160000
--- a/src/doc/reference
+++ b/src/doc/reference
@@ -1 +1 @@
-Subproject commit 0668397076da350c404dadcf07b6cbc433ad3743
+Subproject commit 687faf9958c52116d003b41dfd29cc1cf44f5311
diff --git a/src/doc/rust-by-example b/src/doc/rust-by-example
index 859786c..c79ec34 160000
--- a/src/doc/rust-by-example
+++ b/src/doc/rust-by-example
@@ -1 +1 @@
-Subproject commit 859786c5bc99301bbc22fc631a5c2b341860da08
+Subproject commit c79ec345f08a1e94494cdc8c999709a90203fd88
diff --git a/src/doc/rustc-dev-guide b/src/doc/rustc-dev-guide
index fa928a6..0ed9229 160000
--- a/src/doc/rustc-dev-guide
+++ b/src/doc/rustc-dev-guide
@@ -1 +1 @@
-Subproject commit fa928a6d19e1666d8d811dfe3fd35cdad3b4e459
+Subproject commit 0ed9229f5b6f7824b333beabd7e3d5ba4b9bd971
diff --git a/src/doc/rustc/src/platform-support.md b/src/doc/rustc/src/platform-support.md
index 319dc9a..9a35b35 100644
--- a/src/doc/rustc/src/platform-support.md
+++ b/src/doc/rustc/src/platform-support.md
@@ -382,6 +382,7 @@
[`x86_64-unikraft-linux-musl`](platform-support/unikraft-linux-musl.md) | ✓ | | 64-bit Unikraft with musl 1.2.3
`x86_64-unknown-dragonfly` | ✓ | ✓ | 64-bit DragonFlyBSD
`x86_64-unknown-haiku` | ✓ | ✓ | 64-bit Haiku
+[`x86_64-unknown-hurd-gnu`](platform-support/hurd.md) | ✓ | ✓ | 64-bit GNU/Hurd
[`x86_64-unknown-hermit`](platform-support/hermit.md) | ✓ | | x86_64 Hermit
`x86_64-unknown-l4re-uclibc` | ? | |
[`x86_64-unknown-openbsd`](platform-support/openbsd.md) | ✓ | ✓ | 64-bit OpenBSD
diff --git a/src/doc/rustc/src/platform-support/hurd.md b/src/doc/rustc/src/platform-support/hurd.md
index ddf4021..2521f79 100644
--- a/src/doc/rustc/src/platform-support/hurd.md
+++ b/src/doc/rustc/src/platform-support/hurd.md
@@ -1,4 +1,4 @@
-# `i686-unknown-hurd-gnu`
+# `i686-unknown-hurd-gnu` and `x86_64-unknown-hurd-gnu`
**Tier: 3**
@@ -16,7 +16,8 @@
## Building the target
-This target can be built by adding `i686-unknown-hurd-gnu` as target in the rustc list.
+This target can be built by adding `i686-unknown-hurd-gnu` and
+`x86_64-unknown-hurd-gnu` as targets in the rustc list.
## Building Rust programs
@@ -32,4 +33,4 @@
## Cross-compilation toolchains and C code
The target supports C code, the GNU toolchain calls the target
-`i686-unknown-gnu`.
+`i686-unknown-gnu` and `x86_64-unknown-gnu`.
diff --git a/src/etc/completions/x.py.fish b/src/etc/completions/x.py.fish
index 3a83c89..df31b0d 100644
--- a/src/etc/completions/x.py.fish
+++ b/src/etc/completions/x.py.fish
@@ -1,6 +1,6 @@
# Print an optspec for argparse to handle cmd's options that are independent of any subcommand.
function __fish_x.py_global_optspecs
- string join \n v/verbose i/incremental config= build-dir= build= host= target= exclude= skip= include-default-paths rustc-error-format= on-fail= dry-run dump-bootstrap-shims stage= keep-stage= keep-stage-std= src= j/jobs= warnings= error-format= json-output color= bypass-bootstrap-lock llvm-skip-rebuild= rust-profile-generate= rust-profile-use= llvm-profile-use= llvm-profile-generate enable-bolt-settings skip-stage0-validation reproducible-artifact= set= h/help
+ string join \n v/verbose i/incremental config= build-dir= build= host= target= exclude= skip= include-default-paths rustc-error-format= on-fail= dry-run dump-bootstrap-shims stage= keep-stage= keep-stage-std= src= j/jobs= warnings= error-format= json-output color= bypass-bootstrap-lock rust-profile-generate= rust-profile-use= llvm-profile-use= llvm-profile-generate enable-bolt-settings skip-stage0-validation reproducible-artifact= set= h/help
end
function __fish_x.py_needs_command
@@ -41,7 +41,6 @@
complete -c x.py -n "__fish_x.py_needs_command" -l warnings -d 'if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour' -r -f -a "{deny\t'',warn\t'',default\t''}"
complete -c x.py -n "__fish_x.py_needs_command" -l error-format -d 'rustc error format' -r -f
complete -c x.py -n "__fish_x.py_needs_command" -l color -d 'whether to use color in cargo and rustc output' -r -f -a "{always\t'',never\t'',auto\t''}"
-complete -c x.py -n "__fish_x.py_needs_command" -l llvm-skip-rebuild -d 'whether rebuilding llvm should be skipped, overriding `skip-rebuld` in config.toml' -r -f -a "{true\t'',false\t''}"
complete -c x.py -n "__fish_x.py_needs_command" -l rust-profile-generate -d 'generate PGO profile with rustc build' -r -F
complete -c x.py -n "__fish_x.py_needs_command" -l rust-profile-use -d 'use PGO profile for rustc build' -r -F
complete -c x.py -n "__fish_x.py_needs_command" -l llvm-profile-use -d 'use PGO profile for LLVM build' -r -F
@@ -92,7 +91,6 @@
complete -c x.py -n "__fish_x.py_using_subcommand build" -l warnings -d 'if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour' -r -f -a "{deny\t'',warn\t'',default\t''}"
complete -c x.py -n "__fish_x.py_using_subcommand build" -l error-format -d 'rustc error format' -r -f
complete -c x.py -n "__fish_x.py_using_subcommand build" -l color -d 'whether to use color in cargo and rustc output' -r -f -a "{always\t'',never\t'',auto\t''}"
-complete -c x.py -n "__fish_x.py_using_subcommand build" -l llvm-skip-rebuild -d 'whether rebuilding llvm should be skipped, overriding `skip-rebuld` in config.toml' -r -f -a "{true\t'',false\t''}"
complete -c x.py -n "__fish_x.py_using_subcommand build" -l rust-profile-generate -d 'generate PGO profile with rustc build' -r -F
complete -c x.py -n "__fish_x.py_using_subcommand build" -l rust-profile-use -d 'use PGO profile for rustc build' -r -F
complete -c x.py -n "__fish_x.py_using_subcommand build" -l llvm-profile-use -d 'use PGO profile for LLVM build' -r -F
@@ -126,7 +124,6 @@
complete -c x.py -n "__fish_x.py_using_subcommand check" -l warnings -d 'if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour' -r -f -a "{deny\t'',warn\t'',default\t''}"
complete -c x.py -n "__fish_x.py_using_subcommand check" -l error-format -d 'rustc error format' -r -f
complete -c x.py -n "__fish_x.py_using_subcommand check" -l color -d 'whether to use color in cargo and rustc output' -r -f -a "{always\t'',never\t'',auto\t''}"
-complete -c x.py -n "__fish_x.py_using_subcommand check" -l llvm-skip-rebuild -d 'whether rebuilding llvm should be skipped, overriding `skip-rebuld` in config.toml' -r -f -a "{true\t'',false\t''}"
complete -c x.py -n "__fish_x.py_using_subcommand check" -l rust-profile-generate -d 'generate PGO profile with rustc build' -r -F
complete -c x.py -n "__fish_x.py_using_subcommand check" -l rust-profile-use -d 'use PGO profile for rustc build' -r -F
complete -c x.py -n "__fish_x.py_using_subcommand check" -l llvm-profile-use -d 'use PGO profile for LLVM build' -r -F
@@ -165,7 +162,6 @@
complete -c x.py -n "__fish_x.py_using_subcommand clippy" -l warnings -d 'if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour' -r -f -a "{deny\t'',warn\t'',default\t''}"
complete -c x.py -n "__fish_x.py_using_subcommand clippy" -l error-format -d 'rustc error format' -r -f
complete -c x.py -n "__fish_x.py_using_subcommand clippy" -l color -d 'whether to use color in cargo and rustc output' -r -f -a "{always\t'',never\t'',auto\t''}"
-complete -c x.py -n "__fish_x.py_using_subcommand clippy" -l llvm-skip-rebuild -d 'whether rebuilding llvm should be skipped, overriding `skip-rebuld` in config.toml' -r -f -a "{true\t'',false\t''}"
complete -c x.py -n "__fish_x.py_using_subcommand clippy" -l rust-profile-generate -d 'generate PGO profile with rustc build' -r -F
complete -c x.py -n "__fish_x.py_using_subcommand clippy" -l rust-profile-use -d 'use PGO profile for rustc build' -r -F
complete -c x.py -n "__fish_x.py_using_subcommand clippy" -l llvm-profile-use -d 'use PGO profile for LLVM build' -r -F
@@ -202,7 +198,6 @@
complete -c x.py -n "__fish_x.py_using_subcommand fix" -l warnings -d 'if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour' -r -f -a "{deny\t'',warn\t'',default\t''}"
complete -c x.py -n "__fish_x.py_using_subcommand fix" -l error-format -d 'rustc error format' -r -f
complete -c x.py -n "__fish_x.py_using_subcommand fix" -l color -d 'whether to use color in cargo and rustc output' -r -f -a "{always\t'',never\t'',auto\t''}"
-complete -c x.py -n "__fish_x.py_using_subcommand fix" -l llvm-skip-rebuild -d 'whether rebuilding llvm should be skipped, overriding `skip-rebuld` in config.toml' -r -f -a "{true\t'',false\t''}"
complete -c x.py -n "__fish_x.py_using_subcommand fix" -l rust-profile-generate -d 'generate PGO profile with rustc build' -r -F
complete -c x.py -n "__fish_x.py_using_subcommand fix" -l rust-profile-use -d 'use PGO profile for rustc build' -r -F
complete -c x.py -n "__fish_x.py_using_subcommand fix" -l llvm-profile-use -d 'use PGO profile for LLVM build' -r -F
@@ -236,7 +231,6 @@
complete -c x.py -n "__fish_x.py_using_subcommand fmt" -l warnings -d 'if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour' -r -f -a "{deny\t'',warn\t'',default\t''}"
complete -c x.py -n "__fish_x.py_using_subcommand fmt" -l error-format -d 'rustc error format' -r -f
complete -c x.py -n "__fish_x.py_using_subcommand fmt" -l color -d 'whether to use color in cargo and rustc output' -r -f -a "{always\t'',never\t'',auto\t''}"
-complete -c x.py -n "__fish_x.py_using_subcommand fmt" -l llvm-skip-rebuild -d 'whether rebuilding llvm should be skipped, overriding `skip-rebuld` in config.toml' -r -f -a "{true\t'',false\t''}"
complete -c x.py -n "__fish_x.py_using_subcommand fmt" -l rust-profile-generate -d 'generate PGO profile with rustc build' -r -F
complete -c x.py -n "__fish_x.py_using_subcommand fmt" -l rust-profile-use -d 'use PGO profile for rustc build' -r -F
complete -c x.py -n "__fish_x.py_using_subcommand fmt" -l llvm-profile-use -d 'use PGO profile for LLVM build' -r -F
@@ -272,7 +266,6 @@
complete -c x.py -n "__fish_x.py_using_subcommand doc" -l warnings -d 'if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour' -r -f -a "{deny\t'',warn\t'',default\t''}"
complete -c x.py -n "__fish_x.py_using_subcommand doc" -l error-format -d 'rustc error format' -r -f
complete -c x.py -n "__fish_x.py_using_subcommand doc" -l color -d 'whether to use color in cargo and rustc output' -r -f -a "{always\t'',never\t'',auto\t''}"
-complete -c x.py -n "__fish_x.py_using_subcommand doc" -l llvm-skip-rebuild -d 'whether rebuilding llvm should be skipped, overriding `skip-rebuld` in config.toml' -r -f -a "{true\t'',false\t''}"
complete -c x.py -n "__fish_x.py_using_subcommand doc" -l rust-profile-generate -d 'generate PGO profile with rustc build' -r -F
complete -c x.py -n "__fish_x.py_using_subcommand doc" -l rust-profile-use -d 'use PGO profile for rustc build' -r -F
complete -c x.py -n "__fish_x.py_using_subcommand doc" -l llvm-profile-use -d 'use PGO profile for LLVM build' -r -F
@@ -314,7 +307,6 @@
complete -c x.py -n "__fish_x.py_using_subcommand test" -l warnings -d 'if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour' -r -f -a "{deny\t'',warn\t'',default\t''}"
complete -c x.py -n "__fish_x.py_using_subcommand test" -l error-format -d 'rustc error format' -r -f
complete -c x.py -n "__fish_x.py_using_subcommand test" -l color -d 'whether to use color in cargo and rustc output' -r -f -a "{always\t'',never\t'',auto\t''}"
-complete -c x.py -n "__fish_x.py_using_subcommand test" -l llvm-skip-rebuild -d 'whether rebuilding llvm should be skipped, overriding `skip-rebuld` in config.toml' -r -f -a "{true\t'',false\t''}"
complete -c x.py -n "__fish_x.py_using_subcommand test" -l rust-profile-generate -d 'generate PGO profile with rustc build' -r -F
complete -c x.py -n "__fish_x.py_using_subcommand test" -l rust-profile-use -d 'use PGO profile for rustc build' -r -F
complete -c x.py -n "__fish_x.py_using_subcommand test" -l llvm-profile-use -d 'use PGO profile for LLVM build' -r -F
@@ -356,7 +348,6 @@
complete -c x.py -n "__fish_x.py_using_subcommand miri" -l warnings -d 'if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour' -r -f -a "{deny\t'',warn\t'',default\t''}"
complete -c x.py -n "__fish_x.py_using_subcommand miri" -l error-format -d 'rustc error format' -r -f
complete -c x.py -n "__fish_x.py_using_subcommand miri" -l color -d 'whether to use color in cargo and rustc output' -r -f -a "{always\t'',never\t'',auto\t''}"
-complete -c x.py -n "__fish_x.py_using_subcommand miri" -l llvm-skip-rebuild -d 'whether rebuilding llvm should be skipped, overriding `skip-rebuld` in config.toml' -r -f -a "{true\t'',false\t''}"
complete -c x.py -n "__fish_x.py_using_subcommand miri" -l rust-profile-generate -d 'generate PGO profile with rustc build' -r -F
complete -c x.py -n "__fish_x.py_using_subcommand miri" -l rust-profile-use -d 'use PGO profile for rustc build' -r -F
complete -c x.py -n "__fish_x.py_using_subcommand miri" -l llvm-profile-use -d 'use PGO profile for LLVM build' -r -F
@@ -394,7 +385,6 @@
complete -c x.py -n "__fish_x.py_using_subcommand bench" -l warnings -d 'if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour' -r -f -a "{deny\t'',warn\t'',default\t''}"
complete -c x.py -n "__fish_x.py_using_subcommand bench" -l error-format -d 'rustc error format' -r -f
complete -c x.py -n "__fish_x.py_using_subcommand bench" -l color -d 'whether to use color in cargo and rustc output' -r -f -a "{always\t'',never\t'',auto\t''}"
-complete -c x.py -n "__fish_x.py_using_subcommand bench" -l llvm-skip-rebuild -d 'whether rebuilding llvm should be skipped, overriding `skip-rebuld` in config.toml' -r -f -a "{true\t'',false\t''}"
complete -c x.py -n "__fish_x.py_using_subcommand bench" -l rust-profile-generate -d 'generate PGO profile with rustc build' -r -F
complete -c x.py -n "__fish_x.py_using_subcommand bench" -l rust-profile-use -d 'use PGO profile for rustc build' -r -F
complete -c x.py -n "__fish_x.py_using_subcommand bench" -l llvm-profile-use -d 'use PGO profile for LLVM build' -r -F
@@ -428,7 +418,6 @@
complete -c x.py -n "__fish_x.py_using_subcommand clean" -l warnings -d 'if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour' -r -f -a "{deny\t'',warn\t'',default\t''}"
complete -c x.py -n "__fish_x.py_using_subcommand clean" -l error-format -d 'rustc error format' -r -f
complete -c x.py -n "__fish_x.py_using_subcommand clean" -l color -d 'whether to use color in cargo and rustc output' -r -f -a "{always\t'',never\t'',auto\t''}"
-complete -c x.py -n "__fish_x.py_using_subcommand clean" -l llvm-skip-rebuild -d 'whether rebuilding llvm should be skipped, overriding `skip-rebuld` in config.toml' -r -f -a "{true\t'',false\t''}"
complete -c x.py -n "__fish_x.py_using_subcommand clean" -l rust-profile-generate -d 'generate PGO profile with rustc build' -r -F
complete -c x.py -n "__fish_x.py_using_subcommand clean" -l rust-profile-use -d 'use PGO profile for rustc build' -r -F
complete -c x.py -n "__fish_x.py_using_subcommand clean" -l llvm-profile-use -d 'use PGO profile for LLVM build' -r -F
@@ -463,7 +452,6 @@
complete -c x.py -n "__fish_x.py_using_subcommand dist" -l warnings -d 'if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour' -r -f -a "{deny\t'',warn\t'',default\t''}"
complete -c x.py -n "__fish_x.py_using_subcommand dist" -l error-format -d 'rustc error format' -r -f
complete -c x.py -n "__fish_x.py_using_subcommand dist" -l color -d 'whether to use color in cargo and rustc output' -r -f -a "{always\t'',never\t'',auto\t''}"
-complete -c x.py -n "__fish_x.py_using_subcommand dist" -l llvm-skip-rebuild -d 'whether rebuilding llvm should be skipped, overriding `skip-rebuld` in config.toml' -r -f -a "{true\t'',false\t''}"
complete -c x.py -n "__fish_x.py_using_subcommand dist" -l rust-profile-generate -d 'generate PGO profile with rustc build' -r -F
complete -c x.py -n "__fish_x.py_using_subcommand dist" -l rust-profile-use -d 'use PGO profile for rustc build' -r -F
complete -c x.py -n "__fish_x.py_using_subcommand dist" -l llvm-profile-use -d 'use PGO profile for LLVM build' -r -F
@@ -497,7 +485,6 @@
complete -c x.py -n "__fish_x.py_using_subcommand install" -l warnings -d 'if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour' -r -f -a "{deny\t'',warn\t'',default\t''}"
complete -c x.py -n "__fish_x.py_using_subcommand install" -l error-format -d 'rustc error format' -r -f
complete -c x.py -n "__fish_x.py_using_subcommand install" -l color -d 'whether to use color in cargo and rustc output' -r -f -a "{always\t'',never\t'',auto\t''}"
-complete -c x.py -n "__fish_x.py_using_subcommand install" -l llvm-skip-rebuild -d 'whether rebuilding llvm should be skipped, overriding `skip-rebuld` in config.toml' -r -f -a "{true\t'',false\t''}"
complete -c x.py -n "__fish_x.py_using_subcommand install" -l rust-profile-generate -d 'generate PGO profile with rustc build' -r -F
complete -c x.py -n "__fish_x.py_using_subcommand install" -l rust-profile-use -d 'use PGO profile for rustc build' -r -F
complete -c x.py -n "__fish_x.py_using_subcommand install" -l llvm-profile-use -d 'use PGO profile for LLVM build' -r -F
@@ -532,7 +519,6 @@
complete -c x.py -n "__fish_x.py_using_subcommand run" -l warnings -d 'if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour' -r -f -a "{deny\t'',warn\t'',default\t''}"
complete -c x.py -n "__fish_x.py_using_subcommand run" -l error-format -d 'rustc error format' -r -f
complete -c x.py -n "__fish_x.py_using_subcommand run" -l color -d 'whether to use color in cargo and rustc output' -r -f -a "{always\t'',never\t'',auto\t''}"
-complete -c x.py -n "__fish_x.py_using_subcommand run" -l llvm-skip-rebuild -d 'whether rebuilding llvm should be skipped, overriding `skip-rebuld` in config.toml' -r -f -a "{true\t'',false\t''}"
complete -c x.py -n "__fish_x.py_using_subcommand run" -l rust-profile-generate -d 'generate PGO profile with rustc build' -r -F
complete -c x.py -n "__fish_x.py_using_subcommand run" -l rust-profile-use -d 'use PGO profile for rustc build' -r -F
complete -c x.py -n "__fish_x.py_using_subcommand run" -l llvm-profile-use -d 'use PGO profile for LLVM build' -r -F
@@ -566,7 +552,6 @@
complete -c x.py -n "__fish_x.py_using_subcommand setup" -l warnings -d 'if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour' -r -f -a "{deny\t'',warn\t'',default\t''}"
complete -c x.py -n "__fish_x.py_using_subcommand setup" -l error-format -d 'rustc error format' -r -f
complete -c x.py -n "__fish_x.py_using_subcommand setup" -l color -d 'whether to use color in cargo and rustc output' -r -f -a "{always\t'',never\t'',auto\t''}"
-complete -c x.py -n "__fish_x.py_using_subcommand setup" -l llvm-skip-rebuild -d 'whether rebuilding llvm should be skipped, overriding `skip-rebuld` in config.toml' -r -f -a "{true\t'',false\t''}"
complete -c x.py -n "__fish_x.py_using_subcommand setup" -l rust-profile-generate -d 'generate PGO profile with rustc build' -r -F
complete -c x.py -n "__fish_x.py_using_subcommand setup" -l rust-profile-use -d 'use PGO profile for rustc build' -r -F
complete -c x.py -n "__fish_x.py_using_subcommand setup" -l llvm-profile-use -d 'use PGO profile for LLVM build' -r -F
@@ -600,7 +585,6 @@
complete -c x.py -n "__fish_x.py_using_subcommand suggest" -l warnings -d 'if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour' -r -f -a "{deny\t'',warn\t'',default\t''}"
complete -c x.py -n "__fish_x.py_using_subcommand suggest" -l error-format -d 'rustc error format' -r -f
complete -c x.py -n "__fish_x.py_using_subcommand suggest" -l color -d 'whether to use color in cargo and rustc output' -r -f -a "{always\t'',never\t'',auto\t''}"
-complete -c x.py -n "__fish_x.py_using_subcommand suggest" -l llvm-skip-rebuild -d 'whether rebuilding llvm should be skipped, overriding `skip-rebuld` in config.toml' -r -f -a "{true\t'',false\t''}"
complete -c x.py -n "__fish_x.py_using_subcommand suggest" -l rust-profile-generate -d 'generate PGO profile with rustc build' -r -F
complete -c x.py -n "__fish_x.py_using_subcommand suggest" -l rust-profile-use -d 'use PGO profile for rustc build' -r -F
complete -c x.py -n "__fish_x.py_using_subcommand suggest" -l llvm-profile-use -d 'use PGO profile for LLVM build' -r -F
@@ -636,7 +620,6 @@
complete -c x.py -n "__fish_x.py_using_subcommand vendor" -l warnings -d 'if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour' -r -f -a "{deny\t'',warn\t'',default\t''}"
complete -c x.py -n "__fish_x.py_using_subcommand vendor" -l error-format -d 'rustc error format' -r -f
complete -c x.py -n "__fish_x.py_using_subcommand vendor" -l color -d 'whether to use color in cargo and rustc output' -r -f -a "{always\t'',never\t'',auto\t''}"
-complete -c x.py -n "__fish_x.py_using_subcommand vendor" -l llvm-skip-rebuild -d 'whether rebuilding llvm should be skipped, overriding `skip-rebuld` in config.toml' -r -f -a "{true\t'',false\t''}"
complete -c x.py -n "__fish_x.py_using_subcommand vendor" -l rust-profile-generate -d 'generate PGO profile with rustc build' -r -F
complete -c x.py -n "__fish_x.py_using_subcommand vendor" -l rust-profile-use -d 'use PGO profile for rustc build' -r -F
complete -c x.py -n "__fish_x.py_using_subcommand vendor" -l llvm-profile-use -d 'use PGO profile for LLVM build' -r -F
@@ -671,7 +654,6 @@
complete -c x.py -n "__fish_x.py_using_subcommand perf" -l warnings -d 'if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour' -r -f -a "{deny\t'',warn\t'',default\t''}"
complete -c x.py -n "__fish_x.py_using_subcommand perf" -l error-format -d 'rustc error format' -r -f
complete -c x.py -n "__fish_x.py_using_subcommand perf" -l color -d 'whether to use color in cargo and rustc output' -r -f -a "{always\t'',never\t'',auto\t''}"
-complete -c x.py -n "__fish_x.py_using_subcommand perf" -l llvm-skip-rebuild -d 'whether rebuilding llvm should be skipped, overriding `skip-rebuld` in config.toml' -r -f -a "{true\t'',false\t''}"
complete -c x.py -n "__fish_x.py_using_subcommand perf" -l rust-profile-generate -d 'generate PGO profile with rustc build' -r -F
complete -c x.py -n "__fish_x.py_using_subcommand perf" -l rust-profile-use -d 'use PGO profile for rustc build' -r -F
complete -c x.py -n "__fish_x.py_using_subcommand perf" -l llvm-profile-use -d 'use PGO profile for LLVM build' -r -F
diff --git a/src/etc/completions/x.py.ps1 b/src/etc/completions/x.py.ps1
index 240de32..afbfb05 100644
--- a/src/etc/completions/x.py.ps1
+++ b/src/etc/completions/x.py.ps1
@@ -39,7 +39,6 @@
[CompletionResult]::new('--warnings', '--warnings', [CompletionResultType]::ParameterName, 'if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour')
[CompletionResult]::new('--error-format', '--error-format', [CompletionResultType]::ParameterName, 'rustc error format')
[CompletionResult]::new('--color', '--color', [CompletionResultType]::ParameterName, 'whether to use color in cargo and rustc output')
- [CompletionResult]::new('--llvm-skip-rebuild', '--llvm-skip-rebuild', [CompletionResultType]::ParameterName, 'whether rebuilding llvm should be skipped, overriding `skip-rebuld` in config.toml')
[CompletionResult]::new('--rust-profile-generate', '--rust-profile-generate', [CompletionResultType]::ParameterName, 'generate PGO profile with rustc build')
[CompletionResult]::new('--rust-profile-use', '--rust-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for rustc build')
[CompletionResult]::new('--llvm-profile-use', '--llvm-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for LLVM build')
@@ -97,7 +96,6 @@
[CompletionResult]::new('--warnings', '--warnings', [CompletionResultType]::ParameterName, 'if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour')
[CompletionResult]::new('--error-format', '--error-format', [CompletionResultType]::ParameterName, 'rustc error format')
[CompletionResult]::new('--color', '--color', [CompletionResultType]::ParameterName, 'whether to use color in cargo and rustc output')
- [CompletionResult]::new('--llvm-skip-rebuild', '--llvm-skip-rebuild', [CompletionResultType]::ParameterName, 'whether rebuilding llvm should be skipped, overriding `skip-rebuld` in config.toml')
[CompletionResult]::new('--rust-profile-generate', '--rust-profile-generate', [CompletionResultType]::ParameterName, 'generate PGO profile with rustc build')
[CompletionResult]::new('--rust-profile-use', '--rust-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for rustc build')
[CompletionResult]::new('--llvm-profile-use', '--llvm-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for LLVM build')
@@ -138,7 +136,6 @@
[CompletionResult]::new('--warnings', '--warnings', [CompletionResultType]::ParameterName, 'if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour')
[CompletionResult]::new('--error-format', '--error-format', [CompletionResultType]::ParameterName, 'rustc error format')
[CompletionResult]::new('--color', '--color', [CompletionResultType]::ParameterName, 'whether to use color in cargo and rustc output')
- [CompletionResult]::new('--llvm-skip-rebuild', '--llvm-skip-rebuild', [CompletionResultType]::ParameterName, 'whether rebuilding llvm should be skipped, overriding `skip-rebuld` in config.toml')
[CompletionResult]::new('--rust-profile-generate', '--rust-profile-generate', [CompletionResultType]::ParameterName, 'generate PGO profile with rustc build')
[CompletionResult]::new('--rust-profile-use', '--rust-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for rustc build')
[CompletionResult]::new('--llvm-profile-use', '--llvm-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for LLVM build')
@@ -184,7 +181,6 @@
[CompletionResult]::new('--warnings', '--warnings', [CompletionResultType]::ParameterName, 'if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour')
[CompletionResult]::new('--error-format', '--error-format', [CompletionResultType]::ParameterName, 'rustc error format')
[CompletionResult]::new('--color', '--color', [CompletionResultType]::ParameterName, 'whether to use color in cargo and rustc output')
- [CompletionResult]::new('--llvm-skip-rebuild', '--llvm-skip-rebuild', [CompletionResultType]::ParameterName, 'whether rebuilding llvm should be skipped, overriding `skip-rebuld` in config.toml')
[CompletionResult]::new('--rust-profile-generate', '--rust-profile-generate', [CompletionResultType]::ParameterName, 'generate PGO profile with rustc build')
[CompletionResult]::new('--rust-profile-use', '--rust-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for rustc build')
[CompletionResult]::new('--llvm-profile-use', '--llvm-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for LLVM build')
@@ -228,7 +224,6 @@
[CompletionResult]::new('--warnings', '--warnings', [CompletionResultType]::ParameterName, 'if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour')
[CompletionResult]::new('--error-format', '--error-format', [CompletionResultType]::ParameterName, 'rustc error format')
[CompletionResult]::new('--color', '--color', [CompletionResultType]::ParameterName, 'whether to use color in cargo and rustc output')
- [CompletionResult]::new('--llvm-skip-rebuild', '--llvm-skip-rebuild', [CompletionResultType]::ParameterName, 'whether rebuilding llvm should be skipped, overriding `skip-rebuld` in config.toml')
[CompletionResult]::new('--rust-profile-generate', '--rust-profile-generate', [CompletionResultType]::ParameterName, 'generate PGO profile with rustc build')
[CompletionResult]::new('--rust-profile-use', '--rust-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for rustc build')
[CompletionResult]::new('--llvm-profile-use', '--llvm-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for LLVM build')
@@ -269,7 +264,6 @@
[CompletionResult]::new('--warnings', '--warnings', [CompletionResultType]::ParameterName, 'if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour')
[CompletionResult]::new('--error-format', '--error-format', [CompletionResultType]::ParameterName, 'rustc error format')
[CompletionResult]::new('--color', '--color', [CompletionResultType]::ParameterName, 'whether to use color in cargo and rustc output')
- [CompletionResult]::new('--llvm-skip-rebuild', '--llvm-skip-rebuild', [CompletionResultType]::ParameterName, 'whether rebuilding llvm should be skipped, overriding `skip-rebuld` in config.toml')
[CompletionResult]::new('--rust-profile-generate', '--rust-profile-generate', [CompletionResultType]::ParameterName, 'generate PGO profile with rustc build')
[CompletionResult]::new('--rust-profile-use', '--rust-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for rustc build')
[CompletionResult]::new('--llvm-profile-use', '--llvm-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for LLVM build')
@@ -312,7 +306,6 @@
[CompletionResult]::new('--warnings', '--warnings', [CompletionResultType]::ParameterName, 'if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour')
[CompletionResult]::new('--error-format', '--error-format', [CompletionResultType]::ParameterName, 'rustc error format')
[CompletionResult]::new('--color', '--color', [CompletionResultType]::ParameterName, 'whether to use color in cargo and rustc output')
- [CompletionResult]::new('--llvm-skip-rebuild', '--llvm-skip-rebuild', [CompletionResultType]::ParameterName, 'whether rebuilding llvm should be skipped, overriding `skip-rebuld` in config.toml')
[CompletionResult]::new('--rust-profile-generate', '--rust-profile-generate', [CompletionResultType]::ParameterName, 'generate PGO profile with rustc build')
[CompletionResult]::new('--rust-profile-use', '--rust-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for rustc build')
[CompletionResult]::new('--llvm-profile-use', '--llvm-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for LLVM build')
@@ -361,7 +354,6 @@
[CompletionResult]::new('--warnings', '--warnings', [CompletionResultType]::ParameterName, 'if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour')
[CompletionResult]::new('--error-format', '--error-format', [CompletionResultType]::ParameterName, 'rustc error format')
[CompletionResult]::new('--color', '--color', [CompletionResultType]::ParameterName, 'whether to use color in cargo and rustc output')
- [CompletionResult]::new('--llvm-skip-rebuild', '--llvm-skip-rebuild', [CompletionResultType]::ParameterName, 'whether rebuilding llvm should be skipped, overriding `skip-rebuld` in config.toml')
[CompletionResult]::new('--rust-profile-generate', '--rust-profile-generate', [CompletionResultType]::ParameterName, 'generate PGO profile with rustc build')
[CompletionResult]::new('--rust-profile-use', '--rust-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for rustc build')
[CompletionResult]::new('--llvm-profile-use', '--llvm-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for LLVM build')
@@ -410,7 +402,6 @@
[CompletionResult]::new('--warnings', '--warnings', [CompletionResultType]::ParameterName, 'if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour')
[CompletionResult]::new('--error-format', '--error-format', [CompletionResultType]::ParameterName, 'rustc error format')
[CompletionResult]::new('--color', '--color', [CompletionResultType]::ParameterName, 'whether to use color in cargo and rustc output')
- [CompletionResult]::new('--llvm-skip-rebuild', '--llvm-skip-rebuild', [CompletionResultType]::ParameterName, 'whether rebuilding llvm should be skipped, overriding `skip-rebuld` in config.toml')
[CompletionResult]::new('--rust-profile-generate', '--rust-profile-generate', [CompletionResultType]::ParameterName, 'generate PGO profile with rustc build')
[CompletionResult]::new('--rust-profile-use', '--rust-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for rustc build')
[CompletionResult]::new('--llvm-profile-use', '--llvm-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for LLVM build')
@@ -455,7 +446,6 @@
[CompletionResult]::new('--warnings', '--warnings', [CompletionResultType]::ParameterName, 'if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour')
[CompletionResult]::new('--error-format', '--error-format', [CompletionResultType]::ParameterName, 'rustc error format')
[CompletionResult]::new('--color', '--color', [CompletionResultType]::ParameterName, 'whether to use color in cargo and rustc output')
- [CompletionResult]::new('--llvm-skip-rebuild', '--llvm-skip-rebuild', [CompletionResultType]::ParameterName, 'whether rebuilding llvm should be skipped, overriding `skip-rebuld` in config.toml')
[CompletionResult]::new('--rust-profile-generate', '--rust-profile-generate', [CompletionResultType]::ParameterName, 'generate PGO profile with rustc build')
[CompletionResult]::new('--rust-profile-use', '--rust-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for rustc build')
[CompletionResult]::new('--llvm-profile-use', '--llvm-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for LLVM build')
@@ -496,7 +486,6 @@
[CompletionResult]::new('--warnings', '--warnings', [CompletionResultType]::ParameterName, 'if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour')
[CompletionResult]::new('--error-format', '--error-format', [CompletionResultType]::ParameterName, 'rustc error format')
[CompletionResult]::new('--color', '--color', [CompletionResultType]::ParameterName, 'whether to use color in cargo and rustc output')
- [CompletionResult]::new('--llvm-skip-rebuild', '--llvm-skip-rebuild', [CompletionResultType]::ParameterName, 'whether rebuilding llvm should be skipped, overriding `skip-rebuld` in config.toml')
[CompletionResult]::new('--rust-profile-generate', '--rust-profile-generate', [CompletionResultType]::ParameterName, 'generate PGO profile with rustc build')
[CompletionResult]::new('--rust-profile-use', '--rust-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for rustc build')
[CompletionResult]::new('--llvm-profile-use', '--llvm-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for LLVM build')
@@ -538,7 +527,6 @@
[CompletionResult]::new('--warnings', '--warnings', [CompletionResultType]::ParameterName, 'if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour')
[CompletionResult]::new('--error-format', '--error-format', [CompletionResultType]::ParameterName, 'rustc error format')
[CompletionResult]::new('--color', '--color', [CompletionResultType]::ParameterName, 'whether to use color in cargo and rustc output')
- [CompletionResult]::new('--llvm-skip-rebuild', '--llvm-skip-rebuild', [CompletionResultType]::ParameterName, 'whether rebuilding llvm should be skipped, overriding `skip-rebuld` in config.toml')
[CompletionResult]::new('--rust-profile-generate', '--rust-profile-generate', [CompletionResultType]::ParameterName, 'generate PGO profile with rustc build')
[CompletionResult]::new('--rust-profile-use', '--rust-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for rustc build')
[CompletionResult]::new('--llvm-profile-use', '--llvm-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for LLVM build')
@@ -579,7 +567,6 @@
[CompletionResult]::new('--warnings', '--warnings', [CompletionResultType]::ParameterName, 'if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour')
[CompletionResult]::new('--error-format', '--error-format', [CompletionResultType]::ParameterName, 'rustc error format')
[CompletionResult]::new('--color', '--color', [CompletionResultType]::ParameterName, 'whether to use color in cargo and rustc output')
- [CompletionResult]::new('--llvm-skip-rebuild', '--llvm-skip-rebuild', [CompletionResultType]::ParameterName, 'whether rebuilding llvm should be skipped, overriding `skip-rebuld` in config.toml')
[CompletionResult]::new('--rust-profile-generate', '--rust-profile-generate', [CompletionResultType]::ParameterName, 'generate PGO profile with rustc build')
[CompletionResult]::new('--rust-profile-use', '--rust-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for rustc build')
[CompletionResult]::new('--llvm-profile-use', '--llvm-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for LLVM build')
@@ -621,7 +608,6 @@
[CompletionResult]::new('--warnings', '--warnings', [CompletionResultType]::ParameterName, 'if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour')
[CompletionResult]::new('--error-format', '--error-format', [CompletionResultType]::ParameterName, 'rustc error format')
[CompletionResult]::new('--color', '--color', [CompletionResultType]::ParameterName, 'whether to use color in cargo and rustc output')
- [CompletionResult]::new('--llvm-skip-rebuild', '--llvm-skip-rebuild', [CompletionResultType]::ParameterName, 'whether rebuilding llvm should be skipped, overriding `skip-rebuld` in config.toml')
[CompletionResult]::new('--rust-profile-generate', '--rust-profile-generate', [CompletionResultType]::ParameterName, 'generate PGO profile with rustc build')
[CompletionResult]::new('--rust-profile-use', '--rust-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for rustc build')
[CompletionResult]::new('--llvm-profile-use', '--llvm-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for LLVM build')
@@ -662,7 +648,6 @@
[CompletionResult]::new('--warnings', '--warnings', [CompletionResultType]::ParameterName, 'if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour')
[CompletionResult]::new('--error-format', '--error-format', [CompletionResultType]::ParameterName, 'rustc error format')
[CompletionResult]::new('--color', '--color', [CompletionResultType]::ParameterName, 'whether to use color in cargo and rustc output')
- [CompletionResult]::new('--llvm-skip-rebuild', '--llvm-skip-rebuild', [CompletionResultType]::ParameterName, 'whether rebuilding llvm should be skipped, overriding `skip-rebuld` in config.toml')
[CompletionResult]::new('--rust-profile-generate', '--rust-profile-generate', [CompletionResultType]::ParameterName, 'generate PGO profile with rustc build')
[CompletionResult]::new('--rust-profile-use', '--rust-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for rustc build')
[CompletionResult]::new('--llvm-profile-use', '--llvm-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for LLVM build')
@@ -703,7 +688,6 @@
[CompletionResult]::new('--warnings', '--warnings', [CompletionResultType]::ParameterName, 'if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour')
[CompletionResult]::new('--error-format', '--error-format', [CompletionResultType]::ParameterName, 'rustc error format')
[CompletionResult]::new('--color', '--color', [CompletionResultType]::ParameterName, 'whether to use color in cargo and rustc output')
- [CompletionResult]::new('--llvm-skip-rebuild', '--llvm-skip-rebuild', [CompletionResultType]::ParameterName, 'whether rebuilding llvm should be skipped, overriding `skip-rebuld` in config.toml')
[CompletionResult]::new('--rust-profile-generate', '--rust-profile-generate', [CompletionResultType]::ParameterName, 'generate PGO profile with rustc build')
[CompletionResult]::new('--rust-profile-use', '--rust-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for rustc build')
[CompletionResult]::new('--llvm-profile-use', '--llvm-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for LLVM build')
@@ -746,7 +730,6 @@
[CompletionResult]::new('--warnings', '--warnings', [CompletionResultType]::ParameterName, 'if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour')
[CompletionResult]::new('--error-format', '--error-format', [CompletionResultType]::ParameterName, 'rustc error format')
[CompletionResult]::new('--color', '--color', [CompletionResultType]::ParameterName, 'whether to use color in cargo and rustc output')
- [CompletionResult]::new('--llvm-skip-rebuild', '--llvm-skip-rebuild', [CompletionResultType]::ParameterName, 'whether rebuilding llvm should be skipped, overriding `skip-rebuld` in config.toml')
[CompletionResult]::new('--rust-profile-generate', '--rust-profile-generate', [CompletionResultType]::ParameterName, 'generate PGO profile with rustc build')
[CompletionResult]::new('--rust-profile-use', '--rust-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for rustc build')
[CompletionResult]::new('--llvm-profile-use', '--llvm-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for LLVM build')
@@ -788,7 +771,6 @@
[CompletionResult]::new('--warnings', '--warnings', [CompletionResultType]::ParameterName, 'if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour')
[CompletionResult]::new('--error-format', '--error-format', [CompletionResultType]::ParameterName, 'rustc error format')
[CompletionResult]::new('--color', '--color', [CompletionResultType]::ParameterName, 'whether to use color in cargo and rustc output')
- [CompletionResult]::new('--llvm-skip-rebuild', '--llvm-skip-rebuild', [CompletionResultType]::ParameterName, 'whether rebuilding llvm should be skipped, overriding `skip-rebuld` in config.toml')
[CompletionResult]::new('--rust-profile-generate', '--rust-profile-generate', [CompletionResultType]::ParameterName, 'generate PGO profile with rustc build')
[CompletionResult]::new('--rust-profile-use', '--rust-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for rustc build')
[CompletionResult]::new('--llvm-profile-use', '--llvm-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for LLVM build')
diff --git a/src/etc/completions/x.py.sh b/src/etc/completions/x.py.sh
index b1730e5..2aa0d9f 100644
--- a/src/etc/completions/x.py.sh
+++ b/src/etc/completions/x.py.sh
@@ -70,7 +70,7 @@
case "${cmd}" in
x.py)
- opts="-v -i -j -h --verbose --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --bypass-bootstrap-lock --llvm-skip-rebuild --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --help [PATHS]... [ARGS]... build check clippy fix fmt doc test miri bench clean dist install run setup suggest vendor perf"
+ opts="-v -i -j -h --verbose --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --bypass-bootstrap-lock --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --help [PATHS]... [ARGS]... build check clippy fix fmt doc test miri bench clean dist install run setup suggest vendor perf"
if [[ ${cur} == -* || ${COMP_CWORD} -eq 1 ]] ; then
COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
return 0
@@ -195,10 +195,6 @@
COMPREPLY=($(compgen -W "always never auto" -- "${cur}"))
return 0
;;
- --llvm-skip-rebuild)
- COMPREPLY=($(compgen -W "true false" -- "${cur}"))
- return 0
- ;;
--rust-profile-generate)
local oldifs
if [ -n "${IFS+x}" ]; then
@@ -263,7 +259,7 @@
return 0
;;
x.py__bench)
- opts="-v -i -j -h --test-args --verbose --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --bypass-bootstrap-lock --llvm-skip-rebuild --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --help [PATHS]... [ARGS]..."
+ opts="-v -i -j -h --test-args --verbose --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --bypass-bootstrap-lock --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --help [PATHS]... [ARGS]..."
if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then
COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
return 0
@@ -392,10 +388,6 @@
COMPREPLY=($(compgen -W "always never auto" -- "${cur}"))
return 0
;;
- --llvm-skip-rebuild)
- COMPREPLY=($(compgen -W "true false" -- "${cur}"))
- return 0
- ;;
--rust-profile-generate)
local oldifs
if [ -n "${IFS+x}" ]; then
@@ -460,7 +452,7 @@
return 0
;;
x.py__build)
- opts="-v -i -j -h --verbose --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --bypass-bootstrap-lock --llvm-skip-rebuild --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --help [PATHS]... [ARGS]..."
+ opts="-v -i -j -h --verbose --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --bypass-bootstrap-lock --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --help [PATHS]... [ARGS]..."
if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then
COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
return 0
@@ -585,10 +577,6 @@
COMPREPLY=($(compgen -W "always never auto" -- "${cur}"))
return 0
;;
- --llvm-skip-rebuild)
- COMPREPLY=($(compgen -W "true false" -- "${cur}"))
- return 0
- ;;
--rust-profile-generate)
local oldifs
if [ -n "${IFS+x}" ]; then
@@ -653,7 +641,7 @@
return 0
;;
x.py__check)
- opts="-v -i -j -h --all-targets --verbose --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --bypass-bootstrap-lock --llvm-skip-rebuild --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --help [PATHS]... [ARGS]..."
+ opts="-v -i -j -h --all-targets --verbose --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --bypass-bootstrap-lock --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --help [PATHS]... [ARGS]..."
if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then
COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
return 0
@@ -778,10 +766,6 @@
COMPREPLY=($(compgen -W "always never auto" -- "${cur}"))
return 0
;;
- --llvm-skip-rebuild)
- COMPREPLY=($(compgen -W "true false" -- "${cur}"))
- return 0
- ;;
--rust-profile-generate)
local oldifs
if [ -n "${IFS+x}" ]; then
@@ -846,7 +830,7 @@
return 0
;;
x.py__clean)
- opts="-v -i -j -h --all --stage --verbose --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --bypass-bootstrap-lock --llvm-skip-rebuild --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --help [PATHS]... [ARGS]..."
+ opts="-v -i -j -h --all --stage --verbose --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --bypass-bootstrap-lock --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --help [PATHS]... [ARGS]..."
if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then
COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
return 0
@@ -968,10 +952,6 @@
COMPREPLY=($(compgen -W "always never auto" -- "${cur}"))
return 0
;;
- --llvm-skip-rebuild)
- COMPREPLY=($(compgen -W "true false" -- "${cur}"))
- return 0
- ;;
--rust-profile-generate)
local oldifs
if [ -n "${IFS+x}" ]; then
@@ -1036,7 +1016,7 @@
return 0
;;
x.py__clippy)
- opts="-A -D -W -F -v -i -j -h --fix --allow-dirty --allow-staged --verbose --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --bypass-bootstrap-lock --llvm-skip-rebuild --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --help [PATHS]... [ARGS]..."
+ opts="-A -D -W -F -v -i -j -h --fix --allow-dirty --allow-staged --verbose --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --bypass-bootstrap-lock --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --help [PATHS]... [ARGS]..."
if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then
COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
return 0
@@ -1177,10 +1157,6 @@
COMPREPLY=($(compgen -W "always never auto" -- "${cur}"))
return 0
;;
- --llvm-skip-rebuild)
- COMPREPLY=($(compgen -W "true false" -- "${cur}"))
- return 0
- ;;
--rust-profile-generate)
local oldifs
if [ -n "${IFS+x}" ]; then
@@ -1245,7 +1221,7 @@
return 0
;;
x.py__dist)
- opts="-v -i -j -h --verbose --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --bypass-bootstrap-lock --llvm-skip-rebuild --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --help [PATHS]... [ARGS]..."
+ opts="-v -i -j -h --verbose --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --bypass-bootstrap-lock --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --help [PATHS]... [ARGS]..."
if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then
COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
return 0
@@ -1370,10 +1346,6 @@
COMPREPLY=($(compgen -W "always never auto" -- "${cur}"))
return 0
;;
- --llvm-skip-rebuild)
- COMPREPLY=($(compgen -W "true false" -- "${cur}"))
- return 0
- ;;
--rust-profile-generate)
local oldifs
if [ -n "${IFS+x}" ]; then
@@ -1438,7 +1410,7 @@
return 0
;;
x.py__doc)
- opts="-v -i -j -h --open --json --verbose --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --bypass-bootstrap-lock --llvm-skip-rebuild --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --help [PATHS]... [ARGS]..."
+ opts="-v -i -j -h --open --json --verbose --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --bypass-bootstrap-lock --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --help [PATHS]... [ARGS]..."
if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then
COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
return 0
@@ -1563,10 +1535,6 @@
COMPREPLY=($(compgen -W "always never auto" -- "${cur}"))
return 0
;;
- --llvm-skip-rebuild)
- COMPREPLY=($(compgen -W "true false" -- "${cur}"))
- return 0
- ;;
--rust-profile-generate)
local oldifs
if [ -n "${IFS+x}" ]; then
@@ -1631,7 +1599,7 @@
return 0
;;
x.py__fix)
- opts="-v -i -j -h --verbose --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --bypass-bootstrap-lock --llvm-skip-rebuild --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --help [PATHS]... [ARGS]..."
+ opts="-v -i -j -h --verbose --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --bypass-bootstrap-lock --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --help [PATHS]... [ARGS]..."
if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then
COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
return 0
@@ -1756,10 +1724,6 @@
COMPREPLY=($(compgen -W "always never auto" -- "${cur}"))
return 0
;;
- --llvm-skip-rebuild)
- COMPREPLY=($(compgen -W "true false" -- "${cur}"))
- return 0
- ;;
--rust-profile-generate)
local oldifs
if [ -n "${IFS+x}" ]; then
@@ -1824,7 +1788,7 @@
return 0
;;
x.py__fmt)
- opts="-v -i -j -h --check --all --verbose --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --bypass-bootstrap-lock --llvm-skip-rebuild --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --help [PATHS]... [ARGS]..."
+ opts="-v -i -j -h --check --all --verbose --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --bypass-bootstrap-lock --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --help [PATHS]... [ARGS]..."
if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then
COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
return 0
@@ -1949,10 +1913,6 @@
COMPREPLY=($(compgen -W "always never auto" -- "${cur}"))
return 0
;;
- --llvm-skip-rebuild)
- COMPREPLY=($(compgen -W "true false" -- "${cur}"))
- return 0
- ;;
--rust-profile-generate)
local oldifs
if [ -n "${IFS+x}" ]; then
@@ -2017,7 +1977,7 @@
return 0
;;
x.py__install)
- opts="-v -i -j -h --verbose --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --bypass-bootstrap-lock --llvm-skip-rebuild --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --help [PATHS]... [ARGS]..."
+ opts="-v -i -j -h --verbose --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --bypass-bootstrap-lock --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --help [PATHS]... [ARGS]..."
if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then
COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
return 0
@@ -2142,10 +2102,6 @@
COMPREPLY=($(compgen -W "always never auto" -- "${cur}"))
return 0
;;
- --llvm-skip-rebuild)
- COMPREPLY=($(compgen -W "true false" -- "${cur}"))
- return 0
- ;;
--rust-profile-generate)
local oldifs
if [ -n "${IFS+x}" ]; then
@@ -2210,7 +2166,7 @@
return 0
;;
x.py__miri)
- opts="-v -i -j -h --no-fail-fast --test-args --no-doc --doc --verbose --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --bypass-bootstrap-lock --llvm-skip-rebuild --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --help [PATHS]... [ARGS]..."
+ opts="-v -i -j -h --no-fail-fast --test-args --no-doc --doc --verbose --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --bypass-bootstrap-lock --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --help [PATHS]... [ARGS]..."
if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then
COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
return 0
@@ -2339,10 +2295,6 @@
COMPREPLY=($(compgen -W "always never auto" -- "${cur}"))
return 0
;;
- --llvm-skip-rebuild)
- COMPREPLY=($(compgen -W "true false" -- "${cur}"))
- return 0
- ;;
--rust-profile-generate)
local oldifs
if [ -n "${IFS+x}" ]; then
@@ -2407,7 +2359,7 @@
return 0
;;
x.py__perf)
- opts="-v -i -j -h --verbose --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --bypass-bootstrap-lock --llvm-skip-rebuild --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --help [PATHS]... [ARGS]..."
+ opts="-v -i -j -h --verbose --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --bypass-bootstrap-lock --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --help [PATHS]... [ARGS]..."
if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then
COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
return 0
@@ -2532,10 +2484,6 @@
COMPREPLY=($(compgen -W "always never auto" -- "${cur}"))
return 0
;;
- --llvm-skip-rebuild)
- COMPREPLY=($(compgen -W "true false" -- "${cur}"))
- return 0
- ;;
--rust-profile-generate)
local oldifs
if [ -n "${IFS+x}" ]; then
@@ -2600,7 +2548,7 @@
return 0
;;
x.py__run)
- opts="-v -i -j -h --args --verbose --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --bypass-bootstrap-lock --llvm-skip-rebuild --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --help [PATHS]... [ARGS]..."
+ opts="-v -i -j -h --args --verbose --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --bypass-bootstrap-lock --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --help [PATHS]... [ARGS]..."
if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then
COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
return 0
@@ -2729,10 +2677,6 @@
COMPREPLY=($(compgen -W "always never auto" -- "${cur}"))
return 0
;;
- --llvm-skip-rebuild)
- COMPREPLY=($(compgen -W "true false" -- "${cur}"))
- return 0
- ;;
--rust-profile-generate)
local oldifs
if [ -n "${IFS+x}" ]; then
@@ -2797,7 +2741,7 @@
return 0
;;
x.py__setup)
- opts="-v -i -j -h --verbose --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --bypass-bootstrap-lock --llvm-skip-rebuild --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --help [<PROFILE>|hook|vscode|link] [PATHS]... [ARGS]..."
+ opts="-v -i -j -h --verbose --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --bypass-bootstrap-lock --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --help [<PROFILE>|hook|vscode|link] [PATHS]... [ARGS]..."
if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then
COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
return 0
@@ -2922,10 +2866,6 @@
COMPREPLY=($(compgen -W "always never auto" -- "${cur}"))
return 0
;;
- --llvm-skip-rebuild)
- COMPREPLY=($(compgen -W "true false" -- "${cur}"))
- return 0
- ;;
--rust-profile-generate)
local oldifs
if [ -n "${IFS+x}" ]; then
@@ -2990,7 +2930,7 @@
return 0
;;
x.py__suggest)
- opts="-v -i -j -h --run --verbose --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --bypass-bootstrap-lock --llvm-skip-rebuild --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --help [PATHS]... [ARGS]..."
+ opts="-v -i -j -h --run --verbose --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --bypass-bootstrap-lock --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --help [PATHS]... [ARGS]..."
if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then
COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
return 0
@@ -3115,10 +3055,6 @@
COMPREPLY=($(compgen -W "always never auto" -- "${cur}"))
return 0
;;
- --llvm-skip-rebuild)
- COMPREPLY=($(compgen -W "true false" -- "${cur}"))
- return 0
- ;;
--rust-profile-generate)
local oldifs
if [ -n "${IFS+x}" ]; then
@@ -3183,7 +3119,7 @@
return 0
;;
x.py__test)
- opts="-v -i -j -h --no-fail-fast --test-args --compiletest-rustc-args --no-doc --doc --bless --extra-checks --force-rerun --only-modified --compare-mode --pass --run --rustfix-coverage --verbose --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --bypass-bootstrap-lock --llvm-skip-rebuild --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --help [PATHS]... [ARGS]..."
+ opts="-v -i -j -h --no-fail-fast --test-args --compiletest-rustc-args --no-doc --doc --bless --extra-checks --force-rerun --only-modified --compare-mode --pass --run --rustfix-coverage --verbose --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --bypass-bootstrap-lock --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --help [PATHS]... [ARGS]..."
if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then
COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
return 0
@@ -3332,10 +3268,6 @@
COMPREPLY=($(compgen -W "always never auto" -- "${cur}"))
return 0
;;
- --llvm-skip-rebuild)
- COMPREPLY=($(compgen -W "true false" -- "${cur}"))
- return 0
- ;;
--rust-profile-generate)
local oldifs
if [ -n "${IFS+x}" ]; then
@@ -3400,7 +3332,7 @@
return 0
;;
x.py__vendor)
- opts="-v -i -j -h --sync --versioned-dirs --verbose --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --bypass-bootstrap-lock --llvm-skip-rebuild --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --help [PATHS]... [ARGS]..."
+ opts="-v -i -j -h --sync --versioned-dirs --verbose --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --bypass-bootstrap-lock --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --help [PATHS]... [ARGS]..."
if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then
COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
return 0
@@ -3529,10 +3461,6 @@
COMPREPLY=($(compgen -W "always never auto" -- "${cur}"))
return 0
;;
- --llvm-skip-rebuild)
- COMPREPLY=($(compgen -W "true false" -- "${cur}"))
- return 0
- ;;
--rust-profile-generate)
local oldifs
if [ -n "${IFS+x}" ]; then
diff --git a/src/etc/completions/x.py.zsh b/src/etc/completions/x.py.zsh
index ae076b8..c47937a 100644
--- a/src/etc/completions/x.py.zsh
+++ b/src/etc/completions/x.py.zsh
@@ -33,7 +33,6 @@
'--warnings=[if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour]:deny|warn:(deny warn default)' \
'--error-format=[rustc error format]:FORMAT:( )' \
'--color=[whether to use color in cargo and rustc output]:STYLE:(always never auto)' \
-'--llvm-skip-rebuild=[whether rebuilding llvm should be skipped, overriding \`skip-rebuld\` in config.toml]:VALUE:(true false)' \
'--rust-profile-generate=[generate PGO profile with rustc build]:PROFILE:_files' \
'--rust-profile-use=[use PGO profile for rustc build]:PROFILE:_files' \
'--llvm-profile-use=[use PGO profile for LLVM build]:PROFILE:_files' \
@@ -84,7 +83,6 @@
'--warnings=[if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour]:deny|warn:(deny warn default)' \
'--error-format=[rustc error format]:FORMAT:( )' \
'--color=[whether to use color in cargo and rustc output]:STYLE:(always never auto)' \
-'--llvm-skip-rebuild=[whether rebuilding llvm should be skipped, overriding \`skip-rebuld\` in config.toml]:VALUE:(true false)' \
'--rust-profile-generate=[generate PGO profile with rustc build]:PROFILE:_files' \
'--rust-profile-use=[use PGO profile for rustc build]:PROFILE:_files' \
'--llvm-profile-use=[use PGO profile for LLVM build]:PROFILE:_files' \
@@ -127,7 +125,6 @@
'--warnings=[if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour]:deny|warn:(deny warn default)' \
'--error-format=[rustc error format]:FORMAT:( )' \
'--color=[whether to use color in cargo and rustc output]:STYLE:(always never auto)' \
-'--llvm-skip-rebuild=[whether rebuilding llvm should be skipped, overriding \`skip-rebuld\` in config.toml]:VALUE:(true false)' \
'--rust-profile-generate=[generate PGO profile with rustc build]:PROFILE:_files' \
'--rust-profile-use=[use PGO profile for rustc build]:PROFILE:_files' \
'--llvm-profile-use=[use PGO profile for LLVM build]:PROFILE:_files' \
@@ -175,7 +172,6 @@
'--warnings=[if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour]:deny|warn:(deny warn default)' \
'--error-format=[rustc error format]:FORMAT:( )' \
'--color=[whether to use color in cargo and rustc output]:STYLE:(always never auto)' \
-'--llvm-skip-rebuild=[whether rebuilding llvm should be skipped, overriding \`skip-rebuld\` in config.toml]:VALUE:(true false)' \
'--rust-profile-generate=[generate PGO profile with rustc build]:PROFILE:_files' \
'--rust-profile-use=[use PGO profile for rustc build]:PROFILE:_files' \
'--llvm-profile-use=[use PGO profile for LLVM build]:PROFILE:_files' \
@@ -221,7 +217,6 @@
'--warnings=[if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour]:deny|warn:(deny warn default)' \
'--error-format=[rustc error format]:FORMAT:( )' \
'--color=[whether to use color in cargo and rustc output]:STYLE:(always never auto)' \
-'--llvm-skip-rebuild=[whether rebuilding llvm should be skipped, overriding \`skip-rebuld\` in config.toml]:VALUE:(true false)' \
'--rust-profile-generate=[generate PGO profile with rustc build]:PROFILE:_files' \
'--rust-profile-use=[use PGO profile for rustc build]:PROFILE:_files' \
'--llvm-profile-use=[use PGO profile for LLVM build]:PROFILE:_files' \
@@ -264,7 +259,6 @@
'--warnings=[if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour]:deny|warn:(deny warn default)' \
'--error-format=[rustc error format]:FORMAT:( )' \
'--color=[whether to use color in cargo and rustc output]:STYLE:(always never auto)' \
-'--llvm-skip-rebuild=[whether rebuilding llvm should be skipped, overriding \`skip-rebuld\` in config.toml]:VALUE:(true false)' \
'--rust-profile-generate=[generate PGO profile with rustc build]:PROFILE:_files' \
'--rust-profile-use=[use PGO profile for rustc build]:PROFILE:_files' \
'--llvm-profile-use=[use PGO profile for LLVM build]:PROFILE:_files' \
@@ -309,7 +303,6 @@
'--warnings=[if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour]:deny|warn:(deny warn default)' \
'--error-format=[rustc error format]:FORMAT:( )' \
'--color=[whether to use color in cargo and rustc output]:STYLE:(always never auto)' \
-'--llvm-skip-rebuild=[whether rebuilding llvm should be skipped, overriding \`skip-rebuld\` in config.toml]:VALUE:(true false)' \
'--rust-profile-generate=[generate PGO profile with rustc build]:PROFILE:_files' \
'--rust-profile-use=[use PGO profile for rustc build]:PROFILE:_files' \
'--llvm-profile-use=[use PGO profile for LLVM build]:PROFILE:_files' \
@@ -360,7 +353,6 @@
'--warnings=[if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour]:deny|warn:(deny warn default)' \
'--error-format=[rustc error format]:FORMAT:( )' \
'--color=[whether to use color in cargo and rustc output]:STYLE:(always never auto)' \
-'--llvm-skip-rebuild=[whether rebuilding llvm should be skipped, overriding \`skip-rebuld\` in config.toml]:VALUE:(true false)' \
'--rust-profile-generate=[generate PGO profile with rustc build]:PROFILE:_files' \
'--rust-profile-use=[use PGO profile for rustc build]:PROFILE:_files' \
'--llvm-profile-use=[use PGO profile for LLVM build]:PROFILE:_files' \
@@ -411,7 +403,6 @@
'--warnings=[if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour]:deny|warn:(deny warn default)' \
'--error-format=[rustc error format]:FORMAT:( )' \
'--color=[whether to use color in cargo and rustc output]:STYLE:(always never auto)' \
-'--llvm-skip-rebuild=[whether rebuilding llvm should be skipped, overriding \`skip-rebuld\` in config.toml]:VALUE:(true false)' \
'--rust-profile-generate=[generate PGO profile with rustc build]:PROFILE:_files' \
'--rust-profile-use=[use PGO profile for rustc build]:PROFILE:_files' \
'--llvm-profile-use=[use PGO profile for LLVM build]:PROFILE:_files' \
@@ -458,7 +449,6 @@
'--warnings=[if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour]:deny|warn:(deny warn default)' \
'--error-format=[rustc error format]:FORMAT:( )' \
'--color=[whether to use color in cargo and rustc output]:STYLE:(always never auto)' \
-'--llvm-skip-rebuild=[whether rebuilding llvm should be skipped, overriding \`skip-rebuld\` in config.toml]:VALUE:(true false)' \
'--rust-profile-generate=[generate PGO profile with rustc build]:PROFILE:_files' \
'--rust-profile-use=[use PGO profile for rustc build]:PROFILE:_files' \
'--llvm-profile-use=[use PGO profile for LLVM build]:PROFILE:_files' \
@@ -501,7 +491,6 @@
'--warnings=[if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour]:deny|warn:(deny warn default)' \
'--error-format=[rustc error format]:FORMAT:( )' \
'--color=[whether to use color in cargo and rustc output]:STYLE:(always never auto)' \
-'--llvm-skip-rebuild=[whether rebuilding llvm should be skipped, overriding \`skip-rebuld\` in config.toml]:VALUE:(true false)' \
'--rust-profile-generate=[generate PGO profile with rustc build]:PROFILE:_files' \
'--rust-profile-use=[use PGO profile for rustc build]:PROFILE:_files' \
'--llvm-profile-use=[use PGO profile for LLVM build]:PROFILE:_files' \
@@ -545,7 +534,6 @@
'--warnings=[if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour]:deny|warn:(deny warn default)' \
'--error-format=[rustc error format]:FORMAT:( )' \
'--color=[whether to use color in cargo and rustc output]:STYLE:(always never auto)' \
-'--llvm-skip-rebuild=[whether rebuilding llvm should be skipped, overriding \`skip-rebuld\` in config.toml]:VALUE:(true false)' \
'--rust-profile-generate=[generate PGO profile with rustc build]:PROFILE:_files' \
'--rust-profile-use=[use PGO profile for rustc build]:PROFILE:_files' \
'--llvm-profile-use=[use PGO profile for LLVM build]:PROFILE:_files' \
@@ -588,7 +576,6 @@
'--warnings=[if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour]:deny|warn:(deny warn default)' \
'--error-format=[rustc error format]:FORMAT:( )' \
'--color=[whether to use color in cargo and rustc output]:STYLE:(always never auto)' \
-'--llvm-skip-rebuild=[whether rebuilding llvm should be skipped, overriding \`skip-rebuld\` in config.toml]:VALUE:(true false)' \
'--rust-profile-generate=[generate PGO profile with rustc build]:PROFILE:_files' \
'--rust-profile-use=[use PGO profile for rustc build]:PROFILE:_files' \
'--llvm-profile-use=[use PGO profile for LLVM build]:PROFILE:_files' \
@@ -632,7 +619,6 @@
'--warnings=[if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour]:deny|warn:(deny warn default)' \
'--error-format=[rustc error format]:FORMAT:( )' \
'--color=[whether to use color in cargo and rustc output]:STYLE:(always never auto)' \
-'--llvm-skip-rebuild=[whether rebuilding llvm should be skipped, overriding \`skip-rebuld\` in config.toml]:VALUE:(true false)' \
'--rust-profile-generate=[generate PGO profile with rustc build]:PROFILE:_files' \
'--rust-profile-use=[use PGO profile for rustc build]:PROFILE:_files' \
'--llvm-profile-use=[use PGO profile for LLVM build]:PROFILE:_files' \
@@ -675,7 +661,6 @@
'--warnings=[if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour]:deny|warn:(deny warn default)' \
'--error-format=[rustc error format]:FORMAT:( )' \
'--color=[whether to use color in cargo and rustc output]:STYLE:(always never auto)' \
-'--llvm-skip-rebuild=[whether rebuilding llvm should be skipped, overriding \`skip-rebuld\` in config.toml]:VALUE:(true false)' \
'--rust-profile-generate=[generate PGO profile with rustc build]:PROFILE:_files' \
'--rust-profile-use=[use PGO profile for rustc build]:PROFILE:_files' \
'--llvm-profile-use=[use PGO profile for LLVM build]:PROFILE:_files' \
@@ -719,7 +704,6 @@
'--warnings=[if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour]:deny|warn:(deny warn default)' \
'--error-format=[rustc error format]:FORMAT:( )' \
'--color=[whether to use color in cargo and rustc output]:STYLE:(always never auto)' \
-'--llvm-skip-rebuild=[whether rebuilding llvm should be skipped, overriding \`skip-rebuld\` in config.toml]:VALUE:(true false)' \
'--rust-profile-generate=[generate PGO profile with rustc build]:PROFILE:_files' \
'--rust-profile-use=[use PGO profile for rustc build]:PROFILE:_files' \
'--llvm-profile-use=[use PGO profile for LLVM build]:PROFILE:_files' \
@@ -764,7 +748,6 @@
'--warnings=[if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour]:deny|warn:(deny warn default)' \
'--error-format=[rustc error format]:FORMAT:( )' \
'--color=[whether to use color in cargo and rustc output]:STYLE:(always never auto)' \
-'--llvm-skip-rebuild=[whether rebuilding llvm should be skipped, overriding \`skip-rebuld\` in config.toml]:VALUE:(true false)' \
'--rust-profile-generate=[generate PGO profile with rustc build]:PROFILE:_files' \
'--rust-profile-use=[use PGO profile for rustc build]:PROFILE:_files' \
'--llvm-profile-use=[use PGO profile for LLVM build]:PROFILE:_files' \
@@ -808,7 +791,6 @@
'--warnings=[if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour]:deny|warn:(deny warn default)' \
'--error-format=[rustc error format]:FORMAT:( )' \
'--color=[whether to use color in cargo and rustc output]:STYLE:(always never auto)' \
-'--llvm-skip-rebuild=[whether rebuilding llvm should be skipped, overriding \`skip-rebuld\` in config.toml]:VALUE:(true false)' \
'--rust-profile-generate=[generate PGO profile with rustc build]:PROFILE:_files' \
'--rust-profile-use=[use PGO profile for rustc build]:PROFILE:_files' \
'--llvm-profile-use=[use PGO profile for LLVM build]:PROFILE:_files' \
diff --git a/src/librustdoc/clean/auto_trait.rs b/src/librustdoc/clean/auto_trait.rs
index 6549010..7e3881c 100644
--- a/src/librustdoc/clean/auto_trait.rs
+++ b/src/librustdoc/clean/auto_trait.rs
@@ -115,17 +115,19 @@ fn synthesize_auto_trait_impl<'tcx>(
Some(clean::Item {
name: None,
- attrs: Default::default(),
+ inner: Box::new(clean::ItemInner {
+ attrs: Default::default(),
+ kind: clean::ImplItem(Box::new(clean::Impl {
+ safety: hir::Safety::Safe,
+ generics,
+ trait_: Some(clean_trait_ref_with_constraints(cx, trait_ref, ThinVec::new())),
+ for_: clean_middle_ty(ty::Binder::dummy(ty), cx, None, None),
+ items: Vec::new(),
+ polarity,
+ kind: clean::ImplKind::Auto,
+ })),
+ }),
item_id: clean::ItemId::Auto { trait_: trait_def_id, for_: item_def_id },
- kind: Box::new(clean::ImplItem(Box::new(clean::Impl {
- safety: hir::Safety::Safe,
- generics,
- trait_: Some(clean_trait_ref_with_constraints(cx, trait_ref, ThinVec::new())),
- for_: clean_middle_ty(ty::Binder::dummy(ty), cx, None, None),
- items: Vec::new(),
- polarity,
- kind: clean::ImplKind::Auto,
- }))),
cfg: None,
inline_stmt_id: None,
})
diff --git a/src/librustdoc/clean/blanket_impl.rs b/src/librustdoc/clean/blanket_impl.rs
index 1f5f660..95f6616 100644
--- a/src/librustdoc/clean/blanket_impl.rs
+++ b/src/librustdoc/clean/blanket_impl.rs
@@ -84,42 +84,44 @@ pub(crate) fn synthesize_blanket_impls(
blanket_impls.push(clean::Item {
name: None,
- attrs: Default::default(),
item_id: clean::ItemId::Blanket { impl_id: impl_def_id, for_: item_def_id },
- kind: Box::new(clean::ImplItem(Box::new(clean::Impl {
- safety: hir::Safety::Safe,
- generics: clean_ty_generics(
- cx,
- tcx.generics_of(impl_def_id),
- tcx.explicit_predicates_of(impl_def_id),
- ),
- // FIXME(eddyb) compute both `trait_` and `for_` from
- // the post-inference `trait_ref`, as it's more accurate.
- trait_: Some(clean_trait_ref_with_constraints(
- cx,
- ty::Binder::dummy(trait_ref.instantiate_identity()),
- ThinVec::new(),
- )),
- for_: clean_middle_ty(
- ty::Binder::dummy(ty.instantiate_identity()),
- cx,
- None,
- None,
- ),
- items: tcx
- .associated_items(impl_def_id)
- .in_definition_order()
- .filter(|item| !item.is_impl_trait_in_trait())
- .map(|item| clean_middle_assoc_item(item, cx))
- .collect(),
- polarity: ty::ImplPolarity::Positive,
- kind: clean::ImplKind::Blanket(Box::new(clean_middle_ty(
- ty::Binder::dummy(trait_ref.instantiate_identity().self_ty()),
- cx,
- None,
- None,
- ))),
- }))),
+ inner: Box::new(clean::ItemInner {
+ attrs: Default::default(),
+ kind: clean::ImplItem(Box::new(clean::Impl {
+ safety: hir::Safety::Safe,
+ generics: clean_ty_generics(
+ cx,
+ tcx.generics_of(impl_def_id),
+ tcx.explicit_predicates_of(impl_def_id),
+ ),
+ // FIXME(eddyb) compute both `trait_` and `for_` from
+ // the post-inference `trait_ref`, as it's more accurate.
+ trait_: Some(clean_trait_ref_with_constraints(
+ cx,
+ ty::Binder::dummy(trait_ref.instantiate_identity()),
+ ThinVec::new(),
+ )),
+ for_: clean_middle_ty(
+ ty::Binder::dummy(ty.instantiate_identity()),
+ cx,
+ None,
+ None,
+ ),
+ items: tcx
+ .associated_items(impl_def_id)
+ .in_definition_order()
+ .filter(|item| !item.is_impl_trait_in_trait())
+ .map(|item| clean_middle_assoc_item(item, cx))
+ .collect(),
+ polarity: ty::ImplPolarity::Positive,
+ kind: clean::ImplKind::Blanket(Box::new(clean_middle_ty(
+ ty::Binder::dummy(trait_ref.instantiate_identity().self_ty()),
+ cx,
+ None,
+ None,
+ ))),
+ })),
+ }),
cfg: None,
inline_stmt_id: None,
});
diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs
index d22c4cc..8383012 100644
--- a/src/librustdoc/clean/inline.rs
+++ b/src/librustdoc/clean/inline.rs
@@ -5,7 +5,7 @@
use rustc_data_structures::fx::FxHashSet;
use rustc_hir::def::{DefKind, Res};
-use rustc_hir::def_id::{DefId, DefIdSet, LocalModDefId};
+use rustc_hir::def_id::{DefId, DefIdSet, LocalDefId, LocalModDefId};
use rustc_hir::Mutability;
use rustc_metadata::creader::{CStore, LoadedMacro};
use rustc_middle::ty::fast_reject::SimplifiedType;
@@ -43,7 +43,7 @@ pub(crate) fn try_inline(
cx: &mut DocContext<'_>,
res: Res,
name: Symbol,
- attrs: Option<(&[ast::Attribute], Option<DefId>)>,
+ attrs: Option<(&[ast::Attribute], Option<LocalDefId>)>,
visited: &mut DefIdSet,
) -> Option<Vec<clean::Item>> {
let did = res.opt_def_id()?;
@@ -152,14 +152,8 @@ pub(crate) fn try_inline(
};
cx.inlined.insert(did.into());
- let mut item = crate::clean::generate_item_with_correct_attrs(
- cx,
- kind,
- did,
- name,
- import_def_id.and_then(|def_id| def_id.as_local()),
- None,
- );
+ let mut item =
+ crate::clean::generate_item_with_correct_attrs(cx, kind, did, name, import_def_id, None);
// The visibility needs to reflect the one from the reexport and not from the "source" DefId.
item.inline_stmt_id = import_def_id;
ret.push(item);
@@ -198,7 +192,7 @@ pub(crate) fn try_inline_glob(
visited,
inlined_names,
Some(&reexports),
- Some((attrs, Some(import.owner_id.def_id.to_def_id()))),
+ Some((attrs, Some(import.owner_id.def_id))),
);
items.retain(|item| {
if let Some(name) = item.name {
@@ -372,7 +366,7 @@ fn build_type_alias(
pub(crate) fn build_impls(
cx: &mut DocContext<'_>,
did: DefId,
- attrs: Option<(&[ast::Attribute], Option<DefId>)>,
+ attrs: Option<(&[ast::Attribute], Option<LocalDefId>)>,
ret: &mut Vec<clean::Item>,
) {
let _prof_timer = cx.tcx.sess.prof.generic_activity("build_inherent_impls");
@@ -405,7 +399,7 @@ pub(crate) fn build_impls(
pub(crate) fn merge_attrs(
cx: &mut DocContext<'_>,
old_attrs: &[ast::Attribute],
- new_attrs: Option<(&[ast::Attribute], Option<DefId>)>,
+ new_attrs: Option<(&[ast::Attribute], Option<LocalDefId>)>,
) -> (clean::Attributes, Option<Arc<clean::cfg::Cfg>>) {
// NOTE: If we have additional attributes (from a re-export),
// always insert them first. This ensure that re-export
@@ -416,7 +410,7 @@ pub(crate) fn merge_attrs(
both.extend_from_slice(old_attrs);
(
if let Some(item_id) = item_id {
- Attributes::from_ast_with_additional(old_attrs, (inner, item_id))
+ Attributes::from_ast_with_additional(old_attrs, (inner, item_id.to_def_id()))
} else {
Attributes::from_ast(&both)
},
@@ -431,7 +425,7 @@ pub(crate) fn merge_attrs(
pub(crate) fn build_impl(
cx: &mut DocContext<'_>,
did: DefId,
- attrs: Option<(&[ast::Attribute], Option<DefId>)>,
+ attrs: Option<(&[ast::Attribute], Option<LocalDefId>)>,
ret: &mut Vec<clean::Item>,
) {
if !cx.inlined.insert(did.into()) {
@@ -623,7 +617,7 @@ pub(crate) fn build_impl(
ImplKind::Normal
},
})),
- Box::new(merged_attrs),
+ merged_attrs,
cfg,
));
}
@@ -641,7 +635,7 @@ fn build_module_items(
visited: &mut DefIdSet,
inlined_names: &mut FxHashSet<(ItemType, Symbol)>,
allowed_def_ids: Option<&DefIdSet>,
- attrs: Option<(&[ast::Attribute], Option<DefId>)>,
+ attrs: Option<(&[ast::Attribute], Option<LocalDefId>)>,
) -> Vec<clean::Item> {
let mut items = Vec::new();
@@ -673,27 +667,29 @@ fn build_module_items(
let prim_ty = clean::PrimitiveType::from(p);
items.push(clean::Item {
name: None,
- attrs: Box::default(),
// We can use the item's `DefId` directly since the only information ever used
// from it is `DefId.krate`.
item_id: ItemId::DefId(did),
- kind: Box::new(clean::ImportItem(clean::Import::new_simple(
- item.ident.name,
- clean::ImportSource {
- path: clean::Path {
- res,
- segments: thin_vec![clean::PathSegment {
- name: prim_ty.as_sym(),
- args: clean::GenericArgs::AngleBracketed {
- args: Default::default(),
- constraints: ThinVec::new(),
- },
- }],
+ inner: Box::new(clean::ItemInner {
+ attrs: Default::default(),
+ kind: clean::ImportItem(clean::Import::new_simple(
+ item.ident.name,
+ clean::ImportSource {
+ path: clean::Path {
+ res,
+ segments: thin_vec![clean::PathSegment {
+ name: prim_ty.as_sym(),
+ args: clean::GenericArgs::AngleBracketed {
+ args: Default::default(),
+ constraints: ThinVec::new(),
+ },
+ }],
+ },
+ did: None,
},
- did: None,
- },
- true,
- ))),
+ true,
+ )),
+ }),
cfg: None,
inline_stmt_id: None,
});
@@ -745,7 +741,7 @@ fn build_macro(
cx: &mut DocContext<'_>,
def_id: DefId,
name: Symbol,
- import_def_id: Option<DefId>,
+ import_def_id: Option<LocalDefId>,
macro_kind: MacroKind,
is_doc_hidden: bool,
) -> clean::ItemKind {
@@ -753,7 +749,8 @@ fn build_macro(
LoadedMacro::MacroDef(item_def, _) => match macro_kind {
MacroKind::Bang => {
if let ast::ItemKind::MacroDef(ref def) = item_def.kind {
- let vis = cx.tcx.visibility(import_def_id.unwrap_or(def_id));
+ let vis =
+ cx.tcx.visibility(import_def_id.map(|d| d.to_def_id()).unwrap_or(def_id));
clean::MacroItem(clean::Macro {
source: utils::display_macro_source(
cx,
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index 710bd4a..e47ae7d 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -203,8 +203,8 @@ fn generate_item_with_correct_attrs(
let attrs = Attributes::from_ast_iter(attrs.iter().map(|(attr, did)| (&**attr, *did)), false);
let name = renamed.or(Some(name));
- let mut item = Item::from_def_id_and_attrs_and_parts(def_id, name, kind, Box::new(attrs), cfg);
- item.inline_stmt_id = import_id.map(|local| local.to_def_id());
+ let mut item = Item::from_def_id_and_attrs_and_parts(def_id, name, kind, attrs, cfg);
+ item.inline_stmt_id = import_id;
item
}
@@ -2927,7 +2927,7 @@ fn clean_extern_crate<'tcx>(
})
&& !cx.output_format.is_json();
- let krate_owner_def_id = krate.owner_id.to_def_id();
+ let krate_owner_def_id = krate.owner_id.def_id;
if please_inline {
if let Some(items) = inline::try_inline(
cx,
@@ -2941,7 +2941,7 @@ fn clean_extern_crate<'tcx>(
}
vec![Item::from_def_id_and_parts(
- krate_owner_def_id,
+ krate_owner_def_id.to_def_id(),
Some(name),
ExternCrateItem { src: orig_name },
cx,
@@ -2988,7 +2988,7 @@ fn clean_use_statement_inner<'tcx>(
let inline_attr = attrs.lists(sym::doc).get_word_attr(sym::inline);
let pub_underscore = visibility.is_public() && name == 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.to_def_id();
+ let import_def_id = import.owner_id.def_id;
// The parent of the module in which this import resides. This
// is the same as `current_mod` if that's already the top
@@ -3071,7 +3071,7 @@ fn clean_use_statement_inner<'tcx>(
)
{
items.push(Item::from_def_id_and_parts(
- import_def_id,
+ import_def_id.to_def_id(),
None,
ImportItem(Import::new_simple(name, resolve_use_source(cx, path), false)),
cx,
@@ -3081,7 +3081,7 @@ fn clean_use_statement_inner<'tcx>(
Import::new_simple(name, resolve_use_source(cx, path), true)
};
- vec![Item::from_def_id_and_parts(import_def_id, None, ImportItem(inner), cx)]
+ vec![Item::from_def_id_and_parts(import_def_id.to_def_id(), None, ImportItem(inner), cx)]
}
fn clean_maybe_renamed_foreign_item<'tcx>(
diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs
index 5666b22..383efe5 100644
--- a/src/librustdoc/clean/types.rs
+++ b/src/librustdoc/clean/types.rs
@@ -320,14 +320,28 @@ pub(crate) struct Item {
/// The name of this item.
/// Optional because not every item has a name, e.g. impls.
pub(crate) name: Option<Symbol>,
- pub(crate) attrs: Box<Attributes>,
+ pub(crate) inner: Box<ItemInner>,
+ pub(crate) item_id: ItemId,
+ /// This is the `LocalDefId` of the `use` statement if the item was inlined.
+ /// The crate metadata doesn't hold this information, so the `use` statement
+ /// always belongs to the current crate.
+ pub(crate) inline_stmt_id: Option<LocalDefId>,
+ pub(crate) cfg: Option<Arc<Cfg>>,
+}
+
+#[derive(Clone)]
+pub(crate) struct ItemInner {
/// Information about this item that is specific to what kind of item it is.
/// E.g., struct vs enum vs function.
- pub(crate) kind: Box<ItemKind>,
- pub(crate) item_id: ItemId,
- /// This is the `DefId` of the `use` statement if the item was inlined.
- pub(crate) inline_stmt_id: Option<DefId>,
- pub(crate) cfg: Option<Arc<Cfg>>,
+ pub(crate) kind: ItemKind,
+ pub(crate) attrs: Attributes,
+}
+
+impl std::ops::Deref for Item {
+ type Target = ItemInner;
+ fn deref(&self) -> &ItemInner {
+ &*self.inner
+ }
}
/// NOTE: this does NOT unconditionally print every item, to avoid thousands of lines of logs.
@@ -389,9 +403,9 @@ pub(crate) fn inner_docs(&self, tcx: TyCtxt<'_>) -> bool {
}
pub(crate) fn span(&self, tcx: TyCtxt<'_>) -> Option<Span> {
- let kind = match &*self.kind {
- ItemKind::StrippedItem(k) => k,
- _ => &*self.kind,
+ let kind = match &self.kind {
+ ItemKind::StrippedItem(k) => &*k,
+ _ => &self.kind,
};
match kind {
ItemKind::ModuleItem(Module { span, .. }) => Some(*span),
@@ -436,7 +450,7 @@ pub(crate) fn from_def_id_and_parts(
def_id,
name,
kind,
- Box::new(Attributes::from_ast(ast_attrs)),
+ Attributes::from_ast(ast_attrs),
ast_attrs.cfg(cx.tcx, &cx.cache.hidden_cfg),
)
}
@@ -445,16 +459,15 @@ pub(crate) fn from_def_id_and_attrs_and_parts(
def_id: DefId,
name: Option<Symbol>,
kind: ItemKind,
- attrs: Box<Attributes>,
+ attrs: Attributes,
cfg: Option<Arc<Cfg>>,
) -> Item {
trace!("name={name:?}, def_id={def_id:?} cfg={cfg:?}");
Item {
item_id: def_id.into(),
- kind: Box::new(kind),
+ inner: Box::new(ItemInner { kind, attrs }),
name,
- attrs,
cfg,
inline_stmt_id: None,
}
@@ -522,16 +535,16 @@ pub(crate) fn is_variant(&self) -> bool {
self.type_() == ItemType::Variant
}
pub(crate) fn is_associated_type(&self) -> bool {
- matches!(&*self.kind, AssocTypeItem(..) | StrippedItem(box AssocTypeItem(..)))
+ matches!(self.kind, AssocTypeItem(..) | StrippedItem(box AssocTypeItem(..)))
}
pub(crate) fn is_ty_associated_type(&self) -> bool {
- matches!(&*self.kind, TyAssocTypeItem(..) | StrippedItem(box TyAssocTypeItem(..)))
+ matches!(self.kind, TyAssocTypeItem(..) | StrippedItem(box TyAssocTypeItem(..)))
}
pub(crate) fn is_associated_const(&self) -> bool {
- matches!(&*self.kind, AssocConstItem(..) | StrippedItem(box AssocConstItem(..)))
+ matches!(self.kind, AssocConstItem(..) | StrippedItem(box AssocConstItem(..)))
}
pub(crate) fn is_ty_associated_const(&self) -> bool {
- matches!(&*self.kind, TyAssocConstItem(..) | StrippedItem(box TyAssocConstItem(..)))
+ matches!(self.kind, TyAssocConstItem(..) | StrippedItem(box TyAssocConstItem(..)))
}
pub(crate) fn is_method(&self) -> bool {
self.type_() == ItemType::Method
@@ -555,14 +568,14 @@ pub(crate) fn is_keyword(&self) -> bool {
self.type_() == ItemType::Keyword
}
pub(crate) fn is_stripped(&self) -> bool {
- match *self.kind {
+ match self.kind {
StrippedItem(..) => true,
ImportItem(ref i) => !i.should_be_displayed,
_ => false,
}
}
pub(crate) fn has_stripped_entries(&self) -> Option<bool> {
- match *self.kind {
+ match self.kind {
StructItem(ref struct_) => Some(struct_.has_stripped_entries()),
UnionItem(ref union_) => Some(union_.has_stripped_entries()),
EnumItem(ref enum_) => Some(enum_.has_stripped_entries()),
@@ -605,7 +618,7 @@ pub(crate) fn type_(&self) -> ItemType {
}
pub(crate) fn is_default(&self) -> bool {
- match *self.kind {
+ match self.kind {
ItemKind::MethodItem(_, Some(defaultness)) => {
defaultness.has_value() && !defaultness.is_final()
}
@@ -633,7 +646,7 @@ fn build_fn_header(
};
hir::FnHeader { safety: sig.safety(), abi: sig.abi(), constness, asyncness }
}
- let header = match *self.kind {
+ let header = match self.kind {
ItemKind::ForeignFunctionItem(_, safety) => {
let def_id = self.def_id().unwrap();
let abi = tcx.fn_sig(def_id).skip_binder().abi();
@@ -672,7 +685,7 @@ pub(crate) fn visibility(&self, tcx: TyCtxt<'_>) -> Option<Visibility<DefId>> {
ItemId::DefId(def_id) => def_id,
};
- match *self.kind {
+ match self.kind {
// Primitives and Keywords are written in the source code as private modules.
// The modules need to be private so that nobody actually uses them, but the
// keywords and primitives that they are documenting are public.
@@ -702,7 +715,7 @@ pub(crate) fn visibility(&self, tcx: TyCtxt<'_>) -> Option<Visibility<DefId>> {
_ => {}
}
let def_id = match self.inline_stmt_id {
- Some(inlined) => inlined,
+ Some(inlined) => inlined.to_def_id(),
None => def_id,
};
Some(tcx.visibility(def_id))
@@ -2559,13 +2572,13 @@ mod size_asserts {
use super::*;
// tidy-alphabetical-start
- static_assert_size!(Crate, 64); // frequently moved by-value
+ static_assert_size!(Crate, 56); // frequently moved by-value
static_assert_size!(DocFragment, 32);
static_assert_size!(GenericArg, 32);
static_assert_size!(GenericArgs, 32);
static_assert_size!(GenericParamDef, 40);
static_assert_size!(Generics, 16);
- static_assert_size!(Item, 56);
+ static_assert_size!(Item, 48);
static_assert_size!(ItemKind, 48);
static_assert_size!(PathSegment, 40);
static_assert_size!(Type, 32);
diff --git a/src/librustdoc/clean/utils.rs b/src/librustdoc/clean/utils.rs
index 5686307..885758c 100644
--- a/src/librustdoc/clean/utils.rs
+++ b/src/librustdoc/clean/utils.rs
@@ -36,7 +36,7 @@ pub(crate) fn krate(cx: &mut DocContext<'_>) -> Crate {
// understood by rustdoc.
let mut module = clean_doc_module(&module, cx);
- match *module.kind {
+ match module.kind {
ItemKind::ModuleItem(ref module) => {
for it in &module.items {
// `compiler_builtins` should be masked too, but we can't apply
@@ -60,7 +60,7 @@ pub(crate) fn krate(cx: &mut DocContext<'_>) -> Crate {
let primitives = local_crate.primitives(cx.tcx);
let keywords = local_crate.keywords(cx.tcx);
{
- let ItemKind::ModuleItem(ref mut m) = *module.kind else { unreachable!() };
+ let ItemKind::ModuleItem(ref mut m) = &mut module.inner.kind else { unreachable!() };
m.items.extend(primitives.iter().map(|&(def_id, prim)| {
Item::from_def_id_and_parts(
def_id,
@@ -281,7 +281,7 @@ pub(crate) fn build_deref_target_impls(
let tcx = cx.tcx;
for item in items {
- let target = match *item.kind {
+ let target = match item.kind {
ItemKind::AssocTypeItem(ref t, _) => &t.type_,
_ => continue,
};
diff --git a/src/librustdoc/config.rs b/src/librustdoc/config.rs
index 9e7b69e..b3c87a7 100644
--- a/src/librustdoc/config.rs
+++ b/src/librustdoc/config.rs
@@ -53,12 +53,18 @@ fn try_from(value: &str) -> Result<Self, Self::Error> {
}
}
+/// Either an input crate, markdown file, or nothing (--merge=finalize).
+pub(crate) enum InputMode {
+ /// The `--merge=finalize` step does not need an input crate to rustdoc.
+ NoInputMergeFinalize,
+ /// A crate or markdown file.
+ HasFile(Input),
+}
+
/// Configuration options for rustdoc.
#[derive(Clone)]
pub(crate) struct Options {
// Basic options / Options passed directly to rustc
- /// The crate root or Markdown file to load.
- pub(crate) input: Input,
/// The name of the crate being documented.
pub(crate) crate_name: Option<String>,
/// Whether or not this is a bin crate
@@ -179,7 +185,6 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
}
f.debug_struct("Options")
- .field("input", &self.input.source_name())
.field("crate_name", &self.crate_name)
.field("bin_crate", &self.bin_crate)
.field("proc_macro_crate", &self.proc_macro_crate)
@@ -289,6 +294,12 @@ pub(crate) struct RenderOptions {
/// This field is only used for the JSON output. If it's set to true, no file will be created
/// and content will be displayed in stdout directly.
pub(crate) output_to_stdout: bool,
+ /// Whether we should read or write rendered cross-crate info in the doc root.
+ pub(crate) should_merge: ShouldMerge,
+ /// Path to crate-info for external crates.
+ pub(crate) include_parts_dir: Vec<PathToParts>,
+ /// Where to write crate-info
+ pub(crate) parts_out_dir: Option<PathToParts>,
}
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
@@ -348,7 +359,7 @@ pub(crate) fn from_matches(
early_dcx: &mut EarlyDiagCtxt,
matches: &getopts::Matches,
args: Vec<String>,
- ) -> Option<(Options, RenderOptions)> {
+ ) -> Option<(InputMode, Options, RenderOptions)> {
// Check for unstable options.
nightly_options::check_nightly_options(early_dcx, matches, &opts());
@@ -478,15 +489,17 @@ fn println_condition(condition: Condition) {
let (lint_opts, describe_lints, lint_cap) = get_cmd_lint_options(early_dcx, matches);
let input = if describe_lints {
- "" // dummy, this won't be used
+ InputMode::HasFile(make_input(early_dcx, ""))
} else {
match matches.free.as_slice() {
+ [] if matches.opt_str("merge").as_deref() == Some("finalize") => {
+ InputMode::NoInputMergeFinalize
+ }
[] => dcx.fatal("missing file operand"),
- [input] => input,
+ [input] => InputMode::HasFile(make_input(early_dcx, input)),
_ => dcx.fatal("too many file operands"),
}
};
- let input = make_input(early_dcx, input);
let externs = parse_externs(early_dcx, matches, &unstable_opts);
let extern_html_root_urls = match parse_extern_html_roots(matches) {
@@ -494,6 +507,16 @@ fn println_condition(condition: Condition) {
Err(err) => dcx.fatal(err),
};
+ let parts_out_dir =
+ match matches.opt_str("parts-out-dir").map(|p| PathToParts::from_flag(p)).transpose() {
+ Ok(parts_out_dir) => parts_out_dir,
+ Err(e) => dcx.fatal(e),
+ };
+ let include_parts_dir = match parse_include_parts_dir(matches) {
+ Ok(include_parts_dir) => include_parts_dir,
+ Err(e) => dcx.fatal(e),
+ };
+
let default_settings: Vec<Vec<(String, String)>> = vec![
matches
.opt_str("default-theme")
@@ -735,6 +758,10 @@ fn println_condition(condition: Condition) {
let extern_html_root_takes_precedence =
matches.opt_present("extern-html-root-takes-precedence");
let html_no_source = matches.opt_present("html-no-source");
+ let should_merge = match parse_merge(matches) {
+ Ok(result) => result,
+ Err(e) => dcx.fatal(format!("--merge option error: {e}")),
+ };
if generate_link_to_definition && (show_coverage || output_format != OutputFormat::Html) {
dcx.struct_warn(
@@ -751,7 +778,6 @@ fn println_condition(condition: Condition) {
let unstable_features =
rustc_feature::UnstableFeatures::from_environment(crate_name.as_deref());
let options = Options {
- input,
bin_crate,
proc_macro_crate,
error_format,
@@ -823,16 +849,17 @@ fn println_condition(condition: Condition) {
no_emit_shared: false,
html_no_source,
output_to_stdout,
+ should_merge,
+ include_parts_dir,
+ parts_out_dir,
};
- Some((options, render_options))
+ Some((input, options, render_options))
}
+}
- /// Returns `true` if the file given as `self.input` is a Markdown file.
- pub(crate) fn markdown_input(&self) -> Option<&Path> {
- self.input
- .opt_path()
- .filter(|p| matches!(p.extension(), Some(e) if e == "md" || e == "markdown"))
- }
+/// Returns `true` if the file given as `self.input` is a Markdown file.
+pub(crate) fn markdown_input(input: &Input) -> Option<&Path> {
+ input.opt_path().filter(|p| matches!(p.extension(), Some(e) if e == "md" || e == "markdown"))
}
fn parse_remap_path_prefix(
@@ -900,3 +927,71 @@ fn parse_extern_html_roots(
}
Ok(externs)
}
+
+/// Path directly to crate-info file.
+///
+/// For example, `/home/user/project/target/doc.parts/<crate>/crate-info`.
+#[derive(Clone, Debug)]
+pub(crate) struct PathToParts(pub(crate) PathBuf);
+
+impl PathToParts {
+ fn from_flag(path: String) -> Result<PathToParts, String> {
+ let mut path = PathBuf::from(path);
+ // check here is for diagnostics
+ if path.exists() && !path.is_dir() {
+ Err(format!(
+ "--parts-out-dir and --include-parts-dir expect directories, found: {}",
+ path.display(),
+ ))
+ } else {
+ // if it doesn't exist, we'll create it. worry about that in write_shared
+ path.push("crate-info");
+ Ok(PathToParts(path))
+ }
+ }
+}
+
+/// Reports error if --include-parts-dir / crate-info is not a file
+fn parse_include_parts_dir(m: &getopts::Matches) -> Result<Vec<PathToParts>, String> {
+ let mut ret = Vec::new();
+ for p in m.opt_strs("include-parts-dir") {
+ let p = PathToParts::from_flag(p)?;
+ // this is just for diagnostic
+ if !p.0.is_file() {
+ return Err(format!("--include-parts-dir expected {} to be a file", p.0.display()));
+ }
+ ret.push(p);
+ }
+ Ok(ret)
+}
+
+/// Controls merging of cross-crate information
+#[derive(Debug, Clone)]
+pub(crate) struct ShouldMerge {
+ /// Should we append to existing cci in the doc root
+ pub(crate) read_rendered_cci: bool,
+ /// Should we write cci to the doc root
+ pub(crate) write_rendered_cci: bool,
+}
+
+/// Extracts read_rendered_cci and write_rendered_cci from command line arguments, or
+/// reports an error if an invalid option was provided
+fn parse_merge(m: &getopts::Matches) -> Result<ShouldMerge, &'static str> {
+ match m.opt_str("merge").as_deref() {
+ // default = read-write
+ None => Ok(ShouldMerge { read_rendered_cci: true, write_rendered_cci: true }),
+ Some("none") if m.opt_present("include-parts-dir") => {
+ Err("--include-parts-dir not allowed if --merge=none")
+ }
+ Some("none") => Ok(ShouldMerge { read_rendered_cci: false, write_rendered_cci: false }),
+ Some("shared") if m.opt_present("parts-out-dir") || m.opt_present("include-parts-dir") => {
+ Err("--parts-out-dir and --include-parts-dir not allowed if --merge=shared")
+ }
+ Some("shared") => Ok(ShouldMerge { read_rendered_cci: true, write_rendered_cci: true }),
+ Some("finalize") if m.opt_present("parts-out-dir") => {
+ Err("--parts-out-dir not allowed if --merge=finalize")
+ }
+ Some("finalize") => Ok(ShouldMerge { read_rendered_cci: false, write_rendered_cci: true }),
+ Some(_) => Err("argument to --merge must be `none`, `shared`, or `finalize`"),
+ }
+}
diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs
index 2cde0ac..4fafef6 100644
--- a/src/librustdoc/core.rs
+++ b/src/librustdoc/core.rs
@@ -20,7 +20,7 @@
use rustc_lint::{late_lint_mod, MissingDoc};
use rustc_middle::hir::nested_filter;
use rustc_middle::ty::{ParamEnv, Ty, TyCtxt};
-use rustc_session::config::{self, CrateType, ErrorOutputType, ResolveDocLinks};
+use rustc_session::config::{self, CrateType, ErrorOutputType, Input, ResolveDocLinks};
pub(crate) use rustc_session::config::{Options, UnstableOptions};
use rustc_session::{lint, Session};
use rustc_span::symbol::sym;
@@ -177,8 +177,8 @@ pub(crate) fn new_dcx(
/// Parse, resolve, and typecheck the given crate.
pub(crate) fn create_config(
+ input: Input,
RustdocOptions {
- input,
crate_name,
proc_macro_crate,
error_format,
diff --git a/src/librustdoc/doctest.rs b/src/librustdoc/doctest.rs
index 8b6588e..05ef728 100644
--- a/src/librustdoc/doctest.rs
+++ b/src/librustdoc/doctest.rs
@@ -19,7 +19,7 @@
use rustc_hir::def_id::LOCAL_CRATE;
use rustc_hir::CRATE_HIR_ID;
use rustc_interface::interface;
-use rustc_session::config::{self, CrateType, ErrorOutputType};
+use rustc_session::config::{self, CrateType, ErrorOutputType, Input};
use rustc_session::lint;
use rustc_span::edition::Edition;
use rustc_span::symbol::sym;
@@ -88,7 +88,11 @@ fn get_doctest_dir() -> io::Result<TempDir> {
TempFileBuilder::new().prefix("rustdoctest").tempdir()
}
-pub(crate) fn run(dcx: DiagCtxtHandle<'_>, options: RustdocOptions) -> Result<(), ErrorGuaranteed> {
+pub(crate) fn run(
+ dcx: DiagCtxtHandle<'_>,
+ input: Input,
+ options: RustdocOptions,
+) -> Result<(), ErrorGuaranteed> {
let invalid_codeblock_attributes_name = crate::lint::INVALID_CODEBLOCK_ATTRIBUTES.name;
// See core::create_config for what's going on here.
@@ -135,7 +139,7 @@ pub(crate) fn run(dcx: DiagCtxtHandle<'_>, options: RustdocOptions) -> Result<()
opts: sessopts,
crate_cfg: cfgs,
crate_check_cfg: options.check_cfgs.clone(),
- input: options.input.clone(),
+ input: input.clone(),
output_file: None,
output_dir: None,
file_loader: None,
diff --git a/src/librustdoc/doctest/markdown.rs b/src/librustdoc/doctest/markdown.rs
index 9a237f8..4f83bd5 100644
--- a/src/librustdoc/doctest/markdown.rs
+++ b/src/librustdoc/doctest/markdown.rs
@@ -3,6 +3,7 @@
use std::fs::read_to_string;
use std::sync::{Arc, Mutex};
+use rustc_session::config::Input;
use rustc_span::FileName;
use tempfile::tempdir;
@@ -69,9 +70,8 @@ fn visit_header(&mut self, name: &str, level: u32) {
}
/// Runs any tests/code examples in the markdown file `options.input`.
-pub(crate) fn test(options: Options) -> Result<(), String> {
- use rustc_session::config::Input;
- let input_str = match &options.input {
+pub(crate) fn test(input: &Input, options: Options) -> Result<(), String> {
+ let input_str = match input {
Input::File(path) => {
read_to_string(path).map_err(|err| format!("{}: {err}", path.display()))?
}
@@ -79,7 +79,7 @@ pub(crate) fn test(options: Options) -> Result<(), String> {
};
// Obviously not a real crate name, but close enough for purposes of doctests.
- let crate_name = options.input.filestem().to_string();
+ let crate_name = input.filestem().to_string();
let temp_dir =
tempdir().map_err(|error| format!("failed to create temporary directory: {error:?}"))?;
let args_file = temp_dir.path().join("rustdoc-cfgs");
@@ -96,8 +96,7 @@ pub(crate) fn test(options: Options) -> Result<(), String> {
let mut md_collector = MdCollector {
tests: vec![],
cur_path: vec![],
- filename: options
- .input
+ filename: input
.opt_path()
.map(ToOwned::to_owned)
.map(FileName::from)
diff --git a/src/librustdoc/fold.rs b/src/librustdoc/fold.rs
index bf82c91..c25a4dd 100644
--- a/src/librustdoc/fold.rs
+++ b/src/librustdoc/fold.rs
@@ -1,8 +1,8 @@
use crate::clean::*;
pub(crate) fn strip_item(mut item: Item) -> Item {
- if !matches!(*item.kind, StrippedItem(..)) {
- item.kind = Box::new(StrippedItem(item.kind));
+ if !matches!(item.inner.kind, StrippedItem(..)) {
+ item.inner.kind = StrippedItem(Box::new(item.inner.kind));
}
item
}
@@ -99,10 +99,10 @@ fn fold_inner_recur(&mut self, kind: ItemKind) -> ItemKind {
/// don't override!
fn fold_item_recur(&mut self, mut item: Item) -> Item {
- item.kind = Box::new(match *item.kind {
+ item.inner.kind = match item.inner.kind {
StrippedItem(box i) => StrippedItem(Box::new(self.fold_inner_recur(i))),
- _ => self.fold_inner_recur(*item.kind),
- });
+ _ => self.fold_inner_recur(item.inner.kind),
+ };
item
}
diff --git a/src/librustdoc/formats/cache.rs b/src/librustdoc/formats/cache.rs
index c5e2b33..1b3176e 100644
--- a/src/librustdoc/formats/cache.rs
+++ b/src/librustdoc/formats/cache.rs
@@ -216,7 +216,7 @@ fn fold_item(&mut self, item: clean::Item) -> Option<clean::Item> {
// If this is a stripped module,
// we don't want it or its children in the search index.
- let orig_stripped_mod = match *item.kind {
+ let orig_stripped_mod = match item.kind {
clean::StrippedItem(box clean::ModuleItem(..)) => {
mem::replace(&mut self.cache.stripped_mod, true)
}
@@ -232,7 +232,7 @@ fn is_from_private_dep(tcx: TyCtxt<'_>, cache: &Cache, def_id: DefId) -> bool {
// If the impl is from a masked crate or references something from a
// masked crate then remove it completely.
- if let clean::ImplItem(ref i) = *item.kind
+ if let clean::ImplItem(ref i) = item.kind
&& (self.cache.masked_crates.contains(&item.item_id.krate())
|| i.trait_
.as_ref()
@@ -246,9 +246,9 @@ fn is_from_private_dep(tcx: TyCtxt<'_>, cache: &Cache, def_id: DefId) -> bool {
// Propagate a trait method's documentation to all implementors of the
// trait.
- if let clean::TraitItem(ref t) = *item.kind {
+ if let clean::TraitItem(ref t) = item.kind {
self.cache.traits.entry(item.item_id.expect_def_id()).or_insert_with(|| (**t).clone());
- } else if let clean::ImplItem(ref i) = *item.kind
+ } else if let clean::ImplItem(ref i) = item.kind
&& let Some(trait_) = &i.trait_
&& !i.kind.is_blanket()
{
@@ -263,7 +263,7 @@ fn is_from_private_dep(tcx: TyCtxt<'_>, cache: &Cache, def_id: DefId) -> bool {
// Index this method for searching later on.
let search_name = if !item.is_stripped() {
item.name.or_else(|| {
- if let clean::ImportItem(ref i) = *item.kind
+ if let clean::ImportItem(ref i) = item.kind
&& let clean::ImportKind::Simple(s) = i.kind
{
Some(s)
@@ -287,7 +287,7 @@ fn is_from_private_dep(tcx: TyCtxt<'_>, cache: &Cache, def_id: DefId) -> bool {
_ => false,
};
- match *item.kind {
+ match item.kind {
clean::StructItem(..)
| clean::EnumItem(..)
| clean::TypeAliasItem(..)
@@ -350,7 +350,7 @@ fn is_from_private_dep(tcx: TyCtxt<'_>, cache: &Cache, def_id: DefId) -> bool {
}
// Maintain the parent stack.
- let (item, parent_pushed) = match *item.kind {
+ let (item, parent_pushed) = match item.kind {
clean::TraitItem(..)
| clean::EnumItem(..)
| clean::ForeignTypeItem
@@ -367,7 +367,11 @@ fn is_from_private_dep(tcx: TyCtxt<'_>, cache: &Cache, def_id: DefId) -> bool {
// Once we've recursively found all the generics, hoard off all the
// implementations elsewhere.
- let ret = if let clean::Item { kind: box clean::ImplItem(ref i), .. } = item {
+ let ret = if let clean::Item {
+ inner: box clean::ItemInner { kind: clean::ImplItem(ref i), .. },
+ ..
+ } = item
+ {
// Figure out the id of this impl. This may map to a
// primitive rather than always to a struct/enum.
// Note: matching twice to restrict the lifetime of the `i` borrow.
@@ -436,7 +440,7 @@ fn is_from_private_dep(tcx: TyCtxt<'_>, cache: &Cache, def_id: DefId) -> bool {
fn add_item_to_search_index(tcx: TyCtxt<'_>, cache: &mut Cache, item: &clean::Item, name: Symbol) {
// Item has a name, so it must also have a DefId (can't be an impl, let alone a blanket or auto impl).
let item_def_id = item.item_id.as_def_id().unwrap();
- let (parent_did, parent_path) = match *item.kind {
+ let (parent_did, parent_path) = match item.kind {
clean::StrippedItem(..) => return,
clean::AssocConstItem(..) | clean::AssocTypeItem(..)
if cache.parent_stack.last().is_some_and(|parent| parent.is_trait_impl()) =>
@@ -528,7 +532,7 @@ fn add_item_to_search_index(tcx: TyCtxt<'_>, cache: &mut Cache, item: &clean::It
// - It's either an inline, or a true re-export
// - It's got the same name
// - Both of them have the same exact path
- let defid = match &*item.kind {
+ let defid = match &item.kind {
clean::ItemKind::ImportItem(import) => import.source.did.unwrap_or(item_def_id),
_ => item_def_id,
};
@@ -605,7 +609,7 @@ enum ParentStackItem {
impl ParentStackItem {
fn new(item: &clean::Item) -> Self {
- match &*item.kind {
+ match &item.kind {
clean::ItemKind::ImplItem(box clean::Impl { for_, trait_, generics, kind, .. }) => {
ParentStackItem::Impl {
for_: for_.clone(),
diff --git a/src/librustdoc/formats/item_type.rs b/src/librustdoc/formats/item_type.rs
index 9754e1e..383e313 100644
--- a/src/librustdoc/formats/item_type.rs
+++ b/src/librustdoc/formats/item_type.rs
@@ -70,7 +70,7 @@ fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
impl<'a> From<&'a clean::Item> for ItemType {
fn from(item: &'a clean::Item) -> ItemType {
- let kind = match *item.kind {
+ let kind = match item.kind {
clean::StrippedItem(box ref item) => item,
ref kind => kind,
};
diff --git a/src/librustdoc/formats/mod.rs b/src/librustdoc/formats/mod.rs
index 84adca8..0bdea36 100644
--- a/src/librustdoc/formats/mod.rs
+++ b/src/librustdoc/formats/mod.rs
@@ -16,7 +16,7 @@ pub(crate) struct Impl {
impl Impl {
pub(crate) fn inner_impl(&self) -> &clean::Impl {
- match *self.impl_item.kind {
+ match self.impl_item.kind {
clean::ImplItem(ref impl_) => impl_,
_ => panic!("non-impl item found in impl"),
}
diff --git a/src/librustdoc/formats/renderer.rs b/src/librustdoc/formats/renderer.rs
index cc57dca..edd7d56 100644
--- a/src/librustdoc/formats/renderer.rs
+++ b/src/librustdoc/formats/renderer.rs
@@ -77,7 +77,7 @@ pub(crate) fn run_format<'tcx, T: FormatRenderer<'tcx>>(
cx.mod_item_in(&item)?;
let (clean::StrippedItem(box clean::ModuleItem(module)) | clean::ModuleItem(module)) =
- *item.kind
+ item.inner.kind
else {
unreachable!()
};
diff --git a/src/librustdoc/html/highlight.rs b/src/librustdoc/html/highlight.rs
index 29b4889..e728da6 100644
--- a/src/librustdoc/html/highlight.rs
+++ b/src/librustdoc/html/highlight.rs
@@ -879,7 +879,9 @@ fn advance(
| TokenKind::UnknownPrefix
| TokenKind::InvalidPrefix
| TokenKind::InvalidIdent => Class::Ident(self.new_span(before, text)),
- TokenKind::Lifetime { .. } => Class::Lifetime,
+ TokenKind::Lifetime { .. }
+ | TokenKind::RawLifetime
+ | TokenKind::UnknownPrefixLifetime => Class::Lifetime,
TokenKind::Eof => panic!("Eof in advance"),
};
// Anything that didn't return above is the simple case where we the
diff --git a/src/librustdoc/html/render/context.rs b/src/librustdoc/html/render/context.rs
index 9fe43e4..a9b9377 100644
--- a/src/librustdoc/html/render/context.rs
+++ b/src/librustdoc/html/render/context.rs
@@ -16,12 +16,11 @@
use super::print_item::{full_path, item_path, print_item};
use super::sidebar::{print_sidebar, sidebar_module_like, ModuleLike, Sidebar};
-use super::write_shared::write_shared;
use super::{collect_spans_and_sources, scrape_examples_help, AllTypes, LinkFromSrc, StylePath};
use crate::clean::types::ExternalLocation;
use crate::clean::utils::has_doc_flag;
use crate::clean::{self, ExternalCrate};
-use crate::config::{ModuleSorting, RenderOptions};
+use crate::config::{ModuleSorting, RenderOptions, ShouldMerge};
use crate::docfs::{DocFS, PathError};
use crate::error::Error;
use crate::formats::cache::Cache;
@@ -30,6 +29,7 @@
use crate::html::escape::Escape;
use crate::html::format::{join_with_double_colon, Buffer};
use crate::html::markdown::{self, plain_text_summary, ErrorCodes, IdMap};
+use crate::html::render::write_shared::write_shared;
use crate::html::url_parts_builder::UrlPartsBuilder;
use crate::html::{layout, sources, static_files};
use crate::scrape_examples::AllCallLocations;
@@ -128,8 +128,10 @@ pub(crate) struct SharedContext<'tcx> {
pub(crate) span_correspondence_map: FxHashMap<rustc_span::Span, LinkFromSrc>,
/// The [`Cache`] used during rendering.
pub(crate) cache: Cache,
-
pub(crate) call_locations: AllCallLocations,
+ /// Controls whether we read / write to cci files in the doc root. Defaults read=true,
+ /// write=true
+ should_merge: ShouldMerge,
}
impl SharedContext<'_> {
@@ -551,6 +553,7 @@ fn init(
span_correspondence_map: matches,
cache,
call_locations,
+ should_merge: options.should_merge,
};
let dst = output;
@@ -640,92 +643,96 @@ fn after_krate(&mut self) -> Result<(), Error> {
);
shared.fs.write(final_file, v)?;
- // Generating settings page.
- page.title = "Settings";
- page.description = "Settings of Rustdoc";
- page.root_path = "./";
- page.rust_logo = true;
+ // if to avoid writing help, settings files to doc root unless we're on the final invocation
+ if shared.should_merge.write_rendered_cci {
+ // Generating settings page.
+ page.title = "Settings";
+ page.description = "Settings of Rustdoc";
+ page.root_path = "./";
+ page.rust_logo = true;
- let sidebar = "<h2 class=\"location\">Settings</h2><div class=\"sidebar-elems\"></div>";
- let v = layout::render(
- &shared.layout,
- &page,
- sidebar,
- |buf: &mut Buffer| {
- write!(
- buf,
- "<div class=\"main-heading\">\
- <h1>Rustdoc settings</h1>\
- <span class=\"out-of-band\">\
- <a id=\"back\" href=\"javascript:void(0)\" onclick=\"history.back();\">\
- Back\
- </a>\
- </span>\
- </div>\
- <noscript>\
- <section>\
- You need to enable JavaScript be able to update your settings.\
- </section>\
- </noscript>\
- <script defer src=\"{static_root_path}{settings_js}\"></script>",
- static_root_path = page.get_static_root_path(),
- settings_js = static_files::STATIC_FILES.settings_js,
- );
- // Pre-load all theme CSS files, so that switching feels seamless.
- //
- // When loading settings.html as a popover, the equivalent HTML is
- // generated in main.js.
- for file in &shared.style_files {
- if let Ok(theme) = file.basename() {
- write!(
- buf,
- "<link rel=\"preload\" href=\"{root_path}{theme}{suffix}.css\" \
- as=\"style\">",
- root_path = page.static_root_path.unwrap_or(""),
- suffix = page.resource_suffix,
- );
+ let sidebar = "<h2 class=\"location\">Settings</h2><div class=\"sidebar-elems\"></div>";
+ let v = layout::render(
+ &shared.layout,
+ &page,
+ sidebar,
+ |buf: &mut Buffer| {
+ write!(
+ buf,
+ "<div class=\"main-heading\">\
+ <h1>Rustdoc settings</h1>\
+ <span class=\"out-of-band\">\
+ <a id=\"back\" href=\"javascript:void(0)\" onclick=\"history.back();\">\
+ Back\
+ </a>\
+ </span>\
+ </div>\
+ <noscript>\
+ <section>\
+ You need to enable JavaScript be able to update your settings.\
+ </section>\
+ </noscript>\
+ <script defer src=\"{static_root_path}{settings_js}\"></script>",
+ static_root_path = page.get_static_root_path(),
+ settings_js = static_files::STATIC_FILES.settings_js,
+ );
+ // Pre-load all theme CSS files, so that switching feels seamless.
+ //
+ // When loading settings.html as a popover, the equivalent HTML is
+ // generated in main.js.
+ for file in &shared.style_files {
+ if let Ok(theme) = file.basename() {
+ write!(
+ buf,
+ "<link rel=\"preload\" href=\"{root_path}{theme}{suffix}.css\" \
+ as=\"style\">",
+ root_path = page.static_root_path.unwrap_or(""),
+ suffix = page.resource_suffix,
+ );
+ }
}
- }
- },
- &shared.style_files,
- );
- shared.fs.write(settings_file, v)?;
+ },
+ &shared.style_files,
+ );
+ shared.fs.write(settings_file, v)?;
- // Generating help page.
- page.title = "Help";
- page.description = "Documentation for Rustdoc";
- page.root_path = "./";
- page.rust_logo = true;
+ // Generating help page.
+ page.title = "Help";
+ page.description = "Documentation for Rustdoc";
+ page.root_path = "./";
+ page.rust_logo = true;
- let sidebar = "<h2 class=\"location\">Help</h2><div class=\"sidebar-elems\"></div>";
- let v = layout::render(
- &shared.layout,
- &page,
- sidebar,
- |buf: &mut Buffer| {
- write!(
- buf,
- "<div class=\"main-heading\">\
- <h1>Rustdoc help</h1>\
- <span class=\"out-of-band\">\
- <a id=\"back\" href=\"javascript:void(0)\" onclick=\"history.back();\">\
- Back\
- </a>\
- </span>\
- </div>\
- <noscript>\
- <section>\
- <p>You need to enable JavaScript to use keyboard commands or search.</p>\
- <p>For more information, browse the <a href=\"https://doc.rust-lang.org/rustdoc/\">rustdoc handbook</a>.</p>\
- </section>\
- </noscript>",
- )
- },
- &shared.style_files,
- );
- shared.fs.write(help_file, v)?;
+ let sidebar = "<h2 class=\"location\">Help</h2><div class=\"sidebar-elems\"></div>";
+ let v = layout::render(
+ &shared.layout,
+ &page,
+ sidebar,
+ |buf: &mut Buffer| {
+ write!(
+ buf,
+ "<div class=\"main-heading\">\
+ <h1>Rustdoc help</h1>\
+ <span class=\"out-of-band\">\
+ <a id=\"back\" href=\"javascript:void(0)\" onclick=\"history.back();\">\
+ Back\
+ </a>\
+ </span>\
+ </div>\
+ <noscript>\
+ <section>\
+ <p>You need to enable JavaScript to use keyboard commands or search.</p>\
+ <p>For more information, browse the <a href=\"https://doc.rust-lang.org/rustdoc/\">rustdoc handbook</a>.</p>\
+ </section>\
+ </noscript>",
+ )
+ },
+ &shared.style_files,
+ );
+ shared.fs.write(help_file, v)?;
+ }
- if shared.layout.scrape_examples_extension {
+ // if to avoid writing files to doc root unless we're on the final invocation
+ if shared.layout.scrape_examples_extension && shared.should_merge.write_rendered_cci {
page.title = "About scraped examples";
page.description = "How the scraped examples feature works in Rustdoc";
let v = layout::render(
@@ -800,7 +807,7 @@ fn mod_item_in(&mut self, item: &clean::Item) -> Result<(), Error> {
// Render sidebar-items.js used throughout this module.
if !self.render_redirect_pages {
let (clean::StrippedItem(box clean::ModuleItem(ref module))
- | clean::ModuleItem(ref module)) = *item.kind
+ | clean::ModuleItem(ref module)) = item.kind
else {
unreachable!()
};
diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs
index dc34c78..a402d79 100644
--- a/src/librustdoc/html/render/mod.rs
+++ b/src/librustdoc/html/render/mod.rs
@@ -61,6 +61,7 @@
pub(crate) use self::context::*;
pub(crate) use self::span_map::{collect_spans_and_sources, LinkFromSrc};
+pub(crate) use self::write_shared::*;
use crate::clean::{self, ItemId, RenderedLink};
use crate::error::Error;
use crate::formats::cache::Cache;
@@ -620,7 +621,7 @@ fn document_full_inner<'a, 'cx: 'a>(
}
}
- let kind = match &*item.kind {
+ let kind = match &item.kind {
clean::ItemKind::StrippedItem(box kind) | kind => kind,
};
@@ -1072,7 +1073,7 @@ fn render_assoc_item(
cx: &mut Context<'_>,
render_mode: RenderMode,
) {
- match &*item.kind {
+ match &item.kind {
clean::StrippedItem(..) => {}
clean::TyMethodItem(m) => {
assoc_method(w, item, &m.generics, &m.decl, link, parent, cx, render_mode)
@@ -1350,7 +1351,7 @@ fn render_deref_methods(
.inner_impl()
.items
.iter()
- .find_map(|item| match *item.kind {
+ .find_map(|item| match item.kind {
clean::AssocTypeItem(box ref t, _) => Some(match *t {
clean::TypeAlias { item_type: Some(ref type_), .. } => (type_, &t.type_),
_ => (&t.type_, &t.type_),
@@ -1381,7 +1382,7 @@ fn render_deref_methods(
}
fn should_render_item(item: &clean::Item, deref_mut_: bool, tcx: TyCtxt<'_>) -> bool {
- let self_type_opt = match *item.kind {
+ let self_type_opt = match item.kind {
clean::MethodItem(ref method, _) => method.decl.receiver_type(),
clean::TyMethodItem(ref method) => method.decl.receiver_type(),
_ => None,
@@ -1491,7 +1492,7 @@ fn notable_traits_decl(ty: &clean::Type, cx: &Context<'_>) -> (String, String) {
write!(&mut out, "<div class=\"where\">{}</div>", impl_.print(false, cx));
for it in &impl_.items {
- if let clean::AssocTypeItem(ref tydef, ref _bounds) = *it.kind {
+ if let clean::AssocTypeItem(ref tydef, ref _bounds) = it.kind {
out.push_str("<div class=\"where\"> ");
let empty_set = FxHashSet::default();
let src_link = AssocItemLink::GotoSource(trait_did.into(), &empty_set);
@@ -1659,7 +1660,7 @@ fn doc_impl_item(
let method_toggle_class = if item_type.is_method() { " method-toggle" } else { "" };
write!(w, "<details class=\"toggle{method_toggle_class}\" open><summary>");
}
- match &*item.kind {
+ match &item.kind {
clean::MethodItem(..) | clean::TyMethodItem(_) => {
// Only render when the method is not static or we allow static methods
if render_method_item {
@@ -1690,7 +1691,7 @@ fn doc_impl_item(
w.write_str("</h4></section>");
}
}
- clean::TyAssocConstItem(generics, ty) => {
+ clean::TyAssocConstItem(ref generics, ref ty) => {
let source_id = format!("{item_type}.{name}");
let id = cx.derive_id(&source_id);
write!(w, "<section id=\"{id}\" class=\"{item_type}{in_trait_class}\">");
@@ -1734,7 +1735,7 @@ fn doc_impl_item(
);
w.write_str("</h4></section>");
}
- clean::TyAssocTypeItem(generics, bounds) => {
+ clean::TyAssocTypeItem(ref generics, ref bounds) => {
let source_id = format!("{item_type}.{name}");
let id = cx.derive_id(&source_id);
write!(w, "<section id=\"{id}\" class=\"{item_type}{in_trait_class}\">");
@@ -1794,13 +1795,64 @@ fn doc_impl_item(
let mut default_impl_items = Buffer::empty_from(w);
let impl_ = i.inner_impl();
+ // Impl items are grouped by kinds:
+ //
+ // 1. Constants
+ // 2. Types
+ // 3. Functions
+ //
+ // This order is because you can have associated constants used in associated types (like array
+ // length), and both in associcated functions. So with this order, when reading from top to
+ // bottom, you should see items definitions before they're actually used most of the time.
+ let mut assoc_types = Vec::new();
+ let mut methods = Vec::new();
+
if !impl_.is_negative_trait_impl() {
for trait_item in &impl_.items {
+ match trait_item.kind {
+ clean::MethodItem(..) | clean::TyMethodItem(_) => methods.push(trait_item),
+ clean::TyAssocTypeItem(..) | clean::AssocTypeItem(..) => {
+ assoc_types.push(trait_item)
+ }
+ clean::TyAssocConstItem(..) | clean::AssocConstItem(_) => {
+ // We render it directly since they're supposed to come first.
+ doc_impl_item(
+ &mut default_impl_items,
+ &mut impl_items,
+ cx,
+ trait_item,
+ if trait_.is_some() { &i.impl_item } else { parent },
+ link,
+ render_mode,
+ false,
+ trait_,
+ rendering_params,
+ );
+ }
+ _ => {}
+ }
+ }
+
+ for assoc_type in assoc_types {
doc_impl_item(
&mut default_impl_items,
&mut impl_items,
cx,
- trait_item,
+ assoc_type,
+ if trait_.is_some() { &i.impl_item } else { parent },
+ link,
+ render_mode,
+ false,
+ trait_,
+ rendering_params,
+ );
+ }
+ for method in methods {
+ doc_impl_item(
+ &mut default_impl_items,
+ &mut impl_items,
+ cx,
+ method,
if trait_.is_some() { &i.impl_item } else { parent },
link,
render_mode,
@@ -2000,7 +2052,7 @@ pub(crate) fn render_impl_summary(
write!(w, "{}", inner_impl.print(use_absolute, cx));
if show_def_docs {
for it in &inner_impl.items {
- if let clean::AssocTypeItem(ref tydef, ref _bounds) = *it.kind {
+ if let clean::AssocTypeItem(ref tydef, ref _bounds) = it.kind {
w.write_str("<div class=\"where\"> ");
assoc_type(
w,
@@ -2121,7 +2173,7 @@ fn get_id_for_impl<'tcx>(tcx: TyCtxt<'tcx>, impl_id: ItemId) -> String {
}
fn extract_for_impl_name(item: &clean::Item, cx: &Context<'_>) -> Option<(String, String)> {
- match *item.kind {
+ match item.kind {
clean::ItemKind::ImplItem(ref i) if i.trait_.is_some() => {
// Alternative format produces no URLs,
// so this parameter does nothing.
@@ -2455,28 +2507,6 @@ fn render_call_locations<W: fmt::Write>(mut w: W, cx: &mut Context<'_>, item: &c
let needs_expansion = line_max - line_min > NUM_VISIBLE_LINES;
let locations_encoded = serde_json::to_string(&line_ranges).unwrap();
- write!(
- &mut w,
- "<div class=\"scraped-example {expanded_cls}\" data-locs=\"{locations}\">\
- <div class=\"scraped-example-title\">\
- {name} (<a href=\"{url}\">{title}</a>)\
- </div>\
- <div class=\"code-wrapper\">",
- expanded_cls = if needs_expansion { "" } else { "expanded" },
- name = call_data.display_name,
- url = init_url,
- title = init_title,
- // The locations are encoded as a data attribute, so they can be read
- // later by the JS for interactions.
- locations = Escape(&locations_encoded)
- )
- .unwrap();
-
- if line_ranges.len() > 1 {
- w.write_str(r#"<button class="prev">≺</button> <button class="next">≻</button>"#)
- .unwrap();
- }
-
// Look for the example file in the source map if it exists, otherwise return a dummy span
let file_span = (|| {
let source_map = tcx.sess.source_map();
@@ -2507,9 +2537,16 @@ fn render_call_locations<W: fmt::Write>(mut w: W, cx: &mut Context<'_>, item: &c
cx,
&cx.root_path(),
highlight::DecorationInfo(decoration_info),
- sources::SourceContext::Embedded { offset: line_min, needs_expansion },
+ sources::SourceContext::Embedded(sources::ScrapedInfo {
+ needs_prev_next_buttons: line_ranges.len() > 1,
+ needs_expansion,
+ offset: line_min,
+ name: &call_data.display_name,
+ url: init_url,
+ title: init_title,
+ locations: locations_encoded,
+ }),
);
- w.write_str("</div></div>").unwrap();
true
};
diff --git a/src/librustdoc/html/render/print_item.rs b/src/librustdoc/html/render/print_item.rs
index a0a72d5..52e2515 100644
--- a/src/librustdoc/html/render/print_item.rs
+++ b/src/librustdoc/html/render/print_item.rs
@@ -178,7 +178,7 @@ fn print_where_clause_and_check<'a, 'tcx: 'a>(
pub(super) fn print_item(cx: &mut Context<'_>, item: &clean::Item, buf: &mut Buffer) {
debug_assert!(!item.is_stripped());
- let typ = match *item.kind {
+ let typ = match item.kind {
clean::ModuleItem(_) => {
if item.is_crate() {
"Crate "
@@ -252,7 +252,7 @@ pub(super) fn print_item(cx: &mut Context<'_>, item: &clean::Item, buf: &mut Buf
item_vars.render_into(buf).unwrap();
- match &*item.kind {
+ match &item.kind {
clean::ModuleItem(ref m) => item_module(buf, cx, item, &m.items),
clean::FunctionItem(ref f) | clean::ForeignFunctionItem(ref f, _) => {
item_function(buf, cx, item, f)
@@ -411,7 +411,7 @@ fn cmp(i1: &clean::Item, i2: &clean::Item, tcx: TyCtxt<'_>) -> Ordering {
);
}
- match *myitem.kind {
+ match myitem.kind {
clean::ExternCrateItem { ref src } => {
use crate::html::format::anchor;
@@ -477,7 +477,7 @@ fn cmp(i1: &clean::Item, i2: &clean::Item, tcx: TyCtxt<'_>) -> Ordering {
continue;
}
- let unsafety_flag = match *myitem.kind {
+ let unsafety_flag = match myitem.kind {
clean::FunctionItem(_) | clean::ForeignFunctionItem(..)
if myitem.fn_header(tcx).unwrap().safety == hir::Safety::Unsafe =>
{
@@ -843,33 +843,6 @@ fn trait_item(w: &mut Buffer, cx: &mut Context<'_>, m: &clean::Item, t: &clean::
}
}
- if !required_types.is_empty() {
- write_section_heading(
- w,
- "Required Associated Types",
- "required-associated-types",
- None,
- "<div class=\"methods\">",
- );
- for t in required_types {
- trait_item(w, cx, t, it);
- }
- w.write_str("</div>");
- }
- if !provided_types.is_empty() {
- write_section_heading(
- w,
- "Provided Associated Types",
- "provided-associated-types",
- None,
- "<div class=\"methods\">",
- );
- for t in provided_types {
- trait_item(w, cx, t, it);
- }
- w.write_str("</div>");
- }
-
if !required_consts.is_empty() {
write_section_heading(
w,
@@ -897,6 +870,33 @@ fn trait_item(w: &mut Buffer, cx: &mut Context<'_>, m: &clean::Item, t: &clean::
w.write_str("</div>");
}
+ if !required_types.is_empty() {
+ write_section_heading(
+ w,
+ "Required Associated Types",
+ "required-associated-types",
+ None,
+ "<div class=\"methods\">",
+ );
+ for t in required_types {
+ trait_item(w, cx, t, it);
+ }
+ w.write_str("</div>");
+ }
+ if !provided_types.is_empty() {
+ write_section_heading(
+ w,
+ "Provided Associated Types",
+ "provided-associated-types",
+ None,
+ "<div class=\"methods\">",
+ );
+ for t in provided_types {
+ trait_item(w, cx, t, it);
+ }
+ w.write_str("</div>");
+ }
+
// Output the documentation for each function individually
if !required_methods.is_empty() || must_implement_one_of_functions.is_some() {
write_section_heading(
@@ -1439,7 +1439,7 @@ fn fields_iter(
self.s
.fields
.iter()
- .filter_map(|f| match *f.kind {
+ .filter_map(|f| match f.kind {
clean::StructFieldItem(ref ty) => Some((f, ty)),
_ => None,
})
@@ -1457,7 +1457,7 @@ fn print_tuple_struct_fields<'a, 'cx: 'a>(
display_fn(|f| {
if !s.is_empty()
&& s.iter().all(|field| {
- matches!(*field.kind, clean::StrippedItem(box clean::StructFieldItem(..)))
+ matches!(field.kind, clean::StrippedItem(box clean::StructFieldItem(..)))
})
{
return f.write_str("<span class=\"comment\">/* private fields */</span>");
@@ -1467,7 +1467,7 @@ fn print_tuple_struct_fields<'a, 'cx: 'a>(
if i > 0 {
f.write_str(", ")?;
}
- match *ty.kind {
+ match ty.kind {
clean::StrippedItem(box clean::StructFieldItem(_)) => f.write_str("_")?,
clean::StructFieldItem(ref ty) => write!(f, "{}", ty.print(cx))?,
_ => unreachable!(),
@@ -1521,7 +1521,7 @@ fn should_show_enum_discriminant(
) -> bool {
let mut has_variants_with_value = false;
for variant in variants {
- if let clean::VariantItem(ref var) = *variant.kind
+ if let clean::VariantItem(ref var) = variant.kind
&& matches!(var.kind, clean::VariantKind::CLike)
{
has_variants_with_value |= var.discriminant.is_some();
@@ -1592,7 +1592,7 @@ fn render_enum_fields(
continue;
}
w.write_str(TAB);
- match *v.kind {
+ match v.kind {
clean::VariantItem(ref var) => match var.kind {
clean::VariantKind::CLike => display_c_like_variant(
w,
@@ -1659,7 +1659,7 @@ fn item_variants(
" rightside",
);
w.write_str("<h3 class=\"code-header\">");
- if let clean::VariantItem(ref var) = *variant.kind
+ if let clean::VariantItem(ref var) = variant.kind
&& let clean::VariantKind::CLike = var.kind
{
display_c_like_variant(
@@ -1675,7 +1675,7 @@ fn item_variants(
w.write_str(variant.name.unwrap().as_str());
}
- let clean::VariantItem(variant_data) = &*variant.kind else { unreachable!() };
+ let clean::VariantItem(variant_data) = &variant.kind else { unreachable!() };
if let clean::VariantKind::Tuple(ref s) = variant_data.kind {
write!(w, "({})", print_tuple_struct_fields(cx, s));
@@ -1716,7 +1716,7 @@ fn item_variants(
document_non_exhaustive(variant)
);
for field in fields {
- match *field.kind {
+ match field.kind {
clean::StrippedItem(box clean::StructFieldItem(_)) => {}
clean::StructFieldItem(ref ty) => {
let id = cx.derive_id(format!(
@@ -1886,7 +1886,7 @@ fn item_fields(
) {
let mut fields = fields
.iter()
- .filter_map(|f| match *f.kind {
+ .filter_map(|f| match f.kind {
clean::StructFieldItem(ref ty) => Some((f, ty)),
_ => None,
})
@@ -2196,14 +2196,14 @@ fn render_union<'a, 'cx: 'a>(
write!(f, "{{\n")?;
let count_fields =
- fields.iter().filter(|field| matches!(*field.kind, clean::StructFieldItem(..))).count();
+ fields.iter().filter(|field| matches!(field.kind, clean::StructFieldItem(..))).count();
let toggle = should_hide_fields(count_fields);
if toggle {
toggle_open(&mut f, format_args!("{count_fields} fields"));
}
for field in fields {
- if let clean::StructFieldItem(ref ty) = *field.kind {
+ if let clean::StructFieldItem(ref ty) = field.kind {
write!(
f,
" {}{}: {},\n",
@@ -2279,14 +2279,14 @@ fn render_struct_fields(
w.write_str("{");
}
let count_fields =
- fields.iter().filter(|f| matches!(*f.kind, clean::StructFieldItem(..))).count();
+ fields.iter().filter(|f| matches!(f.kind, clean::StructFieldItem(..))).count();
let has_visible_fields = count_fields > 0;
let toggle = should_hide_fields(count_fields);
if toggle {
toggle_open(&mut w, format_args!("{count_fields} fields"));
}
for field in fields {
- if let clean::StructFieldItem(ref ty) = *field.kind {
+ if let clean::StructFieldItem(ref ty) = field.kind {
write!(
w,
"\n{tab} {vis}{name}: {ty},",
@@ -2314,7 +2314,7 @@ fn render_struct_fields(
w.write_str("(");
if !fields.is_empty()
&& fields.iter().all(|field| {
- matches!(*field.kind, clean::StrippedItem(box clean::StructFieldItem(..)))
+ matches!(field.kind, clean::StrippedItem(box clean::StructFieldItem(..)))
})
{
write!(w, "<span class=\"comment\">/* private fields */</span>");
@@ -2323,7 +2323,7 @@ fn render_struct_fields(
if i > 0 {
w.write_str(", ");
}
- match *field.kind {
+ match field.kind {
clean::StrippedItem(box clean::StructFieldItem(..)) => write!(w, "_"),
clean::StructFieldItem(ref ty) => {
write!(w, "{}{}", visibility_print_with_space(field, cx), ty.print(cx),)
diff --git a/src/librustdoc/html/render/search_index.rs b/src/librustdoc/html/render/search_index.rs
index bfdf457..b84c22a 100644
--- a/src/librustdoc/html/render/search_index.rs
+++ b/src/librustdoc/html/render/search_index.rs
@@ -758,7 +758,7 @@ pub(crate) fn get_function_type_for_search<'tcx>(
None
}
});
- let (mut inputs, mut output, where_clause) = match *item.kind {
+ let (mut inputs, mut output, where_clause) = match item.kind {
clean::FunctionItem(ref f) | clean::MethodItem(ref f, _) | clean::TyMethodItem(ref f) => {
get_fn_inputs_and_outputs(f, tcx, impl_or_trait_generics, cache)
}
@@ -1132,7 +1132,7 @@ fn simplify_fn_type<'tcx, 'a>(
&& trait_.items.iter().any(|at| at.is_ty_associated_type())
{
for assoc_ty in &trait_.items {
- if let clean::ItemKind::TyAssocTypeItem(_generics, bounds) = &*assoc_ty.kind
+ if let clean::ItemKind::TyAssocTypeItem(_generics, bounds) = &assoc_ty.kind
&& let Some(name) = assoc_ty.name
{
let idx = -isize::try_from(rgen.len() + 1).unwrap();
diff --git a/src/librustdoc/html/render/sidebar.rs b/src/librustdoc/html/render/sidebar.rs
index c75c28e..842ee81 100644
--- a/src/librustdoc/html/render/sidebar.rs
+++ b/src/librustdoc/html/render/sidebar.rs
@@ -119,7 +119,7 @@ pub(crate) fn wrapped<T>(v: T) -> rinja::Result<Safe<impl Display>>
pub(super) fn print_sidebar(cx: &Context<'_>, it: &clean::Item, buffer: &mut Buffer) {
let mut ids = IdMap::new();
let mut blocks: Vec<LinkBlock<'_>> = docblock_toc(cx, it, &mut ids).into_iter().collect();
- match *it.kind {
+ match it.kind {
clean::StructItem(ref s) => sidebar_struct(cx, it, s, &mut blocks),
clean::TraitItem(ref t) => sidebar_trait(cx, it, t, &mut blocks),
clean::PrimitiveItem(_) => sidebar_primitive(cx, it, &mut blocks),
@@ -143,7 +143,7 @@ pub(super) fn print_sidebar(cx: &Context<'_>, it: &clean::Item, buffer: &mut Buf
// crate title is displayed as part of logo lockup
let (title_prefix, title) = if !blocks.is_empty() && !it.is_crate() {
(
- match *it.kind {
+ match it.kind {
clean::ModuleItem(..) => "Module ",
_ => "",
},
@@ -181,7 +181,7 @@ pub(super) fn print_sidebar(cx: &Context<'_>, it: &clean::Item, buffer: &mut Buf
fn get_struct_fields_name<'a>(fields: &'a [clean::Item]) -> Vec<Link<'a>> {
let mut fields = fields
.iter()
- .filter(|f| matches!(*f.kind, clean::StructFieldItem(..)))
+ .filter(|f| matches!(f.kind, clean::StructFieldItem(..)))
.filter_map(|f| {
f.name.as_ref().map(|name| Link::new(format!("structfield.{name}"), name.as_str()))
})
@@ -302,10 +302,10 @@ fn filter_items<'a>(
blocks.extend(
[
- ("required-associated-types", "Required Associated Types", req_assoc),
- ("provided-associated-types", "Provided Associated Types", prov_assoc),
("required-associated-consts", "Required Associated Constants", req_assoc_const),
("provided-associated-consts", "Provided Associated Constants", prov_assoc_const),
+ ("required-associated-types", "Required Associated Types", req_assoc),
+ ("provided-associated-types", "Provided Associated Types", prov_assoc),
("required-methods", "Required Methods", req_method),
("provided-methods", "Provided Methods", prov_method),
("foreign-impls", "Implementations on Foreign Types", foreign_impls),
@@ -394,6 +394,7 @@ fn sidebar_assoc_items<'a>(
let cache = cx.cache();
let mut assoc_consts = Vec::new();
+ let mut assoc_types = Vec::new();
let mut methods = Vec::new();
if let Some(v) = cache.impls.get(&did) {
let mut used_links = FxHashSet::default();
@@ -401,22 +402,14 @@ fn sidebar_assoc_items<'a>(
{
let used_links_bor = &mut used_links;
- assoc_consts.extend(
- v.iter()
- .filter(|i| i.inner_impl().trait_.is_none())
- .flat_map(|i| get_associated_constants(i.inner_impl(), used_links_bor)),
- );
+ for impl_ in v.iter().map(|i| i.inner_impl()).filter(|i| i.trait_.is_none()) {
+ assoc_consts.extend(get_associated_constants(impl_, used_links_bor));
+ assoc_types.extend(get_associated_types(impl_, used_links_bor));
+ methods.extend(get_methods(impl_, false, used_links_bor, false, cx.tcx()));
+ }
// We want links' order to be reproducible so we don't use unstable sort.
assoc_consts.sort();
-
- #[rustfmt::skip] // rustfmt makes the pipeline less readable
- methods.extend(
- v.iter()
- .filter(|i| i.inner_impl().trait_.is_none())
- .flat_map(|i| get_methods(i.inner_impl(), false, used_links_bor, false, cx.tcx())),
- );
-
- // We want links' order to be reproducible so we don't use unstable sort.
+ assoc_types.sort();
methods.sort();
}
@@ -426,6 +419,11 @@ fn sidebar_assoc_items<'a>(
"associatedconstant",
assoc_consts,
),
+ LinkBlock::new(
+ Link::new("implementations", "Associated Types"),
+ "associatedtype",
+ assoc_types,
+ ),
LinkBlock::new(Link::new("implementations", "Methods"), "method", methods),
];
@@ -452,6 +450,7 @@ fn sidebar_assoc_items<'a>(
&mut blocks,
);
}
+
links.append(&mut blocks);
}
}
@@ -468,7 +467,7 @@ fn sidebar_deref_methods<'a>(
debug!("found Deref: {impl_:?}");
if let Some((target, real_target)) =
- impl_.inner_impl().items.iter().find_map(|item| match *item.kind {
+ impl_.inner_impl().items.iter().find_map(|item| match item.kind {
clean::AssocTypeItem(box ref t, _) => Some(match *t {
clean::TypeAlias { item_type: Some(ref type_), .. } => (type_, &t.type_),
_ => (&t.type_, &t.type_),
@@ -588,7 +587,7 @@ fn sidebar_module(
&& it
.name
.or_else(|| {
- if let clean::ImportItem(ref i) = *it.kind
+ if let clean::ImportItem(ref i) = it.kind
&& let clean::ImportKind::Simple(s) = i.kind
{
Some(s)
@@ -715,3 +714,19 @@ fn get_associated_constants<'a>(
})
.collect::<Vec<_>>()
}
+
+fn get_associated_types<'a>(
+ i: &'a clean::Impl,
+ used_links: &mut FxHashSet<String>,
+) -> Vec<Link<'a>> {
+ i.items
+ .iter()
+ .filter_map(|item| match item.name {
+ Some(ref name) if !name.is_empty() && item.is_associated_type() => Some(Link::new(
+ get_next_url(used_links, format!("{typ}.{name}", typ = ItemType::AssocType)),
+ name.as_str(),
+ )),
+ _ => None,
+ })
+ .collect::<Vec<_>>()
+}
diff --git a/src/librustdoc/html/render/write_shared.rs b/src/librustdoc/html/render/write_shared.rs
index 60dc142..dc1a8cc 100644
--- a/src/librustdoc/html/render/write_shared.rs
+++ b/src/librustdoc/html/render/write_shared.rs
@@ -29,7 +29,7 @@
use regex::Regex;
use rustc_data_structures::flock;
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
-use rustc_middle::ty::fast_reject::{DeepRejectCtxt, TreatParams};
+use rustc_middle::ty::fast_reject::DeepRejectCtxt;
use rustc_middle::ty::TyCtxt;
use rustc_span::def_id::DefId;
use rustc_span::Symbol;
@@ -39,7 +39,7 @@
use super::{collect_paths_for_type, ensure_trailing_slash, Context, RenderMode};
use crate::clean::{Crate, Item, ItemId, ItemKind};
-use crate::config::{EmitType, RenderOptions};
+use crate::config::{EmitType, PathToParts, RenderOptions, ShouldMerge};
use crate::docfs::PathError;
use crate::error::Error;
use crate::formats::cache::Cache;
@@ -50,12 +50,11 @@
use crate::html::render::ordered_json::{EscapedJson, OrderedJson};
use crate::html::render::search_index::{build_index, SerializedSearchIndex};
use crate::html::render::sorted_template::{self, FileFormat, SortedTemplate};
-use crate::html::render::{AssocItemLink, ImplRenderingParameters};
+use crate::html::render::{AssocItemLink, ImplRenderingParameters, StylePath};
use crate::html::static_files::{self, suffix_path};
use crate::visit::DocVisitor;
use crate::{try_err, try_none};
-/// Write cross-crate information files, static files, invocation-specific files, etc. to disk
pub(crate) fn write_shared(
cx: &mut Context<'_>,
krate: &Crate,
@@ -70,13 +69,14 @@ pub(crate) fn write_shared(
let SerializedSearchIndex { index, desc } =
build_index(&krate, &mut Rc::get_mut(&mut cx.shared).unwrap().cache, tcx);
- write_search_desc(cx, &krate, &desc)?; // does not need to be merged; written unconditionally
+ write_search_desc(cx, &krate, &desc)?; // does not need to be merged
let crate_name = krate.name(cx.tcx());
let crate_name = crate_name.as_str(); // rand
let crate_name_json = OrderedJson::serialize(crate_name).unwrap(); // "rand"
let external_crates = hack_get_external_crate_names(&cx.dst, &cx.shared.resource_suffix)?;
let info = CrateInfo {
+ version: CrateInfoVersion::V1,
src_files_js: SourcesPart::get(cx, &crate_name_json)?,
search_index_js: SearchIndexPart::get(index, &cx.shared.resource_suffix)?,
all_crates: AllCratesPart::get(crate_name_json.clone(), &cx.shared.resource_suffix)?,
@@ -85,47 +85,103 @@ pub(crate) fn write_shared(
type_impl: TypeAliasPart::get(cx, krate, &crate_name_json)?,
};
- let crates = vec![info]; // we have info from just one crate. rest will found in out dir
-
- write_static_files(cx, &opt)?;
- let dst = &cx.dst;
- if opt.emit.is_empty() || opt.emit.contains(&EmitType::InvocationSpecific) {
- if cx.include_sources {
- write_rendered_cci::<SourcesPart, _>(SourcesPart::blank, dst, &crates)?;
- }
- write_rendered_cci::<SearchIndexPart, _>(SearchIndexPart::blank, dst, &crates)?;
- write_rendered_cci::<AllCratesPart, _>(AllCratesPart::blank, dst, &crates)?;
+ if let Some(parts_out_dir) = &opt.parts_out_dir {
+ create_parents(&parts_out_dir.0)?;
+ try_err!(
+ fs::write(&parts_out_dir.0, serde_json::to_string(&info).unwrap()),
+ &parts_out_dir.0
+ );
}
- write_rendered_cci::<TraitAliasPart, _>(TraitAliasPart::blank, dst, &crates)?;
- write_rendered_cci::<TypeAliasPart, _>(TypeAliasPart::blank, dst, &crates)?;
- match &opt.index_page {
- Some(index_page) if opt.enable_index_page => {
- let mut md_opts = opt.clone();
- md_opts.output = cx.dst.clone();
- md_opts.external_html = cx.shared.layout.external_html.clone();
- try_err!(
- crate::markdown::render(&index_page, md_opts, cx.shared.edition()),
- &index_page
- );
+
+ let mut crates = CrateInfo::read_many(&opt.include_parts_dir)?;
+ crates.push(info);
+
+ if opt.should_merge.write_rendered_cci {
+ write_not_crate_specific(
+ &crates,
+ &cx.dst,
+ opt,
+ &cx.shared.style_files,
+ cx.shared.layout.css_file_extension.as_deref(),
+ &cx.shared.resource_suffix,
+ cx.include_sources,
+ )?;
+ match &opt.index_page {
+ Some(index_page) if opt.enable_index_page => {
+ let mut md_opts = opt.clone();
+ md_opts.output = cx.dst.clone();
+ md_opts.external_html = cx.shared.layout.external_html.clone();
+ try_err!(
+ crate::markdown::render(&index_page, md_opts, cx.shared.edition()),
+ &index_page
+ );
+ }
+ None if opt.enable_index_page => {
+ write_rendered_cci::<CratesIndexPart, _>(
+ || CratesIndexPart::blank(cx),
+ &cx.dst,
+ &crates,
+ &opt.should_merge,
+ )?;
+ }
+ _ => {} // they don't want an index page
}
- None if opt.enable_index_page => {
- write_rendered_cci::<CratesIndexPart, _>(|| CratesIndexPart::blank(cx), dst, &crates)?;
- }
- _ => {} // they don't want an index page
}
Rc::get_mut(&mut cx.shared).unwrap().fs.set_sync_only(false);
Ok(())
}
-/// Writes the static files, the style files, and the css extensions
-fn write_static_files(cx: &mut Context<'_>, options: &RenderOptions) -> Result<(), Error> {
- let static_dir = cx.dst.join("static.files");
+/// Writes files that are written directly to the `--out-dir`, without the prefix from the current
+/// crate. These are the rendered cross-crate files that encode info from multiple crates (e.g.
+/// search index), and the static files.
+pub(crate) fn write_not_crate_specific(
+ crates: &[CrateInfo],
+ dst: &Path,
+ opt: &RenderOptions,
+ style_files: &[StylePath],
+ css_file_extension: Option<&Path>,
+ resource_suffix: &str,
+ include_sources: bool,
+) -> Result<(), Error> {
+ write_rendered_cross_crate_info(crates, dst, opt, include_sources)?;
+ write_static_files(dst, opt, style_files, css_file_extension, resource_suffix)?;
+ Ok(())
+}
- cx.shared.fs.create_dir_all(&static_dir).map_err(|e| PathError::new(e, "static.files"))?;
+fn write_rendered_cross_crate_info(
+ crates: &[CrateInfo],
+ dst: &Path,
+ opt: &RenderOptions,
+ include_sources: bool,
+) -> Result<(), Error> {
+ let m = &opt.should_merge;
+ if opt.emit.is_empty() || opt.emit.contains(&EmitType::InvocationSpecific) {
+ if include_sources {
+ write_rendered_cci::<SourcesPart, _>(SourcesPart::blank, dst, &crates, m)?;
+ }
+ write_rendered_cci::<SearchIndexPart, _>(SearchIndexPart::blank, dst, &crates, m)?;
+ write_rendered_cci::<AllCratesPart, _>(AllCratesPart::blank, dst, &crates, m)?;
+ }
+ write_rendered_cci::<TraitAliasPart, _>(TraitAliasPart::blank, dst, &crates, m)?;
+ write_rendered_cci::<TypeAliasPart, _>(TypeAliasPart::blank, dst, &crates, m)?;
+ Ok(())
+}
+
+/// Writes the static files, the style files, and the css extensions.
+/// Have to be careful about these, because they write to the root out dir.
+fn write_static_files(
+ dst: &Path,
+ opt: &RenderOptions,
+ style_files: &[StylePath],
+ css_file_extension: Option<&Path>,
+ resource_suffix: &str,
+) -> Result<(), Error> {
+ let static_dir = dst.join("static.files");
+ try_err!(fs::create_dir_all(&static_dir), &static_dir);
// Handle added third-party themes
- for entry in &cx.shared.style_files {
+ for entry in style_files {
let theme = entry.basename()?;
let extension =
try_none!(try_none!(entry.path.extension(), &entry.path).to_str(), &entry.path);
@@ -136,22 +192,24 @@ fn write_static_files(cx: &mut Context<'_>, options: &RenderOptions) -> Result<(
}
let bytes = try_err!(fs::read(&entry.path), &entry.path);
- let filename = format!("{theme}{suffix}.{extension}", suffix = cx.shared.resource_suffix);
- cx.shared.fs.write(cx.dst.join(filename), bytes)?;
+ let filename = format!("{theme}{resource_suffix}.{extension}");
+ let dst_filename = dst.join(filename);
+ try_err!(fs::write(&dst_filename, bytes), &dst_filename);
}
// When the user adds their own CSS files with --extend-css, we write that as an
// invocation-specific file (that is, with a resource suffix).
- if let Some(ref css) = cx.shared.layout.css_file_extension {
+ if let Some(css) = css_file_extension {
let buffer = try_err!(fs::read_to_string(css), css);
- let path = static_files::suffix_path("theme.css", &cx.shared.resource_suffix);
- cx.shared.fs.write(cx.dst.join(path), buffer)?;
+ let path = static_files::suffix_path("theme.css", resource_suffix);
+ let dst_path = dst.join(path);
+ try_err!(fs::write(&dst_path, buffer), &dst_path);
}
- if options.emit.is_empty() || options.emit.contains(&EmitType::Toolchain) {
+ if opt.emit.is_empty() || opt.emit.contains(&EmitType::Toolchain) {
static_files::for_each(|f: &static_files::StaticFile| {
let filename = static_dir.join(f.output_filename());
- cx.shared.fs.write(filename, f.minified())
+ fs::write(&filename, f.minified()).map_err(|e| PathError::new(e, &filename))
})?;
}
@@ -186,7 +244,8 @@ fn write_search_desc(
/// Contains pre-rendered contents to insert into the CCI template
#[derive(Serialize, Deserialize, Clone, Debug)]
-struct CrateInfo {
+pub(crate) struct CrateInfo {
+ version: CrateInfoVersion,
src_files_js: PartsAndLocations<SourcesPart>,
search_index_js: PartsAndLocations<SearchIndexPart>,
all_crates: PartsAndLocations<AllCratesPart>,
@@ -195,6 +254,33 @@ struct CrateInfo {
type_impl: PartsAndLocations<TypeAliasPart>,
}
+impl CrateInfo {
+ /// Read all of the crate info from its location on the filesystem
+ pub(crate) fn read_many(parts_paths: &[PathToParts]) -> Result<Vec<Self>, Error> {
+ parts_paths
+ .iter()
+ .map(|parts_path| {
+ let path = &parts_path.0;
+ let parts = try_err!(fs::read(&path), &path);
+ let parts: CrateInfo = try_err!(serde_json::from_slice(&parts), &path);
+ Ok::<_, Error>(parts)
+ })
+ .collect::<Result<Vec<CrateInfo>, Error>>()
+ }
+}
+
+/// Version for the format of the crate-info file.
+///
+/// This enum should only ever have one variant, representing the current version.
+/// Gives pretty good error message about expecting the current version on deserialize.
+///
+/// Must be incremented (V2, V3, etc.) upon any changes to the search index or CrateInfo,
+/// to provide better diagnostics about including an invalid file.
+#[derive(Serialize, Deserialize, Clone, Debug)]
+enum CrateInfoVersion {
+ V1,
+}
+
/// Paths (relative to the doc root) and their pre-merge contents
#[derive(Serialize, Deserialize, Debug, Clone)]
#[serde(transparent)]
@@ -783,7 +869,7 @@ impl<'cx, 'cache> DocVisitor for TypeImplCollector<'cx, 'cache> {
fn visit_item(&mut self, it: &Item) {
self.visit_item_recur(it);
let cache = self.cache;
- let ItemKind::TypeAliasItem(ref t) = *it.kind else { return };
+ let ItemKind::TypeAliasItem(ref t) = it.kind else { return };
let Some(self_did) = it.item_id.as_def_id() else { return };
if !self.visited_aliases.insert(self_did) {
return;
@@ -832,7 +918,7 @@ fn visit_item(&mut self, it: &Item) {
// Be aware of `tests/rustdoc/type-alias/deeply-nested-112515.rs` which might regress.
let Some(impl_did) = impl_item_id.as_def_id() else { continue };
let for_ty = self.cx.tcx().type_of(impl_did).skip_binder();
- let reject_cx = DeepRejectCtxt::new(self.cx.tcx(), TreatParams::AsCandidateKey);
+ let reject_cx = DeepRejectCtxt::relate_infer_infer(self.cx.tcx());
if !reject_cx.types_may_unify(aliased_ty, for_ty) {
continue;
}
@@ -900,10 +986,14 @@ fn create_parents(path: &Path) -> Result<(), Error> {
fn read_template_or_blank<F, T: FileFormat>(
mut make_blank: F,
path: &Path,
+ should_merge: &ShouldMerge,
) -> Result<SortedTemplate<T>, Error>
where
F: FnMut() -> SortedTemplate<T>,
{
+ if !should_merge.read_rendered_cci {
+ return Ok(make_blank());
+ }
match fs::read_to_string(&path) {
Ok(template) => Ok(try_err!(SortedTemplate::from_str(&template), &path)),
Err(e) if e.kind() == io::ErrorKind::NotFound => Ok(make_blank()),
@@ -916,6 +1006,7 @@ fn write_rendered_cci<T: CciPart, F>(
mut make_blank: F,
dst: &Path,
crates_info: &[CrateInfo],
+ should_merge: &ShouldMerge,
) -> Result<(), Error>
where
F: FnMut() -> SortedTemplate<T::FileFormat>,
@@ -924,7 +1015,8 @@ fn write_rendered_cci<T: CciPart, F>(
for (path, parts) in get_path_parts::<T>(dst, crates_info) {
create_parents(&path)?;
// read previous rendered cci from storage, append to them
- let mut template = read_template_or_blank::<_, T::FileFormat>(&mut make_blank, &path)?;
+ let mut template =
+ read_template_or_blank::<_, T::FileFormat>(&mut make_blank, &path, should_merge)?;
for part in parts {
template.append(part);
}
diff --git a/src/librustdoc/html/render/write_shared/tests.rs b/src/librustdoc/html/render/write_shared/tests.rs
index e282cd9..a235f1d 100644
--- a/src/librustdoc/html/render/write_shared/tests.rs
+++ b/src/librustdoc/html/render/write_shared/tests.rs
@@ -1,3 +1,4 @@
+use crate::config::ShouldMerge;
use crate::html::render::ordered_json::{EscapedJson, OrderedJson};
use crate::html::render::sorted_template::{Html, SortedTemplate};
use crate::html::render::write_shared::*;
@@ -192,16 +193,17 @@ fn read_template_test() {
let path = path.path().join("file.html");
let make_blank = || SortedTemplate::<Html>::from_before_after("<div>", "</div>");
- let template = read_template_or_blank(make_blank, &path).unwrap();
+ let should_merge = ShouldMerge { read_rendered_cci: true, write_rendered_cci: true };
+ let template = read_template_or_blank(make_blank, &path, &should_merge).unwrap();
assert_eq!(but_last_line(&template.to_string()), "<div></div>");
fs::write(&path, template.to_string()).unwrap();
- let mut template = read_template_or_blank(make_blank, &path).unwrap();
+ let mut template = read_template_or_blank(make_blank, &path, &should_merge).unwrap();
template.append("<img/>".to_string());
fs::write(&path, template.to_string()).unwrap();
- let mut template = read_template_or_blank(make_blank, &path).unwrap();
+ let mut template = read_template_or_blank(make_blank, &path, &should_merge).unwrap();
template.append("<br/>".to_string());
fs::write(&path, template.to_string()).unwrap();
- let template = read_template_or_blank(make_blank, &path).unwrap();
+ let template = read_template_or_blank(make_blank, &path, &should_merge).unwrap();
assert_eq!(but_last_line(&template.to_string()), "<div><br/><img/></div>");
}
diff --git a/src/librustdoc/html/sources.rs b/src/librustdoc/html/sources.rs
index ae65dd7..551bb56 100644
--- a/src/librustdoc/html/sources.rs
+++ b/src/librustdoc/html/sources.rs
@@ -290,9 +290,34 @@ pub(crate) fn clean_path<F, P>(src_root: &Path, p: &Path, mut f: F, mut parent:
}
}
-pub(crate) enum SourceContext {
+pub(crate) struct ScrapedInfo<'a> {
+ pub(crate) offset: usize,
+ pub(crate) needs_prev_next_buttons: bool,
+ pub(crate) name: &'a str,
+ pub(crate) url: &'a str,
+ pub(crate) title: &'a str,
+ pub(crate) locations: String,
+ pub(crate) needs_expansion: bool,
+}
+
+#[derive(Template)]
+#[template(path = "scraped_source.html")]
+struct ScrapedSource<'a, Code: std::fmt::Display> {
+ info: ScrapedInfo<'a>,
+ lines: RangeInclusive<usize>,
+ code_html: Code,
+}
+
+#[derive(Template)]
+#[template(path = "source.html")]
+struct Source<Code: std::fmt::Display> {
+ lines: RangeInclusive<usize>,
+ code_html: Code,
+}
+
+pub(crate) enum SourceContext<'a> {
Standalone,
- Embedded { offset: usize, needs_expansion: bool },
+ Embedded(ScrapedInfo<'a>),
}
/// Wrapper struct to render the source code of a file. This will do things like
@@ -304,23 +329,8 @@ pub(crate) fn print_src(
context: &Context<'_>,
root_path: &str,
decoration_info: highlight::DecorationInfo,
- source_context: SourceContext,
+ source_context: SourceContext<'_>,
) {
- #[derive(Template)]
- #[template(path = "source.html")]
- struct Source<Code: std::fmt::Display> {
- embedded: bool,
- needs_expansion: bool,
- lines: RangeInclusive<usize>,
- code_html: Code,
- }
- let lines = s.lines().count();
- let (embedded, needs_expansion, lines) = match source_context {
- SourceContext::Standalone => (false, false, 1..=lines),
- SourceContext::Embedded { offset, needs_expansion } => {
- (true, needs_expansion, (1 + offset)..=(lines + offset))
- }
- };
let current_href = context
.href_from_span(clean::Span::new(file_span), false)
.expect("only local crates should have sources emitted");
@@ -333,5 +343,14 @@ struct Source<Code: std::fmt::Display> {
);
Ok(())
});
- Source { embedded, needs_expansion, lines, code_html: code }.render_into(&mut writer).unwrap();
+ let lines = s.lines().count();
+ match source_context {
+ SourceContext::Standalone => {
+ Source { lines: (1..=lines), code_html: code }.render_into(&mut writer).unwrap()
+ }
+ SourceContext::Embedded(info) => {
+ let lines = (1 + info.offset)..=(lines + info.offset);
+ ScrapedSource { info, lines, code_html: code }.render_into(&mut writer).unwrap();
+ }
+ };
}
diff --git a/src/librustdoc/html/static/css/noscript.css b/src/librustdoc/html/static/css/noscript.css
index 86e8eda..e62b162 100644
--- a/src/librustdoc/html/static/css/noscript.css
+++ b/src/librustdoc/html/static/css/noscript.css
@@ -59,6 +59,8 @@
--copy-path-button-color: #999;
--copy-path-img-filter: invert(50%);
--copy-path-img-hover-filter: invert(35%);
+ --code-example-button-color: #7f7f7f;
+ --code-example-button-hover-color: #595959;
--codeblock-error-hover-color: rgb(255, 0, 0);
--codeblock-error-color: rgba(255, 0, 0, .5);
--codeblock-ignore-hover-color: rgb(255, 142, 0);
@@ -162,6 +164,8 @@
--copy-path-button-color: #999;
--copy-path-img-filter: invert(50%);
--copy-path-img-hover-filter: invert(65%);
+ --code-example-button-color: #7f7f7f;
+ --code-example-button-hover-color: #a5a5a5;
--codeblock-error-hover-color: rgb(255, 0, 0);
--codeblock-error-color: rgba(255, 0, 0, .5);
--codeblock-ignore-hover-color: rgb(255, 142, 0);
diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css
index 271de1b..38154de 100644
--- a/src/librustdoc/html/static/css/rustdoc.css
+++ b/src/librustdoc/html/static/css/rustdoc.css
@@ -378,7 +378,7 @@
.src .content pre {
padding: 20px;
}
-.rustdoc.src .example-wrap pre.src-line-numbers {
+.rustdoc.src .example-wrap .src-line-numbers {
padding: 20px 0 20px 4px;
}
@@ -757,10 +757,32 @@
margin-bottom: 10px;
}
-.rustdoc .example-wrap > pre {
+.rustdoc .example-wrap > pre,
+.rustdoc .scraped-example .src-line-numbers,
+.rustdoc .scraped-example .src-line-numbers > pre {
border-radius: 6px;
}
+/*
+If the code example line numbers are displayed, there will be a weird radius in the middle from
+both the code example and the line numbers, so we need to remove the radius in this case.
+*/
+.rustdoc .example-wrap > .example-line-numbers,
+.rustdoc .scraped-example .src-line-numbers,
+.rustdoc .scraped-example .src-line-numbers > pre {
+ border-top-right-radius: 0;
+ border-bottom-right-radius: 0;
+}
+.rustdoc .example-wrap > .example-line-numbers + pre,
+.rustdoc .scraped-example .rust {
+ border-top-left-radius: 0;
+ border-bottom-left-radius: 0;
+}
+
+.rustdoc .scraped-example {
+ position: relative;
+}
+
/* For the last child of a div, the margin will be taken care of
by the margin-top of the next item. */
.rustdoc .example-wrap:last-child {
@@ -772,15 +794,36 @@
flex-grow: 1;
}
-.rustdoc:not(.src) .example-wrap pre {
+.scraped-example:not(.expanded) .example-wrap {
+ /* scrape-examples.js has a constant DEFAULT_MAX_LINES (call it N) for the number
+ * of lines shown in the un-expanded example code viewer. This pre needs to have
+ * a max-height equal to line-height * N. The line-height is currently 1.5em,
+ * and we include additional 10px for padding. */
+ max-height: calc(1.5em * 5 + 10px);
+}
+
+.rustdoc:not(.src) .scraped-example:not(.expanded) .src-line-numbers,
+.rustdoc:not(.src) .scraped-example:not(.expanded) .src-line-numbers > pre,
+.rustdoc:not(.src) .scraped-example:not(.expanded) pre.rust {
+ padding-bottom: 0;
+ /* See above comment, should be the same max-height. */
overflow: auto hidden;
}
+.rustdoc:not(.src) .scraped-example .src-line-numbers {
+ padding-top: 0;
+}
+.rustdoc:not(.src) .scraped-example.expanded .src-line-numbers {
+ padding-bottom: 0;
+}
+
+.rustdoc:not(.src) .example-wrap pre {
+ overflow: auto;
+}
.rustdoc .example-wrap pre.example-line-numbers,
-.rustdoc .example-wrap pre.src-line-numbers {
- flex-grow: 0;
+.rustdoc .example-wrap .src-line-numbers {
min-width: fit-content; /* prevent collapsing into nothing in truncated scraped examples */
- overflow: initial;
+ flex-grow: 0;
text-align: right;
-webkit-user-select: none;
user-select: none;
@@ -788,7 +831,7 @@
color: var(--src-line-numbers-span-color);
}
-.rustdoc .example-wrap pre.src-line-numbers {
+.rustdoc .scraped-example .src-line-numbers {
padding: 14px 0;
}
.src-line-numbers a, .src-line-numbers span {
@@ -1500,17 +1543,23 @@
.example-wrap .button-holder.keep-visible {
visibility: visible;
}
-.example-wrap .button-holder .copy-button, .example-wrap .test-arrow {
+.example-wrap .button-holder > * {
background: var(--main-background-color);
cursor: pointer;
border-radius: var(--button-border-radius);
height: var(--copy-path-height);
width: var(--copy-path-width);
+ border: 0;
+ color: var(--code-example-button-color);
+}
+.example-wrap .button-holder > *:hover {
+ color: var(--code-example-button-hover-color);
+}
+.example-wrap .button-holder > *:not(:first-child) {
+ margin-left: var(--button-left-margin);
}
.example-wrap .button-holder .copy-button {
- margin-left: var(--button-left-margin);
padding: 2px 0 0 4px;
- border: 0;
}
.example-wrap .button-holder .copy-button::before,
.example-wrap .test-arrow::before {
@@ -2254,6 +2303,7 @@
}
}
+
/* Should have min-width: (N + 1)px where N is the mobile breakpoint above. */
@media (min-width: 701px) {
/* Places file-link for a scraped example on top of the example to save space.
@@ -2356,99 +2406,41 @@
color: var(--scrape-example-help-hover-color);
}
-.scraped-example {
- /* So .scraped-example-title can be positioned absolutely */
- position: relative;
-}
-
-.scraped-example .code-wrapper {
- position: relative;
- display: flex;
- flex-direction: row;
- flex-wrap: wrap;
- width: 100%;
-}
-
-.scraped-example:not(.expanded) .code-wrapper {
- /* scrape-examples.js has a constant DEFAULT_MAX_LINES (call it N) for the number
- * of lines shown in the un-expanded example code viewer. This pre needs to have
- * a max-height equal to line-height * N. The line-height is currently 1.5em,
- * and we include additional 10px for padding. */
- max-height: calc(1.5em * 5 + 10px);
-}
-
-.scraped-example:not(.expanded) .code-wrapper pre {
- overflow-y: hidden;
- padding-bottom: 0;
- /* See above comment, should be the same max-height. */
- max-height: calc(1.5em * 5 + 10px);
-}
-
-.more-scraped-examples .scraped-example:not(.expanded) .code-wrapper,
-.more-scraped-examples .scraped-example:not(.expanded) .code-wrapper pre {
- /* See above comment, except this height is based on HIDDEN_MAX_LINES. */
- max-height: calc(1.5em * 10 + 10px);
-}
-
-.scraped-example .code-wrapper .next,
-.scraped-example .code-wrapper .prev,
-.scraped-example .code-wrapper .expand {
- color: var(--main-color);
- position: absolute;
- top: 0.25em;
- z-index: 1;
- padding: 0;
- background: none;
- border: none;
- /* iOS button gradient: https://stackoverflow.com/q/5438567 */
- -webkit-appearance: none;
- opacity: 1;
-}
-.scraped-example .code-wrapper .prev {
- right: 2.25em;
-}
-.scraped-example .code-wrapper .next {
- right: 1.25em;
-}
-.scraped-example .code-wrapper .expand {
- right: 0.25em;
-}
-
-.scraped-example:not(.expanded) .code-wrapper::before,
-.scraped-example:not(.expanded) .code-wrapper::after {
+.scraped-example:not(.expanded) .example-wrap::before,
+.scraped-example:not(.expanded) .example-wrap::after {
content: " ";
width: 100%;
height: 5px;
position: absolute;
z-index: 1;
}
-.scraped-example:not(.expanded) .code-wrapper::before {
+.scraped-example:not(.expanded) .example-wrap::before {
top: 0;
background: linear-gradient(to bottom,
var(--scrape-example-code-wrapper-background-start),
var(--scrape-example-code-wrapper-background-end));
}
-.scraped-example:not(.expanded) .code-wrapper::after {
+.scraped-example:not(.expanded) .example-wrap::after {
bottom: 0;
background: linear-gradient(to top,
var(--scrape-example-code-wrapper-background-start),
var(--scrape-example-code-wrapper-background-end));
}
-.scraped-example .code-wrapper .example-wrap {
+.scraped-example:not(.expanded) {
width: 100%;
overflow-y: hidden;
margin-bottom: 0;
}
-.scraped-example:not(.expanded) .code-wrapper .example-wrap {
+.scraped-example:not(.expanded) {
overflow-x: hidden;
}
-.scraped-example .example-wrap .rust span.highlight {
+.scraped-example .rust span.highlight {
background: var(--scrape-example-code-line-highlight);
}
-.scraped-example .example-wrap .rust span.highlight.focus {
+.scraped-example .rust span.highlight.focus {
background: var(--scrape-example-code-line-highlight-focus);
}
@@ -2542,6 +2534,8 @@
--copy-path-button-color: #999;
--copy-path-img-filter: invert(50%);
--copy-path-img-hover-filter: invert(35%);
+ --code-example-button-color: #7f7f7f;
+ --code-example-button-hover-color: #595959;
--codeblock-error-hover-color: rgb(255, 0, 0);
--codeblock-error-color: rgba(255, 0, 0, .5);
--codeblock-ignore-hover-color: rgb(255, 142, 0);
@@ -2644,6 +2638,8 @@
--copy-path-button-color: #999;
--copy-path-img-filter: invert(50%);
--copy-path-img-hover-filter: invert(65%);
+ --code-example-button-color: #7f7f7f;
+ --code-example-button-hover-color: #a5a5a5;
--codeblock-error-hover-color: rgb(255, 0, 0);
--codeblock-error-color: rgba(255, 0, 0, .5);
--codeblock-ignore-hover-color: rgb(255, 142, 0);
@@ -2753,6 +2749,8 @@
--copy-path-button-color: #fff;
--copy-path-img-filter: invert(70%);
--copy-path-img-hover-filter: invert(100%);
+ --code-example-button-color: #b2b2b2;
+ --code-example-button-hover-color: #fff;
--codeblock-error-hover-color: rgb(255, 0, 0);
--codeblock-error-color: rgba(255, 0, 0, .5);
--codeblock-ignore-hover-color: rgb(255, 142, 0);
diff --git a/src/librustdoc/html/static/js/externs.js b/src/librustdoc/html/static/js/externs.js
index 6fd60d6..3d3e0a8 100644
--- a/src/librustdoc/html/static/js/externs.js
+++ b/src/librustdoc/html/static/js/externs.js
@@ -41,6 +41,7 @@
* foundElems: number,
* totalElems: number,
* literalSearch: boolean,
+ * hasReturnArrow: boolean,
* corrections: Array<{from: string, to: integer}> | null,
* typeFingerprint: Uint32Array,
* error: Array<string> | null,
diff --git a/src/librustdoc/html/static/js/main.js b/src/librustdoc/html/static/js/main.js
index 0291b6e..858753a 100644
--- a/src/librustdoc/html/static/js/main.js
+++ b/src/librustdoc/html/static/js/main.js
@@ -1855,8 +1855,13 @@
// Since the button will be added, no need to keep this listener around.
elem.removeEventListener("mouseover", addCopyButton);
- const parent = document.createElement("div");
- parent.className = "button-holder";
+ // If this is a scrapped example, there will already be a "button-holder" element.
+ let parent = elem.querySelector(".button-holder");
+ if (!parent) {
+ parent = document.createElement("div");
+ parent.className = "button-holder";
+ }
+
const runButton = elem.querySelector(".test-arrow");
if (runButton !== null) {
// If there is a run button, we move it into the same div.
diff --git a/src/librustdoc/html/static/js/scrape-examples.js b/src/librustdoc/html/static/js/scrape-examples.js
index 7a3a9c5..06e4281 100644
--- a/src/librustdoc/html/static/js/scrape-examples.js
+++ b/src/librustdoc/html/static/js/scrape-examples.js
@@ -13,7 +13,7 @@
// Scroll code block to the given code location
function scrollToLoc(elt, loc, isHidden) {
- const lines = elt.querySelector(".src-line-numbers");
+ const lines = elt.querySelector(".src-line-numbers > pre");
let scrollOffset;
// If the block is greater than the size of the viewer,
@@ -24,8 +24,7 @@
const line = Math.max(0, loc[0] - 1);
scrollOffset = lines.children[line].offsetTop;
} else {
- const wrapper = elt.querySelector(".code-wrapper");
- const halfHeight = wrapper.offsetHeight / 2;
+ const halfHeight = elt.offsetHeight / 2;
const offsetTop = lines.children[loc[0]].offsetTop;
const lastLine = lines.children[loc[1]];
const offsetBot = lastLine.offsetTop + lastLine.offsetHeight;
@@ -33,7 +32,7 @@
scrollOffset = offsetMid - halfHeight;
}
- lines.scrollTo(0, scrollOffset);
+ lines.parentElement.scrollTo(0, scrollOffset);
elt.querySelector(".rust").scrollTo(0, scrollOffset);
}
diff --git a/src/librustdoc/html/static/js/search.js b/src/librustdoc/html/static/js/search.js
index 6f575e6..4da0bbc 100644
--- a/src/librustdoc/html/static/js/search.js
+++ b/src/librustdoc/html/static/js/search.js
@@ -657,7 +657,7 @@
}
const typeFilter = parserState.typeFilter;
parserState.typeFilter = null;
- if (name === "!") {
+ if (name.trim() === "!") {
if (typeFilter !== null && typeFilter !== "primitive") {
throw [
"Invalid search type: primitive never type ",
@@ -1795,6 +1795,7 @@
// Total number of elements (includes generics).
totalElems: 0,
literalSearch: false,
+ hasReturnArrow: false,
error: null,
correction: null,
proposeCorrectionFrom: null,
@@ -1823,6 +1824,7 @@
continue;
} else if (c === "-" || c === ">") {
if (isReturnArrow(parserState)) {
+ query.hasReturnArrow = true;
break;
}
throw ["Unexpected ", c, " (did you mean ", "->", "?)"];
@@ -1889,9 +1891,7 @@
// Get returned elements.
getItemsBefore(query, parserState, query.returned, "");
// Nothing can come afterward!
- if (query.returned.length === 0) {
- throw ["Expected at least one item after ", "->"];
- }
+ query.hasReturnArrow = true;
break;
} else {
parserState.pos += 1;
@@ -3249,7 +3249,7 @@
this.buildFunctionTypeFingerprint(elem, parsedQuery.typeFingerprint, fps);
}
- if (parsedQuery.foundElems === 1 && parsedQuery.returned.length === 0) {
+ if (parsedQuery.foundElems === 1 && !parsedQuery.hasReturnArrow) {
if (parsedQuery.elems.length === 1) {
const elem = parsedQuery.elems[0];
const length = this.searchIndex.length;
diff --git a/src/librustdoc/html/templates/scraped_source.html b/src/librustdoc/html/templates/scraped_source.html
new file mode 100644
index 0000000..e1fc2e6
--- /dev/null
+++ b/src/librustdoc/html/templates/scraped_source.html
@@ -0,0 +1,33 @@
+<div class="scraped-example{% if !info.needs_expansion +%} expanded{% endif %}" data-locs="{{info.locations}}"> {# #}
+ <div class="scraped-example-title">
+ {{info.name +}} (<a href="{{info.url}}">{{info.title}}</a>) {# #}
+ </div>
+ <div class="example-wrap"> {# #}
+ {# https://developers.google.com/search/docs/crawling-indexing/robots-meta-tag#data-nosnippet-attr
+ Do not show "1 2 3 4 5 ..." in web search results. #}
+ <div class="src-line-numbers" data-nosnippet> {# #}
+ <pre>
+ {% for line in lines.clone() %}
+ {# ~#}
+ <span>{{line|safe}}</span>
+ {% endfor %}
+ </pre> {# #}
+ </div> {# #}
+ <pre class="rust"> {# #}
+ <code>
+ {{code_html|safe}}
+ </code> {# #}
+ </pre> {# #}
+ {% if info.needs_prev_next_buttons || info.needs_expansion %}
+ <div class="button-holder">
+ {% if info.needs_prev_next_buttons %}
+ <button class="prev">≺</button> {# #}
+ <button class="next">≻</button>
+ {% endif %}
+ {% if info.needs_expansion %}
+ <button class="expand">↕</button>
+ {% endif %}
+ </div>
+ {% endif %}
+ </div> {# #}
+</div> {# #}
diff --git a/src/librustdoc/html/templates/source.html b/src/librustdoc/html/templates/source.html
index 42d0127..60a47f1 100644
--- a/src/librustdoc/html/templates/source.html
+++ b/src/librustdoc/html/templates/source.html
@@ -1,21 +1,15 @@
-<div class="example-wrap"> {# #}
+<div class="example-wrap">
{# https://developers.google.com/search/docs/crawling-indexing/robots-meta-tag#data-nosnippet-attr
Do not show "1 2 3 4 5 ..." in web search results. #}
<div data-nosnippet><pre class="src-line-numbers">
{% for line in lines.clone() %}
- {% if embedded %}
- <span>{{line|safe}}</span>
- {%~ else %}
- <a href="#{{line|safe}}" id="{{line|safe}}">{{line|safe}}</a>
- {%~ endif %}
+ {# ~#}
+ <a href="#{{line|safe}}" id="{{line|safe}}">{{line|safe}}</a>
{% endfor %}
</pre></div> {# #}
<pre class="rust"> {# #}
<code>
- {% if needs_expansion %}
- <button class="expand">↕</button>
- {% endif %}
{{code_html|safe}}
</code> {# #}
</pre> {# #}
-</div>
+</div> {# #}
diff --git a/src/librustdoc/json/conversions.rs b/src/librustdoc/json/conversions.rs
index b97d710..82ce619 100644
--- a/src/librustdoc/json/conversions.rs
+++ b/src/librustdoc/json/conversions.rs
@@ -49,7 +49,7 @@ pub(super) fn convert_item(&self, item: clean::Item) -> Option<Item> {
let visibility = item.visibility(self.tcx);
let clean::Item { name, item_id, .. } = item;
let id = id_from_item(&item, self.tcx);
- let inner = match *item.kind {
+ let inner = match item.kind {
clean::KeywordItem => return None,
clean::StrippedItem(ref inner) => {
match &**inner {
@@ -156,7 +156,7 @@ fn from_tcx(args: clean::GenericArgs, tcx: TyCtxt<'_>) -> Self {
match args {
AngleBracketed { args, constraints } => GenericArgs::AngleBracketed {
args: args.into_vec().into_tcx(tcx),
- bindings: constraints.into_tcx(tcx),
+ constraints: constraints.into_tcx(tcx),
},
Parenthesized { inputs, output } => GenericArgs::Parenthesized {
inputs: inputs.into_vec().into_tcx(tcx),
@@ -198,9 +198,9 @@ fn from_tcx(constant: clean::ConstantKind, tcx: TyCtxt<'_>) -> Self {
}
}
-impl FromWithTcx<clean::AssocItemConstraint> for TypeBinding {
+impl FromWithTcx<clean::AssocItemConstraint> for AssocItemConstraint {
fn from_tcx(constraint: clean::AssocItemConstraint, tcx: TyCtxt<'_>) -> Self {
- TypeBinding {
+ AssocItemConstraint {
name: constraint.assoc.name.to_string(),
args: constraint.assoc.args.into_tcx(tcx),
binding: constraint.kind.into_tcx(tcx),
@@ -208,12 +208,12 @@ fn from_tcx(constraint: clean::AssocItemConstraint, tcx: TyCtxt<'_>) -> Self {
}
}
-impl FromWithTcx<clean::AssocItemConstraintKind> for TypeBindingKind {
+impl FromWithTcx<clean::AssocItemConstraintKind> for AssocItemConstraintKind {
fn from_tcx(kind: clean::AssocItemConstraintKind, tcx: TyCtxt<'_>) -> Self {
use clean::AssocItemConstraintKind::*;
match kind {
- Equality { term } => TypeBindingKind::Equality(term.into_tcx(tcx)),
- Bound { bounds } => TypeBindingKind::Constraint(bounds.into_tcx(tcx)),
+ Equality { term } => AssocItemConstraintKind::Equality(term.into_tcx(tcx)),
+ Bound { bounds } => AssocItemConstraintKind::Constraint(bounds.into_tcx(tcx)),
}
}
}
@@ -294,7 +294,7 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
}
pub(crate) fn id_from_item(item: &clean::Item, tcx: TyCtxt<'_>) -> Id {
- match *item.kind {
+ match item.kind {
clean::ItemKind::ImportItem(ref import) => {
let extra =
import.source.did.map(ItemId::from).map(|i| id_from_item_inner(i, tcx, None, None));
@@ -310,11 +310,11 @@ fn from_clean_item(item: clean::Item, tcx: TyCtxt<'_>) -> ItemEnum {
let is_crate = item.is_crate();
let header = item.fn_header(tcx);
- match *item.kind {
+ match item.inner.kind {
ModuleItem(m) => {
ItemEnum::Module(Module { is_crate, items: ids(m.items, tcx), is_stripped: false })
}
- ImportItem(i) => ItemEnum::Import(i.into_tcx(tcx)),
+ ImportItem(i) => ItemEnum::Use(i.into_tcx(tcx)),
StructItem(s) => ItemEnum::Struct(s.into_tcx(tcx)),
UnionItem(u) => ItemEnum::Union(u.into_tcx(tcx)),
StructFieldItem(f) => ItemEnum::StructField(f.into_tcx(tcx)),
@@ -331,7 +331,7 @@ fn from_clean_item(item: clean::Item, tcx: TyCtxt<'_>) -> ItemEnum {
ImplItem(i) => ItemEnum::Impl((*i).into_tcx(tcx)),
StaticItem(s) => ItemEnum::Static(s.into_tcx(tcx)),
ForeignStaticItem(s, _) => ItemEnum::Static(s.into_tcx(tcx)),
- ForeignTypeItem => ItemEnum::ForeignType,
+ ForeignTypeItem => ItemEnum::ExternType,
TypeAliasItem(t) => ItemEnum::TypeAlias(t.into_tcx(tcx)),
// FIXME(generic_const_items): Add support for generic free consts
ConstantItem(ci) => {
@@ -347,21 +347,19 @@ fn from_clean_item(item: clean::Item, tcx: TyCtxt<'_>) -> ItemEnum {
}
// FIXME(generic_const_items): Add support for generic associated consts.
TyAssocConstItem(_generics, ty) => {
- ItemEnum::AssocConst { type_: (*ty).into_tcx(tcx), default: None }
+ ItemEnum::AssocConst { type_: (*ty).into_tcx(tcx), value: None }
}
// FIXME(generic_const_items): Add support for generic associated consts.
AssocConstItem(ci) => {
- ItemEnum::AssocConst { type_: ci.type_.into_tcx(tcx), default: Some(ci.kind.expr(tcx)) }
+ ItemEnum::AssocConst { type_: ci.type_.into_tcx(tcx), value: Some(ci.kind.expr(tcx)) }
}
- TyAssocTypeItem(g, b) => ItemEnum::AssocType {
- generics: g.into_tcx(tcx),
- bounds: b.into_tcx(tcx),
- default: None,
- },
+ TyAssocTypeItem(g, b) => {
+ ItemEnum::AssocType { generics: g.into_tcx(tcx), bounds: b.into_tcx(tcx), type_: None }
+ }
AssocTypeItem(t, b) => ItemEnum::AssocType {
generics: t.generics.into_tcx(tcx),
bounds: b.into_tcx(tcx),
- default: Some(t.item_type.unwrap_or(t.type_).into_tcx(tcx)),
+ type_: Some(t.item_type.unwrap_or(t.type_).into_tcx(tcx)),
},
// `convert_item` early returns `None` for stripped items and keywords.
KeywordItem => unreachable!(),
@@ -385,7 +383,7 @@ fn from_clean_item(item: clean::Item, tcx: TyCtxt<'_>) -> ItemEnum {
impl FromWithTcx<clean::Struct> for Struct {
fn from_tcx(struct_: clean::Struct, tcx: TyCtxt<'_>) -> Self {
- let fields_stripped = struct_.has_stripped_entries();
+ let has_stripped_fields = struct_.has_stripped_entries();
let clean::Struct { ctor_kind, generics, fields } = struct_;
let kind = match ctor_kind {
@@ -394,7 +392,7 @@ fn from_tcx(struct_: clean::Struct, tcx: TyCtxt<'_>) -> Self {
assert!(fields.is_empty());
StructKind::Unit
}
- None => StructKind::Plain { fields: ids(fields, tcx), fields_stripped },
+ None => StructKind::Plain { fields: ids(fields, tcx), has_stripped_fields },
};
Struct {
@@ -407,22 +405,22 @@ fn from_tcx(struct_: clean::Struct, tcx: TyCtxt<'_>) -> Self {
impl FromWithTcx<clean::Union> for Union {
fn from_tcx(union_: clean::Union, tcx: TyCtxt<'_>) -> Self {
- let fields_stripped = union_.has_stripped_entries();
+ let has_stripped_fields = union_.has_stripped_entries();
let clean::Union { generics, fields } = union_;
Union {
generics: generics.into_tcx(tcx),
- fields_stripped,
+ has_stripped_fields,
fields: ids(fields, tcx),
impls: Vec::new(), // Added in JsonRenderer::item
}
}
}
-pub(crate) fn from_fn_header(header: &rustc_hir::FnHeader) -> Header {
- Header {
- async_: header.is_async(),
- const_: header.is_const(),
- unsafe_: header.is_unsafe(),
+pub(crate) fn from_fn_header(header: &rustc_hir::FnHeader) -> FunctionHeader {
+ FunctionHeader {
+ is_async: header.is_async(),
+ is_const: header.is_const(),
+ is_unsafe: header.is_unsafe(),
abi: convert_abi(header.abi),
}
}
@@ -474,7 +472,7 @@ fn from_tcx(kind: clean::GenericParamDefKind, tcx: TyCtxt<'_>) -> Self {
Type { bounds, default, synthetic } => GenericParamDefKind::Type {
bounds: bounds.into_tcx(tcx),
default: default.map(|x| (*x).into_tcx(tcx)),
- synthetic,
+ is_synthetic: synthetic,
},
Const { ty, default, synthetic: _ } => GenericParamDefKind::Const {
type_: (*ty).into_tcx(tcx),
@@ -508,7 +506,7 @@ fn from_tcx(predicate: clean::WherePredicate, tcx: TyCtxt<'_>) -> Self {
.map(|bound| bound.into_tcx(tcx))
.collect(),
default: default.map(|ty| (*ty).into_tcx(tcx)),
- synthetic,
+ is_synthetic: synthetic,
}
}
clean::GenericParamDefKind::Const { ty, default, synthetic: _ } => {
@@ -602,12 +600,12 @@ fn from_tcx(ty: clean::Type, tcx: TyCtxt<'_>) -> Self {
ImplTrait(g) => Type::ImplTrait(g.into_tcx(tcx)),
Infer => Type::Infer,
RawPointer(mutability, type_) => Type::RawPointer {
- mutable: mutability == ast::Mutability::Mut,
+ is_mutable: mutability == ast::Mutability::Mut,
type_: Box::new((*type_).into_tcx(tcx)),
},
BorrowedRef { lifetime, mutability, type_ } => Type::BorrowedRef {
lifetime: lifetime.map(convert_lifetime),
- mutable: mutability == ast::Mutability::Mut,
+ is_mutable: mutability == ast::Mutability::Mut,
type_: Box::new((*type_).into_tcx(tcx)),
},
QPath(box clean::QPathData { assoc, self_type, trait_, .. }) => Type::QualifiedPath {
@@ -643,29 +641,29 @@ impl FromWithTcx<clean::BareFunctionDecl> for FunctionPointer {
fn from_tcx(bare_decl: clean::BareFunctionDecl, tcx: TyCtxt<'_>) -> Self {
let clean::BareFunctionDecl { safety, generic_params, decl, abi } = bare_decl;
FunctionPointer {
- header: Header {
- unsafe_: matches!(safety, rustc_hir::Safety::Unsafe),
- const_: false,
- async_: false,
+ header: FunctionHeader {
+ is_unsafe: matches!(safety, rustc_hir::Safety::Unsafe),
+ is_const: false,
+ is_async: false,
abi: convert_abi(abi),
},
generic_params: generic_params.into_tcx(tcx),
- decl: decl.into_tcx(tcx),
+ sig: decl.into_tcx(tcx),
}
}
}
-impl FromWithTcx<clean::FnDecl> for FnDecl {
+impl FromWithTcx<clean::FnDecl> for FunctionSignature {
fn from_tcx(decl: clean::FnDecl, tcx: TyCtxt<'_>) -> Self {
let clean::FnDecl { inputs, output, c_variadic } = decl;
- FnDecl {
+ FunctionSignature {
inputs: inputs
.values
.into_iter()
.map(|arg| (arg.name.to_string(), arg.type_.into_tcx(tcx)))
.collect(),
output: if output.is_unit() { None } else { Some(output.into_tcx(tcx)) },
- c_variadic,
+ is_c_variadic: c_variadic,
}
}
}
@@ -702,12 +700,12 @@ fn from_tcx(impl_: clean::Impl, tcx: TyCtxt<'_>) -> Self {
let provided_trait_methods = impl_.provided_trait_methods(tcx);
let clean::Impl { safety, generics, trait_, for_, items, polarity, kind } = impl_;
// FIXME: use something like ImplKind in JSON?
- let (synthetic, blanket_impl) = match kind {
+ let (is_synthetic, blanket_impl) = match kind {
clean::ImplKind::Normal | clean::ImplKind::FakeVariadic => (false, None),
clean::ImplKind::Auto => (true, None),
clean::ImplKind::Blanket(ty) => (false, Some(*ty)),
};
- let negative_polarity = match polarity {
+ let is_negative = match polarity {
ty::ImplPolarity::Positive | ty::ImplPolarity::Reservation => false,
ty::ImplPolarity::Negative => true,
};
@@ -721,8 +719,8 @@ fn from_tcx(impl_: clean::Impl, tcx: TyCtxt<'_>) -> Self {
trait_: trait_.map(|path| path.into_tcx(tcx)),
for_: for_.into_tcx(tcx),
items: ids(items, tcx),
- negative: negative_polarity,
- synthetic,
+ is_negative,
+ is_synthetic,
blanket_impl: blanket_impl.map(|x| x.into_tcx(tcx)),
}
}
@@ -736,7 +734,7 @@ pub(crate) fn from_function(
) -> Function {
let clean::Function { decl, generics } = *function;
Function {
- decl: decl.into_tcx(tcx),
+ sig: decl.into_tcx(tcx),
generics: generics.into_tcx(tcx),
header: from_fn_header(&header),
has_body,
@@ -745,11 +743,11 @@ pub(crate) fn from_function(
impl FromWithTcx<clean::Enum> for Enum {
fn from_tcx(enum_: clean::Enum, tcx: TyCtxt<'_>) -> Self {
- let variants_stripped = enum_.has_stripped_entries();
+ let has_stripped_variants = enum_.has_stripped_entries();
let clean::Enum { variants, generics } = enum_;
Enum {
generics: generics.into_tcx(tcx),
- variants_stripped,
+ has_stripped_variants,
variants: ids(variants, tcx),
impls: Vec::new(), // Added in JsonRenderer::item
}
@@ -766,7 +764,7 @@ fn from_tcx(variant: clean::Variant, tcx: TyCtxt<'_>) -> Self {
CLike => VariantKind::Plain,
Tuple(fields) => VariantKind::Tuple(ids_keeping_stripped(fields, tcx)),
Struct(s) => VariantKind::Struct {
- fields_stripped: s.has_stripped_entries(),
+ has_stripped_fields: s.has_stripped_entries(),
fields: ids(s.fields, tcx),
},
};
@@ -787,21 +785,21 @@ fn from_tcx(disr: clean::Discriminant, tcx: TyCtxt<'_>) -> Self {
}
}
-impl FromWithTcx<clean::Import> for Import {
+impl FromWithTcx<clean::Import> for Use {
fn from_tcx(import: clean::Import, tcx: TyCtxt<'_>) -> Self {
use clean::ImportKind::*;
- let (name, glob) = match import.kind {
+ let (name, is_glob) = match import.kind {
Simple(s) => (s.to_string(), false),
Glob => (
import.source.path.last_opt().unwrap_or_else(|| Symbol::intern("*")).to_string(),
true,
),
};
- Import {
+ Use {
source: import.source.path.whole_name(),
name,
id: import.source.did.map(ItemId::from).map(|i| id_from_item_default(i, tcx)),
- glob,
+ is_glob,
}
}
}
@@ -835,7 +833,7 @@ impl FromWithTcx<clean::Static> for Static {
fn from_tcx(stat: clean::Static, tcx: TyCtxt<'_>) -> Self {
Static {
type_: (*stat.type_).into_tcx(tcx),
- mutable: stat.mutability == ast::Mutability::Mut,
+ is_mutable: stat.mutability == ast::Mutability::Mut,
expr: stat
.expr
.map(|e| rendered_const(tcx, tcx.hir().body(e), tcx.hir().body_owner_def_id(e)))
@@ -856,7 +854,7 @@ fn from_tcx(kind: ItemType, _tcx: TyCtxt<'_>) -> Self {
match kind {
Module => ItemKind::Module,
ExternCrate => ItemKind::ExternCrate,
- Import => ItemKind::Import,
+ Import => ItemKind::Use,
Struct => ItemKind::Struct,
Union => ItemKind::Union,
Enum => ItemKind::Enum,
@@ -872,7 +870,7 @@ fn from_tcx(kind: ItemType, _tcx: TyCtxt<'_>) -> Self {
Primitive => ItemKind::Primitive,
AssocConst => ItemKind::AssocConst,
AssocType => ItemKind::AssocType,
- ForeignType => ItemKind::ForeignType,
+ ForeignType => ItemKind::ExternType,
Keyword => ItemKind::Keyword,
TraitAlias => ItemKind::TraitAlias,
ProcAttribute => ItemKind::ProcAttribute,
diff --git a/src/librustdoc/json/import_finder.rs b/src/librustdoc/json/import_finder.rs
index 976a7fd..e21fe96 100644
--- a/src/librustdoc/json/import_finder.rs
+++ b/src/librustdoc/json/import_finder.rs
@@ -24,7 +24,7 @@ struct ImportFinder {
impl DocFolder for ImportFinder {
fn fold_item(&mut self, i: Item) -> Option<Item> {
- match *i.kind {
+ match i.kind {
clean::ImportItem(Import { source: ImportSource { did: Some(did), .. }, .. }) => {
self.imported.insert(did);
Some(i)
diff --git a/src/librustdoc/json/mod.rs b/src/librustdoc/json/mod.rs
index 1b2d61a..f30a34c 100644
--- a/src/librustdoc/json/mod.rs
+++ b/src/librustdoc/json/mod.rs
@@ -85,7 +85,7 @@ fn get_impls(&mut self, id: DefId) -> Vec<types::Id> {
// document primitive items in an arbitrary crate by using
// `rustc_doc_primitive`.
let mut is_primitive_impl = false;
- if let clean::types::ItemKind::ImplItem(ref impl_) = *item.kind
+ if let clean::types::ItemKind::ImplItem(ref impl_) = item.kind
&& impl_.trait_.is_none()
&& let clean::types::Type::Primitive(_) = impl_.for_
{
@@ -164,7 +164,7 @@ fn item(&mut self, item: clean::Item) -> Result<(), Error> {
// Flatten items that recursively store other items. We include orphaned items from
// stripped modules and etc that are otherwise reachable.
- if let ItemKind::StrippedItem(inner) = &*item.kind {
+ if let ItemKind::StrippedItem(inner) = &item.kind {
inner.inner_items().for_each(|i| self.item(i.clone()).unwrap());
}
@@ -197,7 +197,7 @@ fn item(&mut self, item: clean::Item) -> Result<(), Error> {
types::ItemEnum::Function(_)
| types::ItemEnum::Module(_)
- | types::ItemEnum::Import(_)
+ | types::ItemEnum::Use(_)
| types::ItemEnum::AssocConst { .. }
| types::ItemEnum::AssocType { .. } => true,
types::ItemEnum::ExternCrate { .. }
@@ -208,7 +208,7 @@ fn item(&mut self, item: clean::Item) -> Result<(), Error> {
| types::ItemEnum::TypeAlias(_)
| types::ItemEnum::Constant { .. }
| types::ItemEnum::Static(_)
- | types::ItemEnum::ForeignType
+ | types::ItemEnum::ExternType
| types::ItemEnum::Macro(_)
| types::ItemEnum::ProcMacro(_) => false,
};
diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs
index f25acbe..6649e17 100644
--- a/src/librustdoc/lib.rs
+++ b/src/librustdoc/lib.rs
@@ -603,6 +603,33 @@ fn opts() -> Vec<RustcOptGroup> {
"path to function call information (for displaying examples in the documentation)",
)
}),
+ unstable("merge", |o| {
+ o.optopt(
+ "",
+ "merge",
+ "Controls how rustdoc handles files from previously documented crates in the doc root
+ none = Do not write cross-crate information to the --out-dir
+ shared = Append current crate's info to files found in the --out-dir
+ finalize = Write current crate's info and --include-parts-dir info to the --out-dir, overwriting conflicting files",
+ "none|shared|finalize",
+ )
+ }),
+ unstable("parts-out-dir", |o| {
+ o.optopt(
+ "",
+ "parts-out-dir",
+ "Writes trait implementations and other info for the current crate to provided path. Only use with --merge=none",
+ "path/to/doc.parts/<crate-name>",
+ )
+ }),
+ unstable("include-parts-dir", |o| {
+ o.optmulti(
+ "",
+ "include-parts-dir",
+ "Includes trait implementations and other crate info from provided path. Only use with --merge=finalize",
+ "path/to/doc.parts/<crate-name>",
+ )
+ }),
// deprecated / removed options
unstable("disable-minification", |o| o.optflagmulti("", "disable-minification", "removed")),
stable("plugin-path", |o| {
@@ -697,6 +724,32 @@ fn run_renderer<'tcx, T: formats::FormatRenderer<'tcx>>(
}
}
+/// Renders and writes cross-crate info files, like the search index. This function exists so that
+/// we can run rustdoc without a crate root in the `--merge=finalize` mode. Cross-crate info files
+/// discovered via `--include-parts-dir` are combined and written to the doc root.
+fn run_merge_finalize(opt: config::RenderOptions) -> Result<(), error::Error> {
+ assert!(
+ opt.should_merge.write_rendered_cci,
+ "config.rs only allows us to return InputMode::NoInputMergeFinalize if --merge=finalize"
+ );
+ assert!(
+ !opt.should_merge.read_rendered_cci,
+ "config.rs only allows us to return InputMode::NoInputMergeFinalize if --merge=finalize"
+ );
+ let crates = html::render::CrateInfo::read_many(&opt.include_parts_dir)?;
+ let include_sources = !opt.html_no_source;
+ html::render::write_not_crate_specific(
+ &crates,
+ &opt.output,
+ &opt,
+ &opt.themes,
+ opt.extension_css.as_deref(),
+ &opt.resource_suffix,
+ include_sources,
+ )?;
+ Ok(())
+}
+
fn main_args(
early_dcx: &mut EarlyDiagCtxt,
at_args: &[String],
@@ -727,22 +780,35 @@ fn main_args(
// Note that we discard any distinction between different non-zero exit
// codes from `from_matches` here.
- let (options, render_options) = match config::Options::from_matches(early_dcx, &matches, args) {
- Some(opts) => opts,
- None => return Ok(()),
- };
+ let (input, options, render_options) =
+ match config::Options::from_matches(early_dcx, &matches, args) {
+ Some(opts) => opts,
+ None => return Ok(()),
+ };
let dcx =
core::new_dcx(options.error_format, None, options.diagnostic_width, &options.unstable_opts);
let dcx = dcx.handle();
- match (options.should_test, options.markdown_input()) {
- (true, Some(_)) => return wrap_return(dcx, doctest::test_markdown(options)),
- (true, None) => return doctest::run(dcx, options),
- (false, Some(input)) => {
- let input = input.to_owned();
+ let input = match input {
+ config::InputMode::HasFile(input) => input,
+ config::InputMode::NoInputMergeFinalize => {
+ return wrap_return(
+ dcx,
+ run_merge_finalize(render_options)
+ .map_err(|e| format!("could not write merged cross-crate info: {e}")),
+ );
+ }
+ };
+
+ match (options.should_test, config::markdown_input(&input)) {
+ (true, Some(_)) => return wrap_return(dcx, doctest::test_markdown(&input, options)),
+ (true, None) => return doctest::run(dcx, input, options),
+ (false, Some(md_input)) => {
+ let md_input = md_input.to_owned();
let edition = options.edition;
- let config = core::create_config(options, &render_options, using_internal_features);
+ let config =
+ core::create_config(input, options, &render_options, using_internal_features);
// `markdown::render` can invoke `doctest::make_test`, which
// requires session globals and a thread pool, so we use
@@ -750,7 +816,7 @@ fn main_args(
return wrap_return(
dcx,
interface::run_compiler(config, |_compiler| {
- markdown::render(&input, render_options, edition)
+ markdown::render(&md_input, render_options, edition)
}),
);
}
@@ -775,7 +841,7 @@ fn main_args(
let scrape_examples_options = options.scrape_examples_options.clone();
let bin_crate = options.bin_crate;
- let config = core::create_config(options, &render_options, using_internal_features);
+ let config = core::create_config(input, options, &render_options, using_internal_features);
interface::run_compiler(config, |compiler| {
let sess = &compiler.sess;
diff --git a/src/librustdoc/passes/calculate_doc_coverage.rs b/src/librustdoc/passes/calculate_doc_coverage.rs
index 1d0b41f..7391909 100644
--- a/src/librustdoc/passes/calculate_doc_coverage.rs
+++ b/src/librustdoc/passes/calculate_doc_coverage.rs
@@ -195,7 +195,7 @@ fn visit_item(&mut self, i: &clean::Item) {
return;
}
- match *i.kind {
+ match i.kind {
clean::StrippedItem(..) => {
// don't count items in stripped modules
return;
diff --git a/src/librustdoc/passes/check_doc_test_visibility.rs b/src/librustdoc/passes/check_doc_test_visibility.rs
index d456e8e..733fd91 100644
--- a/src/librustdoc/passes/check_doc_test_visibility.rs
+++ b/src/librustdoc/passes/check_doc_test_visibility.rs
@@ -57,7 +57,7 @@ fn visit_test(&mut self, _: String, config: LangString, _: MdRelLine) {
pub(crate) fn should_have_doc_example(cx: &DocContext<'_>, item: &clean::Item) -> bool {
if !cx.cache.effective_visibilities.is_directly_public(cx.tcx, item.item_id.expect_def_id())
|| matches!(
- *item.kind,
+ item.kind,
clean::StructFieldItem(_)
| clean::VariantItem(_)
| clean::AssocConstItem(..)
diff --git a/src/librustdoc/passes/collect_trait_impls.rs b/src/librustdoc/passes/collect_trait_impls.rs
index 394a64d..a9edc48 100644
--- a/src/librustdoc/passes/collect_trait_impls.rs
+++ b/src/librustdoc/passes/collect_trait_impls.rs
@@ -160,13 +160,13 @@ fn add_deref_target(
// scan through included items ahead of time to splice in Deref targets to the "valid" sets
for it in new_items_external.iter().chain(new_items_local.iter()) {
- if let ImplItem(box Impl { ref for_, ref trait_, ref items, .. }) = *it.kind
+ if let ImplItem(box Impl { ref for_, ref trait_, ref items, .. }) = it.kind
&& trait_.as_ref().map(|t| t.def_id()) == tcx.lang_items().deref_trait()
&& cleaner.keep_impl(for_, true)
{
let target = items
.iter()
- .find_map(|item| match *item.kind {
+ .find_map(|item| match item.kind {
AssocTypeItem(ref t, _) => Some(&t.type_),
_ => None,
})
@@ -200,7 +200,7 @@ fn add_deref_target(
// Filter out external items that are not needed
new_items_external.retain(|it| {
- if let ImplItem(box Impl { ref for_, ref trait_, ref kind, .. }) = *it.kind {
+ if let ImplItem(box Impl { ref for_, ref trait_, ref kind, .. }) = it.kind {
cleaner.keep_impl(
for_,
trait_.as_ref().map(|t| t.def_id()) == tcx.lang_items().deref_trait(),
@@ -211,7 +211,7 @@ fn add_deref_target(
}
});
- if let ModuleItem(Module { items, .. }) = &mut *krate.module.kind {
+ if let ModuleItem(Module { items, .. }) = &mut krate.module.inner.kind {
items.extend(synth_impls);
items.extend(new_items_external);
items.extend(new_items_local);
@@ -258,7 +258,7 @@ impl<'cache> DocVisitor for ItemAndAliasCollector<'cache> {
fn visit_item(&mut self, i: &Item) {
self.items.insert(i.item_id);
- if let TypeAliasItem(alias) = &*i.kind
+ if let TypeAliasItem(alias) = &i.inner.kind
&& let Some(did) = alias.type_.def_id(self.cache)
{
self.items.insert(ItemId::DefId(did));
diff --git a/src/librustdoc/passes/propagate_doc_cfg.rs b/src/librustdoc/passes/propagate_doc_cfg.rs
index 5aa6a5e..6be51dd 100644
--- a/src/librustdoc/passes/propagate_doc_cfg.rs
+++ b/src/librustdoc/passes/propagate_doc_cfg.rs
@@ -31,7 +31,7 @@ impl<'a, 'tcx> CfgPropagator<'a, 'tcx> {
// Some items need to merge their attributes with their parents' otherwise a few of them
// (mostly `cfg` ones) will be missing.
fn merge_with_parent_attributes(&mut self, item: &mut Item) {
- let check_parent = match &*item.kind {
+ let check_parent = match &item.kind {
// impl blocks can be in different modules with different cfg and we need to get them
// as well.
ItemKind::ImplItem(_) => false,
diff --git a/src/librustdoc/passes/strip_aliased_non_local.rs b/src/librustdoc/passes/strip_aliased_non_local.rs
index e1dd2d3..6078ab3 100644
--- a/src/librustdoc/passes/strip_aliased_non_local.rs
+++ b/src/librustdoc/passes/strip_aliased_non_local.rs
@@ -23,7 +23,7 @@ struct AliasedNonLocalStripper<'tcx> {
impl<'tcx> DocFolder for AliasedNonLocalStripper<'tcx> {
fn fold_item(&mut self, i: Item) -> Option<Item> {
- Some(match *i.kind {
+ Some(match i.kind {
clean::TypeAliasItem(..) => {
let mut stripper = NonLocalStripper { tcx: self.tcx };
// don't call `fold_item` as that could strip the type-alias it-self
diff --git a/src/librustdoc/passes/strip_hidden.rs b/src/librustdoc/passes/strip_hidden.rs
index 86f14dd..7c5fbac9 100644
--- a/src/librustdoc/passes/strip_hidden.rs
+++ b/src/librustdoc/passes/strip_hidden.rs
@@ -89,7 +89,7 @@ fn recurse_in_impl_or_exported_macro(&mut self, i: Item) -> Item {
impl<'a, 'tcx> DocFolder for Stripper<'a, 'tcx> {
fn fold_item(&mut self, i: Item) -> Option<Item> {
let has_doc_hidden = i.is_doc_hidden();
- let is_impl_or_exported_macro = match *i.kind {
+ let is_impl_or_exported_macro = match i.kind {
clean::ImplItem(..) => true,
// If the macro has the `#[macro_export]` attribute, it means it's accessible at the
// crate level so it should be handled differently.
@@ -138,7 +138,7 @@ fn fold_item(&mut self, i: Item) -> Option<Item> {
// module it's defined in. Both of these are marked "stripped," and
// not included in the final docs, but since they still have an effect
// on the final doc, cannot be completely removed from the Clean IR.
- match *i.kind {
+ match i.kind {
clean::StructFieldItem(..) | clean::ModuleItem(..) | clean::VariantItem(..) => {
// We need to recurse into stripped modules to
// strip things like impl methods but when doing so
diff --git a/src/librustdoc/passes/stripper.rs b/src/librustdoc/passes/stripper.rs
index 3f706ac..a85428f 100644
--- a/src/librustdoc/passes/stripper.rs
+++ b/src/librustdoc/passes/stripper.rs
@@ -39,7 +39,7 @@ fn is_item_reachable(
impl<'a, 'tcx> DocFolder for Stripper<'a, 'tcx> {
fn fold_item(&mut self, i: Item) -> Option<Item> {
- match *i.kind {
+ match i.kind {
clean::StrippedItem(..) => {
// We need to recurse into stripped modules to strip things
// like impl methods but when doing so we must not add any
@@ -130,7 +130,7 @@ fn fold_item(&mut self, i: Item) -> Option<Item> {
clean::KeywordItem => {}
}
- let fastreturn = match *i.kind {
+ let fastreturn = match i.kind {
// nothing left to do for traits (don't want to filter their
// methods out, visibility controlled by the trait)
clean::TraitItem(..) => true,
@@ -195,7 +195,7 @@ fn should_keep_impl(&self, item: &Item, for_def_id: DefId) -> bool {
impl<'a> DocFolder for ImplStripper<'a, '_> {
fn fold_item(&mut self, i: Item) -> Option<Item> {
- if let clean::ImplItem(ref imp) = *i.kind {
+ if let clean::ImplItem(ref imp) = i.kind {
// Impl blocks can be skipped if they are: empty; not a trait impl; and have no
// documentation.
//
@@ -272,7 +272,7 @@ fn import_should_be_hidden(&self, i: &Item, imp: &clean::Import) -> bool {
impl<'tcx> DocFolder for ImportStripper<'tcx> {
fn fold_item(&mut self, i: Item) -> Option<Item> {
- match *i.kind {
+ match &i.kind {
clean::ImportItem(imp)
if !self.document_hidden && self.import_should_be_hidden(&i, &imp) =>
{
diff --git a/src/librustdoc/visit.rs b/src/librustdoc/visit.rs
index 430bbe9..7fb0a32 100644
--- a/src/librustdoc/visit.rs
+++ b/src/librustdoc/visit.rs
@@ -48,8 +48,8 @@ fn visit_inner_recur(&mut self, kind: &ItemKind) {
/// don't override!
fn visit_item_recur(&mut self, item: &Item) {
- match &*item.kind {
- StrippedItem(i) => self.visit_inner_recur(i),
+ match &item.kind {
+ StrippedItem(i) => self.visit_inner_recur(&*i),
_ => self.visit_inner_recur(&item.kind),
}
}
diff --git a/src/rustdoc-json-types/lib.rs b/src/rustdoc-json-types/lib.rs
index 40a90c1..ef21779 100644
--- a/src/rustdoc-json-types/lib.rs
+++ b/src/rustdoc-json-types/lib.rs
@@ -13,7 +13,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 = 33;
+pub const FORMAT_VERSION: u32 = 34;
/// The root of the emitted JSON blob.
///
@@ -194,7 +194,7 @@ pub enum GenericArgs {
/// ```
args: Vec<GenericArg>,
/// Associated type or constant bindings (e.g. `Item=i32` or `Item: Clone`) for this type.
- bindings: Vec<TypeBinding>,
+ constraints: Vec<AssocItemConstraint>,
},
/// `Fn(A, B) -> C`
Parenthesized {
@@ -258,19 +258,19 @@ pub struct Constant {
/// ^^^^^^^^^^ ^^^^^^^^^^^^^^^
/// ```
#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
-pub struct TypeBinding {
+pub struct AssocItemConstraint {
/// The name of the associated type/constant.
pub name: String,
/// Arguments provided to the associated type/constant.
pub args: GenericArgs,
/// The kind of bound applied to the associated type/constant.
- pub binding: TypeBindingKind,
+ pub binding: AssocItemConstraintKind,
}
/// The way in which an associate type/constant is bound.
#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
-pub enum TypeBindingKind {
+pub enum AssocItemConstraintKind {
/// The required value/type is specified exactly. e.g.
/// ```text
/// Iterator<Item = u32, IntoIter: DoubleEndedIterator>
@@ -311,7 +311,7 @@ pub enum ItemKind {
/// A crate imported via the `extern crate` syntax.
ExternCrate,
/// An import of 1 or more items into scope, using the `use` keyword.
- Import,
+ Use,
/// A `struct` declaration.
Struct,
/// A field of a struct.
@@ -341,7 +341,7 @@ pub enum ItemKind {
/// `type`s from an `extern` block.
///
/// See [the tracking issue](https://github.com/rust-lang/rust/issues/43467)
- ForeignType,
+ ExternType,
/// A macro declaration.
///
/// Corresponds to either `ItemEnum::Macro(_)`
@@ -386,7 +386,7 @@ pub enum ItemEnum {
rename: Option<String>,
},
/// An import of 1 or more items into scope, using the `use` keyword.
- Import(Import),
+ Use(Use),
/// A `union` declaration.
Union(Union),
@@ -429,7 +429,7 @@ pub enum ItemEnum {
/// `type`s from an `extern` block.
///
/// See [the tracking issue](https://github.com/rust-lang/rust/issues/43467)
- ForeignType,
+ ExternType,
/// A macro_rules! declarative macro. Contains a single string with the source
/// representation of the macro with the patterns stripped.
@@ -447,12 +447,19 @@ pub enum ItemEnum {
/// The type of the constant.
#[serde(rename = "type")]
type_: Type,
- /// The stringified expression for the default value, if provided, e.g.
+ /// Inside a trait declaration, this is the default value for the associated constant,
+ /// if provided.
+ /// Inside an `impl` block, this is the value assigned to the associated constant,
+ /// and will always be present.
+ ///
+ /// The representation is implementation-defined and not guaranteed to be representative of
+ /// either the resulting value or of the source code.
+ ///
/// ```rust
/// const X: usize = 640 * 1024;
/// // ^^^^^^^^^^
/// ```
- default: Option<String>,
+ value: Option<String>,
},
/// An associated type of a trait or a type.
AssocType {
@@ -467,12 +474,16 @@ pub enum ItemEnum {
/// }
/// ```
bounds: Vec<GenericBound>,
- /// The default for this type, if provided, e.g.
+ /// Inside a trait declaration, this is the default for the associated type, if provided.
+ /// Inside an impl block, this is the type assigned to the associated type, and will always
+ /// be present.
+ ///
/// ```rust
/// type X = usize;
/// // ^^^^^
/// ```
- default: Option<Type>,
+ #[serde(rename = "type")]
+ type_: Option<Type>,
},
}
@@ -497,7 +508,7 @@ pub struct Union {
/// The generic parameters and where clauses on this union.
pub generics: Generics,
/// Whether any fields have been removed from the result, due to being private or hidden.
- pub fields_stripped: bool,
+ pub has_stripped_fields: bool,
/// The list of fields in the union.
///
/// All of the corresponding [`Item`]s are of kind [`ItemEnum::StructField`].
@@ -554,7 +565,7 @@ pub enum StructKind {
/// All of the corresponding [`Item`]s are of kind [`ItemEnum::StructField`].
fields: Vec<Id>,
/// Whether any fields have been removed from the result, due to being private or hidden.
- fields_stripped: bool,
+ has_stripped_fields: bool,
},
}
@@ -564,7 +575,7 @@ pub struct Enum {
/// Information about the type parameters and `where` clauses of the enum.
pub generics: Generics,
/// Whether any variants have been removed from the result, due to being private or hidden.
- pub variants_stripped: bool,
+ pub has_stripped_variants: bool,
/// The list of variants in the enum.
///
/// All of the corresponding [`Item`]s are of kind [`ItemEnum::Variant`]
@@ -621,7 +632,7 @@ pub enum VariantKind {
/// All of the corresponding [`Item`]s are of kind [`ItemEnum::Variant`].
fields: Vec<Id>,
/// Whether any variants have been removed from the result, due to being private or hidden.
- fields_stripped: bool,
+ has_stripped_fields: bool,
},
}
@@ -645,16 +656,13 @@ pub struct Discriminant {
/// A set of fundamental properties of a function.
#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
-pub struct Header {
+pub struct FunctionHeader {
/// Is this function marked as `const`?
- #[serde(rename = "const")]
- pub const_: bool,
+ pub is_const: bool,
/// Is this function unsafe?
- #[serde(rename = "unsafe")]
- pub unsafe_: bool,
+ pub is_unsafe: bool,
/// Is this function async?
- #[serde(rename = "async")]
- pub async_: bool,
+ pub is_async: bool,
/// The ABI used by the function.
pub abi: Abi,
}
@@ -697,11 +705,11 @@ pub enum Abi {
#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub struct Function {
/// Information about the function signature, or declaration.
- pub decl: FnDecl,
+ pub sig: FunctionSignature,
/// Information about the function’s type parameters and `where` clauses.
pub generics: Generics,
/// Information about core properties of the function, e.g. whether it's `const`, its ABI, etc.
- pub header: Header,
+ pub header: FunctionHeader,
/// Whether the function has a body, i.e. an implementation.
pub has_body: bool,
}
@@ -784,7 +792,7 @@ pub enum GenericParamDefKind {
/// In this example, the generic parameter named `impl Trait` (and which
/// is bound by `Trait`) is synthetic, because it was not originally in
/// the Rust source text.
- synthetic: bool,
+ is_synthetic: bool,
},
/// Denotes a constant parameter.
@@ -894,7 +902,7 @@ pub enum TraitBoundModifier {
}
/// Either a type or a constant, usually stored as the right-hand side of an equation in places like
-/// [`TypeBinding`]
+/// [`AssocItemConstraint`]
#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum Term {
@@ -963,7 +971,7 @@ pub enum Type {
/// A raw pointer type, e.g. `*mut u32`, `*const u8`, etc.
RawPointer {
/// This is `true` for `*mut _` and `false` for `*const _`.
- mutable: bool,
+ is_mutable: bool,
/// The type of the pointee.
#[serde(rename = "type")]
type_: Box<Type>,
@@ -973,7 +981,7 @@ pub enum Type {
/// The name of the lifetime of the reference, if provided.
lifetime: Option<String>,
/// This is `true` for `&mut i32` and `false` for `&i32`
- mutable: bool,
+ is_mutable: bool,
/// The type of the pointee, e.g. the `i32` in `&'a mut i32`
#[serde(rename = "type")]
type_: Box<Type>,
@@ -1036,7 +1044,7 @@ pub struct Path {
#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub struct FunctionPointer {
/// The signature of the function.
- pub decl: FnDecl,
+ pub sig: FunctionSignature,
/// Used for Higher-Rank Trait Bounds (HRTBs)
///
/// ```ignore (incomplete expression)
@@ -1045,12 +1053,12 @@ pub struct FunctionPointer {
/// ```
pub generic_params: Vec<GenericParamDef>,
/// The core properties of the function, such as the ABI it conforms to, whether it's unsafe, etc.
- pub header: Header,
+ pub header: FunctionHeader,
}
/// The signature of a function.
#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
-pub struct FnDecl {
+pub struct FunctionSignature {
/// List of argument names and their type.
///
/// Note that not all names will be valid identifiers, as some of
@@ -1063,7 +1071,7 @@ pub struct FnDecl {
/// ```ignore (incomplete code)
/// fn printf(fmt: &str, ...);
/// ```
- pub c_variadic: bool,
+ pub is_c_variadic: bool,
}
/// A `trait` declaration.
@@ -1127,10 +1135,10 @@ pub struct Impl {
/// The list of associated items contained in this impl block.
pub items: Vec<Id>,
/// Whether this is a negative impl (e.g. `!Sized` or `!Send`).
- pub negative: bool,
+ pub is_negative: bool,
/// Whether this is an impl that’s implied by the compiler
/// (for autotraits, e.g. `Send` or `Sync`).
- pub synthetic: bool,
+ pub is_synthetic: bool,
// FIXME: document this
pub blanket_impl: Option<Type>,
}
@@ -1138,7 +1146,7 @@ pub struct Impl {
/// A `use` statement.
#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
-pub struct Import {
+pub struct Use {
/// The full path being imported.
pub source: String,
/// May be different from the last segment of `source` when renaming imports:
@@ -1150,7 +1158,7 @@ pub struct Import {
/// ```
pub id: Option<Id>,
/// Whether this statement is a wildcard `use`, e.g. `use source::*;`
- pub glob: bool,
+ pub is_glob: bool,
}
/// A procedural macro.
@@ -1205,7 +1213,7 @@ pub struct Static {
#[serde(rename = "type")]
pub type_: Type,
/// This is `true` for mutable statics, declared as `static mut X: T = f();`
- pub mutable: bool,
+ pub is_mutable: bool,
/// The stringified expression for the initial value.
///
/// It's not guaranteed that it'll match the actual source code for the initial value.
diff --git a/src/rustdoc-json-types/tests.rs b/src/rustdoc-json-types/tests.rs
index 1126d5f..b9363fc 100644
--- a/src/rustdoc-json-types/tests.rs
+++ b/src/rustdoc-json-types/tests.rs
@@ -4,7 +4,7 @@
fn test_struct_info_roundtrip() {
let s = ItemEnum::Struct(Struct {
generics: Generics { params: vec![], where_predicates: vec![] },
- kind: StructKind::Plain { fields: vec![], fields_stripped: false },
+ kind: StructKind::Plain { fields: vec![], has_stripped_fields: false },
impls: vec![],
});
@@ -23,7 +23,7 @@ fn test_struct_info_roundtrip() {
fn test_union_info_roundtrip() {
let u = ItemEnum::Union(Union {
generics: Generics { params: vec![], where_predicates: vec![] },
- fields_stripped: false,
+ has_stripped_fields: false,
fields: vec![],
impls: vec![],
});
diff --git a/src/stage0 b/src/stage0
index dcc2267..1a60393 100644
--- a/src/stage0
+++ b/src/stage0
@@ -14,448 +14,456 @@
# All changes below this comment will be overridden the next time the
# tool is executed.
-compiler_date=2024-07-26
+compiler_date=2024-09-04
compiler_version=beta
-rustfmt_date=2024-07-30
+rustfmt_date=2024-09-04
rustfmt_version=nightly
-dist/2024-07-26/rustc-beta-aarch64-apple-darwin.tar.gz=a265d7831284938f090ef34cf2fb374f4d2b946c52829de8e53a06b7373c3d7e
-dist/2024-07-26/rustc-beta-aarch64-apple-darwin.tar.xz=f2420846f82f474892776f0bea176fbb2f1850a1fb9f51a1afe40ae6de8bbc17
-dist/2024-07-26/rustc-beta-aarch64-pc-windows-msvc.tar.gz=e3e0e2b8d1f8804cc2b5785765cc6807bbf7120fb010d74453097b5931c82e96
-dist/2024-07-26/rustc-beta-aarch64-pc-windows-msvc.tar.xz=1270aaea2f20a378e68d26518e1d34810ed346a4d4c272138c8aef67e3c386d5
-dist/2024-07-26/rustc-beta-aarch64-unknown-linux-gnu.tar.gz=02bcdc3eed81ba17e485556f1c4d5a00e851afb75a20f860ce7b6d22cb8f9e99
-dist/2024-07-26/rustc-beta-aarch64-unknown-linux-gnu.tar.xz=52b72cc7270fe75e023ca9c40d095a84cb0ce31657357cd7676d6570ca59bc1c
-dist/2024-07-26/rustc-beta-aarch64-unknown-linux-musl.tar.gz=b47ba6f2214f238cf8df3c386765e7816bc86e1166f27ddb6c0ce678ec716939
-dist/2024-07-26/rustc-beta-aarch64-unknown-linux-musl.tar.xz=95537778025708922b4bf27f34f0634a61a1d963a8424f8a06c82564c74e849a
-dist/2024-07-26/rustc-beta-arm-unknown-linux-gnueabi.tar.gz=d79c8b744d00b174be7630a54f9ee23562f8977d7e09e2ee46a9d72a80eef514
-dist/2024-07-26/rustc-beta-arm-unknown-linux-gnueabi.tar.xz=0f7d3d0773a3c1f94e8252d95b134f7f5e727a884ece54aa0f77e5edec5c6e29
-dist/2024-07-26/rustc-beta-arm-unknown-linux-gnueabihf.tar.gz=5e0d51532c4bb0c29fd01ef5d931c229f711c9326df0bdcb2b88c75aa72dc210
-dist/2024-07-26/rustc-beta-arm-unknown-linux-gnueabihf.tar.xz=5fe623cab0afd5f7bdd664a593ac02791915e30cfc9ca76a02ffd70e1e865ede
-dist/2024-07-26/rustc-beta-armv7-unknown-linux-gnueabihf.tar.gz=1df1e1a44170d6c9ab4988e9841ab56ee00248ca5cbf7e38b69677bd5b2de585
-dist/2024-07-26/rustc-beta-armv7-unknown-linux-gnueabihf.tar.xz=70791fcd1aef6686e012740017a0e5bb4441eb4018f875e8e50d5597c183291d
-dist/2024-07-26/rustc-beta-i686-pc-windows-gnu.tar.gz=045fe2478c5a5341d7b7a05b9df23ef8f81ddbe0faa78e3f2107341a0e8189f6
-dist/2024-07-26/rustc-beta-i686-pc-windows-gnu.tar.xz=d7f3888692210b6024ed72864015d1c101f28814dec5b60c9e32a772f11f3b47
-dist/2024-07-26/rustc-beta-i686-pc-windows-msvc.tar.gz=5b2988c87d91013cd92ebca43fd6cf5d49250fc0452830ea46622e418984041e
-dist/2024-07-26/rustc-beta-i686-pc-windows-msvc.tar.xz=b9d65cca6691baf2841432d6d2d566face171c460cf161f39a21acf7c0b033c1
-dist/2024-07-26/rustc-beta-i686-unknown-linux-gnu.tar.gz=7b037163f1c19a0fbbf4029d12a7b3764e747c9ea7944f1e45a6f91a068df224
-dist/2024-07-26/rustc-beta-i686-unknown-linux-gnu.tar.xz=f5044d8f3784e5bc682b03ccbe7389abf5b254a01074fa67eb824d2dfc9fd3ad
-dist/2024-07-26/rustc-beta-loongarch64-unknown-linux-gnu.tar.gz=840131ab570c68c0d46244eac743f7d8a1f470d1926068868d288307a488b3c9
-dist/2024-07-26/rustc-beta-loongarch64-unknown-linux-gnu.tar.xz=6513a144014807bd258d2a90fa4618aabdb4e265268e408d5cb699a610b78c31
-dist/2024-07-26/rustc-beta-loongarch64-unknown-linux-musl.tar.gz=d703a904da3604e553ba0a74775f8005e9f52615be3266197b71362b20414def
-dist/2024-07-26/rustc-beta-loongarch64-unknown-linux-musl.tar.xz=8ab79d34b3c182a4349fd01a50aa13ca064ecea64c2ab09f7a9ec38046741c7a
-dist/2024-07-26/rustc-beta-powerpc-unknown-linux-gnu.tar.gz=70eb8f65e91068ac20366fca1fc30227f36cb2b2ce1abdaa72504583cc7865c7
-dist/2024-07-26/rustc-beta-powerpc-unknown-linux-gnu.tar.xz=3372e272cf9620191000a95fff23e417586e6b894e211d44e4f658c241c3d014
-dist/2024-07-26/rustc-beta-powerpc64-unknown-linux-gnu.tar.gz=e8f09f56c43ae6e99a42a8c430492157415fa6baee2c3f8f86f94ab4279634cd
-dist/2024-07-26/rustc-beta-powerpc64-unknown-linux-gnu.tar.xz=599fcd5c57687e29eec085f7cc2733965a8e8fe5eac6499abd92ffda64f6e500
-dist/2024-07-26/rustc-beta-powerpc64le-unknown-linux-gnu.tar.gz=904029f0c81ec9679851d952f0f0f616cc183028882c6686f5b5bb665ca00cef
-dist/2024-07-26/rustc-beta-powerpc64le-unknown-linux-gnu.tar.xz=31f3f895d665acf082a6dbb40e91fd97f823f84c8e62074dfa82e60f22606f5b
-dist/2024-07-26/rustc-beta-riscv64gc-unknown-linux-gnu.tar.gz=4d374e60b8ac2f3fddd5ba9b46ab80555bc5b19f080b86604dde994087b00ed9
-dist/2024-07-26/rustc-beta-riscv64gc-unknown-linux-gnu.tar.xz=c905a880b98d1eaabfb306d5b6dda018e5025b42028cbb12bad408f4d469f3ae
-dist/2024-07-26/rustc-beta-s390x-unknown-linux-gnu.tar.gz=69f0228799685960f36f31eb4c139cbd7925f5180468e2d4a435ecbad63e9535
-dist/2024-07-26/rustc-beta-s390x-unknown-linux-gnu.tar.xz=1da1caf5b2ad149ef82af58278dea6c381c372366c48cda8ca7f520cc8752b2c
-dist/2024-07-26/rustc-beta-x86_64-apple-darwin.tar.gz=81fe4bef33afb3010fdd7af42653fbf5dd9abf0d69268576dfe144c88c7b9944
-dist/2024-07-26/rustc-beta-x86_64-apple-darwin.tar.xz=c4785475e3f7087cbab405937c0ca3ebc08455dd36df156680cea1ed38fcce5b
-dist/2024-07-26/rustc-beta-x86_64-pc-windows-gnu.tar.gz=6e58397829f67bf952037c94894409032e52ac8ccdf3858346d131fff6175a50
-dist/2024-07-26/rustc-beta-x86_64-pc-windows-gnu.tar.xz=8e834602e7cd1fcd585f51ab280266b4ffc57e0c974a1a26b901701b5127135d
-dist/2024-07-26/rustc-beta-x86_64-pc-windows-msvc.tar.gz=94a8a08495b8093db5d9a32c3258c9f97ea8b0f57947d7ca642664c06cfb438d
-dist/2024-07-26/rustc-beta-x86_64-pc-windows-msvc.tar.xz=8d057c7167cffeebeddabf25f08a50de8dbad5ed7cfffce625c81a99d757e998
-dist/2024-07-26/rustc-beta-x86_64-unknown-freebsd.tar.gz=dcc93e7b76ca7a469544597885a7b5f4b5f822e05a89b2d7a093e06dede9f52b
-dist/2024-07-26/rustc-beta-x86_64-unknown-freebsd.tar.xz=3efb7d4d97dc9b13a0178464e79bbf96bb71763a588b48c587746acd456ceb8d
-dist/2024-07-26/rustc-beta-x86_64-unknown-illumos.tar.gz=ef5a0d34b78848962e83ed468934d7cbedff778a89e50f2128ba25d0943e25ed
-dist/2024-07-26/rustc-beta-x86_64-unknown-illumos.tar.xz=5cccc7bbb15b63d422dfd2c8ac25e2103906880e843feccd318ba8b8c614d3b4
-dist/2024-07-26/rustc-beta-x86_64-unknown-linux-gnu.tar.gz=a9b352f61f8124c1fba0c76ecc8c1c972e61e97f5299f3b86bc17f035351ced5
-dist/2024-07-26/rustc-beta-x86_64-unknown-linux-gnu.tar.xz=a8fced9a5de02bb660491b440f6596e4baf6eb9114b8dd8d93ac7ada6266d274
-dist/2024-07-26/rustc-beta-x86_64-unknown-linux-musl.tar.gz=5e6fae2fd75e1780995fa9839593044539fac3f095c8948ba446b7024f632ec9
-dist/2024-07-26/rustc-beta-x86_64-unknown-linux-musl.tar.xz=9eb16965a7f1f7be7751fb61280f272c2497765e552fc0dd653700d551a04539
-dist/2024-07-26/rustc-beta-x86_64-unknown-netbsd.tar.gz=40b7312ce424dcbde5537da50d17854c255c3ed535a124f4f0102cf62bc86b5a
-dist/2024-07-26/rustc-beta-x86_64-unknown-netbsd.tar.xz=222a86f97d9bf2db38ebea9f45901790429658154d3448d05e7f0ddd9833ff18
-dist/2024-07-26/rust-std-beta-aarch64-apple-darwin.tar.gz=a9b3cfe03b3053cd533ff02fb54f95db009396802464f32840b3369e9a3e6afc
-dist/2024-07-26/rust-std-beta-aarch64-apple-darwin.tar.xz=9ddb6b8291ade9224cc76f4d946c179bdc6e25f5819a4ba1ebe1f207d4c663ac
-dist/2024-07-26/rust-std-beta-aarch64-apple-ios.tar.gz=8c129310921ed45d3cdfc30e60d93403adf8158a6661de96ee5d4a63119cf3e5
-dist/2024-07-26/rust-std-beta-aarch64-apple-ios.tar.xz=e1fcee4b062f25b0350e5e74064615c354ee8b399adf792d46319ee782857398
-dist/2024-07-26/rust-std-beta-aarch64-apple-ios-sim.tar.gz=40d6d48dea64407bf31be39f9e0316a1e47648ee75bc0d3361edb961e062aa6b
-dist/2024-07-26/rust-std-beta-aarch64-apple-ios-sim.tar.xz=3e01648f45e0c7cb040d3c293024477801930d5078d54c6291ba13aa8eb4e1f6
-dist/2024-07-26/rust-std-beta-aarch64-linux-android.tar.gz=da310568bee0d4868132589399c9229df5ac575a028f2409f51fd1f8c9e81779
-dist/2024-07-26/rust-std-beta-aarch64-linux-android.tar.xz=f3079ebecbe5b9f23495fe0966fc39fee1d38869287695804c3c04d53df07496
-dist/2024-07-26/rust-std-beta-aarch64-pc-windows-gnullvm.tar.gz=9dce2956e4b01d867ef6c229dbff9319a779a80e43a29fe1f8b10a333049264d
-dist/2024-07-26/rust-std-beta-aarch64-pc-windows-gnullvm.tar.xz=b64e7b87027dceba21283ba71430a8053a918bfaf6c071cc70d5f5da00155944
-dist/2024-07-26/rust-std-beta-aarch64-pc-windows-msvc.tar.gz=0d103e0c4ec8039dd42be09bb9c74f269a9567fe7dfacfc54106912cd2aeb35b
-dist/2024-07-26/rust-std-beta-aarch64-pc-windows-msvc.tar.xz=4b3627e9e363e9b2fd85222c677a7250b12a5d32919f38a31ed7375637a79a81
-dist/2024-07-26/rust-std-beta-aarch64-unknown-fuchsia.tar.gz=061fdac14ee0bd3abba36269f68e9ad25a243ac7062f946155f98680f484a84c
-dist/2024-07-26/rust-std-beta-aarch64-unknown-fuchsia.tar.xz=8acc12f14ac643b822595a6a07c7e5ac65855b83938ac122e3278f64769eeb13
-dist/2024-07-26/rust-std-beta-aarch64-unknown-linux-gnu.tar.gz=199498df7d94989d4ff1773fdfe86e97ac99ead487f402d020f78688bc6dfba4
-dist/2024-07-26/rust-std-beta-aarch64-unknown-linux-gnu.tar.xz=1337c2f00e9bec2e0a553234d74daea67a9781459d0abe3c8de954981d9354d2
-dist/2024-07-26/rust-std-beta-aarch64-unknown-linux-musl.tar.gz=a7116c13a413989f2ed874d45780aced3299c4ef8ce8e3bc99efe960a73cadb3
-dist/2024-07-26/rust-std-beta-aarch64-unknown-linux-musl.tar.xz=80ef87143ee2339e90842c4893284217ddfa56926524baf94341277c1210dd07
-dist/2024-07-26/rust-std-beta-aarch64-unknown-linux-ohos.tar.gz=c47cab4bb196e749f07d03f6f6c8f2fe538c84a055a298f0b505ab98dadf4a1c
-dist/2024-07-26/rust-std-beta-aarch64-unknown-linux-ohos.tar.xz=b36aa3f0bab63ac21fb69610d379a87fbd1ee87041153eb1e6886a237d22b171
-dist/2024-07-26/rust-std-beta-aarch64-unknown-none.tar.gz=92de36c897dbf90f9986396da1f8a954ad7b4fdab3e466d63974c82611e76d47
-dist/2024-07-26/rust-std-beta-aarch64-unknown-none.tar.xz=fb5d50ce34bd222c1b624e5aa2248776f8926f3ee360b7c4c1e0bd412d01bae2
-dist/2024-07-26/rust-std-beta-aarch64-unknown-none-softfloat.tar.gz=fea794a4c8aec3e5357199db7a9b701ceedded1dbb50167b002d368a6ae09cc7
-dist/2024-07-26/rust-std-beta-aarch64-unknown-none-softfloat.tar.xz=47fc6e497bd4c8013f708ed052701129c308b657d28ee2dce877cb63ccb1b06b
-dist/2024-07-26/rust-std-beta-aarch64-unknown-uefi.tar.gz=17eb45b10a0c9cc702e7fb4f0c7926591d3ad0f052f2bded9cf852ea082cd2bb
-dist/2024-07-26/rust-std-beta-aarch64-unknown-uefi.tar.xz=1f6b1a3082fc29546e4d8dcb20675f62ead20fe96112998dcb1260e206e93cbc
-dist/2024-07-26/rust-std-beta-arm-linux-androideabi.tar.gz=baad78bda532ed77dbf3e4265595b9dac82f6fdc27dc6deaf7386a60b981b927
-dist/2024-07-26/rust-std-beta-arm-linux-androideabi.tar.xz=cf4283b1224d4dac3c55da905608c5bba7639b6511977f3de344a999ae39e571
-dist/2024-07-26/rust-std-beta-arm-unknown-linux-gnueabi.tar.gz=0da01efb79d43140515c48561cbe7a2fdb83895fe4351f2fffaaf108fb163268
-dist/2024-07-26/rust-std-beta-arm-unknown-linux-gnueabi.tar.xz=baa52bf16290d71b1b89f12ddcee5adf18c480071f9fd4daf3fcab72f92fad4a
-dist/2024-07-26/rust-std-beta-arm-unknown-linux-gnueabihf.tar.gz=2325e8bc225a24a0a8c16da6dded16d4befb671b913051a7cce12ee3e183eac7
-dist/2024-07-26/rust-std-beta-arm-unknown-linux-gnueabihf.tar.xz=ab9ad0ec7057deda5c29e5d7de317eb32512fb95b62ba628b91b5246dde9c90d
-dist/2024-07-26/rust-std-beta-arm-unknown-linux-musleabi.tar.gz=be6d9a01609152eb815cef9462023f0ca2f2950ed03d914629d8e6e3a96af8ab
-dist/2024-07-26/rust-std-beta-arm-unknown-linux-musleabi.tar.xz=75ec6023cf9a43ec7ed0f52a1633b56154d9505c5d5d769153b48b9991ce99a8
-dist/2024-07-26/rust-std-beta-arm-unknown-linux-musleabihf.tar.gz=cc1d361b775e966c700d122f925a9f2feacecaf7d2891d9c5c5a4a1060336408
-dist/2024-07-26/rust-std-beta-arm-unknown-linux-musleabihf.tar.xz=934c10c58db5d7644bd0b7df6c3a128cc53b88b412128c33de5932fa0194f4bb
-dist/2024-07-26/rust-std-beta-arm64ec-pc-windows-msvc.tar.gz=949a18d9d8b4c7cb3442ec4e387c91feddf0cc26f1fe602ec6c2c484312c9845
-dist/2024-07-26/rust-std-beta-arm64ec-pc-windows-msvc.tar.xz=7adb9a93d35002d0335b3449b8d9af35a80a35524fe98bd86c3896481f020597
-dist/2024-07-26/rust-std-beta-armebv7r-none-eabi.tar.gz=b40dbc6ba0f3f80414bdc11260f291f067acbceb50d84597a9366746cff53348
-dist/2024-07-26/rust-std-beta-armebv7r-none-eabi.tar.xz=1564c3215b173956bae41cda7312ed7912812e0fbb65dd8d75808a1d5084fc8d
-dist/2024-07-26/rust-std-beta-armebv7r-none-eabihf.tar.gz=809d7f027aecc4a131921181418e66b956ad0a2a7170a3ec3649e21659c5a524
-dist/2024-07-26/rust-std-beta-armebv7r-none-eabihf.tar.xz=1b9589a72d2902cd4491406d93c599d2e850fa2ba19b1bcc6bdc5cc7196f9643
-dist/2024-07-26/rust-std-beta-armv5te-unknown-linux-gnueabi.tar.gz=f2840d36b089fdbcff5f6f9f7a6e576cf21836824957cdf2d1ef2c75a1f5c11f
-dist/2024-07-26/rust-std-beta-armv5te-unknown-linux-gnueabi.tar.xz=5723cf48a1ff47fb764cc5ad921356e490997aa09ecd86404e370ffdacfa4b31
-dist/2024-07-26/rust-std-beta-armv5te-unknown-linux-musleabi.tar.gz=fb33110ad649aac6f55310e6f03d03d4d75ccdca43ada93fb97a717975ef867f
-dist/2024-07-26/rust-std-beta-armv5te-unknown-linux-musleabi.tar.xz=cef39c2886fffef2986e9fe8f3be58f0d7f3846466a35443bc0d49464bdef98a
-dist/2024-07-26/rust-std-beta-armv7-linux-androideabi.tar.gz=68fe7b30550cf1ccc44a1669f26620ae418b48cd6283b716aff3dee91acfcbec
-dist/2024-07-26/rust-std-beta-armv7-linux-androideabi.tar.xz=81f24aedc06a25c8dfce729132a77e90adc5fe2aec86a3a9548aec9458127ce1
-dist/2024-07-26/rust-std-beta-armv7-unknown-linux-gnueabi.tar.gz=a63c5d40bcf8b0702c1a91e992c042130916edfdcf94fb4615ba10c89dad6642
-dist/2024-07-26/rust-std-beta-armv7-unknown-linux-gnueabi.tar.xz=4706424b53063b768223880d87bbec0cf57e524374a6ef053ebef02d096484e4
-dist/2024-07-26/rust-std-beta-armv7-unknown-linux-gnueabihf.tar.gz=85c3684f175642463777aa69889a20391e39afc0d6356baa3ac0445f7aa25119
-dist/2024-07-26/rust-std-beta-armv7-unknown-linux-gnueabihf.tar.xz=a8d67436a8ee232d57e2924f8f9e5cb0050c71740d57a4e677674adb75093f31
-dist/2024-07-26/rust-std-beta-armv7-unknown-linux-musleabi.tar.gz=b3226669f49ee8fc89c1f84855c29f8416df3e32d3276547f521f738179164a6
-dist/2024-07-26/rust-std-beta-armv7-unknown-linux-musleabi.tar.xz=9a5711743a0984ab7baed2a50f87e50d7facff2ef05f5b936b7b25f5a5992734
-dist/2024-07-26/rust-std-beta-armv7-unknown-linux-musleabihf.tar.gz=fd2db70418d432c7b32bed92f5af0f301baa3a71c171d0ee8b0798bbc8e239e2
-dist/2024-07-26/rust-std-beta-armv7-unknown-linux-musleabihf.tar.xz=97922d70b37e1e2ff6dc447625b3482094824910a1d7a483cc707985406560ee
-dist/2024-07-26/rust-std-beta-armv7-unknown-linux-ohos.tar.gz=710be82238e9ad617b2d5f52ef37976b415e7b6ba3d5f3677080f2ccf78b9d44
-dist/2024-07-26/rust-std-beta-armv7-unknown-linux-ohos.tar.xz=2cd0956277cf963f95ffa0104bdcd60cb4e6c4bb2a443a683d67f41726408159
-dist/2024-07-26/rust-std-beta-armv7a-none-eabi.tar.gz=dd38446053d1500f3bdc325ae5cd52d0434c618d79a7c0a0473c76691353bac4
-dist/2024-07-26/rust-std-beta-armv7a-none-eabi.tar.xz=5b82a2f970be59563cc4f550e4202be802cbe21dcbf14de413ed8f30b0e22020
-dist/2024-07-26/rust-std-beta-armv7r-none-eabi.tar.gz=9758806233e59d7d40eeda0740559d9838f9a6c608309567af61245ea57dc212
-dist/2024-07-26/rust-std-beta-armv7r-none-eabi.tar.xz=4266b69d61a46c0c6f6d3aeb2b3378ff88201039df50cd8d3a51c9ff910be181
-dist/2024-07-26/rust-std-beta-armv7r-none-eabihf.tar.gz=6142ea4cdff99902181379fdb9a651fd9d1ab6276ebc104e73b2280a6d9f380f
-dist/2024-07-26/rust-std-beta-armv7r-none-eabihf.tar.xz=bbf4c74f6b6a32f01d03bf101f69dd19b909717036117064fa2c8cdd0b4146da
-dist/2024-07-26/rust-std-beta-i586-pc-windows-msvc.tar.gz=2cc32752932477945f248dee4d277754928b982815e2e2e0d27883522fb9b8d2
-dist/2024-07-26/rust-std-beta-i586-pc-windows-msvc.tar.xz=e40eae93c31c1fa06517a21cfbdd2dd18e2f740aee1251bcc9bdc680a565241c
-dist/2024-07-26/rust-std-beta-i586-unknown-linux-gnu.tar.gz=6d7210503568d9fa02231ac2d9a1b400d00a37f38ec8f00bfcfe45c325aeed02
-dist/2024-07-26/rust-std-beta-i586-unknown-linux-gnu.tar.xz=cdd81201e38226750f2b4292b099b5d78fe0115cedb4c28bf20200144297d8b6
-dist/2024-07-26/rust-std-beta-i586-unknown-linux-musl.tar.gz=95244114ed2d6dd2de488f49115b11a25b008134f1fa1c8f2e2a62849b51f213
-dist/2024-07-26/rust-std-beta-i586-unknown-linux-musl.tar.xz=fcb3280dabb4aae920a14c7f4fec52dc3f11bc68f5143961fa88347aa020bb9a
-dist/2024-07-26/rust-std-beta-i686-linux-android.tar.gz=d36c3baba2df9d69e197a773f752bc36e107c2411d78037a357039a856e35aa5
-dist/2024-07-26/rust-std-beta-i686-linux-android.tar.xz=14b9bedd1bb95e1bac2bb028670b1d9dbe6998bb6ad0cfab1db0be0cd9e3d4cf
-dist/2024-07-26/rust-std-beta-i686-pc-windows-gnu.tar.gz=44463b4a17c87a2de8554e2629eed8172b60b078ccca7e78bb2b0a20324f51ef
-dist/2024-07-26/rust-std-beta-i686-pc-windows-gnu.tar.xz=1e4c3a1d8585aac5aa3e66541b4aef03a0b429a6067300c58f6cf588eac19fa6
-dist/2024-07-26/rust-std-beta-i686-pc-windows-gnullvm.tar.gz=b1d9d5967c039721eda402a7227074ba6e6e8f2877be49eed961ecbce00004ed
-dist/2024-07-26/rust-std-beta-i686-pc-windows-gnullvm.tar.xz=2436343b99d81abae0e6bba16850dbc1c005ebba5defb991c3a0e99834410746
-dist/2024-07-26/rust-std-beta-i686-pc-windows-msvc.tar.gz=c6147e9c6c39501d133a344972dbb8108bdc45bb2fe8ad624162ad04a9c00c6e
-dist/2024-07-26/rust-std-beta-i686-pc-windows-msvc.tar.xz=6207bdfe0796e4bd4e7d25457d67559f15aa2e8bb91b05284ed147f8799de869
-dist/2024-07-26/rust-std-beta-i686-unknown-freebsd.tar.gz=c675df742bd9fbc01f67411a19926e2814412f12e09b53d1492e8c7250f3e685
-dist/2024-07-26/rust-std-beta-i686-unknown-freebsd.tar.xz=d5b9c3783f6d2dbdf25e0495e32a295c4820bbc5b65a44f19f018b1141e85371
-dist/2024-07-26/rust-std-beta-i686-unknown-linux-gnu.tar.gz=748dfafeb6b953017b9129be9697d02a73d5bc8b1371a6a00bbfa20b7b45033c
-dist/2024-07-26/rust-std-beta-i686-unknown-linux-gnu.tar.xz=0c9a0717054858fa821e4c418b9e99cb0a0f852ec3c866951c1d1795cc1e8152
-dist/2024-07-26/rust-std-beta-i686-unknown-linux-musl.tar.gz=96afb9b33c86a6007f9c02f1f418d28f13014ec5154b648ceb7f725449dcbddf
-dist/2024-07-26/rust-std-beta-i686-unknown-linux-musl.tar.xz=7ed52c039fdd13a7477ed211ad8432cfd2fab98832174c8a534e5ac280f28572
-dist/2024-07-26/rust-std-beta-i686-unknown-uefi.tar.gz=676786bd5e7f0739d18d40d99158045fcba746dc306485c0f15ce49ef2b63b0b
-dist/2024-07-26/rust-std-beta-i686-unknown-uefi.tar.xz=d7fdba095ca515454034891c8a862aaa563ee7451289138ce32b10691dbfe38a
-dist/2024-07-26/rust-std-beta-loongarch64-unknown-linux-gnu.tar.gz=ff2eb11f284da7883dbf6ae465af86e50a9cd98c9b7d22b1e710626716e07db5
-dist/2024-07-26/rust-std-beta-loongarch64-unknown-linux-gnu.tar.xz=953fedb9dac336cb796290f619919f4ff9b2a6fcce09e23072f93a40b5498bdd
-dist/2024-07-26/rust-std-beta-loongarch64-unknown-linux-musl.tar.gz=ba1b4f772faf2e738d2696eb576f74bdbd1fed1a073053eee341ec6423b6e1c6
-dist/2024-07-26/rust-std-beta-loongarch64-unknown-linux-musl.tar.xz=f3f3eaafd9ecb1ee0ba68259d88d65ced56f20323a4f542fc85993e92a044206
-dist/2024-07-26/rust-std-beta-loongarch64-unknown-none.tar.gz=f20ecabfab9d8ecbab44d661018b865e449137993726e76b20c7749db4d0986e
-dist/2024-07-26/rust-std-beta-loongarch64-unknown-none.tar.xz=7da2cf413c0665b07b3083862747c9815a78b3775c2bee6cd1f7551e7f2e4c8a
-dist/2024-07-26/rust-std-beta-loongarch64-unknown-none-softfloat.tar.gz=3f7529ea5dcb17c18efa949916dd1ebc29b123a265cc8839cee4fe4e637f19be
-dist/2024-07-26/rust-std-beta-loongarch64-unknown-none-softfloat.tar.xz=d2a30f8659cc66d48da0e6c1919707943321d7f3ac0e2d58a9078aec16c86ef7
-dist/2024-07-26/rust-std-beta-nvptx64-nvidia-cuda.tar.gz=f971daa3f8c3d0773fb6667cb7a544f96ebd049e9b5d1b5ac4bd3ea0c342467b
-dist/2024-07-26/rust-std-beta-nvptx64-nvidia-cuda.tar.xz=3cd2f4ad7d9f41e9f903aa49eb86d142bb5ef69c2c39d9ba16a00a39d74046f1
-dist/2024-07-26/rust-std-beta-powerpc-unknown-linux-gnu.tar.gz=b319ee87ee034a6a2a67dc2efdc72f8285c73d9bd1bd893586170ac54049151a
-dist/2024-07-26/rust-std-beta-powerpc-unknown-linux-gnu.tar.xz=c751e65bbdfd72de07abf138162ab64dcbce51ba50375cef5ca8f35945d9ac7b
-dist/2024-07-26/rust-std-beta-powerpc64-unknown-linux-gnu.tar.gz=0228f8d7e0913cca5db975e0b9ec4807e817dcbc0cd0bd64b64826c9537f25e5
-dist/2024-07-26/rust-std-beta-powerpc64-unknown-linux-gnu.tar.xz=d37d5ae3605d745a393fc71c5f0e169cee283aa840edb9543682b339cd040310
-dist/2024-07-26/rust-std-beta-powerpc64le-unknown-linux-gnu.tar.gz=6dd97a7215bdc8145cee5856957bf3f20719f65c73033006243ac2a9e347394b
-dist/2024-07-26/rust-std-beta-powerpc64le-unknown-linux-gnu.tar.xz=d7541a8e83f7b8a9761988c3ac295a665e21e4d5dc9e2284ef48314f6c784166
-dist/2024-07-26/rust-std-beta-riscv32i-unknown-none-elf.tar.gz=34b21aec2cc1b92b2911211fe3c798918ea6c99d51975f6a979c2da3a09b0a05
-dist/2024-07-26/rust-std-beta-riscv32i-unknown-none-elf.tar.xz=50ba48e76e60ffbfb2bb0ba0b8e12418b7f6a9d7cde31b508bb4656536934e82
-dist/2024-07-26/rust-std-beta-riscv32im-unknown-none-elf.tar.gz=e84526736c1a48dbec3b122b8c01458ff549afdbdd0f73e705c76cca1bd1f767
-dist/2024-07-26/rust-std-beta-riscv32im-unknown-none-elf.tar.xz=df8d9909b0afd0e02b9c027f12e28aa2c40716d7c8a8f5e82b7521d2e145fbf8
-dist/2024-07-26/rust-std-beta-riscv32imac-unknown-none-elf.tar.gz=7b671c5257a7653481fe6bc090c55398607590292590e0fdf5973f5f9b7b18b1
-dist/2024-07-26/rust-std-beta-riscv32imac-unknown-none-elf.tar.xz=7f4d1a8e757fd29f4f58005032608df709003098eb661fe98a0b3116b7237e6a
-dist/2024-07-26/rust-std-beta-riscv32imafc-unknown-none-elf.tar.gz=9d957edfba201b541bd589ca4085e26bf6f890b3970817fe9af6ccf5f2eb0854
-dist/2024-07-26/rust-std-beta-riscv32imafc-unknown-none-elf.tar.xz=0f867e1391009d1d0caefb6b9217fc8e9f3e087a7dd9b22a157719bdc44ac074
-dist/2024-07-26/rust-std-beta-riscv32imc-unknown-none-elf.tar.gz=a02ccac46574fad8929b419eff7510b8a773211d3ccce9ca96f0485e2dab8eaa
-dist/2024-07-26/rust-std-beta-riscv32imc-unknown-none-elf.tar.xz=b70f37cddd519d0d207e28089b469f702bfe72ba5d32a631c85270db75b83d61
-dist/2024-07-26/rust-std-beta-riscv64gc-unknown-linux-gnu.tar.gz=151863cece818be834261e6c148eeabbb1c796c991065c84b813bac64e73fef7
-dist/2024-07-26/rust-std-beta-riscv64gc-unknown-linux-gnu.tar.xz=94cbae695036a4a1fa1faac12a6dd5ebeea18ec2d6e7b01c311d340ce7ddba39
-dist/2024-07-26/rust-std-beta-riscv64gc-unknown-none-elf.tar.gz=3c8ca657208a4d96eff193363375a33d966dc319cd329dd7a0d379e052ab43bc
-dist/2024-07-26/rust-std-beta-riscv64gc-unknown-none-elf.tar.xz=037f7b599421eca888332dadd797509d81af04743eac06120a9882b27aff5ca2
-dist/2024-07-26/rust-std-beta-riscv64imac-unknown-none-elf.tar.gz=d931a3611003cbe61003ca4feeb637449f1d10f7969cd27ca37f11cf5536e465
-dist/2024-07-26/rust-std-beta-riscv64imac-unknown-none-elf.tar.xz=3c7a3a9e1e03c2fe097e2e7353d00d02e864d3964db559f6a08a3d33f1fb7927
-dist/2024-07-26/rust-std-beta-s390x-unknown-linux-gnu.tar.gz=f877200e388345c10d3b0f5b8c484dd42905e769dcc1e21692e1cf7f2d59317e
-dist/2024-07-26/rust-std-beta-s390x-unknown-linux-gnu.tar.xz=1052e8e5681c95ed3c004adee2492ff19d109965e9441a3362df876719899486
-dist/2024-07-26/rust-std-beta-sparc64-unknown-linux-gnu.tar.gz=e487752db0ecd837fb1ecb57064ef2464f7f85ed5fdc9d47322e7b5c37c32300
-dist/2024-07-26/rust-std-beta-sparc64-unknown-linux-gnu.tar.xz=e74a462d598c55822b5841bdc35cb2605b4aa7993e305246b3adf079ae79ea1d
-dist/2024-07-26/rust-std-beta-sparcv9-sun-solaris.tar.gz=3ea692ffe99c953d0049c0a16b71eb0bc3da492b9f9308463311dc0143af84dd
-dist/2024-07-26/rust-std-beta-sparcv9-sun-solaris.tar.xz=97005f0d686a6481c5a532b6e1ea14befc794ed89394a8f1c94ad39257ebdaa8
-dist/2024-07-26/rust-std-beta-thumbv6m-none-eabi.tar.gz=2aa967414bd03764774338e377c4714b8d169b1bbc651624a20158441b8111c3
-dist/2024-07-26/rust-std-beta-thumbv6m-none-eabi.tar.xz=d1a3b6ccbc55d1d9555674d1596a0c9f489304f9cb211e0c4645c17256ada4d1
-dist/2024-07-26/rust-std-beta-thumbv7em-none-eabi.tar.gz=33fe3c61aa2e93c6a925b132fabc11c24e102cc070260d5f89a66e374e9a4d23
-dist/2024-07-26/rust-std-beta-thumbv7em-none-eabi.tar.xz=f50bb682fe484f23ae1ae9b2466c450b8fe9ecc3694fb68e162ce43cc8917af7
-dist/2024-07-26/rust-std-beta-thumbv7em-none-eabihf.tar.gz=53a17d10d498f1b6ebd6852987f304b2e1187544f2c9e91b69d0fdbf88630910
-dist/2024-07-26/rust-std-beta-thumbv7em-none-eabihf.tar.xz=fb97e6f2b047d6251eb6e34891b64f20d0dbc648beb78bb7364fe563670d7de8
-dist/2024-07-26/rust-std-beta-thumbv7m-none-eabi.tar.gz=940eef037faceb2b9bdb1094eac6b175843094d3a3ab3c9850eb28742643e92d
-dist/2024-07-26/rust-std-beta-thumbv7m-none-eabi.tar.xz=c892b8a80db788d1f4bf64ec6f740bb1168a8b9dc88d105366892a476ad3c244
-dist/2024-07-26/rust-std-beta-thumbv7neon-linux-androideabi.tar.gz=905d378e6fd4387381fc166718ff31f017c99e725a9c8461bbac39d5571e246f
-dist/2024-07-26/rust-std-beta-thumbv7neon-linux-androideabi.tar.xz=6c5fc29004bda36ddfb0280636ac2b2c28c538f33cadb07a55174fadb068daa5
-dist/2024-07-26/rust-std-beta-thumbv7neon-unknown-linux-gnueabihf.tar.gz=38c8b07558734a9fff1807a823af72faaf8ab5ea47042f1b88a38d6c3648c43b
-dist/2024-07-26/rust-std-beta-thumbv7neon-unknown-linux-gnueabihf.tar.xz=e30e0000336449a8aabf60839cba4ecca32cf82b02ed0a7a23935793072679f4
-dist/2024-07-26/rust-std-beta-thumbv8m.base-none-eabi.tar.gz=db784556ebf56a79e6330de3204ce6ce5422eca2543b872ed55c238aedbfedae
-dist/2024-07-26/rust-std-beta-thumbv8m.base-none-eabi.tar.xz=373efe8c55e85aae60dfac234471b76fefbc2ba722d97e0338ec593b7c70cce3
-dist/2024-07-26/rust-std-beta-thumbv8m.main-none-eabi.tar.gz=1bd5a11163f5fb9325e21c425d5d2fb3e1f845d265cbf7736679c3bb9c8d22a7
-dist/2024-07-26/rust-std-beta-thumbv8m.main-none-eabi.tar.xz=d858d0077df0fa7363258994e76a1bc0ff850734de6a0fbe955c3c9b9cd46cb7
-dist/2024-07-26/rust-std-beta-thumbv8m.main-none-eabihf.tar.gz=07b356cd0ec3f18617e8f5be04d784847acfca43d6fa2101821dcdee18aada36
-dist/2024-07-26/rust-std-beta-thumbv8m.main-none-eabihf.tar.xz=aecacd11945e6e053fe27faab2c0816628b392cb06c41feb8ed693d43043eba4
-dist/2024-07-26/rust-std-beta-wasm32-unknown-emscripten.tar.gz=7bf6bdb443503d48cb711f8b3e2670fe20e02f71ae940c2f1b273ab1d15452b7
-dist/2024-07-26/rust-std-beta-wasm32-unknown-emscripten.tar.xz=9ed34d7467722660d625e9a048fcb843bdb80aac407b0395a693a5698f6c1465
-dist/2024-07-26/rust-std-beta-wasm32-unknown-unknown.tar.gz=5144fe563c42205ba777678291950bd1b8c2b010b9aae28e2fe96e14e93e28cb
-dist/2024-07-26/rust-std-beta-wasm32-unknown-unknown.tar.xz=6e55e79f65a02abf37e1533c2590f53dfe56b474b58a3220d88f3d1458b6dcdc
-dist/2024-07-26/rust-std-beta-wasm32-wasi.tar.gz=84d03b1c1fc7338895f82f54fdccb18ea6c4ceb43f47c3d46fadb014aa0c9549
-dist/2024-07-26/rust-std-beta-wasm32-wasi.tar.xz=f28cbf9552e3c680342364087e7305a12417a92ed6b6696d71d476e1c1d8d4e7
-dist/2024-07-26/rust-std-beta-wasm32-wasip1.tar.gz=8d56f1aa8661047f854806278b83a514fa79b7a5097635cd095943b3f848ea74
-dist/2024-07-26/rust-std-beta-wasm32-wasip1.tar.xz=78609204d01e0d0bcbc1fb5dd3d9cfcac60db23bfbd2428f1e021d1b05793519
-dist/2024-07-26/rust-std-beta-wasm32-wasip1-threads.tar.gz=ed1b9141bd68b8c13e295904ac66d18ca92c5b92a263fa5109262d15065aeded
-dist/2024-07-26/rust-std-beta-wasm32-wasip1-threads.tar.xz=0c036271c4c4e04357b630146cad296dc6a57363f7dc0cd2f3142ead13bf0602
-dist/2024-07-26/rust-std-beta-x86_64-apple-darwin.tar.gz=c12bc5543c262645f7000cc84247518033f15fcbdfed510eb92393d723906eb1
-dist/2024-07-26/rust-std-beta-x86_64-apple-darwin.tar.xz=a5fc26dd6068cdb28ee2a252af545a34dd2be6e075e7d0aac2d03796c07579f4
-dist/2024-07-26/rust-std-beta-x86_64-apple-ios.tar.gz=a62be7f900cec101b1b7444c7466e8fe0b823d708fadd92bce8bd531866b4938
-dist/2024-07-26/rust-std-beta-x86_64-apple-ios.tar.xz=993875efe27c1018bbcb8326665247a33eda6fc0e934f71124b0a08d72685474
-dist/2024-07-26/rust-std-beta-x86_64-fortanix-unknown-sgx.tar.gz=bc6ae4d5e93b47828678f1af55efc1baae2d76975be3259854272a566f5489c9
-dist/2024-07-26/rust-std-beta-x86_64-fortanix-unknown-sgx.tar.xz=51cf1d675e61aaeedf895e52a9a81b188aa066a68d599963e0435bddfd2f6a5b
-dist/2024-07-26/rust-std-beta-x86_64-linux-android.tar.gz=6bd4089f30f05d9902d667a2d48028345bd558e7365bd3957bc554a4d0c1f939
-dist/2024-07-26/rust-std-beta-x86_64-linux-android.tar.xz=2a7e9250e3bea7f7e502131012139eadb66c71e95e8cec1698e22b21e7c9fbcd
-dist/2024-07-26/rust-std-beta-x86_64-pc-solaris.tar.gz=4169c938b638faff18a5db1bed5e7d2036f45d25ec9799dc2967ad1589d447a9
-dist/2024-07-26/rust-std-beta-x86_64-pc-solaris.tar.xz=8cbda8eeb98be575b78170e9895390e9406c4de41db8363988185dd24e276427
-dist/2024-07-26/rust-std-beta-x86_64-pc-windows-gnu.tar.gz=99a14bf8cffa0c736a25ce117bc5d4ab64963d81c9d9ac377f118a77a6a3c4b6
-dist/2024-07-26/rust-std-beta-x86_64-pc-windows-gnu.tar.xz=9902878b75b3f6cf944909cf6d17efc26dc820708b164b34757d841e89c948bd
-dist/2024-07-26/rust-std-beta-x86_64-pc-windows-gnullvm.tar.gz=54b83918128c3d19b09a4e1801783500266794395e6a6f138ad647bd890b79f6
-dist/2024-07-26/rust-std-beta-x86_64-pc-windows-gnullvm.tar.xz=2b0ed80c922e25f3783fbc0ce181b76b7f758d2a1b85b823851b7ac35c6872df
-dist/2024-07-26/rust-std-beta-x86_64-pc-windows-msvc.tar.gz=44ce7faad791029b670a9d815766a647d488dbbb56eb09024a09a595427fd19b
-dist/2024-07-26/rust-std-beta-x86_64-pc-windows-msvc.tar.xz=cd7011512df191100d31caef920d1a5c6d5ec2a771e0b52078d5d60b45e9a497
-dist/2024-07-26/rust-std-beta-x86_64-unknown-freebsd.tar.gz=dc20c2fc14b2211bf4517464109871f940a227298302d2ec84eaca539a19e9b4
-dist/2024-07-26/rust-std-beta-x86_64-unknown-freebsd.tar.xz=5a7fa24ca3f7b43526c116a5ebce60f29116640ad51c1ed426f9aee705b10897
-dist/2024-07-26/rust-std-beta-x86_64-unknown-fuchsia.tar.gz=975917e862347f7e1472cdaa2258de16cb9981e3a8256f9b7860104740076187
-dist/2024-07-26/rust-std-beta-x86_64-unknown-fuchsia.tar.xz=bb89062b05f025a964e0110fcfc8fdf57300b23314409924cd4a05e9af9614af
-dist/2024-07-26/rust-std-beta-x86_64-unknown-illumos.tar.gz=a1c1e3e15bea1c4e6c70b8a56c4fef1c231b6ab5528c32cb69ded38456b3fa21
-dist/2024-07-26/rust-std-beta-x86_64-unknown-illumos.tar.xz=43b31f7dd50621faff96c13a2246c80e84fc4da4076d4aedca4e9a6bf63ca43b
-dist/2024-07-26/rust-std-beta-x86_64-unknown-linux-gnu.tar.gz=3f8df0e35e2e8d5e0f8181f20f0639323aa8e8c21da60697599447c0d77f783a
-dist/2024-07-26/rust-std-beta-x86_64-unknown-linux-gnu.tar.xz=d0e727d9176abdbef02b1276b3b1acf69068b9c0fc0477fb3248fd06c99292b5
-dist/2024-07-26/rust-std-beta-x86_64-unknown-linux-gnux32.tar.gz=73ba835c5c4c9fcabbcb4e1460d402cf0c0aa9b2e01342521897abd9769dcc02
-dist/2024-07-26/rust-std-beta-x86_64-unknown-linux-gnux32.tar.xz=64e6fc64ccfd0adb2fabc610eba6e877ab83f2de49532363deef4579728baf6f
-dist/2024-07-26/rust-std-beta-x86_64-unknown-linux-musl.tar.gz=58dcb73ba02fa38742d255bd346a77340cf634247904624c7af9b11e769a364c
-dist/2024-07-26/rust-std-beta-x86_64-unknown-linux-musl.tar.xz=ea4417de121ab7e869659b26efd144baf2fd839a956da4acb30121d1bc9132aa
-dist/2024-07-26/rust-std-beta-x86_64-unknown-linux-ohos.tar.gz=d1e861a9176a5cb934270592f7b98528283c363d135736477a844499015ac44a
-dist/2024-07-26/rust-std-beta-x86_64-unknown-linux-ohos.tar.xz=c5f548845c6ccbee1980892e630ab06ec1bef498fb7f6fc80b4ced4a84c23f85
-dist/2024-07-26/rust-std-beta-x86_64-unknown-netbsd.tar.gz=3f6677ecdb1a2f016e9941234c221b06fd0a21cd9bae83a59bdcfde055c4878a
-dist/2024-07-26/rust-std-beta-x86_64-unknown-netbsd.tar.xz=60eae08756d92a70b740ecd8a1412138a9a14486289d73440bf7ee068586f9c4
-dist/2024-07-26/rust-std-beta-x86_64-unknown-none.tar.gz=1f11ad1a66d01a09c7237da76327b70ae2e2a9f7647a3ee0de58d563576efacf
-dist/2024-07-26/rust-std-beta-x86_64-unknown-none.tar.xz=960fb614a927e1b3d1d8e4a9fb7220ae675d0e8219fdde204bc6454fbe69a0a9
-dist/2024-07-26/rust-std-beta-x86_64-unknown-redox.tar.gz=3af955fc52feaee2d89d6d50e0df4d00417897679f0d607a0f146a8d34c20496
-dist/2024-07-26/rust-std-beta-x86_64-unknown-redox.tar.xz=cb607387d0524bc84610cd6cc0a0070e0dadc379a7fb1a736f3f336cf0458b8d
-dist/2024-07-26/rust-std-beta-x86_64-unknown-uefi.tar.gz=ae56b334234ba51cf68be42d0fd58cf3487673dbe747bb3efa01e8563b9b8a90
-dist/2024-07-26/rust-std-beta-x86_64-unknown-uefi.tar.xz=1468622e9bb6384a6ab7006863d2b7d55307e74239befc8e72dfd39f83c0af1e
-dist/2024-07-26/cargo-beta-aarch64-apple-darwin.tar.gz=62f687da4c02bef3e114b92c75b62fc6f7fdfcd210fb66329f6d4780f7dbcd70
-dist/2024-07-26/cargo-beta-aarch64-apple-darwin.tar.xz=f9346e9ed4e5638f58dc237b22aef9e1b25b23bb588c736dceaa25b7b935f2bb
-dist/2024-07-26/cargo-beta-aarch64-pc-windows-msvc.tar.gz=f2442eab2908bb90c551f56da8889e39ce44a31936ce63e13a54432105a67cf9
-dist/2024-07-26/cargo-beta-aarch64-pc-windows-msvc.tar.xz=ffc8c803668d09333fdfee996fa72c8874e91d92567f0b4eff9077d7b9a3070a
-dist/2024-07-26/cargo-beta-aarch64-unknown-linux-gnu.tar.gz=97f6b771f7e559df03f00f8665c6580535499d4afa7bf2a252a145b1aa0e2c0b
-dist/2024-07-26/cargo-beta-aarch64-unknown-linux-gnu.tar.xz=3ee58d5c57ba00e27428392dab1d69655bf7e997a0d3aa6629bb32f4f863396b
-dist/2024-07-26/cargo-beta-aarch64-unknown-linux-musl.tar.gz=b36871d3c88eca54e4c24d50171fd649d10a92f689d4812ebef7b510f0c3d799
-dist/2024-07-26/cargo-beta-aarch64-unknown-linux-musl.tar.xz=ee550d60ae217fe7aec12feada1ba1f84222427677de42382d192ec748f73f18
-dist/2024-07-26/cargo-beta-arm-unknown-linux-gnueabi.tar.gz=6599270c877164e76ef30f00a9b47da1a021fdaf1d4f7fdb194500f861ca8d21
-dist/2024-07-26/cargo-beta-arm-unknown-linux-gnueabi.tar.xz=46429528039b5499c6ac4618c4b73fcdfabf7fdd5ed9f9f3d64ccde0428d78c0
-dist/2024-07-26/cargo-beta-arm-unknown-linux-gnueabihf.tar.gz=01ba37e80e18e673c275538fc0db63b667ef52a72000dcbe76ac68018bd585e8
-dist/2024-07-26/cargo-beta-arm-unknown-linux-gnueabihf.tar.xz=004f5119454fa53c2a7a58f6d176f65903b3c5bfc8eb1f894f6ca4e9bc32b7a1
-dist/2024-07-26/cargo-beta-armv7-unknown-linux-gnueabihf.tar.gz=2bb2e69563684bf64607d3f584b4216b24fe190dd2eabd6c00c2044290beabde
-dist/2024-07-26/cargo-beta-armv7-unknown-linux-gnueabihf.tar.xz=454b0dafb3cd62788dc541ddfea5b484ac799253937602f6456e853c2a293707
-dist/2024-07-26/cargo-beta-i686-pc-windows-gnu.tar.gz=779d704f8f64a7290227631d1e396fe00bdada3cfb7f3e6c775a0bb00047cb97
-dist/2024-07-26/cargo-beta-i686-pc-windows-gnu.tar.xz=8cce8e286ff04f4d58235e8716a0ca05aedfeb9db6fb8952c523264ea649e542
-dist/2024-07-26/cargo-beta-i686-pc-windows-msvc.tar.gz=58b31a781da4f5215b0fbb5f355cbc3c5b2212971c68a1e00de19b851698fda3
-dist/2024-07-26/cargo-beta-i686-pc-windows-msvc.tar.xz=008125eca7351844707c9c14637030da45441a68d74f6e2752ee713f6403f03b
-dist/2024-07-26/cargo-beta-i686-unknown-linux-gnu.tar.gz=cbfc580db37b135a20f42f9da02517ec8cf0a286b7274252c23c6a4947ba6755
-dist/2024-07-26/cargo-beta-i686-unknown-linux-gnu.tar.xz=dc2198fabb6fe6f68353c268698dece4ca3d6901b424a7cc2c68850f81f75f20
-dist/2024-07-26/cargo-beta-loongarch64-unknown-linux-gnu.tar.gz=46ea726328e1700cf2b7d0ddeb16e25ebb648267c76268ba2f4aecb75ba47661
-dist/2024-07-26/cargo-beta-loongarch64-unknown-linux-gnu.tar.xz=520ee25c1f18d80b4e4ce25e8fd961a19c0dd2ee0274e9d9cd3201f7c57c6f77
-dist/2024-07-26/cargo-beta-loongarch64-unknown-linux-musl.tar.gz=fb710b6ae058619042bdf80ef5c2a56457076692a122b4155e0a53f382e8ad83
-dist/2024-07-26/cargo-beta-loongarch64-unknown-linux-musl.tar.xz=ac15e80c28c7a4570bb4a99fa70522a3ae5ba602ce25e96b8e82d097f8b42904
-dist/2024-07-26/cargo-beta-powerpc-unknown-linux-gnu.tar.gz=6907a40c1e7b18146ff2a60c6d44c9716f31cd4aeaae4fe858032aa26c359d27
-dist/2024-07-26/cargo-beta-powerpc-unknown-linux-gnu.tar.xz=4287d73ae2b3272a1893c2ffa32d007edf0b05ff2dbf1da92aa20f2b857e0eab
-dist/2024-07-26/cargo-beta-powerpc64-unknown-linux-gnu.tar.gz=edbdd5fc1e9bc5fdea67e7c2fda3fa9f3eb3f599c307a278bc7bf45ff97d1f48
-dist/2024-07-26/cargo-beta-powerpc64-unknown-linux-gnu.tar.xz=9c7d487f65a6273b76970b2c057b8120abbd89ba67a2f92dd446ecbacf218576
-dist/2024-07-26/cargo-beta-powerpc64le-unknown-linux-gnu.tar.gz=74e57cbc139d548202d94262170ee45e33ae01331358ac2eaa9fa67c968ea1ea
-dist/2024-07-26/cargo-beta-powerpc64le-unknown-linux-gnu.tar.xz=6cf99b689e32ff0caa56e9704dd185f6c268b484ccb657eff212e66fe64d1c10
-dist/2024-07-26/cargo-beta-riscv64gc-unknown-linux-gnu.tar.gz=ed13a39d74e9d814d585ce7fb1aafd093f94317d6ead76e4b43c03b01e210086
-dist/2024-07-26/cargo-beta-riscv64gc-unknown-linux-gnu.tar.xz=b5379d677d6596ffcbd7f3ebef2fd6d968096228101104a45565b170fb050042
-dist/2024-07-26/cargo-beta-s390x-unknown-linux-gnu.tar.gz=1a29502881e6512a8bea566a90781870181f5727359668fa3bed2b3210a21b8d
-dist/2024-07-26/cargo-beta-s390x-unknown-linux-gnu.tar.xz=95970245a7f304c6b83b8dad58b4c877ad2c9b0ca6bfc0090151561ce53a217b
-dist/2024-07-26/cargo-beta-x86_64-apple-darwin.tar.gz=521f03a968c6e0640de6f09ecbc6328ea57b2815f353a14e1d4dd09925e98366
-dist/2024-07-26/cargo-beta-x86_64-apple-darwin.tar.xz=14b733585cc768d26a822de630d990f519b6d6b4ae079f09bacd51b7449c18a4
-dist/2024-07-26/cargo-beta-x86_64-pc-windows-gnu.tar.gz=1bf5d0201ca87a76de8044dd8222517bd130ef3db631dc60a84e2fceced465d7
-dist/2024-07-26/cargo-beta-x86_64-pc-windows-gnu.tar.xz=2eaeb6863c655047e6c938e208ae952df4da2d8b4326aeda60918414764aa7b6
-dist/2024-07-26/cargo-beta-x86_64-pc-windows-msvc.tar.gz=7b7ef80aa6131ddcb8bfec0f9493417e9a1e617a8f599a27de52ee914d022f95
-dist/2024-07-26/cargo-beta-x86_64-pc-windows-msvc.tar.xz=647a6d0ff8f38dd4404c0006e5ed7b3a981dc89bbc334b1bd53225cc4f5511c8
-dist/2024-07-26/cargo-beta-x86_64-unknown-freebsd.tar.gz=bcd0e100d4c66784a2357be74813551c68d4e3b5e6846bfd1bbcb316e5c82c53
-dist/2024-07-26/cargo-beta-x86_64-unknown-freebsd.tar.xz=cc31bb9f5a67359f4af4743afbdf9b694e40cd209211d4ea819c94183de6ab60
-dist/2024-07-26/cargo-beta-x86_64-unknown-illumos.tar.gz=12f6a8d3d17b54ea260f6f5b19be9e208111b0ad37518ae6b6eae558d77a1dc5
-dist/2024-07-26/cargo-beta-x86_64-unknown-illumos.tar.xz=221c9cf9d1fce2b5c50bcf8f435f5335f1c5e9533f51d52b941593d6a964b4c8
-dist/2024-07-26/cargo-beta-x86_64-unknown-linux-gnu.tar.gz=53c64845abe4582a90041b2128b3f931ce636d01fc9a8509b35ded5dd7ae0a35
-dist/2024-07-26/cargo-beta-x86_64-unknown-linux-gnu.tar.xz=61805cfca6e7f602eaab0fde2be48cfed244105b2f4b5bff798752ce06d62713
-dist/2024-07-26/cargo-beta-x86_64-unknown-linux-musl.tar.gz=92ac04de9689176a42e5f0ccf1e44ce78b64bcd15d6e570c171d51c44cf8c6ce
-dist/2024-07-26/cargo-beta-x86_64-unknown-linux-musl.tar.xz=59a371de4343d330b79e84f629c98b5cb9dc58bd9706d1a7a9ff474b28394851
-dist/2024-07-26/cargo-beta-x86_64-unknown-netbsd.tar.gz=f48bb7b7d13862edaa8949be046b5bd2b8c63b0aab8e29bffb1940ec149eb123
-dist/2024-07-26/cargo-beta-x86_64-unknown-netbsd.tar.xz=0a6e09604fe291d0a9a0845a8ac7f434c9f4ffbb698c042ba83a070c23f804fb
-dist/2024-07-26/clippy-beta-aarch64-apple-darwin.tar.gz=4c8991c692f200c6a5f25957e6648e07b7271681cbd9c61749bc990216dbbe6f
-dist/2024-07-26/clippy-beta-aarch64-apple-darwin.tar.xz=51b5b85d46af2a3faeb53b81472c285eccc01f0c83575f62f37739cd48397fe2
-dist/2024-07-26/clippy-beta-aarch64-pc-windows-msvc.tar.gz=3a7755c10b32ee3b4f95875c974f21efad2be7ae27d317bbac056b3e5b9298b7
-dist/2024-07-26/clippy-beta-aarch64-pc-windows-msvc.tar.xz=718692e6a1e00ca042d9767273e487c941c65440e64729844a46e42ec6a8abb2
-dist/2024-07-26/clippy-beta-aarch64-unknown-linux-gnu.tar.gz=18da4a1fac25597186bdc5c825c71bc6fe020e8e6552ac97dd307a0311acab20
-dist/2024-07-26/clippy-beta-aarch64-unknown-linux-gnu.tar.xz=86a7ec123586e0c953efd23b82aea5eab62ab8c065bf3596d3001a23b01243ce
-dist/2024-07-26/clippy-beta-aarch64-unknown-linux-musl.tar.gz=267b8dd0b5024152e36bcfb15af0b8ae3c68a71f559b8ecea1a3c9a8982e315b
-dist/2024-07-26/clippy-beta-aarch64-unknown-linux-musl.tar.xz=6aaae715599da14ca8cc405e51deed3bc160661ec56e929ae347ef1ead7ccf00
-dist/2024-07-26/clippy-beta-arm-unknown-linux-gnueabi.tar.gz=f794412df97e19240f628037f5d1d7391dd09ee1a6de02f4dbff72e2b03d94b6
-dist/2024-07-26/clippy-beta-arm-unknown-linux-gnueabi.tar.xz=49a78a14b9638cabd19ba4261f5bd04066646e1260146e3be288182b73fa1864
-dist/2024-07-26/clippy-beta-arm-unknown-linux-gnueabihf.tar.gz=3dcd9775b46a100a50fbb00188dffdc6f07fca9843994c8406a2d053e41c1672
-dist/2024-07-26/clippy-beta-arm-unknown-linux-gnueabihf.tar.xz=e069b852ace430b2f75486a291d3d7849439c67c3381f5eedc0d6a9e6cde56db
-dist/2024-07-26/clippy-beta-armv7-unknown-linux-gnueabihf.tar.gz=57f7109bef934d0da06f7aea6eaca72b0e66f82d1160fbae05f53c2276da2b82
-dist/2024-07-26/clippy-beta-armv7-unknown-linux-gnueabihf.tar.xz=5ed50d8d088ae0d86ba51a03bf56040da027376f70b5114f593813daa4ce7a40
-dist/2024-07-26/clippy-beta-i686-pc-windows-gnu.tar.gz=d8712ca2ab26256c0fade4ecc8dd8e4ea6770d91e16e460ff2fe3f070febc59f
-dist/2024-07-26/clippy-beta-i686-pc-windows-gnu.tar.xz=9d0c88881e0535f9cb4a48f59b389b1c2a0b5fa46ad8bfa37fbc540676a8f557
-dist/2024-07-26/clippy-beta-i686-pc-windows-msvc.tar.gz=ffa017562648e98c7229e43a7422602c265441228485f0e14e52ebaf48a13e91
-dist/2024-07-26/clippy-beta-i686-pc-windows-msvc.tar.xz=292ab3d318a34e67463728752dc175f65cf5530f9368344dccaa79bad4df3b85
-dist/2024-07-26/clippy-beta-i686-unknown-linux-gnu.tar.gz=89bd927bc9370a405561f6534c5cd88e0f6e06b0b512589e5722349b12a17763
-dist/2024-07-26/clippy-beta-i686-unknown-linux-gnu.tar.xz=732120c4fcdde08fadca139216a91af7a6abee15f0a41735dc8860b36039d88d
-dist/2024-07-26/clippy-beta-loongarch64-unknown-linux-gnu.tar.gz=101e3118bf23246195b159abab59ee5626e767977d97f00e71fc5e67dfbf7784
-dist/2024-07-26/clippy-beta-loongarch64-unknown-linux-gnu.tar.xz=e40c0c15a7b195ed03c5e1167c2cb5e765ef643b0f6621c36643faf87bf46369
-dist/2024-07-26/clippy-beta-loongarch64-unknown-linux-musl.tar.gz=f6ed6391c8997f942d180cd32e81aca654450fb050cd865a8a1b13f77a892245
-dist/2024-07-26/clippy-beta-loongarch64-unknown-linux-musl.tar.xz=16e736f65b0ff029fe9fbafceec938123dff1b5a133f6c48b25edab379a20685
-dist/2024-07-26/clippy-beta-powerpc-unknown-linux-gnu.tar.gz=711fdb406a23ab5c3b1199e7af06608297bd071d7e48734a03bbc1f7a00b66dd
-dist/2024-07-26/clippy-beta-powerpc-unknown-linux-gnu.tar.xz=36d05ba29927b56e0d815dd09b39a3db12b6395e9717e653c20449fa83aa636f
-dist/2024-07-26/clippy-beta-powerpc64-unknown-linux-gnu.tar.gz=d53fb59c723a2e76f1716cf1c82aacd2627e1694aebf70511c24529a4fe1ee99
-dist/2024-07-26/clippy-beta-powerpc64-unknown-linux-gnu.tar.xz=ffec66667d95cabc893cc87988218552eba8930f031419612f80144dcf2cc881
-dist/2024-07-26/clippy-beta-powerpc64le-unknown-linux-gnu.tar.gz=a2cd11651304ecf5ce6a1ee5fdd1acbfd36b1dbd2680cd76f2b9d3a86012b837
-dist/2024-07-26/clippy-beta-powerpc64le-unknown-linux-gnu.tar.xz=c8a8d9fe8badb1e06811412a15ce9cdfef07ecc59bf83cd578b33889751bb560
-dist/2024-07-26/clippy-beta-riscv64gc-unknown-linux-gnu.tar.gz=01ba50dae501edf3afa60aab59d8d81ccfd91126ded4cf7d45f7c4b13fb8c4aa
-dist/2024-07-26/clippy-beta-riscv64gc-unknown-linux-gnu.tar.xz=a7e749bc581f9c64137a00dd891c4abff0d7f5684d2d501aad20ed1b01d9a312
-dist/2024-07-26/clippy-beta-s390x-unknown-linux-gnu.tar.gz=f19081755c37e3dc43091b06bcdc59c82b28c6fa0a78ff02d800a25d6d9f22f2
-dist/2024-07-26/clippy-beta-s390x-unknown-linux-gnu.tar.xz=d5f222e23f4f0ed4929e11684bc7b861c29fa183fffba0dbbfd5739b921f5234
-dist/2024-07-26/clippy-beta-x86_64-apple-darwin.tar.gz=edd631b7938dae6bb6c2694df0dab3ff6670e1a5ab3b5f0e6ce5bd7e992b6310
-dist/2024-07-26/clippy-beta-x86_64-apple-darwin.tar.xz=e4bc44ff13cfdd70f94c5efe86e93de041599e570c19611141c00700a656b40c
-dist/2024-07-26/clippy-beta-x86_64-pc-windows-gnu.tar.gz=1b1aff83773de4dd972734cb03209eccfc3793f442a1a5dea51f451ca34cd1cc
-dist/2024-07-26/clippy-beta-x86_64-pc-windows-gnu.tar.xz=71c357ff694cd954314c47e3bd458465453c65e6022799827b8560ecae16fdc8
-dist/2024-07-26/clippy-beta-x86_64-pc-windows-msvc.tar.gz=d4759993b9659ad8354d3fdf858cf99efebdf8202442505e11b55d24a54b31a0
-dist/2024-07-26/clippy-beta-x86_64-pc-windows-msvc.tar.xz=e29eaea7b7f2e54b9285a2216f5b85440313650090c268048ce9e830e007fa92
-dist/2024-07-26/clippy-beta-x86_64-unknown-freebsd.tar.gz=4009c19d557156e63ad7123d27264650d046cd20e723ec6cc8ffdb3fc1d3b8b1
-dist/2024-07-26/clippy-beta-x86_64-unknown-freebsd.tar.xz=9622117651423c53c35f69cb3087a5294cca098ac93aeb7c18bcab035a1e69ef
-dist/2024-07-26/clippy-beta-x86_64-unknown-illumos.tar.gz=a88fd4b3e30faaecf270936422e254a25ff5dba93b08ca4003a9978ee80d0838
-dist/2024-07-26/clippy-beta-x86_64-unknown-illumos.tar.xz=f391b26009b7089f3d49d2f3409bb4e02e3de0700284727d2d26e7062bb18011
-dist/2024-07-26/clippy-beta-x86_64-unknown-linux-gnu.tar.gz=e467501c65651d519ae9a489e821e7d5dc82fdbeb2da2d4c75f093e1b898abd6
-dist/2024-07-26/clippy-beta-x86_64-unknown-linux-gnu.tar.xz=9dcbd07899af86db3c101275ab0f2fd3b5b0c43d4a92c5b5be05f0e4500d7535
-dist/2024-07-26/clippy-beta-x86_64-unknown-linux-musl.tar.gz=c2a30c78a6ab64d1655651fdd5c7f970dadcd6dfd1a585d130bd890190fe67f6
-dist/2024-07-26/clippy-beta-x86_64-unknown-linux-musl.tar.xz=05c2a38fa5bca162e365218670a7c195ebd9b3491d14464282a273dfe93b0ad7
-dist/2024-07-26/clippy-beta-x86_64-unknown-netbsd.tar.gz=75ee727a80119a810193519535f962721d547297feb9b5597b397e59277de701
-dist/2024-07-26/clippy-beta-x86_64-unknown-netbsd.tar.xz=002b726868a14df5ea31fe8eb75fae24660fb1cfad73591e86f9179dd1bb2dc4
-dist/2024-07-30/rustfmt-nightly-aarch64-apple-darwin.tar.gz=d3bb2f1fa20555373189caa7e58a8e3071c7ea6e7059bab15d6dd52dfef56c4f
-dist/2024-07-30/rustfmt-nightly-aarch64-apple-darwin.tar.xz=ba0019eb0766dd438069988156994270959c875b010afce0f455540a0bb2ee2f
-dist/2024-07-30/rustfmt-nightly-aarch64-pc-windows-msvc.tar.gz=24bbbe80a998b78f04c15d82fcef9498315b1b8d0ddabeeb5b6729b14bafbf70
-dist/2024-07-30/rustfmt-nightly-aarch64-pc-windows-msvc.tar.xz=cc396d3639c7213ab6442dc79ab6a1a42bb17910aa6d27046cc89ebeb6973231
-dist/2024-07-30/rustfmt-nightly-aarch64-unknown-linux-gnu.tar.gz=e6dc772727a20920607923ff5a99526054e6244c40cc6c97fe68db58896de6fc
-dist/2024-07-30/rustfmt-nightly-aarch64-unknown-linux-gnu.tar.xz=eec95e09ec7bd64ab8a47e7311103f5bc58aa3499edcba052699686315f8441a
-dist/2024-07-30/rustfmt-nightly-aarch64-unknown-linux-musl.tar.gz=fef3eb7d5dee7458daacfba9b97d579868864267fcdc85334f02384683ce0c17
-dist/2024-07-30/rustfmt-nightly-aarch64-unknown-linux-musl.tar.xz=44f376f4d9e84645373b4cbfe17678c288a71b92622ab4091ca7b82ed6a21b57
-dist/2024-07-30/rustfmt-nightly-arm-unknown-linux-gnueabi.tar.gz=5c17927f12149fa605e3f671d25ac456d1d2bdac796b5ca466bfa7fb8688d224
-dist/2024-07-30/rustfmt-nightly-arm-unknown-linux-gnueabi.tar.xz=04783b1a2efc10696b0d32fde7c63437e17548d38b2272f928f28915107f4f18
-dist/2024-07-30/rustfmt-nightly-arm-unknown-linux-gnueabihf.tar.gz=1365d93efc4391f189726e69c7a968c8debb50411f29404da42d19bc9e053937
-dist/2024-07-30/rustfmt-nightly-arm-unknown-linux-gnueabihf.tar.xz=db344c9f6d31ac5a2efc839cbb886c312534e9b1fe4b116629eaca74f79c316d
-dist/2024-07-30/rustfmt-nightly-armv7-unknown-linux-gnueabihf.tar.gz=049a2b666956a56365661d944a0fc030673bec5578062ddaad104363f4ff1031
-dist/2024-07-30/rustfmt-nightly-armv7-unknown-linux-gnueabihf.tar.xz=32d3bc08316c0cfc3c1ea689ccdc80978f744864c048863b9d51ae59b6e2f0c2
-dist/2024-07-30/rustfmt-nightly-i686-pc-windows-gnu.tar.gz=bc33833cd41bf5ac36730fc9d3ef9c87643d42b8e711de286138962fb5fac4a5
-dist/2024-07-30/rustfmt-nightly-i686-pc-windows-gnu.tar.xz=feffb4527ad627a0239d788272edac9a0fbec704de3a67aabbd8a9cbb95d4fe3
-dist/2024-07-30/rustfmt-nightly-i686-pc-windows-msvc.tar.gz=0ffb98b839f6640ac75e094cbb469a06f2e45f51ced01efbeb51a3fba866a048
-dist/2024-07-30/rustfmt-nightly-i686-pc-windows-msvc.tar.xz=d229ea866bf4d6c2d8d748630146c7bccedb4ba5a17056fbdc4558baf976f067
-dist/2024-07-30/rustfmt-nightly-i686-unknown-linux-gnu.tar.gz=431de55efb797c75d8e440ba3da9ac70a04cccfc56b4e22b80b6488360915f90
-dist/2024-07-30/rustfmt-nightly-i686-unknown-linux-gnu.tar.xz=e9e4eac4205014b6b61c759a8326f7a5e44e8ff05726510a8bbefd656f78e97c
-dist/2024-07-30/rustfmt-nightly-loongarch64-unknown-linux-gnu.tar.gz=99381507f8fc42d9bd00c545dd7ef4734e364a4e994d02bae148f78b94f50ab5
-dist/2024-07-30/rustfmt-nightly-loongarch64-unknown-linux-gnu.tar.xz=6e2cd283d9370beb9c208bd823ac2433df500adf7e70d8acfe5a261e62be2b4a
-dist/2024-07-30/rustfmt-nightly-loongarch64-unknown-linux-musl.tar.gz=761a9733f53ecba343139bd1c028a66242824ef8f7c54ae63e0aaf0e77cabcf9
-dist/2024-07-30/rustfmt-nightly-loongarch64-unknown-linux-musl.tar.xz=c2973a99220588ea78b7a052861c345f01254073d6bb77e96982b12382907e2b
-dist/2024-07-30/rustfmt-nightly-powerpc-unknown-linux-gnu.tar.gz=4288ee8fc5f650b3d5c24be2ea114e133d3bad8ddf7e2211cdb72151410c755a
-dist/2024-07-30/rustfmt-nightly-powerpc-unknown-linux-gnu.tar.xz=2a31e1f211a26f6798acd4c779827bfa4e1ac4d77103a48be74617e5af1661a1
-dist/2024-07-30/rustfmt-nightly-powerpc64-unknown-linux-gnu.tar.gz=9598edeb1ff5eff934f1e4783b3ed263babb53d3513564ccccf453dada872ba1
-dist/2024-07-30/rustfmt-nightly-powerpc64-unknown-linux-gnu.tar.xz=eb5392fce8ee4a016406efba546366ff91d4db8cda94dd131dbda70c553b6c06
-dist/2024-07-30/rustfmt-nightly-powerpc64le-unknown-linux-gnu.tar.gz=0e9c55ee790eed653eda7b913e64d344ccbbe1681321377186d1e4882dc93bfc
-dist/2024-07-30/rustfmt-nightly-powerpc64le-unknown-linux-gnu.tar.xz=c9a0b3eddac707c4e0c1cdc754d2821845e5f4bdcbd001b71d7287fe851cc44b
-dist/2024-07-30/rustfmt-nightly-riscv64gc-unknown-linux-gnu.tar.gz=99c264f806d4a6a1288a9cc7f28e178102520ebe4728fb0da3f8142c1d6720e0
-dist/2024-07-30/rustfmt-nightly-riscv64gc-unknown-linux-gnu.tar.xz=3f1835460dbf17a3dbf47f2772e182ebf6337fd6a946a033f9700fb38140eda6
-dist/2024-07-30/rustfmt-nightly-s390x-unknown-linux-gnu.tar.gz=385224b95c56de8598dd5b4eeb48d7d7a8eb920825c55bb4d7be54142d7e2857
-dist/2024-07-30/rustfmt-nightly-s390x-unknown-linux-gnu.tar.xz=535220608ee858d46746c8de4c1e58f4f675061517b6b06c8af47004d5291f85
-dist/2024-07-30/rustfmt-nightly-x86_64-apple-darwin.tar.gz=aa19f1856befff101bcb433049e923486d7bc1a056638e478651936572e7e3bf
-dist/2024-07-30/rustfmt-nightly-x86_64-apple-darwin.tar.xz=2ed04cf9fddeafbb83d82988e00d3b7f5ae9382468ce1093cbb110bf46b04711
-dist/2024-07-30/rustfmt-nightly-x86_64-pc-windows-gnu.tar.gz=962dea60de3ac68a573f088f9c1b003816ce93f9088df15fe8cf7771a3abdc73
-dist/2024-07-30/rustfmt-nightly-x86_64-pc-windows-gnu.tar.xz=72f7b787644bd9008b13018512c0b09a425c15a337821dc9bded9ab7211c61de
-dist/2024-07-30/rustfmt-nightly-x86_64-pc-windows-msvc.tar.gz=1096ba25a23461eed84804584eb9ffdff780e2c737cc9dce1e8929419dfd645b
-dist/2024-07-30/rustfmt-nightly-x86_64-pc-windows-msvc.tar.xz=854b9e410e65b953ab71f356bd5b618679aa7c1f5a3de7f81ec388720ed04f60
-dist/2024-07-30/rustfmt-nightly-x86_64-unknown-freebsd.tar.gz=03b4ab410c70fee3daa7a577c311b29344158a7d35ea87627233cb6165191338
-dist/2024-07-30/rustfmt-nightly-x86_64-unknown-freebsd.tar.xz=d755700cc17416c4488db2d582250b5ec329fc0c2b94e9db0e6688ca30a7316c
-dist/2024-07-30/rustfmt-nightly-x86_64-unknown-illumos.tar.gz=b7448089c61c2f0a427416cd7521130c31a98c52e435bd0d04d6aad72d765ba6
-dist/2024-07-30/rustfmt-nightly-x86_64-unknown-illumos.tar.xz=cb3f479897032ff9ec5e06913e8e4374ce46af7f8a9030299c7b0cab2dab2005
-dist/2024-07-30/rustfmt-nightly-x86_64-unknown-linux-gnu.tar.gz=0c7dbff79d04218a7ba3f5992f67d25043bc5f348038f37ab7385cbc4d0df00d
-dist/2024-07-30/rustfmt-nightly-x86_64-unknown-linux-gnu.tar.xz=4f62cbc75a81d57748111a915ebb20f561f403c1b695141780d50c398b186fa6
-dist/2024-07-30/rustfmt-nightly-x86_64-unknown-linux-musl.tar.gz=e5e8b07ae7ba0e1f526828a10f2515a68b0ed6023eed25e3bb10b80e21e8db76
-dist/2024-07-30/rustfmt-nightly-x86_64-unknown-linux-musl.tar.xz=424ec90c59fca7e21b302efd7c6c7f7dbc5dcadd1afbb15e90efea38ea8a19cf
-dist/2024-07-30/rustfmt-nightly-x86_64-unknown-netbsd.tar.gz=f22576893113958f6caabcf3ab3e38287fea010c1809a8bb1197220d6660ea4e
-dist/2024-07-30/rustfmt-nightly-x86_64-unknown-netbsd.tar.xz=5e85141abe2a3c537cb4171c60cff5bdb11f075aa79212e0a958081d4648aec6
-dist/2024-07-30/rustc-nightly-aarch64-apple-darwin.tar.gz=f793e4645be9461fae09e82710bcfdfc6d749735be202f2e2cd6c2c643bb8925
-dist/2024-07-30/rustc-nightly-aarch64-apple-darwin.tar.xz=e42f52cc5a865ab92321b97aaeff4d39cbaad1a5b60a9a77de9f42e3b3231d21
-dist/2024-07-30/rustc-nightly-aarch64-pc-windows-msvc.tar.gz=0258ba5bf957d190ef3a384c5451ebbe8406c195a29b3a7ee2a4c48e0514f203
-dist/2024-07-30/rustc-nightly-aarch64-pc-windows-msvc.tar.xz=788b7e9239562f43c0d96cfd66f543604eef1c9b40d22898c456fade608e9c31
-dist/2024-07-30/rustc-nightly-aarch64-unknown-linux-gnu.tar.gz=94187df22d7b96a5c39c5c9a078f566b80d392abfd2a5d7059b836cfa0c446e1
-dist/2024-07-30/rustc-nightly-aarch64-unknown-linux-gnu.tar.xz=ca1381c6de1a96f32a30736c28aa196f7e653b4f57f01ffe2db52fe238a9f202
-dist/2024-07-30/rustc-nightly-aarch64-unknown-linux-musl.tar.gz=1c72596862a133003f68590a8ae09bf6ab25a5f9667a6d245eafede1ebd8f450
-dist/2024-07-30/rustc-nightly-aarch64-unknown-linux-musl.tar.xz=de0c216f229301bc88690b10b8f063b8e389915503980973b91bfe17b1fb6eda
-dist/2024-07-30/rustc-nightly-arm-unknown-linux-gnueabi.tar.gz=e00283a7ee9a702446456feb0156f1d1fc738fd013983f15c456fcafb8294309
-dist/2024-07-30/rustc-nightly-arm-unknown-linux-gnueabi.tar.xz=03fab128bc3756676c645f637edc5051f8096b00780d8ef4de7a85b3f248933a
-dist/2024-07-30/rustc-nightly-arm-unknown-linux-gnueabihf.tar.gz=105e06c0ca69b4a700980f2a588f831c23a9a9253268bd652110328b99918cb1
-dist/2024-07-30/rustc-nightly-arm-unknown-linux-gnueabihf.tar.xz=0da27ffe5504a03923ae5858b69cdd6eb276e6bd2bfb504bcf13ebdda654316b
-dist/2024-07-30/rustc-nightly-armv7-unknown-linux-gnueabihf.tar.gz=edb1bec402f3799e05fd3e31f30763e7266d2e062e410af8eab7636440da272c
-dist/2024-07-30/rustc-nightly-armv7-unknown-linux-gnueabihf.tar.xz=638a09ecfe0b66391ce6802e3e15bf15462aca1c8cfb2a49b948ec69eda0575c
-dist/2024-07-30/rustc-nightly-i686-pc-windows-gnu.tar.gz=456683fa10703ba8249f8b1735293c79edac0c32aec60c1a91315fb41c8e5ecc
-dist/2024-07-30/rustc-nightly-i686-pc-windows-gnu.tar.xz=fd5d9a7bf543d3c61ca85340961d5e17b42b37c35fe45c666c2a0e125548f42e
-dist/2024-07-30/rustc-nightly-i686-pc-windows-msvc.tar.gz=2b75a4e15d1f98f123ef74aecab3570296aeb7e35f18548a2b3d1735e01b06e0
-dist/2024-07-30/rustc-nightly-i686-pc-windows-msvc.tar.xz=1163178e95180725bd31b7dabf1e9a9788a8e7cc576dd53148cfec32443e64a1
-dist/2024-07-30/rustc-nightly-i686-unknown-linux-gnu.tar.gz=0aad8dd79beca26278e1c1847dde17ee22ae64b78f2b02be65e12bc126de699b
-dist/2024-07-30/rustc-nightly-i686-unknown-linux-gnu.tar.xz=a548e90fbce90c26b6700cff7964d72c7e959a6f317e891db4f91ce7cd187c41
-dist/2024-07-30/rustc-nightly-loongarch64-unknown-linux-gnu.tar.gz=654ec9040afb20d660603adcd31824efeacef0ae2d48d342bb9504bd2f723453
-dist/2024-07-30/rustc-nightly-loongarch64-unknown-linux-gnu.tar.xz=998407bc1303eecb1ef4c6b14862ffdf31fb0cf991f5d169a822a23627b29352
-dist/2024-07-30/rustc-nightly-loongarch64-unknown-linux-musl.tar.gz=5b4febf9a1802c2c756ef8a7693a9cfd83bf95284d79d9f9b9dd265234d6aebc
-dist/2024-07-30/rustc-nightly-loongarch64-unknown-linux-musl.tar.xz=dbc2a6417fabcfb37f4fa42d50391c1cb29f18d1771321088c08afdf0a0e4809
-dist/2024-07-30/rustc-nightly-powerpc-unknown-linux-gnu.tar.gz=2befcab4aa3e31064b87e4696aa2f1e76bd9c24067eb1921feb7f6497d58338c
-dist/2024-07-30/rustc-nightly-powerpc-unknown-linux-gnu.tar.xz=508a3c1241507a53a0d6b27df2171eaf0a4df903773b5592f005ee4d39d91287
-dist/2024-07-30/rustc-nightly-powerpc64-unknown-linux-gnu.tar.gz=c4e8da248306be350f7a89b2522e976a12ab89d5ae2e19157ed3b148e3948c50
-dist/2024-07-30/rustc-nightly-powerpc64-unknown-linux-gnu.tar.xz=5858e1cf6371f25ba3c381e07ba6f4551c2a13516011fc10dbdafc4caf1bff93
-dist/2024-07-30/rustc-nightly-powerpc64le-unknown-linux-gnu.tar.gz=3639bbb7aac353772171dcfaecd589352de3fd8cc7395e7628d7590830034af4
-dist/2024-07-30/rustc-nightly-powerpc64le-unknown-linux-gnu.tar.xz=3cad5f0b74fc3f5be70cf496c93054c50e8a3f92cfc894a2febfbecc382dcb55
-dist/2024-07-30/rustc-nightly-riscv64gc-unknown-linux-gnu.tar.gz=437fc8b815c09a3c5159735d9fec0e5d8dd64416149cb77c13a16863e6636412
-dist/2024-07-30/rustc-nightly-riscv64gc-unknown-linux-gnu.tar.xz=7bc2917e7816f7df1bc7faeda28010d247c923aba412b5ec1cc9c6757eec37d9
-dist/2024-07-30/rustc-nightly-s390x-unknown-linux-gnu.tar.gz=603e391a14c26a51f4f02020b5abbd307d29476fdc0689e5bf9570f2e6ac69a8
-dist/2024-07-30/rustc-nightly-s390x-unknown-linux-gnu.tar.xz=d04ea4e522cf1ecaa6b2f3edcb32155142378bc648aa159a574838ed2d58b794
-dist/2024-07-30/rustc-nightly-x86_64-apple-darwin.tar.gz=0ed639da01e58645eb33a75e020d57c58c92651d817e89574cb67bae5b298d35
-dist/2024-07-30/rustc-nightly-x86_64-apple-darwin.tar.xz=b4010f38396e7b8acd67cf2234c94ede11cf78a226a134c809d504e594037311
-dist/2024-07-30/rustc-nightly-x86_64-pc-windows-gnu.tar.gz=7ec8aba7a7581d59c7ceaffdd374852d08b17bc7e02674c5bfd4f47f4a0aee39
-dist/2024-07-30/rustc-nightly-x86_64-pc-windows-gnu.tar.xz=41c3ba0543220e11bc53282dd7d2a37acd6450a59683e1c83d2150dc798cfba7
-dist/2024-07-30/rustc-nightly-x86_64-pc-windows-msvc.tar.gz=67e5d75dda47c587a4be517db547354d1da0228110b7d5488d8822a7ef7cda20
-dist/2024-07-30/rustc-nightly-x86_64-pc-windows-msvc.tar.xz=4b5f0c4101a783dd313c0cd1435d7eccfeac97452afaeaf42ba975805541dc74
-dist/2024-07-30/rustc-nightly-x86_64-unknown-freebsd.tar.gz=09e12b5003969b768b5c06b3e3b41a64429e28c32790ff28c12b8c5814f350c0
-dist/2024-07-30/rustc-nightly-x86_64-unknown-freebsd.tar.xz=a4b3b402cf4beb3e7c7b9b6620f34d045ef42261514ae7d8483d3790d1dfd88a
-dist/2024-07-30/rustc-nightly-x86_64-unknown-illumos.tar.gz=c344d0c95aadac0e5e0100743b80768c9d0cd76b123ab07e6387ad1ea3e3efba
-dist/2024-07-30/rustc-nightly-x86_64-unknown-illumos.tar.xz=ac0a79660227fe163c796e6b816596299f6d8b32ba008ce30cde492709efb7c0
-dist/2024-07-30/rustc-nightly-x86_64-unknown-linux-gnu.tar.gz=4090ff8086317662d3def1bc92d51e6f2decd2c64f4b6ede38604fd5029d3d02
-dist/2024-07-30/rustc-nightly-x86_64-unknown-linux-gnu.tar.xz=e665bd4e3763b456576eaa45bcf188648cc6e6443ecdff8ef91a5c7649cbfd25
-dist/2024-07-30/rustc-nightly-x86_64-unknown-linux-musl.tar.gz=4fa994e08274599ae3bceb9310c584be89d11f231aad3e8fc1e2d6a6ddbb77bf
-dist/2024-07-30/rustc-nightly-x86_64-unknown-linux-musl.tar.xz=bd8d53403bf6337782bffc3050a46887fbe2568c850809c5b32c8d84492d2ee9
-dist/2024-07-30/rustc-nightly-x86_64-unknown-netbsd.tar.gz=606a430036fdda0b92dd4a4cb99830881389693e6ed02a01ddd51eaecdfdf463
-dist/2024-07-30/rustc-nightly-x86_64-unknown-netbsd.tar.xz=fa34273b20336b8b373f686c88ee297033f635895ad225a2ca5271b6da3d7dea
\ No newline at end of file
+dist/2024-09-04/rustc-beta-aarch64-apple-darwin.tar.gz=cb6487c102a7c5822be2236d79a2c4737b0ff284931c61607518a0de8d300abf
+dist/2024-09-04/rustc-beta-aarch64-apple-darwin.tar.xz=2556c7c07811195e94639f6d6556a0f49f3c267e0e3bfc44b1fdc555aac1ffe5
+dist/2024-09-04/rustc-beta-aarch64-pc-windows-msvc.tar.gz=c207a307bf10a50e2884f4d9408528a22703e1010dd921459541ee11aecc2405
+dist/2024-09-04/rustc-beta-aarch64-pc-windows-msvc.tar.xz=d6f99991029db32be7527dbe1a6ae840600db6d7497123156e6672f7a0e83aa2
+dist/2024-09-04/rustc-beta-aarch64-unknown-linux-gnu.tar.gz=b57cb4d25045e23f897078216776f244a73498ea89240077bda7a84c31c2f4fe
+dist/2024-09-04/rustc-beta-aarch64-unknown-linux-gnu.tar.xz=2c2b95c852114d7b18c3db13234ac56f933b70c3cf8b5ac9fce65415434961fe
+dist/2024-09-04/rustc-beta-aarch64-unknown-linux-musl.tar.gz=1f216d67bcd5d1e011bd2c6c69b6791c94e29cf7da3ab7dea82ff71a911e149b
+dist/2024-09-04/rustc-beta-aarch64-unknown-linux-musl.tar.xz=86abb27afb03e347abff65e4e34f1ec2e943af14f04f8cd9dd8666338147562d
+dist/2024-09-04/rustc-beta-arm-unknown-linux-gnueabi.tar.gz=842754febca1a5c6f7ccacf231621ba4578d72718a950ddedbf07a73594fa55f
+dist/2024-09-04/rustc-beta-arm-unknown-linux-gnueabi.tar.xz=3094887ecd5e3432e1ada0bba4a425213215c50680dc30d0c1d15ffda5bc62a0
+dist/2024-09-04/rustc-beta-arm-unknown-linux-gnueabihf.tar.gz=27192e3423f2b580d7927ae788cf778ff9c092e2eb7cdd5d16b41aa94d2bf03c
+dist/2024-09-04/rustc-beta-arm-unknown-linux-gnueabihf.tar.xz=e57767bd767964d51533e2310f177827842bf49176895280b3de3860caf351ab
+dist/2024-09-04/rustc-beta-armv7-unknown-linux-gnueabihf.tar.gz=b639bfce72277714769d36efab294ef3578573b93037160be7dff9f4a6e6b5ef
+dist/2024-09-04/rustc-beta-armv7-unknown-linux-gnueabihf.tar.xz=fce2b931641d51e88eb3e34d60bebe75384c1981654937b16f1333438d8b0696
+dist/2024-09-04/rustc-beta-i686-pc-windows-gnu.tar.gz=b58f7013b41044260ab2f9456940d9ce017dcfea06059fae8a672664f8ba00df
+dist/2024-09-04/rustc-beta-i686-pc-windows-gnu.tar.xz=c91958645f3c4cd562a5eb800ddb843aabfa2f067f5659313fdedeb270935bf8
+dist/2024-09-04/rustc-beta-i686-pc-windows-msvc.tar.gz=9a5075768fe2d42195c639d8c1066a020b573eae24c0c63e9a8876b78c39d673
+dist/2024-09-04/rustc-beta-i686-pc-windows-msvc.tar.xz=e76c27a8892a5b7a74c4d18d10c745af226711dbf62450378a3034a706624ce1
+dist/2024-09-04/rustc-beta-i686-unknown-linux-gnu.tar.gz=c10ffb2db62b113af1feab8625f1d88d31c1d4a4246d00e19a3588c9f69c0164
+dist/2024-09-04/rustc-beta-i686-unknown-linux-gnu.tar.xz=0496fbfa32d6c22929fe94ae5dcaabc47d31d7482f0fe6748ef7b7eb7443b775
+dist/2024-09-04/rustc-beta-loongarch64-unknown-linux-gnu.tar.gz=64b55368e8044ea44588c98f1529f46d65f7607ebf2fa2d50785abecfb37c188
+dist/2024-09-04/rustc-beta-loongarch64-unknown-linux-gnu.tar.xz=e03528ee7e4e92d666199ebcdde7d10f1d0fbeb2766217fd95f98da93bc361d0
+dist/2024-09-04/rustc-beta-loongarch64-unknown-linux-musl.tar.gz=eeb913008ecfbaaa76b7690b2e68bd1e70efc1afda19f44a1aa551a76e4b536a
+dist/2024-09-04/rustc-beta-loongarch64-unknown-linux-musl.tar.xz=c94c3545fa2a491763b1e593419034294c57a3df2ca8064db0b11d2e82e76c85
+dist/2024-09-04/rustc-beta-powerpc-unknown-linux-gnu.tar.gz=54c97827079aa7646cf206517f603487f4634ab1a17f2a7882b0cd3d6ffae8db
+dist/2024-09-04/rustc-beta-powerpc-unknown-linux-gnu.tar.xz=ee98a0e07989de836ff8ff4e768c6f0f13aa15150d1b59543297f31b2768a5fc
+dist/2024-09-04/rustc-beta-powerpc64-unknown-linux-gnu.tar.gz=a0fcd0f7af5b05a22d9be0abb6f3aa44c028c2606195163d2ad4b0352455ed1f
+dist/2024-09-04/rustc-beta-powerpc64-unknown-linux-gnu.tar.xz=cf35d480a6c0b439d29baacc4ee4087c4d7b5c1b4050302f3146f0bdbffcd472
+dist/2024-09-04/rustc-beta-powerpc64le-unknown-linux-gnu.tar.gz=ef19ce4d791b1caad30bc5af9e30494161f343d936a3300eb0d7c5e8f37db441
+dist/2024-09-04/rustc-beta-powerpc64le-unknown-linux-gnu.tar.xz=12adfd58c851d1f7bb23c5698abf6dffa2c26348df55fbb518c27497f7ebdf17
+dist/2024-09-04/rustc-beta-riscv64gc-unknown-linux-gnu.tar.gz=818151529f1e445f9202d0092f09f02818a2c52ad6814a89b2bbfcb0227c5202
+dist/2024-09-04/rustc-beta-riscv64gc-unknown-linux-gnu.tar.xz=e195d07d37699d860ce97422bba7f68166292103cedf4932b3ba8c0d9fa7e186
+dist/2024-09-04/rustc-beta-s390x-unknown-linux-gnu.tar.gz=d4a73ddd7eafdffe7f23720a7202f48676ae0bc49248d3a455c997d718730c5f
+dist/2024-09-04/rustc-beta-s390x-unknown-linux-gnu.tar.xz=475bb6e51f37fc769480345982e14afeee099cdf769773d0d0215d01fc77ce41
+dist/2024-09-04/rustc-beta-x86_64-apple-darwin.tar.gz=c061d06da7d4a283136d8e80f307c1ef4157739898776f5579b8d92980be0775
+dist/2024-09-04/rustc-beta-x86_64-apple-darwin.tar.xz=330b580c90ace563c96db64f639668284d8ede835870acf76b106d4c4913f476
+dist/2024-09-04/rustc-beta-x86_64-pc-windows-gnu.tar.gz=27f9e3c2e9380c689ab0c5e8438f1969261a30445e9b2d38efa9417fba1f4ea2
+dist/2024-09-04/rustc-beta-x86_64-pc-windows-gnu.tar.xz=62fc92dac7be442dcf306ae1baef471447b80a6a221502bf7b14b249dd599db7
+dist/2024-09-04/rustc-beta-x86_64-pc-windows-msvc.tar.gz=c52202bf41aafb517959e01cac2e4bbb53144aa0164f9b31e7b9db0af32be6c6
+dist/2024-09-04/rustc-beta-x86_64-pc-windows-msvc.tar.xz=24db84f0de7573812fe36fed5653fc117c80fc35b02a9340f746ded6a11d3bc0
+dist/2024-09-04/rustc-beta-x86_64-unknown-freebsd.tar.gz=406f8a37572376fec7563664043b4fc3b0e7a48c738b6ef862da3fc41f33b1d3
+dist/2024-09-04/rustc-beta-x86_64-unknown-freebsd.tar.xz=93fa021ca3973a52cbccd51771536e2b9a355eae4f4ab95c7168f4af79e96d4e
+dist/2024-09-04/rustc-beta-x86_64-unknown-illumos.tar.gz=a2a5942342b2f5dc7a196500210075ac695f106a18fd487a3c694847013454f3
+dist/2024-09-04/rustc-beta-x86_64-unknown-illumos.tar.xz=c8b63f35f30bb1d6adb49834b3a42dfc07c27042e8411f1b4777adced6193298
+dist/2024-09-04/rustc-beta-x86_64-unknown-linux-gnu.tar.gz=145c5d6e0edb688dbe59f9c638959e11718e0bdc625db76bac1d2836efd9f116
+dist/2024-09-04/rustc-beta-x86_64-unknown-linux-gnu.tar.xz=82845313e17067dac361eada63fdf2479fc177e8aa97aba5cb40a50861e276bc
+dist/2024-09-04/rustc-beta-x86_64-unknown-linux-musl.tar.gz=8351011105a5a338adbd2433ff5aa24cd038a67c0f0d040e4b92926d4aecd28e
+dist/2024-09-04/rustc-beta-x86_64-unknown-linux-musl.tar.xz=b2a972069142d5fdab775fd7709d4bc85b1c2c4167e9c455d2ef1b72cc207fd1
+dist/2024-09-04/rustc-beta-x86_64-unknown-netbsd.tar.gz=327501931ce36eb5613e5e77fb5356ff24f60078516473cd7f664bc970aee994
+dist/2024-09-04/rustc-beta-x86_64-unknown-netbsd.tar.xz=6d940ec725fa4931c914c291977f63828fe71e9763a3b8195dda668541c9122f
+dist/2024-09-04/rust-std-beta-aarch64-apple-darwin.tar.gz=9bf325e98fa60fcb7d4f09b796f2fe0e7e7c54e83ffba6d5cf30776a0346972d
+dist/2024-09-04/rust-std-beta-aarch64-apple-darwin.tar.xz=45d632045f5e3f8150d82fdc5163aea1d5ad785cd16da2d46293581b09bda895
+dist/2024-09-04/rust-std-beta-aarch64-apple-ios.tar.gz=c42f808164d79e023dc4186e47a6032c0877536a0c9459f3e871c66c129b0f75
+dist/2024-09-04/rust-std-beta-aarch64-apple-ios.tar.xz=9bbe6ae21530fb0555472f9a540b7791d5dce059439608d797507057199e696e
+dist/2024-09-04/rust-std-beta-aarch64-apple-ios-macabi.tar.gz=ae8005ea419f9f19be0c2603529d8801dc77e5344c72c1bd42eed81046fe5113
+dist/2024-09-04/rust-std-beta-aarch64-apple-ios-macabi.tar.xz=0053948699aba18b2bee7473f335940573aaf4bad6aabb00f28f2a335d280dab
+dist/2024-09-04/rust-std-beta-aarch64-apple-ios-sim.tar.gz=5adc7721f8f7fc0537b11a28ee2df6d90b96222a07590c84fab4dbefe33087d1
+dist/2024-09-04/rust-std-beta-aarch64-apple-ios-sim.tar.xz=4f3a9b61500ef3a38961288784c61a520baabfa597e997195007e0e229d1e4bf
+dist/2024-09-04/rust-std-beta-aarch64-linux-android.tar.gz=7192a628d6605b437a7203c18d48ac9a5af4879674117e9aebafb5029a10e069
+dist/2024-09-04/rust-std-beta-aarch64-linux-android.tar.xz=845177bda3220a534b20c66cda3bf27b0681c2977dfbcedeaf41022bc518f832
+dist/2024-09-04/rust-std-beta-aarch64-pc-windows-gnullvm.tar.gz=1a0ced7e1fbcdd38fcb33f1753f3af8b23f075d4ce38c3d1256ba142ddf80a47
+dist/2024-09-04/rust-std-beta-aarch64-pc-windows-gnullvm.tar.xz=75272f629adfaacb58c511163ae9b73714fe3f60d5e39b4cd996a42226626518
+dist/2024-09-04/rust-std-beta-aarch64-pc-windows-msvc.tar.gz=3b19e6dca8515f28a2325d7cf2f098e82e194d4418fce7c3caa94c9c08023646
+dist/2024-09-04/rust-std-beta-aarch64-pc-windows-msvc.tar.xz=138e8e1a85efb4f66ec878db18dfa48681f3045589c7b9a749afd0104dafd278
+dist/2024-09-04/rust-std-beta-aarch64-unknown-fuchsia.tar.gz=6da128ca58f46d2608c4d9630c09de263b853f9fe8b6fa41def0749e99a128e0
+dist/2024-09-04/rust-std-beta-aarch64-unknown-fuchsia.tar.xz=67a2c04a9f4947b4c313220150521f494364c5e589ff23a4584fa60b924ae095
+dist/2024-09-04/rust-std-beta-aarch64-unknown-linux-gnu.tar.gz=85ccd5a6e81caa63d4d4cfe55eead8a3829a5636d41f7640ea393bf7652eec28
+dist/2024-09-04/rust-std-beta-aarch64-unknown-linux-gnu.tar.xz=fb91518e70808c659f6f078c0094ca471e4e4f5d81c29c1bdc8907f6bdffc64f
+dist/2024-09-04/rust-std-beta-aarch64-unknown-linux-musl.tar.gz=410b24f1372f84d60804b4bcf20fa2025adaee3c56ab7dabda1e320809acafdb
+dist/2024-09-04/rust-std-beta-aarch64-unknown-linux-musl.tar.xz=64d7fa38af8a1c38e42bc9b9ab909f476d3388b7d02a21ba92519145cb3a3df8
+dist/2024-09-04/rust-std-beta-aarch64-unknown-linux-ohos.tar.gz=f4722b2a656d4f87bd13d4c8da6116e993e916114c55a2fd1a588e51dfde4ab0
+dist/2024-09-04/rust-std-beta-aarch64-unknown-linux-ohos.tar.xz=cb9150701f21de444addcdc9a53c83eeed3aaa3bc447e8f6358825a2f889bff2
+dist/2024-09-04/rust-std-beta-aarch64-unknown-none.tar.gz=26cf0407f17db7645fc1a4051d08246f1325b17941dd5139cb69b782498aa043
+dist/2024-09-04/rust-std-beta-aarch64-unknown-none.tar.xz=9dcdfd018e2ca6f21d0689adb152917a8695c2f14c4f6a53a5b52280219c2540
+dist/2024-09-04/rust-std-beta-aarch64-unknown-none-softfloat.tar.gz=1d1e555bb8af601d8df16b80dd263391a4c0805e1203c618fb370de1911a5a17
+dist/2024-09-04/rust-std-beta-aarch64-unknown-none-softfloat.tar.xz=078d88a6d4882696b3764d10dbd10e0d756752255096690e895903cd83265c70
+dist/2024-09-04/rust-std-beta-aarch64-unknown-uefi.tar.gz=5933f618e5c99e06c8556871a85016eba58f6de1056468a1ad47823105908fba
+dist/2024-09-04/rust-std-beta-aarch64-unknown-uefi.tar.xz=322f61ff7a6f6b261bbb9c592f50a39fa179c1f870d911a57b2afda7d7b2d196
+dist/2024-09-04/rust-std-beta-arm-linux-androideabi.tar.gz=e66bc47a75e12569032c81f6c950513e3fc78cf75e496e9873792b4c83f3dca1
+dist/2024-09-04/rust-std-beta-arm-linux-androideabi.tar.xz=9a84da40c9e5fb55e1ebad0dc9b724fe9d71d86bea0d2227315590f290fdce13
+dist/2024-09-04/rust-std-beta-arm-unknown-linux-gnueabi.tar.gz=3e8b535ec051eaaf63490649b1258ae64f1786abca6967bdc3eb6c6da96a4d81
+dist/2024-09-04/rust-std-beta-arm-unknown-linux-gnueabi.tar.xz=4936561a884b3b725a9b78651ea05a36da5e643be4e574416e12ba1c1e5f37d9
+dist/2024-09-04/rust-std-beta-arm-unknown-linux-gnueabihf.tar.gz=00eb51ffccdac33a39da37878104dded2c5efa01da5adf8bd932a0d9fb49d17b
+dist/2024-09-04/rust-std-beta-arm-unknown-linux-gnueabihf.tar.xz=3eb187c4a6f416672a8a36997aca5f04bab9ec6aee3a0d1f4ad5a0ed950605c3
+dist/2024-09-04/rust-std-beta-arm-unknown-linux-musleabi.tar.gz=66752ad65876dad43c19973f8967a098236f2605d2aa82df5b0f040247e049c3
+dist/2024-09-04/rust-std-beta-arm-unknown-linux-musleabi.tar.xz=f508b8c7956209c87259b38bebe5576ca8a5662a4d4747941082dd39d991610e
+dist/2024-09-04/rust-std-beta-arm-unknown-linux-musleabihf.tar.gz=926f2839c6627c822aa9f494e99030873987b6fca66364cc12ba468928a93b9c
+dist/2024-09-04/rust-std-beta-arm-unknown-linux-musleabihf.tar.xz=e2be0999ea8df01c1029b0976861162c9c60e41a87b4097345f2c5822777ee2b
+dist/2024-09-04/rust-std-beta-arm64ec-pc-windows-msvc.tar.gz=ec912c9e372cd0ae1a754305f0645580cf40f9742c4cbcc54952e613d47f595e
+dist/2024-09-04/rust-std-beta-arm64ec-pc-windows-msvc.tar.xz=f86091e5d806a9b4efa388e036ee69fa63fca68feca174c6670cd04966e2725f
+dist/2024-09-04/rust-std-beta-armebv7r-none-eabi.tar.gz=d51aa780c5df5b8b2e1fbbe97f79914ed083ea13528c43cca797ab8931a418d2
+dist/2024-09-04/rust-std-beta-armebv7r-none-eabi.tar.xz=19cbb2d1d8a6a3a33669da9fab7eb48f78f0682d777d2c2f188daf6d91895bc7
+dist/2024-09-04/rust-std-beta-armebv7r-none-eabihf.tar.gz=a1ae798b4eaf206510c33d5af1d4c99ed553fce89413449a5f82d5b80a2558aa
+dist/2024-09-04/rust-std-beta-armebv7r-none-eabihf.tar.xz=a0cb421635b927e5b255238658c9f9f5a0b2da60e05c993ecbda35af9318d6bc
+dist/2024-09-04/rust-std-beta-armv5te-unknown-linux-gnueabi.tar.gz=5f9995804004211baefab1d230089a5719bce40b632bd3380044142a89ae5f2d
+dist/2024-09-04/rust-std-beta-armv5te-unknown-linux-gnueabi.tar.xz=66f410541f2f53d44b2a2931b10a229c8143d6e9caabadea2df40704aad71854
+dist/2024-09-04/rust-std-beta-armv5te-unknown-linux-musleabi.tar.gz=64b62816adc9574f6961832a4c469e1103057ed553a4c42796e3af4962dc694a
+dist/2024-09-04/rust-std-beta-armv5te-unknown-linux-musleabi.tar.xz=3c0b3741af7f9b50d041dd52fe86fb4144c295632a6eba0197e77ac4ca94ab27
+dist/2024-09-04/rust-std-beta-armv7-linux-androideabi.tar.gz=aa3d37e6fc483c798a9debecf2ae7609609d0560baebb90733582b9bee15c493
+dist/2024-09-04/rust-std-beta-armv7-linux-androideabi.tar.xz=ed88cf7c141efd01eceb81b3b85e4eef38f559d8652d2fc4bf3395f4e3d2ef48
+dist/2024-09-04/rust-std-beta-armv7-unknown-linux-gnueabi.tar.gz=f8b34e2dd9bb5b2ea008bf6a69944da389d8d086a1ece57c1572c749717f4df8
+dist/2024-09-04/rust-std-beta-armv7-unknown-linux-gnueabi.tar.xz=7ae6076c42fecf7b92305af4220abd3d724d49d96def617a67db1ef298b74bb5
+dist/2024-09-04/rust-std-beta-armv7-unknown-linux-gnueabihf.tar.gz=4e13553b0288f4cd046372c080f4968a2b69bcb489f6929e98e72682b601d4cc
+dist/2024-09-04/rust-std-beta-armv7-unknown-linux-gnueabihf.tar.xz=dbaeb0445cfc110d7879a23ea7c4034cebb4158cd9781d8719f51864356a15d4
+dist/2024-09-04/rust-std-beta-armv7-unknown-linux-musleabi.tar.gz=164fa06abffc38aaf81c86aeb50fde51c96d713bb78d759a6f7e668c7967bdfb
+dist/2024-09-04/rust-std-beta-armv7-unknown-linux-musleabi.tar.xz=2ec4d5e339593555d02ea738ae1815e27d108fce5faeffd503308780c80a1a8d
+dist/2024-09-04/rust-std-beta-armv7-unknown-linux-musleabihf.tar.gz=36a09d9287c9d89b3946dc6aea2ce846e754ca2b07b667035f62e8d00c81587c
+dist/2024-09-04/rust-std-beta-armv7-unknown-linux-musleabihf.tar.xz=573316d483a27930bd1423ae8c1f2624dba141865150a41a5be317cc53fd850a
+dist/2024-09-04/rust-std-beta-armv7-unknown-linux-ohos.tar.gz=487feddaa3b11ad15b544e3338f4dfeb1f5297ce5d851dec1df36eee7bc016a2
+dist/2024-09-04/rust-std-beta-armv7-unknown-linux-ohos.tar.xz=866f612bc4fce03e851eb0b370282b35b066018c2b2467d265cbdde4bcc8afbd
+dist/2024-09-04/rust-std-beta-armv7a-none-eabi.tar.gz=3b2f1fefd2d97006264e5ce50839c8c22e9f6553f639e95c8bcc5bd01c54bead
+dist/2024-09-04/rust-std-beta-armv7a-none-eabi.tar.xz=55294ba0b8da663399c427b57157f4a3e43b117c77e011801410a9bfb62584a0
+dist/2024-09-04/rust-std-beta-armv7r-none-eabi.tar.gz=60ef291da36a614ddfd38c8bac0519113dc1203603181ba3a581df074fb62f07
+dist/2024-09-04/rust-std-beta-armv7r-none-eabi.tar.xz=6dde05a2b3a57ae340f699f959e7032bb6e53cf7e1ea24bf1dd88766dba2dcdf
+dist/2024-09-04/rust-std-beta-armv7r-none-eabihf.tar.gz=cc2ae41c8c8ee69f26eb55a033e5c6c23ec1e968aaa4c2e03357b62056176725
+dist/2024-09-04/rust-std-beta-armv7r-none-eabihf.tar.xz=dc7d1e0637369b0a32f8730a771e4b059ce45131b51beb276de8c03e153834b5
+dist/2024-09-04/rust-std-beta-i586-pc-windows-msvc.tar.gz=d6ce6f7d1412c1e0ec60a09c9db3d9bcbd0075617dd1756fa82e93d3df0ef8e4
+dist/2024-09-04/rust-std-beta-i586-pc-windows-msvc.tar.xz=60ff61cf60ac63a6c1ce3c6558351e873968ea1f812afdc7516ae5d19d85e54e
+dist/2024-09-04/rust-std-beta-i586-unknown-linux-gnu.tar.gz=4f5204d8d51ecbf0768419076c94dde6e0c776a9403e3e108866eec3faa68d06
+dist/2024-09-04/rust-std-beta-i586-unknown-linux-gnu.tar.xz=3ba0815668b11d682a54bfc4731aca5f7a821d77ab8ac32f9922bf9d684d72b4
+dist/2024-09-04/rust-std-beta-i586-unknown-linux-musl.tar.gz=ac1094f3e22829c4e3e27a91dae48f84ab2bca4373a6e851bdee807887e145ab
+dist/2024-09-04/rust-std-beta-i586-unknown-linux-musl.tar.xz=6547347750eefb619ac15256a3e1ef09c3ee633d73b23aae239cfcf4261f0d16
+dist/2024-09-04/rust-std-beta-i686-linux-android.tar.gz=af1e7557a1008392a0c2eee4f9e6b26ca56b21be2838ff4a4e3784363b1c3423
+dist/2024-09-04/rust-std-beta-i686-linux-android.tar.xz=b5d395b1c6994447b3358058aaf2219f952cb9fe6d5df0d8a533b9c2ed84134c
+dist/2024-09-04/rust-std-beta-i686-pc-windows-gnu.tar.gz=a0c0535feb405bf313035cdbc690fd80c18e1975ef0da2fcaeaeab66eb8ee461
+dist/2024-09-04/rust-std-beta-i686-pc-windows-gnu.tar.xz=85b08876c40d2bc1b44bf7d64319d1dae3af2dbd75cf3e3f37b3ea20bd21209c
+dist/2024-09-04/rust-std-beta-i686-pc-windows-gnullvm.tar.gz=60c37fb7de68381a3665728eb6a74ea017d81e2dcae11acf683cebcef7267487
+dist/2024-09-04/rust-std-beta-i686-pc-windows-gnullvm.tar.xz=a97edc7de6792da17dbcb6b5a67da4aa79784921c2b160185b2c8a806bd4945b
+dist/2024-09-04/rust-std-beta-i686-pc-windows-msvc.tar.gz=ea25bfabaad2bc02b0d37672bdf9357f317fd27031ef6039460e25c066917b11
+dist/2024-09-04/rust-std-beta-i686-pc-windows-msvc.tar.xz=ef65a47d79945d6375347c9889c3ec3250d4635e1918689cc1f992b7daf4f547
+dist/2024-09-04/rust-std-beta-i686-unknown-freebsd.tar.gz=5c4ca0b3bca99fc468bc7ada8ef1d202e9be8ba9808298485654ceab545538e8
+dist/2024-09-04/rust-std-beta-i686-unknown-freebsd.tar.xz=59ffa74e46e807cacd4ea0a1b16ce0ec7152c4458ad9f86feea82162b1c53da6
+dist/2024-09-04/rust-std-beta-i686-unknown-linux-gnu.tar.gz=dc535c0b1fe81cc6d1bbd8fecbc0625cb85c44a6f10dd8641fb8ae88083febc5
+dist/2024-09-04/rust-std-beta-i686-unknown-linux-gnu.tar.xz=624ce72e0b60a7b0d9a06b6925fd0e9a3bd50d9d7ed59db4a16145ff5381c232
+dist/2024-09-04/rust-std-beta-i686-unknown-linux-musl.tar.gz=6d43cf9f2dc34205616b17eafa8bf28f951de538e6d80ab4993d9b840b72ba49
+dist/2024-09-04/rust-std-beta-i686-unknown-linux-musl.tar.xz=b397f611d609167ddf2b5699d7cfef9da9c6c78988c7ca2c32b2f81f6640eba6
+dist/2024-09-04/rust-std-beta-i686-unknown-uefi.tar.gz=878584e638e92902521231a4b578ae1828d1e06093104b6ceca9a22a6c05939d
+dist/2024-09-04/rust-std-beta-i686-unknown-uefi.tar.xz=2806b9124d6145b65bfefc2e72a8ec3f745d3972904b7a2546bcaf649028a332
+dist/2024-09-04/rust-std-beta-loongarch64-unknown-linux-gnu.tar.gz=eb2792e0b57b36ed03762eff460bfbb7d8b28aaa309702e7e6414eba0a7d0e63
+dist/2024-09-04/rust-std-beta-loongarch64-unknown-linux-gnu.tar.xz=c36d7526ad190b15a41a1695be4b813d09d649395b1e91bf6dadc336333c690d
+dist/2024-09-04/rust-std-beta-loongarch64-unknown-linux-musl.tar.gz=d891dc7b3c1d05a1c245076a6656f2ad33cba79073e36e8e1eb11ab0c0045cdd
+dist/2024-09-04/rust-std-beta-loongarch64-unknown-linux-musl.tar.xz=6dbbd097bba35b9f0465a6d6b4d19d8b4700dbeecc1b0919aa99c72cad564a0a
+dist/2024-09-04/rust-std-beta-loongarch64-unknown-none.tar.gz=54da489ea59169e39b50d0be0221e20cf03bdad413854e0f35f66c323bf4e88e
+dist/2024-09-04/rust-std-beta-loongarch64-unknown-none.tar.xz=4c360c531107de92b695dd389514dc0af053a04d28c566a06a25e467d5ab548f
+dist/2024-09-04/rust-std-beta-loongarch64-unknown-none-softfloat.tar.gz=7ce834710452cb0569cdd234698f647db87e774d3e964493e17017a81a417aba
+dist/2024-09-04/rust-std-beta-loongarch64-unknown-none-softfloat.tar.xz=3e554450f5107e02335fa14fc7c7a2a3d4718741001f0f4e43984a3c0841ddf4
+dist/2024-09-04/rust-std-beta-nvptx64-nvidia-cuda.tar.gz=e8c8607e58379162fe0ec072bd544c97d73619df88eb56aeccdf2ebd5357f1b3
+dist/2024-09-04/rust-std-beta-nvptx64-nvidia-cuda.tar.xz=1dd759c92e6c1f67d5b697e1034b4962434a17211383741d0cc71acda9fcf209
+dist/2024-09-04/rust-std-beta-powerpc-unknown-linux-gnu.tar.gz=83907d49dd4cf4f73c1295571400c9761bae7a3b2447c140a358a07710e28f93
+dist/2024-09-04/rust-std-beta-powerpc-unknown-linux-gnu.tar.xz=f1ec605497fb3d7d364f2dfb7bc5c4898940518c1712b0271372ee608d61fd34
+dist/2024-09-04/rust-std-beta-powerpc64-unknown-linux-gnu.tar.gz=ac2b94c0f76c1f23be43880c01aab0a45d47e48a6c53b5dcfcf4e9507aa481e9
+dist/2024-09-04/rust-std-beta-powerpc64-unknown-linux-gnu.tar.xz=129ff2031d8ae69c34e944516bb47e093a2f2b47972bd401337fc1dc8b0f2b93
+dist/2024-09-04/rust-std-beta-powerpc64le-unknown-linux-gnu.tar.gz=2dd17129ca857bfa97d8ae3429984f80a116cc9f967809b7e5bdcc5845398a30
+dist/2024-09-04/rust-std-beta-powerpc64le-unknown-linux-gnu.tar.xz=06426a601db3dfc60f01b03bc201d21cc6bdc9b633a564e7025518decb91fea1
+dist/2024-09-04/rust-std-beta-riscv32i-unknown-none-elf.tar.gz=80bcbeed550e6ac30e9826cb801be5206d7937d2d940fca2d40ddabec62e2111
+dist/2024-09-04/rust-std-beta-riscv32i-unknown-none-elf.tar.xz=2994ee26443be51f11e8cc6e66aa2ee38e7f9440efbe0aa6aa2c513b3fe07f33
+dist/2024-09-04/rust-std-beta-riscv32im-unknown-none-elf.tar.gz=09f2b6dd18ebff39077a252e0d4b63b3557a49fb3a4f218f50f127aa44f653ec
+dist/2024-09-04/rust-std-beta-riscv32im-unknown-none-elf.tar.xz=156c0ef4be19442b8f59269815e570faa464332ccd2a8db91828eff9ab702ea7
+dist/2024-09-04/rust-std-beta-riscv32imac-unknown-none-elf.tar.gz=037ceaaf4b1356f72d16f2a6c0dfe50b1df8a82743da79262b020712ffcfb7ff
+dist/2024-09-04/rust-std-beta-riscv32imac-unknown-none-elf.tar.xz=a6e6f00d5df339ac19ebe2c661a5a4ec9b648328767db864b3db1bde0b330bfe
+dist/2024-09-04/rust-std-beta-riscv32imafc-unknown-none-elf.tar.gz=6da55a90ba454e77dd2c90d5d5c5ed833befab415ba65adf27d8e36645b189c0
+dist/2024-09-04/rust-std-beta-riscv32imafc-unknown-none-elf.tar.xz=9213accb8bc2b3a678c3b3cb4300015b1cc52798157e3898d99699b96bac486d
+dist/2024-09-04/rust-std-beta-riscv32imc-unknown-none-elf.tar.gz=5504f5fe7b45570922f7901476b8ac1eb28e9a7643bf5ace75bb368a644a05f8
+dist/2024-09-04/rust-std-beta-riscv32imc-unknown-none-elf.tar.xz=50109eb03c075ced8ebcff0909450f173e00491efece5874b8b59ad750bfc9ad
+dist/2024-09-04/rust-std-beta-riscv64gc-unknown-linux-gnu.tar.gz=1ed3d0c1066b52dd2174ed45635386ff22798de8cee92765503fbcf71463094a
+dist/2024-09-04/rust-std-beta-riscv64gc-unknown-linux-gnu.tar.xz=e2b22ed31374775441c6d80da80a52bc7558a1363776363ae341e78d0abf34fb
+dist/2024-09-04/rust-std-beta-riscv64gc-unknown-linux-musl.tar.gz=eff055a0e773741c4c2101791feea744c57ae95c50ad32ebec616daab1d098c8
+dist/2024-09-04/rust-std-beta-riscv64gc-unknown-linux-musl.tar.xz=680c9c2de4c7abf391d073709988593eb1daffe19876bd789a0f810f9d8d8458
+dist/2024-09-04/rust-std-beta-riscv64gc-unknown-none-elf.tar.gz=ae71d4f0789955cc883948c75aad9e492e37c206a64561705c8b7a9fec243f3e
+dist/2024-09-04/rust-std-beta-riscv64gc-unknown-none-elf.tar.xz=f41ecbae85295dda2dde95653a059be1852eacc28c175d36cb82cdacbf97a5e9
+dist/2024-09-04/rust-std-beta-riscv64imac-unknown-none-elf.tar.gz=1db39d0674e227b0fcacbc9de7aea52a349f515aaa8ea595cfbd91c6138e0b4c
+dist/2024-09-04/rust-std-beta-riscv64imac-unknown-none-elf.tar.xz=971c6dd1c7e3c6ab14d6d5f563edf974c87cbfd2a2028bced6e01175c8abafe6
+dist/2024-09-04/rust-std-beta-s390x-unknown-linux-gnu.tar.gz=029150a3c19afdafaff023ffd80f7aa1c2cfce7d7464339b0873a6e3da10a923
+dist/2024-09-04/rust-std-beta-s390x-unknown-linux-gnu.tar.xz=22a4612a5a7b38adb3e63ec8526444e51fe222c125c2ba51499987a3906b1cf5
+dist/2024-09-04/rust-std-beta-sparc64-unknown-linux-gnu.tar.gz=069c8fc749bc2ed94179af8e38849b83912c84cd551c4bf27f95e99def8ed0fc
+dist/2024-09-04/rust-std-beta-sparc64-unknown-linux-gnu.tar.xz=5b436df8a26688cc9853f5e12735187e9924a44101e21c4e59fc3dd38778e39a
+dist/2024-09-04/rust-std-beta-sparcv9-sun-solaris.tar.gz=77f6b8e4760ea43aac97ebb177223ad943fbbcc55dc3656afa400d7d1ea35787
+dist/2024-09-04/rust-std-beta-sparcv9-sun-solaris.tar.xz=d2b3e49982ccdb966f420eaba9d582108b227f1acb485f0b176762871d41ef3c
+dist/2024-09-04/rust-std-beta-thumbv6m-none-eabi.tar.gz=5e511b55cc961482998cca16def2424e749cf83a46a52b235e902baf8a653cca
+dist/2024-09-04/rust-std-beta-thumbv6m-none-eabi.tar.xz=8491ec0a3233b04909ad307bf679d6a012fe153eb9ae544956c8fa87a57dd55c
+dist/2024-09-04/rust-std-beta-thumbv7em-none-eabi.tar.gz=9b4d4913146843b01b4b6b7d8e1230c01f764a2ae2433dbb3264bfad14d0b3c6
+dist/2024-09-04/rust-std-beta-thumbv7em-none-eabi.tar.xz=ee700f3dca7d811a230222627ecc6c22d9850151adf47c2a48fb840a079508aa
+dist/2024-09-04/rust-std-beta-thumbv7em-none-eabihf.tar.gz=d54ea14641f79deb2b661e1fe9e9ff56d85189da5ced0f96c16503892c4b367a
+dist/2024-09-04/rust-std-beta-thumbv7em-none-eabihf.tar.xz=cd1529c6f77a079fbf15bcf81d41b4f18a8572729975b2a3ac91e18841e93495
+dist/2024-09-04/rust-std-beta-thumbv7m-none-eabi.tar.gz=fe214540eafddf6dc65ca94f1dad3a12df9e92a157060a9c27a730d99a706b28
+dist/2024-09-04/rust-std-beta-thumbv7m-none-eabi.tar.xz=2b9b1289855f7d9520eab69bc8c4e8505857e44b1e498968e47e3e847ae5a7da
+dist/2024-09-04/rust-std-beta-thumbv7neon-linux-androideabi.tar.gz=dc28759dc83a72d5c8505e90abb98ee55fb0ac53736422c95b631e063f566e5f
+dist/2024-09-04/rust-std-beta-thumbv7neon-linux-androideabi.tar.xz=b25c463af699783e8df43d7ccc5d1692d97e8a1ade8322dcf0cd74246d1d94b8
+dist/2024-09-04/rust-std-beta-thumbv7neon-unknown-linux-gnueabihf.tar.gz=bb8ebf0008749bafb9cee686c7b09db4e4585178b506bc9bec6508577bc98713
+dist/2024-09-04/rust-std-beta-thumbv7neon-unknown-linux-gnueabihf.tar.xz=afb9a8ed9a5dccb0c43eb6a920c647735648a1378413ff1fae754a7e5f972b06
+dist/2024-09-04/rust-std-beta-thumbv8m.base-none-eabi.tar.gz=b090d076b04e7894a94c1ed892825a3f6d27aa3908d40d1a66f098b9d53f4309
+dist/2024-09-04/rust-std-beta-thumbv8m.base-none-eabi.tar.xz=3213f7cb7365420b767779edc091a35f9e3a39e9439d0bf542dcc099eff25ce7
+dist/2024-09-04/rust-std-beta-thumbv8m.main-none-eabi.tar.gz=5d977dc47e7c04d1f729a2a153e2c37ceab7d9a049b111505146e82b7b3bc30b
+dist/2024-09-04/rust-std-beta-thumbv8m.main-none-eabi.tar.xz=8e9cef53163ff70ec8868d11d7c237cf40ced06852fcb193b3ef45232c3cd90a
+dist/2024-09-04/rust-std-beta-thumbv8m.main-none-eabihf.tar.gz=01f1916e4de4401ef0b7c43bfb0df72169f36ab09eda9ee923ef0d6608b8fafb
+dist/2024-09-04/rust-std-beta-thumbv8m.main-none-eabihf.tar.xz=1a9a9fe79884bd8e8e35cc8bcf3d1fb7a82ee4a40c630b78a302aabb047959f1
+dist/2024-09-04/rust-std-beta-wasm32-unknown-emscripten.tar.gz=66da8c5a7e579df020ef012747f9c8ce6a3094bdf43a99dc3763a9234eda3fff
+dist/2024-09-04/rust-std-beta-wasm32-unknown-emscripten.tar.xz=34ba780c992a10428fac49c9149d1f613fac221dd92866a93795543a991c29af
+dist/2024-09-04/rust-std-beta-wasm32-unknown-unknown.tar.gz=485304f0705ea8ef1a3516cd01e9b63e010af514edc03774cd87284367ed5e04
+dist/2024-09-04/rust-std-beta-wasm32-unknown-unknown.tar.xz=414608d21dd7cd268ad57a6be916b0be2c95433e2bc14083ff8c4a7a7cc8952b
+dist/2024-09-04/rust-std-beta-wasm32-wasi.tar.gz=c745c8682a54abe37c2734bf0c7931b6d10269eb56c07765e39dd289dab67e01
+dist/2024-09-04/rust-std-beta-wasm32-wasi.tar.xz=732c12837772531eabc44a7d4a545e130e2ae220d3670748fa2050cd4c65a18b
+dist/2024-09-04/rust-std-beta-wasm32-wasip1.tar.gz=2b54c587ddd908481f5561d6de60c7fdbef234ca2ecec4eb4d4791416038f7db
+dist/2024-09-04/rust-std-beta-wasm32-wasip1.tar.xz=799ee151f0aa3c5ec132f03c42152393d966c9249972967133edef56b30d66ae
+dist/2024-09-04/rust-std-beta-wasm32-wasip1-threads.tar.gz=120b8cad5a2a153bee58ccf81824e6a1c7c16befdd2785f963a9b2dfc350b9f2
+dist/2024-09-04/rust-std-beta-wasm32-wasip1-threads.tar.xz=5d74a8dc4731ab433cf796e7568122c7ca1463c648d2b49876ae1deaeaefa314
+dist/2024-09-04/rust-std-beta-wasm32-wasip2.tar.gz=911e60f2976d3b98dc9f6e82f72c459c5e07713e2dde2c7337569a71db2d1218
+dist/2024-09-04/rust-std-beta-wasm32-wasip2.tar.xz=947d312ec07c6190dcd4abeb493a2b67ac64a9a549ef30372c8eee7164c74883
+dist/2024-09-04/rust-std-beta-x86_64-apple-darwin.tar.gz=7b6e65885f14982f1112a2c0e8dd3266b1c4313276342ed98f2681432720b8c6
+dist/2024-09-04/rust-std-beta-x86_64-apple-darwin.tar.xz=cdbe462e3935c5a34415275afe830a6b5edae2fda84ed35e836ae868c884d19f
+dist/2024-09-04/rust-std-beta-x86_64-apple-ios.tar.gz=f75e7896ed5c9b64f817e9b2d6ed4d637e19ff26a14f72a570b4eff532f5b32b
+dist/2024-09-04/rust-std-beta-x86_64-apple-ios.tar.xz=60db5599bdad826b32637dfd2989daa90597b278ac14b42ede3a7c15aed119e0
+dist/2024-09-04/rust-std-beta-x86_64-apple-ios-macabi.tar.gz=3f57688112d2d80010636724acec5083bce0bc0a901f9ccbd76a09bb21de2b17
+dist/2024-09-04/rust-std-beta-x86_64-apple-ios-macabi.tar.xz=841dcf3eba0ad5b7bc8a4d55fabca80a1a27a3d697431c251b48912131148b6e
+dist/2024-09-04/rust-std-beta-x86_64-fortanix-unknown-sgx.tar.gz=96af596e4bc63519decc0e17005006aee8a2f22258d86b6efa25a94fbbe62f23
+dist/2024-09-04/rust-std-beta-x86_64-fortanix-unknown-sgx.tar.xz=4215a327f11bc7fa02546e69cb52c6c7bfe6a1ca602a6bf7a266e11937204bef
+dist/2024-09-04/rust-std-beta-x86_64-linux-android.tar.gz=80849fc95791de8cf98da9ebd405a4e268445b22b9413c8545870fe83f5891c7
+dist/2024-09-04/rust-std-beta-x86_64-linux-android.tar.xz=f849ad9d7ccc7eda06404e3bd67f150c3d8dfa66609405435fb2ba09c00ca136
+dist/2024-09-04/rust-std-beta-x86_64-pc-solaris.tar.gz=f871244a44131b1e2f56ad7c77ccb4e7433f39d6b248951f449914a65178bea3
+dist/2024-09-04/rust-std-beta-x86_64-pc-solaris.tar.xz=933b3b634b5caf57213be093977b0f56ba3609dc9407ac026079f75f4783642d
+dist/2024-09-04/rust-std-beta-x86_64-pc-windows-gnu.tar.gz=28ef28c4b17b5e8a20ae5f19feeb4643864f64ac8e9c68b84f8cec067317c339
+dist/2024-09-04/rust-std-beta-x86_64-pc-windows-gnu.tar.xz=1e40daa830d390d57c0dd23331849edf45adc0a35d120725bfd9fae43edf13e1
+dist/2024-09-04/rust-std-beta-x86_64-pc-windows-gnullvm.tar.gz=b9a6e290d7b9c71b4a33164116cc523654c3147168a04fc7608a27397c100944
+dist/2024-09-04/rust-std-beta-x86_64-pc-windows-gnullvm.tar.xz=a6e1db0945d1a5243caf2d1ad7d24b4dd16f8882d3e88118f203c91ff5e2cd52
+dist/2024-09-04/rust-std-beta-x86_64-pc-windows-msvc.tar.gz=8d70d70a645b36e6de01b08a34a28a995c73f91e8a285607a5516180d3a93350
+dist/2024-09-04/rust-std-beta-x86_64-pc-windows-msvc.tar.xz=d5a6fc72bf9dc0b7083d364358232a5df68b2b9f03a1a553bbeecf2a84936cb8
+dist/2024-09-04/rust-std-beta-x86_64-unknown-freebsd.tar.gz=01e159405178d883deb8eb09e9101826e7591c8d8fd6840133c0e8f77e00e395
+dist/2024-09-04/rust-std-beta-x86_64-unknown-freebsd.tar.xz=7fddda753b5f3e244de9427de6399052c81df87bd2b76d2c1f9a0fa4d1d1cddf
+dist/2024-09-04/rust-std-beta-x86_64-unknown-fuchsia.tar.gz=2c37eaef53b50d812205ed24de580165bfa800658ab9a9ea503667105119a544
+dist/2024-09-04/rust-std-beta-x86_64-unknown-fuchsia.tar.xz=8d1e3d290c5736c4e7a48a6b1a88ba18b9e68876638896b31b61917c6fcd2af4
+dist/2024-09-04/rust-std-beta-x86_64-unknown-illumos.tar.gz=83a57ec9e9696a63dadf9307e0cce117b92be8e9b7d17edfe410d38f75629202
+dist/2024-09-04/rust-std-beta-x86_64-unknown-illumos.tar.xz=3db6747b556581f02e0cf058b93538785d1eca9aaefe36dc8b7667428fa05ef7
+dist/2024-09-04/rust-std-beta-x86_64-unknown-linux-gnu.tar.gz=fe737fb11bd2a16b7636013f37041a35126f0bf8b2c562ac38384d45e49088c4
+dist/2024-09-04/rust-std-beta-x86_64-unknown-linux-gnu.tar.xz=a7a3f5245067b2967bbc4bd010ac3a6e9613cc9b6462c53cdcf0b91eab6cddbb
+dist/2024-09-04/rust-std-beta-x86_64-unknown-linux-gnux32.tar.gz=8b3fa007713d4e37de79d5662a3de446d378e00fc631478e465fb170447c49ea
+dist/2024-09-04/rust-std-beta-x86_64-unknown-linux-gnux32.tar.xz=c2dd95e94f9a9bc2d31e807a3b7cc5cb43a994cd4400ac1636ade3005344146b
+dist/2024-09-04/rust-std-beta-x86_64-unknown-linux-musl.tar.gz=a294420b029900027530932ebd29cbd3f17672fffc60128122473088329f8cb8
+dist/2024-09-04/rust-std-beta-x86_64-unknown-linux-musl.tar.xz=72a1c8052534e1b986ebd1bb5364de9e9e67353cfc6de7341f759d8da370bf2d
+dist/2024-09-04/rust-std-beta-x86_64-unknown-linux-ohos.tar.gz=7227b14f3148302d954756bd4df570289aa8dedd8d889b5399821356ac097f8a
+dist/2024-09-04/rust-std-beta-x86_64-unknown-linux-ohos.tar.xz=61cf15b98ba67fb648ee87901bc33644efc342c2b6401ab8b6a14cae755cbd8d
+dist/2024-09-04/rust-std-beta-x86_64-unknown-netbsd.tar.gz=61b604f112031aadd7ad87e535cbb4966c53099e276fc76d99fecd0e912b2e28
+dist/2024-09-04/rust-std-beta-x86_64-unknown-netbsd.tar.xz=428a0a6955266ac0e74b11bb4c58a461c041f13f241d5a2d698139b4b5839ad5
+dist/2024-09-04/rust-std-beta-x86_64-unknown-none.tar.gz=c8b29984bf2b6d77893cda301e55dd128da76bad7dd87c751aa5585add2262fd
+dist/2024-09-04/rust-std-beta-x86_64-unknown-none.tar.xz=1460566b927586f6afa531aa1cefa9aec0d4e829a08a151638a42c255b6a7ef3
+dist/2024-09-04/rust-std-beta-x86_64-unknown-redox.tar.gz=17503716bb940d50db15bd1b467fe03ff15474f1b0b162eb3f2891699d898768
+dist/2024-09-04/rust-std-beta-x86_64-unknown-redox.tar.xz=66007a1f995597a697747886eacbe38c9d6a588b1ed365e6b4b522c72bc7b8af
+dist/2024-09-04/rust-std-beta-x86_64-unknown-uefi.tar.gz=b612bac841c9f93bc6189971bf82df47e8730cf1696d2d6f3344be67a6c28f0c
+dist/2024-09-04/rust-std-beta-x86_64-unknown-uefi.tar.xz=3dd0f70f8f226160700a52c19aebc2f27801360a8d2882702c5a0be94560da3b
+dist/2024-09-04/cargo-beta-aarch64-apple-darwin.tar.gz=3efe0d5356824c1620e223686c81cf10b629db0a0c385c3177b5fe1866776b5c
+dist/2024-09-04/cargo-beta-aarch64-apple-darwin.tar.xz=07deeec79d74a39b0cf971bd980936eb476005bf0e832adef9e4521bba3c010b
+dist/2024-09-04/cargo-beta-aarch64-pc-windows-msvc.tar.gz=c9da3632a36a2db512015580bd20e0b5207f8a0d98ae093a99755e4c512215f8
+dist/2024-09-04/cargo-beta-aarch64-pc-windows-msvc.tar.xz=b0b9aabd90863c1671ad80955277c2f006654779837cb1358774b8189fba357b
+dist/2024-09-04/cargo-beta-aarch64-unknown-linux-gnu.tar.gz=cb862535909b1f0fea6ee40a6a888f2f860f95b8700b1d5167bd7a41b9e33958
+dist/2024-09-04/cargo-beta-aarch64-unknown-linux-gnu.tar.xz=b1ff8f714cda2c98a7129e861adcf33245bd84bdfbdcec9fb1a89545dcd033f7
+dist/2024-09-04/cargo-beta-aarch64-unknown-linux-musl.tar.gz=5c3659e979393c8c1dbe1a6ccb09eea412671363e228f0c7ab4bd4896cd48470
+dist/2024-09-04/cargo-beta-aarch64-unknown-linux-musl.tar.xz=0435e1332b1bc40a280fc867eab54e925135eba774c3bc0553a8bb100d644f59
+dist/2024-09-04/cargo-beta-arm-unknown-linux-gnueabi.tar.gz=6f7f079ef04c4b1d14864cba67ec650a3e43f3baa81fea1797d00067f22a72a8
+dist/2024-09-04/cargo-beta-arm-unknown-linux-gnueabi.tar.xz=549607bdeacd26fa770ecb00ce54cb3ea72c5568e65966c1fddc3a540b9f6e6a
+dist/2024-09-04/cargo-beta-arm-unknown-linux-gnueabihf.tar.gz=e23b18a2a86bca5320b66c54d43a54d90db1b787443cb0e04d66e9d7428fece7
+dist/2024-09-04/cargo-beta-arm-unknown-linux-gnueabihf.tar.xz=5968c534ce88a2574a4f59a0ced82df36aef9c7338ed9c718e85aad514a792f4
+dist/2024-09-04/cargo-beta-armv7-unknown-linux-gnueabihf.tar.gz=3170e39d306e797e5631884c629ecb33a54635056b5a71fbebe5372c1c34da37
+dist/2024-09-04/cargo-beta-armv7-unknown-linux-gnueabihf.tar.xz=76b729642fdba25c015e49e444e158170d3ed2ac0a533ba7c6095ecdc0862ba5
+dist/2024-09-04/cargo-beta-i686-pc-windows-gnu.tar.gz=c58826189772af945c9d40868e80d64359f4108afa06d150a3d350323b0eb8df
+dist/2024-09-04/cargo-beta-i686-pc-windows-gnu.tar.xz=1b644d661778bfcbec892eab17bee06861940037992821c4ded8321a69c0f6a8
+dist/2024-09-04/cargo-beta-i686-pc-windows-msvc.tar.gz=e026eac2c2e891976e085d26591d85000dccf3c3654f3edd65e99c6c0ba43574
+dist/2024-09-04/cargo-beta-i686-pc-windows-msvc.tar.xz=e7307b2e55302228c5036991ca6141a5202a16f43b0148607f3802fdc90aa0cc
+dist/2024-09-04/cargo-beta-i686-unknown-linux-gnu.tar.gz=0a00604bad2096cd0b0db59a1b41b5737696015a4ddc60f9b1132829a4cd0a5f
+dist/2024-09-04/cargo-beta-i686-unknown-linux-gnu.tar.xz=a623eecb18a21b2dc6a4b62876b8fa4fc467c53fdd0cfdac493f89d619be5aa7
+dist/2024-09-04/cargo-beta-loongarch64-unknown-linux-gnu.tar.gz=64955892d99d0e7f0042016d7a5e3ac87f89b6f514b1934611050f89aa5f6a28
+dist/2024-09-04/cargo-beta-loongarch64-unknown-linux-gnu.tar.xz=3c7c3061c466fc4a1eb836c97cab95d511778d77d220189a6a77f8e5b46e4888
+dist/2024-09-04/cargo-beta-loongarch64-unknown-linux-musl.tar.gz=be1c255840307bd24c2c8b5c92e2fa0eed6037daf3ed9597e17bc56f313ef506
+dist/2024-09-04/cargo-beta-loongarch64-unknown-linux-musl.tar.xz=d0e456bc8b64a0ee778e69eac75b6a258c37f7b2d06496a8dfcc47d91e1c2dd1
+dist/2024-09-04/cargo-beta-powerpc-unknown-linux-gnu.tar.gz=b9cd94c4ac9a11eece8712b325d08007b641d5da7487fd38b30dbaf0f3d1b5a4
+dist/2024-09-04/cargo-beta-powerpc-unknown-linux-gnu.tar.xz=68dd4a74494fe8f02781a2b338eff5f5cc78d66048eddd3ed7cc3e31dcecd2c8
+dist/2024-09-04/cargo-beta-powerpc64-unknown-linux-gnu.tar.gz=b464ad7a1233e3ad5129340e623a60d2ad0882843acbef60a9aed45a453ccac1
+dist/2024-09-04/cargo-beta-powerpc64-unknown-linux-gnu.tar.xz=1167f3d38628c01b11dfb9f66eacdf4cd519b46ea1b8c9d182a390e7d552a933
+dist/2024-09-04/cargo-beta-powerpc64le-unknown-linux-gnu.tar.gz=eb16d3791a79aa384326e2e79aeafd8d3e27adf4733a5bcca441e278e578b60e
+dist/2024-09-04/cargo-beta-powerpc64le-unknown-linux-gnu.tar.xz=d100dcb6437e87b3b687a7059dd932567855f68d962a109268fcce5a5aa688c6
+dist/2024-09-04/cargo-beta-riscv64gc-unknown-linux-gnu.tar.gz=ee771d98286302d4a8a93ba5165c342a2fbe770bf7758f8bbc490ad188d2e5cc
+dist/2024-09-04/cargo-beta-riscv64gc-unknown-linux-gnu.tar.xz=d2e9eb5a1800545eec4186b5252737f3b3a02d232473e6864e4c6fd752a69623
+dist/2024-09-04/cargo-beta-s390x-unknown-linux-gnu.tar.gz=b35ef65a54c9dd068a699f4210c0c88bd2777308fd7ddad3c7d0b9a1c994657e
+dist/2024-09-04/cargo-beta-s390x-unknown-linux-gnu.tar.xz=eaee5c891aab499438427c2c965c2c8f4471a3b051effee139f251f544ac4ac4
+dist/2024-09-04/cargo-beta-x86_64-apple-darwin.tar.gz=917ba277cb3f050fb3e65126b587245bf89891256faec33a57e2b1a064075534
+dist/2024-09-04/cargo-beta-x86_64-apple-darwin.tar.xz=179d6fe24981d477eb806ba714bd639750577cb9de2d152116e994d3955ade38
+dist/2024-09-04/cargo-beta-x86_64-pc-windows-gnu.tar.gz=6aa52989d1ccb25b03433dec436507455256cb1e2ed305ba747c342551d0778f
+dist/2024-09-04/cargo-beta-x86_64-pc-windows-gnu.tar.xz=bc0403c00fa2093f09d95b1ad091850b2450f4e1d7fac225a730d7363074806b
+dist/2024-09-04/cargo-beta-x86_64-pc-windows-msvc.tar.gz=5c1e018191c296ddc443699e48c4f1a3e700983fc45ea230172f35881d09e103
+dist/2024-09-04/cargo-beta-x86_64-pc-windows-msvc.tar.xz=f1b44ff315f5332815263d5b0a1cd06f852431acbf5cc902bb6723c3398e11d6
+dist/2024-09-04/cargo-beta-x86_64-unknown-freebsd.tar.gz=7da980ccdb2d6bc0946749fcceaed7124f311b38bf28cef0797ca85909f5d5fb
+dist/2024-09-04/cargo-beta-x86_64-unknown-freebsd.tar.xz=a935462749686fb68eac699ea67ef1afaa22ed0b147d2e4d0a6712f225341fa2
+dist/2024-09-04/cargo-beta-x86_64-unknown-illumos.tar.gz=ccc3d29e88482885090f6fb954518bcb0b6bd3f54283702df9e0e80b78454c01
+dist/2024-09-04/cargo-beta-x86_64-unknown-illumos.tar.xz=c0cb33e5088f2b9f5fe8bedb3915fec10e7f65563013b914e0738486b5e8ebab
+dist/2024-09-04/cargo-beta-x86_64-unknown-linux-gnu.tar.gz=84fdbbc0912c4020dd1baec1d603c5d5c1986c7b321d3d9c0c42184aa6347f15
+dist/2024-09-04/cargo-beta-x86_64-unknown-linux-gnu.tar.xz=8f8948750141c3ee8a50e575f196bd972876e784cf1793b256a5a9462c9e3d44
+dist/2024-09-04/cargo-beta-x86_64-unknown-linux-musl.tar.gz=9ef6b7450b94ce202f1b603151075bf8f595022f2c52f6bcd1c4a72423db2b80
+dist/2024-09-04/cargo-beta-x86_64-unknown-linux-musl.tar.xz=5b63b98d67e211057fbaeb1db3721b90252a331143ca267bb30eebca4ac01cdd
+dist/2024-09-04/cargo-beta-x86_64-unknown-netbsd.tar.gz=69d500e2fca1c44fea31310b0636a9af009d4ec96b5ed2335864c47350fa7b59
+dist/2024-09-04/cargo-beta-x86_64-unknown-netbsd.tar.xz=7da3c2641f0ecdbd8b770402356416750a52265a6848d3734fce2195c889768a
+dist/2024-09-04/clippy-beta-aarch64-apple-darwin.tar.gz=15395c04235f2475d5e41371e2797f181af71275f82f04fbb885b1cd7a197f45
+dist/2024-09-04/clippy-beta-aarch64-apple-darwin.tar.xz=8be6fb9e0cafcd262594cfc4a36807bede9e158cbf7eb38c0f25144bf3bfdd1e
+dist/2024-09-04/clippy-beta-aarch64-pc-windows-msvc.tar.gz=b043e41facce81a5fc607f2268330b279d7e26975e409158ac2cbbc841d10f85
+dist/2024-09-04/clippy-beta-aarch64-pc-windows-msvc.tar.xz=ba41705b213f863416120c28fa4a7959cf41e261cce8233b12fd91aa0157d601
+dist/2024-09-04/clippy-beta-aarch64-unknown-linux-gnu.tar.gz=b093269be813ea76964de2c03c7380bcefab1e7d6e31c93fd3f374619a99a5f0
+dist/2024-09-04/clippy-beta-aarch64-unknown-linux-gnu.tar.xz=06d71273208fcbfa5958987038eacda066d4518b5cd6bd7405a981bf841868ae
+dist/2024-09-04/clippy-beta-aarch64-unknown-linux-musl.tar.gz=aa159e61c4986def9d27f55504d822d6023c277a546e95079161577ae2991df4
+dist/2024-09-04/clippy-beta-aarch64-unknown-linux-musl.tar.xz=7a3023b98a1c72c993d176c85f4790b234c41f35184636d29deeba40d51587a2
+dist/2024-09-04/clippy-beta-arm-unknown-linux-gnueabi.tar.gz=8e30a0377b780311bf51bdc48dcf233a344cb2fd9ae9aec174bc87d29f94c34b
+dist/2024-09-04/clippy-beta-arm-unknown-linux-gnueabi.tar.xz=488c28d10f45a498b1054fad9feb72a848d0668cd12d29b3a81f5569b1145018
+dist/2024-09-04/clippy-beta-arm-unknown-linux-gnueabihf.tar.gz=db25c9aa95b08acdaeaba407367a823e9e2094b0616c80b0c8a84d7c2f6c4292
+dist/2024-09-04/clippy-beta-arm-unknown-linux-gnueabihf.tar.xz=7c320cc979ebdde8753093a0e4b1da850b1b680c1ecd10c5d3e33242af12e4dd
+dist/2024-09-04/clippy-beta-armv7-unknown-linux-gnueabihf.tar.gz=835c0912556cd5b0b180856359db8d75204830984fb1b5f72bf436f137955fa2
+dist/2024-09-04/clippy-beta-armv7-unknown-linux-gnueabihf.tar.xz=836a54126122c2abfc649982708d97b6451eaf3a31ba556ed73ec1f4269be738
+dist/2024-09-04/clippy-beta-i686-pc-windows-gnu.tar.gz=90b52880cbd51bacb9597ee4fed07fa13fc399f03c5ba840c0c9e6c0a096b772
+dist/2024-09-04/clippy-beta-i686-pc-windows-gnu.tar.xz=c41be130f3276c4c905eab580e866682e4f3bbdd11b348f4d1438c67602fb036
+dist/2024-09-04/clippy-beta-i686-pc-windows-msvc.tar.gz=f023406dc34bb09d020a41fdf6ceb3e60c90dd38380fbbcc26e9f4e144eebca0
+dist/2024-09-04/clippy-beta-i686-pc-windows-msvc.tar.xz=b21746ec1a2c9fc76ce82917b65c8e73482aaefe5f99282f0c5e9682a3af486e
+dist/2024-09-04/clippy-beta-i686-unknown-linux-gnu.tar.gz=cce9cd9d470250c73437e151622b02f804fff3db045c6de25ee949aed435c383
+dist/2024-09-04/clippy-beta-i686-unknown-linux-gnu.tar.xz=9565f70c8d90540d464fb1f3b8bff52b77bf55189ab938b2c18bdeed751e9e4c
+dist/2024-09-04/clippy-beta-loongarch64-unknown-linux-gnu.tar.gz=0d1d63a8eca4d0812446f94bc793fbb7660da11babf5d8607d2798749c938a6b
+dist/2024-09-04/clippy-beta-loongarch64-unknown-linux-gnu.tar.xz=db178c0eaddcb318653d4b05fe0d97738440713f0cd120657cc2a3e758d52432
+dist/2024-09-04/clippy-beta-loongarch64-unknown-linux-musl.tar.gz=a604be9f091f88e97f702f619d86b91bff0a20fbd267200ac1e66df2bd823766
+dist/2024-09-04/clippy-beta-loongarch64-unknown-linux-musl.tar.xz=93c395e07a8457b8904c470751490326303e2ceaa93b737f8fc521b49dfbd69b
+dist/2024-09-04/clippy-beta-powerpc-unknown-linux-gnu.tar.gz=08aa4a8ccd7569a0513c2443e2b10993cbb92bed531370891452bd3dd8c0eb82
+dist/2024-09-04/clippy-beta-powerpc-unknown-linux-gnu.tar.xz=f6b0222261e1e2b1465549eda331c16d4ea6729d15e6fe208dbc4cce115e75e7
+dist/2024-09-04/clippy-beta-powerpc64-unknown-linux-gnu.tar.gz=96e2dca5adb7f5ffe41e5ff30e9419575f3991adde8bdbba023d11f344044dc1
+dist/2024-09-04/clippy-beta-powerpc64-unknown-linux-gnu.tar.xz=3ced511aca7268960c616d0105da02a92d83b7983b6accbb37eba722eff64cbf
+dist/2024-09-04/clippy-beta-powerpc64le-unknown-linux-gnu.tar.gz=421c27b25b79b9c88e4b65ac7cd0a4f06934a63324c56870cd7fff905869a33e
+dist/2024-09-04/clippy-beta-powerpc64le-unknown-linux-gnu.tar.xz=63254a01ab1a9a21cdb5a0b3a4da9e8ae7921b9ceec2339df4bbfb19ea7c6454
+dist/2024-09-04/clippy-beta-riscv64gc-unknown-linux-gnu.tar.gz=4ee751b09816886f8edbc431ab8c63df6c664dbedc40a67748fb17a639a070f1
+dist/2024-09-04/clippy-beta-riscv64gc-unknown-linux-gnu.tar.xz=7e9ffb62ab6c8f1cbb5f9e0b0a3c79cf104dfac09be2ef1d5e6b6c0c34b406c7
+dist/2024-09-04/clippy-beta-s390x-unknown-linux-gnu.tar.gz=0a49c1e844859f27b1283087c476a559c4c3a4c33c8ce2748165cc5c0b0ed039
+dist/2024-09-04/clippy-beta-s390x-unknown-linux-gnu.tar.xz=6daec872df52125b3de854ff0962433ba13b7cbe5519edfb29944fbc4cc817ad
+dist/2024-09-04/clippy-beta-x86_64-apple-darwin.tar.gz=6611771ce0e7cc19fbbb9383875edaf7de975b6cf154fcd5cd18a09f09793a36
+dist/2024-09-04/clippy-beta-x86_64-apple-darwin.tar.xz=1c90c63f87b43797aa04b88e4c1d0fe0f2ad131060fc8495be190d0ebd89a43e
+dist/2024-09-04/clippy-beta-x86_64-pc-windows-gnu.tar.gz=53a04c1426bc151fec4699848e33141df1b04097d4883c07fc07d2bf0bcddf8a
+dist/2024-09-04/clippy-beta-x86_64-pc-windows-gnu.tar.xz=be748b65b238e3e948e2421f82a72d1108ec79651381b1dcdaaa97df15c981df
+dist/2024-09-04/clippy-beta-x86_64-pc-windows-msvc.tar.gz=24ea01230bbf6b4f43094cfcf6c7c72e6d319c493ff3817456c667b89026c608
+dist/2024-09-04/clippy-beta-x86_64-pc-windows-msvc.tar.xz=37130d66eeaed68f0780b1dc19f2f59a2a0419350920521690d4870d7d71d8f1
+dist/2024-09-04/clippy-beta-x86_64-unknown-freebsd.tar.gz=4e427b7ea0f334bd6ea8c2de7fc1d5bf43d5333bc7a435cf65543c564fab6e41
+dist/2024-09-04/clippy-beta-x86_64-unknown-freebsd.tar.xz=b221491159f5352dd392f6ee6419f9d5d693ac347df9863fdac77f2ca1cf6a67
+dist/2024-09-04/clippy-beta-x86_64-unknown-illumos.tar.gz=9d835b4369fb51ab8c1eafb553b9304548e91dd32784ae81cb783b40985d2eee
+dist/2024-09-04/clippy-beta-x86_64-unknown-illumos.tar.xz=a6780c72c71f2e6c6e1bbc8bc4e639389ab9b7aed0ee7e2e0c21819156b5578e
+dist/2024-09-04/clippy-beta-x86_64-unknown-linux-gnu.tar.gz=613bf471668edb8209910dd13086cbefed0da6dea46dce2013a000ecc4315e45
+dist/2024-09-04/clippy-beta-x86_64-unknown-linux-gnu.tar.xz=e3328f37cfc89de1aabd89653a42ff54b8dadcc49e651b22fda325c00644309d
+dist/2024-09-04/clippy-beta-x86_64-unknown-linux-musl.tar.gz=d6a7a5ee37587c0b92aabfc5b9466d175cb8d05d209412a5beee8a61c241396f
+dist/2024-09-04/clippy-beta-x86_64-unknown-linux-musl.tar.xz=dc73b566be162eef2032eccb69b3542ab3c72b760fe7eeaacfcd367ee0b20f12
+dist/2024-09-04/clippy-beta-x86_64-unknown-netbsd.tar.gz=6f1e0be96b59a63a6616b68717c0a393fd99ec1a768affdd5c86249e5eb5d210
+dist/2024-09-04/clippy-beta-x86_64-unknown-netbsd.tar.xz=30fff8aceaedf6d76c6fc0636c2ddecc97fb66f9219b86299550b7312f043e38
+dist/2024-09-04/rustfmt-nightly-aarch64-apple-darwin.tar.gz=37a5383ba608540ed57484e221e87f3cd78fd35f068e98f0da1d3932d86d2eff
+dist/2024-09-04/rustfmt-nightly-aarch64-apple-darwin.tar.xz=a3935c24f5ac1d69756f4598f227e43304ede4e35f9808b3db9f04adfecc5445
+dist/2024-09-04/rustfmt-nightly-aarch64-pc-windows-msvc.tar.gz=0b21dd8c54055102a41f7ad622565c1fc36ff97642f2e2998e48d1cb1ebae196
+dist/2024-09-04/rustfmt-nightly-aarch64-pc-windows-msvc.tar.xz=2a543dbf79042924e8c05aaeed97ff37089c8f6994977b932bacb0403f11584c
+dist/2024-09-04/rustfmt-nightly-aarch64-unknown-linux-gnu.tar.gz=8d9b19108587e6d8d12270ff025579dc559173245e08b94113bb91a7ada80670
+dist/2024-09-04/rustfmt-nightly-aarch64-unknown-linux-gnu.tar.xz=d288770b8a85e24b35561129cc2a09c848006c547ce5fa35d33c8ed7e85d5322
+dist/2024-09-04/rustfmt-nightly-aarch64-unknown-linux-musl.tar.gz=2e69adc7e75efcd889108d185f200db6280494b05de6a06291dbf26ef32e5d42
+dist/2024-09-04/rustfmt-nightly-aarch64-unknown-linux-musl.tar.xz=fca74af6db1c53a79a4412a020f56ec9c61603d3373eaa936a57dad45f3751d7
+dist/2024-09-04/rustfmt-nightly-arm-unknown-linux-gnueabi.tar.gz=b2be0123cde401aaed259a9387e04f3978fbddce98096b3a8a654b76f92f2e6b
+dist/2024-09-04/rustfmt-nightly-arm-unknown-linux-gnueabi.tar.xz=c44c42a59887f1479383694f43688f9f2a8174ac89fdf657b2e8619372e0bcef
+dist/2024-09-04/rustfmt-nightly-arm-unknown-linux-gnueabihf.tar.gz=3d99bab3656d0318173c414dcb8930291ab43285883ca80a04d854023a4201a3
+dist/2024-09-04/rustfmt-nightly-arm-unknown-linux-gnueabihf.tar.xz=29e506c1a18449b84a643f0075f1263cd8512662f55e2c5b18305213e4246783
+dist/2024-09-04/rustfmt-nightly-armv7-unknown-linux-gnueabihf.tar.gz=b486ff8e1e136ba15c9bb14db08dcd14b612adf1617cf1f820a23ee403958049
+dist/2024-09-04/rustfmt-nightly-armv7-unknown-linux-gnueabihf.tar.xz=b4d593b5a89bb42e7f9eaa17df12778dd816c75e8997e964371286041691cbbf
+dist/2024-09-04/rustfmt-nightly-i686-pc-windows-gnu.tar.gz=dcf94a642166b0664a63c4162a2d303c75fdef6f2a7f9b3e502ba5baae117f69
+dist/2024-09-04/rustfmt-nightly-i686-pc-windows-gnu.tar.xz=4b27ac17748d8cdcd2bc7b9956541333997c6ec56f7a770628dc8e57fc7f442f
+dist/2024-09-04/rustfmt-nightly-i686-pc-windows-msvc.tar.gz=8a3caf2dc2b786ca58f6d37c011dc210e883398a3734f9f13678a9e57c5ccf5d
+dist/2024-09-04/rustfmt-nightly-i686-pc-windows-msvc.tar.xz=e129b88dd69200e305cc5ae16231952d85f9461dad13fd3bae5e889dac89d9c6
+dist/2024-09-04/rustfmt-nightly-i686-unknown-linux-gnu.tar.gz=1bc390abb8f754d5b8679b33186b97262dadff9c6db7268cfbcfe605c628a681
+dist/2024-09-04/rustfmt-nightly-i686-unknown-linux-gnu.tar.xz=8420198b0a22aaa5951678b954bcce636c78ba6567a06484c830b3eded815228
+dist/2024-09-04/rustfmt-nightly-loongarch64-unknown-linux-gnu.tar.gz=05071fe12ed4030464f996fe36dd2e3f60d3701956275499acaeaf03a16e36eb
+dist/2024-09-04/rustfmt-nightly-loongarch64-unknown-linux-gnu.tar.xz=2bfdabab0d03e570c073463a8867bbdb54879f501b0822906fa2aa5705603d7c
+dist/2024-09-04/rustfmt-nightly-loongarch64-unknown-linux-musl.tar.gz=0c7e3b10626a9d9a3f8522175085169ea4e34568a7be0093c6682bb9659bf65f
+dist/2024-09-04/rustfmt-nightly-loongarch64-unknown-linux-musl.tar.xz=deb2b51a41dae2e72188fa6c06c4a7bdb08c2723b3ce823602087bd9eb36eb07
+dist/2024-09-04/rustfmt-nightly-powerpc-unknown-linux-gnu.tar.gz=e34590ec2cbd481ffd237101c239f27bd2298517bb7fc9c9f9b6d71abfff69e4
+dist/2024-09-04/rustfmt-nightly-powerpc-unknown-linux-gnu.tar.xz=9cd0d3dd57b764ad054d4295f822a7fd74a1b1ee5babf77ed2dc2c39ee60b7a2
+dist/2024-09-04/rustfmt-nightly-powerpc64-unknown-linux-gnu.tar.gz=62566938d97058dd38b1e0c97aa4421d709ce988544956d6a4aaf3e54425dbce
+dist/2024-09-04/rustfmt-nightly-powerpc64-unknown-linux-gnu.tar.xz=8f27c6fc5b56092302e49da973ff08f0d3131465bf9a701a9ddc91d373acc435
+dist/2024-09-04/rustfmt-nightly-powerpc64le-unknown-linux-gnu.tar.gz=7637f3b8060635595a3d2fb83fef68e9990ff1adb1bd3288c7c41767b37ee2c4
+dist/2024-09-04/rustfmt-nightly-powerpc64le-unknown-linux-gnu.tar.xz=3275f15e3d7e9ccb991f6f9a7059acefd0bee49bfd4cf0724aed11e51e3772db
+dist/2024-09-04/rustfmt-nightly-riscv64gc-unknown-linux-gnu.tar.gz=29379bab930e7b350cec51be33663ad67a0d30922d658006911f895221dcbffd
+dist/2024-09-04/rustfmt-nightly-riscv64gc-unknown-linux-gnu.tar.xz=4f71e948ec587836315d7ec98e6f3c6125a298faf1321b4524257d3c9664f9eb
+dist/2024-09-04/rustfmt-nightly-s390x-unknown-linux-gnu.tar.gz=5b9361317481269e090b4270bcf754caca8a1797f6b2d83a4c570a4024bb0dc3
+dist/2024-09-04/rustfmt-nightly-s390x-unknown-linux-gnu.tar.xz=db3bf98663017bec6b6beba5848a350d4d34f39e3f98bacb321866112cff7c15
+dist/2024-09-04/rustfmt-nightly-x86_64-apple-darwin.tar.gz=9d5b8c84f82ededb2370c20afdb6b7d06d97161a65348f4ee2b6ab2171236cd0
+dist/2024-09-04/rustfmt-nightly-x86_64-apple-darwin.tar.xz=e880f57ba68bce871fa67230db19aab1f146548254867f09e0d83750bbb50a1c
+dist/2024-09-04/rustfmt-nightly-x86_64-pc-windows-gnu.tar.gz=8b2c79814b202661c74584d7c4aeb35cc0c8520c4df1c81f2fb2896a22385191
+dist/2024-09-04/rustfmt-nightly-x86_64-pc-windows-gnu.tar.xz=c193e2f2b859239aa0489c65663fb83c4bd7a87571d5b6ca6572f722c46cef64
+dist/2024-09-04/rustfmt-nightly-x86_64-pc-windows-msvc.tar.gz=8d6583366248882490371ef5d4532f82ba1779cb993b0078ca6903f9b6a0c5be
+dist/2024-09-04/rustfmt-nightly-x86_64-pc-windows-msvc.tar.xz=0b69fdd8edb566a75cdff616e09223b10796a91eaf8bd90aa11ddd6af61381b9
+dist/2024-09-04/rustfmt-nightly-x86_64-unknown-freebsd.tar.gz=0a452883a9a494f1613f9b0c796d13745e56eb85597142a677c78daeca95a67c
+dist/2024-09-04/rustfmt-nightly-x86_64-unknown-freebsd.tar.xz=01eb4d938f6e9228cae297688340daf298bf6e5322a4e3cdb4e06554fa131deb
+dist/2024-09-04/rustfmt-nightly-x86_64-unknown-illumos.tar.gz=4d9220bee07e3576f34c3a3dd327723ed660a774c4391f7a4a7e6a78ea2ca88c
+dist/2024-09-04/rustfmt-nightly-x86_64-unknown-illumos.tar.xz=2e2cd60bbb356d7b702c511ba56b480ffe0bbceef8f945be0f7b8e338d7998a0
+dist/2024-09-04/rustfmt-nightly-x86_64-unknown-linux-gnu.tar.gz=4aac5347a6011ff27609b4a6b413454d610a5687253a7e09d1bcc8c0e3aa0e6f
+dist/2024-09-04/rustfmt-nightly-x86_64-unknown-linux-gnu.tar.xz=ad3a0127c2cc09893fb19e4c58faa6188afeb575996ee4708eae6c5713ff9646
+dist/2024-09-04/rustfmt-nightly-x86_64-unknown-linux-musl.tar.gz=869fbf24ca816b0bf931da79920ae8edaef8a749271434c6522f7ff55920a507
+dist/2024-09-04/rustfmt-nightly-x86_64-unknown-linux-musl.tar.xz=f4870110759f28ad1cdde912fd3f79bd8eb0073bd42e436a456f0d04e7c2bd26
+dist/2024-09-04/rustfmt-nightly-x86_64-unknown-netbsd.tar.gz=eac75028d080b3d4ab86dbbb4f46c7734c60bd747e0325afbaa3b7a7cf0003be
+dist/2024-09-04/rustfmt-nightly-x86_64-unknown-netbsd.tar.xz=fe13bf3e0ec3088b35608d65b76f77014e0b90886ba81decfa21019ff222c79b
+dist/2024-09-04/rustc-nightly-aarch64-apple-darwin.tar.gz=ecda4ccde26bf6f8405ddbb838239c4f42e9136001e8954b21357d86343ad06d
+dist/2024-09-04/rustc-nightly-aarch64-apple-darwin.tar.xz=cdb1b12e6acf5b2bc5a5328f7cb292760d391b3e269d2b2143c87a344efcc9dd
+dist/2024-09-04/rustc-nightly-aarch64-pc-windows-msvc.tar.gz=46af634f433b9c7182637880f7b910ef13d2da9b1d7d4e255f9cd302691b99fc
+dist/2024-09-04/rustc-nightly-aarch64-pc-windows-msvc.tar.xz=a14935b0b82835388886c826b703057af093dfe16f0367c058dd6d352e585859
+dist/2024-09-04/rustc-nightly-aarch64-unknown-linux-gnu.tar.gz=68ced431fa8682f83dd79901ccb986accc5a6d948c837c43eb5fa244c19eab88
+dist/2024-09-04/rustc-nightly-aarch64-unknown-linux-gnu.tar.xz=fa078e5edc9f6c7be5a39eac722f142d526b68e30acc8f81bd001035fd657a83
+dist/2024-09-04/rustc-nightly-aarch64-unknown-linux-musl.tar.gz=c88a3c5cbb7a8a55f18d27f2c573192d824e33657a143641d1c8fa1504cbc805
+dist/2024-09-04/rustc-nightly-aarch64-unknown-linux-musl.tar.xz=00170baf596aa6e043598e3c38153f29c1cbfe4a63298d4007979877e9c3e1c2
+dist/2024-09-04/rustc-nightly-arm-unknown-linux-gnueabi.tar.gz=19a55b89192897c77240404ff7ed8c64cdba106db13be4a1ae86a9ac44753c30
+dist/2024-09-04/rustc-nightly-arm-unknown-linux-gnueabi.tar.xz=42937abfd803faed251cecc7ac74abcc3c40332b8466535cc1727138fe03beeb
+dist/2024-09-04/rustc-nightly-arm-unknown-linux-gnueabihf.tar.gz=3cc5d6e89cd8b53db0c2900a73e59c188e90d042b2e43502e384f44d229b93e7
+dist/2024-09-04/rustc-nightly-arm-unknown-linux-gnueabihf.tar.xz=4e1ff68b91e0cc730ca6012aa577aaf73dd5108d0b26575eaade0a2380914fe0
+dist/2024-09-04/rustc-nightly-armv7-unknown-linux-gnueabihf.tar.gz=082a2efdf341bdfd9bbe3e2340ae8dbf71bff71908439696d30fa25d00c5fe1b
+dist/2024-09-04/rustc-nightly-armv7-unknown-linux-gnueabihf.tar.xz=0b480d334a3709ca23dfd4839b518391031b6afde4cea0c30f08f160e39592a0
+dist/2024-09-04/rustc-nightly-i686-pc-windows-gnu.tar.gz=bf06c7a0faebb7dbfa2c09d02f506410f05abc6aa2ba54c515f2a429e904de2a
+dist/2024-09-04/rustc-nightly-i686-pc-windows-gnu.tar.xz=c49f577fa788bb6b40350dd9e9f9088ded647f0a5cf5df69135a83d2e085d9ca
+dist/2024-09-04/rustc-nightly-i686-pc-windows-msvc.tar.gz=e42254e299e367c9414c4b61715125410ddc3ecb30f2457e4eb843725c6b6abd
+dist/2024-09-04/rustc-nightly-i686-pc-windows-msvc.tar.xz=91a752b8a61b81281203297712b1bc775a227d9626b4c84d9e10130f428f843d
+dist/2024-09-04/rustc-nightly-i686-unknown-linux-gnu.tar.gz=6f23df634f3e7028d9a6e9989e1edbc2d00e9b435473807f526fd58c150baf3d
+dist/2024-09-04/rustc-nightly-i686-unknown-linux-gnu.tar.xz=de7cef873379e3d5ef80b402b9d98bdf74366de27e8f928125081628937baf76
+dist/2024-09-04/rustc-nightly-loongarch64-unknown-linux-gnu.tar.gz=ef0946845c41e096dced01baf6e843c57fcf695c82d5408a1b7c0a5bbd150b39
+dist/2024-09-04/rustc-nightly-loongarch64-unknown-linux-gnu.tar.xz=d43bb8987a3bb394d7d2cf39d78f54505700525b250cb30741b903bf8712f3bf
+dist/2024-09-04/rustc-nightly-loongarch64-unknown-linux-musl.tar.gz=00013767600b1a5153ed4faa9d227fd55a905c375f712a7ca59573a317684c97
+dist/2024-09-04/rustc-nightly-loongarch64-unknown-linux-musl.tar.xz=cf1c4351f70e951290583213dade06fe4a61e6dcbc2d0e69be54ea91210051de
+dist/2024-09-04/rustc-nightly-powerpc-unknown-linux-gnu.tar.gz=be1957674fdda24a9cd8935789db35a17d3a0d71219bb6f1256af74c64ffc697
+dist/2024-09-04/rustc-nightly-powerpc-unknown-linux-gnu.tar.xz=20541daa3925834012ab68f186a1f1ab4d060cced96646e2142a0f14c04b6ad6
+dist/2024-09-04/rustc-nightly-powerpc64-unknown-linux-gnu.tar.gz=0eb6741b87d430573c9b0d5b9ba9725c0c03caabc01d5ee258867ea19aedafdc
+dist/2024-09-04/rustc-nightly-powerpc64-unknown-linux-gnu.tar.xz=8ad4670b74093e3c7055149649145a4af2b2a3d24a68bf893ed72202cc934946
+dist/2024-09-04/rustc-nightly-powerpc64le-unknown-linux-gnu.tar.gz=2d7b60aa2d4853eba2bb2644cb14768a5a864386da0854aca7c1f6397374dca2
+dist/2024-09-04/rustc-nightly-powerpc64le-unknown-linux-gnu.tar.xz=17792328178392ad96b1a0c05405c61d0b1e7196bdca9e55baebff12a4949725
+dist/2024-09-04/rustc-nightly-riscv64gc-unknown-linux-gnu.tar.gz=2db9fe19d4e1d7f68a0802868d9344e23932190e2d46407523208a67b5ba053a
+dist/2024-09-04/rustc-nightly-riscv64gc-unknown-linux-gnu.tar.xz=f0d4df5e4cfeff06eb2cb07c6f9ac0596130923133571fd1702d56a0251ebb99
+dist/2024-09-04/rustc-nightly-s390x-unknown-linux-gnu.tar.gz=4d3fea9ec53336195c0daa2b2937507c2216537647829466a19acee2ce9e201a
+dist/2024-09-04/rustc-nightly-s390x-unknown-linux-gnu.tar.xz=84ca3dccf7af68a343fed4d209771bac7439149695f63517bd048287f4539add
+dist/2024-09-04/rustc-nightly-x86_64-apple-darwin.tar.gz=f6f43ebb82851edae301033a2cfbd02724849c7fda42294818f3081f74d3a1a3
+dist/2024-09-04/rustc-nightly-x86_64-apple-darwin.tar.xz=55b0db99f02bd4c5595117663f6b6cc739f63723999062ced0096727e627f072
+dist/2024-09-04/rustc-nightly-x86_64-pc-windows-gnu.tar.gz=6cb63e57f9873e40695b735b8cdb9f0de70306f1692161cd8f7767b4016dcf39
+dist/2024-09-04/rustc-nightly-x86_64-pc-windows-gnu.tar.xz=79bf54beceda0a7f6580d3ef336d8deae3991b3b57e4c6aba635f9d848cc860d
+dist/2024-09-04/rustc-nightly-x86_64-pc-windows-msvc.tar.gz=7757651c78d5000926bd5e91996ea8abdc32db8e67b31271cb70680f551edd5f
+dist/2024-09-04/rustc-nightly-x86_64-pc-windows-msvc.tar.xz=4671e03fc7100bac43cf332e387161c0ccde77d3f893a9dfdd27be63fff39932
+dist/2024-09-04/rustc-nightly-x86_64-unknown-freebsd.tar.gz=675f49fc6a51d5e715789bc9ad92b9db12a94a033254e34efb65358700207bb5
+dist/2024-09-04/rustc-nightly-x86_64-unknown-freebsd.tar.xz=f9efc43f26600caf2ef7c8084fe94ae31ba540ae7e9f104e6a587c6e4272cd6b
+dist/2024-09-04/rustc-nightly-x86_64-unknown-illumos.tar.gz=9bd74b7ee78a02306f47640b99d752ea373ffdd88067376d9f03564f07edfb24
+dist/2024-09-04/rustc-nightly-x86_64-unknown-illumos.tar.xz=67c5d546df9fa451d42804de2d439229e9b21eb9329ff16eeadcc52f5b6393d1
+dist/2024-09-04/rustc-nightly-x86_64-unknown-linux-gnu.tar.gz=dfc427db6a14237a12fd077ccc44c07e7bb46a1b2965a3fb1ddd78a2ec334b81
+dist/2024-09-04/rustc-nightly-x86_64-unknown-linux-gnu.tar.xz=8d307dce871ae5f7cc1410e85bb7b38f80aed5c1138030b4f112e727fb8c654b
+dist/2024-09-04/rustc-nightly-x86_64-unknown-linux-musl.tar.gz=b7f84d8aab03afcf2bab8ed21fa3ece6ac418d076e0195381110adfac2aa1fbc
+dist/2024-09-04/rustc-nightly-x86_64-unknown-linux-musl.tar.xz=296083c6b50b7dffe8a62884bac7e831e29487a31c8e6fb319f04f0e62157175
+dist/2024-09-04/rustc-nightly-x86_64-unknown-netbsd.tar.gz=96986595ce82c735b87fe75f00722514c49e7118d38c4bced554c9017377ec91
+dist/2024-09-04/rustc-nightly-x86_64-unknown-netbsd.tar.xz=bf8c9411ff7279fd56bb7e3c68ac29c8ce79ba031317b76aac6a74d20f1511f0
\ No newline at end of file
diff --git a/src/tools/clippy/clippy_lints/src/escape.rs b/src/tools/clippy/clippy_lints/src/escape.rs
index a5da52b..8036069 100644
--- a/src/tools/clippy/clippy_lints/src/escape.rs
+++ b/src/tools/clippy/clippy_lints/src/escape.rs
@@ -50,7 +50,7 @@ pub fn new(conf: &'static Conf) -> Self {
}
fn is_non_trait_box(ty: Ty<'_>) -> bool {
- ty.is_box() && !ty.boxed_ty().is_trait()
+ ty.boxed_ty().is_some_and(|boxed| !boxed.is_trait())
}
struct EscapeDelegate<'a, 'tcx> {
@@ -191,8 +191,8 @@ fn fake_read(&mut self, _: &PlaceWithHirId<'tcx>, _: FakeReadCause, _: HirId) {}
impl<'a, 'tcx> EscapeDelegate<'a, 'tcx> {
fn is_large_box(&self, ty: Ty<'tcx>) -> bool {
// Large types need to be boxed to avoid stack overflows.
- if ty.is_box() {
- self.cx.layout_of(ty.boxed_ty()).map_or(0, |l| l.size.bytes()) > self.too_large_for_stack
+ if let Some(boxed_ty) = ty.boxed_ty() {
+ self.cx.layout_of(boxed_ty).map_or(0, |l| l.size.bytes()) > self.too_large_for_stack
} else {
false
}
diff --git a/src/tools/clippy/clippy_lints/src/methods/mod.rs b/src/tools/clippy/clippy_lints/src/methods/mod.rs
index d712699..f61bb3a 100644
--- a/src/tools/clippy/clippy_lints/src/methods/mod.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/mod.rs
@@ -5187,8 +5187,8 @@ fn matches<'a>(self, cx: &LateContext<'a>, parent_ty: Ty<'a>, ty: Ty<'a>) -> boo
fn matches_value<'a>(cx: &LateContext<'a>, parent_ty: Ty<'a>, ty: Ty<'a>) -> bool {
if ty == parent_ty {
true
- } else if ty.is_box() {
- ty.boxed_ty() == parent_ty
+ } else if let Some(boxed_ty) = ty.boxed_ty() {
+ boxed_ty == parent_ty
} else if is_type_diagnostic_item(cx, ty, sym::Rc) || is_type_diagnostic_item(cx, ty, sym::Arc) {
if let ty::Adt(_, args) = ty.kind() {
args.types().next().map_or(false, |t| t == parent_ty)
diff --git a/src/tools/clippy/clippy_lints/src/methods/utils.rs b/src/tools/clippy/clippy_lints/src/methods/utils.rs
index 0d2b0a3..fe860e5 100644
--- a/src/tools/clippy/clippy_lints/src/methods/utils.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/utils.rs
@@ -16,7 +16,7 @@ pub(super) fn derefs_to_slice<'tcx>(
fn may_slice<'a>(cx: &LateContext<'a>, ty: Ty<'a>) -> bool {
match ty.kind() {
ty::Slice(_) => true,
- ty::Adt(def, _) if def.is_box() => may_slice(cx, ty.boxed_ty()),
+ ty::Adt(..) if let Some(boxed) = ty.boxed_ty() => may_slice(cx, boxed),
ty::Adt(..) => is_type_diagnostic_item(cx, ty, sym::Vec),
ty::Array(_, size) => size.try_eval_target_usize(cx.tcx, cx.param_env).is_some(),
ty::Ref(_, inner, _) => may_slice(cx, *inner),
@@ -33,7 +33,7 @@ fn may_slice<'a>(cx: &LateContext<'a>, ty: Ty<'a>) -> bool {
} else {
match ty.kind() {
ty::Slice(_) => Some(expr),
- ty::Adt(def, _) if def.is_box() && may_slice(cx, ty.boxed_ty()) => Some(expr),
+ _ if ty.boxed_ty().is_some_and(|boxed| may_slice(cx, boxed)) => Some(expr),
ty::Ref(_, inner, _) => {
if may_slice(cx, *inner) {
Some(expr)
diff --git a/src/tools/clippy/clippy_lints/src/transmute/mod.rs b/src/tools/clippy/clippy_lints/src/transmute/mod.rs
index 373bf61..a2ae36c 100644
--- a/src/tools/clippy/clippy_lints/src/transmute/mod.rs
+++ b/src/tools/clippy/clippy_lints/src/transmute/mod.rs
@@ -619,10 +619,10 @@ fn check_expr(&mut self, cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) {
| transmute_ref_to_ref::check(cx, e, from_ty, to_ty, arg, const_context)
| transmute_ptr_to_ptr::check(cx, e, from_ty, to_ty, arg, &self.msrv)
| transmute_int_to_bool::check(cx, e, from_ty, to_ty, arg)
- | transmute_int_to_float::check(cx, e, from_ty, to_ty, arg, const_context)
+ | transmute_int_to_float::check(cx, e, from_ty, to_ty, arg)
| transmute_int_to_non_zero::check(cx, e, from_ty, to_ty, arg)
- | transmute_float_to_int::check(cx, e, from_ty, to_ty, arg, const_context)
- | transmute_num_to_bytes::check(cx, e, from_ty, to_ty, arg, const_context)
+ | transmute_float_to_int::check(cx, e, from_ty, to_ty, arg)
+ | transmute_num_to_bytes::check(cx, e, from_ty, to_ty, arg)
| (unsound_collection_transmute::check(cx, e, from_ty, to_ty)
|| transmute_undefined_repr::check(cx, e, from_ty, to_ty))
| (eager_transmute::check(cx, e, arg, from_ty, to_ty));
diff --git a/src/tools/clippy/clippy_lints/src/transmute/transmute_float_to_int.rs b/src/tools/clippy/clippy_lints/src/transmute/transmute_float_to_int.rs
index ab3bb5e..cb46109 100644
--- a/src/tools/clippy/clippy_lints/src/transmute/transmute_float_to_int.rs
+++ b/src/tools/clippy/clippy_lints/src/transmute/transmute_float_to_int.rs
@@ -15,10 +15,9 @@ pub(super) fn check<'tcx>(
from_ty: Ty<'tcx>,
to_ty: Ty<'tcx>,
mut arg: &'tcx Expr<'_>,
- const_context: bool,
) -> bool {
match (&from_ty.kind(), &to_ty.kind()) {
- (ty::Float(float_ty), ty::Int(_) | ty::Uint(_)) if !const_context => {
+ (ty::Float(float_ty), ty::Int(_) | ty::Uint(_)) => {
span_lint_and_then(
cx,
TRANSMUTE_FLOAT_TO_INT,
diff --git a/src/tools/clippy/clippy_lints/src/transmute/transmute_int_to_float.rs b/src/tools/clippy/clippy_lints/src/transmute/transmute_int_to_float.rs
index d51888e..e00fb90 100644
--- a/src/tools/clippy/clippy_lints/src/transmute/transmute_int_to_float.rs
+++ b/src/tools/clippy/clippy_lints/src/transmute/transmute_int_to_float.rs
@@ -14,10 +14,9 @@ pub(super) fn check<'tcx>(
from_ty: Ty<'tcx>,
to_ty: Ty<'tcx>,
arg: &'tcx Expr<'_>,
- const_context: bool,
) -> bool {
match (&from_ty.kind(), &to_ty.kind()) {
- (ty::Int(_) | ty::Uint(_), ty::Float(_)) if !const_context => {
+ (ty::Int(_) | ty::Uint(_), ty::Float(_)) => {
span_lint_and_then(
cx,
TRANSMUTE_INT_TO_FLOAT,
diff --git a/src/tools/clippy/clippy_lints/src/transmute/transmute_num_to_bytes.rs b/src/tools/clippy/clippy_lints/src/transmute/transmute_num_to_bytes.rs
index 88b0ac5..362f2bb 100644
--- a/src/tools/clippy/clippy_lints/src/transmute/transmute_num_to_bytes.rs
+++ b/src/tools/clippy/clippy_lints/src/transmute/transmute_num_to_bytes.rs
@@ -14,18 +14,12 @@ pub(super) fn check<'tcx>(
from_ty: Ty<'tcx>,
to_ty: Ty<'tcx>,
arg: &'tcx Expr<'_>,
- const_context: bool,
) -> bool {
match (&from_ty.kind(), &to_ty.kind()) {
(ty::Int(_) | ty::Uint(_) | ty::Float(_), ty::Array(arr_ty, _)) => {
if !matches!(arr_ty.kind(), ty::Uint(UintTy::U8)) {
return false;
}
- if matches!(from_ty.kind(), ty::Float(_)) && const_context {
- // TODO: Remove when const_float_bits_conv is stabilized
- // rust#72447
- return false;
- }
span_lint_and_then(
cx,
diff --git a/src/tools/clippy/clippy_lints/src/unnecessary_box_returns.rs b/src/tools/clippy/clippy_lints/src/unnecessary_box_returns.rs
index 3f130bf..14f4aa6 100644
--- a/src/tools/clippy/clippy_lints/src/unnecessary_box_returns.rs
+++ b/src/tools/clippy/clippy_lints/src/unnecessary_box_returns.rs
@@ -75,11 +75,9 @@ fn check_fn_item(&mut self, cx: &LateContext<'_>, decl: &FnDecl<'_>, def_id: Loc
.instantiate_bound_regions_with_erased(cx.tcx.fn_sig(def_id).skip_binder())
.output();
- if !return_ty.is_box() {
+ let Some(boxed_ty) = return_ty.boxed_ty() else {
return;
- }
-
- let boxed_ty = return_ty.boxed_ty();
+ };
// It's sometimes useful to return Box<T> if T is unsized, so don't lint those.
// Also, don't lint if we know that T is very large, in which case returning
diff --git a/src/tools/clippy/clippy_utils/src/ty.rs b/src/tools/clippy/clippy_utils/src/ty.rs
index f80981c..5851342 100644
--- a/src/tools/clippy/clippy_utils/src/ty.rs
+++ b/src/tools/clippy/clippy_utils/src/ty.rs
@@ -704,8 +704,8 @@ pub fn expr_sig<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'_>) -> Option<ExprFnS
/// If the type is function like, get the signature for it.
pub fn ty_sig<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> Option<ExprFnSig<'tcx>> {
- if ty.is_box() {
- return ty_sig(cx, ty.boxed_ty());
+ if let Some(boxed_ty) = ty.boxed_ty() {
+ return ty_sig(cx, boxed_ty);
}
match *ty.kind() {
ty::Closure(id, subs) => {
diff --git a/src/tools/clippy/tests/ui/transmute.rs b/src/tools/clippy/tests/ui/transmute.rs
index 4662952..eeea3f0 100644
--- a/src/tools/clippy/tests/ui/transmute.rs
+++ b/src/tools/clippy/tests/ui/transmute.rs
@@ -140,24 +140,32 @@ fn test() {
mod issue_5747 {
const VALUE16: f16 = unsafe { std::mem::transmute(0_u16) };
+ //~^ ERROR: transmute from a `u16` to a `f16`
const VALUE32: f32 = unsafe { std::mem::transmute(0_u32) };
+ //~^ ERROR: transmute from a `u32` to a `f32`
const VALUE64: f64 = unsafe { std::mem::transmute(0_i64) };
+ //~^ ERROR: transmute from a `i64` to a `f64`
const VALUE128: f128 = unsafe { std::mem::transmute(0_i128) };
+ //~^ ERROR: transmute from a `i128` to a `f128`
const fn from_bits_16(v: i16) -> f16 {
unsafe { std::mem::transmute(v) }
+ //~^ ERROR: transmute from a `i16` to a `f16`
}
const fn from_bits_32(v: i32) -> f32 {
unsafe { std::mem::transmute(v) }
+ //~^ ERROR: transmute from a `i32` to a `f32`
}
const fn from_bits_64(v: u64) -> f64 {
unsafe { std::mem::transmute(v) }
+ //~^ ERROR: transmute from a `u64` to a `f64`
}
const fn from_bits_128(v: u128) -> f128 {
unsafe { std::mem::transmute(v) }
+ //~^ ERROR: transmute from a `u128` to a `f128`
}
}
}
@@ -205,9 +213,13 @@ const fn test_const() {
//~^ ERROR: transmute from a `i128` to a `[u8; 16]`
let _: [u8; 2] = std::mem::transmute(0.0f16);
+ //~^ ERROR: transmute from a `f16` to a `[u8; 2]`
let _: [u8; 4] = std::mem::transmute(0.0f32);
+ //~^ ERROR: transmute from a `f32` to a `[u8; 4]`
let _: [u8; 8] = std::mem::transmute(0.0f64);
+ //~^ ERROR: transmute from a `f64` to a `[u8; 8]`
let _: [u8; 16] = std::mem::transmute(0.0f128);
+ //~^ ERROR: transmute from a `f128` to a `[u8; 16]`
}
}
}
diff --git a/src/tools/clippy/tests/ui/transmute.stderr b/src/tools/clippy/tests/ui/transmute.stderr
index 0072f62..41a10f3 100644
--- a/src/tools/clippy/tests/ui/transmute.stderr
+++ b/src/tools/clippy/tests/ui/transmute.stderr
@@ -148,8 +148,56 @@
LL | let _: f128 = unsafe { std::mem::transmute(0_i128) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `f128::from_bits(0_i128 as u128)`
+error: transmute from a `u16` to a `f16`
+ --> tests/ui/transmute.rs:142:39
+ |
+LL | const VALUE16: f16 = unsafe { std::mem::transmute(0_u16) };
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `f16::from_bits(0_u16)`
+
+error: transmute from a `u32` to a `f32`
+ --> tests/ui/transmute.rs:144:39
+ |
+LL | const VALUE32: f32 = unsafe { std::mem::transmute(0_u32) };
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `f32::from_bits(0_u32)`
+
+error: transmute from a `i64` to a `f64`
+ --> tests/ui/transmute.rs:146:39
+ |
+LL | const VALUE64: f64 = unsafe { std::mem::transmute(0_i64) };
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `f64::from_bits(0_i64 as u64)`
+
+error: transmute from a `i128` to a `f128`
+ --> tests/ui/transmute.rs:148:41
+ |
+LL | const VALUE128: f128 = unsafe { std::mem::transmute(0_i128) };
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `f128::from_bits(0_i128 as u128)`
+
+error: transmute from a `i16` to a `f16`
+ --> tests/ui/transmute.rs:152:22
+ |
+LL | unsafe { std::mem::transmute(v) }
+ | ^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `f16::from_bits(v as u16)`
+
+error: transmute from a `i32` to a `f32`
+ --> tests/ui/transmute.rs:157:22
+ |
+LL | unsafe { std::mem::transmute(v) }
+ | ^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `f32::from_bits(v as u32)`
+
+error: transmute from a `u64` to a `f64`
+ --> tests/ui/transmute.rs:162:22
+ |
+LL | unsafe { std::mem::transmute(v) }
+ | ^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `f64::from_bits(v)`
+
+error: transmute from a `u128` to a `f128`
+ --> tests/ui/transmute.rs:167:22
+ |
+LL | unsafe { std::mem::transmute(v) }
+ | ^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `f128::from_bits(v)`
+
error: transmute from a `u8` to a `[u8; 1]`
- --> tests/ui/transmute.rs:168:30
+ --> tests/ui/transmute.rs:176:30
|
LL | let _: [u8; 1] = std::mem::transmute(0u8);
| ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `to_ne_bytes()`: `0u8.to_ne_bytes()`
@@ -158,97 +206,121 @@
= help: to override `-D warnings` add `#[allow(clippy::transmute_num_to_bytes)]`
error: transmute from a `u32` to a `[u8; 4]`
- --> tests/ui/transmute.rs:171:30
+ --> tests/ui/transmute.rs:179:30
|
LL | let _: [u8; 4] = std::mem::transmute(0u32);
| ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `to_ne_bytes()`: `0u32.to_ne_bytes()`
error: transmute from a `u128` to a `[u8; 16]`
- --> tests/ui/transmute.rs:173:31
+ --> tests/ui/transmute.rs:181:31
|
LL | let _: [u8; 16] = std::mem::transmute(0u128);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `to_ne_bytes()`: `0u128.to_ne_bytes()`
error: transmute from a `i8` to a `[u8; 1]`
- --> tests/ui/transmute.rs:175:30
+ --> tests/ui/transmute.rs:183:30
|
LL | let _: [u8; 1] = std::mem::transmute(0i8);
| ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `to_ne_bytes()`: `0i8.to_ne_bytes()`
error: transmute from a `i32` to a `[u8; 4]`
- --> tests/ui/transmute.rs:177:30
+ --> tests/ui/transmute.rs:185:30
|
LL | let _: [u8; 4] = std::mem::transmute(0i32);
| ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `to_ne_bytes()`: `0i32.to_ne_bytes()`
error: transmute from a `i128` to a `[u8; 16]`
- --> tests/ui/transmute.rs:179:31
+ --> tests/ui/transmute.rs:187:31
|
LL | let _: [u8; 16] = std::mem::transmute(0i128);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `to_ne_bytes()`: `0i128.to_ne_bytes()`
error: transmute from a `f16` to a `[u8; 2]`
- --> tests/ui/transmute.rs:182:30
+ --> tests/ui/transmute.rs:190:30
|
LL | let _: [u8; 2] = std::mem::transmute(0.0f16);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `to_ne_bytes()`: `0.0f16.to_ne_bytes()`
error: transmute from a `f32` to a `[u8; 4]`
- --> tests/ui/transmute.rs:184:30
+ --> tests/ui/transmute.rs:192:30
|
LL | let _: [u8; 4] = std::mem::transmute(0.0f32);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `to_ne_bytes()`: `0.0f32.to_ne_bytes()`
error: transmute from a `f64` to a `[u8; 8]`
- --> tests/ui/transmute.rs:186:30
+ --> tests/ui/transmute.rs:194:30
|
LL | let _: [u8; 8] = std::mem::transmute(0.0f64);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `to_ne_bytes()`: `0.0f64.to_ne_bytes()`
error: transmute from a `f128` to a `[u8; 16]`
- --> tests/ui/transmute.rs:188:31
+ --> tests/ui/transmute.rs:196:31
|
LL | let _: [u8; 16] = std::mem::transmute(0.0f128);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `to_ne_bytes()`: `0.0f128.to_ne_bytes()`
error: transmute from a `u8` to a `[u8; 1]`
- --> tests/ui/transmute.rs:194:30
+ --> tests/ui/transmute.rs:202:30
|
LL | let _: [u8; 1] = std::mem::transmute(0u8);
| ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `to_ne_bytes()`: `0u8.to_ne_bytes()`
error: transmute from a `u32` to a `[u8; 4]`
- --> tests/ui/transmute.rs:196:30
+ --> tests/ui/transmute.rs:204:30
|
LL | let _: [u8; 4] = std::mem::transmute(0u32);
| ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `to_ne_bytes()`: `0u32.to_ne_bytes()`
error: transmute from a `u128` to a `[u8; 16]`
- --> tests/ui/transmute.rs:198:31
+ --> tests/ui/transmute.rs:206:31
|
LL | let _: [u8; 16] = std::mem::transmute(0u128);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `to_ne_bytes()`: `0u128.to_ne_bytes()`
error: transmute from a `i8` to a `[u8; 1]`
- --> tests/ui/transmute.rs:200:30
+ --> tests/ui/transmute.rs:208:30
|
LL | let _: [u8; 1] = std::mem::transmute(0i8);
| ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `to_ne_bytes()`: `0i8.to_ne_bytes()`
error: transmute from a `i32` to a `[u8; 4]`
- --> tests/ui/transmute.rs:202:30
+ --> tests/ui/transmute.rs:210:30
|
LL | let _: [u8; 4] = std::mem::transmute(0i32);
| ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `to_ne_bytes()`: `0i32.to_ne_bytes()`
error: transmute from a `i128` to a `[u8; 16]`
- --> tests/ui/transmute.rs:204:31
+ --> tests/ui/transmute.rs:212:31
|
LL | let _: [u8; 16] = std::mem::transmute(0i128);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `to_ne_bytes()`: `0i128.to_ne_bytes()`
+error: transmute from a `f16` to a `[u8; 2]`
+ --> tests/ui/transmute.rs:215:30
+ |
+LL | let _: [u8; 2] = std::mem::transmute(0.0f16);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `to_ne_bytes()`: `0.0f16.to_ne_bytes()`
+
+error: transmute from a `f32` to a `[u8; 4]`
+ --> tests/ui/transmute.rs:217:30
+ |
+LL | let _: [u8; 4] = std::mem::transmute(0.0f32);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `to_ne_bytes()`: `0.0f32.to_ne_bytes()`
+
+error: transmute from a `f64` to a `[u8; 8]`
+ --> tests/ui/transmute.rs:219:30
+ |
+LL | let _: [u8; 8] = std::mem::transmute(0.0f64);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `to_ne_bytes()`: `0.0f64.to_ne_bytes()`
+
+error: transmute from a `f128` to a `[u8; 16]`
+ --> tests/ui/transmute.rs:221:31
+ |
+LL | let _: [u8; 16] = std::mem::transmute(0.0f128);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `to_ne_bytes()`: `0.0f128.to_ne_bytes()`
+
error: transmute from a `&[u8]` to a `&str`
- --> tests/ui/transmute.rs:218:28
+ --> tests/ui/transmute.rs:230:28
|
LL | let _: &str = unsafe { std::mem::transmute(B) };
| ^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::str::from_utf8(B).unwrap()`
@@ -257,16 +329,16 @@
= help: to override `-D warnings` add `#[allow(clippy::transmute_bytes_to_str)]`
error: transmute from a `&mut [u8]` to a `&mut str`
- --> tests/ui/transmute.rs:221:32
+ --> tests/ui/transmute.rs:233:32
|
LL | let _: &mut str = unsafe { std::mem::transmute(mb) };
| ^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::str::from_utf8_mut(mb).unwrap()`
error: transmute from a `&[u8]` to a `&str`
- --> tests/ui/transmute.rs:223:30
+ --> tests/ui/transmute.rs:235:30
|
LL | const _: &str = unsafe { std::mem::transmute(B) };
| ^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::str::from_utf8_unchecked(B)`
-error: aborting due to 42 previous errors
+error: aborting due to 54 previous errors
diff --git a/src/tools/clippy/tests/ui/transmute_float_to_int.fixed b/src/tools/clippy/tests/ui/transmute_float_to_int.fixed
index 4361a74..83814ca 100644
--- a/src/tools/clippy/tests/ui/transmute_float_to_int.fixed
+++ b/src/tools/clippy/tests/ui/transmute_float_to_int.fixed
@@ -1,7 +1,7 @@
#![warn(clippy::transmute_float_to_int)]
#![allow(clippy::missing_transmute_annotations)]
-#![feature(f128)]
-#![feature(f16)]
+#![feature(f128, f128_const)]
+#![feature(f16, f16_const)]
fn float_to_int() {
let _: u32 = unsafe { 1f32.to_bits() };
@@ -20,25 +20,33 @@
}
mod issue_5747 {
- const VALUE16: i16 = unsafe { std::mem::transmute(1f16) };
- const VALUE32: i32 = unsafe { std::mem::transmute(1f32) };
- const VALUE64: u64 = unsafe { std::mem::transmute(1f64) };
- const VALUE128: u128 = unsafe { std::mem::transmute(1f128) };
+ const VALUE16: i16 = unsafe { 1f16.to_bits() as i16 };
+ //~^ ERROR: transmute from a `f16` to a `i16`
+ const VALUE32: i32 = unsafe { 1f32.to_bits() as i32 };
+ //~^ ERROR: transmute from a `f32` to a `i32`
+ const VALUE64: u64 = unsafe { 1f64.to_bits() };
+ //~^ ERROR: transmute from a `f64` to a `u64`
+ const VALUE128: u128 = unsafe { 1f128.to_bits() };
+ //~^ ERROR: transmute from a `f128` to a `u128`
const fn to_bits_16(v: f16) -> u16 {
- unsafe { std::mem::transmute(v) }
+ unsafe { v.to_bits() }
+ //~^ ERROR: transmute from a `f16` to a `u16`
}
const fn to_bits_32(v: f32) -> u32 {
- unsafe { std::mem::transmute(v) }
+ unsafe { v.to_bits() }
+ //~^ ERROR: transmute from a `f32` to a `u32`
}
const fn to_bits_64(v: f64) -> i64 {
- unsafe { std::mem::transmute(v) }
+ unsafe { v.to_bits() as i64 }
+ //~^ ERROR: transmute from a `f64` to a `i64`
}
const fn to_bits_128(v: f128) -> i128 {
- unsafe { std::mem::transmute(v) }
+ unsafe { v.to_bits() as i128 }
+ //~^ ERROR: transmute from a `f128` to a `i128`
}
}
diff --git a/src/tools/clippy/tests/ui/transmute_float_to_int.rs b/src/tools/clippy/tests/ui/transmute_float_to_int.rs
index 363ce0b..64d6e91 100644
--- a/src/tools/clippy/tests/ui/transmute_float_to_int.rs
+++ b/src/tools/clippy/tests/ui/transmute_float_to_int.rs
@@ -1,7 +1,7 @@
#![warn(clippy::transmute_float_to_int)]
#![allow(clippy::missing_transmute_annotations)]
-#![feature(f128)]
-#![feature(f16)]
+#![feature(f128, f128_const)]
+#![feature(f16, f16_const)]
fn float_to_int() {
let _: u32 = unsafe { std::mem::transmute(1f32) };
@@ -21,24 +21,32 @@ fn float_to_int() {
mod issue_5747 {
const VALUE16: i16 = unsafe { std::mem::transmute(1f16) };
+ //~^ ERROR: transmute from a `f16` to a `i16`
const VALUE32: i32 = unsafe { std::mem::transmute(1f32) };
+ //~^ ERROR: transmute from a `f32` to a `i32`
const VALUE64: u64 = unsafe { std::mem::transmute(1f64) };
+ //~^ ERROR: transmute from a `f64` to a `u64`
const VALUE128: u128 = unsafe { std::mem::transmute(1f128) };
+ //~^ ERROR: transmute from a `f128` to a `u128`
const fn to_bits_16(v: f16) -> u16 {
unsafe { std::mem::transmute(v) }
+ //~^ ERROR: transmute from a `f16` to a `u16`
}
const fn to_bits_32(v: f32) -> u32 {
unsafe { std::mem::transmute(v) }
+ //~^ ERROR: transmute from a `f32` to a `u32`
}
const fn to_bits_64(v: f64) -> i64 {
unsafe { std::mem::transmute(v) }
+ //~^ ERROR: transmute from a `f64` to a `i64`
}
const fn to_bits_128(v: f128) -> i128 {
unsafe { std::mem::transmute(v) }
+ //~^ ERROR: transmute from a `f128` to a `i128`
}
}
diff --git a/src/tools/clippy/tests/ui/transmute_float_to_int.stderr b/src/tools/clippy/tests/ui/transmute_float_to_int.stderr
index 9cac75f..0cabab5 100644
--- a/src/tools/clippy/tests/ui/transmute_float_to_int.stderr
+++ b/src/tools/clippy/tests/ui/transmute_float_to_int.stderr
@@ -37,5 +37,53 @@
LL | let _: u64 = unsafe { std::mem::transmute(-1.0) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `(-1.0f64).to_bits()`
-error: aborting due to 6 previous errors
+error: transmute from a `f16` to a `i16`
+ --> tests/ui/transmute_float_to_int.rs:23:35
+ |
+LL | const VALUE16: i16 = unsafe { std::mem::transmute(1f16) };
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `1f16.to_bits() as i16`
+
+error: transmute from a `f32` to a `i32`
+ --> tests/ui/transmute_float_to_int.rs:25:35
+ |
+LL | const VALUE32: i32 = unsafe { std::mem::transmute(1f32) };
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `1f32.to_bits() as i32`
+
+error: transmute from a `f64` to a `u64`
+ --> tests/ui/transmute_float_to_int.rs:27:35
+ |
+LL | const VALUE64: u64 = unsafe { std::mem::transmute(1f64) };
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `1f64.to_bits()`
+
+error: transmute from a `f128` to a `u128`
+ --> tests/ui/transmute_float_to_int.rs:29:37
+ |
+LL | const VALUE128: u128 = unsafe { std::mem::transmute(1f128) };
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `1f128.to_bits()`
+
+error: transmute from a `f16` to a `u16`
+ --> tests/ui/transmute_float_to_int.rs:33:18
+ |
+LL | unsafe { std::mem::transmute(v) }
+ | ^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `v.to_bits()`
+
+error: transmute from a `f32` to a `u32`
+ --> tests/ui/transmute_float_to_int.rs:38:18
+ |
+LL | unsafe { std::mem::transmute(v) }
+ | ^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `v.to_bits()`
+
+error: transmute from a `f64` to a `i64`
+ --> tests/ui/transmute_float_to_int.rs:43:18
+ |
+LL | unsafe { std::mem::transmute(v) }
+ | ^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `v.to_bits() as i64`
+
+error: transmute from a `f128` to a `i128`
+ --> tests/ui/transmute_float_to_int.rs:48:18
+ |
+LL | unsafe { std::mem::transmute(v) }
+ | ^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `v.to_bits() as i128`
+
+error: aborting due to 14 previous errors
diff --git a/src/tools/compiletest/src/lib.rs b/src/tools/compiletest/src/lib.rs
index 5402e69..33687a3 100644
--- a/src/tools/compiletest/src/lib.rs
+++ b/src/tools/compiletest/src/lib.rs
@@ -808,8 +808,12 @@ fn make_test(
&config, cache, test_name, &test_path, src_file, revision, poisoned,
);
// Ignore tests that already run and are up to date with respect to inputs.
- if !config.force_rerun {
- desc.ignore |= is_up_to_date(&config, testpaths, &early_props, revision, inputs);
+ if !config.force_rerun
+ && is_up_to_date(&config, testpaths, &early_props, revision, inputs)
+ {
+ desc.ignore = true;
+ // Keep this in sync with the "up-to-date" message detected by bootstrap.
+ desc.ignore_message = Some("up-to-date");
}
test::TestDescAndFn {
desc,
diff --git a/src/tools/enzyme b/src/tools/enzyme
new file mode 160000
index 0000000..2fe5164
--- /dev/null
+++ b/src/tools/enzyme
@@ -0,0 +1 @@
+Subproject commit 2fe5164a2423dd67ef25e2c4fb204fd06362494b
diff --git a/src/tools/jsondoclint/src/item_kind.rs b/src/tools/jsondoclint/src/item_kind.rs
index 7d6ec47..5114683 100644
--- a/src/tools/jsondoclint/src/item_kind.rs
+++ b/src/tools/jsondoclint/src/item_kind.rs
@@ -5,7 +5,7 @@
pub(crate) enum Kind {
Module,
ExternCrate,
- Import,
+ Use,
Struct,
StructField,
Union,
@@ -18,7 +18,7 @@ pub(crate) enum Kind {
TraitAlias,
Impl,
Static,
- ForeignType,
+ ExternType,
Macro,
ProcAttribute,
ProcDerive,
@@ -36,7 +36,7 @@ pub fn can_appear_in_mod(self) -> bool {
match self {
Module => true,
ExternCrate => true,
- Import => true,
+ Use => true,
Union => true,
Struct => true,
Enum => true,
@@ -50,7 +50,7 @@ pub fn can_appear_in_mod(self) -> bool {
Macro => true,
ProcMacro => true,
Primitive => true,
- ForeignType => true,
+ ExternType => true,
// FIXME(adotinthevoid): I'm not sure if these are correct
Keyword => false,
@@ -69,7 +69,7 @@ pub fn can_appear_in_mod(self) -> bool {
pub fn can_appear_in_import(self) -> bool {
match self {
Kind::Variant => true,
- Kind::Import => false,
+ Kind::Use => false,
other => other.can_appear_in_mod(),
}
}
@@ -90,7 +90,7 @@ pub fn can_appear_in_trait(self) -> bool {
Kind::Module => false,
Kind::ExternCrate => false,
- Kind::Import => false,
+ Kind::Use => false,
Kind::Struct => false,
Kind::StructField => false,
Kind::Union => false,
@@ -102,7 +102,7 @@ pub fn can_appear_in_trait(self) -> bool {
Kind::TraitAlias => false,
Kind::Impl => false,
Kind::Static => false,
- Kind::ForeignType => false,
+ Kind::ExternType => false,
Kind::Macro => false,
Kind::ProcAttribute => false,
Kind::ProcDerive => false,
@@ -135,7 +135,7 @@ pub fn from_item(i: &Item) -> Self {
use Kind::*;
match i.inner {
ItemEnum::Module(_) => Module,
- ItemEnum::Import(_) => Import,
+ ItemEnum::Use(_) => Use,
ItemEnum::Union(_) => Union,
ItemEnum::Struct(_) => Struct,
ItemEnum::StructField(_) => StructField,
@@ -151,7 +151,7 @@ pub fn from_item(i: &Item) -> Self {
ItemEnum::Macro(_) => Macro,
ItemEnum::ProcMacro(_) => ProcMacro,
ItemEnum::Primitive(_) => Primitive,
- ItemEnum::ForeignType => ForeignType,
+ ItemEnum::ExternType => ExternType,
ItemEnum::ExternCrate { .. } => ExternCrate,
ItemEnum::AssocConst { .. } => AssocConst,
ItemEnum::AssocType { .. } => AssocType,
@@ -166,10 +166,10 @@ pub fn from_summary(s: &ItemSummary) -> Self {
ItemKind::Constant => Constant,
ItemKind::Enum => Enum,
ItemKind::ExternCrate => ExternCrate,
- ItemKind::ForeignType => ForeignType,
+ ItemKind::ExternType => ExternType,
ItemKind::Function => Function,
ItemKind::Impl => Impl,
- ItemKind::Import => Import,
+ ItemKind::Use => Use,
ItemKind::Keyword => Keyword,
ItemKind::Macro => Macro,
ItemKind::Module => Module,
diff --git a/src/tools/jsondoclint/src/validator.rs b/src/tools/jsondoclint/src/validator.rs
index 0ffb96b..10ab62c 100644
--- a/src/tools/jsondoclint/src/validator.rs
+++ b/src/tools/jsondoclint/src/validator.rs
@@ -2,10 +2,11 @@
use std::hash::Hash;
use rustdoc_json_types::{
- Constant, Crate, DynTrait, Enum, FnDecl, Function, FunctionPointer, GenericArg, GenericArgs,
- GenericBound, GenericParamDef, Generics, Id, Impl, Import, ItemEnum, ItemSummary, Module, Path,
- Primitive, ProcMacro, Static, Struct, StructKind, Term, Trait, TraitAlias, Type, TypeAlias,
- TypeBinding, TypeBindingKind, Union, Variant, VariantKind, WherePredicate,
+ AssocItemConstraint, AssocItemConstraintKind, Constant, Crate, DynTrait, Enum, Function,
+ FunctionPointer, FunctionSignature, GenericArg, GenericArgs, GenericBound, GenericParamDef,
+ Generics, Id, Impl, ItemEnum, ItemSummary, Module, Path, Primitive, ProcMacro, Static, Struct,
+ StructKind, Term, Trait, TraitAlias, Type, TypeAlias, Union, Use, Variant, VariantKind,
+ WherePredicate,
};
use serde_json::Value;
@@ -90,7 +91,7 @@ fn check_item(&mut self, id: &'a Id) {
item.links.values().for_each(|id| self.add_any_id(id));
match &item.inner {
- ItemEnum::Import(x) => self.check_import(x),
+ ItemEnum::Use(x) => self.check_use(x),
ItemEnum::Union(x) => self.check_union(x),
ItemEnum::Struct(x) => self.check_struct(x),
ItemEnum::StructField(x) => self.check_struct_field(x),
@@ -106,18 +107,18 @@ fn check_item(&mut self, id: &'a Id) {
self.check_constant(const_);
}
ItemEnum::Static(x) => self.check_static(x),
- ItemEnum::ForeignType => {} // nop
+ ItemEnum::ExternType => {} // nop
ItemEnum::Macro(x) => self.check_macro(x),
ItemEnum::ProcMacro(x) => self.check_proc_macro(x),
ItemEnum::Primitive(x) => self.check_primitive_type(x),
ItemEnum::Module(x) => self.check_module(x, id),
// FIXME: Why don't these have their own structs?
ItemEnum::ExternCrate { .. } => {}
- ItemEnum::AssocConst { type_, default: _ } => self.check_type(type_),
- ItemEnum::AssocType { generics, bounds, default } => {
+ ItemEnum::AssocConst { type_, value: _ } => self.check_type(type_),
+ ItemEnum::AssocType { generics, bounds, type_ } => {
self.check_generics(generics);
bounds.iter().for_each(|b| self.check_generic_bound(b));
- if let Some(ty) = default {
+ if let Some(ty) = type_ {
self.check_type(ty);
}
}
@@ -133,8 +134,8 @@ fn check_module(&mut self, module: &'a Module, id: &Id) {
module.items.iter().for_each(|i| self.add_mod_item_id(i));
}
- fn check_import(&mut self, x: &'a Import) {
- if x.glob {
+ fn check_use(&mut self, x: &'a Use) {
+ if x.is_glob {
self.add_glob_import_item_id(x.id.as_ref().unwrap());
} else if let Some(id) = &x.id {
self.add_import_item_id(id);
@@ -152,7 +153,7 @@ fn check_struct(&mut self, x: &'a Struct) {
match &x.kind {
StructKind::Unit => {}
StructKind::Tuple(fields) => fields.iter().flatten().for_each(|f| self.add_field_id(f)),
- StructKind::Plain { fields, fields_stripped: _ } => {
+ StructKind::Plain { fields, has_stripped_fields: _ } => {
fields.iter().for_each(|f| self.add_field_id(f))
}
}
@@ -187,7 +188,7 @@ fn check_variant(&mut self, x: &'a Variant, id: &'a Id) {
match kind {
VariantKind::Plain => {}
VariantKind::Tuple(tys) => tys.iter().flatten().for_each(|t| self.add_field_id(t)),
- VariantKind::Struct { fields, fields_stripped: _ } => {
+ VariantKind::Struct { fields, has_stripped_fields: _ } => {
fields.iter().for_each(|f| self.add_field_id(f))
}
}
@@ -195,7 +196,7 @@ fn check_variant(&mut self, x: &'a Variant, id: &'a Id) {
fn check_function(&mut self, x: &'a Function) {
self.check_generics(&x.generics);
- self.check_fn_decl(&x.decl);
+ self.check_function_signature(&x.sig);
}
fn check_trait(&mut self, x: &'a Trait, id: &Id) {
@@ -267,8 +268,8 @@ fn check_type(&mut self, x: &'a Type) {
Type::Array { type_, len: _ } => self.check_type(&**type_),
Type::ImplTrait(bounds) => bounds.iter().for_each(|b| self.check_generic_bound(b)),
Type::Infer => {}
- Type::RawPointer { mutable: _, type_ } => self.check_type(&**type_),
- Type::BorrowedRef { lifetime: _, mutable: _, type_ } => self.check_type(&**type_),
+ Type::RawPointer { is_mutable: _, type_ } => self.check_type(&**type_),
+ Type::BorrowedRef { lifetime: _, is_mutable: _, type_ } => self.check_type(&**type_),
Type::QualifiedPath { name: _, args, self_type, trait_ } => {
self.check_generic_args(&**args);
self.check_type(&**self_type);
@@ -279,7 +280,7 @@ fn check_type(&mut self, x: &'a Type) {
}
}
- fn check_fn_decl(&mut self, x: &'a FnDecl) {
+ fn check_function_signature(&mut self, x: &'a FunctionSignature) {
x.inputs.iter().for_each(|(_name, ty)| self.check_type(ty));
if let Some(output) = &x.output {
self.check_type(output);
@@ -309,9 +310,9 @@ fn check_path(&mut self, x: &'a Path, kind: PathKind) {
fn check_generic_args(&mut self, x: &'a GenericArgs) {
match x {
- GenericArgs::AngleBracketed { args, bindings } => {
+ GenericArgs::AngleBracketed { args, constraints } => {
args.iter().for_each(|arg| self.check_generic_arg(arg));
- bindings.iter().for_each(|bind| self.check_type_binding(bind));
+ constraints.iter().for_each(|bind| self.check_assoc_item_constraint(bind));
}
GenericArgs::Parenthesized { inputs, output } => {
inputs.iter().for_each(|ty| self.check_type(ty));
@@ -325,7 +326,7 @@ fn check_generic_args(&mut self, x: &'a GenericArgs) {
fn check_generic_param_def(&mut self, gpd: &'a GenericParamDef) {
match &gpd.kind {
rustdoc_json_types::GenericParamDefKind::Lifetime { outlives: _ } => {}
- rustdoc_json_types::GenericParamDefKind::Type { bounds, default, synthetic: _ } => {
+ rustdoc_json_types::GenericParamDefKind::Type { bounds, default, is_synthetic: _ } => {
bounds.iter().for_each(|b| self.check_generic_bound(b));
if let Some(ty) = default {
self.check_type(ty);
@@ -346,11 +347,11 @@ fn check_generic_arg(&mut self, arg: &'a GenericArg) {
}
}
- fn check_type_binding(&mut self, bind: &'a TypeBinding) {
+ fn check_assoc_item_constraint(&mut self, bind: &'a AssocItemConstraint) {
self.check_generic_args(&bind.args);
match &bind.binding {
- TypeBindingKind::Equality(term) => self.check_term(term),
- TypeBindingKind::Constraint(bounds) => {
+ AssocItemConstraintKind::Equality(term) => self.check_term(term),
+ AssocItemConstraintKind::Constraint(bounds) => {
bounds.iter().for_each(|b| self.check_generic_bound(b))
}
}
@@ -388,7 +389,7 @@ fn check_dyn_trait(&mut self, dyn_trait: &'a DynTrait) {
}
fn check_function_pointer(&mut self, fp: &'a FunctionPointer) {
- self.check_fn_decl(&fp.decl);
+ self.check_function_signature(&fp.sig);
fp.generic_params.iter().for_each(|gpd| self.check_generic_param_def(gpd));
}
diff --git a/src/tools/lint-docs/src/lib.rs b/src/tools/lint-docs/src/lib.rs
index 72bb9db..532a27b 100644
--- a/src/tools/lint-docs/src/lib.rs
+++ b/src/tools/lint-docs/src/lib.rs
@@ -56,6 +56,8 @@ pub struct LintExtractor<'a> {
pub rustc_path: &'a Path,
/// The target arch to build the docs for.
pub rustc_target: &'a str,
+ /// The target linker overriding `rustc`'s default
+ pub rustc_linker: Option<&'a str>,
/// Verbose output.
pub verbose: bool,
/// Validate the style and the code example.
@@ -459,6 +461,9 @@ fn generate_lint_output(
}
cmd.arg("--error-format=json");
cmd.arg("--target").arg(self.rustc_target);
+ if let Some(target_linker) = self.rustc_linker {
+ cmd.arg(format!("-Clinker={target_linker}"));
+ }
if options.contains(&"test") {
cmd.arg("--test");
}
diff --git a/src/tools/lint-docs/src/main.rs b/src/tools/lint-docs/src/main.rs
index 2055fed..e377283 100644
--- a/src/tools/lint-docs/src/main.rs
+++ b/src/tools/lint-docs/src/main.rs
@@ -27,6 +27,7 @@ fn doit() -> Result<(), Box<dyn Error>> {
let mut out_path = None;
let mut rustc_path = None;
let mut rustc_target = None;
+ let mut rustc_linker = None;
let mut verbose = false;
let mut validate = false;
while let Some(arg) = args.next() {
@@ -55,6 +56,12 @@ fn doit() -> Result<(), Box<dyn Error>> {
None => return Err("--rustc-target requires a value".into()),
};
}
+ "--rustc-linker" => {
+ rustc_linker = match args.next() {
+ Some(s) => Some(s),
+ None => return Err("--rustc-linker requires a value".into()),
+ };
+ }
"-v" | "--verbose" => verbose = true,
"--validate" => validate = true,
s => return Err(format!("unexpected argument `{}`", s).into()),
@@ -77,6 +84,7 @@ fn doit() -> Result<(), Box<dyn Error>> {
out_path: &out_path.unwrap(),
rustc_path: &rustc_path.unwrap(),
rustc_target: &rustc_target.unwrap(),
+ rustc_linker: rustc_linker.as_deref(),
verbose,
validate,
};
diff --git a/src/tools/miri/Cargo.toml b/src/tools/miri/Cargo.toml
index 4b7f348..d8cfa5b 100644
--- a/src/tools/miri/Cargo.toml
+++ b/src/tools/miri/Cargo.toml
@@ -37,8 +37,6 @@
[target.'cfg(unix)'.dependencies]
libc = "0.2"
-
-[target.'cfg(target_os = "linux")'.dependencies]
libffi = "3.2.0"
libloading = "0.8"
diff --git a/src/tools/miri/README.md b/src/tools/miri/README.md
index 5821adb..dbb0e8a 100644
--- a/src/tools/miri/README.md
+++ b/src/tools/miri/README.md
@@ -383,7 +383,7 @@
file descriptors will be mixed up.
This is **work in progress**; currently, only integer arguments and return values are
supported (and no, pointer/integer casts to work around this limitation will not work;
- they will fail horribly). It also only works on Linux hosts for now.
+ they will fail horribly). It also only works on Unix hosts for now.
* `-Zmiri-measureme=<name>` enables `measureme` profiling for the interpreted program.
This can be used to find which parts of your program are executing slowly under Miri.
The profile is written out to a file inside a directory called `<name>`, and can be processed
diff --git a/src/tools/miri/miri.bat b/src/tools/miri/miri.bat
index 6f9a8f3..b046b63 100644
--- a/src/tools/miri/miri.bat
+++ b/src/tools/miri/miri.bat
@@ -5,8 +5,8 @@
:: If any other steps are added, the "|| exit /b" must be appended to early
:: return from the script. If not, it will continue execution.
-cargo +stable build %CARGO_EXTRA_FLAGS% -q --target-dir %MIRI_SCRIPT_TARGET_DIR% --manifest-path %0\..\miri-script\Cargo.toml ^
- || (echo Failed to build miri-script. Is the 'stable' toolchain installed? & exit /b)
+cargo +nightly build %CARGO_EXTRA_FLAGS% -q --target-dir %MIRI_SCRIPT_TARGET_DIR% --manifest-path %0\..\miri-script\Cargo.toml ^
+ || (echo Failed to build miri-script. Is the 'nightly' toolchain installed? & exit /b)
:: Forwards all arguments to this file to the executable.
:: We invoke the binary directly to avoid going through rustup, which would set some extra
diff --git a/src/tools/miri/rust-version b/src/tools/miri/rust-version
index c33d9ad..3fdad2a 100644
--- a/src/tools/miri/rust-version
+++ b/src/tools/miri/rust-version
@@ -1 +1 @@
-0d634185dfddefe09047881175f35c65d68dcff1
+54fdef7799d9ff9470bb5cabd29fde9471a99eaa
diff --git a/src/tools/miri/src/alloc_addresses/mod.rs b/src/tools/miri/src/alloc_addresses/mod.rs
index 76c68ad..c19a962 100644
--- a/src/tools/miri/src/alloc_addresses/mod.rs
+++ b/src/tools/miri/src/alloc_addresses/mod.rs
@@ -5,7 +5,6 @@
use std::cell::RefCell;
use std::cmp::max;
-use std::collections::hash_map::Entry;
use rand::Rng;
@@ -151,6 +150,95 @@ fn alloc_id_from_addr(&self, addr: u64, size: i64) -> Option<AllocId> {
}
}
+ fn addr_from_alloc_id_uncached(
+ &self,
+ global_state: &mut GlobalStateInner,
+ alloc_id: AllocId,
+ memory_kind: MemoryKind,
+ ) -> InterpResult<'tcx, u64> {
+ let ecx = self.eval_context_ref();
+ let mut rng = ecx.machine.rng.borrow_mut();
+ let (size, align, kind) = ecx.get_alloc_info(alloc_id);
+ // This is either called immediately after allocation (and then cached), or when
+ // adjusting `tcx` pointers (which never get freed). So assert that we are looking
+ // at a live allocation. This also ensures that we never re-assign an address to an
+ // allocation that previously had an address, but then was freed and the address
+ // information was removed.
+ assert!(!matches!(kind, AllocKind::Dead));
+
+ // This allocation does not have a base address yet, pick or reuse one.
+ if ecx.machine.native_lib.is_some() {
+ // In native lib mode, we use the "real" address of the bytes for this allocation.
+ // This ensures the interpreted program and native code have the same view of memory.
+ let base_ptr = match kind {
+ AllocKind::LiveData => {
+ if ecx.tcx.try_get_global_alloc(alloc_id).is_some() {
+ // For new global allocations, we always pre-allocate the memory to be able use the machine address directly.
+ let prepared_bytes = MiriAllocBytes::zeroed(size, align)
+ .unwrap_or_else(|| {
+ panic!("Miri ran out of memory: cannot create allocation of {size:?} bytes")
+ });
+ let ptr = prepared_bytes.as_ptr();
+ // Store prepared allocation space to be picked up for use later.
+ global_state
+ .prepared_alloc_bytes
+ .try_insert(alloc_id, prepared_bytes)
+ .unwrap();
+ ptr
+ } else {
+ ecx.get_alloc_bytes_unchecked_raw(alloc_id)?
+ }
+ }
+ AllocKind::Function | AllocKind::VTable => {
+ // Allocate some dummy memory to get a unique address for this function/vtable.
+ let alloc_bytes =
+ MiriAllocBytes::from_bytes(&[0u8; 1], Align::from_bytes(1).unwrap());
+ let ptr = alloc_bytes.as_ptr();
+ // Leak the underlying memory to ensure it remains unique.
+ std::mem::forget(alloc_bytes);
+ ptr
+ }
+ AllocKind::Dead => unreachable!(),
+ };
+ // Ensure this pointer's provenance is exposed, so that it can be used by FFI code.
+ return Ok(base_ptr.expose_provenance().try_into().unwrap());
+ }
+ // We are not in native lib mode, so we control the addresses ourselves.
+ if let Some((reuse_addr, clock)) =
+ global_state.reuse.take_addr(&mut *rng, size, align, memory_kind, ecx.active_thread())
+ {
+ if let Some(clock) = clock {
+ ecx.acquire_clock(&clock);
+ }
+ Ok(reuse_addr)
+ } else {
+ // We have to pick a fresh address.
+ // Leave some space to the previous allocation, to give it some chance to be less aligned.
+ // We ensure that `(global_state.next_base_addr + slack) % 16` is uniformly distributed.
+ let slack = rng.gen_range(0..16);
+ // From next_base_addr + slack, round up to adjust for alignment.
+ let base_addr = global_state
+ .next_base_addr
+ .checked_add(slack)
+ .ok_or_else(|| err_exhaust!(AddressSpaceFull))?;
+ let base_addr = align_addr(base_addr, align.bytes());
+
+ // Remember next base address. If this allocation is zero-sized, leave a gap of at
+ // least 1 to avoid two allocations having the same base address. (The logic in
+ // `alloc_id_from_addr` assumes unique addresses, and different function/vtable pointers
+ // need to be distinguishable!)
+ global_state.next_base_addr = base_addr
+ .checked_add(max(size.bytes(), 1))
+ .ok_or_else(|| err_exhaust!(AddressSpaceFull))?;
+ // Even if `Size` didn't overflow, we might still have filled up the address space.
+ if global_state.next_base_addr > ecx.target_usize_max() {
+ throw_exhaust!(AddressSpaceFull);
+ }
+
+ Ok(base_addr)
+ }
+ }
+
fn addr_from_alloc_id(
&self,
alloc_id: AllocId,
@@ -160,98 +248,16 @@ fn addr_from_alloc_id(
let mut global_state = ecx.machine.alloc_addresses.borrow_mut();
let global_state = &mut *global_state;
- Ok(match global_state.base_addr.entry(alloc_id) {
- Entry::Occupied(entry) => *entry.get(),
- Entry::Vacant(entry) => {
- let mut rng = ecx.machine.rng.borrow_mut();
- let (size, align, kind) = ecx.get_alloc_info(alloc_id);
- // This is either called immediately after allocation (and then cached), or when
- // adjusting `tcx` pointers (which never get freed). So assert that we are looking
- // at a live allocation. This also ensures that we never re-assign an address to an
- // allocation that previously had an address, but then was freed and the address
- // information was removed.
- assert!(!matches!(kind, AllocKind::Dead));
-
- // This allocation does not have a base address yet, pick or reuse one.
- let base_addr = if ecx.machine.native_lib.is_some() {
- // In native lib mode, we use the "real" address of the bytes for this allocation.
- // This ensures the interpreted program and native code have the same view of memory.
- match kind {
- AllocKind::LiveData => {
- let ptr = if ecx.tcx.try_get_global_alloc(alloc_id).is_some() {
- // For new global allocations, we always pre-allocate the memory to be able use the machine address directly.
- let prepared_bytes = MiriAllocBytes::zeroed(size, align)
- .unwrap_or_else(|| {
- panic!("Miri ran out of memory: cannot create allocation of {size:?} bytes")
- });
- let ptr = prepared_bytes.as_ptr();
- // Store prepared allocation space to be picked up for use later.
- global_state.prepared_alloc_bytes.try_insert(alloc_id, prepared_bytes).unwrap();
- ptr
- } else {
- ecx.get_alloc_bytes_unchecked_raw(alloc_id)?
- };
- // Ensure this pointer's provenance is exposed, so that it can be used by FFI code.
- ptr.expose_provenance().try_into().unwrap()
- }
- AllocKind::Function | AllocKind::VTable => {
- // Allocate some dummy memory to get a unique address for this function/vtable.
- let alloc_bytes = MiriAllocBytes::from_bytes(&[0u8; 1], Align::from_bytes(1).unwrap());
- // We don't need to expose these bytes as nobody is allowed to access them.
- let addr = alloc_bytes.as_ptr().addr().try_into().unwrap();
- // Leak the underlying memory to ensure it remains unique.
- std::mem::forget(alloc_bytes);
- addr
- }
- AllocKind::Dead => unreachable!()
- }
- } else if let Some((reuse_addr, clock)) = global_state.reuse.take_addr(
- &mut *rng,
- size,
- align,
- memory_kind,
- ecx.active_thread(),
- ) {
- if let Some(clock) = clock {
- ecx.acquire_clock(&clock);
- }
- reuse_addr
- } else {
- // We have to pick a fresh address.
- // Leave some space to the previous allocation, to give it some chance to be less aligned.
- // We ensure that `(global_state.next_base_addr + slack) % 16` is uniformly distributed.
- let slack = rng.gen_range(0..16);
- // From next_base_addr + slack, round up to adjust for alignment.
- let base_addr = global_state
- .next_base_addr
- .checked_add(slack)
- .ok_or_else(|| err_exhaust!(AddressSpaceFull))?;
- let base_addr = align_addr(base_addr, align.bytes());
-
- // Remember next base address. If this allocation is zero-sized, leave a gap
- // of at least 1 to avoid two allocations having the same base address.
- // (The logic in `alloc_id_from_addr` assumes unique addresses, and different
- // function/vtable pointers need to be distinguishable!)
- global_state.next_base_addr = base_addr
- .checked_add(max(size.bytes(), 1))
- .ok_or_else(|| err_exhaust!(AddressSpaceFull))?;
- // Even if `Size` didn't overflow, we might still have filled up the address space.
- if global_state.next_base_addr > ecx.target_usize_max() {
- throw_exhaust!(AddressSpaceFull);
- }
-
- base_addr
- };
- trace!(
- "Assigning base address {:#x} to allocation {:?} (size: {}, align: {})",
- base_addr,
- alloc_id,
- size.bytes(),
- align.bytes(),
- );
+ match global_state.base_addr.get(&alloc_id) {
+ Some(&addr) => Ok(addr),
+ None => {
+ // First time we're looking for the absolute address of this allocation.
+ let base_addr =
+ self.addr_from_alloc_id_uncached(global_state, alloc_id, memory_kind)?;
+ trace!("Assigning base address {:#x} to allocation {:?}", base_addr, alloc_id);
// Store address in cache.
- entry.insert(base_addr);
+ global_state.base_addr.try_insert(alloc_id, base_addr).unwrap();
// Also maintain the opposite mapping in `int_to_ptr_map`, ensuring we keep it sorted.
// We have a fast-path for the common case that this address is bigger than all previous ones.
@@ -269,9 +275,9 @@ fn addr_from_alloc_id(
};
global_state.int_to_ptr_map.insert(pos, (base_addr, alloc_id));
- base_addr
+ Ok(base_addr)
}
- })
+ }
}
}
@@ -359,16 +365,23 @@ fn adjust_alloc_root_pointer(
// This returns some prepared `MiriAllocBytes`, either because `addr_from_alloc_id` reserved
// memory space in the past, or by doing the pre-allocation right upon being called.
- fn get_global_alloc_bytes(&self, id: AllocId, kind: MemoryKind, bytes: &[u8], align: Align) -> InterpResult<'tcx, MiriAllocBytes> {
+ fn get_global_alloc_bytes(
+ &self,
+ id: AllocId,
+ kind: MemoryKind,
+ bytes: &[u8],
+ align: Align,
+ ) -> InterpResult<'tcx, MiriAllocBytes> {
let ecx = self.eval_context_ref();
- Ok(if ecx.machine.native_lib.is_some() {
+ if ecx.machine.native_lib.is_some() {
// In native lib mode, MiriAllocBytes for global allocations are handled via `prepared_alloc_bytes`.
- // This additional call ensures that some `MiriAllocBytes` are always prepared.
+ // This additional call ensures that some `MiriAllocBytes` are always prepared, just in case
+ // this function gets called before the first time `addr_from_alloc_id` gets called.
ecx.addr_from_alloc_id(id, kind)?;
- let mut global_state = ecx.machine.alloc_addresses.borrow_mut();
// The memory we need here will have already been allocated during an earlier call to
// `addr_from_alloc_id` for this allocation. So don't create a new `MiriAllocBytes` here, instead
// fetch the previously prepared bytes from `prepared_alloc_bytes`.
+ let mut global_state = ecx.machine.alloc_addresses.borrow_mut();
let mut prepared_alloc_bytes = global_state
.prepared_alloc_bytes
.remove(&id)
@@ -378,10 +391,10 @@ fn get_global_alloc_bytes(&self, id: AllocId, kind: MemoryKind, bytes: &[u8], al
assert_eq!(prepared_alloc_bytes.len(), bytes.len());
// Copy allocation contents into prepared memory.
prepared_alloc_bytes.copy_from_slice(bytes);
- prepared_alloc_bytes
+ Ok(prepared_alloc_bytes)
} else {
- MiriAllocBytes::from_bytes(std::borrow::Cow::Borrowed(&*bytes), align)
- })
+ Ok(MiriAllocBytes::from_bytes(std::borrow::Cow::Borrowed(bytes), align))
+ }
}
/// When a pointer is used for a memory access, this computes where in which allocation the
diff --git a/src/tools/miri/src/concurrency/data_race.rs b/src/tools/miri/src/concurrency/data_race.rs
index 6fd207c..b604fd8 100644
--- a/src/tools/miri/src/concurrency/data_race.rs
+++ b/src/tools/miri/src/concurrency/data_race.rs
@@ -637,7 +637,7 @@ fn write_scalar_atomic(
// The program didn't actually do a read, so suppress the memory access hooks.
// This is also a very special exception where we just ignore an error -- if this read
// was UB e.g. because the memory is uninitialized, we don't want to know!
- let old_val = this.run_for_validation(|| this.read_scalar(dest)).ok();
+ let old_val = this.run_for_validation(|this| this.read_scalar(dest)).ok();
this.allow_data_races_mut(move |this| this.write_scalar(val, dest))?;
this.validate_atomic_store(dest, atomic)?;
this.buffered_atomic_write(val, dest, atomic, old_val)
diff --git a/src/tools/miri/src/concurrency/init_once.rs b/src/tools/miri/src/concurrency/init_once.rs
index c23e573..d709e4e 100644
--- a/src/tools/miri/src/concurrency/init_once.rs
+++ b/src/tools/miri/src/concurrency/init_once.rs
@@ -35,8 +35,14 @@ fn init_once_get_or_create_id(
offset: u64,
) -> InterpResult<'tcx, InitOnceId> {
let this = self.eval_context_mut();
- this.get_or_create_id(lock_op, lock_layout, offset, |ecx| &mut ecx.machine.sync.init_onces)?
- .ok_or_else(|| err_ub_format!("init_once has invalid ID").into())
+ this.get_or_create_id(
+ lock_op,
+ lock_layout,
+ offset,
+ |ecx| &mut ecx.machine.sync.init_onces,
+ |_| Ok(Default::default()),
+ )?
+ .ok_or_else(|| err_ub_format!("init_once has invalid ID").into())
}
#[inline]
diff --git a/src/tools/miri/src/concurrency/sync.rs b/src/tools/miri/src/concurrency/sync.rs
index d972831..97e910d 100644
--- a/src/tools/miri/src/concurrency/sync.rs
+++ b/src/tools/miri/src/concurrency/sync.rs
@@ -66,6 +66,27 @@ pub fn to_u32_scalar(&self) -> Scalar {
declare_id!(MutexId);
+/// The mutex kind.
+#[derive(Debug, Clone, Copy)]
+#[non_exhaustive]
+pub enum MutexKind {
+ Invalid,
+ Normal,
+ Default,
+ Recursive,
+ ErrorCheck,
+}
+
+#[derive(Debug)]
+/// Additional data that may be used by shim implementations.
+pub struct AdditionalMutexData {
+ /// The mutex kind, used by some mutex implementations like pthreads mutexes.
+ pub kind: MutexKind,
+
+ /// The address of the mutex.
+ pub address: u64,
+}
+
/// The mutex state.
#[derive(Default, Debug)]
struct Mutex {
@@ -77,6 +98,9 @@ struct Mutex {
queue: VecDeque<ThreadId>,
/// Mutex clock. This tracks the moment of the last unlock.
clock: VClock,
+
+ /// Additional data that can be set by shim implementations.
+ data: Option<AdditionalMutexData>,
}
declare_id!(RwLockId);
@@ -168,13 +192,15 @@ pub(super) trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> {
/// Returns `None` if memory stores a non-zero invalid ID.
///
/// `get_objs` must return the `IndexVec` that stores all the objects of this type.
+ /// `create_obj` must create the new object if initialization is needed.
#[inline]
- fn get_or_create_id<Id: SyncId + Idx, T: Default>(
+ fn get_or_create_id<Id: SyncId + Idx, T>(
&mut self,
lock_op: &OpTy<'tcx>,
lock_layout: TyAndLayout<'tcx>,
offset: u64,
get_objs: impl for<'a> Fn(&'a mut MiriInterpCx<'tcx>) -> &'a mut IndexVec<Id, T>,
+ create_obj: impl for<'a> FnOnce(&'a mut MiriInterpCx<'tcx>) -> InterpResult<'tcx, T>,
) -> InterpResult<'tcx, Option<Id>> {
let this = self.eval_context_mut();
let value_place =
@@ -196,7 +222,8 @@ fn get_or_create_id<Id: SyncId + Idx, T: Default>(
Ok(if success.to_bool().expect("compare_exchange's second return value is a bool") {
// We set the in-memory ID to `next_index`, now also create this object in the machine
// state.
- let new_index = get_objs(this).push(T::default());
+ let obj = create_obj(this)?;
+ let new_index = get_objs(this).push(obj);
assert_eq!(next_index, new_index);
Some(new_index)
} else {
@@ -210,6 +237,32 @@ fn get_or_create_id<Id: SyncId + Idx, T: Default>(
})
}
+ /// Eagerly creates a Miri sync structure.
+ ///
+ /// `create_id` will store the index of the sync_structure in the memory pointed to by
+ /// `lock_op`, so that future calls to `get_or_create_id` will see it as initialized.
+ /// - `lock_op` must hold a pointer to the sync structure.
+ /// - `lock_layout` must be the memory layout of the sync structure.
+ /// - `offset` must be the offset inside the sync structure where its miri id will be stored.
+ /// - `get_objs` is described in `get_or_create_id`.
+ /// - `obj` must be the new sync object.
+ fn create_id<Id: SyncId + Idx, T>(
+ &mut self,
+ lock_op: &OpTy<'tcx>,
+ lock_layout: TyAndLayout<'tcx>,
+ offset: u64,
+ get_objs: impl for<'a> Fn(&'a mut MiriInterpCx<'tcx>) -> &'a mut IndexVec<Id, T>,
+ obj: T,
+ ) -> InterpResult<'tcx, Id> {
+ let this = self.eval_context_mut();
+ let value_place =
+ this.deref_pointer_and_offset(lock_op, offset, lock_layout, this.machine.layouts.u32)?;
+
+ let new_index = get_objs(this).push(obj);
+ this.write_scalar(Scalar::from_u32(new_index.to_u32()), &value_place)?;
+ Ok(new_index)
+ }
+
fn condvar_reacquire_mutex(
&mut self,
mutex: MutexId,
@@ -236,15 +289,53 @@ fn condvar_reacquire_mutex(
// situations.
impl<'tcx> EvalContextExt<'tcx> for crate::MiriInterpCx<'tcx> {}
pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
+ /// Eagerly create and initialize a new mutex.
+ fn mutex_create(
+ &mut self,
+ lock_op: &OpTy<'tcx>,
+ lock_layout: TyAndLayout<'tcx>,
+ offset: u64,
+ data: Option<AdditionalMutexData>,
+ ) -> InterpResult<'tcx, MutexId> {
+ let this = self.eval_context_mut();
+ this.create_id(
+ lock_op,
+ lock_layout,
+ offset,
+ |ecx| &mut ecx.machine.sync.mutexes,
+ Mutex { data, ..Default::default() },
+ )
+ }
+
+ /// Lazily create a new mutex.
+ /// `initialize_data` must return any additional data that a user wants to associate with the mutex.
fn mutex_get_or_create_id(
&mut self,
lock_op: &OpTy<'tcx>,
lock_layout: TyAndLayout<'tcx>,
offset: u64,
+ initialize_data: impl for<'a> FnOnce(
+ &'a mut MiriInterpCx<'tcx>,
+ ) -> InterpResult<'tcx, Option<AdditionalMutexData>>,
) -> InterpResult<'tcx, MutexId> {
let this = self.eval_context_mut();
- this.get_or_create_id(lock_op, lock_layout, offset, |ecx| &mut ecx.machine.sync.mutexes)?
- .ok_or_else(|| err_ub_format!("mutex has invalid ID").into())
+ this.get_or_create_id(
+ lock_op,
+ lock_layout,
+ offset,
+ |ecx| &mut ecx.machine.sync.mutexes,
+ |ecx| initialize_data(ecx).map(|data| Mutex { data, ..Default::default() }),
+ )?
+ .ok_or_else(|| err_ub_format!("mutex has invalid ID").into())
+ }
+
+ /// Retrieve the additional data stored for a mutex.
+ fn mutex_get_data<'a>(&'a mut self, id: MutexId) -> Option<&'a AdditionalMutexData>
+ where
+ 'tcx: 'a,
+ {
+ let this = self.eval_context_ref();
+ this.machine.sync.mutexes[id].data.as_ref()
}
fn rwlock_get_or_create_id(
@@ -254,8 +345,14 @@ fn rwlock_get_or_create_id(
offset: u64,
) -> InterpResult<'tcx, RwLockId> {
let this = self.eval_context_mut();
- this.get_or_create_id(lock_op, lock_layout, offset, |ecx| &mut ecx.machine.sync.rwlocks)?
- .ok_or_else(|| err_ub_format!("rwlock has invalid ID").into())
+ this.get_or_create_id(
+ lock_op,
+ lock_layout,
+ offset,
+ |ecx| &mut ecx.machine.sync.rwlocks,
+ |_| Ok(Default::default()),
+ )?
+ .ok_or_else(|| err_ub_format!("rwlock has invalid ID").into())
}
fn condvar_get_or_create_id(
@@ -265,8 +362,14 @@ fn condvar_get_or_create_id(
offset: u64,
) -> InterpResult<'tcx, CondvarId> {
let this = self.eval_context_mut();
- this.get_or_create_id(lock_op, lock_layout, offset, |ecx| &mut ecx.machine.sync.condvars)?
- .ok_or_else(|| err_ub_format!("condvar has invalid ID").into())
+ this.get_or_create_id(
+ lock_op,
+ lock_layout,
+ offset,
+ |ecx| &mut ecx.machine.sync.condvars,
+ |_| Ok(Default::default()),
+ )?
+ .ok_or_else(|| err_ub_format!("condvar has invalid ID").into())
}
#[inline]
diff --git a/src/tools/miri/src/concurrency/thread.rs b/src/tools/miri/src/concurrency/thread.rs
index 79f292f..306245a 100644
--- a/src/tools/miri/src/concurrency/thread.rs
+++ b/src/tools/miri/src/concurrency/thread.rs
@@ -888,8 +888,13 @@ fn get_or_create_thread_local_alloc(
}
let alloc = this.ctfe_query(|tcx| tcx.eval_static_initializer(def_id))?;
// We make a full copy of this allocation.
- let mut alloc =
- alloc.inner().adjust_from_tcx(&this.tcx, |bytes, align| Ok(MiriAllocBytes::from_bytes(std::borrow::Cow::Borrowed(bytes), align)), |ptr| this.global_root_pointer(ptr))?;
+ let mut alloc = alloc.inner().adjust_from_tcx(
+ &this.tcx,
+ |bytes, align| {
+ Ok(MiriAllocBytes::from_bytes(std::borrow::Cow::Borrowed(bytes), align))
+ },
+ |ptr| this.global_root_pointer(ptr),
+ )?;
// This allocation will be deallocated when the thread dies, so it is not in read-only memory.
alloc.mutability = Mutability::Mut;
// Create a fresh allocation with this content.
diff --git a/src/tools/miri/src/eval.rs b/src/tools/miri/src/eval.rs
index bb623c6..0850a8f 100644
--- a/src/tools/miri/src/eval.rs
+++ b/src/tools/miri/src/eval.rs
@@ -458,14 +458,7 @@ pub fn eval_entry<'tcx>(
panic::resume_unwind(panic_payload)
});
// `Ok` can never happen.
- #[cfg(not(bootstrap))]
let Err(res) = res;
- #[cfg(bootstrap)]
- let res = match res {
- Err(res) => res,
- // `Ok` can never happen
- Ok(never) => match never {},
- };
// Machine cleanup. Only do this if all threads have terminated; threads that are still running
// might cause Stacked Borrows errors (https://github.com/rust-lang/miri/issues/2396).
diff --git a/src/tools/miri/src/helpers.rs b/src/tools/miri/src/helpers.rs
index a546ad2..cba99c0 100644
--- a/src/tools/miri/src/helpers.rs
+++ b/src/tools/miri/src/helpers.rs
@@ -869,7 +869,7 @@ fn try_unwrap_io_result<T: From<i32>>(
/// Dereference a pointer operand to a place using `layout` instead of the pointer's declared type
fn deref_pointer_as(
&self,
- op: &impl Readable<'tcx, Provenance>,
+ op: &impl Projectable<'tcx, Provenance>,
layout: TyAndLayout<'tcx>,
) -> InterpResult<'tcx, MPlaceTy<'tcx>> {
let this = self.eval_context_ref();
@@ -880,7 +880,7 @@ fn deref_pointer_as(
/// Calculates the MPlaceTy given the offset and layout of an access on an operand
fn deref_pointer_and_offset(
&self,
- op: &impl Readable<'tcx, Provenance>,
+ op: &impl Projectable<'tcx, Provenance>,
offset: u64,
base_layout: TyAndLayout<'tcx>,
value_layout: TyAndLayout<'tcx>,
@@ -897,7 +897,7 @@ fn deref_pointer_and_offset(
fn deref_pointer_and_read(
&self,
- op: &impl Readable<'tcx, Provenance>,
+ op: &impl Projectable<'tcx, Provenance>,
offset: u64,
base_layout: TyAndLayout<'tcx>,
value_layout: TyAndLayout<'tcx>,
@@ -909,7 +909,7 @@ fn deref_pointer_and_read(
fn deref_pointer_and_write(
&mut self,
- op: &impl Readable<'tcx, Provenance>,
+ op: &impl Projectable<'tcx, Provenance>,
offset: u64,
value: impl Into<Scalar>,
base_layout: TyAndLayout<'tcx>,
diff --git a/src/tools/miri/src/intrinsics/mod.rs b/src/tools/miri/src/intrinsics/mod.rs
index 18b2282..0ab1b9d 100644
--- a/src/tools/miri/src/intrinsics/mod.rs
+++ b/src/tools/miri/src/intrinsics/mod.rs
@@ -152,8 +152,10 @@ fn emulate_intrinsic_by_name(
// ```
// Would not be considered UB, or the other way around (`is_val_statically_known(0)`).
"is_val_statically_known" => {
- let [arg] = check_arg_count(args)?;
- this.validate_operand(arg, /*recursive*/ false)?;
+ let [_arg] = check_arg_count(args)?;
+ // FIXME: should we check for validity here? It's tricky because we do not have a
+ // place. Codegen does not seem to set any attributes like `noundef` for intrinsic
+ // calls, so we don't *have* to do anything.
let branch: bool = this.machine.rng.get_mut().gen();
this.write_scalar(Scalar::from_bool(branch), dest)?;
}
diff --git a/src/tools/miri/src/lib.rs b/src/tools/miri/src/lib.rs
index 8a59206..85b4b02 100644
--- a/src/tools/miri/src/lib.rs
+++ b/src/tools/miri/src/lib.rs
@@ -133,7 +133,10 @@
cpu_affinity::MAX_CPUS,
data_race::{AtomicFenceOrd, AtomicReadOrd, AtomicRwOrd, AtomicWriteOrd, EvalContextExt as _},
init_once::{EvalContextExt as _, InitOnceId},
- sync::{CondvarId, EvalContextExt as _, MutexId, RwLockId, SynchronizationObjects},
+ sync::{
+ AdditionalMutexData, CondvarId, EvalContextExt as _, MutexId, MutexKind, RwLockId,
+ SynchronizationObjects,
+ },
thread::{
BlockReason, EvalContextExt as _, StackEmptyCallback, ThreadId, ThreadManager,
TimeoutAnchor, TimeoutClock, UnblockCallback,
diff --git a/src/tools/miri/src/machine.rs b/src/tools/miri/src/machine.rs
index 66c6966..76b4366 100644
--- a/src/tools/miri/src/machine.rs
+++ b/src/tools/miri/src/machine.rs
@@ -535,9 +535,9 @@ pub struct MiriMachine<'tcx> {
pub(crate) basic_block_count: u64,
/// Handle of the optional shared object file for native functions.
- #[cfg(target_os = "linux")]
+ #[cfg(unix)]
pub native_lib: Option<(libloading::Library, std::path::PathBuf)>,
- #[cfg(not(target_os = "linux"))]
+ #[cfg(not(unix))]
pub native_lib: Option<!>,
/// Run a garbage collector for BorTags every N basic blocks.
@@ -572,6 +572,9 @@ pub struct MiriMachine<'tcx> {
/// Invariant: the promised alignment will never be less than the native alignment of the
/// allocation.
pub(crate) symbolic_alignment: RefCell<FxHashMap<AllocId, (Size, Align)>>,
+
+ /// A cache of "data range" computations for unions (i.e., the offsets of non-padding bytes).
+ union_data_ranges: FxHashMap<Ty<'tcx>, RangeSet>,
}
impl<'tcx> MiriMachine<'tcx> {
@@ -678,7 +681,7 @@ pub(crate) fn new(config: &MiriConfig, layout_cx: LayoutCx<'tcx, TyCtxt<'tcx>>)
report_progress: config.report_progress,
basic_block_count: 0,
clock: Clock::new(config.isolated_op == IsolatedOp::Allow),
- #[cfg(target_os = "linux")]
+ #[cfg(unix)]
native_lib: config.native_lib.as_ref().map(|lib_file_path| {
let target_triple = layout_cx.tcx.sess.opts.target_triple.triple();
// Check if host target == the session target.
@@ -700,9 +703,9 @@ pub(crate) fn new(config: &MiriConfig, layout_cx: LayoutCx<'tcx, TyCtxt<'tcx>>)
lib_file_path.clone(),
)
}),
- #[cfg(not(target_os = "linux"))]
+ #[cfg(not(unix))]
native_lib: config.native_lib.as_ref().map(|_| {
- panic!("loading external .so files is only supported on Linux")
+ panic!("calling functions from native libraries via FFI is only supported on Unix")
}),
gc_interval: config.gc_interval,
since_gc: 0,
@@ -714,6 +717,7 @@ pub(crate) fn new(config: &MiriConfig, layout_cx: LayoutCx<'tcx, TyCtxt<'tcx>>)
allocation_spans: RefCell::new(FxHashMap::default()),
const_cache: RefCell::new(FxHashMap::default()),
symbolic_alignment: RefCell::new(FxHashMap::default()),
+ union_data_ranges: FxHashMap::default(),
}
}
@@ -826,6 +830,7 @@ fn visit_provenance(&self, visit: &mut VisitWith<'_>) {
allocation_spans: _,
const_cache: _,
symbolic_alignment: _,
+ union_data_ranges: _,
} = self;
threads.visit_provenance(visit);
@@ -1277,12 +1282,12 @@ fn adjust_global_allocation<'b>(
) -> InterpResult<'tcx, Cow<'b, Allocation<Self::Provenance, Self::AllocExtra, Self::Bytes>>>
{
let kind = Self::GLOBAL_KIND.unwrap().into();
- let alloc = alloc.adjust_from_tcx(&ecx.tcx,
+ let alloc = alloc.adjust_from_tcx(
+ &ecx.tcx,
|bytes, align| ecx.get_global_alloc_bytes(id, kind, bytes, align),
|ptr| ecx.global_root_pointer(ptr),
)?;
- let extra =
- Self::init_alloc_extra(ecx, id, kind, alloc.size(), alloc.align)?;
+ let extra = Self::init_alloc_extra(ecx, id, kind, alloc.size(), alloc.align)?;
Ok(Cow::Owned(alloc.with_extra(extra)))
}
@@ -1627,4 +1632,12 @@ fn get_global_alloc_salt(
ecx.machine.rng.borrow_mut().gen::<usize>() % ADDRS_PER_ANON_GLOBAL
}
}
+
+ fn cached_union_data_range<'e>(
+ ecx: &'e mut InterpCx<'tcx, Self>,
+ ty: Ty<'tcx>,
+ compute_range: impl FnOnce() -> RangeSet,
+ ) -> Cow<'e, RangeSet> {
+ Cow::Borrowed(ecx.machine.union_data_ranges.entry(ty).or_insert_with(compute_range))
+ }
}
diff --git a/src/tools/miri/src/shims/foreign_items.rs b/src/tools/miri/src/shims/foreign_items.rs
index d40dbdb..1b45bc2 100644
--- a/src/tools/miri/src/shims/foreign_items.rs
+++ b/src/tools/miri/src/shims/foreign_items.rs
@@ -226,7 +226,7 @@ fn emulate_foreign_item_inner(
let this = self.eval_context_mut();
// First deal with any external C functions in linked .so file.
- #[cfg(target_os = "linux")]
+ #[cfg(unix)]
if this.machine.native_lib.as_ref().is_some() {
use crate::shims::native_lib::EvalContextExt as _;
// An Ok(false) here means that the function being called was not exported
diff --git a/src/tools/miri/src/shims/mod.rs b/src/tools/miri/src/shims/mod.rs
index 7d5349f..618cf8c 100644
--- a/src/tools/miri/src/shims/mod.rs
+++ b/src/tools/miri/src/shims/mod.rs
@@ -2,7 +2,7 @@
mod alloc;
mod backtrace;
-#[cfg(target_os = "linux")]
+#[cfg(unix)]
mod native_lib;
mod unix;
mod wasi;
diff --git a/src/tools/miri/src/shims/native_lib.rs b/src/tools/miri/src/shims/native_lib.rs
index 25d96fb..e4998c3 100644
--- a/src/tools/miri/src/shims/native_lib.rs
+++ b/src/tools/miri/src/shims/native_lib.rs
@@ -240,13 +240,16 @@ fn imm_to_carg<'tcx>(v: ImmTy<'tcx>, cx: &impl HasDataLayout) -> InterpResult<'t
ty::RawPtr(_, mutability) => {
// Arbitrary mutable pointer accesses are not currently supported in Miri.
if mutability.is_mut() {
- throw_unsup_format!("unsupported mutable pointer type for native call: {}", v.layout.ty);
+ throw_unsup_format!(
+ "unsupported mutable pointer type for native call: {}",
+ v.layout.ty
+ );
} else {
let s = v.to_scalar().to_pointer(cx)?.addr();
// This relies on the `expose_provenance` in `addr_from_alloc_id`.
CArg::RawPtr(std::ptr::with_exposed_provenance_mut(s.bytes_usize()))
}
- },
+ }
_ => throw_unsup_format!("unsupported argument type for native call: {}", v.layout.ty),
})
}
diff --git a/src/tools/miri/src/shims/unix/macos/sync.rs b/src/tools/miri/src/shims/unix/macos/sync.rs
index 5e5fccb..882c08c 100644
--- a/src/tools/miri/src/shims/unix/macos/sync.rs
+++ b/src/tools/miri/src/shims/unix/macos/sync.rs
@@ -19,7 +19,7 @@ fn os_unfair_lock_getid(&mut self, lock_op: &OpTy<'tcx>) -> InterpResult<'tcx, M
// os_unfair_lock holds a 32-bit value, is initialized with zero and
// must be assumed to be opaque. Therefore, we can just store our
// internal mutex ID in the structure without anyone noticing.
- this.mutex_get_or_create_id(lock_op, this.libc_ty_layout("os_unfair_lock"), 0)
+ this.mutex_get_or_create_id(lock_op, this.libc_ty_layout("os_unfair_lock"), 0, |_| Ok(None))
}
}
diff --git a/src/tools/miri/src/shims/unix/sync.rs b/src/tools/miri/src/shims/unix/sync.rs
index 0b889b1..57cc9cf4 100644
--- a/src/tools/miri/src/shims/unix/sync.rs
+++ b/src/tools/miri/src/shims/unix/sync.rs
@@ -62,7 +62,6 @@ fn is_mutex_kind_normal<'tcx>(ecx: &MiriInterpCx<'tcx>, kind: i32) -> InterpResu
// pthread_mutex_t is between 24 and 48 bytes, depending on the platform.
// We ignore the platform layout and store our own fields:
// - id: u32
-// - kind: i32
fn mutex_id_offset<'tcx>(ecx: &MiriInterpCx<'tcx>) -> InterpResult<'tcx, u64> {
let offset = match &*ecx.tcx.sess.target.os {
@@ -74,6 +73,8 @@ fn mutex_id_offset<'tcx>(ecx: &MiriInterpCx<'tcx>) -> InterpResult<'tcx, u64> {
// Sanity-check this against PTHREAD_MUTEX_INITIALIZER (but only once):
// the id must start out as 0.
+ // FIXME on some platforms (e.g linux) there are more static initializers for
+ // recursive or error checking mutexes. We should also add thme in this sanity check.
static SANITY: AtomicBool = AtomicBool::new(false);
if !SANITY.swap(true, Ordering::Relaxed) {
let static_initializer = ecx.eval_path(&["libc", "PTHREAD_MUTEX_INITIALIZER"]);
@@ -90,79 +91,92 @@ fn mutex_id_offset<'tcx>(ecx: &MiriInterpCx<'tcx>) -> InterpResult<'tcx, u64> {
Ok(offset)
}
-fn mutex_kind_offset<'tcx>(ecx: &MiriInterpCx<'tcx>) -> u64 {
- // These offsets are picked for compatibility with Linux's static initializer
- // macros, e.g. PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP.)
- let offset = if ecx.pointer_size().bytes() == 8 { 16 } else { 12 };
-
- // Sanity-check this against PTHREAD_MUTEX_INITIALIZER (but only once):
- // the kind must start out as PTHREAD_MUTEX_DEFAULT.
- static SANITY: AtomicBool = AtomicBool::new(false);
- if !SANITY.swap(true, Ordering::Relaxed) {
- let static_initializer = ecx.eval_path(&["libc", "PTHREAD_MUTEX_INITIALIZER"]);
- let kind_field = static_initializer
- .offset(Size::from_bytes(mutex_kind_offset(ecx)), ecx.machine.layouts.i32, ecx)
- .unwrap();
- let kind = ecx.read_scalar(&kind_field).unwrap().to_i32().unwrap();
- assert_eq!(
- kind,
- ecx.eval_libc_i32("PTHREAD_MUTEX_DEFAULT"),
- "PTHREAD_MUTEX_INITIALIZER is incompatible with our pthread_mutex layout: kind is not PTHREAD_MUTEX_DEFAULT"
- );
- }
-
- offset
+/// Eagerly create and initialize a new mutex.
+fn mutex_create<'tcx>(
+ ecx: &mut MiriInterpCx<'tcx>,
+ mutex_op: &OpTy<'tcx>,
+ kind: i32,
+) -> InterpResult<'tcx> {
+ // FIXME: might be worth changing mutex_create to take the mplace
+ // rather than the `OpTy`.
+ let address = ecx.read_pointer(mutex_op)?.addr().bytes();
+ let kind = translate_kind(ecx, kind)?;
+ let data = Some(AdditionalMutexData { address, kind });
+ ecx.mutex_create(mutex_op, ecx.libc_ty_layout("pthread_mutex_t"), mutex_id_offset(ecx)?, data)?;
+ Ok(())
}
+/// Returns the `MutexId` of the mutex stored at `mutex_op`.
+///
+/// `mutex_get_id` will also check if the mutex has been moved since its first use and
+/// return an error if it has.
fn mutex_get_id<'tcx>(
ecx: &mut MiriInterpCx<'tcx>,
mutex_op: &OpTy<'tcx>,
) -> InterpResult<'tcx, MutexId> {
- ecx.mutex_get_or_create_id(
+ let address = ecx.read_pointer(mutex_op)?.addr().bytes();
+
+ // FIXME: might be worth changing mutex_get_or_create_id to take the mplace
+ // rather than the `OpTy`.
+ let id = ecx.mutex_get_or_create_id(
mutex_op,
ecx.libc_ty_layout("pthread_mutex_t"),
mutex_id_offset(ecx)?,
- )
+ |ecx| {
+ // This is called if a static initializer was used and the lock has not been assigned
+ // an ID yet. We have to determine the mutex kind from the static initializer.
+ let kind = kind_from_static_initializer(ecx, mutex_op)?;
+
+ Ok(Some(AdditionalMutexData { kind, address }))
+ },
+ )?;
+
+ // Check that the mutex has not been moved since last use.
+ let data = ecx.mutex_get_data(id).expect("data should be always exist for pthreads");
+ if data.address != address {
+ throw_ub_format!("pthread_mutex_t can't be moved after first use")
+ }
+
+ Ok(id)
}
-fn mutex_reset_id<'tcx>(
- ecx: &mut MiriInterpCx<'tcx>,
- mutex_op: &OpTy<'tcx>,
-) -> InterpResult<'tcx, ()> {
- ecx.deref_pointer_and_write(
- mutex_op,
- mutex_id_offset(ecx)?,
- Scalar::from_u32(0),
- ecx.libc_ty_layout("pthread_mutex_t"),
- ecx.machine.layouts.u32,
- )
-}
-
-fn mutex_get_kind<'tcx>(
+/// Returns the kind of a static initializer.
+fn kind_from_static_initializer<'tcx>(
ecx: &MiriInterpCx<'tcx>,
mutex_op: &OpTy<'tcx>,
-) -> InterpResult<'tcx, i32> {
- ecx.deref_pointer_and_read(
- mutex_op,
- mutex_kind_offset(ecx),
- ecx.libc_ty_layout("pthread_mutex_t"),
- ecx.machine.layouts.i32,
- )?
- .to_i32()
+) -> InterpResult<'tcx, MutexKind> {
+ // Only linux has static initializers other than PTHREAD_MUTEX_DEFAULT.
+ let kind = match &*ecx.tcx.sess.target.os {
+ "linux" => {
+ let offset = if ecx.pointer_size().bytes() == 8 { 16 } else { 12 };
+
+ ecx.deref_pointer_and_read(
+ mutex_op,
+ offset,
+ ecx.libc_ty_layout("pthread_mutex_t"),
+ ecx.machine.layouts.i32,
+ )?
+ .to_i32()?
+ }
+ | "illumos" | "solaris" | "macos" => ecx.eval_libc_i32("PTHREAD_MUTEX_DEFAULT"),
+ os => throw_unsup_format!("`pthread_mutex` is not supported on {os}"),
+ };
+
+ translate_kind(ecx, kind)
}
-fn mutex_set_kind<'tcx>(
- ecx: &mut MiriInterpCx<'tcx>,
- mutex_op: &OpTy<'tcx>,
- kind: i32,
-) -> InterpResult<'tcx, ()> {
- ecx.deref_pointer_and_write(
- mutex_op,
- mutex_kind_offset(ecx),
- Scalar::from_i32(kind),
- ecx.libc_ty_layout("pthread_mutex_t"),
- ecx.machine.layouts.i32,
- )
+fn translate_kind<'tcx>(ecx: &MiriInterpCx<'tcx>, kind: i32) -> InterpResult<'tcx, MutexKind> {
+ Ok(if is_mutex_kind_default(ecx, kind)? {
+ MutexKind::Default
+ } else if is_mutex_kind_normal(ecx, kind)? {
+ MutexKind::Normal
+ } else if kind == ecx.eval_libc_i32("PTHREAD_MUTEX_ERRORCHECK") {
+ MutexKind::ErrorCheck
+ } else if kind == ecx.eval_libc_i32("PTHREAD_MUTEX_RECURSIVE") {
+ MutexKind::Recursive
+ } else {
+ throw_unsup_format!("unsupported type of mutex: {kind}");
+ })
}
// pthread_rwlock_t is between 32 and 56 bytes, depending on the platform.
@@ -452,10 +466,7 @@ fn pthread_mutex_init(
mutexattr_get_kind(this, attr_op)?
};
- // Write 0 to use the same code path as the static initializers.
- mutex_reset_id(this, mutex_op)?;
-
- mutex_set_kind(this, mutex_op, kind)?;
+ mutex_create(this, mutex_op, kind)?;
Ok(())
}
@@ -467,8 +478,9 @@ fn pthread_mutex_lock(
) -> InterpResult<'tcx> {
let this = self.eval_context_mut();
- let kind = mutex_get_kind(this, mutex_op)?;
let id = mutex_get_id(this, mutex_op)?;
+ let kind =
+ this.mutex_get_data(id).expect("data should always exist for pthread mutexes").kind;
let ret = if this.mutex_is_locked(id) {
let owner_thread = this.mutex_get_owner(id);
@@ -477,19 +489,19 @@ fn pthread_mutex_lock(
return Ok(());
} else {
// Trying to acquire the same mutex again.
- if is_mutex_kind_default(this, kind)? {
- throw_ub_format!("trying to acquire already locked default mutex");
- } else if is_mutex_kind_normal(this, kind)? {
- throw_machine_stop!(TerminationInfo::Deadlock);
- } else if kind == this.eval_libc_i32("PTHREAD_MUTEX_ERRORCHECK") {
- this.eval_libc_i32("EDEADLK")
- } else if kind == this.eval_libc_i32("PTHREAD_MUTEX_RECURSIVE") {
- this.mutex_lock(id);
- 0
- } else {
- throw_unsup_format!(
- "called pthread_mutex_lock on an unsupported type of mutex"
- );
+ match kind {
+ MutexKind::Default =>
+ throw_ub_format!("trying to acquire already locked default mutex"),
+ MutexKind::Normal => throw_machine_stop!(TerminationInfo::Deadlock),
+ MutexKind::ErrorCheck => this.eval_libc_i32("EDEADLK"),
+ MutexKind::Recursive => {
+ this.mutex_lock(id);
+ 0
+ }
+ _ =>
+ throw_unsup_format!(
+ "called pthread_mutex_lock on an unsupported type of mutex"
+ ),
}
}
} else {
@@ -504,26 +516,26 @@ fn pthread_mutex_lock(
fn pthread_mutex_trylock(&mut self, mutex_op: &OpTy<'tcx>) -> InterpResult<'tcx, Scalar> {
let this = self.eval_context_mut();
- let kind = mutex_get_kind(this, mutex_op)?;
let id = mutex_get_id(this, mutex_op)?;
+ let kind =
+ this.mutex_get_data(id).expect("data should always exist for pthread mutexes").kind;
Ok(Scalar::from_i32(if this.mutex_is_locked(id) {
let owner_thread = this.mutex_get_owner(id);
if owner_thread != this.active_thread() {
this.eval_libc_i32("EBUSY")
} else {
- if is_mutex_kind_default(this, kind)?
- || is_mutex_kind_normal(this, kind)?
- || kind == this.eval_libc_i32("PTHREAD_MUTEX_ERRORCHECK")
- {
- this.eval_libc_i32("EBUSY")
- } else if kind == this.eval_libc_i32("PTHREAD_MUTEX_RECURSIVE") {
- this.mutex_lock(id);
- 0
- } else {
- throw_unsup_format!(
- "called pthread_mutex_trylock on an unsupported type of mutex"
- );
+ match kind {
+ MutexKind::Default | MutexKind::Normal | MutexKind::ErrorCheck =>
+ this.eval_libc_i32("EBUSY"),
+ MutexKind::Recursive => {
+ this.mutex_lock(id);
+ 0
+ }
+ _ =>
+ throw_unsup_format!(
+ "called pthread_mutex_trylock on an unsupported type of mutex"
+ ),
}
}
} else {
@@ -536,8 +548,9 @@ fn pthread_mutex_trylock(&mut self, mutex_op: &OpTy<'tcx>) -> InterpResult<'tcx,
fn pthread_mutex_unlock(&mut self, mutex_op: &OpTy<'tcx>) -> InterpResult<'tcx, Scalar> {
let this = self.eval_context_mut();
- let kind = mutex_get_kind(this, mutex_op)?;
let id = mutex_get_id(this, mutex_op)?;
+ let kind =
+ this.mutex_get_data(id).expect("data should always exist for pthread mutexes").kind;
if let Some(_old_locked_count) = this.mutex_unlock(id)? {
// The mutex was locked by the current thread.
@@ -546,20 +559,21 @@ fn pthread_mutex_unlock(&mut self, mutex_op: &OpTy<'tcx>) -> InterpResult<'tcx,
// The mutex was locked by another thread or not locked at all. See
// the “Unlock When Not Owner” column in
// https://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_mutex_unlock.html.
- if is_mutex_kind_default(this, kind)? {
- throw_ub_format!(
- "unlocked a default mutex that was not locked by the current thread"
- );
- } else if is_mutex_kind_normal(this, kind)? {
- throw_ub_format!(
- "unlocked a PTHREAD_MUTEX_NORMAL mutex that was not locked by the current thread"
- );
- } else if kind == this.eval_libc_i32("PTHREAD_MUTEX_ERRORCHECK")
- || kind == this.eval_libc_i32("PTHREAD_MUTEX_RECURSIVE")
- {
- Ok(Scalar::from_i32(this.eval_libc_i32("EPERM")))
- } else {
- throw_unsup_format!("called pthread_mutex_unlock on an unsupported type of mutex");
+ match kind {
+ MutexKind::Default =>
+ throw_ub_format!(
+ "unlocked a default mutex that was not locked by the current thread"
+ ),
+ MutexKind::Normal =>
+ throw_ub_format!(
+ "unlocked a PTHREAD_MUTEX_NORMAL mutex that was not locked by the current thread"
+ ),
+ MutexKind::ErrorCheck | MutexKind::Recursive =>
+ Ok(Scalar::from_i32(this.eval_libc_i32("EPERM"))),
+ _ =>
+ throw_unsup_format!(
+ "called pthread_mutex_unlock on an unsupported type of mutex"
+ ),
}
}
}
@@ -574,7 +588,6 @@ fn pthread_mutex_destroy(&mut self, mutex_op: &OpTy<'tcx>) -> InterpResult<'tcx,
}
// Destroying an uninit pthread_mutex is UB, so check to make sure it's not uninit.
- mutex_get_kind(this, mutex_op)?;
mutex_get_id(this, mutex_op)?;
// This might lead to false positives, see comment in pthread_mutexattr_destroy
diff --git a/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_mutex_move.init.stderr b/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_mutex_move.init.stderr
new file mode 100644
index 0000000..5ca6acc
--- /dev/null
+++ b/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_mutex_move.init.stderr
@@ -0,0 +1,20 @@
+error: Undefined Behavior: pthread_mutex_t can't be moved after first use
+ --> $DIR/libc_pthread_mutex_move.rs:LL:CC
+ |
+LL | libc::pthread_mutex_lock(&mut m2 as *mut _);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ pthread_mutex_t can't be moved after first use
+ |
+ = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
+ = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
+ = note: BACKTRACE:
+ = note: inside `check` at $DIR/libc_pthread_mutex_move.rs:LL:CC
+note: inside `main`
+ --> $DIR/libc_pthread_mutex_move.rs:LL:CC
+ |
+LL | check();
+ | ^^^^^^^
+
+note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
+
+error: aborting due to 1 previous error
+
diff --git a/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_mutex_move.rs b/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_mutex_move.rs
new file mode 100644
index 0000000..229335c
--- /dev/null
+++ b/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_mutex_move.rs
@@ -0,0 +1,28 @@
+//@ignore-target-windows: No pthreads on Windows
+//@revisions: static_initializer init
+
+fn main() {
+ check();
+}
+
+#[cfg(init)]
+fn check() {
+ unsafe {
+ let mut m: libc::pthread_mutex_t = std::mem::zeroed();
+ assert_eq!(libc::pthread_mutex_init(&mut m as *mut _, std::ptr::null()), 0);
+
+ let mut m2 = m; // move the mutex
+ libc::pthread_mutex_lock(&mut m2 as *mut _); //~[init] ERROR: pthread_mutex_t can't be moved after first use
+ }
+}
+
+#[cfg(static_initializer)]
+fn check() {
+ unsafe {
+ let mut m: libc::pthread_mutex_t = libc::PTHREAD_MUTEX_INITIALIZER;
+ libc::pthread_mutex_lock(&mut m as *mut _);
+
+ let mut m2 = m; // move the mutex
+ libc::pthread_mutex_unlock(&mut m2 as *mut _); //~[static_initializer] ERROR: pthread_mutex_t can't be moved after first use
+ }
+}
diff --git a/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_mutex_move.static_initializer.stderr b/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_mutex_move.static_initializer.stderr
new file mode 100644
index 0000000..c3632ec
--- /dev/null
+++ b/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_mutex_move.static_initializer.stderr
@@ -0,0 +1,20 @@
+error: Undefined Behavior: pthread_mutex_t can't be moved after first use
+ --> $DIR/libc_pthread_mutex_move.rs:LL:CC
+ |
+LL | libc::pthread_mutex_unlock(&mut m2 as *mut _);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ pthread_mutex_t can't be moved after first use
+ |
+ = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
+ = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
+ = note: BACKTRACE:
+ = note: inside `check` at $DIR/libc_pthread_mutex_move.rs:LL:CC
+note: inside `main`
+ --> $DIR/libc_pthread_mutex_move.rs:LL:CC
+ |
+LL | check();
+ | ^^^^^^^
+
+note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
+
+error: aborting due to 1 previous error
+
diff --git a/src/tools/miri/tests/fail/provenance/int_copy_looses_provenance0.rs b/src/tools/miri/tests/fail/provenance/int_copy_looses_provenance0.rs
new file mode 100644
index 0000000..fd0773e
--- /dev/null
+++ b/src/tools/miri/tests/fail/provenance/int_copy_looses_provenance0.rs
@@ -0,0 +1,10 @@
+use std::mem;
+
+// Doing a copy at integer type should lose provenance.
+// This tests the unoptimized base case.
+fn main() {
+ let ptrs = [(&42, true)];
+ let ints: [(usize, bool); 1] = unsafe { mem::transmute(ptrs) };
+ let ptr = (&raw const ints[0].0).cast::<&i32>();
+ let _val = unsafe { *ptr.read() }; //~ERROR: dangling
+}
diff --git a/src/tools/miri/tests/fail/provenance/int_copy_looses_provenance0.stderr b/src/tools/miri/tests/fail/provenance/int_copy_looses_provenance0.stderr
new file mode 100644
index 0000000..fc012af
--- /dev/null
+++ b/src/tools/miri/tests/fail/provenance/int_copy_looses_provenance0.stderr
@@ -0,0 +1,15 @@
+error: Undefined Behavior: constructing invalid value: encountered a dangling reference ($HEX[noalloc] has no provenance)
+ --> $DIR/int_copy_looses_provenance0.rs:LL:CC
+ |
+LL | let _val = unsafe { *ptr.read() };
+ | ^^^^^^^^^^ constructing invalid value: encountered a dangling reference ($HEX[noalloc] has no provenance)
+ |
+ = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
+ = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
+ = note: BACKTRACE:
+ = note: inside `main` at $DIR/int_copy_looses_provenance0.rs:LL:CC
+
+note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
+
+error: aborting due to 1 previous error
+
diff --git a/src/tools/miri/tests/fail/provenance/int_copy_looses_provenance1.rs b/src/tools/miri/tests/fail/provenance/int_copy_looses_provenance1.rs
new file mode 100644
index 0000000..ce64dcc
--- /dev/null
+++ b/src/tools/miri/tests/fail/provenance/int_copy_looses_provenance1.rs
@@ -0,0 +1,10 @@
+use std::mem;
+
+// Doing a copy at integer type should lose provenance.
+// This tests the optimized-array case of integer copies.
+fn main() {
+ let ptrs = [&42];
+ let ints: [usize; 1] = unsafe { mem::transmute(ptrs) };
+ let ptr = (&raw const ints[0]).cast::<&i32>();
+ let _val = unsafe { *ptr.read() }; //~ERROR: dangling
+}
diff --git a/src/tools/miri/tests/fail/provenance/int_copy_looses_provenance1.stderr b/src/tools/miri/tests/fail/provenance/int_copy_looses_provenance1.stderr
new file mode 100644
index 0000000..3752626
--- /dev/null
+++ b/src/tools/miri/tests/fail/provenance/int_copy_looses_provenance1.stderr
@@ -0,0 +1,15 @@
+error: Undefined Behavior: constructing invalid value: encountered a dangling reference ($HEX[noalloc] has no provenance)
+ --> $DIR/int_copy_looses_provenance1.rs:LL:CC
+ |
+LL | let _val = unsafe { *ptr.read() };
+ | ^^^^^^^^^^ constructing invalid value: encountered a dangling reference ($HEX[noalloc] has no provenance)
+ |
+ = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
+ = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
+ = note: BACKTRACE:
+ = note: inside `main` at $DIR/int_copy_looses_provenance1.rs:LL:CC
+
+note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
+
+error: aborting due to 1 previous error
+
diff --git a/src/tools/miri/tests/fail/provenance/int_copy_looses_provenance2.rs b/src/tools/miri/tests/fail/provenance/int_copy_looses_provenance2.rs
new file mode 100644
index 0000000..e8966c5
--- /dev/null
+++ b/src/tools/miri/tests/fail/provenance/int_copy_looses_provenance2.rs
@@ -0,0 +1,12 @@
+use std::mem;
+
+// Doing a copy at integer type should lose provenance.
+// This tests the case where provenacne is hiding in the metadata of a pointer.
+fn main() {
+ let ptrs = [(&42, &42)];
+ // Typed copy at wide pointer type (with integer-typed metadata).
+ let ints: [*const [usize]; 1] = unsafe { mem::transmute(ptrs) };
+ // Get a pointer to the metadata field.
+ let ptr = (&raw const ints[0]).wrapping_byte_add(mem::size_of::<*const ()>()).cast::<&i32>();
+ let _val = unsafe { *ptr.read() }; //~ERROR: dangling
+}
diff --git a/src/tools/miri/tests/fail/provenance/int_copy_looses_provenance2.stderr b/src/tools/miri/tests/fail/provenance/int_copy_looses_provenance2.stderr
new file mode 100644
index 0000000..8402c7b
--- /dev/null
+++ b/src/tools/miri/tests/fail/provenance/int_copy_looses_provenance2.stderr
@@ -0,0 +1,15 @@
+error: Undefined Behavior: constructing invalid value: encountered a dangling reference ($HEX[noalloc] has no provenance)
+ --> $DIR/int_copy_looses_provenance2.rs:LL:CC
+ |
+LL | let _val = unsafe { *ptr.read() };
+ | ^^^^^^^^^^ constructing invalid value: encountered a dangling reference ($HEX[noalloc] has no provenance)
+ |
+ = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
+ = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
+ = note: BACKTRACE:
+ = note: inside `main` at $DIR/int_copy_looses_provenance2.rs:LL:CC
+
+note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
+
+error: aborting due to 1 previous error
+
diff --git a/src/tools/miri/tests/fail/provenance/int_copy_looses_provenance3.rs b/src/tools/miri/tests/fail/provenance/int_copy_looses_provenance3.rs
new file mode 100644
index 0000000..48a48ce
--- /dev/null
+++ b/src/tools/miri/tests/fail/provenance/int_copy_looses_provenance3.rs
@@ -0,0 +1,29 @@
+#![feature(strict_provenance)]
+use std::mem;
+
+#[repr(C, usize)]
+#[allow(unused)]
+enum E {
+ Var1(usize),
+ Var2(usize),
+}
+
+// Doing a copy at integer type should lose provenance.
+// This tests the case where provenacne is hiding in the discriminant of an enum.
+fn main() {
+ assert_eq!(mem::size_of::<E>(), 2*mem::size_of::<usize>());
+
+ // We want to store provenance in the enum discriminant, but the value still needs to
+ // be valid atfor the type. So we split provenance and data.
+ let ptr = &42;
+ let ptr = ptr as *const i32;
+ let ptrs = [(ptr.with_addr(0), ptr)];
+ // Typed copy at the enum type.
+ let ints: [E; 1] = unsafe { mem::transmute(ptrs) };
+ // Read the discriminant.
+ let discr = unsafe { (&raw const ints[0]).cast::<*const i32>().read() };
+ // Take the provenance from there, together with the original address.
+ let ptr = discr.with_addr(ptr.addr());
+ // There should be no provenance is `discr`, so this should be UB.
+ let _val = unsafe { *ptr }; //~ERROR: dangling
+}
diff --git a/src/tools/miri/tests/fail/provenance/int_copy_looses_provenance3.stderr b/src/tools/miri/tests/fail/provenance/int_copy_looses_provenance3.stderr
new file mode 100644
index 0000000..b50e23d
--- /dev/null
+++ b/src/tools/miri/tests/fail/provenance/int_copy_looses_provenance3.stderr
@@ -0,0 +1,15 @@
+error: Undefined Behavior: memory access failed: expected a pointer to 4 bytes of memory, but got $HEX[noalloc] which is a dangling pointer (it has no provenance)
+ --> $DIR/int_copy_looses_provenance3.rs:LL:CC
+ |
+LL | let _val = unsafe { *ptr };
+ | ^^^^ memory access failed: expected a pointer to 4 bytes of memory, but got $HEX[noalloc] which is a dangling pointer (it has no provenance)
+ |
+ = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
+ = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
+ = note: BACKTRACE:
+ = note: inside `main` at $DIR/int_copy_looses_provenance3.rs:LL:CC
+
+note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
+
+error: aborting due to 1 previous error
+
diff --git a/src/tools/miri/tests/fail/provenance/ptr_copy_loses_partial_provenance0.rs b/src/tools/miri/tests/fail/provenance/ptr_copy_loses_partial_provenance0.rs
new file mode 100644
index 0000000..ff94f22
--- /dev/null
+++ b/src/tools/miri/tests/fail/provenance/ptr_copy_loses_partial_provenance0.rs
@@ -0,0 +1,18 @@
+fn main() {
+ let half_ptr = std::mem::size_of::<*const ()>() / 2;
+ let mut bytes = [1u8; 16];
+ let bytes = bytes.as_mut_ptr();
+
+ unsafe {
+ // Put a pointer in the middle.
+ bytes.add(half_ptr).cast::<&i32>().write_unaligned(&42);
+ // Typed copy of the entire thing as two pointers, but not perfectly
+ // overlapping with the pointer we have in there.
+ let copy = bytes.cast::<[*const (); 2]>().read_unaligned();
+ let copy_bytes = copy.as_ptr().cast::<u8>();
+ // Now go to the middle of the copy and get the pointer back out.
+ let ptr = copy_bytes.add(half_ptr).cast::<*const i32>().read_unaligned();
+ // Dereferencing this should fail as the copy has removed the provenance.
+ let _val = *ptr; //~ERROR: dangling
+ }
+}
diff --git a/src/tools/miri/tests/fail/provenance/ptr_copy_loses_partial_provenance0.stderr b/src/tools/miri/tests/fail/provenance/ptr_copy_loses_partial_provenance0.stderr
new file mode 100644
index 0000000..ed38572
--- /dev/null
+++ b/src/tools/miri/tests/fail/provenance/ptr_copy_loses_partial_provenance0.stderr
@@ -0,0 +1,15 @@
+error: Undefined Behavior: memory access failed: expected a pointer to 4 bytes of memory, but got $HEX[noalloc] which is a dangling pointer (it has no provenance)
+ --> $DIR/ptr_copy_loses_partial_provenance0.rs:LL:CC
+ |
+LL | let _val = *ptr;
+ | ^^^^ memory access failed: expected a pointer to 4 bytes of memory, but got $HEX[noalloc] which is a dangling pointer (it has no provenance)
+ |
+ = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
+ = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
+ = note: BACKTRACE:
+ = note: inside `main` at $DIR/ptr_copy_loses_partial_provenance0.rs:LL:CC
+
+note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
+
+error: aborting due to 1 previous error
+
diff --git a/src/tools/miri/tests/fail/provenance/ptr_copy_loses_partial_provenance1.rs b/src/tools/miri/tests/fail/provenance/ptr_copy_loses_partial_provenance1.rs
new file mode 100644
index 0000000..d0e3dac
--- /dev/null
+++ b/src/tools/miri/tests/fail/provenance/ptr_copy_loses_partial_provenance1.rs
@@ -0,0 +1,18 @@
+fn main() {
+ let half_ptr = std::mem::size_of::<*const ()>() / 2;
+ let mut bytes = [1u8; 16];
+ let bytes = bytes.as_mut_ptr();
+
+ unsafe {
+ // Put a pointer in the middle.
+ bytes.add(half_ptr).cast::<&i32>().write_unaligned(&42);
+ // Typed copy of the entire thing as two *function* pointers, but not perfectly
+ // overlapping with the pointer we have in there.
+ let copy = bytes.cast::<[fn(); 2]>().read_unaligned();
+ let copy_bytes = copy.as_ptr().cast::<u8>();
+ // Now go to the middle of the copy and get the pointer back out.
+ let ptr = copy_bytes.add(half_ptr).cast::<*const i32>().read_unaligned();
+ // Dereferencing this should fail as the copy has removed the provenance.
+ let _val = *ptr; //~ERROR: dangling
+ }
+}
diff --git a/src/tools/miri/tests/fail/provenance/ptr_copy_loses_partial_provenance1.stderr b/src/tools/miri/tests/fail/provenance/ptr_copy_loses_partial_provenance1.stderr
new file mode 100644
index 0000000..2e11687
--- /dev/null
+++ b/src/tools/miri/tests/fail/provenance/ptr_copy_loses_partial_provenance1.stderr
@@ -0,0 +1,15 @@
+error: Undefined Behavior: memory access failed: expected a pointer to 4 bytes of memory, but got $HEX[noalloc] which is a dangling pointer (it has no provenance)
+ --> $DIR/ptr_copy_loses_partial_provenance1.rs:LL:CC
+ |
+LL | let _val = *ptr;
+ | ^^^^ memory access failed: expected a pointer to 4 bytes of memory, but got $HEX[noalloc] which is a dangling pointer (it has no provenance)
+ |
+ = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
+ = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
+ = note: BACKTRACE:
+ = note: inside `main` at $DIR/ptr_copy_loses_partial_provenance1.rs:LL:CC
+
+note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
+
+error: aborting due to 1 previous error
+
diff --git a/src/tools/miri/tests/fail/uninit/padding-enum.rs b/src/tools/miri/tests/fail/uninit/padding-enum.rs
new file mode 100644
index 0000000..3852ac5
--- /dev/null
+++ b/src/tools/miri/tests/fail/uninit/padding-enum.rs
@@ -0,0 +1,23 @@
+use std::mem;
+
+// We have three fields to avoid the ScalarPair optimization.
+#[allow(unused)]
+enum E {
+ None,
+ Some(&'static (), &'static (), usize),
+}
+
+fn main() { unsafe {
+ let mut p: mem::MaybeUninit<E> = mem::MaybeUninit::zeroed();
+ // The copy when `E` is returned from `transmute` should destroy padding
+ // (even when we use `write_unaligned`, which under the hood uses an untyped copy).
+ p.as_mut_ptr().write_unaligned(mem::transmute((0usize, 0usize, 0usize)));
+ // This is a `None`, so everything but the discriminant is padding.
+ assert!(matches!(*p.as_ptr(), E::None));
+
+ // Turns out the discriminant is (currently) stored
+ // in the 2nd pointer, so the first half is padding.
+ let c = &p as *const _ as *const u8;
+ let _val = *c.add(0); // Get a padding byte.
+ //~^ERROR: uninitialized
+} }
diff --git a/src/tools/miri/tests/fail/uninit/padding-enum.stderr b/src/tools/miri/tests/fail/uninit/padding-enum.stderr
new file mode 100644
index 0000000..c571f188
--- /dev/null
+++ b/src/tools/miri/tests/fail/uninit/padding-enum.stderr
@@ -0,0 +1,15 @@
+error: Undefined Behavior: using uninitialized data, but this operation requires initialized memory
+ --> $DIR/padding-enum.rs:LL:CC
+ |
+LL | let _val = *c.add(0); // Get a padding byte.
+ | ^^^^^^^^^ using uninitialized data, but this operation requires initialized memory
+ |
+ = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
+ = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
+ = note: BACKTRACE:
+ = note: inside `main` at $DIR/padding-enum.rs:LL:CC
+
+note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
+
+error: aborting due to 1 previous error
+
diff --git a/src/tools/miri/tests/fail/uninit/padding-pair.rs b/src/tools/miri/tests/fail/uninit/padding-pair.rs
new file mode 100644
index 0000000..c8c00b3
--- /dev/null
+++ b/src/tools/miri/tests/fail/uninit/padding-pair.rs
@@ -0,0 +1,25 @@
+#![feature(core_intrinsics)]
+
+use std::mem::{self, MaybeUninit};
+
+fn main() {
+ // This constructs a `(usize, bool)` pair: 9 bytes initialized, the rest not.
+ // Ensure that these 9 bytes are indeed initialized, and the rest is indeed not.
+ // This should be the case even if we write into previously initialized storage.
+ let mut x: MaybeUninit<Box<[u8]>> = MaybeUninit::zeroed();
+ let z = std::intrinsics::add_with_overflow(0usize, 0usize);
+ unsafe { x.as_mut_ptr().cast::<(usize, bool)>().write(z) };
+ // Now read this bytewise. There should be (`ptr_size + 1`) def bytes followed by
+ // (`ptr_size - 1`) undef bytes (the padding after the bool) in there.
+ let z: *const u8 = &x as *const _ as *const _;
+ let first_undef = mem::size_of::<usize>() as isize + 1;
+ for i in 0..first_undef {
+ let byte = unsafe { *z.offset(i) };
+ assert_eq!(byte, 0);
+ }
+ let v = unsafe { *z.offset(first_undef) };
+ //~^ ERROR: uninitialized
+ if v == 0 {
+ println!("it is zero");
+ }
+}
diff --git a/src/tools/miri/tests/fail/uninit/padding-pair.stderr b/src/tools/miri/tests/fail/uninit/padding-pair.stderr
new file mode 100644
index 0000000..d35934d
--- /dev/null
+++ b/src/tools/miri/tests/fail/uninit/padding-pair.stderr
@@ -0,0 +1,15 @@
+error: Undefined Behavior: using uninitialized data, but this operation requires initialized memory
+ --> $DIR/padding-pair.rs:LL:CC
+ |
+LL | let v = unsafe { *z.offset(first_undef) };
+ | ^^^^^^^^^^^^^^^^^^^^^^ using uninitialized data, but this operation requires initialized memory
+ |
+ = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
+ = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
+ = note: BACKTRACE:
+ = note: inside `main` at $DIR/padding-pair.rs:LL:CC
+
+note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
+
+error: aborting due to 1 previous error
+
diff --git a/src/tools/miri/tests/fail/uninit/padding-struct-in-union.rs b/src/tools/miri/tests/fail/uninit/padding-struct-in-union.rs
new file mode 100644
index 0000000..132b858
--- /dev/null
+++ b/src/tools/miri/tests/fail/uninit/padding-struct-in-union.rs
@@ -0,0 +1,32 @@
+#[repr(C)]
+#[derive(Debug, Copy, Clone)]
+struct Foo {
+ val16: u16,
+ // Padding bytes go here!
+ val32: u32,
+}
+
+#[repr(C)]
+#[derive(Debug, Copy, Clone)]
+struct Bar {
+ bytes: [u8; 8],
+}
+
+#[repr(C)]
+union FooBar {
+ foo: Foo,
+ bar: Bar,
+}
+
+pub fn main() {
+ // Initialize as u8 to ensure padding bytes are zeroed.
+ let mut foobar = FooBar { bar: Bar { bytes: [0u8; 8] } };
+ // Reading either field is ok.
+ let _val = unsafe { (foobar.foo, foobar.bar) };
+ // Does this assignment copy the uninitialized padding bytes
+ // over the initialized padding bytes? miri doesn't seem to think so.
+ foobar.foo = Foo { val16: 1, val32: 2 };
+ // This resets the padding to uninit.
+ let _val = unsafe { (foobar.foo, foobar.bar) };
+ //~^ ERROR: uninitialized
+}
diff --git a/src/tools/miri/tests/fail/uninit/padding-struct-in-union.stderr b/src/tools/miri/tests/fail/uninit/padding-struct-in-union.stderr
new file mode 100644
index 0000000..e122249
--- /dev/null
+++ b/src/tools/miri/tests/fail/uninit/padding-struct-in-union.stderr
@@ -0,0 +1,15 @@
+error: Undefined Behavior: constructing invalid value at .bytes[2]: encountered uninitialized memory, but expected an integer
+ --> $DIR/padding-struct-in-union.rs:LL:CC
+ |
+LL | let _val = unsafe { (foobar.foo, foobar.bar) };
+ | ^^^^^^^^^^ constructing invalid value at .bytes[2]: encountered uninitialized memory, but expected an integer
+ |
+ = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
+ = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
+ = note: BACKTRACE:
+ = note: inside `main` at $DIR/padding-struct-in-union.rs:LL:CC
+
+note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
+
+error: aborting due to 1 previous error
+
diff --git a/src/tools/miri/tests/fail/uninit/padding-struct.rs b/src/tools/miri/tests/fail/uninit/padding-struct.rs
new file mode 100644
index 0000000..dd3be50
--- /dev/null
+++ b/src/tools/miri/tests/fail/uninit/padding-struct.rs
@@ -0,0 +1,11 @@
+use std::mem;
+
+#[repr(C)]
+struct Pair(u8, u16);
+
+fn main() { unsafe {
+ let p: Pair = mem::transmute(0u32); // The copy when `Pair` is returned from `transmute` should destroy padding.
+ let c = &p as *const _ as *const u8;
+ let _val = *c.add(1); // Get the padding byte.
+ //~^ERROR: uninitialized
+} }
diff --git a/src/tools/miri/tests/fail/uninit/padding-struct.stderr b/src/tools/miri/tests/fail/uninit/padding-struct.stderr
new file mode 100644
index 0000000..8dc40a4
--- /dev/null
+++ b/src/tools/miri/tests/fail/uninit/padding-struct.stderr
@@ -0,0 +1,15 @@
+error: Undefined Behavior: using uninitialized data, but this operation requires initialized memory
+ --> $DIR/padding-struct.rs:LL:CC
+ |
+LL | let _val = *c.add(1); // Get the padding byte.
+ | ^^^^^^^^^ using uninitialized data, but this operation requires initialized memory
+ |
+ = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
+ = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
+ = note: BACKTRACE:
+ = note: inside `main` at $DIR/padding-struct.rs:LL:CC
+
+note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
+
+error: aborting due to 1 previous error
+
diff --git a/src/tools/miri/tests/fail/uninit/padding-union.rs b/src/tools/miri/tests/fail/uninit/padding-union.rs
new file mode 100644
index 0000000..2e9e0a4
--- /dev/null
+++ b/src/tools/miri/tests/fail/uninit/padding-union.rs
@@ -0,0 +1,14 @@
+use std::mem;
+
+#[allow(unused)]
+#[repr(C)]
+union U {
+ field: (u8, u16),
+}
+
+fn main() { unsafe {
+ let p: U = mem::transmute(0u32); // The copy when `U` is returned from `transmute` should destroy padding.
+ let c = &p as *const _ as *const [u8; 4];
+ let _val = *c; // Read the entire thing, definitely contains the padding byte.
+ //~^ERROR: uninitialized
+} }
diff --git a/src/tools/miri/tests/fail/uninit/padding-union.stderr b/src/tools/miri/tests/fail/uninit/padding-union.stderr
new file mode 100644
index 0000000..04002da
--- /dev/null
+++ b/src/tools/miri/tests/fail/uninit/padding-union.stderr
@@ -0,0 +1,15 @@
+error: Undefined Behavior: constructing invalid value at [1]: encountered uninitialized memory, but expected an integer
+ --> $DIR/padding-union.rs:LL:CC
+ |
+LL | let _val = *c; // Read the entire thing, definitely contains the padding byte.
+ | ^^ constructing invalid value at [1]: encountered uninitialized memory, but expected an integer
+ |
+ = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
+ = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
+ = note: BACKTRACE:
+ = note: inside `main` at $DIR/padding-union.rs:LL:CC
+
+note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
+
+error: aborting due to 1 previous error
+
diff --git a/src/tools/miri/tests/fail/uninit/padding-wide-ptr.rs b/src/tools/miri/tests/fail/uninit/padding-wide-ptr.rs
new file mode 100644
index 0000000..0403a9c
--- /dev/null
+++ b/src/tools/miri/tests/fail/uninit/padding-wide-ptr.rs
@@ -0,0 +1,18 @@
+use std::mem;
+
+// If this is `None`, the metadata becomes padding.
+type T = Option<&'static str>;
+
+fn main() { unsafe {
+ let mut p: mem::MaybeUninit<T> = mem::MaybeUninit::zeroed();
+ // The copy when `T` is returned from `transmute` should destroy padding
+ // (even when we use `write_unaligned`, which under the hood uses an untyped copy).
+ p.as_mut_ptr().write_unaligned(mem::transmute((0usize, 0usize)));
+ // Null epresents `None`.
+ assert!(matches!(*p.as_ptr(), None));
+
+ // The second part, with the length, becomes padding.
+ let c = &p as *const _ as *const u8;
+ let _val = *c.add(mem::size_of::<*const u8>()); // Get a padding byte.
+ //~^ERROR: uninitialized
+} }
diff --git a/src/tools/miri/tests/fail/uninit/padding-wide-ptr.stderr b/src/tools/miri/tests/fail/uninit/padding-wide-ptr.stderr
new file mode 100644
index 0000000..0da7255
--- /dev/null
+++ b/src/tools/miri/tests/fail/uninit/padding-wide-ptr.stderr
@@ -0,0 +1,15 @@
+error: Undefined Behavior: using uninitialized data, but this operation requires initialized memory
+ --> $DIR/padding-wide-ptr.rs:LL:CC
+ |
+LL | let _val = *c.add(mem::size_of::<*const u8>()); // Get a padding byte.
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ using uninitialized data, but this operation requires initialized memory
+ |
+ = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
+ = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
+ = note: BACKTRACE:
+ = note: inside `main` at $DIR/padding-wide-ptr.rs:LL:CC
+
+note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
+
+error: aborting due to 1 previous error
+
diff --git a/src/tools/miri/tests/fail/transmute-pair-uninit.rs b/src/tools/miri/tests/fail/uninit/transmute-pair-uninit.rs
similarity index 61%
rename from src/tools/miri/tests/fail/transmute-pair-uninit.rs
rename to src/tools/miri/tests/fail/uninit/transmute-pair-uninit.rs
index bc95f3c..0ba5520 100644
--- a/src/tools/miri/tests/fail/transmute-pair-uninit.rs
+++ b/src/tools/miri/tests/fail/uninit/transmute-pair-uninit.rs
@@ -1,16 +1,17 @@
#![feature(core_intrinsics)]
-use std::mem;
+use std::mem::{self, MaybeUninit};
fn main() {
- let x: Option<Box<[u8]>> = unsafe {
+ // This constructs a `(usize, bool)` pair: 9 bytes initialized, the rest not.
+ // Ensure that these 9 bytes are indeed initialized, and the rest is indeed not.
+ let x: MaybeUninit<Box<[u8]>> = unsafe {
let z = std::intrinsics::add_with_overflow(0usize, 0usize);
- std::mem::transmute::<(usize, bool), Option<Box<[u8]>>>(z)
+ std::mem::transmute::<(usize, bool), MaybeUninit<Box<[u8]>>>(z)
};
- let y = &x;
// Now read this bytewise. There should be (`ptr_size + 1`) def bytes followed by
// (`ptr_size - 1`) undef bytes (the padding after the bool) in there.
- let z: *const u8 = y as *const _ as *const _;
+ let z: *const u8 = &x as *const _ as *const _;
let first_undef = mem::size_of::<usize>() as isize + 1;
for i in 0..first_undef {
let byte = unsafe { *z.offset(i) };
diff --git a/src/tools/miri/tests/fail/transmute-pair-uninit.stderr b/src/tools/miri/tests/fail/uninit/transmute-pair-uninit.stderr
similarity index 100%
rename from src/tools/miri/tests/fail/transmute-pair-uninit.stderr
rename to src/tools/miri/tests/fail/uninit/transmute-pair-uninit.stderr
diff --git a/src/tools/miri/tests/native-lib/fail/function_not_in_so.rs b/src/tools/miri/tests/native-lib/fail/function_not_in_so.rs
index 3540c75..c532d05 100644
--- a/src/tools/miri/tests/native-lib/fail/function_not_in_so.rs
+++ b/src/tools/miri/tests/native-lib/fail/function_not_in_so.rs
@@ -1,4 +1,6 @@
-//@only-target-linux
+// Only works on Unix targets
+//@ignore-target-windows
+//@ignore-target-wasm
//@only-on-host
//@normalize-stderr-test: "OS `.*`" -> "$$OS"
diff --git a/src/tools/miri/tests/native-lib/fail/private_function.rs b/src/tools/miri/tests/native-lib/fail/private_function.rs
new file mode 100644
index 0000000..3c6fda7
--- /dev/null
+++ b/src/tools/miri/tests/native-lib/fail/private_function.rs
@@ -0,0 +1,15 @@
+// Only works on Unix targets
+//@ignore-target-windows
+//@ignore-target-wasm
+//@only-on-host
+//@normalize-stderr-test: "OS `.*`" -> "$$OS"
+
+extern "C" {
+ fn not_exported();
+}
+
+fn main() {
+ unsafe {
+ not_exported(); //~ ERROR: unsupported operation: can't call foreign function `not_exported`
+ }
+}
diff --git a/src/tools/miri/tests/native-lib/fail/private_function.stderr b/src/tools/miri/tests/native-lib/fail/private_function.stderr
new file mode 100644
index 0000000..e27a501
--- /dev/null
+++ b/src/tools/miri/tests/native-lib/fail/private_function.stderr
@@ -0,0 +1,15 @@
+error: unsupported operation: can't call foreign function `not_exported` on $OS
+ --> $DIR/private_function.rs:LL:CC
+ |
+LL | not_exported();
+ | ^^^^^^^^^^^^^^ can't call foreign function `not_exported` on $OS
+ |
+ = help: if this is a basic API commonly used on this target, please report an issue with Miri
+ = help: however, note that Miri does not aim to support every FFI function out there; for instance, we will not support APIs for things such as GUIs, scripting languages, or databases
+ = note: BACKTRACE:
+ = note: inside `main` at $DIR/private_function.rs:LL:CC
+
+note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
+
+error: aborting due to 1 previous error
+
diff --git a/src/tools/miri/tests/native-lib/native-lib.map b/src/tools/miri/tests/native-lib/native-lib.map
deleted file mode 100644
index 7e3bd19..0000000
--- a/src/tools/miri/tests/native-lib/native-lib.map
+++ /dev/null
@@ -1,20 +0,0 @@
-CODEABI_1.0 {
- # Define which symbols to export.
- global:
- # scalar_arguments.c
- add_one_int;
- printer;
- test_stack_spill;
- get_unsigned_int;
- add_int16;
- add_short_to_long;
-
- # ptr_read_access.c
- print_pointer;
- access_simple;
- access_nested;
- access_static;
-
- # The rest remains private.
- local: *;
-};
diff --git a/src/tools/miri/tests/native-lib/pass/ptr_read_access.rs b/src/tools/miri/tests/native-lib/pass/ptr_read_access.rs
index d8e6209..2990dfa 100644
--- a/src/tools/miri/tests/native-lib/pass/ptr_read_access.rs
+++ b/src/tools/miri/tests/native-lib/pass/ptr_read_access.rs
@@ -1,4 +1,6 @@
-//@only-target-linux
+// Only works on Unix targets
+//@ignore-target-windows
+//@ignore-target-wasm
//@only-on-host
fn main() {
@@ -26,7 +28,7 @@ fn test_pointer() {
fn test_simple() {
#[repr(C)]
struct Simple {
- field: i32
+ field: i32,
}
extern "C" {
@@ -41,7 +43,7 @@ struct Simple {
// Test function that dereferences nested struct pointers and accesses fields.
fn test_nested() {
use std::ptr::NonNull;
-
+
#[derive(Debug, PartialEq, Eq)]
#[repr(C)]
struct Nested {
@@ -62,7 +64,6 @@ struct Nested {
// Test function that dereferences static struct pointers and accesses fields.
fn test_static() {
-
#[repr(C)]
struct Static {
value: i32,
@@ -72,11 +73,8 @@ struct Static {
extern "C" {
fn access_static(n_ptr: *const Static) -> i32;
}
-
- static STATIC: Static = Static {
- value: 9001,
- recurse: &STATIC,
- };
+
+ static STATIC: Static = Static { value: 9001, recurse: &STATIC };
assert_eq!(unsafe { access_static(&STATIC) }, 9001);
}
diff --git a/src/tools/miri/tests/native-lib/pass/scalar_arguments.rs b/src/tools/miri/tests/native-lib/pass/scalar_arguments.rs
index 1e1d0b1..378baa7 100644
--- a/src/tools/miri/tests/native-lib/pass/scalar_arguments.rs
+++ b/src/tools/miri/tests/native-lib/pass/scalar_arguments.rs
@@ -1,4 +1,6 @@
-//@only-target-linux
+// Only works on Unix targets
+//@ignore-target-windows
+//@ignore-target-wasm
//@only-on-host
extern "C" {
diff --git a/src/tools/miri/tests/native-lib/ptr_read_access.c b/src/tools/miri/tests/native-lib/ptr_read_access.c
index 03b9189..540845d 100644
--- a/src/tools/miri/tests/native-lib/ptr_read_access.c
+++ b/src/tools/miri/tests/native-lib/ptr_read_access.c
@@ -1,8 +1,11 @@
#include <stdio.h>
+// See comments in build_native_lib()
+#define EXPORT __attribute__((visibility("default")))
+
/* Test: test_pointer */
-void print_pointer(const int *ptr) {
+EXPORT void print_pointer(const int *ptr) {
printf("printing pointer dereference from C: %d\n", *ptr);
}
@@ -12,7 +15,7 @@
int field;
} Simple;
-int access_simple(const Simple *s_ptr) {
+EXPORT int access_simple(const Simple *s_ptr) {
return s_ptr->field;
}
@@ -24,7 +27,7 @@
} Nested;
// Returns the innermost/last value of a Nested pointer chain.
-int access_nested(const Nested *n_ptr) {
+EXPORT int access_nested(const Nested *n_ptr) {
// Edge case: `n_ptr == NULL` (i.e. first Nested is None).
if (!n_ptr) { return 0; }
@@ -42,6 +45,6 @@
struct Static *recurse;
} Static;
-int access_static(const Static *s_ptr) {
+EXPORT int access_static(const Static *s_ptr) {
return s_ptr->recurse->recurse->value;
}
diff --git a/src/tools/miri/tests/native-lib/scalar_arguments.c b/src/tools/miri/tests/native-lib/scalar_arguments.c
index 68714f1..6da730a 100644
--- a/src/tools/miri/tests/native-lib/scalar_arguments.c
+++ b/src/tools/miri/tests/native-lib/scalar_arguments.c
@@ -1,27 +1,35 @@
#include <stdio.h>
-int add_one_int(int x) {
+// See comments in build_native_lib()
+#define EXPORT __attribute__((visibility("default")))
+
+EXPORT int add_one_int(int x) {
return 2 + x;
}
-void printer() {
+EXPORT void printer(void) {
printf("printing from C\n");
}
// function with many arguments, to test functionality when some args are stored
// on the stack
-int test_stack_spill(int a, int b, int c, int d, int e, int f, int g, int h, int i, int j, int k, int l) {
+EXPORT int test_stack_spill(int a, int b, int c, int d, int e, int f, int g, int h, int i, int j, int k, int l) {
return a+b+c+d+e+f+g+h+i+j+k+l;
}
-unsigned int get_unsigned_int() {
+EXPORT unsigned int get_unsigned_int(void) {
return -10;
}
-short add_int16(short x) {
+EXPORT short add_int16(short x) {
return x + 3;
}
-long add_short_to_long(short x, long y) {
+EXPORT long add_short_to_long(short x, long y) {
return x + y;
}
+
+// To test that functions not marked with EXPORT cannot be called by Miri.
+int not_exported(void) {
+ return 0;
+}
diff --git a/src/tools/miri/tests/pass/arrays.rs b/src/tools/miri/tests/pass/arrays.rs
index 61b4445..b0c6f54 100644
--- a/src/tools/miri/tests/pass/arrays.rs
+++ b/src/tools/miri/tests/pass/arrays.rs
@@ -61,6 +61,20 @@ fn debug() {
println!("{:?}", array);
}
+fn huge_zst() {
+ fn id<T>(x: T) -> T { x }
+
+ // A "huge" zero-sized array. Make sure we don't loop over it in any part of Miri.
+ let val = [(); usize::MAX];
+ id(val); // make a copy
+
+ let val = [val; 2];
+ id(val);
+
+ // Also wrap it in a union (which, in particular, hits the logic for computing union padding).
+ let _copy = std::mem::MaybeUninit::new(val);
+}
+
fn main() {
assert_eq!(empty_array(), []);
assert_eq!(index_unsafe(), 20);
@@ -73,4 +87,5 @@ fn main() {
from();
eq();
debug();
+ huge_zst();
}
diff --git a/src/tools/miri/tests/pass/async-niche-aliasing.rs b/src/tools/miri/tests/pass/async-niche-aliasing.rs
new file mode 100644
index 0000000..7f19afb
--- /dev/null
+++ b/src/tools/miri/tests/pass/async-niche-aliasing.rs
@@ -0,0 +1,66 @@
+//@revisions: stack tree
+//@[tree]compile-flags: -Zmiri-tree-borrows
+
+use std::{
+ future::Future,
+ pin::Pin,
+ sync::Arc,
+ task::{Context, Poll, Wake},
+ mem::MaybeUninit,
+};
+
+struct ThingAdder<'a> {
+ // Using `MaybeUninit` to ensure there are no niches here.
+ thing: MaybeUninit<&'a mut String>,
+}
+
+impl Future for ThingAdder<'_> {
+ type Output = ();
+
+ fn poll(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<Self::Output> {
+ unsafe {
+ **self.get_unchecked_mut().thing.assume_init_mut() += ", world";
+ }
+ Poll::Pending
+ }
+}
+
+fn main() {
+ let mut thing = "hello".to_owned();
+ // This future has (at least) two fields, a String (`thing`) and a ThingAdder pointing to that string.
+ let fut = async move { ThingAdder { thing: MaybeUninit::new(&mut thing) }.await };
+
+ let mut fut = MaybeDone::Future(fut);
+ let mut fut = unsafe { Pin::new_unchecked(&mut fut) };
+
+ let waker = Arc::new(DummyWaker).into();
+ let mut ctx = Context::from_waker(&waker);
+ // This ends up reading the discriminant of the `MaybeDone`. If that is stored inside the
+ // `thing: String` as a niche optimization, that causes aliasing conflicts with the reference
+ // stored in `ThingAdder`.
+ assert_eq!(fut.as_mut().poll(&mut ctx), Poll::Pending);
+ assert_eq!(fut.as_mut().poll(&mut ctx), Poll::Pending);
+}
+
+struct DummyWaker;
+
+impl Wake for DummyWaker {
+ fn wake(self: Arc<Self>) {}
+}
+
+pub enum MaybeDone<F: Future> {
+ Future(F),
+ Done,
+}
+impl<F: Future<Output = ()>> Future for MaybeDone<F> {
+ type Output = ();
+
+ fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
+ unsafe {
+ match *self.as_mut().get_unchecked_mut() {
+ MaybeDone::Future(ref mut f) => Pin::new_unchecked(f).poll(cx),
+ MaybeDone::Done => unreachable!(),
+ }
+ }
+ }
+}
diff --git a/src/tools/miri/tests/pass/enums.rs b/src/tools/miri/tests/pass/enums.rs
index 1dafef0..9fc61f0 100644
--- a/src/tools/miri/tests/pass/enums.rs
+++ b/src/tools/miri/tests/pass/enums.rs
@@ -132,6 +132,43 @@ enum Aligned {
assert_eq!(aligned as u8, 0);
}
+// This hits a corner case in the logic for clearing padding on typed copies.
+fn padding_clear_corner_case() {
+ #[allow(unused)]
+ #[derive(Copy, Clone)]
+ #[repr(C)]
+ pub struct Decoded {
+ /// The scaled mantissa.
+ pub mant: u64,
+ /// The lower error range.
+ pub minus: u64,
+ /// The upper error range.
+ pub plus: u64,
+ /// The shared exponent in base 2.
+ pub exp: i16,
+ /// True when the error range is inclusive.
+ ///
+ /// In IEEE 754, this is true when the original mantissa was even.
+ pub inclusive: bool,
+ }
+
+ #[allow(unused)]
+ #[derive(Copy, Clone)]
+ pub enum FullDecoded {
+ /// Not-a-number.
+ Nan,
+ /// Infinities, either positive or negative.
+ Infinite,
+ /// Zero, either positive or negative.
+ Zero,
+ /// Finite numbers with further decoded fields.
+ Finite(Decoded),
+ }
+
+ let val = FullDecoded::Finite(Decoded { mant: 0, minus: 0, plus: 0, exp: 0, inclusive: false });
+ let _val2 = val; // trigger typed copy
+}
+
fn main() {
test(MyEnum::MyEmptyVariant);
test(MyEnum::MyNewtypeVariant(42));
@@ -141,4 +178,5 @@ fn main() {
discriminant_overflow();
more_discriminant_overflow();
overaligned_casts();
+ padding_clear_corner_case();
}
diff --git a/src/tools/miri/tests/pass/provenance.rs b/src/tools/miri/tests/pass/provenance.rs
index 9e8a965..2e4d240 100644
--- a/src/tools/miri/tests/pass/provenance.rs
+++ b/src/tools/miri/tests/pass/provenance.rs
@@ -12,6 +12,7 @@ fn main() {
bytewise_custom_memcpy();
bytewise_custom_memcpy_chunked();
int_load_strip_provenance();
+ maybe_uninit_preserves_partial_provenance();
}
/// Some basic smoke tests for provenance.
@@ -145,3 +146,24 @@ fn int_load_strip_provenance() {
let ints: [usize; 1] = unsafe { mem::transmute(ptrs) };
assert_eq!(ptrs[0] as *const _ as usize, ints[0]);
}
+
+fn maybe_uninit_preserves_partial_provenance() {
+ // This is the same test as ptr_copy_loses_partial_provenance.rs, but using MaybeUninit and thus
+ // properly preserving partial provenance.
+ unsafe {
+ let mut bytes = [1u8; 16];
+ let bytes = bytes.as_mut_ptr();
+
+ // Put a pointer in the middle.
+ bytes.add(4).cast::<&i32>().write_unaligned(&42);
+ // Copy the entire thing as two pointers but not perfectly
+ // overlapping with the pointer we have in there.
+ let copy = bytes.cast::<[mem::MaybeUninit<*const ()>; 2]>().read_unaligned();
+ let copy_bytes = copy.as_ptr().cast::<u8>();
+ // Now go to the middle of the copy and get the pointer back out.
+ let ptr = copy_bytes.add(4).cast::<*const i32>().read_unaligned();
+ // And deref this to ensure we get the right value.
+ let val = *ptr;
+ assert_eq!(val, 42);
+ }
+}
diff --git a/src/tools/miri/tests/ui.rs b/src/tools/miri/tests/ui.rs
index c510ef9..e62394b 100644
--- a/src/tools/miri/tests/ui.rs
+++ b/src/tools/miri/tests/ui.rs
@@ -36,20 +36,21 @@ fn build_native_lib() -> PathBuf {
// Create the directory if it does not already exist.
std::fs::create_dir_all(&so_target_dir)
.expect("Failed to create directory for shared object file");
- let so_file_path = so_target_dir.join("native-lib.so");
+ // We use a platform-neutral file extension to avoid having to hard-code alternatives.
+ let native_lib_path = so_target_dir.join("native-lib.module");
let cc_output = Command::new(cc)
.args([
"-shared",
+ "-fPIC",
+ // We hide all symbols by default and export just the ones we need
+ // This is to future-proof against a more complex shared object which eg defines its own malloc
+ // (but we wouldn't want miri to call that, as it would if it was exported).
+ "-fvisibility=hidden",
"-o",
- so_file_path.to_str().unwrap(),
+ native_lib_path.to_str().unwrap(),
// FIXME: Automate gathering of all relevant C source files in the directory.
"tests/native-lib/scalar_arguments.c",
"tests/native-lib/ptr_read_access.c",
- // Only add the functions specified in libcode.version to the shared object file.
- // This is to avoid automatically adding `malloc`, etc.
- // Source: https://anadoxin.org/blog/control-over-symbol-exports-in-gcc.html/
- "-fPIC",
- "-Wl,--version-script=tests/native-lib/native-lib.map",
// Ensure we notice serious problems in the C code.
"-Wall",
"-Wextra",
@@ -64,7 +65,7 @@ fn build_native_lib() -> PathBuf {
String::from_utf8_lossy(&cc_output.stderr),
);
}
- so_file_path
+ native_lib_path
}
/// Does *not* set any args or env vars, since it is shared between the test runner and
@@ -300,7 +301,7 @@ fn main() -> Result<()> {
WithDependencies,
tmpdir.path(),
)?;
- if cfg!(target_os = "linux") {
+ if cfg!(unix) {
ui(Mode::Pass, "tests/native-lib/pass", &target, WithoutDependencies, tmpdir.path())?;
ui(
Mode::Fail { require_patterns: true, rustfix: RustfixMode::Disabled },
diff --git a/src/tools/run-make-support/src/command.rs b/src/tools/run-make-support/src/command.rs
index a0b96e2..6b58173 100644
--- a/src/tools/run-make-support/src/command.rs
+++ b/src/tools/run-make-support/src/command.rs
@@ -15,7 +15,7 @@
/// This is a custom command wrapper that simplifies working with commands and makes it easier to
/// ensure that we check the exit status of executed processes.
///
-/// # A [`Command`] must be executed
+/// # A [`Command`] must be executed exactly once
///
/// A [`Command`] is armed by a [`DropBomb`] on construction to enforce that it will be executed. If
/// a [`Command`] is constructed but never executed, the drop bomb will explode and cause the test
@@ -23,26 +23,73 @@
/// containing constructed but never executed commands is dangerous because it can give a false
/// sense of confidence.
///
+/// Each [`Command`] invocation can also only be executed once, because we want to enforce
+/// `std{in,out,err}` config via [`std::process::Stdio`] but [`std::process::Stdio`] is not
+/// cloneable.
+///
+/// In this sense, [`Command`] exhibits linear type semantics but enforced at run-time.
+///
/// [`run`]: Self::run
/// [`run_fail`]: Self::run_fail
/// [`run_unchecked`]: Self::run_unchecked
#[derive(Debug)]
pub struct Command {
cmd: StdCommand,
- stdin: Option<Box<[u8]>>,
+ // Convience for providing a quick stdin buffer.
+ stdin_buf: Option<Box<[u8]>>,
+
+ // Configurations for child process's std{in,out,err} handles.
+ stdin: Option<Stdio>,
+ stdout: Option<Stdio>,
+ stderr: Option<Stdio>,
+
+ // Emulate linear type semantics.
drop_bomb: DropBomb,
+ already_executed: bool,
}
impl Command {
#[track_caller]
pub fn new<P: AsRef<OsStr>>(program: P) -> Self {
let program = program.as_ref();
- Self { cmd: StdCommand::new(program), stdin: None, drop_bomb: DropBomb::arm(program) }
+ Self {
+ cmd: StdCommand::new(program),
+ stdin_buf: None,
+ drop_bomb: DropBomb::arm(program),
+ stdin: None,
+ stdout: None,
+ stderr: None,
+ already_executed: false,
+ }
}
- /// Specify a stdin input
- pub fn stdin<I: AsRef<[u8]>>(&mut self, input: I) -> &mut Self {
- self.stdin = Some(input.as_ref().to_vec().into_boxed_slice());
+ /// Specify a stdin input buffer. This is a convenience helper,
+ pub fn stdin_buf<I: AsRef<[u8]>>(&mut self, input: I) -> &mut Self {
+ self.stdin_buf = Some(input.as_ref().to_vec().into_boxed_slice());
+ self
+ }
+
+ /// Configuration for the child process’s standard input (stdin) handle.
+ ///
+ /// See [`std::process::Command::stdin`].
+ pub fn stdin<T: Into<Stdio>>(&mut self, cfg: T) -> &mut Self {
+ self.stdin = Some(cfg.into());
+ self
+ }
+
+ /// Configuration for the child process’s standard output (stdout) handle.
+ ///
+ /// See [`std::process::Command::stdout`].
+ pub fn stdout<T: Into<Stdio>>(&mut self, cfg: T) -> &mut Self {
+ self.stdout = Some(cfg.into());
+ self
+ }
+
+ /// Configuration for the child process’s standard error (stderr) handle.
+ ///
+ /// See [`std::process::Command::stderr`].
+ pub fn stderr<T: Into<Stdio>>(&mut self, cfg: T) -> &mut Self {
+ self.stderr = Some(cfg.into());
self
}
@@ -105,6 +152,8 @@ pub fn current_dir<P: AsRef<Path>>(&mut self, path: P) -> &mut Self {
}
/// Run the constructed command and assert that it is successfully run.
+ ///
+ /// By default, std{in,out,err} are [`Stdio::piped()`].
#[track_caller]
pub fn run(&mut self) -> CompletedProcess {
let output = self.command_output();
@@ -115,6 +164,8 @@ pub fn run(&mut self) -> CompletedProcess {
}
/// Run the constructed command and assert that it does not successfully run.
+ ///
+ /// By default, std{in,out,err} are [`Stdio::piped()`].
#[track_caller]
pub fn run_fail(&mut self) -> CompletedProcess {
let output = self.command_output();
@@ -124,10 +175,10 @@ pub fn run_fail(&mut self) -> CompletedProcess {
output
}
- /// Run the command but do not check its exit status.
- /// Only use if you explicitly don't care about the exit status.
- /// Prefer to use [`Self::run`] and [`Self::run_fail`]
- /// whenever possible.
+ /// Run the command but do not check its exit status. Only use if you explicitly don't care
+ /// about the exit status.
+ ///
+ /// Prefer to use [`Self::run`] and [`Self::run_fail`] whenever possible.
#[track_caller]
pub fn run_unchecked(&mut self) -> CompletedProcess {
self.command_output()
@@ -135,13 +186,19 @@ pub fn run_unchecked(&mut self) -> CompletedProcess {
#[track_caller]
fn command_output(&mut self) -> CompletedProcess {
+ if self.already_executed {
+ panic!("command was already executed");
+ } else {
+ self.already_executed = true;
+ }
+
self.drop_bomb.defuse();
// let's make sure we piped all the input and outputs
- self.cmd.stdin(Stdio::piped());
- self.cmd.stdout(Stdio::piped());
- self.cmd.stderr(Stdio::piped());
+ self.cmd.stdin(self.stdin.take().unwrap_or(Stdio::piped()));
+ self.cmd.stdout(self.stdout.take().unwrap_or(Stdio::piped()));
+ self.cmd.stderr(self.stderr.take().unwrap_or(Stdio::piped()));
- let output = if let Some(input) = &self.stdin {
+ let output = if let Some(input) = &self.stdin_buf {
let mut child = self.cmd.spawn().unwrap();
{
diff --git a/src/tools/run-make-support/src/external_deps/cargo.rs b/src/tools/run-make-support/src/external_deps/cargo.rs
new file mode 100644
index 0000000..b0e045d
--- /dev/null
+++ b/src/tools/run-make-support/src/external_deps/cargo.rs
@@ -0,0 +1,7 @@
+use crate::command::Command;
+use crate::env_var;
+
+/// Returns a command that can be used to invoke Cargo.
+pub fn cargo() -> Command {
+ Command::new(env_var("BOOTSTRAP_CARGO"))
+}
diff --git a/src/tools/run-make-support/src/external_deps/llvm.rs b/src/tools/run-make-support/src/external_deps/llvm.rs
index e931585..16c4251 100644
--- a/src/tools/run-make-support/src/external_deps/llvm.rs
+++ b/src/tools/run-make-support/src/external_deps/llvm.rs
@@ -110,6 +110,13 @@ pub struct LlvmDwarfdump {
cmd: Command,
}
+/// A `llvm-pdbutil` invocation builder.
+#[derive(Debug)]
+#[must_use]
+pub struct LlvmPdbutil {
+ cmd: Command,
+}
+
crate::macros::impl_common_helpers!(LlvmReadobj);
crate::macros::impl_common_helpers!(LlvmProfdata);
crate::macros::impl_common_helpers!(LlvmFilecheck);
@@ -118,6 +125,7 @@ pub struct LlvmDwarfdump {
crate::macros::impl_common_helpers!(LlvmNm);
crate::macros::impl_common_helpers!(LlvmBcanalyzer);
crate::macros::impl_common_helpers!(LlvmDwarfdump);
+crate::macros::impl_common_helpers!(LlvmPdbutil);
/// Generate the path to the bin directory of LLVM.
#[must_use]
@@ -227,9 +235,10 @@ pub fn new() -> Self {
Self { cmd }
}
- /// Pipe a read file into standard input containing patterns that will be matched against the .patterns(path) call.
- pub fn stdin<I: AsRef<[u8]>>(&mut self, input: I) -> &mut Self {
- self.cmd.stdin(input);
+ /// Provide a buffer representing standard input containing patterns that will be matched
+ /// against the `.patterns(path)` call.
+ pub fn stdin_buf<I: AsRef<[u8]>>(&mut self, input: I) -> &mut Self {
+ self.cmd.stdin_buf(input);
self
}
@@ -359,3 +368,19 @@ pub fn input<P: AsRef<Path>>(&mut self, path: P) -> &mut Self {
self
}
}
+
+impl LlvmPdbutil {
+ /// Construct a new `llvm-pdbutil` invocation. This assumes that `llvm-pdbutil` is available
+ /// at `$LLVM_BIN_DIR/llvm-pdbutil`.
+ pub fn new() -> Self {
+ let llvm_pdbutil = llvm_bin_dir().join("llvm-pdbutil");
+ let cmd = Command::new(llvm_pdbutil);
+ Self { cmd }
+ }
+
+ /// Provide an input file.
+ pub fn input<P: AsRef<Path>>(&mut self, path: P) -> &mut Self {
+ self.cmd.arg(path.as_ref());
+ self
+ }
+}
diff --git a/src/tools/run-make-support/src/external_deps/mod.rs b/src/tools/run-make-support/src/external_deps/mod.rs
index f7c8472..80c34a9 100644
--- a/src/tools/run-make-support/src/external_deps/mod.rs
+++ b/src/tools/run-make-support/src/external_deps/mod.rs
@@ -2,6 +2,7 @@
//! such as `cc` or `python`.
pub mod c_build;
+pub mod cargo;
pub mod cc;
pub mod clang;
pub mod htmldocck;
diff --git a/src/tools/run-make-support/src/external_deps/rustc.rs b/src/tools/run-make-support/src/external_deps/rustc.rs
index cece58d..35d983d 100644
--- a/src/tools/run-make-support/src/external_deps/rustc.rs
+++ b/src/tools/run-make-support/src/external_deps/rustc.rs
@@ -36,10 +36,13 @@ pub struct Rustc {
crate::macros::impl_common_helpers!(Rustc);
+pub fn rustc_path() -> String {
+ env_var("RUSTC")
+}
+
#[track_caller]
fn setup_common() -> Command {
- let rustc = env_var("RUSTC");
- let mut cmd = Command::new(rustc);
+ let mut cmd = Command::new(rustc_path());
set_host_rpath(&mut cmd);
cmd
}
@@ -291,9 +294,9 @@ pub fn link_args(&mut self, link_args: &str) -> &mut Self {
self
}
- /// Specify a stdin input
- pub fn stdin<I: AsRef<[u8]>>(&mut self, input: I) -> &mut Self {
- self.cmd.stdin(input);
+ /// Specify a stdin input buffer.
+ pub fn stdin_buf<I: AsRef<[u8]>>(&mut self, input: I) -> &mut Self {
+ self.cmd.stdin_buf(input);
self
}
diff --git a/src/tools/run-make-support/src/external_deps/rustdoc.rs b/src/tools/run-make-support/src/external_deps/rustdoc.rs
index 96b1c71..df5e5d8 100644
--- a/src/tools/run-make-support/src/external_deps/rustdoc.rs
+++ b/src/tools/run-make-support/src/external_deps/rustdoc.rs
@@ -85,9 +85,9 @@ pub fn arg_file<P: AsRef<Path>>(&mut self, path: P) -> &mut Self {
self
}
- /// Specify a stdin input
- pub fn stdin<I: AsRef<[u8]>>(&mut self, input: I) -> &mut Self {
- self.cmd.stdin(input);
+ /// Specify a stdin input buffer.
+ pub fn stdin_buf<I: AsRef<[u8]>>(&mut self, input: I) -> &mut Self {
+ self.cmd.stdin_buf(input);
self
}
diff --git a/src/tools/run-make-support/src/lib.rs b/src/tools/run-make-support/src/lib.rs
index 989d00d..15d813c 100644
--- a/src/tools/run-make-support/src/lib.rs
+++ b/src/tools/run-make-support/src/lib.rs
@@ -34,6 +34,7 @@ pub mod rfs {
}
// Re-exports of third-party library crates.
+// tidy-alphabetical-start
pub use bstr;
pub use gimli;
pub use libc;
@@ -41,6 +42,7 @@ pub mod rfs {
pub use regex;
pub use serde_json;
pub use wasmparser;
+// tidy-alphabetical-end
// Re-exports of external dependencies.
pub use external_deps::{c_build, cc, clang, htmldocck, llvm, python, rustc, rustdoc};
@@ -48,6 +50,7 @@ pub mod rfs {
// These rely on external dependencies.
pub use cc::{cc, cxx, extra_c_flags, extra_cxx_flags, Cc};
pub use c_build::{build_native_dynamic_lib, build_native_static_lib, build_native_static_lib_optimized, build_native_static_lib_cxx};
+pub use cargo::cargo;
pub use clang::{clang, Clang};
pub use htmldocck::htmldocck;
pub use llvm::{
@@ -56,7 +59,7 @@ pub mod rfs {
LlvmProfdata, LlvmReadobj,
};
pub use python::python_command;
-pub use rustc::{aux_build, bare_rustc, rustc, Rustc};
+pub use rustc::{aux_build, bare_rustc, rustc, rustc_path, Rustc};
pub use rustdoc::{bare_rustdoc, rustdoc, Rustdoc};
/// [`diff`][mod@diff] is implemented in terms of the [similar] library.
@@ -71,7 +74,7 @@ pub mod rfs {
pub use run::{cmd, run, run_fail, run_with_args};
/// Helpers for checking target information.
-pub use targets::{is_darwin, is_msvc, is_windows, llvm_components_contain, target, uname};
+pub use targets::{is_darwin, is_msvc, is_windows, llvm_components_contain, target, uname, apple_os};
/// Helpers for building names of output artifacts that are potentially target-specific.
pub use artifact_names::{
@@ -96,3 +99,4 @@ pub mod rfs {
pub use string::{
count_regex_matches_in_files_with_extension, invalid_utf8_contains, invalid_utf8_not_contains,
};
+use crate::external_deps::cargo;
diff --git a/src/tools/run-make-support/src/targets.rs b/src/tools/run-make-support/src/targets.rs
index 5dcb0b8..896abb7 100644
--- a/src/tools/run-make-support/src/targets.rs
+++ b/src/tools/run-make-support/src/targets.rs
@@ -28,6 +28,24 @@ pub fn is_darwin() -> bool {
target().contains("darwin")
}
+/// Get the target OS on Apple operating systems.
+#[must_use]
+pub fn apple_os() -> &'static str {
+ if target().contains("darwin") {
+ "macos"
+ } else if target().contains("ios") {
+ "ios"
+ } else if target().contains("tvos") {
+ "tvos"
+ } else if target().contains("watchos") {
+ "watchos"
+ } else if target().contains("visionos") {
+ "visionos"
+ } else {
+ panic!("not an Apple OS")
+ }
+}
+
/// Check if `component` is within `LLVM_COMPONENTS`
#[must_use]
pub fn llvm_components_contain(component: &str) -> bool {
diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/inert_attr_macro.rs b/src/tools/rust-analyzer/crates/hir-expand/src/inert_attr_macro.rs
index ee15b1b..5c25a55 100644
--- a/src/tools/rust-analyzer/crates/hir-expand/src/inert_attr_macro.rs
+++ b/src/tools/rust-analyzer/crates/hir-expand/src/inert_attr_macro.rs
@@ -464,6 +464,9 @@ macro_rules! experimental {
// Used by the `rustc::potential_query_instability` lint to warn methods which
// might not be stable during incremental compilation.
rustc_attr!(rustc_lint_query_instability, Normal, template!(Word), WarnFollowing, INTERNAL_UNSTABLE),
+ // Used by the `rustc::untracked_query_information` lint to warn methods which
+ // might break incremental compilation.
+ rustc_attr!(rustc_lint_untracked_query_information, Normal, template!(Word), WarnFollowing, INTERNAL_UNSTABLE),
// Used by the `rustc::untranslatable_diagnostic` and `rustc::diagnostic_outside_of_impl` lints
// to assist in changes to diagnostic APIs.
rustc_attr!(rustc_lint_diagnostics, Normal, template!(Word), WarnFollowing, INTERNAL_UNSTABLE),
diff --git a/src/tools/rust-analyzer/crates/parser/src/lexed_str.rs b/src/tools/rust-analyzer/crates/parser/src/lexed_str.rs
index ff92483..3590486 100644
--- a/src/tools/rust-analyzer/crates/parser/src/lexed_str.rs
+++ b/src/tools/rust-analyzer/crates/parser/src/lexed_str.rs
@@ -198,6 +198,13 @@ fn extend_token(&mut self, kind: &rustc_lexer::TokenKind, token_text: &str) {
}
LIFETIME_IDENT
}
+ rustc_lexer::TokenKind::UnknownPrefixLifetime => {
+ err = "Unknown lifetime prefix";
+ LIFETIME_IDENT
+ }
+ rustc_lexer::TokenKind::RawLifetime => {
+ LIFETIME_IDENT
+ }
rustc_lexer::TokenKind::Semi => T![;],
rustc_lexer::TokenKind::Comma => T![,],
diff --git a/src/tools/rustfmt/src/expr.rs b/src/tools/rustfmt/src/expr.rs
index 6ba5217..75c75c5 100644
--- a/src/tools/rustfmt/src/expr.rs
+++ b/src/tools/rustfmt/src/expr.rs
@@ -462,7 +462,7 @@ fn rewrite_empty_block(
return None;
}
- let label_str = rewrite_label(label);
+ let label_str = rewrite_label(context, label);
if attrs.map_or(false, |a| !inner_attributes(a).is_empty()) {
return None;
}
@@ -527,7 +527,7 @@ fn rewrite_single_line_block(
if let Some(block_expr) = stmt::Stmt::from_simple_block(context, block, attrs) {
let expr_shape = shape.offset_left(last_line_width(prefix))?;
let expr_str = block_expr.rewrite(context, expr_shape)?;
- let label_str = rewrite_label(label);
+ let label_str = rewrite_label(context, label);
let result = format!("{prefix}{label_str}{{ {expr_str} }}");
if result.len() <= shape.width && !result.contains('\n') {
return Some(result);
@@ -562,7 +562,7 @@ pub(crate) fn rewrite_block_with_visitor(
}
let inner_attrs = attrs.map(inner_attributes);
- let label_str = rewrite_label(label);
+ let label_str = rewrite_label(context, label);
visitor.visit_block(block, inner_attrs.as_deref(), has_braces);
let visitor_context = visitor.get_context();
context
@@ -939,7 +939,7 @@ fn rewrite_cond(
fresh_shape
};
- let label_string = rewrite_label(self.label);
+ let label_string = rewrite_label(context, self.label);
// 1 = space after keyword.
let offset = self.keyword.len() + label_string.len() + 1;
@@ -1168,9 +1168,9 @@ fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option<String>
}
}
-fn rewrite_label(opt_label: Option<ast::Label>) -> Cow<'static, str> {
+fn rewrite_label(context: &RewriteContext<'_>, opt_label: Option<ast::Label>) -> Cow<'static, str> {
match opt_label {
- Some(label) => Cow::from(format!("{}: ", label.ident)),
+ Some(label) => Cow::from(format!("{}: ", context.snippet(label.ident.span))),
None => Cow::from(""),
}
}
diff --git a/src/tools/rustfmt/src/macros.rs b/src/tools/rustfmt/src/macros.rs
index b14b74a..524fc66 100644
--- a/src/tools/rustfmt/src/macros.rs
+++ b/src/tools/rustfmt/src/macros.rs
@@ -1074,7 +1074,7 @@ fn force_space_before(tok: &TokenKind) -> bool {
fn ident_like(tok: &Token) -> bool {
matches!(
tok.kind,
- TokenKind::Ident(..) | TokenKind::Literal(..) | TokenKind::Lifetime(_)
+ TokenKind::Ident(..) | TokenKind::Literal(..) | TokenKind::Lifetime(..)
)
}
@@ -1099,7 +1099,9 @@ fn next_space(tok: &TokenKind) -> SpaceState {
| TokenKind::OpenDelim(_)
| TokenKind::CloseDelim(_) => SpaceState::Never,
- TokenKind::Literal(..) | TokenKind::Ident(..) | TokenKind::Lifetime(_) => SpaceState::Ident,
+ TokenKind::Literal(..) | TokenKind::Ident(..) | TokenKind::Lifetime(..) => {
+ SpaceState::Ident
+ }
_ => SpaceState::Always,
}
diff --git a/src/tools/rustfmt/src/types.rs b/src/tools/rustfmt/src/types.rs
index 875c611..7730aa4 100644
--- a/src/tools/rustfmt/src/types.rs
+++ b/src/tools/rustfmt/src/types.rs
@@ -548,7 +548,7 @@ fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option<String>
impl Rewrite for ast::Lifetime {
fn rewrite(&self, context: &RewriteContext<'_>, _: Shape) -> Option<String> {
- Some(rewrite_ident(context, self.ident).to_owned())
+ Some(context.snippet(self.ident.span).to_owned())
}
}
diff --git a/src/tools/rustfmt/tests/target/raw-lifetimes.rs b/src/tools/rustfmt/tests/target/raw-lifetimes.rs
new file mode 100644
index 0000000..62fb9be
--- /dev/null
+++ b/src/tools/rustfmt/tests/target/raw-lifetimes.rs
@@ -0,0 +1,15 @@
+// rustfmt-edition: 2021
+
+// Simple idempotence test for raw lifetimes.
+
+fn test<'r#gen>() -> &'r#gen () {
+ // Test raw lifetimes...
+}
+
+fn label() {
+ 'r#label: {
+ // Test raw labels.
+ }
+}
+
+fn main() {}
diff --git a/src/tools/tidy/config/black.toml b/src/tools/tidy/config/black.toml
index e73847a..a1e1eef 100644
--- a/src/tools/tidy/config/black.toml
+++ b/src/tools/tidy/config/black.toml
@@ -12,5 +12,6 @@
src/llvm-project/|\
src/doc/embedded-book/|\
src/tools/rustc-perf/|\
+ src/tools/enzyme/|\
library/backtrace/
)"""
diff --git a/src/tools/tidy/config/ruff.toml b/src/tools/tidy/config/ruff.toml
index c87c17f..2be1090 100644
--- a/src/tools/tidy/config/ruff.toml
+++ b/src/tools/tidy/config/ruff.toml
@@ -16,6 +16,7 @@
"src/llvm-project/",
"src/doc/embedded-book/",
"library/backtrace/",
+ "src/tools/enzyme/",
"src/tools/rustc-perf/",
# Hack: CI runs from a subdirectory under the main checkout
"../src/doc/nomicon/",
@@ -29,6 +30,7 @@
"../src/llvm-project/",
"../src/doc/embedded-book/",
"../library/backtrace/",
+ "../src/tools/enzyme/",
"../src/tools/rustc-perf/",
]
diff --git a/src/tools/tidy/src/allowed_run_make_makefiles.txt b/src/tools/tidy/src/allowed_run_make_makefiles.txt
index 22d1e93..50d21c7 100644
--- a/src/tools/tidy/src/allowed_run_make_makefiles.txt
+++ b/src/tools/tidy/src/allowed_run_make_makefiles.txt
@@ -6,7 +6,6 @@
run-make/issue-84395-lto-embed-bitcode/Makefile
run-make/jobserver-error/Makefile
run-make/libs-through-symlinks/Makefile
-run-make/macos-deployment-target/Makefile
run-make/split-debuginfo/Makefile
run-make/symbol-mangling-hashed/Makefile
run-make/translation/Makefile
diff --git a/src/tools/tidy/src/walk.rs b/src/tools/tidy/src/walk.rs
index d4721b5..4a69022 100644
--- a/src/tools/tidy/src/walk.rs
+++ b/src/tools/tidy/src/walk.rs
@@ -24,6 +24,7 @@ pub fn filter_dirs(path: &Path) -> bool {
"src/tools/rust-analyzer",
"src/tools/rustc-perf",
"src/tools/rustfmt",
+ "src/tools/enzyme",
"src/doc/book",
"src/doc/edition-guide",
"src/doc/embedded-book",
diff --git a/src/tools/wasm-component-ld/README.md b/src/tools/wasm-component-ld/README.md
index 54608a2..b51de9a 100644
--- a/src/tools/wasm-component-ld/README.md
+++ b/src/tools/wasm-component-ld/README.md
@@ -1,7 +1,7 @@
# `wasm-component-ld`
-This wrapper is a wrapper around the [`wasm-component-ld`] crates.io crate. That
-crate. That crate is itself a thin wrapper around two pieces:
+This wrapper is a wrapper around the [`wasm-component-ld`] crates.io crate.
+That crate is itself a thin wrapper around two pieces:
* `wasm-ld` - the LLVM-based linker distributed as part of LLD and packaged in
Rust as `rust-lld`.
diff --git a/tests/assembly/asm/aarch64-modifiers.rs b/tests/assembly/asm/aarch64-modifiers.rs
index b7ef1d7..a4a41dd 100644
--- a/tests/assembly/asm/aarch64-modifiers.rs
+++ b/tests/assembly/asm/aarch64-modifiers.rs
@@ -1,6 +1,7 @@
//@ assembly-output: emit-asm
//@ compile-flags: -O -C panic=abort
//@ compile-flags: --target aarch64-unknown-linux-gnu
+//@ compile-flags: -Zmerge-functions=disabled
//@ needs-llvm-components: aarch64
#![feature(no_core, lang_items, rustc_attrs)]
@@ -29,12 +30,6 @@ macro_rules! check {
// -O and extern "C" guarantee that the selected register is always r0/s0/d0/q0
#[no_mangle]
pub unsafe extern "C" fn $func() -> i32 {
- // Hack to avoid function merging
- extern "Rust" {
- fn dont_merge(s: &str);
- }
- dont_merge(stringify!($func));
-
let y;
asm!($code, out($reg) y);
y
diff --git a/tests/assembly/asm/aarch64-types.rs b/tests/assembly/asm/aarch64-types.rs
index f363456..cf1882b 100644
--- a/tests/assembly/asm/aarch64-types.rs
+++ b/tests/assembly/asm/aarch64-types.rs
@@ -4,6 +4,7 @@
//@ [aarch64] needs-llvm-components: aarch64
//@ [arm64ec] compile-flags: --target arm64ec-pc-windows-msvc
//@ [arm64ec] needs-llvm-components: aarch64
+//@ compile-flags: -Zmerge-functions=disabled
#![feature(no_core, lang_items, rustc_attrs, repr_simd, asm_experimental_arch, f16, f128)]
#![crate_type = "rlib"]
@@ -132,12 +133,6 @@ macro_rules! check {
// LLVM issue: <https://github.com/llvm/llvm-project/issues/94434>
#[no_mangle]
pub unsafe fn $func(inp: &$ty, out: &mut $ty) {
- // Hack to avoid function merging
- extern "Rust" {
- fn dont_merge(s: &str);
- }
- dont_merge(stringify!($func));
-
let x = *inp;
let y;
asm!(
@@ -155,12 +150,6 @@ macro_rules! check_reg {
// FIXME(f16_f128): See FIXME in `check!`
#[no_mangle]
pub unsafe fn $func(inp: &$ty, out: &mut $ty) {
- // Hack to avoid function merging
- extern "Rust" {
- fn dont_merge(s: &str);
- }
- dont_merge(stringify!($func));
-
let x = *inp;
let y;
asm!(concat!($mov, " ", $reg, ", ", $reg), lateout($reg) y, in($reg) x);
diff --git a/tests/assembly/asm/arm-modifiers.rs b/tests/assembly/asm/arm-modifiers.rs
index 0674e16..d421e0e 100644
--- a/tests/assembly/asm/arm-modifiers.rs
+++ b/tests/assembly/asm/arm-modifiers.rs
@@ -2,6 +2,7 @@
//@ compile-flags: -O -C panic=abort
//@ compile-flags: --target armv7-unknown-linux-gnueabihf
//@ compile-flags: -C target-feature=+neon
+//@ compile-flags: -Zmerge-functions=disabled
//@ needs-llvm-components: arm
#![feature(no_core, lang_items, rustc_attrs, repr_simd)]
@@ -40,12 +41,6 @@ macro_rules! check {
// -O and extern "C" guarantee that the selected register is always r0/s0/d0/q0
#[no_mangle]
pub unsafe extern "C" fn $func() -> $ty {
- // Hack to avoid function merging
- extern "Rust" {
- fn dont_merge(s: &str);
- }
- dont_merge(stringify!($func));
-
let y;
asm!(concat!($mov, " {0:", $modifier, "}, {0:", $modifier, "}"), out($reg) y);
y
diff --git a/tests/assembly/asm/arm-types.rs b/tests/assembly/asm/arm-types.rs
index eeff1a0..448b92a 100644
--- a/tests/assembly/asm/arm-types.rs
+++ b/tests/assembly/asm/arm-types.rs
@@ -2,6 +2,7 @@
//@ assembly-output: emit-asm
//@ compile-flags: --target armv7-unknown-linux-gnueabihf
//@ compile-flags: -C opt-level=0
+//@ compile-flags: -Zmerge-functions=disabled
//@[d32] compile-flags: -C target-feature=+d32
//@[neon] compile-flags: -C target-feature=+neon --cfg d32
//@[neon] filecheck-flags: --check-prefix d32
@@ -114,12 +115,6 @@ macro_rules! check {
($func:ident $ty:ident $class:ident $mov:literal) => {
#[no_mangle]
pub unsafe fn $func(x: $ty) -> $ty {
- // Hack to avoid function merging
- extern "Rust" {
- fn dont_merge(s: &str);
- }
- dont_merge(stringify!($func));
-
let y;
asm!(concat!($mov, " {}, {}"), out($class) y, in($class) x);
y
@@ -131,12 +126,6 @@ macro_rules! check_reg {
($func:ident $ty:ident $reg:tt $mov:literal) => {
#[no_mangle]
pub unsafe fn $func(x: $ty) -> $ty {
- // Hack to avoid function merging
- extern "Rust" {
- fn dont_merge(s: &str);
- }
- dont_merge(stringify!($func));
-
let y;
asm!(concat!($mov, " ", $reg, ", ", $reg), lateout($reg) y, in($reg) x);
y
diff --git a/tests/assembly/asm/hexagon-types.rs b/tests/assembly/asm/hexagon-types.rs
index 269c758..9389fcf 100644
--- a/tests/assembly/asm/hexagon-types.rs
+++ b/tests/assembly/asm/hexagon-types.rs
@@ -1,5 +1,6 @@
//@ assembly-output: emit-asm
//@ compile-flags: --target hexagon-unknown-linux-musl
+//@ compile-flags: -Zmerge-functions=disabled
//@ needs-llvm-components: hexagon
#![feature(no_core, lang_items, rustc_attrs, repr_simd, asm_experimental_arch)]
@@ -41,12 +42,6 @@ macro_rules! check {
($func:ident $ty:ident $class:ident) => {
#[no_mangle]
pub unsafe fn $func(x: $ty) -> $ty {
- // Hack to avoid function merging
- extern "Rust" {
- fn dont_merge(s: &str);
- }
- dont_merge(stringify!($func));
-
let y;
asm!("{} = {}", out($class) y, in($class) x);
y
@@ -58,12 +53,6 @@ macro_rules! check_reg {
($func:ident $ty:ident $reg:tt) => {
#[no_mangle]
pub unsafe fn $func(x: $ty) -> $ty {
- // Hack to avoid function merging
- extern "Rust" {
- fn dont_merge(s: &str);
- }
- dont_merge(stringify!($func));
-
let y;
asm!(concat!($reg, " = ", $reg), lateout($reg) y, in($reg) x);
y
@@ -77,12 +66,6 @@ pub unsafe fn $func(x: $ty) -> $ty {
// CHECK: InlineAsm End
#[no_mangle]
pub unsafe fn sym_static() {
- // Hack to avoid function merging
- extern "Rust" {
- fn dont_merge(s: &str);
- }
- dont_merge(stringify!($func));
-
asm!("r0 = #{}", sym extern_static);
}
@@ -92,12 +75,6 @@ pub unsafe fn sym_static() {
// CHECK: InlineAsm End
#[no_mangle]
pub unsafe fn sym_fn() {
- // Hack to avoid function merging
- extern "Rust" {
- fn dont_merge(s: &str);
- }
- dont_merge(stringify!($func));
-
asm!("r0 = #{}", sym extern_func);
}
diff --git a/tests/assembly/asm/loongarch-type.rs b/tests/assembly/asm/loongarch-type.rs
index e4c46cf..1b097f4 100644
--- a/tests/assembly/asm/loongarch-type.rs
+++ b/tests/assembly/asm/loongarch-type.rs
@@ -1,5 +1,6 @@
//@ assembly-output: emit-asm
//@ compile-flags: --target loongarch64-unknown-linux-gnu
+//@ compile-flags: -Zmerge-functions=disabled
//@ needs-llvm-components: loongarch
#![feature(no_core, lang_items, rustc_attrs, asm_experimental_arch)]
@@ -39,11 +40,6 @@ impl Copy for ptr {}
static extern_static: u8;
}
-// Hack to avoid function merging
-extern "Rust" {
- fn dont_merge(s: &str);
-}
-
// CHECK-LABEL: sym_fn:
// CHECK: #APP
// CHECK: pcalau12i $t0, %got_pc_hi20(extern_func)
@@ -67,8 +63,6 @@ pub unsafe fn sym_static() {
macro_rules! check { ($func:ident, $ty:ty, $class:ident, $mov:literal) => {
#[no_mangle]
pub unsafe fn $func(x: $ty) -> $ty {
- dont_merge(stringify!($func));
-
let y;
asm!(concat!($mov," {}, {}"), out($class) y, in($class) x);
y
@@ -78,8 +72,6 @@ pub unsafe fn $func(x: $ty) -> $ty {
macro_rules! check_reg { ($func:ident, $ty:ty, $reg:tt, $mov:literal) => {
#[no_mangle]
pub unsafe fn $func(x: $ty) -> $ty {
- dont_merge(stringify!($func));
-
let y;
asm!(concat!($mov, " ", $reg, ", ", $reg), lateout($reg) y, in($reg) x);
y
diff --git a/tests/assembly/asm/mips-types.rs b/tests/assembly/asm/mips-types.rs
index bd62f4a..f40a28b 100644
--- a/tests/assembly/asm/mips-types.rs
+++ b/tests/assembly/asm/mips-types.rs
@@ -4,6 +4,7 @@
//@[mips32] needs-llvm-components: mips
//@[mips64] compile-flags: --target mips64-unknown-linux-gnuabi64
//@[mips64] needs-llvm-components: mips
+//@ compile-flags: -Zmerge-functions=disabled
#![feature(no_core, lang_items, rustc_attrs, repr_simd, asm_experimental_arch)]
#![crate_type = "rlib"]
@@ -43,16 +44,9 @@ impl Copy for ptr {}
static extern_static: u8;
}
-// Hack to avoid function merging
-extern "Rust" {
- fn dont_merge(s: &str);
-}
-
macro_rules! check { ($func:ident, $ty:ty, $class:ident, $mov:literal) => {
#[no_mangle]
pub unsafe fn $func(x: $ty) -> $ty {
- dont_merge(stringify!($func));
-
let y;
asm!(concat!($mov," {}, {}"), out($class) y, in($class) x);
y
@@ -62,8 +56,6 @@ pub unsafe fn $func(x: $ty) -> $ty {
macro_rules! check_reg { ($func:ident, $ty:ty, $reg:tt, $mov:literal) => {
#[no_mangle]
pub unsafe fn $func(x: $ty) -> $ty {
- dont_merge(stringify!($func));
-
let y;
asm!(concat!($mov, " ", $reg, ", ", $reg), lateout($reg) y, in($reg) x);
y
diff --git a/tests/assembly/asm/powerpc-types.rs b/tests/assembly/asm/powerpc-types.rs
index bc8af08..85321e5 100644
--- a/tests/assembly/asm/powerpc-types.rs
+++ b/tests/assembly/asm/powerpc-types.rs
@@ -4,6 +4,7 @@
//@[powerpc] needs-llvm-components: powerpc
//@[powerpc64] compile-flags: --target powerpc64-unknown-linux-gnu
//@[powerpc64] needs-llvm-components: powerpc
+//@ compile-flags: -Zmerge-functions=disabled
#![feature(no_core, lang_items, rustc_attrs, repr_simd, asm_experimental_arch)]
#![crate_type = "rlib"]
@@ -43,16 +44,9 @@ impl Copy for ptr {}
static extern_static: u8;
}
-// Hack to avoid function merging
-extern "Rust" {
- fn dont_merge(s: &str);
-}
-
macro_rules! check { ($func:ident, $ty:ty, $class:ident, $mov:literal) => {
#[no_mangle]
pub unsafe fn $func(x: $ty) -> $ty {
- dont_merge(stringify!($func));
-
let y;
asm!(concat!($mov," {}, {}"), out($class) y, in($class) x);
y
@@ -62,8 +56,6 @@ pub unsafe fn $func(x: $ty) -> $ty {
macro_rules! check_reg { ($func:ident, $ty:ty, $rego:tt, $regc:tt, $mov:literal) => {
#[no_mangle]
pub unsafe fn $func(x: $ty) -> $ty {
- dont_merge(stringify!($func));
-
let y;
asm!(concat!($mov, " ", $rego, ", ", $rego), lateout($regc) y, in($regc) x);
y
diff --git a/tests/assembly/asm/riscv-types.rs b/tests/assembly/asm/riscv-types.rs
index 51b3aaf..1f5d7d8 100644
--- a/tests/assembly/asm/riscv-types.rs
+++ b/tests/assembly/asm/riscv-types.rs
@@ -27,6 +27,7 @@
//@[riscv32-zfh] filecheck-flags: --check-prefix zfhmin
//@ compile-flags: -C target-feature=+d
+//@ compile-flags: -Zmerge-functions=disabled
#![feature(no_core, lang_items, rustc_attrs, f16)]
#![crate_type = "rlib"]
@@ -90,12 +91,6 @@ macro_rules! check {
($func:ident $ty:ident $class:ident $mov:literal) => {
#[no_mangle]
pub unsafe fn $func(x: $ty) -> $ty {
- // Hack to avoid function merging
- extern "Rust" {
- fn dont_merge(s: &str);
- }
- dont_merge(stringify!($func));
-
let y;
asm!(concat!($mov, " {}, {}"), out($class) y, in($class) x);
y
@@ -107,12 +102,6 @@ macro_rules! check_reg {
($func:ident $ty:ident $reg:tt $mov:literal) => {
#[no_mangle]
pub unsafe fn $func(x: $ty) -> $ty {
- // Hack to avoid function merging
- extern "Rust" {
- fn dont_merge(s: &str);
- }
- dont_merge(stringify!($func));
-
let y;
asm!(concat!($mov, " ", $reg, ", ", $reg), lateout($reg) y, in($reg) x);
y
diff --git a/tests/assembly/asm/s390x-types.rs b/tests/assembly/asm/s390x-types.rs
index 6619073..e68b18d 100644
--- a/tests/assembly/asm/s390x-types.rs
+++ b/tests/assembly/asm/s390x-types.rs
@@ -2,6 +2,7 @@
//@ assembly-output: emit-asm
//@[s390x] compile-flags: --target s390x-unknown-linux-gnu
//@[s390x] needs-llvm-components: systemz
+//@ compile-flags: -Zmerge-functions=disabled
#![feature(no_core, lang_items, rustc_attrs, repr_simd, asm_experimental_arch)]
#![crate_type = "rlib"]
@@ -42,16 +43,9 @@ impl Copy for ptr {}
static extern_static: u8;
}
-// Hack to avoid function merging
-extern "Rust" {
- fn dont_merge(s: &str);
-}
-
macro_rules! check { ($func:ident, $ty:ty, $class:ident, $mov:literal) => {
#[no_mangle]
pub unsafe fn $func(x: $ty) -> $ty {
- dont_merge(stringify!($func));
-
let y;
asm!(concat!($mov," {}, {}"), out($class) y, in($class) x);
y
@@ -61,8 +55,6 @@ pub unsafe fn $func(x: $ty) -> $ty {
macro_rules! check_reg { ($func:ident, $ty:ty, $reg:tt, $mov:literal) => {
#[no_mangle]
pub unsafe fn $func(x: $ty) -> $ty {
- dont_merge(stringify!($func));
-
let y;
asm!(concat!($mov, " %", $reg, ", %", $reg), lateout($reg) y, in($reg) x);
y
diff --git a/tests/assembly/asm/x86-modifiers.rs b/tests/assembly/asm/x86-modifiers.rs
index c5e393b..5a48af9 100644
--- a/tests/assembly/asm/x86-modifiers.rs
+++ b/tests/assembly/asm/x86-modifiers.rs
@@ -7,6 +7,7 @@
//@[i686] needs-llvm-components: x86
//@ compile-flags: -C llvm-args=--x86-asm-syntax=intel
//@ compile-flags: -C target-feature=+avx512bw
+//@ compile-flags: -Zmerge-functions=disabled
#![feature(no_core, lang_items, rustc_attrs)]
#![crate_type = "rlib"]
@@ -38,12 +39,6 @@ macro_rules! check {
// -O and extern "C" guarantee that the selected register is always ax/xmm0
#[no_mangle]
pub unsafe extern "C" fn $func() -> i32 {
- // Hack to avoid function merging
- extern "Rust" {
- fn dont_merge(s: &str);
- }
- dont_merge(stringify!($func));
-
let y;
asm!(concat!($mov, " {0:", $modifier, "}, {0:", $modifier, "}"), out($reg) y);
y
diff --git a/tests/assembly/asm/x86-types.rs b/tests/assembly/asm/x86-types.rs
index 8e22961..a40bc10 100644
--- a/tests/assembly/asm/x86-types.rs
+++ b/tests/assembly/asm/x86-types.rs
@@ -6,6 +6,7 @@
//@[i686] needs-llvm-components: x86
//@ compile-flags: -C llvm-args=--x86-asm-syntax=intel
//@ compile-flags: -C target-feature=+avx512bw
+//@ compile-flags: -Zmerge-functions=disabled
#![feature(no_core, lang_items, rustc_attrs, repr_simd, f16, f128)]
#![crate_type = "rlib"]
@@ -283,12 +284,6 @@ macro_rules! check {
($func:ident $ty:ident $class:ident $mov:literal) => {
#[no_mangle]
pub unsafe fn $func(x: $ty) -> $ty {
- // Hack to avoid function merging
- extern "Rust" {
- fn dont_merge(s: &str);
- }
- dont_merge(stringify!($func));
-
let y;
asm!(concat!($mov, " {}, {}"), lateout($class) y, in($class) x);
y
@@ -300,12 +295,6 @@ macro_rules! check_reg {
($func:ident $ty:ident $reg:tt $mov:literal) => {
#[no_mangle]
pub unsafe fn $func(x: $ty) -> $ty {
- // Hack to avoid function merging
- extern "Rust" {
- fn dont_merge(s: &str);
- }
- dont_merge(stringify!($func));
-
let y;
asm!(concat!($mov, " ", $reg, ", ", $reg), lateout($reg) y, in($reg) x);
y
diff --git a/tests/assembly/s390x-backchain-toggle.rs b/tests/assembly/s390x-backchain-toggle.rs
new file mode 100644
index 0000000..8b6d0cf
--- /dev/null
+++ b/tests/assembly/s390x-backchain-toggle.rs
@@ -0,0 +1,46 @@
+//@ revisions: enable-backchain disable-backchain
+//@ assembly-output: emit-asm
+//@ compile-flags: -O --crate-type=lib --target=s390x-unknown-linux-gnu
+//@ needs-llvm-components: systemz
+//@[enable-backchain] compile-flags: -Ctarget-feature=+backchain
+//@[disable-backchain] compile-flags: -Ctarget-feature=-backchain
+#![feature(no_core, lang_items)]
+#![no_std]
+#![no_core]
+
+#[lang = "sized"]
+trait Sized {}
+
+extern "C" {
+ fn extern_func();
+}
+
+// CHECK-LABEL: test_backchain
+#[no_mangle]
+extern "C" fn test_backchain() -> i32 {
+ // Here we try to match if backchain register is saved to the parameter area (stored in r15/sp)
+ // And also if a new parameter area (160 bytes) is allocated for the upcoming function call
+ // enable-backchain: lgr [[REG1:.*]], %r15
+ // enable-backchain-NEXT: aghi %r15, -160
+ // enable-backchain: stg [[REG1]], 0(%r15)
+ // disable-backchain: aghi %r15, -160
+ // disable-backchain-NOT: stg %r{{.*}}, 0(%r15)
+ unsafe {
+ extern_func();
+ }
+ // enable-backchain-NEXT: brasl %r{{.*}}, extern_func@PLT
+ // disable-backchain: brasl %r{{.*}}, extern_func@PLT
+
+ // Make sure that the expected return value is written into %r2 (return register):
+ // enable-backchain-NEXT: lghi %r2, 1
+ // disable-backchain: lghi %r2, 0
+ #[cfg(target_feature = "backchain")]
+ {
+ 1
+ }
+ #[cfg(not(target_feature = "backchain"))]
+ {
+ 0
+ }
+ // CHECK: br %r{{.*}}
+}
diff --git a/tests/assembly/targets/targets-elf.rs b/tests/assembly/targets/targets-elf.rs
index c8610e0..4e1c5e6 100644
--- a/tests/assembly/targets/targets-elf.rs
+++ b/tests/assembly/targets/targets-elf.rs
@@ -552,6 +552,9 @@
//@ revisions: x86_64_unknown_haiku
//@ [x86_64_unknown_haiku] compile-flags: --target x86_64-unknown-haiku
//@ [x86_64_unknown_haiku] needs-llvm-components: x86
+//@ revisions: x86_64_unknown_hurd_gnu
+//@ [x86_64_unknown_hurd_gnu] compile-flags: --target x86_64-unknown-hurd-gnu
+//@ [x86_64_unknown_hurd_gnu] needs-llvm-components: x86
//@ revisions: x86_64_unknown_hermit
//@ [x86_64_unknown_hermit] compile-flags: --target x86_64-unknown-hermit
//@ [x86_64_unknown_hermit] needs-llvm-components: x86
diff --git a/tests/codegen/intrinsics/likely.rs b/tests/codegen/intrinsics/likely.rs
index 098fd99..9dc31d2 100644
--- a/tests/codegen/intrinsics/likely.rs
+++ b/tests/codegen/intrinsics/likely.rs
@@ -1,4 +1,4 @@
-//@ compile-flags: -C no-prepopulate-passes
+//@ compile-flags: -C no-prepopulate-passes -Copt-level=1
#![crate_type = "lib"]
#![feature(core_intrinsics)]
diff --git a/tests/codegen/naked-asan.rs b/tests/codegen/naked-asan.rs
new file mode 100644
index 0000000..ac36018
--- /dev/null
+++ b/tests/codegen/naked-asan.rs
@@ -0,0 +1,23 @@
+// Make sure we do not request sanitizers for naked functions.
+
+//@ only-x86_64
+//@ needs-sanitizer-address
+//@ compile-flags: -Zsanitizer=address -Ctarget-feature=-crt-static
+
+#![crate_type = "lib"]
+#![no_std]
+#![feature(abi_x86_interrupt, naked_functions)]
+
+// CHECK: define x86_intrcc void @page_fault_handler(ptr {{.*}}%0, i64 {{.*}}%1){{.*}}#[[ATTRS:[0-9]+]] {
+// CHECK-NOT: memcpy
+#[naked]
+#[no_mangle]
+pub extern "x86-interrupt" fn page_fault_handler(_: u64, _: u64) {
+ unsafe {
+ core::arch::asm!("ud2", options(noreturn));
+ }
+}
+
+// CHECK: #[[ATTRS]] =
+// CHECK-NOT: sanitize_address
+// CHECK: !llvm.module.flags
diff --git a/tests/coverage/async.cov-map b/tests/coverage/async.cov-map
index 9e5a4bd..1ba165f 100644
--- a/tests/coverage/async.cov-map
+++ b/tests/coverage/async.cov-map
@@ -92,20 +92,18 @@
- Code(Counter(0)) at (prev + 25, 1) to (start + 0, 23)
Function name: async::g::{closure#0} (unused)
-Raw bytes (69): 0x[01, 01, 00, 0d, 00, 19, 17, 01, 0c, 00, 02, 09, 00, 0a, 00, 00, 0e, 00, 11, 00, 00, 12, 00, 17, 00, 00, 1b, 00, 1c, 00, 00, 20, 00, 22, 00, 01, 09, 00, 0a, 00, 00, 0e, 00, 11, 00, 00, 12, 00, 17, 00, 00, 1b, 00, 1c, 00, 00, 20, 00, 22, 00, 01, 0e, 00, 10, 00, 02, 01, 00, 02]
+Raw bytes (59): 0x[01, 01, 00, 0b, 00, 19, 17, 01, 0c, 00, 02, 09, 00, 0a, 00, 00, 0e, 00, 17, 00, 00, 1b, 00, 1c, 00, 00, 20, 00, 22, 00, 01, 09, 00, 0a, 00, 00, 0e, 00, 17, 00, 00, 1b, 00, 1c, 00, 00, 20, 00, 22, 00, 01, 0e, 00, 10, 00, 02, 01, 00, 02]
Number of files: 1
- file 0 => global file 1
Number of expressions: 0
-Number of file 0 mappings: 13
+Number of file 0 mappings: 11
- Code(Zero) at (prev + 25, 23) to (start + 1, 12)
- Code(Zero) at (prev + 2, 9) to (start + 0, 10)
-- Code(Zero) at (prev + 0, 14) to (start + 0, 17)
-- Code(Zero) at (prev + 0, 18) to (start + 0, 23)
+- Code(Zero) at (prev + 0, 14) to (start + 0, 23)
- Code(Zero) at (prev + 0, 27) to (start + 0, 28)
- Code(Zero) at (prev + 0, 32) to (start + 0, 34)
- Code(Zero) at (prev + 1, 9) to (start + 0, 10)
-- Code(Zero) at (prev + 0, 14) to (start + 0, 17)
-- Code(Zero) at (prev + 0, 18) to (start + 0, 23)
+- Code(Zero) at (prev + 0, 14) to (start + 0, 23)
- Code(Zero) at (prev + 0, 27) to (start + 0, 28)
- Code(Zero) at (prev + 0, 32) to (start + 0, 34)
- Code(Zero) at (prev + 1, 14) to (start + 0, 16)
@@ -120,15 +118,14 @@
- Code(Counter(0)) at (prev + 33, 1) to (start + 0, 22)
Function name: async::h::{closure#0} (unused)
-Raw bytes (44): 0x[01, 01, 00, 08, 00, 21, 16, 03, 0c, 00, 04, 09, 00, 0a, 00, 00, 0e, 00, 13, 00, 00, 14, 00, 19, 00, 00, 1a, 00, 1b, 00, 00, 20, 00, 22, 00, 01, 0e, 00, 10, 00, 02, 01, 00, 02]
+Raw bytes (39): 0x[01, 01, 00, 07, 00, 21, 16, 03, 0c, 00, 04, 09, 00, 0a, 00, 00, 0e, 00, 19, 00, 00, 1a, 00, 1b, 00, 00, 20, 00, 22, 00, 01, 0e, 00, 10, 00, 02, 01, 00, 02]
Number of files: 1
- file 0 => global file 1
Number of expressions: 0
-Number of file 0 mappings: 8
+Number of file 0 mappings: 7
- Code(Zero) at (prev + 33, 22) to (start + 3, 12)
- Code(Zero) at (prev + 4, 9) to (start + 0, 10)
-- Code(Zero) at (prev + 0, 14) to (start + 0, 19)
-- Code(Zero) at (prev + 0, 20) to (start + 0, 25)
+- Code(Zero) at (prev + 0, 14) to (start + 0, 25)
- Code(Zero) at (prev + 0, 26) to (start + 0, 27)
- Code(Zero) at (prev + 0, 32) to (start + 0, 34)
- Code(Zero) at (prev + 1, 14) to (start + 0, 16)
@@ -143,28 +140,25 @@
- Code(Counter(0)) at (prev + 42, 1) to (start + 0, 19)
Function name: async::i::{closure#0}
-Raw bytes (78): 0x[01, 01, 02, 07, 21, 19, 1d, 0e, 01, 2a, 13, 04, 0c, 0d, 05, 09, 00, 0a, 01, 00, 0e, 00, 12, 05, 00, 13, 00, 18, 09, 00, 1c, 00, 21, 0d, 00, 27, 00, 2a, 15, 00, 2b, 00, 30, 1d, 01, 09, 00, 0a, 11, 00, 0e, 00, 11, 25, 00, 12, 00, 17, 29, 00, 1b, 00, 20, 1d, 00, 24, 00, 26, 21, 01, 0e, 00, 10, 03, 02, 01, 00, 02]
+Raw bytes (63): 0x[01, 01, 02, 07, 19, 11, 15, 0b, 01, 2a, 13, 04, 0c, 09, 05, 09, 00, 0a, 01, 00, 0e, 00, 18, 05, 00, 1c, 00, 21, 09, 00, 27, 00, 30, 15, 01, 09, 00, 0a, 0d, 00, 0e, 00, 17, 1d, 00, 1b, 00, 20, 15, 00, 24, 00, 26, 19, 01, 0e, 00, 10, 03, 02, 01, 00, 02]
Number of files: 1
- file 0 => global file 1
Number of expressions: 2
-- expression 0 operands: lhs = Expression(1, Add), rhs = Counter(8)
-- expression 1 operands: lhs = Counter(6), rhs = Counter(7)
-Number of file 0 mappings: 14
+- expression 0 operands: lhs = Expression(1, Add), rhs = Counter(6)
+- expression 1 operands: lhs = Counter(4), rhs = Counter(5)
+Number of file 0 mappings: 11
- Code(Counter(0)) at (prev + 42, 19) to (start + 4, 12)
-- Code(Counter(3)) at (prev + 5, 9) to (start + 0, 10)
-- Code(Counter(0)) at (prev + 0, 14) to (start + 0, 18)
-- Code(Counter(1)) at (prev + 0, 19) to (start + 0, 24)
-- Code(Counter(2)) at (prev + 0, 28) to (start + 0, 33)
-- Code(Counter(3)) at (prev + 0, 39) to (start + 0, 42)
-- Code(Counter(5)) at (prev + 0, 43) to (start + 0, 48)
-- Code(Counter(7)) at (prev + 1, 9) to (start + 0, 10)
-- Code(Counter(4)) at (prev + 0, 14) to (start + 0, 17)
-- Code(Counter(9)) at (prev + 0, 18) to (start + 0, 23)
-- Code(Counter(10)) at (prev + 0, 27) to (start + 0, 32)
-- Code(Counter(7)) at (prev + 0, 36) to (start + 0, 38)
-- Code(Counter(8)) at (prev + 1, 14) to (start + 0, 16)
+- Code(Counter(2)) at (prev + 5, 9) to (start + 0, 10)
+- Code(Counter(0)) at (prev + 0, 14) to (start + 0, 24)
+- Code(Counter(1)) at (prev + 0, 28) to (start + 0, 33)
+- Code(Counter(2)) at (prev + 0, 39) to (start + 0, 48)
+- Code(Counter(5)) at (prev + 1, 9) to (start + 0, 10)
+- Code(Counter(3)) at (prev + 0, 14) to (start + 0, 23)
+- Code(Counter(7)) at (prev + 0, 27) to (start + 0, 32)
+- Code(Counter(5)) at (prev + 0, 36) to (start + 0, 38)
+- Code(Counter(6)) at (prev + 1, 14) to (start + 0, 16)
- Code(Expression(0, Add)) at (prev + 2, 1) to (start + 0, 2)
- = ((c6 + c7) + c8)
+ = ((c4 + c5) + c6)
Function name: async::j
Raw bytes (58): 0x[01, 01, 02, 07, 0d, 05, 09, 0a, 01, 35, 01, 00, 0d, 01, 0b, 0b, 00, 0c, 05, 01, 09, 00, 0a, 01, 00, 0e, 00, 1b, 05, 00, 1f, 00, 27, 09, 01, 09, 00, 0a, 11, 00, 0e, 00, 1a, 09, 00, 1e, 00, 20, 0d, 01, 0e, 00, 10, 03, 02, 01, 00, 02]
diff --git a/tests/coverage/async.coverage b/tests/coverage/async.coverage
index f547382..9956742 100644
--- a/tests/coverage/async.coverage
+++ b/tests/coverage/async.coverage
@@ -45,9 +45,9 @@
LL| 1| // executed asynchronously.
LL| 1| match x {
LL| 1| y if c(x).await == y + 1 => { d().await; }
- ^0 ^0 ^0 ^0
+ ^0 ^0
LL| 1| y if f().await == y + 1 => (),
- ^0 ^0 ^0
+ ^0 ^0
LL| 1| _ => (),
LL| | }
LL| 1|}
diff --git a/tests/coverage/await_ready.cov-map b/tests/coverage/await_ready.cov-map
new file mode 100644
index 0000000..0c9f2ae
--- /dev/null
+++ b/tests/coverage/await_ready.cov-map
@@ -0,0 +1,25 @@
+Function name: await_ready::await_ready
+Raw bytes (9): 0x[01, 01, 00, 01, 01, 0a, 01, 00, 1e]
+Number of files: 1
+- file 0 => global file 1
+Number of expressions: 0
+Number of file 0 mappings: 1
+- Code(Counter(0)) at (prev + 10, 1) to (start + 0, 30)
+
+Function name: await_ready::await_ready::{closure#0}
+Raw bytes (14): 0x[01, 01, 00, 02, 01, 0a, 1e, 03, 0f, 05, 04, 01, 00, 02]
+Number of files: 1
+- file 0 => global file 1
+Number of expressions: 0
+Number of file 0 mappings: 2
+- Code(Counter(0)) at (prev + 10, 30) to (start + 3, 15)
+- Code(Counter(1)) at (prev + 4, 1) to (start + 0, 2)
+
+Function name: await_ready::main
+Raw bytes (9): 0x[01, 01, 00, 01, 01, 10, 01, 03, 02]
+Number of files: 1
+- file 0 => global file 1
+Number of expressions: 0
+Number of file 0 mappings: 1
+- Code(Counter(0)) at (prev + 16, 1) to (start + 3, 2)
+
diff --git a/tests/coverage/await_ready.coverage b/tests/coverage/await_ready.coverage
new file mode 100644
index 0000000..0075f09
--- /dev/null
+++ b/tests/coverage/await_ready.coverage
@@ -0,0 +1,38 @@
+ LL| |#![feature(coverage_attribute)]
+ LL| |#![feature(custom_inner_attributes)] // for #![rustfmt::skip]
+ LL| |#![feature(noop_waker)]
+ LL| |#![rustfmt::skip]
+ LL| |//@ edition: 2021
+ LL| |
+ LL| |#[coverage(off)]
+ LL| |async fn ready() -> u8 { 1 }
+ LL| |
+ LL| 1|async fn await_ready() -> u8 {
+ LL| 1| // await should be covered even if the function never yields
+ LL| 1| ready()
+ LL| 1| .await
+ LL| 1|}
+ LL| |
+ LL| 1|fn main() {
+ LL| 1| let mut future = Box::pin(await_ready());
+ LL| 1| executor::block_on(future.as_mut());
+ LL| 1|}
+ LL| |
+ LL| |mod executor {
+ LL| | use core::future::Future;
+ LL| | use core::pin::pin;
+ LL| | use core::task::{Context, Poll, Waker};
+ LL| |
+ LL| | #[coverage(off)]
+ LL| | pub fn block_on<F: Future>(mut future: F) -> F::Output {
+ LL| | let mut future = pin!(future);
+ LL| | let mut context = Context::from_waker(Waker::noop());
+ LL| |
+ LL| | loop {
+ LL| | if let Poll::Ready(val) = future.as_mut().poll(&mut context) {
+ LL| | break val;
+ LL| | }
+ LL| | }
+ LL| | }
+ LL| |}
+
diff --git a/tests/coverage/await_ready.rs b/tests/coverage/await_ready.rs
new file mode 100644
index 0000000..9212a4b
--- /dev/null
+++ b/tests/coverage/await_ready.rs
@@ -0,0 +1,37 @@
+#![feature(coverage_attribute)]
+#![feature(custom_inner_attributes)] // for #![rustfmt::skip]
+#![feature(noop_waker)]
+#![rustfmt::skip]
+//@ edition: 2021
+
+#[coverage(off)]
+async fn ready() -> u8 { 1 }
+
+async fn await_ready() -> u8 {
+ // await should be covered even if the function never yields
+ ready()
+ .await
+}
+
+fn main() {
+ let mut future = Box::pin(await_ready());
+ executor::block_on(future.as_mut());
+}
+
+mod executor {
+ use core::future::Future;
+ use core::pin::pin;
+ use core::task::{Context, Poll, Waker};
+
+ #[coverage(off)]
+ pub fn block_on<F: Future>(mut future: F) -> F::Output {
+ let mut future = pin!(future);
+ let mut context = Context::from_waker(Waker::noop());
+
+ loop {
+ if let Poll::Ready(val) = future.as_mut().poll(&mut context) {
+ break val;
+ }
+ }
+ }
+}
diff --git a/tests/crashes/118987.rs b/tests/crashes/118987.rs
deleted file mode 100644
index 4382a7b..0000000
--- a/tests/crashes/118987.rs
+++ /dev/null
@@ -1,17 +0,0 @@
-//@ known-bug: #118987
-#![feature(specialization)] //~ WARN the feature `specialization` is incomplete
-
-trait Assoc {
- type Output;
-}
-
-default impl<T: Clone> Assoc for T {
- type Output = bool;
-}
-
-impl Assoc for u8 {}
-
-trait Foo {}
-
-impl Foo for <u8 as Assoc>::Output {}
-impl Foo for <u16 as Assoc>::Output {}
diff --git a/tests/crashes/123629.rs b/tests/crashes/123629.rs
new file mode 100644
index 0000000..6153232
--- /dev/null
+++ b/tests/crashes/123629.rs
@@ -0,0 +1,10 @@
+//@ known-bug: #123629
+#![feature(generic_assert)]
+
+fn foo()
+where
+ for<const N: usize = { assert!(u) }> ():,
+{
+}
+
+fn main() {}
diff --git a/tests/crashes/124164.rs b/tests/crashes/124164.rs
deleted file mode 100644
index 8c9b4bd..0000000
--- a/tests/crashes/124164.rs
+++ /dev/null
@@ -1,4 +0,0 @@
-//@ known-bug: #124164
-static S_COUNT: = std::sync::atomic::AtomicUsize::new(0);
-
-fn main() {}
diff --git a/tests/crashes/126896.rs b/tests/crashes/126896.rs
deleted file mode 100644
index 49c539d..0000000
--- a/tests/crashes/126896.rs
+++ /dev/null
@@ -1,17 +0,0 @@
-//@ known-bug: rust-lang/rust#126896
-//@ compile-flags: -Zvalidate-mir -Zinline-mir=yes
-
-#![feature(type_alias_impl_trait)]
-type Two<'a, 'b> = impl std::fmt::Debug;
-
-fn set(x: &mut isize) -> isize {
- *x
-}
-
-fn d(x: Two) {
- let c1 = || set(x);
- c1;
-}
-
-fn main() {
-}
diff --git a/tests/crashes/127033.rs b/tests/crashes/127033.rs
new file mode 100644
index 0000000..919c9df
--- /dev/null
+++ b/tests/crashes/127033.rs
@@ -0,0 +1,18 @@
+//@ known-bug: #127033
+//@ compile-flags: --edition=2021
+
+pub trait RaftLogStorage {
+ fn save_vote(vote: ()) -> impl std::future::Future + Send;
+}
+
+struct X;
+impl RaftLogStorage for X {
+ fn save_vote(vote: ()) -> impl std::future::Future {
+ loop {}
+ async {
+ vote
+ }
+ }
+}
+
+fn main() {}
diff --git a/tests/crashes/129166.rs b/tests/crashes/129166.rs
deleted file mode 100644
index d3635d4..0000000
--- a/tests/crashes/129166.rs
+++ /dev/null
@@ -1,7 +0,0 @@
-//@ known-bug: rust-lang/rust#129166
-
-fn main() {
- #[cfg_eval]
- #[cfg]
- 0
-}
diff --git a/tests/crashes/129372.rs b/tests/crashes/129372.rs
new file mode 100644
index 0000000..43be01b
--- /dev/null
+++ b/tests/crashes/129372.rs
@@ -0,0 +1,52 @@
+//@ known-bug: #129372
+//@ compile-flags: -Cdebuginfo=2 -Copt-level=0
+
+pub struct Wrapper<T>(T);
+struct Struct;
+
+pub trait TraitA {
+ type AssocA<'t>;
+}
+pub trait TraitB {
+ type AssocB;
+}
+
+pub fn helper(v: impl MethodTrait) {
+ let _local_that_causes_ice = v.method();
+}
+
+pub fn main() {
+ helper(Wrapper(Struct));
+}
+
+pub trait MethodTrait {
+ type Assoc<'a>;
+
+ fn method(self) -> impl for<'a> FnMut(&'a ()) -> Self::Assoc<'a>;
+}
+
+impl<T: TraitB> MethodTrait for T
+where
+ <T as TraitB>::AssocB: TraitA,
+{
+ type Assoc<'a> = <T::AssocB as TraitA>::AssocA<'a>;
+
+ fn method(self) -> impl for<'a> FnMut(&'a ()) -> Self::Assoc<'a> {
+ move |_| loop {}
+ }
+}
+
+impl<T, B> TraitB for Wrapper<B>
+where
+ B: TraitB<AssocB = T>,
+{
+ type AssocB = T;
+}
+
+impl TraitB for Struct {
+ type AssocB = Struct;
+}
+
+impl TraitA for Struct {
+ type AssocA<'t> = Self;
+}
diff --git a/tests/crashes/74299.rs b/tests/crashes/74299.rs
deleted file mode 100644
index 0e2ddce..0000000
--- a/tests/crashes/74299.rs
+++ /dev/null
@@ -1,24 +0,0 @@
-//@ known-bug: #74299
-#![feature(specialization)]
-
-trait X {
- type U;
- fn f(&self) -> Self::U {
- loop {}
- }
-}
-
-impl<T> X for T {
- default type U = ();
-}
-
-trait Y {
- fn g(&self) {}
-}
-
-impl Y for <() as X>::U {}
-impl Y for <i32 as X>::U {}
-
-fn main() {
- ().f().g();
-}
diff --git a/tests/debuginfo/by-value-non-immediate-argument.rs b/tests/debuginfo/by-value-non-immediate-argument.rs
index f0a39a4..192f6ef 100644
--- a/tests/debuginfo/by-value-non-immediate-argument.rs
+++ b/tests/debuginfo/by-value-non-immediate-argument.rs
@@ -1,6 +1,7 @@
//@ min-lldb-version: 1800
//@ min-gdb-version: 13.0
//@ compile-flags:-g
+//@ ignore-windows-gnu: #128973
// === GDB TESTS ===================================================================================
diff --git a/tests/debuginfo/method-on-enum.rs b/tests/debuginfo/method-on-enum.rs
index a570144..754b4a2 100644
--- a/tests/debuginfo/method-on-enum.rs
+++ b/tests/debuginfo/method-on-enum.rs
@@ -3,6 +3,8 @@
//@ compile-flags:-g
+//@ ignore-windows-gnu: #128973
+
// === GDB TESTS ===================================================================================
// gdb-command:run
diff --git "a/tests/mir-opt/async_closure_shims.main-\173closure\0430\175-\173closure\0430\175-\173closure\0430\175.coroutine_by_move.0.panic-abort.mir" "b/tests/mir-opt/async_closure_shims.main-\173closure\0430\175-\173closure\0430\175-\173closure\0430\175.built.after.mir"
similarity index 81%
rename from "tests/mir-opt/async_closure_shims.main-\173closure\0430\175-\173closure\0430\175-\173closure\0430\175.coroutine_by_move.0.panic-abort.mir"
rename to "tests/mir-opt/async_closure_shims.main-\173closure\0430\175-\173closure\0430\175-\173closure\0430\175.built.after.mir"
index 1f5bb55..7da33b8 100644
--- "a/tests/mir-opt/async_closure_shims.main-\173closure\0430\175-\173closure\0430\175-\173closure\0430\175.coroutine_by_move.0.panic-abort.mir"
+++ "b/tests/mir-opt/async_closure_shims.main-\173closure\0430\175-\173closure\0430\175-\173closure\0430\175.built.after.mir"
@@ -1,11 +1,11 @@
-// MIR for `main::{closure#0}::{closure#0}::{closure#0}` 0 coroutine_by_move
+// MIR for `main::{closure#0}::{closure#0}::{closure#0}` after built
-fn main::{closure#0}::{closure#0}::{closure#0}(_1: {async closure body@$DIR/async_closure_shims.rs:53:53: 56:10}, _2: ResumeTy) -> ()
+fn main::{closure#0}::{closure#0}::{closure#0}(_1: {async closure body@$DIR/async_closure_shims.rs:54:53: 57:10}, _2: ResumeTy) -> ()
yields ()
{
debug _task_context => _2;
debug a => (_1.0: i32);
- debug b => (_1.1: i32);
+ debug b => (*(_1.1: &i32));
let mut _0: ();
let _3: i32;
scope 1 {
@@ -28,7 +28,7 @@
_4 = &_3;
FakeRead(ForLet(None), _4);
StorageLive(_5);
- _5 = &(_1.1: i32);
+ _5 = &(*(_1.1: &i32));
FakeRead(ForLet(None), _5);
_0 = const ();
StorageDead(_5);
diff --git "a/tests/mir-opt/async_closure_shims.main-\173closure\0430\175-\173closure\0430\175-\173closure\0430\175.coroutine_by_move.0.panic-unwind.mir" "b/tests/mir-opt/async_closure_shims.main-\173closure\0430\175-\173closure\0430\175-\173closure\0430\175.coroutine_by_move.0.panic-unwind.mir"
deleted file mode 100644
index 1f5bb55..0000000
--- "a/tests/mir-opt/async_closure_shims.main-\173closure\0430\175-\173closure\0430\175-\173closure\0430\175.coroutine_by_move.0.panic-unwind.mir"
+++ /dev/null
@@ -1,47 +0,0 @@
-// MIR for `main::{closure#0}::{closure#0}::{closure#0}` 0 coroutine_by_move
-
-fn main::{closure#0}::{closure#0}::{closure#0}(_1: {async closure body@$DIR/async_closure_shims.rs:53:53: 56:10}, _2: ResumeTy) -> ()
-yields ()
- {
- debug _task_context => _2;
- debug a => (_1.0: i32);
- debug b => (_1.1: i32);
- let mut _0: ();
- let _3: i32;
- scope 1 {
- debug a => _3;
- let _4: &i32;
- scope 2 {
- debug a => _4;
- let _5: &i32;
- scope 3 {
- debug b => _5;
- }
- }
- }
-
- bb0: {
- StorageLive(_3);
- _3 = copy (_1.0: i32);
- FakeRead(ForLet(None), _3);
- StorageLive(_4);
- _4 = &_3;
- FakeRead(ForLet(None), _4);
- StorageLive(_5);
- _5 = &(_1.1: i32);
- FakeRead(ForLet(None), _5);
- _0 = const ();
- StorageDead(_5);
- StorageDead(_4);
- StorageDead(_3);
- drop(_1) -> [return: bb1, unwind: bb2];
- }
-
- bb1: {
- return;
- }
-
- bb2 (cleanup): {
- resume;
- }
-}
diff --git "a/tests/mir-opt/async_closure_shims.main-\173closure\0430\175-\173closure\0430\175-\173closure\0430\175.coroutine_by_move.0.panic-abort.mir" "b/tests/mir-opt/async_closure_shims.main-\173closure\0430\175-\173closure\0430\175-\173closure\0431\175.built.after.mir"
similarity index 80%
copy from "tests/mir-opt/async_closure_shims.main-\173closure\0430\175-\173closure\0430\175-\173closure\0430\175.coroutine_by_move.0.panic-abort.mir"
copy to "tests/mir-opt/async_closure_shims.main-\173closure\0430\175-\173closure\0430\175-\173closure\0431\175.built.after.mir"
index 1f5bb55..a21e82e 100644
--- "a/tests/mir-opt/async_closure_shims.main-\173closure\0430\175-\173closure\0430\175-\173closure\0430\175.coroutine_by_move.0.panic-abort.mir"
+++ "b/tests/mir-opt/async_closure_shims.main-\173closure\0430\175-\173closure\0430\175-\173closure\0431\175.built.after.mir"
@@ -1,6 +1,6 @@
-// MIR for `main::{closure#0}::{closure#0}::{closure#0}` 0 coroutine_by_move
+// MIR for `main::{closure#0}::{closure#0}::{closure#1}` after built
-fn main::{closure#0}::{closure#0}::{closure#0}(_1: {async closure body@$DIR/async_closure_shims.rs:53:53: 56:10}, _2: ResumeTy) -> ()
+fn main::{closure#0}::{closure#0}::{closure#1}(_1: {async closure body@$DIR/async_closure_shims.rs:54:53: 57:10}, _2: ResumeTy) -> ()
yields ()
{
debug _task_context => _2;
diff --git "a/tests/mir-opt/async_closure_shims.main-\173closure\0430\175-\173closure\0430\175.coroutine_closure_by_move.0.mir" "b/tests/mir-opt/async_closure_shims.main-\173closure\0430\175-\173closure\0430\175.coroutine_closure_by_move.0.mir"
new file mode 100644
index 0000000..c156636
--- /dev/null
+++ "b/tests/mir-opt/async_closure_shims.main-\173closure\0430\175-\173closure\0430\175.coroutine_closure_by_move.0.mir"
@@ -0,0 +1,10 @@
+// MIR for `main::{closure#0}::{closure#0}` 0 coroutine_closure_by_move
+
+fn main::{closure#0}::{closure#0}(_1: {async closure@$DIR/async_closure_shims.rs:54:33: 54:52}, _2: i32) -> {async closure body@$DIR/async_closure_shims.rs:54:53: 57:10} {
+ let mut _0: {async closure body@$DIR/async_closure_shims.rs:54:53: 57:10};
+
+ bb0: {
+ _0 = {coroutine@$DIR/async_closure_shims.rs:54:53: 57:10 (#0)} { a: move _2, b: move (_1.0: i32) };
+ return;
+ }
+}
diff --git "a/tests/mir-opt/async_closure_shims.main-\173closure\0430\175-\173closure\0430\175.coroutine_closure_by_move.0.panic-abort.mir" "b/tests/mir-opt/async_closure_shims.main-\173closure\0430\175-\173closure\0430\175.coroutine_closure_by_move.0.panic-abort.mir"
deleted file mode 100644
index a984845..0000000
--- "a/tests/mir-opt/async_closure_shims.main-\173closure\0430\175-\173closure\0430\175.coroutine_closure_by_move.0.panic-abort.mir"
+++ /dev/null
@@ -1,10 +0,0 @@
-// MIR for `main::{closure#0}::{closure#0}` 0 coroutine_closure_by_move
-
-fn main::{closure#0}::{closure#0}(_1: {async closure@$DIR/async_closure_shims.rs:53:33: 53:52}, _2: i32) -> {async closure body@$DIR/async_closure_shims.rs:53:53: 56:10} {
- let mut _0: {async closure body@$DIR/async_closure_shims.rs:53:53: 56:10};
-
- bb0: {
- _0 = {coroutine@$DIR/async_closure_shims.rs:53:53: 56:10 (#0)} { a: move _2, b: move (_1.0: i32) };
- return;
- }
-}
diff --git "a/tests/mir-opt/async_closure_shims.main-\173closure\0430\175-\173closure\0430\175.coroutine_closure_by_move.0.panic-unwind.mir" "b/tests/mir-opt/async_closure_shims.main-\173closure\0430\175-\173closure\0430\175.coroutine_closure_by_move.0.panic-unwind.mir"
deleted file mode 100644
index a984845..0000000
--- "a/tests/mir-opt/async_closure_shims.main-\173closure\0430\175-\173closure\0430\175.coroutine_closure_by_move.0.panic-unwind.mir"
+++ /dev/null
@@ -1,10 +0,0 @@
-// MIR for `main::{closure#0}::{closure#0}` 0 coroutine_closure_by_move
-
-fn main::{closure#0}::{closure#0}(_1: {async closure@$DIR/async_closure_shims.rs:53:33: 53:52}, _2: i32) -> {async closure body@$DIR/async_closure_shims.rs:53:53: 56:10} {
- let mut _0: {async closure body@$DIR/async_closure_shims.rs:53:53: 56:10};
-
- bb0: {
- _0 = {coroutine@$DIR/async_closure_shims.rs:53:53: 56:10 (#0)} { a: move _2, b: move (_1.0: i32) };
- return;
- }
-}
diff --git "a/tests/mir-opt/async_closure_shims.main-\173closure\0430\175-\173closure\0431\175-\173closure\0430\175.coroutine_by_move.0.panic-abort.mir" "b/tests/mir-opt/async_closure_shims.main-\173closure\0430\175-\173closure\0431\175-\173closure\0430\175.built.after.mir"
similarity index 86%
rename from "tests/mir-opt/async_closure_shims.main-\173closure\0430\175-\173closure\0431\175-\173closure\0430\175.coroutine_by_move.0.panic-abort.mir"
rename to "tests/mir-opt/async_closure_shims.main-\173closure\0430\175-\173closure\0431\175-\173closure\0430\175.built.after.mir"
index 17fa931..a4a6a53 100644
--- "a/tests/mir-opt/async_closure_shims.main-\173closure\0430\175-\173closure\0431\175-\173closure\0430\175.coroutine_by_move.0.panic-abort.mir"
+++ "b/tests/mir-opt/async_closure_shims.main-\173closure\0430\175-\173closure\0431\175-\173closure\0430\175.built.after.mir"
@@ -1,6 +1,6 @@
-// MIR for `main::{closure#0}::{closure#1}::{closure#0}` 0 coroutine_by_move
+// MIR for `main::{closure#0}::{closure#1}::{closure#0}` after built
-fn main::{closure#0}::{closure#1}::{closure#0}(_1: {async closure body@$DIR/async_closure_shims.rs:62:48: 65:10}, _2: ResumeTy) -> ()
+fn main::{closure#0}::{closure#1}::{closure#0}(_1: {async closure body@$DIR/async_closure_shims.rs:63:48: 66:10}, _2: ResumeTy) -> ()
yields ()
{
debug _task_context => _2;
diff --git "a/tests/mir-opt/async_closure_shims.main-\173closure\0430\175-\173closure\0431\175-\173closure\0430\175.coroutine_by_move.0.panic-unwind.mir" "b/tests/mir-opt/async_closure_shims.main-\173closure\0430\175-\173closure\0431\175-\173closure\0430\175.coroutine_by_move.0.panic-unwind.mir"
deleted file mode 100644
index 17fa931..0000000
--- "a/tests/mir-opt/async_closure_shims.main-\173closure\0430\175-\173closure\0431\175-\173closure\0430\175.coroutine_by_move.0.panic-unwind.mir"
+++ /dev/null
@@ -1,47 +0,0 @@
-// MIR for `main::{closure#0}::{closure#1}::{closure#0}` 0 coroutine_by_move
-
-fn main::{closure#0}::{closure#1}::{closure#0}(_1: {async closure body@$DIR/async_closure_shims.rs:62:48: 65:10}, _2: ResumeTy) -> ()
-yields ()
- {
- debug _task_context => _2;
- debug a => (_1.0: i32);
- debug b => (*(_1.1: &i32));
- let mut _0: ();
- let _3: i32;
- scope 1 {
- debug a => _3;
- let _4: &i32;
- scope 2 {
- debug a => _4;
- let _5: &i32;
- scope 3 {
- debug b => _5;
- }
- }
- }
-
- bb0: {
- StorageLive(_3);
- _3 = copy (_1.0: i32);
- FakeRead(ForLet(None), _3);
- StorageLive(_4);
- _4 = &_3;
- FakeRead(ForLet(None), _4);
- StorageLive(_5);
- _5 = &(*(_1.1: &i32));
- FakeRead(ForLet(None), _5);
- _0 = const ();
- StorageDead(_5);
- StorageDead(_4);
- StorageDead(_3);
- drop(_1) -> [return: bb1, unwind: bb2];
- }
-
- bb1: {
- return;
- }
-
- bb2 (cleanup): {
- resume;
- }
-}
diff --git "a/tests/mir-opt/async_closure_shims.main-\173closure\0430\175-\173closure\0431\175-\173closure\0430\175.coroutine_by_move.0.panic-abort.mir" "b/tests/mir-opt/async_closure_shims.main-\173closure\0430\175-\173closure\0431\175-\173closure\0431\175.built.after.mir"
similarity index 80%
copy from "tests/mir-opt/async_closure_shims.main-\173closure\0430\175-\173closure\0431\175-\173closure\0430\175.coroutine_by_move.0.panic-abort.mir"
copy to "tests/mir-opt/async_closure_shims.main-\173closure\0430\175-\173closure\0431\175-\173closure\0431\175.built.after.mir"
index 17fa931..69bba6f 100644
--- "a/tests/mir-opt/async_closure_shims.main-\173closure\0430\175-\173closure\0431\175-\173closure\0430\175.coroutine_by_move.0.panic-abort.mir"
+++ "b/tests/mir-opt/async_closure_shims.main-\173closure\0430\175-\173closure\0431\175-\173closure\0431\175.built.after.mir"
@@ -1,6 +1,6 @@
-// MIR for `main::{closure#0}::{closure#1}::{closure#0}` 0 coroutine_by_move
+// MIR for `main::{closure#0}::{closure#1}::{closure#1}` after built
-fn main::{closure#0}::{closure#1}::{closure#0}(_1: {async closure body@$DIR/async_closure_shims.rs:62:48: 65:10}, _2: ResumeTy) -> ()
+fn main::{closure#0}::{closure#1}::{closure#1}(_1: {async closure body@$DIR/async_closure_shims.rs:63:48: 66:10}, _2: ResumeTy) -> ()
yields ()
{
debug _task_context => _2;
diff --git "a/tests/mir-opt/async_closure_shims.main-\173closure\0430\175-\173closure\0431\175.coroutine_closure_by_move.0.panic-abort.mir" "b/tests/mir-opt/async_closure_shims.main-\173closure\0430\175-\173closure\0431\175.coroutine_closure_by_move.0.mir"
similarity index 60%
rename from "tests/mir-opt/async_closure_shims.main-\173closure\0430\175-\173closure\0431\175.coroutine_closure_by_move.0.panic-abort.mir"
rename to "tests/mir-opt/async_closure_shims.main-\173closure\0430\175-\173closure\0431\175.coroutine_closure_by_move.0.mir"
index aab9f7b..134fe14 100644
--- "a/tests/mir-opt/async_closure_shims.main-\173closure\0430\175-\173closure\0431\175.coroutine_closure_by_move.0.panic-abort.mir"
+++ "b/tests/mir-opt/async_closure_shims.main-\173closure\0430\175-\173closure\0431\175.coroutine_closure_by_move.0.mir"
@@ -1,10 +1,10 @@
// MIR for `main::{closure#0}::{closure#1}` 0 coroutine_closure_by_move
-fn main::{closure#0}::{closure#1}(_1: {async closure@$DIR/async_closure_shims.rs:62:33: 62:47}, _2: i32) -> {async closure body@$DIR/async_closure_shims.rs:62:48: 65:10} {
- let mut _0: {async closure body@$DIR/async_closure_shims.rs:62:48: 65:10};
+fn main::{closure#0}::{closure#1}(_1: {async closure@$DIR/async_closure_shims.rs:63:33: 63:47}, _2: i32) -> {async closure body@$DIR/async_closure_shims.rs:63:48: 66:10} {
+ let mut _0: {async closure body@$DIR/async_closure_shims.rs:63:48: 66:10};
bb0: {
- _0 = {coroutine@$DIR/async_closure_shims.rs:62:48: 65:10 (#0)} { a: move _2, b: move (_1.0: &i32) };
+ _0 = {coroutine@$DIR/async_closure_shims.rs:63:48: 66:10 (#0)} { a: move _2, b: move (_1.0: &i32) };
return;
}
}
diff --git "a/tests/mir-opt/async_closure_shims.main-\173closure\0430\175-\173closure\0431\175.coroutine_closure_by_move.0.panic-unwind.mir" "b/tests/mir-opt/async_closure_shims.main-\173closure\0430\175-\173closure\0431\175.coroutine_closure_by_move.0.panic-unwind.mir"
deleted file mode 100644
index aab9f7b..0000000
--- "a/tests/mir-opt/async_closure_shims.main-\173closure\0430\175-\173closure\0431\175.coroutine_closure_by_move.0.panic-unwind.mir"
+++ /dev/null
@@ -1,10 +0,0 @@
-// MIR for `main::{closure#0}::{closure#1}` 0 coroutine_closure_by_move
-
-fn main::{closure#0}::{closure#1}(_1: {async closure@$DIR/async_closure_shims.rs:62:33: 62:47}, _2: i32) -> {async closure body@$DIR/async_closure_shims.rs:62:48: 65:10} {
- let mut _0: {async closure body@$DIR/async_closure_shims.rs:62:48: 65:10};
-
- bb0: {
- _0 = {coroutine@$DIR/async_closure_shims.rs:62:48: 65:10 (#0)} { a: move _2, b: move (_1.0: &i32) };
- return;
- }
-}
diff --git "a/tests/mir-opt/async_closure_shims.main-\173closure\0430\175-\173closure\0431\175.coroutine_closure_by_ref.0.panic-abort.mir" "b/tests/mir-opt/async_closure_shims.main-\173closure\0430\175-\173closure\0431\175.coroutine_closure_by_ref.0.mir"
similarity index 60%
rename from "tests/mir-opt/async_closure_shims.main-\173closure\0430\175-\173closure\0431\175.coroutine_closure_by_ref.0.panic-abort.mir"
rename to "tests/mir-opt/async_closure_shims.main-\173closure\0430\175-\173closure\0431\175.coroutine_closure_by_ref.0.mir"
index 3fdc817..f267d93 100644
--- "a/tests/mir-opt/async_closure_shims.main-\173closure\0430\175-\173closure\0431\175.coroutine_closure_by_ref.0.panic-abort.mir"
+++ "b/tests/mir-opt/async_closure_shims.main-\173closure\0430\175-\173closure\0431\175.coroutine_closure_by_ref.0.mir"
@@ -1,10 +1,10 @@
// MIR for `main::{closure#0}::{closure#1}` 0 coroutine_closure_by_ref
-fn main::{closure#0}::{closure#1}(_1: &{async closure@$DIR/async_closure_shims.rs:62:33: 62:47}, _2: i32) -> {async closure body@$DIR/async_closure_shims.rs:62:48: 65:10} {
- let mut _0: {async closure body@$DIR/async_closure_shims.rs:62:48: 65:10};
+fn main::{closure#0}::{closure#1}(_1: &{async closure@$DIR/async_closure_shims.rs:63:33: 63:47}, _2: i32) -> {async closure body@$DIR/async_closure_shims.rs:63:48: 66:10} {
+ let mut _0: {async closure body@$DIR/async_closure_shims.rs:63:48: 66:10};
bb0: {
- _0 = {coroutine@$DIR/async_closure_shims.rs:62:48: 65:10 (#0)} { a: move _2, b: copy ((*_1).0: &i32) };
+ _0 = {coroutine@$DIR/async_closure_shims.rs:63:48: 66:10 (#0)} { a: move _2, b: copy ((*_1).0: &i32) };
return;
}
}
diff --git "a/tests/mir-opt/async_closure_shims.main-\173closure\0430\175-\173closure\0431\175.coroutine_closure_by_ref.0.panic-unwind.mir" "b/tests/mir-opt/async_closure_shims.main-\173closure\0430\175-\173closure\0431\175.coroutine_closure_by_ref.0.panic-unwind.mir"
deleted file mode 100644
index 3fdc817..0000000
--- "a/tests/mir-opt/async_closure_shims.main-\173closure\0430\175-\173closure\0431\175.coroutine_closure_by_ref.0.panic-unwind.mir"
+++ /dev/null
@@ -1,10 +0,0 @@
-// MIR for `main::{closure#0}::{closure#1}` 0 coroutine_closure_by_ref
-
-fn main::{closure#0}::{closure#1}(_1: &{async closure@$DIR/async_closure_shims.rs:62:33: 62:47}, _2: i32) -> {async closure body@$DIR/async_closure_shims.rs:62:48: 65:10} {
- let mut _0: {async closure body@$DIR/async_closure_shims.rs:62:48: 65:10};
-
- bb0: {
- _0 = {coroutine@$DIR/async_closure_shims.rs:62:48: 65:10 (#0)} { a: move _2, b: copy ((*_1).0: &i32) };
- return;
- }
-}
diff --git a/tests/mir-opt/async_closure_shims.rs b/tests/mir-opt/async_closure_shims.rs
index 57c55ef..b2168ba 100644
--- a/tests/mir-opt/async_closure_shims.rs
+++ b/tests/mir-opt/async_closure_shims.rs
@@ -1,6 +1,5 @@
//@ edition:2021
// skip-filecheck
-// EMIT_MIR_FOR_EACH_PANIC_STRATEGY
#![feature(async_closure, noop_waker, async_fn_traits)]
#![allow(unused)]
@@ -22,7 +21,7 @@ pub fn block_on<T>(fut: impl Future<Output = T>) -> T {
}
}
-async fn call(f: &mut impl AsyncFn(i32)) {
+async fn call(f: &impl AsyncFn(i32)) {
f(0).await;
}
@@ -43,10 +42,12 @@ async fn call_normal_mut<F: Future<Output = ()>>(f: &mut impl FnMut(i32) -> F) {
}
// EMIT_MIR async_closure_shims.main-{closure#0}-{closure#0}.coroutine_closure_by_move.0.mir
-// EMIT_MIR async_closure_shims.main-{closure#0}-{closure#0}-{closure#0}.coroutine_by_move.0.mir
+// EMIT_MIR async_closure_shims.main-{closure#0}-{closure#0}-{closure#0}.built.after.mir
+// EMIT_MIR async_closure_shims.main-{closure#0}-{closure#0}-{closure#1}.built.after.mir
// EMIT_MIR async_closure_shims.main-{closure#0}-{closure#1}.coroutine_closure_by_ref.0.mir
// EMIT_MIR async_closure_shims.main-{closure#0}-{closure#1}.coroutine_closure_by_move.0.mir
-// EMIT_MIR async_closure_shims.main-{closure#0}-{closure#1}-{closure#0}.coroutine_by_move.0.mir
+// EMIT_MIR async_closure_shims.main-{closure#0}-{closure#1}-{closure#0}.built.after.mir
+// EMIT_MIR async_closure_shims.main-{closure#0}-{closure#1}-{closure#1}.built.after.mir
pub fn main() {
block_on(async {
let b = 2i32;
@@ -54,7 +55,7 @@ pub fn main() {
let a = &a;
let b = &b;
};
- call(&mut async_closure).await;
+ call(&async_closure).await;
call_mut(&mut async_closure).await;
call_once(async_closure).await;
diff --git a/tests/run-make/apple-deployment-target/foo.rs b/tests/run-make/apple-deployment-target/foo.rs
new file mode 100644
index 0000000..f328e4d
--- /dev/null
+++ b/tests/run-make/apple-deployment-target/foo.rs
@@ -0,0 +1 @@
+fn main() {}
diff --git a/tests/run-make/apple-deployment-target/rmake.rs b/tests/run-make/apple-deployment-target/rmake.rs
new file mode 100644
index 0000000..b2d1af6
--- /dev/null
+++ b/tests/run-make/apple-deployment-target/rmake.rs
@@ -0,0 +1,157 @@
+//! Test codegen when setting deployment targets on Apple platforms.
+//!
+//! This is important since its a compatibility hazard. The linker will
+//! generate load commands differently based on what minimum OS it can assume.
+//!
+//! See https://github.com/rust-lang/rust/pull/105123.
+
+//@ only-apple
+
+use run_make_support::{apple_os, cmd, run_in_tmpdir, rustc, target};
+
+/// Run vtool to check the `minos` field in LC_BUILD_VERSION.
+///
+/// On lower deployment targets, LC_VERSION_MIN_MACOSX, LC_VERSION_MIN_IPHONEOS and similar
+/// are used instead of LC_BUILD_VERSION - these have a `version` field, so also check that.
+#[track_caller]
+fn minos(file: &str, version: &str) {
+ cmd("vtool")
+ .arg("-show-build")
+ .arg(file)
+ .run()
+ .assert_stdout_contains_regex(format!("(minos|version) {version}"));
+}
+
+fn main() {
+ // These versions should generally be higher than the default versions
+ let (env_var, example_version, higher_example_version) = match apple_os() {
+ "macos" => ("MACOSX_DEPLOYMENT_TARGET", "12.0", "13.0"),
+ // armv7s-apple-ios and i386-apple-ios only supports iOS 10.0
+ "ios" if target() == "armv7s-apple-ios" || target() == "i386-apple-ios" => {
+ ("IPHONEOS_DEPLOYMENT_TARGET", "10.0", "10.0")
+ }
+ "ios" => ("IPHONEOS_DEPLOYMENT_TARGET", "15.0", "16.0"),
+ "watchos" => ("WATCHOS_DEPLOYMENT_TARGET", "7.0", "9.0"),
+ "tvos" => ("TVOS_DEPLOYMENT_TARGET", "14.0", "15.0"),
+ "visionos" => ("XROS_DEPLOYMENT_TARGET", "1.1", "1.2"),
+ _ => unreachable!(),
+ };
+ let default_version =
+ rustc().target(target()).env_remove(env_var).print("deployment-target").run().stdout_utf8();
+ let default_version = default_version.strip_prefix("deployment_target=").unwrap().trim();
+
+ // Test that version makes it to the object file.
+ run_in_tmpdir(|| {
+ let rustc = || {
+ let mut rustc = rustc();
+ rustc.target(target());
+ rustc.crate_type("lib");
+ rustc.emit("obj");
+ rustc.input("foo.rs");
+ rustc.output("foo.o");
+ rustc
+ };
+
+ rustc().env(env_var, example_version).run();
+ minos("foo.o", example_version);
+
+ // FIXME(madsmtm): Doesn't work on Mac Catalyst and the simulator.
+ if !target().contains("macabi") && !target().contains("sim") {
+ rustc().env_remove(env_var).run();
+ minos("foo.o", default_version);
+ }
+ });
+
+ // Test that version makes it to the linker when linking dylibs.
+ run_in_tmpdir(|| {
+ // Certain watchOS targets don't support dynamic linking, so we disable the test on those.
+ if apple_os() == "watchos" {
+ return;
+ }
+
+ let rustc = || {
+ let mut rustc = rustc();
+ rustc.target(target());
+ rustc.crate_type("dylib");
+ rustc.input("foo.rs");
+ rustc.output("libfoo.dylib");
+ rustc
+ };
+
+ rustc().env(env_var, example_version).run();
+ minos("libfoo.dylib", example_version);
+
+ // FIXME(madsmtm): Deployment target is not currently passed properly to linker
+ // rustc().env_remove(env_var).run();
+ // minos("libfoo.dylib", default_version);
+
+ // Test with ld64 instead
+
+ rustc().arg("-Clinker-flavor=ld").env(env_var, example_version).run();
+ minos("libfoo.dylib", example_version);
+
+ rustc().arg("-Clinker-flavor=ld").env_remove(env_var).run();
+ minos("libfoo.dylib", default_version);
+ });
+
+ // Test that version makes it to the linker when linking executables.
+ run_in_tmpdir(|| {
+ let rustc = || {
+ let mut rustc = rustc();
+ rustc.target(target());
+ rustc.crate_type("bin");
+ rustc.input("foo.rs");
+ rustc.output("foo");
+ rustc
+ };
+
+ // FIXME(madsmtm): Doesn't work on watchOS for some reason?
+ if !target().contains("watchos") {
+ rustc().env(env_var, example_version).run();
+ minos("foo", example_version);
+
+ // FIXME(madsmtm): Deployment target is not currently passed properly to linker
+ // rustc().env_remove(env_var).run();
+ // minos("foo", default_version);
+ }
+
+ // Test with ld64 instead
+
+ rustc().arg("-Clinker-flavor=ld").env(env_var, example_version).run();
+ minos("foo", example_version);
+
+ rustc().arg("-Clinker-flavor=ld").env_remove(env_var).run();
+ minos("foo", default_version);
+ });
+
+ // Test that changing the deployment target busts the incremental cache.
+ run_in_tmpdir(|| {
+ let rustc = || {
+ let mut rustc = rustc();
+ rustc.target(target());
+ rustc.incremental("incremental");
+ rustc.crate_type("lib");
+ rustc.emit("obj");
+ rustc.input("foo.rs");
+ rustc.output("foo.o");
+ rustc
+ };
+
+ // FIXME(madsmtm): Incremental cache is not yet busted
+ // https://github.com/rust-lang/rust/issues/118204
+ let higher_example_version = example_version;
+ let default_version = example_version;
+
+ rustc().env(env_var, example_version).run();
+ minos("foo.o", example_version);
+
+ rustc().env(env_var, higher_example_version).run();
+ minos("foo.o", higher_example_version);
+
+ // FIXME(madsmtm): Doesn't work on Mac Catalyst and the simulator.
+ if !target().contains("macabi") && !target().contains("sim") {
+ rustc().env_remove(env_var).run();
+ minos("foo.o", default_version);
+ }
+ });
+}
diff --git a/tests/run-make/clear-error-blank-output/rmake.rs b/tests/run-make/clear-error-blank-output/rmake.rs
index e0f042c..22e0306 100644
--- a/tests/run-make/clear-error-blank-output/rmake.rs
+++ b/tests/run-make/clear-error-blank-output/rmake.rs
@@ -8,6 +8,6 @@
use run_make_support::rustc;
fn main() {
- let output = rustc().output("").stdin(b"fn main() {}").run_fail();
+ let output = rustc().output("").stdin_buf(b"fn main() {}").run_fail();
output.assert_stderr_not_contains("panic");
}
diff --git a/tests/run-make/comment-section/rmake.rs b/tests/run-make/comment-section/rmake.rs
index 1557f50..ccfc38e 100644
--- a/tests/run-make/comment-section/rmake.rs
+++ b/tests/run-make/comment-section/rmake.rs
@@ -14,7 +14,7 @@ fn main() {
rustc()
.arg("-")
- .stdin("fn main() {}")
+ .stdin_buf("fn main() {}")
.emit("link,obj")
.arg("-Csave-temps")
.target(target)
diff --git a/tests/run-make/compile-stdin/rmake.rs b/tests/run-make/compile-stdin/rmake.rs
index f93080d..b824433 100644
--- a/tests/run-make/compile-stdin/rmake.rs
+++ b/tests/run-make/compile-stdin/rmake.rs
@@ -8,6 +8,6 @@
use run_make_support::{run, rustc};
fn main() {
- rustc().arg("-").stdin("fn main() {}").run();
+ rustc().arg("-").stdin_buf("fn main() {}").run();
run("rust_out");
}
diff --git a/tests/run-make/libtest-junit/rmake.rs b/tests/run-make/libtest-junit/rmake.rs
index d631313..5917660 100644
--- a/tests/run-make/libtest-junit/rmake.rs
+++ b/tests/run-make/libtest-junit/rmake.rs
@@ -21,7 +21,7 @@ fn run_tests(extra_args: &[&str], expected_file: &str) {
.run_fail();
let test_stdout = &cmd_out.stdout_utf8();
- python_command().arg("validate_junit.py").stdin(test_stdout).run();
+ python_command().arg("validate_junit.py").stdin_buf(test_stdout).run();
diff()
.expected_file(expected_file)
diff --git a/tests/run-make/llvm-ident/rmake.rs b/tests/run-make/llvm-ident/rmake.rs
index 9699d05..47e6fc4 100644
--- a/tests/run-make/llvm-ident/rmake.rs
+++ b/tests/run-make/llvm-ident/rmake.rs
@@ -17,7 +17,7 @@ fn main() {
.codegen_units(16)
.opt_level("2")
.target(&env_var("TARGET"))
- .stdin("fn main(){}")
+ .stdin_buf("fn main(){}")
.run();
// `llvm-dis` is used here since `--emit=llvm-ir` does not emit LLVM IR
diff --git a/tests/run-make/llvm-outputs/rmake.rs b/tests/run-make/llvm-outputs/rmake.rs
index b8ac21c..632e9a0 100644
--- a/tests/run-make/llvm-outputs/rmake.rs
+++ b/tests/run-make/llvm-outputs/rmake.rs
@@ -11,8 +11,8 @@ fn main() {
let p = cwd();
path_bc = p.join("nonexistant_dir_bc");
path_ir = p.join("nonexistant_dir_ir");
- rustc().input("-").stdin("fn main() {}").out_dir(&path_bc).emit("llvm-bc").run();
- rustc().input("-").stdin("fn main() {}").out_dir(&path_ir).emit("llvm-ir").run();
+ rustc().input("-").stdin_buf("fn main() {}").out_dir(&path_bc).emit("llvm-bc").run();
+ rustc().input("-").stdin_buf("fn main() {}").out_dir(&path_ir).emit("llvm-ir").run();
assert!(path_bc.exists());
assert!(path_ir.exists());
});
diff --git a/tests/run-make/macos-deployment-target/Makefile b/tests/run-make/macos-deployment-target/Makefile
deleted file mode 100644
index 757ca69..0000000
--- a/tests/run-make/macos-deployment-target/Makefile
+++ /dev/null
@@ -1,21 +0,0 @@
-# only-macos
-#
-# Check that a set deployment target actually makes it to the linker.
-# This is important since its a compatibility hazard. The linker will
-# generate load commands differently based on what minimum OS it can assume.
-
-include ../tools.mk
-
-ifeq ($(strip $(shell uname -m)),arm64)
- GREP_PATTERN = "minos 11.0"
-else
- GREP_PATTERN = "version 10.13"
-endif
-
-OUT_FILE=$(TMPDIR)/with_deployment_target.dylib
-all:
- env MACOSX_DEPLOYMENT_TARGET=10.13 $(RUSTC) with_deployment_target.rs -o $(OUT_FILE)
-# XXX: The check is for either the x86_64 minimum OR the aarch64 minimum (M1 starts at macOS 11).
-# They also use different load commands, so we let that change with each too. The aarch64 check
-# isn't as robust as the x86 one, but testing both seems unneeded.
- vtool -show-build $(OUT_FILE) | $(CGREP) -e $(GREP_PATTERN)
diff --git a/tests/run-make/macos-deployment-target/with_deployment_target.rs b/tests/run-make/macos-deployment-target/with_deployment_target.rs
deleted file mode 100644
index 342fe0e..0000000
--- a/tests/run-make/macos-deployment-target/with_deployment_target.rs
+++ /dev/null
@@ -1,4 +0,0 @@
-#![crate_type = "cdylib"]
-
-#[allow(dead_code)]
-fn something_and_nothing() {}
diff --git a/tests/run-make/no-builtins-attribute/rmake.rs b/tests/run-make/no-builtins-attribute/rmake.rs
index 1e15b0c..7182c65 100644
--- a/tests/run-make/no-builtins-attribute/rmake.rs
+++ b/tests/run-make/no-builtins-attribute/rmake.rs
@@ -9,5 +9,5 @@
fn main() {
rustc().input("no_builtins.rs").emit("link").run();
rustc().input("main.rs").emit("llvm-ir").run();
- llvm_filecheck().patterns("filecheck.main.txt").stdin(rfs::read("main.ll")).run();
+ llvm_filecheck().patterns("filecheck.main.txt").stdin_buf(rfs::read("main.ll")).run();
}
diff --git a/tests/run-make/pgo-branch-weights/rmake.rs b/tests/run-make/pgo-branch-weights/rmake.rs
index ef33d00..105c2fa 100644
--- a/tests/run-make/pgo-branch-weights/rmake.rs
+++ b/tests/run-make/pgo-branch-weights/rmake.rs
@@ -35,5 +35,8 @@ fn main() {
.codegen_units(1)
.emit("llvm-ir")
.run();
- llvm_filecheck().patterns("filecheck-patterns.txt").stdin(rfs::read("interesting.ll")).run();
+ llvm_filecheck()
+ .patterns("filecheck-patterns.txt")
+ .stdin_buf(rfs::read("interesting.ll"))
+ .run();
}
diff --git a/tests/run-make/pgo-indirect-call-promotion/rmake.rs b/tests/run-make/pgo-indirect-call-promotion/rmake.rs
index d0ccfd8..28232eb 100644
--- a/tests/run-make/pgo-indirect-call-promotion/rmake.rs
+++ b/tests/run-make/pgo-indirect-call-promotion/rmake.rs
@@ -29,5 +29,8 @@ fn main() {
.codegen_units(1)
.emit("llvm-ir")
.run();
- llvm_filecheck().patterns("filecheck-patterns.txt").stdin(rfs::read("interesting.ll")).run();
+ llvm_filecheck()
+ .patterns("filecheck-patterns.txt")
+ .stdin_buf(rfs::read("interesting.ll"))
+ .run();
}
diff --git a/tests/run-make/pgo-use/rmake.rs b/tests/run-make/pgo-use/rmake.rs
index cad4937..276af9e 100644
--- a/tests/run-make/pgo-use/rmake.rs
+++ b/tests/run-make/pgo-use/rmake.rs
@@ -51,5 +51,5 @@ fn main() {
let lines: Vec<_> = ir.lines().rev().collect();
let mut reversed_ir = lines.join("\n");
reversed_ir.push('\n');
- llvm_filecheck().patterns("filecheck-patterns.txt").stdin(reversed_ir.as_bytes()).run();
+ llvm_filecheck().patterns("filecheck-patterns.txt").stdin_buf(reversed_ir.as_bytes()).run();
}
diff --git a/tests/run-make/rustc-crates-on-stable/rmake.rs b/tests/run-make/rustc-crates-on-stable/rmake.rs
new file mode 100644
index 0000000..81cc775
--- /dev/null
+++ b/tests/run-make/rustc-crates-on-stable/rmake.rs
@@ -0,0 +1,36 @@
+//! Checks if selected rustc crates can be compiled on the stable channel (or a "simulation" of it).
+//! These crates are designed to be used by downstream users.
+
+use run_make_support::{cargo, rustc_path, source_root};
+
+fn main() {
+ // Use the stage0 beta cargo for the compilation (it shouldn't really matter which cargo we use)
+ cargo()
+ // Ensure `proc-macro2`'s nightly detection is disabled
+ .env("RUSTC_STAGE", "0")
+ .env("RUSTC", rustc_path())
+ // We want to disallow all nightly features to simulate a stable build
+ .env("RUSTFLAGS", "-Zallow-features=")
+ .arg("build")
+ .arg("--manifest-path")
+ .arg(source_root().join("Cargo.toml"))
+ .args(&[
+ // Avoid depending on transitive rustc crates
+ "--no-default-features",
+ // Emit artifacts in this temporary directory, not in the source_root's `target` folder
+ "--target-dir",
+ "target",
+ ])
+ // Check that these crates can be compiled on "stable"
+ .args(&[
+ "-p",
+ "rustc_type_ir",
+ "-p",
+ "rustc_next_trait_solver",
+ "-p",
+ "rustc_pattern_analysis",
+ "-p",
+ "rustc_lexer",
+ ])
+ .run();
+}
diff --git a/tests/run-make/rustdoc-default-output/output-default.stdout b/tests/run-make/rustdoc-default-output/output-default.stdout
index bc38d9e..125443c 100644
--- a/tests/run-make/rustdoc-default-output/output-default.stdout
+++ b/tests/run-make/rustdoc-default-output/output-default.stdout
@@ -172,6 +172,23 @@
--scrape-tests Include test code when scraping examples
--with-examples path to function call information (for displaying examples in the documentation)
+ --merge none|shared|finalize
+ Controls how rustdoc handles files from previously
+ documented crates in the doc root
+ none = Do not write cross-crate information to the
+ --out-dir
+ shared = Append current crate's info to files found in
+ the --out-dir
+ finalize = Write current crate's info and
+ --include-parts-dir info to the --out-dir, overwriting
+ conflicting files
+ --parts-out-dir path/to/doc.parts/<crate-name>
+ Writes trait implementations and other info for the
+ current crate to provided path. Only use with
+ --merge=none
+ --include-parts-dir path/to/doc.parts/<crate-name>
+ Includes trait implementations and other crate info
+ from provided path. Only use with --merge=finalize
--disable-minification
removed
--plugin-path DIR
diff --git a/tests/run-make/separate-link/rmake.rs b/tests/run-make/separate-link/rmake.rs
index e91b254..0ec7334 100644
--- a/tests/run-make/separate-link/rmake.rs
+++ b/tests/run-make/separate-link/rmake.rs
@@ -8,7 +8,7 @@
use run_make_support::{run, rustc};
fn main() {
- rustc().stdin(b"fn main(){}").arg("-Zno-link").arg("-").run();
+ rustc().stdin_buf(b"fn main(){}").arg("-Zno-link").arg("-").run();
rustc().arg("-Zlink-only").input("rust_out.rlink").run();
run("rust_out");
}
diff --git a/tests/run-make/static-pie/rmake.rs b/tests/run-make/static-pie/rmake.rs
index 74f86bb..1557c17 100644
--- a/tests/run-make/static-pie/rmake.rs
+++ b/tests/run-make/static-pie/rmake.rs
@@ -28,7 +28,7 @@ fn ok_compiler_version(compiler: &str) -> bool {
}
let compiler_output =
- cmd(compiler).stdin(trigger).arg("-").arg("-E").arg("-x").arg("c").run().stdout_utf8();
+ cmd(compiler).stdin_buf(trigger).arg("-").arg("-E").arg("-x").arg("c").run().stdout_utf8();
let re = Regex::new(r"(?m)^(\d+)").unwrap();
let version: u32 =
re.captures(&compiler_output).unwrap().get(1).unwrap().as_str().parse().unwrap();
diff --git a/tests/run-make/stdin-rustc/rmake.rs b/tests/run-make/stdin-rustc/rmake.rs
index 68e9cf2..2d634dd 100644
--- a/tests/run-make/stdin-rustc/rmake.rs
+++ b/tests/run-make/stdin-rustc/rmake.rs
@@ -14,7 +14,7 @@ fn main() {
fn main() {
// echo $HELLO_WORLD | rustc -
- rustc().arg("-").stdin(HELLO_WORLD).run();
+ rustc().arg("-").stdin_buf(HELLO_WORLD).run();
assert!(
PathBuf::from(if !is_windows() { "rust_out" } else { "rust_out.exe" })
.try_exists()
@@ -22,7 +22,7 @@ fn main() {
);
// echo $NOT_UTF8 | rustc -
- rustc().arg("-").stdin(NOT_UTF8).run_fail().assert_stderr_contains(
+ rustc().arg("-").stdin_buf(NOT_UTF8).run_fail().assert_stderr_contains(
"error: couldn't read from stdin, as it did not contain valid UTF-8",
);
}
diff --git a/tests/run-make/stdin-rustdoc/rmake.rs b/tests/run-make/stdin-rustdoc/rmake.rs
index de47a24..30f97b8 100644
--- a/tests/run-make/stdin-rustdoc/rmake.rs
+++ b/tests/run-make/stdin-rustdoc/rmake.rs
@@ -15,11 +15,11 @@ fn main() {
let out_dir = PathBuf::from("doc");
// rustdoc -
- rustdoc().arg("-").out_dir(&out_dir).stdin(INPUT).run();
+ rustdoc().arg("-").out_dir(&out_dir).stdin_buf(INPUT).run();
assert!(out_dir.join("rust_out/struct.F.html").try_exists().unwrap());
// rustdoc --test -
- rustdoc().arg("--test").arg("-").stdin(INPUT).run();
+ rustdoc().arg("--test").arg("-").stdin_buf(INPUT).run();
// rustdoc file.rs -
rustdoc().arg("file.rs").arg("-").run_fail();
diff --git a/tests/run-make/sysroot-crates-are-unstable/rmake.rs b/tests/run-make/sysroot-crates-are-unstable/rmake.rs
index 2240d87..c81c7fa 100644
--- a/tests/run-make/sysroot-crates-are-unstable/rmake.rs
+++ b/tests/run-make/sysroot-crates-are-unstable/rmake.rs
@@ -34,7 +34,7 @@ fn check_crate_is_unstable(cr: &Crate) {
.target(target())
.extern_(name, path)
.input("-")
- .stdin(format!("extern crate {name};"))
+ .stdin_buf(format!("extern crate {name};"))
.run_fail();
// Make sure it failed for the intended reason, not some other reason.
diff --git a/tests/run-make/unknown-mod-stdin/rmake.rs b/tests/run-make/unknown-mod-stdin/rmake.rs
index 0fe5c78..6be3119 100644
--- a/tests/run-make/unknown-mod-stdin/rmake.rs
+++ b/tests/run-make/unknown-mod-stdin/rmake.rs
@@ -12,7 +12,7 @@
use run_make_support::{diff, rustc};
fn main() {
- let out = rustc().crate_type("rlib").stdin(b"mod unknown;").arg("-").run_fail();
+ let out = rustc().crate_type("rlib").stdin_buf(b"mod unknown;").arg("-").run_fail();
diff()
.actual_text("actual-stdout", out.stdout_utf8())
.expected_file("unknown-mod.stdout")
diff --git a/tests/run-make/x86_64-fortanix-unknown-sgx-lvi/rmake.rs b/tests/run-make/x86_64-fortanix-unknown-sgx-lvi/rmake.rs
index 130781a..e58762a 100644
--- a/tests/run-make/x86_64-fortanix-unknown-sgx-lvi/rmake.rs
+++ b/tests/run-make/x86_64-fortanix-unknown-sgx-lvi/rmake.rs
@@ -78,19 +78,23 @@ fn check(func_re: &str, mut checks: &str) {
// This is because frame pointers are optional, and them being enabled requires
// an additional `popq` in the pattern checking file.
if func_re == "std::io::stdio::_print::[[:alnum:]]+" {
- let output = llvm_filecheck().stdin(&dump).patterns(checks).run_unchecked();
+ let output = llvm_filecheck().stdin_buf(&dump).patterns(checks).run_unchecked();
if !output.status().success() {
checks = "print.without_frame_pointers.checks";
- llvm_filecheck().stdin(&dump).patterns(checks).run();
+ llvm_filecheck().stdin_buf(&dump).patterns(checks).run();
}
} else {
- llvm_filecheck().stdin(&dump).patterns(checks).run();
+ llvm_filecheck().stdin_buf(&dump).patterns(checks).run();
}
if !["rust_plus_one_global_asm", "cmake_plus_one_c_global_asm", "cmake_plus_one_cxx_global_asm"]
.contains(&func_re)
{
// The assembler cannot avoid explicit `ret` instructions. Sequences
// of `shlq $0x0, (%rsp); lfence; retq` are used instead.
- llvm_filecheck().args(&["--implicit-check-not", "ret"]).stdin(dump).patterns(checks).run();
+ llvm_filecheck()
+ .args(&["--implicit-check-not", "ret"])
+ .stdin_buf(dump)
+ .patterns(checks)
+ .run();
}
}
diff --git a/tests/rustdoc-gui/code-example-buttons.goml b/tests/rustdoc-gui/code-example-buttons.goml
index 4f037ec..c62683b 100644
--- a/tests/rustdoc-gui/code-example-buttons.goml
+++ b/tests/rustdoc-gui/code-example-buttons.goml
@@ -94,3 +94,24 @@
"filter": "invert(0.5)",
"filter_hover": "invert(0.35)",
})
+
+define-function: (
+ "check-buttons-position",
+ [pre_selector],
+ block {
+ move-cursor-to: |pre_selector| + " .rust:not(.item-decl)"
+ store-position: (|pre_selector| + " .rust:not(.item-decl)", {"x": x, "y": y})
+ assert-position: (|pre_selector| + " .rust:not(.item-decl) + .button-holder", {
+ "y": |y| + 4,
+ })
+ }
+)
+
+call-function: ("check-buttons-position", {"pre_selector": ".example-wrap"})
+
+go-to: "file://" + |DOC_PATH| + "/scrape_examples/fn.test_many.html"
+// We should work as well for scraped examples.
+call-function: ("check-buttons-position", {"pre_selector": ".scraped-example .example-wrap"})
+// And also when the scraped example "title" goes above.
+set-window-size: (600, 600)
+call-function: ("check-buttons-position", {"pre_selector": ".scraped-example .example-wrap"})
diff --git a/tests/rustdoc-gui/docblock-code-block-line-number.goml b/tests/rustdoc-gui/docblock-code-block-line-number.goml
index 348ce0c..03f8f80 100644
--- a/tests/rustdoc-gui/docblock-code-block-line-number.goml
+++ b/tests/rustdoc-gui/docblock-code-block-line-number.goml
@@ -5,6 +5,18 @@
// We check that without this setting, there is no line number displayed.
assert-false: "pre.example-line-numbers"
+// All corners should be rounded.
+assert-css: (
+ ".example-wrap .rust",
+ {
+ "border-top-left-radius": "6px",
+ "border-bottom-left-radius": "6px",
+ "border-top-right-radius": "6px",
+ "border-bottom-right-radius": "6px",
+ },
+ ALL,
+)
+
// We set the setting to show the line numbers on code examples.
set-local-storage: {"rustdoc-line-numbers": "true"}
reload:
@@ -29,9 +41,21 @@
"margin": "0px",
"padding": "14px 8px",
"text-align": "right",
+ // There should not be a radius on the right of the line numbers.
+ "border-top-left-radius": "6px",
+ "border-bottom-left-radius": "6px",
+ "border-top-right-radius": "0px",
+ "border-bottom-right-radius": "0px",
},
ALL,
)
+ // There should not be a radius on the left of the line numbers.
+ assert-css: ("pre.example-line-numbers + .rust", {
+ "border-top-left-radius": "0px",
+ "border-bottom-left-radius": "0px",
+ "border-top-right-radius": "6px",
+ "border-bottom-right-radius": "6px",
+ })
},
)
call-function: ("check-colors", {
@@ -64,7 +88,56 @@
assert-false: "pre.example-line-numbers"
assert-local-storage: {"rustdoc-line-numbers": "false" }
+// Check that the rounded corners are back.
+assert-css: (
+ ".example-wrap .rust",
+ {
+ "border-top-left-radius": "6px",
+ "border-bottom-left-radius": "6px",
+ "border-top-right-radius": "6px",
+ "border-bottom-right-radius": "6px",
+ },
+ ALL,
+)
+
// Finally, turn it on again.
click: "input#line-numbers"
wait-for: "pre.example-line-numbers"
assert-local-storage: {"rustdoc-line-numbers": "true" }
+
+// Same check with scraped examples line numbers.
+go-to: "file://" + |DOC_PATH| + "/scrape_examples/fn.test_many.html"
+
+assert-css: (
+ ".scraped-example .src-line-numbers > pre",
+ {
+ // There should not be a radius on the right of the line numbers.
+ "border-top-left-radius": "6px",
+ "border-bottom-left-radius": "6px",
+ "border-top-right-radius": "0px",
+ "border-bottom-right-radius": "0px",
+ },
+ ALL,
+)
+assert-css: (
+ ".scraped-example .src-line-numbers",
+ {
+ // There should not be a radius on the right of the line numbers.
+ "border-top-left-radius": "6px",
+ "border-bottom-left-radius": "6px",
+ "border-top-right-radius": "0px",
+ "border-bottom-right-radius": "0px",
+ },
+ ALL,
+)
+assert-css: (
+ ".scraped-example .rust",
+ {
+ // There should not be a radius on the left of the code.
+ "border-top-left-radius": "0px",
+ "border-bottom-left-radius": "0px",
+ "border-top-right-radius": "6px",
+ "border-bottom-right-radius": "6px",
+ },
+ ALL,
+)
diff --git a/tests/rustdoc-gui/scrape-examples-button-focus.goml b/tests/rustdoc-gui/scrape-examples-button-focus.goml
index af4293d..83ed6a2 100644
--- a/tests/rustdoc-gui/scrape-examples-button-focus.goml
+++ b/tests/rustdoc-gui/scrape-examples-button-focus.goml
@@ -3,29 +3,53 @@
go-to: "file://" + |DOC_PATH| + "/scrape_examples/fn.test.html"
// The next/prev buttons vertically scroll the code viewport between examples
-store-property: (".scraped-example-list > .scraped-example pre", {"scrollTop": initialScrollTop})
+move-cursor-to: ".scraped-example-list > .scraped-example"
+store-property: (".scraped-example-list > .scraped-example .src-line-numbers", {
+ "scrollTop": initialScrollTop,
+})
+assert-property: (".scraped-example-list > .scraped-example .rust", {
+ "scrollTop": |initialScrollTop|,
+})
focus: ".scraped-example-list > .scraped-example .next"
press-key: "Enter"
-assert-property-false: (".scraped-example-list > .scraped-example pre", {
+assert-property-false: (".scraped-example-list > .scraped-example .src-line-numbers", {
+ "scrollTop": |initialScrollTop|
+}, NEAR)
+assert-property-false: (".scraped-example-list > .scraped-example .rust", {
"scrollTop": |initialScrollTop|
}, NEAR)
focus: ".scraped-example-list > .scraped-example .prev"
press-key: "Enter"
-assert-property: (".scraped-example-list > .scraped-example pre", {
+assert-property: (".scraped-example-list > .scraped-example .src-line-numbers", {
+ "scrollTop": |initialScrollTop|
+}, NEAR)
+assert-property: (".scraped-example-list > .scraped-example .rust", {
"scrollTop": |initialScrollTop|
}, NEAR)
// The expand button increases the scrollHeight of the minimized code viewport
store-property: (".scraped-example-list > .scraped-example pre", {"offsetHeight": smallOffsetHeight})
-assert-property-false: (".scraped-example-list > .scraped-example pre", {
+assert-property: (".scraped-example-list > .scraped-example .src-line-numbers", {
+ "scrollHeight": |smallOffsetHeight|
+}, NEAR)
+assert-property: (".scraped-example-list > .scraped-example .rust", {
"scrollHeight": |smallOffsetHeight|
}, NEAR)
focus: ".scraped-example-list > .scraped-example .expand"
press-key: "Enter"
-assert-property-false: (".scraped-example-list > .scraped-example pre", {
+assert-property-false: (".scraped-example-list > .scraped-example .src-line-numbers", {
"offsetHeight": |smallOffsetHeight|
}, NEAR)
-store-property: (".scraped-example-list > .scraped-example pre", {"offsetHeight": fullOffsetHeight})
-assert-property: (".scraped-example-list > .scraped-example pre", {
+assert-property-false: (".scraped-example-list > .scraped-example .rust", {
+ "offsetHeight": |smallOffsetHeight|
+}, NEAR)
+store-property: (".scraped-example-list > .scraped-example .src-line-numbers", {
+ "offsetHeight": fullOffsetHeight,
+})
+assert-property: (".scraped-example-list > .scraped-example .rust", {
+ "offsetHeight": |fullOffsetHeight|,
+ "scrollHeight": |fullOffsetHeight|,
+})
+assert-property: (".scraped-example-list > .scraped-example .src-line-numbers", {
"scrollHeight": |fullOffsetHeight|
}, NEAR)
diff --git a/tests/rustdoc-gui/scrape-examples-color.goml b/tests/rustdoc-gui/scrape-examples-color.goml
index 588ba08..b0faca1 100644
--- a/tests/rustdoc-gui/scrape-examples-color.goml
+++ b/tests/rustdoc-gui/scrape-examples-color.goml
@@ -10,10 +10,10 @@
block {
call-function: ("switch-theme", {"theme": |theme|})
wait-for: ".more-examples-toggle"
- assert-css: (".scraped-example .example-wrap .rust span.highlight:not(.focus)", {
+ assert-css: (".scraped-example .rust span.highlight:not(.focus)", {
"background-color": |highlight|,
}, ALL)
- assert-css: (".scraped-example .example-wrap .rust span.highlight.focus", {
+ assert-css: (".scraped-example .rust span.highlight.focus", {
"background-color": |highlight_focus|,
}, ALL)
@@ -67,11 +67,11 @@
[theme, background_color_start, background_color_end],
block {
call-function: ("switch-theme", {"theme": |theme|})
- assert-css: (".scraped-example:not(.expanded) .code-wrapper::before", {
+ assert-css: (".scraped-example:not(.expanded) .example-wrap::before", {
"background-image": "linear-gradient(" + |background_color_start| + ", " +
|background_color_end| + ")",
})
- assert-css: (".scraped-example:not(.expanded) .code-wrapper::after", {
+ assert-css: (".scraped-example:not(.expanded) .example-wrap::after", {
"background-image": "linear-gradient(to top, " + |background_color_start| + ", " +
|background_color_end| + ")",
})
diff --git a/tests/rustdoc-gui/scrape-examples-layout.goml b/tests/rustdoc-gui/scrape-examples-layout.goml
index 4fc1c1a..6bea352 100644
--- a/tests/rustdoc-gui/scrape-examples-layout.goml
+++ b/tests/rustdoc-gui/scrape-examples-layout.goml
@@ -1,48 +1,115 @@
// Check that the line number column has the correct layout.
go-to: "file://" + |DOC_PATH| + "/scrape_examples/fn.test_many.html"
+set-window-size: (1000, 1000)
+
// Check that it's not zero.
assert-property-false: (
- ".more-scraped-examples .scraped-example .code-wrapper .src-line-numbers",
+ ".more-scraped-examples .scraped-example .src-line-numbers",
{"clientWidth": "0"}
)
// Check that examples with very long lines have the same width as ones that don't.
store-property: (
- ".more-scraped-examples .scraped-example:nth-child(2) .code-wrapper .src-line-numbers",
+ ".more-scraped-examples .scraped-example:nth-child(2) .src-line-numbers",
{"clientWidth": clientWidth},
)
assert-property: (
- ".more-scraped-examples .scraped-example:nth-child(3) .code-wrapper .src-line-numbers",
+ ".more-scraped-examples .scraped-example:nth-child(3) .src-line-numbers",
{"clientWidth": |clientWidth|}
)
assert-property: (
- ".more-scraped-examples .scraped-example:nth-child(4) .code-wrapper .src-line-numbers",
+ ".more-scraped-examples .scraped-example:nth-child(4) .src-line-numbers",
{"clientWidth": |clientWidth|}
)
assert-property: (
- ".more-scraped-examples .scraped-example:nth-child(5) .code-wrapper .src-line-numbers",
+ ".more-scraped-examples .scraped-example:nth-child(5) .src-line-numbers",
{"clientWidth": |clientWidth|}
)
assert-property: (
- ".more-scraped-examples .scraped-example:nth-child(6) .code-wrapper .src-line-numbers",
+ ".more-scraped-examples .scraped-example:nth-child(6) .src-line-numbers",
{"clientWidth": |clientWidth|}
)
+// The "title" should be located at the right bottom corner of the code example.
+store-position: (".scraped-example .example-wrap", {"x": x, "y": y})
+store-size: (".scraped-example .example-wrap", {"width": width, "height": height})
+store-size: (".scraped-example .scraped-example-title", {
+ "width": title_width,
+ "height": title_height,
+})
+assert-position: (".scraped-example .scraped-example-title", {
+ "x": |x| + |width| - |title_width| - 5,
+ "y": |y| + |height| - |title_height| - 8,
+})
+
+// Check that the expand button works and also that line number aligns with code.
+move-cursor-to: ".scraped-example .rust"
+click: ".scraped-example .button-holder .expand"
+wait-for: ".scraped-example.expanded"
+// They should have the same y position.
+compare-elements-position: (
+ ".scraped-example.expanded .src-line-numbers pre span",
+ ".scraped-example.expanded .rust code",
+ ["y"],
+)
+// And they should have the same height.
+compare-elements-size: (
+ ".scraped-example.expanded .src-line-numbers",
+ ".scraped-example.expanded .rust",
+ ["height"],
+)
+// Collapse code again.
+click: ".scraped-example .button-holder .expand"
+
// Check that for both mobile and desktop sizes, the buttons in scraped examples are displayed
// correctly.
store-value: (offset_y, 4)
// First with desktop
-assert-position: (".scraped-example .code-wrapper", {"y": 226})
-assert-position: (".scraped-example .code-wrapper .prev", {"y": 226 + |offset_y|})
+assert-position: (".scraped-example", {"y": 226})
+assert-position: (".scraped-example .prev", {"y": 226 + |offset_y|})
+
+// Gradient background should be at the top of the code block.
+assert-css: (".scraped-example .example-wrap::before", {"top": "0px"})
+assert-css: (".scraped-example .example-wrap::after", {"bottom": "0px"})
// Then with mobile
set-window-size: (600, 600)
-assert-position: (".scraped-example .code-wrapper", {"y": 308})
-assert-position: (".scraped-example .code-wrapper .prev", {"y": 308 + |offset_y|})
+store-size: (".scraped-example .scraped-example-title", {"height": title_height})
+assert-position: (".scraped-example", {"y": 284})
+assert-position: (".scraped-example .prev", {"y": 284 + |offset_y| + |title_height|})
+
+define-function: (
+ "check_title_and_code_position",
+ [],
+ block {
+ // Title should be above the code.
+ store-position: (".scraped-example .example-wrap .src-line-numbers", {"x": x, "y": y})
+ store-size: (".scraped-example .scraped-example-title", { "height": title_height })
+
+ assert-position: (".scraped-example .scraped-example-title", {
+ "x": |x|, // same X position.
+ "y": |y| - |title_height|,
+ })
+
+ // Line numbers should be right beside the code.
+ compare-elements-position: (
+ ".scraped-example .example-wrap .src-line-numbers",
+ ".scraped-example .example-wrap .rust",
+ ["y"],
+ )
+ }
+)
+
+// Check that the title is now above the code.
+call-function: ("check_title_and_code_position", {})
+
+// Then with small mobile
+set-window-size: (300, 300)
+call-function: ("check_title_and_code_position", {})
diff --git a/tests/rustdoc-gui/src/theme_css/custom-theme.css b/tests/rustdoc-gui/src/theme_css/custom-theme.css
index a56c31a..366f09f 100644
--- a/tests/rustdoc-gui/src/theme_css/custom-theme.css
+++ b/tests/rustdoc-gui/src/theme_css/custom-theme.css
@@ -23,6 +23,8 @@
--copy-path-button-color: #999;
--copy-path-img-filter: invert(50%);
--copy-path-img-hover-filter: invert(35%);
+ --code-example-button-color: #7f7f7f;
+ --code-example-button-hover-color: #a5a5a5;
--codeblock-error-hover-color: rgb(255, 0, 0);
--codeblock-error-color: rgba(255, 0, 0, .5);
--codeblock-ignore-hover-color: rgb(255, 142, 0);
diff --git a/tests/rustdoc-js-std/parser-errors.js b/tests/rustdoc-js-std/parser-errors.js
index c4d7c2b..5ce35bf 100644
--- a/tests/rustdoc-js-std/parser-errors.js
+++ b/tests/rustdoc-js-std/parser-errors.js
@@ -252,15 +252,6 @@
error: "Unexpected `'` after `b` (not a valid identifier)",
},
{
- query: "a->",
- elems: [],
- foundElems: 0,
- original: "a->",
- returned: [],
- userQuery: "a->",
- error: "Expected at least one item after `->`",
- },
- {
query: '"p" <a>',
elems: [],
foundElems: 0,
diff --git a/tests/rustdoc-js-std/parser-returned.js b/tests/rustdoc-js-std/parser-returned.js
index 44e517c..8f68209 100644
--- a/tests/rustdoc-js-std/parser-returned.js
+++ b/tests/rustdoc-js-std/parser-returned.js
@@ -94,4 +94,72 @@
userQuery: "-> !",
error: null,
},
+ {
+ query: "a->",
+ elems: [{
+ name: "a",
+ fullPath: ["a"],
+ pathWithoutLast: [],
+ pathLast: "a",
+ generics: [],
+ typeFilter: -1,
+ }],
+ foundElems: 1,
+ original: "a->",
+ returned: [],
+ userQuery: "a->",
+ hasReturnArrow: true,
+ error: null,
+ },
+ {
+ query: "!->",
+ elems: [{
+ name: "never",
+ fullPath: ["never"],
+ pathWithoutLast: [],
+ pathLast: "never",
+ generics: [],
+ typeFilter: 1,
+ }],
+ foundElems: 1,
+ original: "!->",
+ returned: [],
+ userQuery: "!->",
+ hasReturnArrow: true,
+ error: null,
+ },
+ {
+ query: "! ->",
+ elems: [{
+ name: "never",
+ fullPath: ["never"],
+ pathWithoutLast: [],
+ pathLast: "never",
+ generics: [],
+ typeFilter: 1,
+ }],
+ foundElems: 1,
+ original: "! ->",
+ returned: [],
+ userQuery: "! ->",
+ hasReturnArrow: true,
+ error: null,
+ },
+ {
+ query: "primitive:!->",
+ elems: [{
+ name: "never",
+ fullPath: ["never"],
+ pathWithoutLast: [],
+ pathLast: "never",
+ generics: [],
+ typeFilter: 1,
+ }],
+ foundElems: 1,
+ original: "primitive:!->",
+ returned: [],
+ userQuery: "primitive:!->",
+ hasReturnArrow: true,
+ error: null,
+ },
];
diff --git a/tests/rustdoc-js/never-search.js b/tests/rustdoc-js/never-search.js
index 9f18370..9cc62a5 100644
--- a/tests/rustdoc-js/never-search.js
+++ b/tests/rustdoc-js/never-search.js
@@ -2,6 +2,13 @@
const EXPECTED = [
{
+ 'query': '! ->',
+ 'others': [
+ { 'path': 'never_search', 'name': 'impossible' },
+ { 'path': 'never_search', 'name': 'box_impossible' },
+ ],
+ },
+ {
'query': '-> !',
'others': [
{ 'path': 'never_search', 'name': 'loops' },
diff --git a/tests/rustdoc-json/assoc_items.rs b/tests/rustdoc-json/assoc_items.rs
index 7fd0fe2..f315f37 100644
--- a/tests/rustdoc-json/assoc_items.rs
+++ b/tests/rustdoc-json/assoc_items.rs
@@ -9,12 +9,12 @@ impl Simple {
pub trait EasyToImpl {
//@ has "$.index[*][?(@.docs=='ToDeclare trait')].inner.assoc_type"
- //@ is "$.index[*][?(@.docs=='ToDeclare trait')].inner.assoc_type.default" null
+ //@ is "$.index[*][?(@.docs=='ToDeclare trait')].inner.assoc_type.type" null
//@ is "$.index[*][?(@.docs=='ToDeclare trait')].inner.assoc_type.bounds" []
/// ToDeclare trait
type ToDeclare;
//@ has "$.index[*][?(@.docs=='AN_ATTRIBUTE trait')].inner.assoc_const"
- //@ is "$.index[*][?(@.docs=='AN_ATTRIBUTE trait')].inner.assoc_const.default" null
+ //@ is "$.index[*][?(@.docs=='AN_ATTRIBUTE trait')].inner.assoc_const.value" null
//@ is "$.index[*][?(@.docs=='AN_ATTRIBUTE trait')].inner.assoc_const.type.primitive" '"usize"'
/// AN_ATTRIBUTE trait
const AN_ATTRIBUTE: usize;
@@ -22,13 +22,13 @@ pub trait EasyToImpl {
impl EasyToImpl for Simple {
//@ has "$.index[*][?(@.docs=='ToDeclare impl')].inner.assoc_type"
- //@ is "$.index[*][?(@.docs=='ToDeclare impl')].inner.assoc_type.default.primitive" \"usize\"
+ //@ is "$.index[*][?(@.docs=='ToDeclare impl')].inner.assoc_type.type.primitive" \"usize\"
/// ToDeclare impl
type ToDeclare = usize;
//@ has "$.index[*][?(@.docs=='AN_ATTRIBUTE impl')].inner.assoc_const"
//@ is "$.index[*][?(@.docs=='AN_ATTRIBUTE impl')].inner.assoc_const.type.primitive" \"usize\"
- //@ is "$.index[*][?(@.docs=='AN_ATTRIBUTE impl')].inner.assoc_const.default" \"12\"
+ //@ is "$.index[*][?(@.docs=='AN_ATTRIBUTE impl')].inner.assoc_const.value" \"12\"
/// AN_ATTRIBUTE impl
const AN_ATTRIBUTE: usize = 12;
}
diff --git a/tests/rustdoc-json/blanket_impls.rs b/tests/rustdoc-json/blanket_impls.rs
index bc2c98d..f2acabb 100644
--- a/tests/rustdoc-json/blanket_impls.rs
+++ b/tests/rustdoc-json/blanket_impls.rs
@@ -3,6 +3,6 @@
#![no_std]
//@ has "$.index[*][?(@.name=='Error')].inner.assoc_type"
-//@ has "$.index[*][?(@.name=='Error')].inner.assoc_type.default.resolved_path"
-//@ has "$.index[*][?(@.name=='Error')].inner.assoc_type.default.resolved_path.name" \"Infallible\"
+//@ has "$.index[*][?(@.name=='Error')].inner.assoc_type.type.resolved_path"
+//@ has "$.index[*][?(@.name=='Error')].inner.assoc_type.type.resolved_path.name" \"Infallible\"
pub struct ForBlanketTryFromImpl;
diff --git a/tests/rustdoc-json/enums/kind.rs b/tests/rustdoc-json/enums/kind.rs
index ef3d936..2e0fb31 100644
--- a/tests/rustdoc-json/enums/kind.rs
+++ b/tests/rustdoc-json/enums/kind.rs
@@ -5,7 +5,7 @@ pub enum Foo {
//@ is "$.index[*][?(@.name=='Unit')].inner.variant.kind" '"plain"'
Unit,
//@ set Named = "$.index[*][?(@.name=='Named')].id"
- //@ is "$.index[*][?(@.name=='Named')].inner.variant.kind.struct" '{"fields": [], "fields_stripped": false}'
+ //@ is "$.index[*][?(@.name=='Named')].inner.variant.kind.struct" '{"fields": [], "has_stripped_fields": false}'
Named {},
//@ set Tuple = "$.index[*][?(@.name=='Tuple')].id"
//@ is "$.index[*][?(@.name=='Tuple')].inner.variant.kind.tuple" []
@@ -13,7 +13,7 @@ pub enum Foo {
//@ set NamedField = "$.index[*][?(@.name=='NamedField')].id"
//@ set x = "$.index[*][?(@.name=='x' && @.inner.struct_field)].id"
//@ is "$.index[*][?(@.name=='NamedField')].inner.variant.kind.struct.fields[*]" $x
- //@ is "$.index[*][?(@.name=='NamedField')].inner.variant.kind.struct.fields_stripped" false
+ //@ is "$.index[*][?(@.name=='NamedField')].inner.variant.kind.struct.has_stripped_fields" false
NamedField { x: i32 },
//@ set TupleField = "$.index[*][?(@.name=='TupleField')].id"
//@ set tup_field = "$.index[*][?(@.name=='0' && @.inner.struct_field)].id"
diff --git a/tests/rustdoc-json/enums/struct_field_hidden.rs b/tests/rustdoc-json/enums/struct_field_hidden.rs
index b724f9a..2184f58 100644
--- a/tests/rustdoc-json/enums/struct_field_hidden.rs
+++ b/tests/rustdoc-json/enums/struct_field_hidden.rs
@@ -9,7 +9,7 @@
//@ set y = "$.index[*][?(@.name=='y')].id"
y: i32,
},
- //@ is "$.index[*][?(@.name=='Variant')].inner.variant.kind.struct.fields_stripped" true
+ //@ is "$.index[*][?(@.name=='Variant')].inner.variant.kind.struct.has_stripped_fields" true
//@ is "$.index[*][?(@.name=='Variant')].inner.variant.kind.struct.fields[0]" $b
//@ is "$.index[*][?(@.name=='Variant')].inner.variant.kind.struct.fields[1]" $y
//@ count "$.index[*][?(@.name=='Variant')].inner.variant.kind.struct.fields[*]" 2
diff --git a/tests/rustdoc-json/enums/use_glob.rs b/tests/rustdoc-json/enums/use_glob.rs
index 61766d2..2631b43 100644
--- a/tests/rustdoc-json/enums/use_glob.rs
+++ b/tests/rustdoc-json/enums/use_glob.rs
@@ -7,9 +7,9 @@ pub enum Color {
Blue,
}
-//@ set use_Color = "$.index[*][?(@.inner.import)].id"
-//@ is "$.index[*][?(@.inner.import)].inner.import.id" $Color
-//@ is "$.index[*][?(@.inner.import)].inner.import.glob" true
+//@ set use_Color = "$.index[*][?(@.inner.use)].id"
+//@ is "$.index[*][?(@.inner.use)].inner.use.id" $Color
+//@ is "$.index[*][?(@.inner.use)].inner.use.is_glob" true
pub use Color::*;
//@ ismany "$.index[*][?(@.name == 'use_glob')].inner.module.items[*]" $Color $use_Color
diff --git a/tests/rustdoc-json/enums/use_variant.rs b/tests/rustdoc-json/enums/use_variant.rs
index 9010d61..6d3322e 100644
--- a/tests/rustdoc-json/enums/use_variant.rs
+++ b/tests/rustdoc-json/enums/use_variant.rs
@@ -5,8 +5,8 @@ pub enum AlwaysNone {
}
//@ is "$.index[*][?(@.name == 'AlwaysNone')].inner.enum.variants[*]" $None
-//@ set use_None = "$.index[*][?(@.inner.import)].id"
-//@ is "$.index[*][?(@.inner.import)].inner.import.id" $None
+//@ set use_None = "$.index[*][?(@.inner.use)].id"
+//@ is "$.index[*][?(@.inner.use)].inner.use.id" $None
pub use AlwaysNone::None;
//@ ismany "$.index[*][?(@.name == 'use_variant')].inner.module.items[*]" $AlwaysNone $use_None
diff --git a/tests/rustdoc-json/enums/use_variant_foreign.rs b/tests/rustdoc-json/enums/use_variant_foreign.rs
index 0f3f16ff..a9ad61b 100644
--- a/tests/rustdoc-json/enums/use_variant_foreign.rs
+++ b/tests/rustdoc-json/enums/use_variant_foreign.rs
@@ -2,7 +2,7 @@
extern crate color;
-//@ has "$.index[*].inner.import[?(@.name == 'Red')]"
+//@ has "$.index[*].inner.use[?(@.name == 'Red')]"
pub use color::Color::Red;
//@ !has "$.index[*][?(@.name == 'Red')]"
diff --git a/tests/rustdoc-json/fn_pointer/generics.rs b/tests/rustdoc-json/fn_pointer/generics.rs
index 9f5d23a..7d64e49 100644
--- a/tests/rustdoc-json/fn_pointer/generics.rs
+++ b/tests/rustdoc-json/fn_pointer/generics.rs
@@ -1,9 +1,9 @@
// ignore-tidy-linelength
-//@ count "$.index[*][?(@.name=='WithHigherRankTraitBounds')].inner.type_alias.type.function_pointer.decl.inputs[*]" 1
-//@ is "$.index[*][?(@.name=='WithHigherRankTraitBounds')].inner.type_alias.type.function_pointer.decl.inputs[0][0]" '"val"'
-//@ is "$.index[*][?(@.name=='WithHigherRankTraitBounds')].inner.type_alias.type.function_pointer.decl.inputs[0][1].borrowed_ref.lifetime" \"\'c\"
-//@ is "$.index[*][?(@.name=='WithHigherRankTraitBounds')].inner.type_alias.type.function_pointer.decl.output.primitive" \"i32\"
+//@ count "$.index[*][?(@.name=='WithHigherRankTraitBounds')].inner.type_alias.type.function_pointer.sig.inputs[*]" 1
+//@ is "$.index[*][?(@.name=='WithHigherRankTraitBounds')].inner.type_alias.type.function_pointer.sig.inputs[0][0]" '"val"'
+//@ is "$.index[*][?(@.name=='WithHigherRankTraitBounds')].inner.type_alias.type.function_pointer.sig.inputs[0][1].borrowed_ref.lifetime" \"\'c\"
+//@ is "$.index[*][?(@.name=='WithHigherRankTraitBounds')].inner.type_alias.type.function_pointer.sig.output.primitive" \"i32\"
//@ count "$.index[*][?(@.name=='WithHigherRankTraitBounds')].inner.type_alias.type.function_pointer.generic_params[*]" 1
//@ is "$.index[*][?(@.name=='WithHigherRankTraitBounds')].inner.type_alias.type.function_pointer.generic_params[0].name" \"\'c\"
//@ is "$.index[*][?(@.name=='WithHigherRankTraitBounds')].inner.type_alias.type.function_pointer.generic_params[0].kind" '{ "lifetime": { "outlives": [] } }'
diff --git a/tests/rustdoc-json/fn_pointer/qualifiers.rs b/tests/rustdoc-json/fn_pointer/qualifiers.rs
index 9c0e6c0..6f03cf5 100644
--- a/tests/rustdoc-json/fn_pointer/qualifiers.rs
+++ b/tests/rustdoc-json/fn_pointer/qualifiers.rs
@@ -1,11 +1,11 @@
// ignore-tidy-linelength
-//@ is "$.index[*][?(@.name=='FnPointer')].inner.type_alias.type.function_pointer.header.unsafe" false
-//@ is "$.index[*][?(@.name=='FnPointer')].inner.type_alias.type.function_pointer.header.const" false
-//@ is "$.index[*][?(@.name=='FnPointer')].inner.type_alias.type.function_pointer.header.async" false
+//@ is "$.index[*][?(@.name=='FnPointer')].inner.type_alias.type.function_pointer.header.is_unsafe" false
+//@ is "$.index[*][?(@.name=='FnPointer')].inner.type_alias.type.function_pointer.header.is_const" false
+//@ is "$.index[*][?(@.name=='FnPointer')].inner.type_alias.type.function_pointer.header.is_async" false
pub type FnPointer = fn();
-//@ is "$.index[*][?(@.name=='UnsafePointer')].inner.type_alias.type.function_pointer.header.unsafe" true
-//@ is "$.index[*][?(@.name=='UnsafePointer')].inner.type_alias.type.function_pointer.header.const" false
-//@ is "$.index[*][?(@.name=='UnsafePointer')].inner.type_alias.type.function_pointer.header.async" false
+//@ is "$.index[*][?(@.name=='UnsafePointer')].inner.type_alias.type.function_pointer.header.is_unsafe" true
+//@ is "$.index[*][?(@.name=='UnsafePointer')].inner.type_alias.type.function_pointer.header.is_const" false
+//@ is "$.index[*][?(@.name=='UnsafePointer')].inner.type_alias.type.function_pointer.header.is_async" false
pub type UnsafePointer = unsafe fn();
diff --git a/tests/rustdoc-json/fns/async_return.rs b/tests/rustdoc-json/fns/async_return.rs
index e029c72..18a8a58 100644
--- a/tests/rustdoc-json/fns/async_return.rs
+++ b/tests/rustdoc-json/fns/async_return.rs
@@ -5,30 +5,30 @@
use std::future::Future;
-//@ is "$.index[*][?(@.name=='get_int')].inner.function.decl.output.primitive" \"i32\"
-//@ is "$.index[*][?(@.name=='get_int')].inner.function.header.async" false
+//@ is "$.index[*][?(@.name=='get_int')].inner.function.sig.output.primitive" \"i32\"
+//@ is "$.index[*][?(@.name=='get_int')].inner.function.header.is_async" false
pub fn get_int() -> i32 {
42
}
-//@ is "$.index[*][?(@.name=='get_int_async')].inner.function.decl.output.primitive" \"i32\"
-//@ is "$.index[*][?(@.name=='get_int_async')].inner.function.header.async" true
+//@ is "$.index[*][?(@.name=='get_int_async')].inner.function.sig.output.primitive" \"i32\"
+//@ is "$.index[*][?(@.name=='get_int_async')].inner.function.header.is_async" true
pub async fn get_int_async() -> i32 {
42
}
-//@ is "$.index[*][?(@.name=='get_int_future')].inner.function.decl.output.impl_trait[0].trait_bound.trait.name" '"Future"'
-//@ is "$.index[*][?(@.name=='get_int_future')].inner.function.decl.output.impl_trait[0].trait_bound.trait.args.angle_bracketed.bindings[0].name" '"Output"'
-//@ is "$.index[*][?(@.name=='get_int_future')].inner.function.decl.output.impl_trait[0].trait_bound.trait.args.angle_bracketed.bindings[0].binding.equality.type.primitive" \"i32\"
-//@ is "$.index[*][?(@.name=='get_int_future')].inner.function.header.async" false
+//@ is "$.index[*][?(@.name=='get_int_future')].inner.function.sig.output.impl_trait[0].trait_bound.trait.name" '"Future"'
+//@ is "$.index[*][?(@.name=='get_int_future')].inner.function.sig.output.impl_trait[0].trait_bound.trait.args.angle_bracketed.constraints[0].name" '"Output"'
+//@ is "$.index[*][?(@.name=='get_int_future')].inner.function.sig.output.impl_trait[0].trait_bound.trait.args.angle_bracketed.constraints[0].binding.equality.type.primitive" \"i32\"
+//@ is "$.index[*][?(@.name=='get_int_future')].inner.function.header.is_async" false
pub fn get_int_future() -> impl Future<Output = i32> {
async { 42 }
}
-//@ is "$.index[*][?(@.name=='get_int_future_async')].inner.function.decl.output.impl_trait[0].trait_bound.trait.name" '"Future"'
-//@ is "$.index[*][?(@.name=='get_int_future_async')].inner.function.decl.output.impl_trait[0].trait_bound.trait.args.angle_bracketed.bindings[0].name" '"Output"'
-//@ is "$.index[*][?(@.name=='get_int_future_async')].inner.function.decl.output.impl_trait[0].trait_bound.trait.args.angle_bracketed.bindings[0].binding.equality.type.primitive" \"i32\"
-//@ is "$.index[*][?(@.name=='get_int_future_async')].inner.function.header.async" true
+//@ is "$.index[*][?(@.name=='get_int_future_async')].inner.function.sig.output.impl_trait[0].trait_bound.trait.name" '"Future"'
+//@ is "$.index[*][?(@.name=='get_int_future_async')].inner.function.sig.output.impl_trait[0].trait_bound.trait.args.angle_bracketed.constraints[0].name" '"Output"'
+//@ is "$.index[*][?(@.name=='get_int_future_async')].inner.function.sig.output.impl_trait[0].trait_bound.trait.args.angle_bracketed.constraints[0].binding.equality.type.primitive" \"i32\"
+//@ is "$.index[*][?(@.name=='get_int_future_async')].inner.function.header.is_async" true
pub async fn get_int_future_async() -> impl Future<Output = i32> {
async { 42 }
}
diff --git a/tests/rustdoc-json/fns/extern_c_variadic.rs b/tests/rustdoc-json/fns/extern_c_variadic.rs
index defe663..8e90856 100644
--- a/tests/rustdoc-json/fns/extern_c_variadic.rs
+++ b/tests/rustdoc-json/fns/extern_c_variadic.rs
@@ -1,6 +1,6 @@
extern "C" {
- //@ is "$.index[*][?(@.name == 'not_variadic')].inner.function.decl.c_variadic" false
+ //@ is "$.index[*][?(@.name == 'not_variadic')].inner.function.sig.is_c_variadic" false
pub fn not_variadic(_: i32);
- //@ is "$.index[*][?(@.name == 'variadic')].inner.function.decl.c_variadic" true
+ //@ is "$.index[*][?(@.name == 'variadic')].inner.function.sig.is_c_variadic" true
pub fn variadic(_: i32, ...);
}
diff --git a/tests/rustdoc-json/fns/generic_args.rs b/tests/rustdoc-json/fns/generic_args.rs
index 75c5fcb..b541244 100644
--- a/tests/rustdoc-json/fns/generic_args.rs
+++ b/tests/rustdoc-json/fns/generic_args.rs
@@ -12,27 +12,27 @@ pub trait GenericFoo<'a> {}
//@ is "$.index[*][?(@.name=='generics')].inner.function.generics.params[0].kind.type.default" 'null'
//@ count "$.index[*][?(@.name=='generics')].inner.function.generics.params[0].kind.type.bounds[*]" 1
//@ is "$.index[*][?(@.name=='generics')].inner.function.generics.params[0].kind.type.bounds[0].trait_bound.trait.id" '$foo'
-//@ count "$.index[*][?(@.name=='generics')].inner.function.decl.inputs[*]" 1
-//@ is "$.index[*][?(@.name=='generics')].inner.function.decl.inputs[0][0]" '"f"'
-//@ is "$.index[*][?(@.name=='generics')].inner.function.decl.inputs[0][1].generic" '"F"'
+//@ count "$.index[*][?(@.name=='generics')].inner.function.sig.inputs[*]" 1
+//@ is "$.index[*][?(@.name=='generics')].inner.function.sig.inputs[0][0]" '"f"'
+//@ is "$.index[*][?(@.name=='generics')].inner.function.sig.inputs[0][1].generic" '"F"'
pub fn generics<F: Foo>(f: F) {}
//@ is "$.index[*][?(@.name=='impl_trait')].inner.function.generics.where_predicates" "[]"
//@ count "$.index[*][?(@.name=='impl_trait')].inner.function.generics.params[*]" 1
//@ is "$.index[*][?(@.name=='impl_trait')].inner.function.generics.params[0].name" '"impl Foo"'
//@ is "$.index[*][?(@.name=='impl_trait')].inner.function.generics.params[0].kind.type.bounds[0].trait_bound.trait.id" $foo
-//@ count "$.index[*][?(@.name=='impl_trait')].inner.function.decl.inputs[*]" 1
-//@ is "$.index[*][?(@.name=='impl_trait')].inner.function.decl.inputs[0][0]" '"f"'
-//@ count "$.index[*][?(@.name=='impl_trait')].inner.function.decl.inputs[0][1].impl_trait[*]" 1
-//@ is "$.index[*][?(@.name=='impl_trait')].inner.function.decl.inputs[0][1].impl_trait[0].trait_bound.trait.id" $foo
+//@ count "$.index[*][?(@.name=='impl_trait')].inner.function.sig.inputs[*]" 1
+//@ is "$.index[*][?(@.name=='impl_trait')].inner.function.sig.inputs[0][0]" '"f"'
+//@ count "$.index[*][?(@.name=='impl_trait')].inner.function.sig.inputs[0][1].impl_trait[*]" 1
+//@ is "$.index[*][?(@.name=='impl_trait')].inner.function.sig.inputs[0][1].impl_trait[0].trait_bound.trait.id" $foo
pub fn impl_trait(f: impl Foo) {}
//@ count "$.index[*][?(@.name=='where_clase')].inner.function.generics.params[*]" 3
//@ is "$.index[*][?(@.name=='where_clase')].inner.function.generics.params[0].name" '"F"'
-//@ is "$.index[*][?(@.name=='where_clase')].inner.function.generics.params[0].kind" '{"type": {"bounds": [], "default": null, "synthetic": false}}'
-//@ count "$.index[*][?(@.name=='where_clase')].inner.function.decl.inputs[*]" 3
-//@ is "$.index[*][?(@.name=='where_clase')].inner.function.decl.inputs[0][0]" '"f"'
-//@ is "$.index[*][?(@.name=='where_clase')].inner.function.decl.inputs[0][1].generic" '"F"'
+//@ is "$.index[*][?(@.name=='where_clase')].inner.function.generics.params[0].kind" '{"type": {"bounds": [], "default": null, "is_synthetic": false}}'
+//@ count "$.index[*][?(@.name=='where_clase')].inner.function.sig.inputs[*]" 3
+//@ is "$.index[*][?(@.name=='where_clase')].inner.function.sig.inputs[0][0]" '"f"'
+//@ is "$.index[*][?(@.name=='where_clase')].inner.function.sig.inputs[0][1].generic" '"F"'
//@ count "$.index[*][?(@.name=='where_clase')].inner.function.generics.where_predicates[*]" 3
//@ is "$.index[*][?(@.name=='where_clase')].inner.function.generics.where_predicates[0].bound_predicate.type.generic" \"F\"
diff --git a/tests/rustdoc-json/fns/generic_returns.rs b/tests/rustdoc-json/fns/generic_returns.rs
index 07dc691..2f23801 100644
--- a/tests/rustdoc-json/fns/generic_returns.rs
+++ b/tests/rustdoc-json/fns/generic_returns.rs
@@ -5,9 +5,9 @@
//@ set foo = "$.index[*][?(@.name=='Foo')].id"
pub trait Foo {}
-//@ is "$.index[*][?(@.name=='get_foo')].inner.function.decl.inputs" []
-//@ count "$.index[*][?(@.name=='get_foo')].inner.function.decl.output.impl_trait[*]" 1
-//@ is "$.index[*][?(@.name=='get_foo')].inner.function.decl.output.impl_trait[0].trait_bound.trait.id" $foo
+//@ is "$.index[*][?(@.name=='get_foo')].inner.function.sig.inputs" []
+//@ count "$.index[*][?(@.name=='get_foo')].inner.function.sig.output.impl_trait[*]" 1
+//@ is "$.index[*][?(@.name=='get_foo')].inner.function.sig.output.impl_trait[0].trait_bound.trait.id" $foo
pub fn get_foo() -> impl Foo {
Fooer {}
}
diff --git a/tests/rustdoc-json/fns/generics.rs b/tests/rustdoc-json/fns/generics.rs
index 43fc727..f2064fd 100644
--- a/tests/rustdoc-json/fns/generics.rs
+++ b/tests/rustdoc-json/fns/generics.rs
@@ -6,17 +6,17 @@ pub trait Wham {}
//@ is "$.index[*][?(@.name=='one_generic_param_fn')].inner.function.generics.where_predicates" []
//@ count "$.index[*][?(@.name=='one_generic_param_fn')].inner.function.generics.params[*]" 1
//@ is "$.index[*][?(@.name=='one_generic_param_fn')].inner.function.generics.params[0].name" '"T"'
-//@ is "$.index[*][?(@.name=='one_generic_param_fn')].inner.function.generics.params[0].kind.type.synthetic" false
+//@ is "$.index[*][?(@.name=='one_generic_param_fn')].inner.function.generics.params[0].kind.type.is_synthetic" false
//@ is "$.index[*][?(@.name=='one_generic_param_fn')].inner.function.generics.params[0].kind.type.bounds[0].trait_bound.trait.id" $wham_id
-//@ is "$.index[*][?(@.name=='one_generic_param_fn')].inner.function.decl.inputs" '[["w", {"generic": "T"}]]'
+//@ is "$.index[*][?(@.name=='one_generic_param_fn')].inner.function.sig.inputs" '[["w", {"generic": "T"}]]'
pub fn one_generic_param_fn<T: Wham>(w: T) {}
//@ is "$.index[*][?(@.name=='one_synthetic_generic_param_fn')].inner.function.generics.where_predicates" []
//@ count "$.index[*][?(@.name=='one_synthetic_generic_param_fn')].inner.function.generics.params[*]" 1
//@ is "$.index[*][?(@.name=='one_synthetic_generic_param_fn')].inner.function.generics.params[0].name" '"impl Wham"'
-//@ is "$.index[*][?(@.name=='one_synthetic_generic_param_fn')].inner.function.generics.params[0].kind.type.synthetic" true
+//@ is "$.index[*][?(@.name=='one_synthetic_generic_param_fn')].inner.function.generics.params[0].kind.type.is_synthetic" true
//@ is "$.index[*][?(@.name=='one_synthetic_generic_param_fn')].inner.function.generics.params[0].kind.type.bounds[0].trait_bound.trait.id" $wham_id
-//@ count "$.index[*][?(@.name=='one_synthetic_generic_param_fn')].inner.function.decl.inputs[*]" 1
-//@ is "$.index[*][?(@.name=='one_synthetic_generic_param_fn')].inner.function.decl.inputs[0][0]" '"w"'
-//@ is "$.index[*][?(@.name=='one_synthetic_generic_param_fn')].inner.function.decl.inputs[0][1].impl_trait[0].trait_bound.trait.id" $wham_id
+//@ count "$.index[*][?(@.name=='one_synthetic_generic_param_fn')].inner.function.sig.inputs[*]" 1
+//@ is "$.index[*][?(@.name=='one_synthetic_generic_param_fn')].inner.function.sig.inputs[0][0]" '"w"'
+//@ is "$.index[*][?(@.name=='one_synthetic_generic_param_fn')].inner.function.sig.inputs[0][1].impl_trait[0].trait_bound.trait.id" $wham_id
pub fn one_synthetic_generic_param_fn(w: impl Wham) {}
diff --git a/tests/rustdoc-json/fns/pattern_arg.rs b/tests/rustdoc-json/fns/pattern_arg.rs
index 3fa423b..d2a00f4 100644
--- a/tests/rustdoc-json/fns/pattern_arg.rs
+++ b/tests/rustdoc-json/fns/pattern_arg.rs
@@ -1,7 +1,7 @@
-//@ is "$.index[*][?(@.name=='fst')].inner.function.decl.inputs[0][0]" '"(x, _)"'
+//@ is "$.index[*][?(@.name=='fst')].inner.function.sig.inputs[0][0]" '"(x, _)"'
pub fn fst<X, Y>((x, _): (X, Y)) -> X {
x
}
-//@ is "$.index[*][?(@.name=='drop_int')].inner.function.decl.inputs[0][0]" '"_"'
+//@ is "$.index[*][?(@.name=='drop_int')].inner.function.sig.inputs[0][0]" '"_"'
pub fn drop_int(_: i32) {}
diff --git a/tests/rustdoc-json/fns/qualifiers.rs b/tests/rustdoc-json/fns/qualifiers.rs
index beb1b4c..67e49f0 100644
--- a/tests/rustdoc-json/fns/qualifiers.rs
+++ b/tests/rustdoc-json/fns/qualifiers.rs
@@ -1,33 +1,33 @@
//@ edition:2018
-//@ is "$.index[*][?(@.name=='nothing_fn')].inner.function.header.async" false
-//@ is "$.index[*][?(@.name=='nothing_fn')].inner.function.header.const" false
-//@ is "$.index[*][?(@.name=='nothing_fn')].inner.function.header.unsafe" false
+//@ is "$.index[*][?(@.name=='nothing_fn')].inner.function.header.is_async" false
+//@ is "$.index[*][?(@.name=='nothing_fn')].inner.function.header.is_const" false
+//@ is "$.index[*][?(@.name=='nothing_fn')].inner.function.header.is_unsafe" false
pub fn nothing_fn() {}
-//@ is "$.index[*][?(@.name=='unsafe_fn')].inner.function.header.async" false
-//@ is "$.index[*][?(@.name=='unsafe_fn')].inner.function.header.const" false
-//@ is "$.index[*][?(@.name=='unsafe_fn')].inner.function.header.unsafe" true
+//@ is "$.index[*][?(@.name=='unsafe_fn')].inner.function.header.is_async" false
+//@ is "$.index[*][?(@.name=='unsafe_fn')].inner.function.header.is_const" false
+//@ is "$.index[*][?(@.name=='unsafe_fn')].inner.function.header.is_unsafe" true
pub unsafe fn unsafe_fn() {}
-//@ is "$.index[*][?(@.name=='const_fn')].inner.function.header.async" false
-//@ is "$.index[*][?(@.name=='const_fn')].inner.function.header.const" true
-//@ is "$.index[*][?(@.name=='const_fn')].inner.function.header.unsafe" false
+//@ is "$.index[*][?(@.name=='const_fn')].inner.function.header.is_async" false
+//@ is "$.index[*][?(@.name=='const_fn')].inner.function.header.is_const" true
+//@ is "$.index[*][?(@.name=='const_fn')].inner.function.header.is_unsafe" false
pub const fn const_fn() {}
-//@ is "$.index[*][?(@.name=='async_fn')].inner.function.header.async" true
-//@ is "$.index[*][?(@.name=='async_fn')].inner.function.header.const" false
-//@ is "$.index[*][?(@.name=='async_fn')].inner.function.header.unsafe" false
+//@ is "$.index[*][?(@.name=='async_fn')].inner.function.header.is_async" true
+//@ is "$.index[*][?(@.name=='async_fn')].inner.function.header.is_const" false
+//@ is "$.index[*][?(@.name=='async_fn')].inner.function.header.is_unsafe" false
pub async fn async_fn() {}
-//@ is "$.index[*][?(@.name=='async_unsafe_fn')].inner.function.header.async" true
-//@ is "$.index[*][?(@.name=='async_unsafe_fn')].inner.function.header.const" false
-//@ is "$.index[*][?(@.name=='async_unsafe_fn')].inner.function.header.unsafe" true
+//@ is "$.index[*][?(@.name=='async_unsafe_fn')].inner.function.header.is_async" true
+//@ is "$.index[*][?(@.name=='async_unsafe_fn')].inner.function.header.is_const" false
+//@ is "$.index[*][?(@.name=='async_unsafe_fn')].inner.function.header.is_unsafe" true
pub async unsafe fn async_unsafe_fn() {}
-//@ is "$.index[*][?(@.name=='const_unsafe_fn')].inner.function.header.async" false
-//@ is "$.index[*][?(@.name=='const_unsafe_fn')].inner.function.header.const" true
-//@ is "$.index[*][?(@.name=='const_unsafe_fn')].inner.function.header.unsafe" true
+//@ is "$.index[*][?(@.name=='const_unsafe_fn')].inner.function.header.is_async" false
+//@ is "$.index[*][?(@.name=='const_unsafe_fn')].inner.function.header.is_const" true
+//@ is "$.index[*][?(@.name=='const_unsafe_fn')].inner.function.header.is_unsafe" true
pub const unsafe fn const_unsafe_fn() {}
// It's impossible for a function to be both const and async, so no test for that
diff --git a/tests/rustdoc-json/fns/return_type_alias.rs b/tests/rustdoc-json/fns/return_type_alias.rs
index 67bc46a..d60c4b6 100644
--- a/tests/rustdoc-json/fns/return_type_alias.rs
+++ b/tests/rustdoc-json/fns/return_type_alias.rs
@@ -3,7 +3,7 @@
///@ set foo = "$.index[*][?(@.name=='Foo')].id"
pub type Foo = i32;
-//@ is "$.index[*][?(@.name=='demo')].inner.function.decl.output.resolved_path.id" $foo
+//@ is "$.index[*][?(@.name=='demo')].inner.function.sig.output.resolved_path.id" $foo
pub fn demo() -> Foo {
42
}
diff --git a/tests/rustdoc-json/generic-associated-types/gats.rs b/tests/rustdoc-json/generic-associated-types/gats.rs
index 8a38230..fdf605e 100644
--- a/tests/rustdoc-json/generic-associated-types/gats.rs
+++ b/tests/rustdoc-json/generic-associated-types/gats.rs
@@ -13,10 +13,10 @@ pub trait LendingIterator {
where
Self: 'a;
- //@ count "$.index[*][?(@.name=='lending_next')].inner.function.decl.output.qualified_path.args.angle_bracketed.args[*]" 1
- //@ count "$.index[*][?(@.name=='lending_next')].inner.function.decl.output.qualified_path.args.angle_bracketed.bindings[*]" 0
- //@ is "$.index[*][?(@.name=='lending_next')].inner.function.decl.output.qualified_path.self_type.generic" \"Self\"
- //@ is "$.index[*][?(@.name=='lending_next')].inner.function.decl.output.qualified_path.name" \"LendingItem\"
+ //@ count "$.index[*][?(@.name=='lending_next')].inner.function.sig.output.qualified_path.args.angle_bracketed.args[*]" 1
+ //@ count "$.index[*][?(@.name=='lending_next')].inner.function.sig.output.qualified_path.args.angle_bracketed.bindings[*]" 0
+ //@ is "$.index[*][?(@.name=='lending_next')].inner.function.sig.output.qualified_path.self_type.generic" \"Self\"
+ //@ is "$.index[*][?(@.name=='lending_next')].inner.function.sig.output.qualified_path.name" \"LendingItem\"
fn lending_next<'a>(&'a self) -> Self::LendingItem<'a>;
}
@@ -26,9 +26,9 @@ pub trait Iterator {
//@ count "$.index[*][?(@.name=='Item')].inner.assoc_type.bounds[*]" 1
type Item: Display;
- //@ count "$.index[*][?(@.name=='next')].inner.function.decl.output.qualified_path.args.angle_bracketed.args[*]" 0
- //@ count "$.index[*][?(@.name=='next')].inner.function.decl.output.qualified_path.args.angle_bracketed.bindings[*]" 0
- //@ is "$.index[*][?(@.name=='next')].inner.function.decl.output.qualified_path.self_type.generic" \"Self\"
- //@ is "$.index[*][?(@.name=='next')].inner.function.decl.output.qualified_path.name" \"Item\"
+ //@ count "$.index[*][?(@.name=='next')].inner.function.sig.output.qualified_path.args.angle_bracketed.args[*]" 0
+ //@ count "$.index[*][?(@.name=='next')].inner.function.sig.output.qualified_path.args.angle_bracketed.bindings[*]" 0
+ //@ is "$.index[*][?(@.name=='next')].inner.function.sig.output.qualified_path.self_type.generic" \"Self\"
+ //@ is "$.index[*][?(@.name=='next')].inner.function.sig.output.qualified_path.name" \"Item\"
fn next<'a>(&'a self) -> Self::Item;
}
diff --git a/tests/rustdoc-json/glob_import.rs b/tests/rustdoc-json/glob_import.rs
index a67a99a..b63e5da 100644
--- a/tests/rustdoc-json/glob_import.rs
+++ b/tests/rustdoc-json/glob_import.rs
@@ -3,7 +3,7 @@
#![no_std]
//@ has "$.index[*][?(@.name=='glob')]"
-//@ has "$.index[*][?(@.inner.import)].inner.import.name" \"*\"
+//@ has "$.index[*][?(@.inner.use)].inner.use.name" \"*\"
mod m1 {
pub fn f() {}
diff --git a/tests/rustdoc-json/impl-trait-in-assoc-type.rs b/tests/rustdoc-json/impl-trait-in-assoc-type.rs
index f02e38c..907a0f6 100644
--- a/tests/rustdoc-json/impl-trait-in-assoc-type.rs
+++ b/tests/rustdoc-json/impl-trait-in-assoc-type.rs
@@ -9,11 +9,11 @@ impl IntoIterator for AlwaysTrue {
/// type Item
type Item = bool;
- //@ count '$.index[*][?(@.docs=="type IntoIter")].inner.assoc_type.default.impl_trait[*]' 1
- //@ is '$.index[*][?(@.docs=="type IntoIter")].inner.assoc_type.default.impl_trait[0].trait_bound.trait.name' '"Iterator"'
- //@ count '$.index[*][?(@.docs=="type IntoIter")].inner.assoc_type.default.impl_trait[0].trait_bound.trait.args.angle_bracketed.bindings[*]' 1
- //@ is '$.index[*][?(@.docs=="type IntoIter")].inner.assoc_type.default.impl_trait[0].trait_bound.trait.args.angle_bracketed.bindings[0].name' '"Item"'
- //@ is '$.index[*][?(@.docs=="type IntoIter")].inner.assoc_type.default.impl_trait[0].trait_bound.trait.args.angle_bracketed.bindings[0].binding.equality.type.primitive' '"bool"'
+ //@ count '$.index[*][?(@.docs=="type IntoIter")].inner.assoc_type.type.impl_trait[*]' 1
+ //@ is '$.index[*][?(@.docs=="type IntoIter")].inner.assoc_type.type.impl_trait[0].trait_bound.trait.name' '"Iterator"'
+ //@ count '$.index[*][?(@.docs=="type IntoIter")].inner.assoc_type.type.impl_trait[0].trait_bound.trait.args.angle_bracketed.constraints[*]' 1
+ //@ is '$.index[*][?(@.docs=="type IntoIter")].inner.assoc_type.type.impl_trait[0].trait_bound.trait.args.angle_bracketed.constraints[0].name' '"Item"'
+ //@ is '$.index[*][?(@.docs=="type IntoIter")].inner.assoc_type.type.impl_trait[0].trait_bound.trait.args.angle_bracketed.constraints[0].binding.equality.type.primitive' '"bool"'
//@ set IntoIter = '$.index[*][?(@.docs=="type IntoIter")].id'
/// type IntoIter
diff --git a/tests/rustdoc-json/impl-trait-precise-capturing.rs b/tests/rustdoc-json/impl-trait-precise-capturing.rs
index 0c116a1..5225256 100644
--- a/tests/rustdoc-json/impl-trait-precise-capturing.rs
+++ b/tests/rustdoc-json/impl-trait-precise-capturing.rs
@@ -1,4 +1,4 @@
-//@ is "$.index[*][?(@.name=='hello')].inner.function.decl.output.impl_trait[1].use[0]" \"\'a\"
-//@ is "$.index[*][?(@.name=='hello')].inner.function.decl.output.impl_trait[1].use[1]" \"T\"
-//@ is "$.index[*][?(@.name=='hello')].inner.function.decl.output.impl_trait[1].use[2]" \"N\"
+//@ is "$.index[*][?(@.name=='hello')].inner.function.sig.output.impl_trait[1].use[0]" \"\'a\"
+//@ is "$.index[*][?(@.name=='hello')].inner.function.sig.output.impl_trait[1].use[1]" \"T\"
+//@ is "$.index[*][?(@.name=='hello')].inner.function.sig.output.impl_trait[1].use[2]" \"N\"
pub fn hello<'a, T, const N: usize>() -> impl Sized + use<'a, T, N> {}
diff --git a/tests/rustdoc-json/impls/auto.rs b/tests/rustdoc-json/impls/auto.rs
index 84a1e6e..e14c935 100644
--- a/tests/rustdoc-json/impls/auto.rs
+++ b/tests/rustdoc-json/impls/auto.rs
@@ -18,5 +18,5 @@ pub fn baz(&self) {}
//@ is "$.index[*][?(@.docs=='has span')].span.begin" "[13, 0]"
//@ is "$.index[*][?(@.docs=='has span')].span.end" "[15, 1]"
// FIXME: this doesn't work due to https://github.com/freestrings/jsonpath/issues/91
-// is "$.index[*][?(@.inner.impl.synthetic==true)].span" null
+// is "$.index[*][?(@.inner.impl.is_synthetic==true)].span" null
pub struct Foo;
diff --git a/tests/rustdoc-json/impls/foreign_for_local.rs b/tests/rustdoc-json/impls/foreign_for_local.rs
index 20690f2..1347f95 100644
--- a/tests/rustdoc-json/impls/foreign_for_local.rs
+++ b/tests/rustdoc-json/impls/foreign_for_local.rs
@@ -3,7 +3,7 @@
/// ForeignTrait id hack
pub use foreign_trait::ForeignTrait as _;
-//@ set ForeignTrait = "$.index[*][?(@.docs=='ForeignTrait id hack')].inner.import.id"
+//@ set ForeignTrait = "$.index[*][?(@.docs=='ForeignTrait id hack')].inner.use.id"
pub struct LocalStruct;
//@ set LocalStruct = "$.index[*][?(@.name=='LocalStruct')].id"
diff --git a/tests/rustdoc-json/impls/import_from_private.rs b/tests/rustdoc-json/impls/import_from_private.rs
index e386252..32b9abb 100644
--- a/tests/rustdoc-json/impls/import_from_private.rs
+++ b/tests/rustdoc-json/impls/import_from_private.rs
@@ -11,10 +11,10 @@ pub fn doit() {}
}
}
-//@ set import = "$.index[*][?(@.inner.import)].id"
+//@ set import = "$.index[*][?(@.inner.use)].id"
pub use bar::Baz;
//@ is "$.index[*].inner.module.items[*]" $import
-//@ is "$.index[*].inner.import.id" $baz
+//@ is "$.index[*].inner.use.id" $baz
//@ has "$.index[*][?(@.name == 'Baz')].inner.struct.impls[*]" $impl
//@ is "$.index[*][?(@.docs=='impl')].inner.impl.items[*]" $doit
diff --git a/tests/rustdoc-json/impls/local_for_foreign.rs b/tests/rustdoc-json/impls/local_for_foreign.rs
index bd49269..cd89c47 100644
--- a/tests/rustdoc-json/impls/local_for_foreign.rs
+++ b/tests/rustdoc-json/impls/local_for_foreign.rs
@@ -3,7 +3,7 @@
/// ForeignStruct id hack
pub use foreign_struct::ForeignStruct as _;
-//@ set ForeignStruct = "$.index[*][?(@.docs=='ForeignStruct id hack')].inner.import.id"
+//@ set ForeignStruct = "$.index[*][?(@.docs=='ForeignStruct id hack')].inner.use.id"
pub trait LocalTrait {}
//@ set LocalTrait = "$.index[*][?(@.name=='LocalTrait')].id"
diff --git a/tests/rustdoc-json/lifetime/longest.rs b/tests/rustdoc-json/lifetime/longest.rs
index 39f791d..8ac60be 100644
--- a/tests/rustdoc-json/lifetime/longest.rs
+++ b/tests/rustdoc-json/lifetime/longest.rs
@@ -6,21 +6,21 @@
//@ count "$.index[*][?(@.name=='longest')].inner.function.generics.params[*]" 1
//@ is "$.index[*][?(@.name=='longest')].inner.function.generics.where_predicates" []
-//@ count "$.index[*][?(@.name=='longest')].inner.function.decl.inputs[*]" 2
-//@ is "$.index[*][?(@.name=='longest')].inner.function.decl.inputs[0][0]" '"l"'
-//@ is "$.index[*][?(@.name=='longest')].inner.function.decl.inputs[1][0]" '"r"'
+//@ count "$.index[*][?(@.name=='longest')].inner.function.sig.inputs[*]" 2
+//@ is "$.index[*][?(@.name=='longest')].inner.function.sig.inputs[0][0]" '"l"'
+//@ is "$.index[*][?(@.name=='longest')].inner.function.sig.inputs[1][0]" '"r"'
-//@ is "$.index[*][?(@.name=='longest')].inner.function.decl.inputs[0][1].borrowed_ref.lifetime" \"\'a\"
-//@ is "$.index[*][?(@.name=='longest')].inner.function.decl.inputs[0][1].borrowed_ref.mutable" false
-//@ is "$.index[*][?(@.name=='longest')].inner.function.decl.inputs[0][1].borrowed_ref.type.primitive" \"str\"
+//@ is "$.index[*][?(@.name=='longest')].inner.function.sig.inputs[0][1].borrowed_ref.lifetime" \"\'a\"
+//@ is "$.index[*][?(@.name=='longest')].inner.function.sig.inputs[0][1].borrowed_ref.is_mutable" false
+//@ is "$.index[*][?(@.name=='longest')].inner.function.sig.inputs[0][1].borrowed_ref.type.primitive" \"str\"
-//@ is "$.index[*][?(@.name=='longest')].inner.function.decl.inputs[1][1].borrowed_ref.lifetime" \"\'a\"
-//@ is "$.index[*][?(@.name=='longest')].inner.function.decl.inputs[1][1].borrowed_ref.mutable" false
-//@ is "$.index[*][?(@.name=='longest')].inner.function.decl.inputs[1][1].borrowed_ref.type.primitive" \"str\"
+//@ is "$.index[*][?(@.name=='longest')].inner.function.sig.inputs[1][1].borrowed_ref.lifetime" \"\'a\"
+//@ is "$.index[*][?(@.name=='longest')].inner.function.sig.inputs[1][1].borrowed_ref.is_mutable" false
+//@ is "$.index[*][?(@.name=='longest')].inner.function.sig.inputs[1][1].borrowed_ref.type.primitive" \"str\"
-//@ is "$.index[*][?(@.name=='longest')].inner.function.decl.output.borrowed_ref.lifetime" \"\'a\"
-//@ is "$.index[*][?(@.name=='longest')].inner.function.decl.output.borrowed_ref.mutable" false
-//@ is "$.index[*][?(@.name=='longest')].inner.function.decl.output.borrowed_ref.type.primitive" \"str\"
+//@ is "$.index[*][?(@.name=='longest')].inner.function.sig.output.borrowed_ref.lifetime" \"\'a\"
+//@ is "$.index[*][?(@.name=='longest')].inner.function.sig.output.borrowed_ref.is_mutable" false
+//@ is "$.index[*][?(@.name=='longest')].inner.function.sig.output.borrowed_ref.type.primitive" \"str\"
pub fn longest<'a>(l: &'a str, r: &'a str) -> &'a str {
if l.len() > r.len() { l } else { r }
diff --git a/tests/rustdoc-json/lifetime/outlives.rs b/tests/rustdoc-json/lifetime/outlives.rs
index c98555d..99d1429 100644
--- a/tests/rustdoc-json/lifetime/outlives.rs
+++ b/tests/rustdoc-json/lifetime/outlives.rs
@@ -10,9 +10,9 @@
//@ is "$.index[*][?(@.name=='foo')].inner.function.generics.params[2].kind.type.default" null
//@ count "$.index[*][?(@.name=='foo')].inner.function.generics.params[2].kind.type.bounds[*]" 1
//@ is "$.index[*][?(@.name=='foo')].inner.function.generics.params[2].kind.type.bounds[0].outlives" \"\'b\"
-//@ is "$.index[*][?(@.name=='foo')].inner.function.decl.inputs[0][1].borrowed_ref.lifetime" \"\'a\"
-//@ is "$.index[*][?(@.name=='foo')].inner.function.decl.inputs[0][1].borrowed_ref.mutable" false
-//@ is "$.index[*][?(@.name=='foo')].inner.function.decl.inputs[0][1].borrowed_ref.type.borrowed_ref.lifetime" \"\'b\"
-//@ is "$.index[*][?(@.name=='foo')].inner.function.decl.inputs[0][1].borrowed_ref.type.borrowed_ref.mutable" false
-//@ is "$.index[*][?(@.name=='foo')].inner.function.decl.inputs[0][1].borrowed_ref.type.borrowed_ref.type.generic" \"T\"
+//@ is "$.index[*][?(@.name=='foo')].inner.function.sig.inputs[0][1].borrowed_ref.lifetime" \"\'a\"
+//@ is "$.index[*][?(@.name=='foo')].inner.function.sig.inputs[0][1].borrowed_ref.is_mutable" false
+//@ is "$.index[*][?(@.name=='foo')].inner.function.sig.inputs[0][1].borrowed_ref.type.borrowed_ref.lifetime" \"\'b\"
+//@ is "$.index[*][?(@.name=='foo')].inner.function.sig.inputs[0][1].borrowed_ref.type.borrowed_ref.is_mutable" false
+//@ is "$.index[*][?(@.name=='foo')].inner.function.sig.inputs[0][1].borrowed_ref.type.borrowed_ref.type.generic" \"T\"
pub fn foo<'a, 'b: 'a, T: 'b>(_: &'a &'b T) {}
diff --git a/tests/rustdoc-json/methods/qualifiers.rs b/tests/rustdoc-json/methods/qualifiers.rs
index 8de8cfd..ba7c2e6 100644
--- a/tests/rustdoc-json/methods/qualifiers.rs
+++ b/tests/rustdoc-json/methods/qualifiers.rs
@@ -3,34 +3,34 @@
pub struct Foo;
impl Foo {
- //@ is "$.index[*][?(@.name=='const_meth')].inner.function.header.async" false
- //@ is "$.index[*][?(@.name=='const_meth')].inner.function.header.const" true
- //@ is "$.index[*][?(@.name=='const_meth')].inner.function.header.unsafe" false
+ //@ is "$.index[*][?(@.name=='const_meth')].inner.function.header.is_async" false
+ //@ is "$.index[*][?(@.name=='const_meth')].inner.function.header.is_const" true
+ //@ is "$.index[*][?(@.name=='const_meth')].inner.function.header.is_unsafe" false
pub const fn const_meth() {}
- //@ is "$.index[*][?(@.name=='nothing_meth')].inner.function.header.async" false
- //@ is "$.index[*][?(@.name=='nothing_meth')].inner.function.header.const" false
- //@ is "$.index[*][?(@.name=='nothing_meth')].inner.function.header.unsafe" false
+ //@ is "$.index[*][?(@.name=='nothing_meth')].inner.function.header.is_async" false
+ //@ is "$.index[*][?(@.name=='nothing_meth')].inner.function.header.is_const" false
+ //@ is "$.index[*][?(@.name=='nothing_meth')].inner.function.header.is_unsafe" false
pub fn nothing_meth() {}
- //@ is "$.index[*][?(@.name=='unsafe_meth')].inner.function.header.async" false
- //@ is "$.index[*][?(@.name=='unsafe_meth')].inner.function.header.const" false
- //@ is "$.index[*][?(@.name=='unsafe_meth')].inner.function.header.unsafe" true
+ //@ is "$.index[*][?(@.name=='unsafe_meth')].inner.function.header.is_async" false
+ //@ is "$.index[*][?(@.name=='unsafe_meth')].inner.function.header.is_const" false
+ //@ is "$.index[*][?(@.name=='unsafe_meth')].inner.function.header.is_unsafe" true
pub unsafe fn unsafe_meth() {}
- //@ is "$.index[*][?(@.name=='async_meth')].inner.function.header.async" true
- //@ is "$.index[*][?(@.name=='async_meth')].inner.function.header.const" false
- //@ is "$.index[*][?(@.name=='async_meth')].inner.function.header.unsafe" false
+ //@ is "$.index[*][?(@.name=='async_meth')].inner.function.header.is_async" true
+ //@ is "$.index[*][?(@.name=='async_meth')].inner.function.header.is_const" false
+ //@ is "$.index[*][?(@.name=='async_meth')].inner.function.header.is_unsafe" false
pub async fn async_meth() {}
- //@ is "$.index[*][?(@.name=='async_unsafe_meth')].inner.function.header.async" true
- //@ is "$.index[*][?(@.name=='async_unsafe_meth')].inner.function.header.const" false
- //@ is "$.index[*][?(@.name=='async_unsafe_meth')].inner.function.header.unsafe" true
+ //@ is "$.index[*][?(@.name=='async_unsafe_meth')].inner.function.header.is_async" true
+ //@ is "$.index[*][?(@.name=='async_unsafe_meth')].inner.function.header.is_const" false
+ //@ is "$.index[*][?(@.name=='async_unsafe_meth')].inner.function.header.is_unsafe" true
pub async unsafe fn async_unsafe_meth() {}
- //@ is "$.index[*][?(@.name=='const_unsafe_meth')].inner.function.header.async" false
- //@ is "$.index[*][?(@.name=='const_unsafe_meth')].inner.function.header.const" true
- //@ is "$.index[*][?(@.name=='const_unsafe_meth')].inner.function.header.unsafe" true
+ //@ is "$.index[*][?(@.name=='const_unsafe_meth')].inner.function.header.is_async" false
+ //@ is "$.index[*][?(@.name=='const_unsafe_meth')].inner.function.header.is_const" true
+ //@ is "$.index[*][?(@.name=='const_unsafe_meth')].inner.function.header.is_unsafe" true
pub const unsafe fn const_unsafe_meth() {}
// It's impossible for a method to be both const and async, so no test for that
diff --git a/tests/rustdoc-json/nested.rs b/tests/rustdoc-json/nested.rs
index ae2d9fe..10ec283 100644
--- a/tests/rustdoc-json/nested.rs
+++ b/tests/rustdoc-json/nested.rs
@@ -22,11 +22,11 @@ pub mod l3 {
//@ ismany "$.index[*][?(@.name=='l3')].inner.module.items[*]" $l4_id
pub struct L4;
}
- //@ is "$.index[*][?(@.inner.import)].inner.import.glob" false
- //@ is "$.index[*][?(@.inner.import)].inner.import.source" '"l3::L4"'
- //@ is "$.index[*][?(@.inner.import)].inner.import.glob" false
- //@ is "$.index[*][?(@.inner.import)].inner.import.id" $l4_id
- //@ set l4_use_id = "$.index[*][?(@.inner.import)].id"
+ //@ is "$.index[*][?(@.inner.use)].inner.use.is_glob" false
+ //@ is "$.index[*][?(@.inner.use)].inner.use.source" '"l3::L4"'
+ //@ is "$.index[*][?(@.inner.use)].inner.use.is_glob" false
+ //@ is "$.index[*][?(@.inner.use)].inner.use.id" $l4_id
+ //@ set l4_use_id = "$.index[*][?(@.inner.use)].id"
pub use l3::L4;
}
//@ ismany "$.index[*][?(@.name=='l1')].inner.module.items[*]" $l3_id $l4_use_id
diff --git a/tests/rustdoc-json/non_lifetime_binders.rs b/tests/rustdoc-json/non_lifetime_binders.rs
index 06f6e10..8443141 100644
--- a/tests/rustdoc-json/non_lifetime_binders.rs
+++ b/tests/rustdoc-json/non_lifetime_binders.rs
@@ -11,7 +11,7 @@ pub trait Trait {}
//@ is "$.index[*][?(@.name=='foo')].inner.function.generics.where_predicates[0].bound_predicate.generic_params[0].name" \"\'a\"
//@ is "$.index[*][?(@.name=='foo')].inner.function.generics.where_predicates[0].bound_predicate.generic_params[0].kind" '{ "lifetime": { "outlives": [] } }'
//@ is "$.index[*][?(@.name=='foo')].inner.function.generics.where_predicates[0].bound_predicate.generic_params[1].name" \"T\"
-//@ is "$.index[*][?(@.name=='foo')].inner.function.generics.where_predicates[0].bound_predicate.generic_params[1].kind" '{ "type": { "bounds": [], "default": null, "synthetic": false } }'
+//@ is "$.index[*][?(@.name=='foo')].inner.function.generics.where_predicates[0].bound_predicate.generic_params[1].kind" '{ "type": { "bounds": [], "default": null, "is_synthetic": false } }'
pub fn foo()
where
for<'a, T> &'a Wrapper<T>: Trait,
diff --git a/tests/rustdoc-json/primitives/use_primitive.rs b/tests/rustdoc-json/primitives/use_primitive.rs
index 27394a6..d4cdef8 100644
--- a/tests/rustdoc-json/primitives/use_primitive.rs
+++ b/tests/rustdoc-json/primitives/use_primitive.rs
@@ -13,7 +13,7 @@ mod usize {}
//@ !is "$.index[*][?(@.name=='checked_add')]" $local_crate_id
//@ !has "$.index[*][?(@.name=='is_ascii_uppercase')]"
-//@ is "$.index[*].inner.import[?(@.name=='my_i32')].id" null
+//@ is "$.index[*].inner.use[?(@.name=='my_i32')].id" null
pub use i32 as my_i32;
-//@ is "$.index[*].inner.import[?(@.name=='u32')].id" null
+//@ is "$.index[*].inner.use[?(@.name=='u32')].id" null
pub use u32;
diff --git a/tests/rustdoc-json/reexport/extern_crate_glob.rs b/tests/rustdoc-json/reexport/extern_crate_glob.rs
index a0b4cb8..dfe6e7a 100644
--- a/tests/rustdoc-json/reexport/extern_crate_glob.rs
+++ b/tests/rustdoc-json/reexport/extern_crate_glob.rs
@@ -6,6 +6,6 @@
pub use enum_with_discriminant::*;
//@ !has '$.index[*][?(@.docs == "Should not be inlined")]'
-//@ is '$.index[*][?(@.inner.import)].inner.import.name' \"enum_with_discriminant\"
-//@ set use = '$.index[*][?(@.inner.import)].id'
+//@ is '$.index[*][?(@.inner.use)].inner.use.name' \"enum_with_discriminant\"
+//@ set use = '$.index[*][?(@.inner.use)].id'
//@ is '$.index[*][?(@.name == "extern_crate_glob")].inner.module.items[*]' $use
diff --git a/tests/rustdoc-json/reexport/glob_collision.rs b/tests/rustdoc-json/reexport/glob_collision.rs
index 3a034af..8142c35 100644
--- a/tests/rustdoc-json/reexport/glob_collision.rs
+++ b/tests/rustdoc-json/reexport/glob_collision.rs
@@ -14,13 +14,13 @@ pub fn f(_: u8) {}
}
//@ set m1_use = "$.index[*][?(@.docs=='m1 re-export')].id"
-//@ is "$.index[*].inner.import[?(@.name=='m1')].id" $m1
-//@ is "$.index[*].inner.import[?(@.name=='m1')].glob" true
+//@ is "$.index[*].inner.use[?(@.name=='m1')].id" $m1
+//@ is "$.index[*].inner.use[?(@.name=='m1')].is_glob" true
/// m1 re-export
pub use m1::*;
//@ set m2_use = "$.index[*][?(@.docs=='m2 re-export')].id"
-//@ is "$.index[*].inner.import[?(@.name=='m2')].id" $m2
-//@ is "$.index[*].inner.import[?(@.name=='m2')].glob" true
+//@ is "$.index[*].inner.use[?(@.name=='m2')].id" $m2
+//@ is "$.index[*].inner.use[?(@.name=='m2')].is_glob" true
/// m2 re-export
pub use m2::*;
diff --git a/tests/rustdoc-json/reexport/glob_empty_mod.rs b/tests/rustdoc-json/reexport/glob_empty_mod.rs
index 326df5f..ee17794 100644
--- a/tests/rustdoc-json/reexport/glob_empty_mod.rs
+++ b/tests/rustdoc-json/reexport/glob_empty_mod.rs
@@ -4,5 +4,5 @@
//@ set m1 = "$.index[*][?(@.name=='m1')].id"
mod m1 {}
-//@ is "$.index[*][?(@.inner.import)].inner.import.id" $m1
+//@ is "$.index[*][?(@.inner.use)].inner.use.id" $m1
pub use m1::*;
diff --git a/tests/rustdoc-json/reexport/glob_extern.rs b/tests/rustdoc-json/reexport/glob_extern.rs
index ff5d986..98be477 100644
--- a/tests/rustdoc-json/reexport/glob_extern.rs
+++ b/tests/rustdoc-json/reexport/glob_extern.rs
@@ -12,8 +12,8 @@ mod mod1 {
//@ set mod1_id = "$.index[*][?(@.name=='mod1')].id"
}
-//@ is "$.index[*][?(@.inner.import)].inner.import.glob" true
-//@ is "$.index[*][?(@.inner.import)].inner.import.id" $mod1_id
-//@ set use_id = "$.index[*][?(@.inner.import)].id"
+//@ is "$.index[*][?(@.inner.use)].inner.use.is_glob" true
+//@ is "$.index[*][?(@.inner.use)].inner.use.id" $mod1_id
+//@ set use_id = "$.index[*][?(@.inner.use)].id"
//@ ismany "$.index[*][?(@.name=='glob_extern')].inner.module.items[*]" $use_id
pub use mod1::*;
diff --git a/tests/rustdoc-json/reexport/glob_private.rs b/tests/rustdoc-json/reexport/glob_private.rs
index 0a88910..2084ffc 100644
--- a/tests/rustdoc-json/reexport/glob_private.rs
+++ b/tests/rustdoc-json/reexport/glob_private.rs
@@ -12,7 +12,7 @@ mod mod2 {
}
//@ set mod2_use_id = "$.index[*][?(@.docs=='Mod2 re-export')].id"
- //@ is "$.index[*][?(@.docs=='Mod2 re-export')].inner.import.name" \"mod2\"
+ //@ is "$.index[*][?(@.docs=='Mod2 re-export')].inner.use.name" \"mod2\"
/// Mod2 re-export
pub use self::mod2::*;
@@ -23,7 +23,7 @@ mod mod2 {
}
//@ set mod1_use_id = "$.index[*][?(@.docs=='Mod1 re-export')].id"
-//@ is "$.index[*][?(@.docs=='Mod1 re-export')].inner.import.name" \"mod1\"
+//@ is "$.index[*][?(@.docs=='Mod1 re-export')].inner.use.name" \"mod1\"
/// Mod1 re-export
pub use mod1::*;
diff --git a/tests/rustdoc-json/reexport/in_root_and_mod.rs b/tests/rustdoc-json/reexport/in_root_and_mod.rs
index f94e416..a1d2080 100644
--- a/tests/rustdoc-json/reexport/in_root_and_mod.rs
+++ b/tests/rustdoc-json/reexport/in_root_and_mod.rs
@@ -4,10 +4,10 @@ mod foo {
pub struct Foo;
}
-//@ has "$.index[*].inner[?(@.import.source=='foo::Foo')]"
+//@ has "$.index[*].inner[?(@.use.source=='foo::Foo')]"
pub use foo::Foo;
pub mod bar {
- //@ has "$.index[*].inner[?(@.import.source=='crate::foo::Foo')]"
+ //@ has "$.index[*].inner[?(@.use.source=='crate::foo::Foo')]"
pub use crate::foo::Foo;
}
diff --git a/tests/rustdoc-json/reexport/in_root_and_mod_pub.rs b/tests/rustdoc-json/reexport/in_root_and_mod_pub.rs
index 13dee32..7d26d2a 100644
--- a/tests/rustdoc-json/reexport/in_root_and_mod_pub.rs
+++ b/tests/rustdoc-json/reexport/in_root_and_mod_pub.rs
@@ -5,14 +5,14 @@
}
//@ set root_import_id = "$.index[*][?(@.docs=='Outer re-export')].id"
-//@ is "$.index[*].inner[?(@.import.source=='foo::Bar')].import.id" $bar_id
+//@ is "$.index[*].inner[?(@.use.source=='foo::Bar')].use.id" $bar_id
//@ has "$.index[*][?(@.name=='in_root_and_mod_pub')].inner.module.items[*]" $root_import_id
/// Outer re-export
pub use foo::Bar;
pub mod baz {
//@ set baz_import_id = "$.index[*][?(@.docs=='Inner re-export')].id"
- //@ is "$.index[*].inner[?(@.import.source=='crate::foo::Bar')].import.id" $bar_id
+ //@ is "$.index[*].inner[?(@.use.source=='crate::foo::Bar')].use.id" $bar_id
//@ ismany "$.index[*][?(@.name=='baz')].inner.module.items[*]" $baz_import_id
/// Inner re-export
pub use crate::foo::Bar;
diff --git a/tests/rustdoc-json/reexport/mod_not_included.rs b/tests/rustdoc-json/reexport/mod_not_included.rs
index 7e0c011..d0ce957 100644
--- a/tests/rustdoc-json/reexport/mod_not_included.rs
+++ b/tests/rustdoc-json/reexport/mod_not_included.rs
@@ -7,5 +7,5 @@ pub fn x() {}
pub use m1::x;
//@ has "$.index[*][?(@.name=='x' && @.inner.function)]"
-//@ has "$.index[*].inner[?(@.import.name=='x')].import.source" '"m1::x"'
+//@ has "$.index[*].inner[?(@.use.name=='x')].use.source" '"m1::x"'
//@ !has "$.index[*][?(@.name=='m1')]"
diff --git a/tests/rustdoc-json/reexport/private_twice_one_inline.rs b/tests/rustdoc-json/reexport/private_twice_one_inline.rs
index be66ad5..87b97e6 100644
--- a/tests/rustdoc-json/reexport/private_twice_one_inline.rs
+++ b/tests/rustdoc-json/reexport/private_twice_one_inline.rs
@@ -7,18 +7,18 @@
extern crate pub_struct as foo;
#[doc(inline)]
//@ set crate_use_id = "$.index[*][?(@.docs=='Hack A')].id"
-//@ set foo_id = "$.index[*][?(@.docs=='Hack A')].inner.import.id"
+//@ set foo_id = "$.index[*][?(@.docs=='Hack A')].inner.use.id"
/// Hack A
pub use foo::Foo;
//@ set bar_id = "$.index[*][?(@.name=='bar')].id"
pub mod bar {
- //@ is "$.index[*][?(@.docs=='Hack B')].inner.import.id" $foo_id
+ //@ is "$.index[*][?(@.docs=='Hack B')].inner.use.id" $foo_id
//@ set bar_use_id = "$.index[*][?(@.docs=='Hack B')].id"
//@ ismany "$.index[*][?(@.name=='bar')].inner.module.items[*]" $bar_use_id
/// Hack B
pub use foo::Foo;
}
-//@ ismany "$.index[*][?(@.inner.import)].id" $crate_use_id $bar_use_id
+//@ ismany "$.index[*][?(@.inner.use)].id" $crate_use_id $bar_use_id
//@ ismany "$.index[*][?(@.name=='private_twice_one_inline')].inner.module.items[*]" $bar_id $crate_use_id
diff --git a/tests/rustdoc-json/reexport/private_two_names.rs b/tests/rustdoc-json/reexport/private_two_names.rs
index 1e5466d..1ed54f1 100644
--- a/tests/rustdoc-json/reexport/private_two_names.rs
+++ b/tests/rustdoc-json/reexport/private_two_names.rs
@@ -9,13 +9,13 @@ mod style {
pub struct Color;
}
-//@ is "$.index[*][?(@.docs=='First re-export')].inner.import.id" $color_struct_id
-//@ is "$.index[*][?(@.docs=='First re-export')].inner.import.name" \"Color\"
+//@ is "$.index[*][?(@.docs=='First re-export')].inner.use.id" $color_struct_id
+//@ is "$.index[*][?(@.docs=='First re-export')].inner.use.name" \"Color\"
//@ set color_export_id = "$.index[*][?(@.docs=='First re-export')].id"
/// First re-export
pub use style::Color;
-//@ is "$.index[*][?(@.docs=='Second re-export')].inner.import.id" $color_struct_id
-//@ is "$.index[*][?(@.docs=='Second re-export')].inner.import.name" \"Colour\"
+//@ is "$.index[*][?(@.docs=='Second re-export')].inner.use.id" $color_struct_id
+//@ is "$.index[*][?(@.docs=='Second re-export')].inner.use.name" \"Colour\"
//@ set colour_export_id = "$.index[*][?(@.docs=='Second re-export')].id"
/// Second re-export
pub use style::Color as Colour;
diff --git a/tests/rustdoc-json/reexport/reexport_of_hidden.rs b/tests/rustdoc-json/reexport/reexport_of_hidden.rs
index 07ce1f5..80f171d 100644
--- a/tests/rustdoc-json/reexport/reexport_of_hidden.rs
+++ b/tests/rustdoc-json/reexport/reexport_of_hidden.rs
@@ -1,6 +1,6 @@
//@ compile-flags: --document-hidden-items
-//@ has "$.index[*].inner[?(@.import.name=='UsedHidden')]"
+//@ has "$.index[*].inner[?(@.use.name=='UsedHidden')]"
//@ has "$.index[*][?(@.name=='Hidden')]"
pub mod submodule {
#[doc(hidden)]
diff --git a/tests/rustdoc-json/reexport/rename_private.rs b/tests/rustdoc-json/reexport/rename_private.rs
index 3335d18..3f13f30 100644
--- a/tests/rustdoc-json/reexport/rename_private.rs
+++ b/tests/rustdoc-json/reexport/rename_private.rs
@@ -6,5 +6,5 @@ mod inner {
pub struct Public;
}
-//@ is "$.index[*][?(@.inner.import)].inner.import.name" \"NewName\"
+//@ is "$.index[*][?(@.inner.use)].inner.use.name" \"NewName\"
pub use inner::Public as NewName;
diff --git a/tests/rustdoc-json/reexport/rename_public.rs b/tests/rustdoc-json/reexport/rename_public.rs
index e534f45..81c003a 100644
--- a/tests/rustdoc-json/reexport/rename_public.rs
+++ b/tests/rustdoc-json/reexport/rename_public.rs
@@ -7,8 +7,8 @@ pub mod inner {
pub struct Public;
}
//@ set import_id = "$.index[*][?(@.docs=='Re-export')].id"
-//@ !has "$.index[*].inner[?(@.import.name=='Public')]"
-//@ is "$.index[*].inner[?(@.import.name=='NewName')].import.source" \"inner::Public\"
+//@ !has "$.index[*].inner[?(@.use.name=='Public')]"
+//@ is "$.index[*].inner[?(@.use.name=='NewName')].use.source" \"inner::Public\"
/// Re-export
pub use inner::Public as NewName;
diff --git a/tests/rustdoc-json/reexport/same_name_different_types.rs b/tests/rustdoc-json/reexport/same_name_different_types.rs
index b0a06d4..e9bc4a5a 100644
--- a/tests/rustdoc-json/reexport/same_name_different_types.rs
+++ b/tests/rustdoc-json/reexport/same_name_different_types.rs
@@ -13,10 +13,10 @@ pub struct Foo {}
pub fn Foo() {}
}
-//@ ismany "$.index[*].inner[?(@.import.name == 'Foo')].import.id" $foo_fn $foo_struct
-//@ ismany "$.index[*].inner[?(@.import.name == 'Bar')].import.id" $foo_fn $foo_struct
+//@ ismany "$.index[*].inner[?(@.use.name == 'Foo')].use.id" $foo_fn $foo_struct
+//@ ismany "$.index[*].inner[?(@.use.name == 'Bar')].use.id" $foo_fn $foo_struct
-//@ count "$.index[*].inner[?(@.import.name == 'Foo')]" 2
+//@ count "$.index[*].inner[?(@.use.name == 'Foo')]" 2
pub use nested::Foo;
-//@ count "$.index[*].inner[?(@.import.name == 'Bar')]" 2
+//@ count "$.index[*].inner[?(@.use.name == 'Bar')]" 2
pub use Foo as Bar;
diff --git a/tests/rustdoc-json/reexport/same_type_reexported_more_than_once.rs b/tests/rustdoc-json/reexport/same_type_reexported_more_than_once.rs
index c533b9b..27e2827 100644
--- a/tests/rustdoc-json/reexport/same_type_reexported_more_than_once.rs
+++ b/tests/rustdoc-json/reexport/same_type_reexported_more_than_once.rs
@@ -10,11 +10,11 @@ pub trait Trait {}
}
//@ set export_id = "$.index[*][?(@.docs=='First re-export')].id"
-//@ is "$.index[*].inner[?(@.import.name=='Trait')].import.id" $trait_id
+//@ is "$.index[*].inner[?(@.use.name=='Trait')].use.id" $trait_id
/// First re-export
pub use inner::Trait;
//@ set reexport_id = "$.index[*][?(@.docs=='Second re-export')].id"
-//@ is "$.index[*].inner[?(@.import.name=='Reexport')].import.id" $trait_id
+//@ is "$.index[*].inner[?(@.use.name=='Reexport')].use.id" $trait_id
/// Second re-export
pub use inner::Trait as Reexport;
diff --git a/tests/rustdoc-json/reexport/simple_private.rs b/tests/rustdoc-json/reexport/simple_private.rs
index 9af01578..8a936f5 100644
--- a/tests/rustdoc-json/reexport/simple_private.rs
+++ b/tests/rustdoc-json/reexport/simple_private.rs
@@ -6,9 +6,9 @@ mod inner {
pub struct Public;
}
-//@ is "$.index[*][?(@.inner.import)].inner.import.name" \"Public\"
-//@ is "$.index[*][?(@.inner.import)].inner.import.id" $pub_id
-//@ set use_id = "$.index[*][?(@.inner.import)].id"
+//@ is "$.index[*][?(@.inner.use)].inner.use.name" \"Public\"
+//@ is "$.index[*][?(@.inner.use)].inner.use.id" $pub_id
+//@ set use_id = "$.index[*][?(@.inner.use)].id"
pub use inner::Public;
//@ ismany "$.index[*][?(@.name=='simple_private')].inner.module.items[*]" $use_id
diff --git a/tests/rustdoc-json/reexport/simple_public.rs b/tests/rustdoc-json/reexport/simple_public.rs
index d7b44b2..e5a8dc7 100644
--- a/tests/rustdoc-json/reexport/simple_public.rs
+++ b/tests/rustdoc-json/reexport/simple_public.rs
@@ -9,7 +9,7 @@ pub mod inner {
}
//@ set import_id = "$.index[*][?(@.docs=='Outer')].id"
-//@ is "$.index[*][?(@.docs=='Outer')].inner.import.source" \"inner::Public\"
+//@ is "$.index[*][?(@.docs=='Outer')].inner.use.source" \"inner::Public\"
/// Outer
pub use inner::Public;
diff --git a/tests/rustdoc-json/return_private.rs b/tests/rustdoc-json/return_private.rs
index 4a1922e..0b341e2 100644
--- a/tests/rustdoc-json/return_private.rs
+++ b/tests/rustdoc-json/return_private.rs
@@ -6,7 +6,7 @@ mod secret {
}
//@ has "$.index[*][?(@.name=='get_secret')].inner.function"
-//@ is "$.index[*][?(@.name=='get_secret')].inner.function.decl.output.resolved_path.name" \"secret::Secret\"
+//@ is "$.index[*][?(@.name=='get_secret')].inner.function.sig.output.resolved_path.name" \"secret::Secret\"
pub fn get_secret() -> secret::Secret {
secret::Secret
}
diff --git a/tests/rustdoc-json/structs/plain_all_pub.rs b/tests/rustdoc-json/structs/plain_all_pub.rs
index aa53b59..67d2a4a 100644
--- a/tests/rustdoc-json/structs/plain_all_pub.rs
+++ b/tests/rustdoc-json/structs/plain_all_pub.rs
@@ -8,4 +8,4 @@
//@ is "$.index[*][?(@.name=='Demo')].inner.struct.kind.plain.fields[0]" $x
//@ is "$.index[*][?(@.name=='Demo')].inner.struct.kind.plain.fields[1]" $y
//@ count "$.index[*][?(@.name=='Demo')].inner.struct.kind.plain.fields[*]" 2
-//@ is "$.index[*][?(@.name=='Demo')].inner.struct.kind.plain.fields_stripped" false
+//@ is "$.index[*][?(@.name=='Demo')].inner.struct.kind.plain.has_stripped_fields" false
diff --git a/tests/rustdoc-json/structs/plain_doc_hidden.rs b/tests/rustdoc-json/structs/plain_doc_hidden.rs
index 39f9367..4573adc 100644
--- a/tests/rustdoc-json/structs/plain_doc_hidden.rs
+++ b/tests/rustdoc-json/structs/plain_doc_hidden.rs
@@ -8,4 +8,4 @@
//@ !has "$.index[*][?(@.name=='y')].id"
//@ is "$.index[*][?(@.name=='Demo')].inner.struct.kind.plain.fields[0]" $x
//@ count "$.index[*][?(@.name=='Demo')].inner.struct.kind.plain.fields[*]" 1
-//@ is "$.index[*][?(@.name=='Demo')].inner.struct.kind.plain.fields_stripped" true
+//@ is "$.index[*][?(@.name=='Demo')].inner.struct.kind.plain.has_stripped_fields" true
diff --git a/tests/rustdoc-json/structs/plain_empty.rs b/tests/rustdoc-json/structs/plain_empty.rs
index 00b4b05..3001302 100644
--- a/tests/rustdoc-json/structs/plain_empty.rs
+++ b/tests/rustdoc-json/structs/plain_empty.rs
@@ -1,5 +1,5 @@
//@ is "$.index[*][?(@.name=='PlainEmpty')].visibility" \"public\"
//@ has "$.index[*][?(@.name=='PlainEmpty')].inner.struct"
-//@ is "$.index[*][?(@.name=='PlainEmpty')].inner.struct.kind.plain.fields_stripped" false
+//@ is "$.index[*][?(@.name=='PlainEmpty')].inner.struct.kind.plain.has_stripped_fields" false
//@ is "$.index[*][?(@.name=='PlainEmpty')].inner.struct.kind.plain.fields" []
pub struct PlainEmpty {}
diff --git a/tests/rustdoc-json/structs/plain_pub_priv.rs b/tests/rustdoc-json/structs/plain_pub_priv.rs
index f9ab871..91079a3 100644
--- a/tests/rustdoc-json/structs/plain_pub_priv.rs
+++ b/tests/rustdoc-json/structs/plain_pub_priv.rs
@@ -6,4 +6,4 @@
//@ set x = "$.index[*][?(@.name=='x')].id"
//@ is "$.index[*][?(@.name=='Demo')].inner.struct.kind.plain.fields[0]" $x
//@ count "$.index[*][?(@.name=='Demo')].inner.struct.kind.plain.fields[*]" 1
-//@ is "$.index[*][?(@.name=='Demo')].inner.struct.kind.plain.fields_stripped" true
+//@ is "$.index[*][?(@.name=='Demo')].inner.struct.kind.plain.has_stripped_fields" true
diff --git a/tests/rustdoc-json/structs/with_generics.rs b/tests/rustdoc-json/structs/with_generics.rs
index 6e13dae..3e7f175 100644
--- a/tests/rustdoc-json/structs/with_generics.rs
+++ b/tests/rustdoc-json/structs/with_generics.rs
@@ -6,7 +6,7 @@
//@ is "$.index[*][?(@.name=='WithGenerics')].inner.struct.generics.params[0].kind.type.bounds" []
//@ is "$.index[*][?(@.name=='WithGenerics')].inner.struct.generics.params[1].name" \"U\"
//@ is "$.index[*][?(@.name=='WithGenerics')].inner.struct.generics.params[1].kind.type.bounds" []
-//@ is "$.index[*][?(@.name=='WithGenerics')].inner.struct.kind.plain.fields_stripped" true
+//@ is "$.index[*][?(@.name=='WithGenerics')].inner.struct.kind.plain.has_stripped_fields" true
//@ is "$.index[*][?(@.name=='WithGenerics')].inner.struct.kind.plain.fields" []
pub struct WithGenerics<T, U> {
stuff: Vec<T>,
diff --git a/tests/rustdoc-json/structs/with_primitives.rs b/tests/rustdoc-json/structs/with_primitives.rs
index 2ca11b5..7202ab9 100644
--- a/tests/rustdoc-json/structs/with_primitives.rs
+++ b/tests/rustdoc-json/structs/with_primitives.rs
@@ -4,7 +4,7 @@
//@ has "$.index[*][?(@.name=='WithPrimitives')].inner.struct"
//@ is "$.index[*][?(@.name=='WithPrimitives')].inner.struct.generics.params[0].name" \"\'a\"
//@ is "$.index[*][?(@.name=='WithPrimitives')].inner.struct.generics.params[0].kind.lifetime.outlives" []
-//@ is "$.index[*][?(@.name=='WithPrimitives')].inner.struct.kind.plain.fields_stripped" true
+//@ is "$.index[*][?(@.name=='WithPrimitives')].inner.struct.kind.plain.has_stripped_fields" true
//@ is "$.index[*][?(@.name=='WithPrimitives')].inner.struct.kind.plain.fields" []
pub struct WithPrimitives<'a> {
num: u32,
diff --git a/tests/rustdoc-json/trait_alias.rs b/tests/rustdoc-json/trait_alias.rs
index ca9e5ed..3ae5fad 100644
--- a/tests/rustdoc-json/trait_alias.rs
+++ b/tests/rustdoc-json/trait_alias.rs
@@ -7,12 +7,12 @@
//@ is "$.index[*][?(@.name=='StrLike')].span.filename" $FILE
pub trait StrLike = AsRef<str>;
-//@ is "$.index[*][?(@.name=='f')].inner.function.decl.output.impl_trait[0].trait_bound.trait.id" $StrLike
+//@ is "$.index[*][?(@.name=='f')].inner.function.sig.output.impl_trait[0].trait_bound.trait.id" $StrLike
pub fn f() -> impl StrLike {
"heya"
}
-//@ !is "$.index[*][?(@.name=='g')].inner.function.decl.output.impl_trait[0].trait_bound.trait.id" $StrLike
+//@ !is "$.index[*][?(@.name=='g')].inner.function.sig.output.impl_trait[0].trait_bound.trait.id" $StrLike
pub fn g() -> impl AsRef<str> {
"heya"
}
diff --git a/tests/rustdoc-json/traits/self.rs b/tests/rustdoc-json/traits/self.rs
index c7d952a..060bc37 100644
--- a/tests/rustdoc-json/traits/self.rs
+++ b/tests/rustdoc-json/traits/self.rs
@@ -9,29 +9,29 @@
// Each assertion matches 3 times, and should be the same each time.
impl Foo {
- //@ ismany '$.index[*][?(@.name=="by_ref")].inner.function.decl.inputs[0][0]' '"self"' '"self"' '"self"'
- //@ ismany '$.index[*][?(@.name=="by_ref")].inner.function.decl.inputs[0][1].borrowed_ref.type.generic' '"Self"' '"Self"' '"Self"'
- //@ ismany '$.index[*][?(@.name=="by_ref")].inner.function.decl.inputs[0][1].borrowed_ref.lifetime' null null null
- //@ ismany '$.index[*][?(@.name=="by_ref")].inner.function.decl.inputs[0][1].borrowed_ref.mutable' false false false
+ //@ ismany '$.index[*][?(@.name=="by_ref")].inner.function.sig.inputs[0][0]' '"self"' '"self"' '"self"'
+ //@ ismany '$.index[*][?(@.name=="by_ref")].inner.function.sig.inputs[0][1].borrowed_ref.type.generic' '"Self"' '"Self"' '"Self"'
+ //@ ismany '$.index[*][?(@.name=="by_ref")].inner.function.sig.inputs[0][1].borrowed_ref.lifetime' null null null
+ //@ ismany '$.index[*][?(@.name=="by_ref")].inner.function.sig.inputs[0][1].borrowed_ref.is_mutable' false false false
pub fn by_ref(&self) {}
- //@ ismany '$.index[*][?(@.name=="by_exclusive_ref")].inner.function.decl.inputs[0][0]' '"self"' '"self"' '"self"'
- //@ ismany '$.index[*][?(@.name=="by_exclusive_ref")].inner.function.decl.inputs[0][1].borrowed_ref.type.generic' '"Self"' '"Self"' '"Self"'
- //@ ismany '$.index[*][?(@.name=="by_exclusive_ref")].inner.function.decl.inputs[0][1].borrowed_ref.lifetime' null null null
- //@ ismany '$.index[*][?(@.name=="by_exclusive_ref")].inner.function.decl.inputs[0][1].borrowed_ref.mutable' true true true
+ //@ ismany '$.index[*][?(@.name=="by_exclusive_ref")].inner.function.sig.inputs[0][0]' '"self"' '"self"' '"self"'
+ //@ ismany '$.index[*][?(@.name=="by_exclusive_ref")].inner.function.sig.inputs[0][1].borrowed_ref.type.generic' '"Self"' '"Self"' '"Self"'
+ //@ ismany '$.index[*][?(@.name=="by_exclusive_ref")].inner.function.sig.inputs[0][1].borrowed_ref.lifetime' null null null
+ //@ ismany '$.index[*][?(@.name=="by_exclusive_ref")].inner.function.sig.inputs[0][1].borrowed_ref.is_mutable' true true true
pub fn by_exclusive_ref(&mut self) {}
- //@ ismany '$.index[*][?(@.name=="by_value")].inner.function.decl.inputs[0][0]' '"self"' '"self"' '"self"'
- //@ ismany '$.index[*][?(@.name=="by_value")].inner.function.decl.inputs[0][1].generic' '"Self"' '"Self"' '"Self"'
+ //@ ismany '$.index[*][?(@.name=="by_value")].inner.function.sig.inputs[0][0]' '"self"' '"self"' '"self"'
+ //@ ismany '$.index[*][?(@.name=="by_value")].inner.function.sig.inputs[0][1].generic' '"Self"' '"Self"' '"Self"'
pub fn by_value(self) {}
- //@ ismany '$.index[*][?(@.name=="with_lifetime")].inner.function.decl.inputs[0][0]' '"self"' '"self"' '"self"'
- //@ ismany '$.index[*][?(@.name=="with_lifetime")].inner.function.decl.inputs[0][1].borrowed_ref.type.generic' '"Self"' '"Self"' '"Self"'
- //@ ismany '$.index[*][?(@.name=="with_lifetime")].inner.function.decl.inputs[0][1].borrowed_ref.lifetime' \"\'a\" \"\'a\" \"\'a\"
- //@ ismany '$.index[*][?(@.name=="with_lifetime")].inner.function.decl.inputs[0][1].borrowed_ref.mutable' false false false
+ //@ ismany '$.index[*][?(@.name=="with_lifetime")].inner.function.sig.inputs[0][0]' '"self"' '"self"' '"self"'
+ //@ ismany '$.index[*][?(@.name=="with_lifetime")].inner.function.sig.inputs[0][1].borrowed_ref.type.generic' '"Self"' '"Self"' '"Self"'
+ //@ ismany '$.index[*][?(@.name=="with_lifetime")].inner.function.sig.inputs[0][1].borrowed_ref.lifetime' \"\'a\" \"\'a\" \"\'a\"
+ //@ ismany '$.index[*][?(@.name=="with_lifetime")].inner.function.sig.inputs[0][1].borrowed_ref.is_mutable' false false false
pub fn with_lifetime<'a>(&'a self) {}
- //@ ismany '$.index[*][?(@.name=="build")].inner.function.decl.output.generic' '"Self"' '"Self"' '"Self"'
+ //@ ismany '$.index[*][?(@.name=="build")].inner.function.sig.output.generic' '"Self"' '"Self"' '"Self"'
pub fn build() -> Self {
Self
}
diff --git a/tests/rustdoc-json/traits/trait_alias.rs b/tests/rustdoc-json/traits/trait_alias.rs
index a1ab039..17c83dd 100644
--- a/tests/rustdoc-json/traits/trait_alias.rs
+++ b/tests/rustdoc-json/traits/trait_alias.rs
@@ -19,8 +19,8 @@ pub trait Orig<T> {}
impl Orig<i32> for Struct {}
-//@ has "$.index[*][?(@.name=='takes_alias')].inner.function.decl.inputs[0][1].impl_trait"
-//@ is "$.index[*][?(@.name=='takes_alias')].inner.function.decl.inputs[0][1].impl_trait[0].trait_bound.trait.id" $Alias
+//@ has "$.index[*][?(@.name=='takes_alias')].inner.function.sig.inputs[0][1].impl_trait"
+//@ is "$.index[*][?(@.name=='takes_alias')].inner.function.sig.inputs[0][1].impl_trait[0].trait_bound.trait.id" $Alias
//@ is "$.index[*][?(@.name=='takes_alias')].inner.function.generics.params[0].kind.type.bounds[0].trait_bound.trait.id" $Alias
pub fn takes_alias(_: impl Alias) {}
// FIXME: Should the trait be mentioned in both the decl and generics?
diff --git a/tests/rustdoc-json/type/dyn.rs b/tests/rustdoc-json/type/dyn.rs
index 86ea1c2..97c8689 100644
--- a/tests/rustdoc-json/type/dyn.rs
+++ b/tests/rustdoc-json/type/dyn.rs
@@ -11,7 +11,7 @@
//@ is "$.index[*][?(@.name=='SyncIntGen')].inner.type_alias.generics" '{"params": [], "where_predicates": []}'
//@ has "$.index[*][?(@.name=='SyncIntGen')].inner.type_alias.type.resolved_path"
//@ is "$.index[*][?(@.name=='SyncIntGen')].inner.type_alias.type.resolved_path.name" \"Box\"
-//@ is "$.index[*][?(@.name=='SyncIntGen')].inner.type_alias.type.resolved_path.args.angle_bracketed.bindings" []
+//@ is "$.index[*][?(@.name=='SyncIntGen')].inner.type_alias.type.resolved_path.args.angle_bracketed.constraints" []
//@ count "$.index[*][?(@.name=='SyncIntGen')].inner.type_alias.type.resolved_path.args.angle_bracketed.args" 1
//@ has "$.index[*][?(@.name=='SyncIntGen')].inner.type_alias.type.resolved_path.args.angle_bracketed.args[0].type.dyn_trait"
//@ is "$.index[*][?(@.name=='SyncIntGen')].inner.type_alias.type.resolved_path.args.angle_bracketed.args[0].type.dyn_trait.lifetime" \"\'static\"
@@ -28,7 +28,7 @@
//@ has "$.index[*][?(@.name=='RefFn')].inner.type_alias"
//@ is "$.index[*][?(@.name=='RefFn')].inner.type_alias.generics" '{"params": [{"kind": {"lifetime": {"outlives": []}},"name": "'\''a"}],"where_predicates": []}'
//@ has "$.index[*][?(@.name=='RefFn')].inner.type_alias.type.borrowed_ref"
-//@ is "$.index[*][?(@.name=='RefFn')].inner.type_alias.type.borrowed_ref.mutable" 'false'
+//@ is "$.index[*][?(@.name=='RefFn')].inner.type_alias.type.borrowed_ref.is_mutable" 'false'
//@ is "$.index[*][?(@.name=='RefFn')].inner.type_alias.type.borrowed_ref.lifetime" "\"'a\""
//@ has "$.index[*][?(@.name=='RefFn')].inner.type_alias.type.borrowed_ref.type.dyn_trait"
//@ is "$.index[*][?(@.name=='RefFn')].inner.type_alias.type.borrowed_ref.type.dyn_trait.lifetime" null
diff --git a/tests/rustdoc-json/type/extern.rs b/tests/rustdoc-json/type/extern.rs
index fda5d5a..97e1c37 100644
--- a/tests/rustdoc-json/type/extern.rs
+++ b/tests/rustdoc-json/type/extern.rs
@@ -6,4 +6,4 @@
}
//@ is "$.index[*][?(@.docs=='No inner information')].name" '"Foo"'
-//@ is "$.index[*][?(@.docs=='No inner information')].inner" \"foreign_type\"
+//@ is "$.index[*][?(@.docs=='No inner information')].inner" \"extern_type\"
diff --git a/tests/rustdoc-json/type/fn_lifetime.rs b/tests/rustdoc-json/type/fn_lifetime.rs
index 2893b37..7fa12da 100644
--- a/tests/rustdoc-json/type/fn_lifetime.rs
+++ b/tests/rustdoc-json/type/fn_lifetime.rs
@@ -7,9 +7,9 @@
//@ count "$.index[*][?(@.name=='GenericFn')].inner.type_alias.generics.params[*].kind.lifetime.outlives[*]" 0
//@ count "$.index[*][?(@.name=='GenericFn')].inner.type_alias.generics.where_predicates[*]" 0
//@ count "$.index[*][?(@.name=='GenericFn')].inner.type_alias.type.function_pointer.generic_params[*]" 0
-//@ count "$.index[*][?(@.name=='GenericFn')].inner.type_alias.type.function_pointer.decl.inputs[*]" 1
-//@ is "$.index[*][?(@.name=='GenericFn')].inner.type_alias.type.function_pointer.decl.inputs[*][1].borrowed_ref.lifetime" \"\'a\"
-//@ is "$.index[*][?(@.name=='GenericFn')].inner.type_alias.type.function_pointer.decl.output.borrowed_ref.lifetime" \"\'a\"
+//@ count "$.index[*][?(@.name=='GenericFn')].inner.type_alias.type.function_pointer.sig.inputs[*]" 1
+//@ is "$.index[*][?(@.name=='GenericFn')].inner.type_alias.type.function_pointer.sig.inputs[*][1].borrowed_ref.lifetime" \"\'a\"
+//@ is "$.index[*][?(@.name=='GenericFn')].inner.type_alias.type.function_pointer.sig.output.borrowed_ref.lifetime" \"\'a\"
pub type GenericFn<'a> = fn(&'a i32) -> &'a i32;
@@ -20,7 +20,7 @@
//@ is "$.index[*][?(@.name=='ForAll')].inner.type_alias.type.function_pointer.generic_params[*].name" \"\'a\"
//@ has "$.index[*][?(@.name=='ForAll')].inner.type_alias.type.function_pointer.generic_params[*].kind.lifetime"
//@ count "$.index[*][?(@.name=='ForAll')].inner.type_alias.type.function_pointer.generic_params[*].kind.lifetime.outlives[*]" 0
-//@ count "$.index[*][?(@.name=='ForAll')].inner.type_alias.type.function_pointer.decl.inputs[*]" 1
-//@ is "$.index[*][?(@.name=='ForAll')].inner.type_alias.type.function_pointer.decl.inputs[*][1].borrowed_ref.lifetime" \"\'a\"
-//@ is "$.index[*][?(@.name=='ForAll')].inner.type_alias.type.function_pointer.decl.output.borrowed_ref.lifetime" \"\'a\"
+//@ count "$.index[*][?(@.name=='ForAll')].inner.type_alias.type.function_pointer.sig.inputs[*]" 1
+//@ is "$.index[*][?(@.name=='ForAll')].inner.type_alias.type.function_pointer.sig.inputs[*][1].borrowed_ref.lifetime" \"\'a\"
+//@ is "$.index[*][?(@.name=='ForAll')].inner.type_alias.type.function_pointer.sig.output.borrowed_ref.lifetime" \"\'a\"
pub type ForAll = for<'a> fn(&'a i32) -> &'a i32;
diff --git a/tests/rustdoc-json/type/generic_default.rs b/tests/rustdoc-json/type/generic_default.rs
index 3063763..c1a0580 100644
--- a/tests/rustdoc-json/type/generic_default.rs
+++ b/tests/rustdoc-json/type/generic_default.rs
@@ -25,7 +25,7 @@ pub struct MyError {}
//@ has "$.index[*][?(@.name=='MyResult')].inner.type_alias.type.resolved_path"
//@ is "$.index[*][?(@.name=='MyResult')].inner.type_alias.type.resolved_path.id" $result
//@ is "$.index[*][?(@.name=='MyResult')].inner.type_alias.type.resolved_path.name" \"Result\"
-//@ is "$.index[*][?(@.name=='MyResult')].inner.type_alias.type.resolved_path.args.angle_bracketed.bindings" []
+//@ is "$.index[*][?(@.name=='MyResult')].inner.type_alias.type.resolved_path.args.angle_bracketed.constraints" []
//@ has "$.index[*][?(@.name=='MyResult')].inner.type_alias.type.resolved_path.args.angle_bracketed.args[0].type.generic"
//@ has "$.index[*][?(@.name=='MyResult')].inner.type_alias.type.resolved_path.args.angle_bracketed.args[1].type.generic"
//@ is "$.index[*][?(@.name=='MyResult')].inner.type_alias.type.resolved_path.args.angle_bracketed.args[0].type.generic" \"T\"
diff --git a/tests/rustdoc-json/type/hrtb.rs b/tests/rustdoc-json/type/hrtb.rs
index a28b2fd..825720e 100644
--- a/tests/rustdoc-json/type/hrtb.rs
+++ b/tests/rustdoc-json/type/hrtb.rs
@@ -12,10 +12,10 @@ pub fn genfn<F>(f: F)
//@ is "$.index[*][?(@.name=='dynfn')].inner.function.generics" '{"params": [], "where_predicates": []}'
//@ is "$.index[*][?(@.name=='dynfn')].inner.function.generics" '{"params": [], "where_predicates": []}'
-//@ is "$.index[*][?(@.name=='dynfn')].inner.function.decl.inputs[0][1].borrowed_ref.type.dyn_trait.lifetime" null
-//@ count "$.index[*][?(@.name=='dynfn')].inner.function.decl.inputs[0][1].borrowed_ref.type.dyn_trait.traits[*]" 1
-//@ is "$.index[*][?(@.name=='dynfn')].inner.function.decl.inputs[0][1].borrowed_ref.type.dyn_trait.traits[0].generic_params" '[{"kind": {"lifetime": {"outlives": []}},"name": "'\''a"},{"kind": {"lifetime": {"outlives": []}},"name": "'\''b"}]'
-//@ is "$.index[*][?(@.name=='dynfn')].inner.function.decl.inputs[0][1].borrowed_ref.type.dyn_trait.traits[0].trait.name" '"Fn"'
+//@ is "$.index[*][?(@.name=='dynfn')].inner.function.sig.inputs[0][1].borrowed_ref.type.dyn_trait.lifetime" null
+//@ count "$.index[*][?(@.name=='dynfn')].inner.function.sig.inputs[0][1].borrowed_ref.type.dyn_trait.traits[*]" 1
+//@ is "$.index[*][?(@.name=='dynfn')].inner.function.sig.inputs[0][1].borrowed_ref.type.dyn_trait.traits[0].generic_params" '[{"kind": {"lifetime": {"outlives": []}},"name": "'\''a"},{"kind": {"lifetime": {"outlives": []}},"name": "'\''b"}]'
+//@ is "$.index[*][?(@.name=='dynfn')].inner.function.sig.inputs[0][1].borrowed_ref.type.dyn_trait.traits[0].trait.name" '"Fn"'
pub fn dynfn(f: &dyn for<'a, 'b> Fn(&'a i32, &'b i32)) {
let zero = 0;
f(&zero, &zero);
diff --git a/tests/rustdoc-json/type/inherent_associated_type.rs b/tests/rustdoc-json/type/inherent_associated_type.rs
index 386c7c8..b8ce11f 100644
--- a/tests/rustdoc-json/type/inherent_associated_type.rs
+++ b/tests/rustdoc-json/type/inherent_associated_type.rs
@@ -10,9 +10,9 @@
pub fn create() -> Owner::Metadata {
OwnerMetadata
}
-//@ is '$.index[*][?(@.name=="create")].inner.function.decl.output.qualified_path.name' '"Metadata"'
-//@ is '$.index[*][?(@.name=="create")].inner.function.decl.output.qualified_path.trait' null
-//@ is '$.index[*][?(@.name=="create")].inner.function.decl.output.qualified_path.self_type.resolved_path.id' $Owner
+//@ is '$.index[*][?(@.name=="create")].inner.function.sig.output.qualified_path.name' '"Metadata"'
+//@ is '$.index[*][?(@.name=="create")].inner.function.sig.output.qualified_path.trait' null
+//@ is '$.index[*][?(@.name=="create")].inner.function.sig.output.qualified_path.self_type.resolved_path.id' $Owner
/// impl
impl Owner {
@@ -21,4 +21,4 @@ impl Owner {
}
//@ set iat = '$.index[*][?(@.docs=="iat")].id'
//@ is '$.index[*][?(@.docs=="impl")].inner.impl.items[*]' $iat
-//@ is '$.index[*][?(@.docs=="iat")].inner.assoc_type.default.resolved_path.id' $OwnerMetadata
+//@ is '$.index[*][?(@.docs=="iat")].inner.assoc_type.type.resolved_path.id' $OwnerMetadata
diff --git a/tests/rustdoc-json/type/inherent_associated_type_bound.rs b/tests/rustdoc-json/type/inherent_associated_type_bound.rs
index 45fe19b..d0a88b1 100644
--- a/tests/rustdoc-json/type/inherent_associated_type_bound.rs
+++ b/tests/rustdoc-json/type/inherent_associated_type_bound.rs
@@ -5,14 +5,14 @@
//@ set Carrier = '$.index[*][?(@.name=="Carrier")].id'
pub struct Carrier<'a>(&'a ());
-//@ count "$.index[*][?(@.name=='user')].inner.function.decl.inputs[*]" 1
-//@ is "$.index[*][?(@.name=='user')].inner.function.decl.inputs[0][0]" '"_"'
-//@ is '$.index[*][?(@.name=="user")].inner.function.decl.inputs[0][1].function_pointer.generic_params[*].name' \""'b"\"
-//@ is '$.index[*][?(@.name=="user")].inner.function.decl.inputs[0][1].function_pointer.decl.inputs[0][1].qualified_path.self_type.resolved_path.id' $Carrier
-//@ is '$.index[*][?(@.name=="user")].inner.function.decl.inputs[0][1].function_pointer.decl.inputs[0][1].qualified_path.self_type.resolved_path.args.angle_bracketed.args[0].lifetime' \""'b"\"
-//@ is '$.index[*][?(@.name=="user")].inner.function.decl.inputs[0][1].function_pointer.decl.inputs[0][1].qualified_path.name' '"Focus"'
-//@ is '$.index[*][?(@.name=="user")].inner.function.decl.inputs[0][1].function_pointer.decl.inputs[0][1].qualified_path.trait' null
-//@ is '$.index[*][?(@.name=="user")].inner.function.decl.inputs[0][1].function_pointer.decl.inputs[0][1].qualified_path.args.angle_bracketed.args[0].type.primitive' '"i32"'
+//@ count "$.index[*][?(@.name=='user')].inner.function.sig.inputs[*]" 1
+//@ is "$.index[*][?(@.name=='user')].inner.function.sig.inputs[0][0]" '"_"'
+//@ is '$.index[*][?(@.name=="user")].inner.function.sig.inputs[0][1].function_pointer.generic_params[*].name' \""'b"\"
+//@ is '$.index[*][?(@.name=="user")].inner.function.sig.inputs[0][1].function_pointer.sig.inputs[0][1].qualified_path.self_type.resolved_path.id' $Carrier
+//@ is '$.index[*][?(@.name=="user")].inner.function.sig.inputs[0][1].function_pointer.sig.inputs[0][1].qualified_path.self_type.resolved_path.args.angle_bracketed.args[0].lifetime' \""'b"\"
+//@ is '$.index[*][?(@.name=="user")].inner.function.sig.inputs[0][1].function_pointer.sig.inputs[0][1].qualified_path.name' '"Focus"'
+//@ is '$.index[*][?(@.name=="user")].inner.function.sig.inputs[0][1].function_pointer.sig.inputs[0][1].qualified_path.trait' null
+//@ is '$.index[*][?(@.name=="user")].inner.function.sig.inputs[0][1].function_pointer.sig.inputs[0][1].qualified_path.args.angle_bracketed.args[0].type.primitive' '"i32"'
pub fn user(_: for<'b> fn(Carrier<'b>::Focus<i32>)) {}
impl<'a> Carrier<'a> {
diff --git a/tests/rustdoc-json/type/inherent_associated_type_projections.rs b/tests/rustdoc-json/type/inherent_associated_type_projections.rs
index 9b827a9..e73e86d 100644
--- a/tests/rustdoc-json/type/inherent_associated_type_projections.rs
+++ b/tests/rustdoc-json/type/inherent_associated_type_projections.rs
@@ -5,12 +5,12 @@
//@ set Parametrized = '$.index[*][?(@.name=="Parametrized")].id'
pub struct Parametrized<T>(T);
-//@ count "$.index[*][?(@.name=='test')].inner.function.decl.inputs[*]" 1
-//@ is "$.index[*][?(@.name=='test')].inner.function.decl.inputs[0][0]" '"_"'
-//@ is '$.index[*][?(@.name=="test")].inner.function.decl.inputs[0][1].qualified_path.self_type.resolved_path.id' $Parametrized
-//@ is '$.index[*][?(@.name=="test")].inner.function.decl.inputs[0][1].qualified_path.self_type.resolved_path.args.angle_bracketed.args[0].type.primitive' \"i32\"
-//@ is '$.index[*][?(@.name=="test")].inner.function.decl.inputs[0][1].qualified_path.name' '"Proj"'
-//@ is '$.index[*][?(@.name=="test")].inner.function.decl.inputs[0][1].qualified_path.trait' null
+//@ count "$.index[*][?(@.name=='test')].inner.function.sig.inputs[*]" 1
+//@ is "$.index[*][?(@.name=='test')].inner.function.sig.inputs[0][0]" '"_"'
+//@ is '$.index[*][?(@.name=="test")].inner.function.sig.inputs[0][1].qualified_path.self_type.resolved_path.id' $Parametrized
+//@ is '$.index[*][?(@.name=="test")].inner.function.sig.inputs[0][1].qualified_path.self_type.resolved_path.args.angle_bracketed.args[0].type.primitive' \"i32\"
+//@ is '$.index[*][?(@.name=="test")].inner.function.sig.inputs[0][1].qualified_path.name' '"Proj"'
+//@ is '$.index[*][?(@.name=="test")].inner.function.sig.inputs[0][1].qualified_path.trait' null
pub fn test(_: Parametrized<i32>::Proj) {}
/// param_bool
diff --git a/tests/rustdoc-json/type_alias.rs b/tests/rustdoc-json/type_alias.rs
index ecf35c5..2f2b4c4 100644
--- a/tests/rustdoc-json/type_alias.rs
+++ b/tests/rustdoc-json/type_alias.rs
@@ -4,12 +4,12 @@
//@ is "$.index[*][?(@.name=='IntVec')].span.filename" $FILE
pub type IntVec = Vec<u32>;
-//@ is "$.index[*][?(@.name=='f')].inner.function.decl.output.resolved_path.id" $IntVec
+//@ is "$.index[*][?(@.name=='f')].inner.function.sig.output.resolved_path.id" $IntVec
pub fn f() -> IntVec {
vec![0; 32]
}
-//@ !is "$.index[*][?(@.name=='g')].inner.function.decl.output.resolved_path.id" $IntVec
+//@ !is "$.index[*][?(@.name=='g')].inner.function.sig.output.resolved_path.id" $IntVec
pub fn g() -> Vec<u32> {
vec![0; 32]
}
diff --git a/tests/rustdoc-json/unions/union.rs b/tests/rustdoc-json/unions/union.rs
index 4a97b5d..7f135a7 100644
--- a/tests/rustdoc-json/unions/union.rs
+++ b/tests/rustdoc-json/unions/union.rs
@@ -7,8 +7,8 @@ pub union Union {
float: f32,
}
-//@ has "$.index[*][?(@.name=='make_int_union')].inner.function.decl.output.resolved_path"
-//@ is "$.index[*][?(@.name=='make_int_union')].inner.function.decl.output.resolved_path.id" $Union
+//@ has "$.index[*][?(@.name=='make_int_union')].inner.function.sig.output.resolved_path"
+//@ is "$.index[*][?(@.name=='make_int_union')].inner.function.sig.output.resolved_path.id" $Union
pub fn make_int_union(int: i32) -> Union {
Union { int }
}
diff --git a/tests/rustdoc/impl-associated-items-order.rs b/tests/rustdoc/impl-associated-items-order.rs
new file mode 100644
index 0000000..759e0f0
--- /dev/null
+++ b/tests/rustdoc/impl-associated-items-order.rs
@@ -0,0 +1,42 @@
+// This test ensures that impl associated items always follow this order:
+//
+// 1. Consts
+// 2. Types
+// 3. Functions
+
+#![feature(inherent_associated_types)]
+#![allow(incomplete_features)]
+#![crate_name = "foo"]
+
+//@ has 'foo/struct.Bar.html'
+pub struct Bar;
+
+impl Bar {
+ //@ has - '//*[@id="implementations-list"]//*[@class="impl-items"]/section[3]/h4' \
+ // 'pub fn foo()'
+ pub fn foo() {}
+ //@ has - '//*[@id="implementations-list"]//*[@class="impl-items"]/section[1]/h4' \
+ // 'pub const X: u8 = 12u8'
+ pub const X: u8 = 12;
+ //@ has - '//*[@id="implementations-list"]//*[@class="impl-items"]/section[2]/h4' \
+ // 'pub type Y = u8'
+ pub type Y = u8;
+}
+
+pub trait Foo {
+ const W: u32;
+ fn yeay();
+ type Z;
+}
+
+impl Foo for Bar {
+ //@ has - '//*[@id="trait-implementations-list"]//*[@class="impl-items"]/section[2]/h4' \
+ // 'type Z = u8'
+ type Z = u8;
+ //@ has - '//*[@id="trait-implementations-list"]//*[@class="impl-items"]/section[1]/h4' \
+ // 'const W: u32 = 12u32'
+ const W: u32 = 12;
+ //@ has - '//*[@id="trait-implementations-list"]//*[@class="impl-items"]/section[3]/h4' \
+ // 'fn yeay()'
+ fn yeay() {}
+}
diff --git a/tests/rustdoc/impl-associated-items-sidebar.rs b/tests/rustdoc/impl-associated-items-sidebar.rs
new file mode 100644
index 0000000..d393a57
--- /dev/null
+++ b/tests/rustdoc/impl-associated-items-sidebar.rs
@@ -0,0 +1,42 @@
+// This test ensures that impl/trait associated items are listed in the sidebar.
+
+// ignore-tidy-linelength
+
+#![feature(inherent_associated_types)]
+#![feature(associated_type_defaults)]
+#![allow(incomplete_features)]
+#![crate_name = "foo"]
+
+//@ has 'foo/struct.Bar.html'
+pub struct Bar;
+
+impl Bar {
+ //@ has - '//*[@class="sidebar-elems"]//h3[1]' 'Associated Constants'
+ //@ has - '//*[@class="sidebar-elems"]//ul[@class="block associatedconstant"]/li/a[@href="#associatedconstant.X"]' 'X'
+ pub const X: u8 = 12;
+ //@ has - '//*[@class="sidebar-elems"]//h3[2]' 'Associated Types'
+ //@ has - '//*[@class="sidebar-elems"]//ul[@class="block associatedtype"]/li/a[@href="#associatedtype.Y"]' 'Y'
+ pub type Y = u8;
+}
+
+//@ has 'foo/trait.Foo.html'
+pub trait Foo {
+ //@ has - '//*[@class="sidebar-elems"]//h3[5]' 'Required Methods'
+ //@ has - '//*[@class="sidebar-elems"]//ul[@class="block"][5]/li/a[@href="#tymethod.yeay"]' 'yeay'
+ fn yeay();
+ //@ has - '//*[@class="sidebar-elems"]//h3[6]' 'Provided Methods'
+ //@ has - '//*[@class="sidebar-elems"]//ul[@class="block"][6]/li/a[@href="#method.boo"]' 'boo'
+ fn boo() {}
+ //@ has - '//*[@class="sidebar-elems"]//h3[1]' 'Required Associated Constants'
+ //@ has - '//*[@class="sidebar-elems"]//ul[@class="block"][1]/li/a[@href="#associatedconstant.W"]' 'W'
+ const W: u32;
+ //@ has - '//*[@class="sidebar-elems"]//h3[2]' 'Provided Associated Constants'
+ //@ has - '//*[@class="sidebar-elems"]//ul[@class="block"][2]/li/a[@href="#associatedconstant.U"]' 'U'
+ const U: u32 = 0;
+ //@ has - '//*[@class="sidebar-elems"]//h3[3]' 'Required Associated Types'
+ //@ has - '//*[@class="sidebar-elems"]//ul[@class="block"][3]/li/a[@href="#associatedtype.Z"]' 'Z'
+ type Z;
+ //@ has - '//*[@class="sidebar-elems"]//h3[4]' 'Provided Associated Types'
+ //@ has - '//*[@class="sidebar-elems"]//ul[@class="block"][4]/li/a[@href="#associatedtype.T"]' 'T'
+ type T = u32;
+}
diff --git a/tests/rustdoc/merge-cross-crate-info/cargo-transitive-read-write/auxiliary/quebec.rs b/tests/rustdoc/merge-cross-crate-info/cargo-transitive-read-write/auxiliary/quebec.rs
new file mode 100644
index 0000000..fdafb3b
--- /dev/null
+++ b/tests/rustdoc/merge-cross-crate-info/cargo-transitive-read-write/auxiliary/quebec.rs
@@ -0,0 +1,5 @@
+//@ doc-flags:--merge=shared
+//@ doc-flags:--enable-index-page
+//@ doc-flags:-Zunstable-options
+
+pub struct Quebec;
diff --git a/tests/rustdoc/merge-cross-crate-info/cargo-transitive-read-write/auxiliary/tango.rs b/tests/rustdoc/merge-cross-crate-info/cargo-transitive-read-write/auxiliary/tango.rs
new file mode 100644
index 0000000..ff12fe9
--- /dev/null
+++ b/tests/rustdoc/merge-cross-crate-info/cargo-transitive-read-write/auxiliary/tango.rs
@@ -0,0 +1,8 @@
+//@ aux-build:quebec.rs
+//@ build-aux-docs
+//@ doc-flags:--merge=shared
+//@ doc-flags:--enable-index-page
+//@ doc-flags:-Zunstable-options
+
+extern crate quebec;
+pub trait Tango {}
diff --git a/tests/rustdoc/merge-cross-crate-info/cargo-transitive-read-write/sierra.rs b/tests/rustdoc/merge-cross-crate-info/cargo-transitive-read-write/sierra.rs
new file mode 100644
index 0000000..665f956
--- /dev/null
+++ b/tests/rustdoc/merge-cross-crate-info/cargo-transitive-read-write/sierra.rs
@@ -0,0 +1,25 @@
+//@ aux-build:tango.rs
+//@ build-aux-docs
+//@ doc-flags:--merge=shared
+//@ doc-flags:--enable-index-page
+//@ doc-flags:-Zunstable-options
+
+//@ has index.html
+//@ has index.html '//h1' 'List of all crates'
+//@ has index.html '//ul[@class="all-items"]//a[@href="quebec/index.html"]' 'quebec'
+//@ has index.html '//ul[@class="all-items"]//a[@href="sierra/index.html"]' 'sierra'
+//@ has index.html '//ul[@class="all-items"]//a[@href="tango/index.html"]' 'tango'
+//@ has quebec/struct.Quebec.html
+//@ has sierra/struct.Sierra.html
+//@ has tango/trait.Tango.html
+//@ hasraw sierra/struct.Sierra.html 'Tango'
+//@ hasraw trait.impl/tango/trait.Tango.js 'struct.Sierra.html'
+//@ hasraw search-index.js 'Tango'
+//@ hasraw search-index.js 'Sierra'
+//@ hasraw search-index.js 'Quebec'
+
+// similar to cargo-workflow-transitive, but we use --merge=read-write,
+// which is the default.
+extern crate tango;
+pub struct Sierra;
+impl tango::Tango for Sierra {}
diff --git a/tests/rustdoc/merge-cross-crate-info/kitchen-sink-separate-dirs/auxiliary/quebec.rs b/tests/rustdoc/merge-cross-crate-info/kitchen-sink-separate-dirs/auxiliary/quebec.rs
new file mode 100644
index 0000000..d10bc03
--- /dev/null
+++ b/tests/rustdoc/merge-cross-crate-info/kitchen-sink-separate-dirs/auxiliary/quebec.rs
@@ -0,0 +1,7 @@
+//@ unique-doc-out-dir
+//@ doc-flags:--merge=none
+//@ doc-flags:--parts-out-dir=info/doc.parts/quebec
+//@ doc-flags:--enable-index-page
+//@ doc-flags:-Zunstable-options
+
+pub struct Quebec;
diff --git a/tests/rustdoc/merge-cross-crate-info/kitchen-sink-separate-dirs/auxiliary/romeo.rs b/tests/rustdoc/merge-cross-crate-info/kitchen-sink-separate-dirs/auxiliary/romeo.rs
new file mode 100644
index 0000000..6d0c865
--- /dev/null
+++ b/tests/rustdoc/merge-cross-crate-info/kitchen-sink-separate-dirs/auxiliary/romeo.rs
@@ -0,0 +1,10 @@
+//@ aux-build:sierra.rs
+//@ build-aux-docs
+//@ unique-doc-out-dir
+//@ doc-flags:--merge=none
+//@ doc-flags:--parts-out-dir=info/doc.parts/romeo
+//@ doc-flags:--enable-index-page
+//@ doc-flags:-Zunstable-options
+
+extern crate sierra;
+pub type Romeo = sierra::Sierra;
diff --git a/tests/rustdoc/merge-cross-crate-info/kitchen-sink-separate-dirs/auxiliary/sierra.rs b/tests/rustdoc/merge-cross-crate-info/kitchen-sink-separate-dirs/auxiliary/sierra.rs
new file mode 100644
index 0000000..10898f3
--- /dev/null
+++ b/tests/rustdoc/merge-cross-crate-info/kitchen-sink-separate-dirs/auxiliary/sierra.rs
@@ -0,0 +1,11 @@
+//@ aux-build:tango.rs
+//@ build-aux-docs
+//@ unique-doc-out-dir
+//@ doc-flags:--merge=none
+//@ doc-flags:--parts-out-dir=info/doc.parts/sierra
+//@ doc-flags:--enable-index-page
+//@ doc-flags:-Zunstable-options
+
+extern crate tango;
+pub struct Sierra;
+impl tango::Tango for Sierra {}
diff --git a/tests/rustdoc/merge-cross-crate-info/kitchen-sink-separate-dirs/auxiliary/tango.rs b/tests/rustdoc/merge-cross-crate-info/kitchen-sink-separate-dirs/auxiliary/tango.rs
new file mode 100644
index 0000000..3c3721e
--- /dev/null
+++ b/tests/rustdoc/merge-cross-crate-info/kitchen-sink-separate-dirs/auxiliary/tango.rs
@@ -0,0 +1,10 @@
+//@ aux-build:quebec.rs
+//@ build-aux-docs
+//@ unique-doc-out-dir
+//@ doc-flags:--merge=none
+//@ doc-flags:--parts-out-dir=info/doc.parts/tango
+//@ doc-flags:--enable-index-page
+//@ doc-flags:-Zunstable-options
+
+extern crate quebec;
+pub trait Tango {}
diff --git a/tests/rustdoc/merge-cross-crate-info/kitchen-sink-separate-dirs/indigo.rs b/tests/rustdoc/merge-cross-crate-info/kitchen-sink-separate-dirs/indigo.rs
new file mode 100644
index 0000000..f03f6bd
--- /dev/null
+++ b/tests/rustdoc/merge-cross-crate-info/kitchen-sink-separate-dirs/indigo.rs
@@ -0,0 +1,35 @@
+//@ aux-build:tango.rs
+//@ aux-build:romeo.rs
+//@ aux-build:quebec.rs
+//@ aux-build:sierra.rs
+//@ build-aux-docs
+//@ doc-flags:--merge=finalize
+//@ doc-flags:--include-parts-dir=info/doc.parts/tango
+//@ doc-flags:--include-parts-dir=info/doc.parts/romeo
+//@ doc-flags:--include-parts-dir=info/doc.parts/quebec
+//@ doc-flags:--include-parts-dir=info/doc.parts/sierra
+//@ doc-flags:--enable-index-page
+//@ doc-flags:-Zunstable-options
+
+//@ has index.html '//h1' 'List of all crates'
+//@ has index.html
+//@ has index.html '//ul[@class="all-items"]//a[@href="indigo/index.html"]' 'indigo'
+//@ has index.html '//ul[@class="all-items"]//a[@href="quebec/index.html"]' 'quebec'
+//@ has index.html '//ul[@class="all-items"]//a[@href="romeo/index.html"]' 'romeo'
+//@ has index.html '//ul[@class="all-items"]//a[@href="sierra/index.html"]' 'sierra'
+//@ has index.html '//ul[@class="all-items"]//a[@href="tango/index.html"]' 'tango'
+//@ !has quebec/struct.Quebec.html
+//@ !has romeo/type.Romeo.html
+//@ !has sierra/struct.Sierra.html
+//@ !has tango/trait.Tango.html
+//@ hasraw trait.impl/tango/trait.Tango.js 'struct.Sierra.html'
+//@ hasraw search-index.js 'Quebec'
+//@ hasraw search-index.js 'Romeo'
+//@ hasraw search-index.js 'Sierra'
+//@ hasraw search-index.js 'Tango'
+//@ has type.impl/sierra/struct.Sierra.js
+//@ hasraw type.impl/sierra/struct.Sierra.js 'Tango'
+//@ hasraw type.impl/sierra/struct.Sierra.js 'Romeo'
+
+// document everything in the default mode, there are separate out
+// directories that are linked together
diff --git a/tests/rustdoc/merge-cross-crate-info/no-merge-separate/auxiliary/quebec.rs b/tests/rustdoc/merge-cross-crate-info/no-merge-separate/auxiliary/quebec.rs
new file mode 100644
index 0000000..6121052
--- /dev/null
+++ b/tests/rustdoc/merge-cross-crate-info/no-merge-separate/auxiliary/quebec.rs
@@ -0,0 +1,6 @@
+//@ unique-doc-out-dir
+//@ doc-flags:--merge=none
+//@ doc-flags:--enable-index-page
+//@ doc-flags:-Zunstable-options
+
+pub struct Quebec;
diff --git a/tests/rustdoc/merge-cross-crate-info/no-merge-separate/auxiliary/tango.rs b/tests/rustdoc/merge-cross-crate-info/no-merge-separate/auxiliary/tango.rs
new file mode 100644
index 0000000..70d8a4b
--- /dev/null
+++ b/tests/rustdoc/merge-cross-crate-info/no-merge-separate/auxiliary/tango.rs
@@ -0,0 +1,9 @@
+//@ aux-build:quebec.rs
+//@ build-aux-docs
+//@ unique-doc-out-dir
+//@ doc-flags:--merge=none
+//@ doc-flags:--enable-index-page
+//@ doc-flags:-Zunstable-options
+
+extern crate quebec;
+pub trait Tango {}
diff --git a/tests/rustdoc/merge-cross-crate-info/no-merge-separate/sierra.rs b/tests/rustdoc/merge-cross-crate-info/no-merge-separate/sierra.rs
new file mode 100644
index 0000000..7eac207
--- /dev/null
+++ b/tests/rustdoc/merge-cross-crate-info/no-merge-separate/sierra.rs
@@ -0,0 +1,17 @@
+//@ aux-build:tango.rs
+//@ build-aux-docs
+//@ doc-flags:--merge=none
+//@ doc-flags:--enable-index-page
+//@ doc-flags:-Zunstable-options
+
+//@ !has index.html
+//@ has sierra/struct.Sierra.html
+//@ hasraw sierra/struct.Sierra.html 'Tango'
+//@ !has trait.impl/tango/trait.Tango.js
+//@ !has search-index.js
+
+// we don't generate any cross-crate info if --merge=none, even if we
+// document crates separately
+extern crate tango;
+pub struct Sierra;
+impl tango::Tango for Sierra {}
diff --git a/tests/rustdoc/merge-cross-crate-info/no-merge-write-anyway/auxiliary/quebec.rs b/tests/rustdoc/merge-cross-crate-info/no-merge-write-anyway/auxiliary/quebec.rs
new file mode 100644
index 0000000..6ab9215
--- /dev/null
+++ b/tests/rustdoc/merge-cross-crate-info/no-merge-write-anyway/auxiliary/quebec.rs
@@ -0,0 +1,6 @@
+//@ doc-flags:--merge=none
+//@ doc-flags:--parts-out-dir=info/doc.parts/quebec
+//@ doc-flags:--enable-index-page
+//@ doc-flags:-Zunstable-options
+
+pub struct Quebec;
diff --git a/tests/rustdoc/merge-cross-crate-info/no-merge-write-anyway/auxiliary/tango.rs b/tests/rustdoc/merge-cross-crate-info/no-merge-write-anyway/auxiliary/tango.rs
new file mode 100644
index 0000000..9fa99d3
--- /dev/null
+++ b/tests/rustdoc/merge-cross-crate-info/no-merge-write-anyway/auxiliary/tango.rs
@@ -0,0 +1,9 @@
+//@ aux-build:quebec.rs
+//@ build-aux-docs
+//@ doc-flags:--merge=none
+//@ doc-flags:--parts-out-dir=info/doc.parts/tango
+//@ doc-flags:--enable-index-page
+//@ doc-flags:-Zunstable-options
+
+extern crate quebec;
+pub trait Tango {}
diff --git a/tests/rustdoc/merge-cross-crate-info/no-merge-write-anyway/sierra.rs b/tests/rustdoc/merge-cross-crate-info/no-merge-write-anyway/sierra.rs
new file mode 100644
index 0000000..f3340a8
--- /dev/null
+++ b/tests/rustdoc/merge-cross-crate-info/no-merge-write-anyway/sierra.rs
@@ -0,0 +1,18 @@
+//@ aux-build:tango.rs
+//@ build-aux-docs
+//@ doc-flags:--merge=none
+//@ doc-flags:--parts-out-dir=info/doc.parts/sierra
+//@ doc-flags:--enable-index-page
+//@ doc-flags:-Zunstable-options
+
+//@ !has index.html
+//@ has sierra/struct.Sierra.html
+//@ has tango/trait.Tango.html
+//@ hasraw sierra/struct.Sierra.html 'Tango'
+//@ !has trait.impl/tango/trait.Tango.js
+//@ !has search-index.js
+
+// we --merge=none, so --parts-out-dir doesn't do anything
+extern crate tango;
+pub struct Sierra;
+impl tango::Tango for Sierra {}
diff --git a/tests/rustdoc/merge-cross-crate-info/overwrite-but-include/auxiliary/quebec.rs b/tests/rustdoc/merge-cross-crate-info/overwrite-but-include/auxiliary/quebec.rs
new file mode 100644
index 0000000..6ab9215
--- /dev/null
+++ b/tests/rustdoc/merge-cross-crate-info/overwrite-but-include/auxiliary/quebec.rs
@@ -0,0 +1,6 @@
+//@ doc-flags:--merge=none
+//@ doc-flags:--parts-out-dir=info/doc.parts/quebec
+//@ doc-flags:--enable-index-page
+//@ doc-flags:-Zunstable-options
+
+pub struct Quebec;
diff --git a/tests/rustdoc/merge-cross-crate-info/overwrite-but-include/auxiliary/tango.rs b/tests/rustdoc/merge-cross-crate-info/overwrite-but-include/auxiliary/tango.rs
new file mode 100644
index 0000000..9fa99d3
--- /dev/null
+++ b/tests/rustdoc/merge-cross-crate-info/overwrite-but-include/auxiliary/tango.rs
@@ -0,0 +1,9 @@
+//@ aux-build:quebec.rs
+//@ build-aux-docs
+//@ doc-flags:--merge=none
+//@ doc-flags:--parts-out-dir=info/doc.parts/tango
+//@ doc-flags:--enable-index-page
+//@ doc-flags:-Zunstable-options
+
+extern crate quebec;
+pub trait Tango {}
diff --git a/tests/rustdoc/merge-cross-crate-info/overwrite-but-include/sierra.rs b/tests/rustdoc/merge-cross-crate-info/overwrite-but-include/sierra.rs
new file mode 100644
index 0000000..8eb0f1d
--- /dev/null
+++ b/tests/rustdoc/merge-cross-crate-info/overwrite-but-include/sierra.rs
@@ -0,0 +1,22 @@
+//@ aux-build:tango.rs
+//@ build-aux-docs
+//@ doc-flags:--merge=finalize
+//@ doc-flags:--include-parts-dir=info/doc.parts/tango
+//@ doc-flags:--enable-index-page
+//@ doc-flags:-Zunstable-options
+
+//@ has quebec/struct.Quebec.html
+//@ has sierra/struct.Sierra.html
+//@ has tango/trait.Tango.html
+//@ hasraw sierra/struct.Sierra.html 'Tango'
+//@ hasraw trait.impl/tango/trait.Tango.js 'struct.Sierra.html'
+//@ hasraw search-index.js 'Tango'
+//@ hasraw search-index.js 'Sierra'
+//@ !hasraw search-index.js 'Quebec'
+
+// we overwrite quebec and tango's cross-crate information, but we
+// include the info from tango meaning that it should appear in the out
+// dir
+extern crate tango;
+pub struct Sierra;
+impl tango::Tango for Sierra {}
diff --git a/tests/rustdoc/merge-cross-crate-info/overwrite-but-separate/auxiliary/quebec.rs b/tests/rustdoc/merge-cross-crate-info/overwrite-but-separate/auxiliary/quebec.rs
new file mode 100644
index 0000000..d10bc03
--- /dev/null
+++ b/tests/rustdoc/merge-cross-crate-info/overwrite-but-separate/auxiliary/quebec.rs
@@ -0,0 +1,7 @@
+//@ unique-doc-out-dir
+//@ doc-flags:--merge=none
+//@ doc-flags:--parts-out-dir=info/doc.parts/quebec
+//@ doc-flags:--enable-index-page
+//@ doc-flags:-Zunstable-options
+
+pub struct Quebec;
diff --git a/tests/rustdoc/merge-cross-crate-info/overwrite-but-separate/auxiliary/tango.rs b/tests/rustdoc/merge-cross-crate-info/overwrite-but-separate/auxiliary/tango.rs
new file mode 100644
index 0000000..3c3721e
--- /dev/null
+++ b/tests/rustdoc/merge-cross-crate-info/overwrite-but-separate/auxiliary/tango.rs
@@ -0,0 +1,10 @@
+//@ aux-build:quebec.rs
+//@ build-aux-docs
+//@ unique-doc-out-dir
+//@ doc-flags:--merge=none
+//@ doc-flags:--parts-out-dir=info/doc.parts/tango
+//@ doc-flags:--enable-index-page
+//@ doc-flags:-Zunstable-options
+
+extern crate quebec;
+pub trait Tango {}
diff --git a/tests/rustdoc/merge-cross-crate-info/overwrite-but-separate/sierra.rs b/tests/rustdoc/merge-cross-crate-info/overwrite-but-separate/sierra.rs
new file mode 100644
index 0000000..4ee0362
--- /dev/null
+++ b/tests/rustdoc/merge-cross-crate-info/overwrite-but-separate/sierra.rs
@@ -0,0 +1,25 @@
+//@ aux-build:tango.rs
+//@ build-aux-docs
+//@ doc-flags:--merge=finalize
+//@ doc-flags:--include-parts-dir=info/doc.parts/tango
+//@ doc-flags:--include-parts-dir=info/doc.parts/quebec
+//@ doc-flags:--enable-index-page
+//@ doc-flags:-Zunstable-options
+
+//@ has index.html
+//@ has index.html '//h1' 'List of all crates'
+//@ has index.html '//ul[@class="all-items"]//a[@href="quebec/index.html"]' 'quebec'
+//@ has index.html '//ul[@class="all-items"]//a[@href="sierra/index.html"]' 'sierra'
+//@ has index.html '//ul[@class="all-items"]//a[@href="tango/index.html"]' 'tango'
+//@ has sierra/struct.Sierra.html
+//@ hasraw trait.impl/tango/trait.Tango.js 'struct.Sierra.html'
+//@ hasraw search-index.js 'Tango'
+//@ hasraw search-index.js 'Sierra'
+//@ hasraw search-index.js 'Quebec'
+
+// If these were documeted into the same directory, the info would be
+// overwritten. However, since they are merged, we can still recover all
+// of the cross-crate information
+extern crate tango;
+pub struct Sierra;
+impl tango::Tango for Sierra {}
diff --git a/tests/rustdoc/merge-cross-crate-info/overwrite/auxiliary/quebec.rs b/tests/rustdoc/merge-cross-crate-info/overwrite/auxiliary/quebec.rs
new file mode 100644
index 0000000..0e28d8e
--- /dev/null
+++ b/tests/rustdoc/merge-cross-crate-info/overwrite/auxiliary/quebec.rs
@@ -0,0 +1,5 @@
+//@ doc-flags:--merge=none
+//@ doc-flags:--enable-index-page
+//@ doc-flags:-Zunstable-options
+
+pub struct Quebec;
diff --git a/tests/rustdoc/merge-cross-crate-info/overwrite/auxiliary/tango.rs b/tests/rustdoc/merge-cross-crate-info/overwrite/auxiliary/tango.rs
new file mode 100644
index 0000000..363b2d5
--- /dev/null
+++ b/tests/rustdoc/merge-cross-crate-info/overwrite/auxiliary/tango.rs
@@ -0,0 +1,8 @@
+//@ aux-build:quebec.rs
+//@ build-aux-docs
+//@ doc-flags:--merge=finalize
+//@ doc-flags:--enable-index-page
+//@ doc-flags:-Zunstable-options
+
+extern crate quebec;
+pub trait Tango {}
diff --git a/tests/rustdoc/merge-cross-crate-info/overwrite/sierra.rs b/tests/rustdoc/merge-cross-crate-info/overwrite/sierra.rs
new file mode 100644
index 0000000..11e61dd
--- /dev/null
+++ b/tests/rustdoc/merge-cross-crate-info/overwrite/sierra.rs
@@ -0,0 +1,20 @@
+//@ aux-build:tango.rs
+//@ build-aux-docs
+//@ doc-flags:--merge=shared
+//@ doc-flags:--enable-index-page
+//@ doc-flags:-Zunstable-options
+
+//@ has quebec/struct.Quebec.html
+//@ has sierra/struct.Sierra.html
+//@ has tango/trait.Tango.html
+//@ hasraw sierra/struct.Sierra.html 'Tango'
+//@ hasraw trait.impl/tango/trait.Tango.js 'struct.Sierra.html'
+//@ hasraw search-index.js 'Tango'
+//@ hasraw search-index.js 'Sierra'
+//@ !hasraw search-index.js 'Quebec'
+
+// since tango is documented with --merge=finalize, we overwrite q's
+// cross-crate information
+extern crate tango;
+pub struct Sierra;
+impl tango::Tango for Sierra {}
diff --git a/tests/rustdoc/merge-cross-crate-info/single-crate-finalize/quebec.rs b/tests/rustdoc/merge-cross-crate-info/single-crate-finalize/quebec.rs
new file mode 100644
index 0000000..09bb78c
--- /dev/null
+++ b/tests/rustdoc/merge-cross-crate-info/single-crate-finalize/quebec.rs
@@ -0,0 +1,13 @@
+//@ doc-flags:--merge=finalize
+//@ doc-flags:--enable-index-page
+//@ doc-flags:-Zunstable-options
+
+//@ has index.html
+//@ has index.html '//h1' 'List of all crates'
+//@ has index.html '//ul[@class="all-items"]//a[@href="quebec/index.html"]' 'quebec'
+//@ has quebec/struct.Quebec.html
+//@ hasraw search-index.js 'Quebec'
+
+// there is nothing to read from the output directory if we use a single
+// crate
+pub struct Quebec;
diff --git a/tests/rustdoc/merge-cross-crate-info/single-crate-read-write/quebec.rs b/tests/rustdoc/merge-cross-crate-info/single-crate-read-write/quebec.rs
new file mode 100644
index 0000000..7247542
--- /dev/null
+++ b/tests/rustdoc/merge-cross-crate-info/single-crate-read-write/quebec.rs
@@ -0,0 +1,12 @@
+//@ doc-flags:--merge=shared
+//@ doc-flags:--enable-index-page
+//@ doc-flags:-Zunstable-options
+
+//@ has index.html
+//@ has index.html '//h1' 'List of all crates'
+//@ has index.html '//ul[@class="all-items"]//a[@href="quebec/index.html"]' 'quebec'
+//@ has quebec/struct.Quebec.html
+//@ hasraw search-index.js 'Quebec'
+
+// read-write is the default and this does the same as `single-crate`
+pub struct Quebec;
diff --git a/tests/rustdoc/merge-cross-crate-info/single-crate-write-anyway/quebec.rs b/tests/rustdoc/merge-cross-crate-info/single-crate-write-anyway/quebec.rs
new file mode 100644
index 0000000..b20e173
--- /dev/null
+++ b/tests/rustdoc/merge-cross-crate-info/single-crate-write-anyway/quebec.rs
@@ -0,0 +1,13 @@
+//@ doc-flags:--parts-out-dir=info/doc.parts/quebec
+//@ doc-flags:--enable-index-page
+//@ doc-flags:-Zunstable-options
+
+//@ has index.html
+//@ has index.html '//h1' 'List of all crates'
+//@ has index.html '//ul[@class="all-items"]//a[@href="quebec/index.html"]' 'quebec'
+//@ has quebec/struct.Quebec.html
+//@ hasraw search-index.js 'Quebec'
+
+// we can --parts-out-dir, but that doesn't do anything other than create
+// the file
+pub struct Quebec;
diff --git a/tests/rustdoc/merge-cross-crate-info/single-merge-none-useless-write/quebec.rs b/tests/rustdoc/merge-cross-crate-info/single-merge-none-useless-write/quebec.rs
new file mode 100644
index 0000000..e888a43
--- /dev/null
+++ b/tests/rustdoc/merge-cross-crate-info/single-merge-none-useless-write/quebec.rs
@@ -0,0 +1,11 @@
+//@ doc-flags:--merge=none
+//@ doc-flags:--parts-out-dir=info/doc.parts/quebec
+//@ doc-flags:--enable-index-page
+//@ doc-flags:-Zunstable-options
+
+//@ !has index.html
+//@ has quebec/struct.Quebec.html
+//@ !has search-index.js
+
+// --merge=none doesn't write anything, despite --parts-out-dir
+pub struct Quebec;
diff --git a/tests/rustdoc/merge-cross-crate-info/transitive-finalize/auxiliary/quebec.rs b/tests/rustdoc/merge-cross-crate-info/transitive-finalize/auxiliary/quebec.rs
new file mode 100644
index 0000000..1beca54
--- /dev/null
+++ b/tests/rustdoc/merge-cross-crate-info/transitive-finalize/auxiliary/quebec.rs
@@ -0,0 +1,5 @@
+//@ doc-flags:--merge=finalize
+//@ doc-flags:--enable-index-page
+//@ doc-flags:-Zunstable-options
+
+pub struct Quebec;
diff --git a/tests/rustdoc/merge-cross-crate-info/transitive-finalize/auxiliary/tango.rs b/tests/rustdoc/merge-cross-crate-info/transitive-finalize/auxiliary/tango.rs
new file mode 100644
index 0000000..363b2d5
--- /dev/null
+++ b/tests/rustdoc/merge-cross-crate-info/transitive-finalize/auxiliary/tango.rs
@@ -0,0 +1,8 @@
+//@ aux-build:quebec.rs
+//@ build-aux-docs
+//@ doc-flags:--merge=finalize
+//@ doc-flags:--enable-index-page
+//@ doc-flags:-Zunstable-options
+
+extern crate quebec;
+pub trait Tango {}
diff --git a/tests/rustdoc/merge-cross-crate-info/transitive-finalize/sierra.rs b/tests/rustdoc/merge-cross-crate-info/transitive-finalize/sierra.rs
new file mode 100644
index 0000000..68fc4b1
--- /dev/null
+++ b/tests/rustdoc/merge-cross-crate-info/transitive-finalize/sierra.rs
@@ -0,0 +1,20 @@
+//@ aux-build:tango.rs
+//@ build-aux-docs
+//@ doc-flags:--merge=finalize
+//@ doc-flags:--enable-index-page
+//@ doc-flags:-Zunstable-options
+
+//@ has index.html
+//@ has index.html '//h1' 'List of all crates'
+//@ has index.html '//ul[@class="all-items"]//a[@href="sierra/index.html"]' 'sierra'
+//@ has index.html '//ul[@class="all-items"]//a[@href="tango/index.html"]' 'tango'
+//@ has sierra/struct.Sierra.html
+//@ has tango/trait.Tango.html
+//@ hasraw sierra/struct.Sierra.html 'Tango'
+//@ hasraw trait.impl/tango/trait.Tango.js 'struct.Sierra.html'
+//@ hasraw search-index.js 'Sierra'
+
+// write only overwrites stuff in the output directory
+extern crate tango;
+pub struct Sierra;
+impl tango::Tango for Sierra {}
diff --git a/tests/rustdoc/merge-cross-crate-info/transitive-merge-none/auxiliary/quebec.rs b/tests/rustdoc/merge-cross-crate-info/transitive-merge-none/auxiliary/quebec.rs
new file mode 100644
index 0000000..6ab9215
--- /dev/null
+++ b/tests/rustdoc/merge-cross-crate-info/transitive-merge-none/auxiliary/quebec.rs
@@ -0,0 +1,6 @@
+//@ doc-flags:--merge=none
+//@ doc-flags:--parts-out-dir=info/doc.parts/quebec
+//@ doc-flags:--enable-index-page
+//@ doc-flags:-Zunstable-options
+
+pub struct Quebec;
diff --git a/tests/rustdoc/merge-cross-crate-info/transitive-merge-none/auxiliary/tango.rs b/tests/rustdoc/merge-cross-crate-info/transitive-merge-none/auxiliary/tango.rs
new file mode 100644
index 0000000..9fa99d3
--- /dev/null
+++ b/tests/rustdoc/merge-cross-crate-info/transitive-merge-none/auxiliary/tango.rs
@@ -0,0 +1,9 @@
+//@ aux-build:quebec.rs
+//@ build-aux-docs
+//@ doc-flags:--merge=none
+//@ doc-flags:--parts-out-dir=info/doc.parts/tango
+//@ doc-flags:--enable-index-page
+//@ doc-flags:-Zunstable-options
+
+extern crate quebec;
+pub trait Tango {}
diff --git a/tests/rustdoc/merge-cross-crate-info/transitive-merge-none/sierra.rs b/tests/rustdoc/merge-cross-crate-info/transitive-merge-none/sierra.rs
new file mode 100644
index 0000000..b407228
--- /dev/null
+++ b/tests/rustdoc/merge-cross-crate-info/transitive-merge-none/sierra.rs
@@ -0,0 +1,27 @@
+//@ aux-build:tango.rs
+//@ build-aux-docs
+//@ doc-flags:--merge=finalize
+//@ doc-flags:--include-parts-dir=info/doc.parts/tango
+//@ doc-flags:--include-parts-dir=info/doc.parts/quebec
+//@ doc-flags:--enable-index-page
+//@ doc-flags:-Zunstable-options
+
+//@ has index.html
+//@ has index.html '//h1' 'List of all crates'
+//@ has index.html '//ul[@class="all-items"]//a[@href="quebec/index.html"]' 'quebec'
+//@ has index.html '//ul[@class="all-items"]//a[@href="sierra/index.html"]' 'sierra'
+//@ has index.html '//ul[@class="all-items"]//a[@href="tango/index.html"]' 'tango'
+//@ has quebec/struct.Quebec.html
+//@ has sierra/struct.Sierra.html
+//@ has tango/trait.Tango.html
+//@ hasraw sierra/struct.Sierra.html 'Tango'
+//@ hasraw trait.impl/tango/trait.Tango.js 'struct.Sierra.html'
+//@ hasraw search-index.js 'Tango'
+//@ hasraw search-index.js 'Sierra'
+//@ hasraw search-index.js 'Quebec'
+
+// We avoid writing any cross-crate information, preferring to include it
+// with --include-parts-dir.
+extern crate tango;
+pub struct Sierra;
+impl tango::Tango for Sierra {}
diff --git a/tests/rustdoc/merge-cross-crate-info/transitive-merge-read-write/auxiliary/quebec.rs b/tests/rustdoc/merge-cross-crate-info/transitive-merge-read-write/auxiliary/quebec.rs
new file mode 100644
index 0000000..1beca54
--- /dev/null
+++ b/tests/rustdoc/merge-cross-crate-info/transitive-merge-read-write/auxiliary/quebec.rs
@@ -0,0 +1,5 @@
+//@ doc-flags:--merge=finalize
+//@ doc-flags:--enable-index-page
+//@ doc-flags:-Zunstable-options
+
+pub struct Quebec;
diff --git a/tests/rustdoc/merge-cross-crate-info/transitive-merge-read-write/auxiliary/tango.rs b/tests/rustdoc/merge-cross-crate-info/transitive-merge-read-write/auxiliary/tango.rs
new file mode 100644
index 0000000..ff12fe9
--- /dev/null
+++ b/tests/rustdoc/merge-cross-crate-info/transitive-merge-read-write/auxiliary/tango.rs
@@ -0,0 +1,8 @@
+//@ aux-build:quebec.rs
+//@ build-aux-docs
+//@ doc-flags:--merge=shared
+//@ doc-flags:--enable-index-page
+//@ doc-flags:-Zunstable-options
+
+extern crate quebec;
+pub trait Tango {}
diff --git a/tests/rustdoc/merge-cross-crate-info/transitive-merge-read-write/sierra.rs b/tests/rustdoc/merge-cross-crate-info/transitive-merge-read-write/sierra.rs
new file mode 100644
index 0000000..15e32d5
--- /dev/null
+++ b/tests/rustdoc/merge-cross-crate-info/transitive-merge-read-write/sierra.rs
@@ -0,0 +1,25 @@
+//@ aux-build:tango.rs
+//@ build-aux-docs
+//@ doc-flags:--merge=shared
+//@ doc-flags:--enable-index-page
+//@ doc-flags:-Zunstable-options
+
+//@ has index.html
+//@ has index.html '//h1' 'List of all crates'
+//@ has index.html '//ul[@class="all-items"]//a[@href="quebec/index.html"]' 'quebec'
+//@ has index.html '//ul[@class="all-items"]//a[@href="sierra/index.html"]' 'sierra'
+//@ has index.html '//ul[@class="all-items"]//a[@href="tango/index.html"]' 'tango'
+//@ has quebec/struct.Quebec.html
+//@ has sierra/struct.Sierra.html
+//@ has tango/trait.Tango.html
+//@ hasraw sierra/struct.Sierra.html 'Tango'
+//@ hasraw trait.impl/tango/trait.Tango.js 'struct.Sierra.html'
+//@ hasraw search-index.js 'Tango'
+//@ hasraw search-index.js 'Sierra'
+//@ hasraw search-index.js 'Quebec'
+
+// We can use read-write to emulate the default behavior of rustdoc, when
+// --merge is left out.
+extern crate tango;
+pub struct Sierra;
+impl tango::Tango for Sierra {}
diff --git a/tests/rustdoc/merge-cross-crate-info/transitive-no-info/auxiliary/quebec.rs b/tests/rustdoc/merge-cross-crate-info/transitive-no-info/auxiliary/quebec.rs
new file mode 100644
index 0000000..0e28d8e
--- /dev/null
+++ b/tests/rustdoc/merge-cross-crate-info/transitive-no-info/auxiliary/quebec.rs
@@ -0,0 +1,5 @@
+//@ doc-flags:--merge=none
+//@ doc-flags:--enable-index-page
+//@ doc-flags:-Zunstable-options
+
+pub struct Quebec;
diff --git a/tests/rustdoc/merge-cross-crate-info/transitive-no-info/auxiliary/tango.rs b/tests/rustdoc/merge-cross-crate-info/transitive-no-info/auxiliary/tango.rs
new file mode 100644
index 0000000..3827119
--- /dev/null
+++ b/tests/rustdoc/merge-cross-crate-info/transitive-no-info/auxiliary/tango.rs
@@ -0,0 +1,8 @@
+//@ aux-build:quebec.rs
+//@ build-aux-docs
+//@ doc-flags:--merge=none
+//@ doc-flags:--enable-index-page
+//@ doc-flags:-Zunstable-options
+
+extern crate quebec;
+pub trait Tango {}
diff --git a/tests/rustdoc/merge-cross-crate-info/transitive-no-info/sierra.rs b/tests/rustdoc/merge-cross-crate-info/transitive-no-info/sierra.rs
new file mode 100644
index 0000000..3eb2ceb
--- /dev/null
+++ b/tests/rustdoc/merge-cross-crate-info/transitive-no-info/sierra.rs
@@ -0,0 +1,17 @@
+//@ aux-build:tango.rs
+//@ build-aux-docs
+//@ doc-flags:--merge=none
+//@ doc-flags:--enable-index-page
+//@ doc-flags:-Zunstable-options
+
+//@ !has index.html
+//@ has sierra/struct.Sierra.html
+//@ has tango/trait.Tango.html
+//@ hasraw sierra/struct.Sierra.html 'Tango'
+//@ !has trait.impl/tango/trait.Tango.js
+//@ !has search-index.js
+
+// --merge=none on all crates does not generate any cross-crate info
+extern crate tango;
+pub struct Sierra;
+impl tango::Tango for Sierra {}
diff --git a/tests/rustdoc/merge-cross-crate-info/two-separate-out-dir/auxiliary/foxtrot.rs b/tests/rustdoc/merge-cross-crate-info/two-separate-out-dir/auxiliary/foxtrot.rs
new file mode 100644
index 0000000..e492b70
--- /dev/null
+++ b/tests/rustdoc/merge-cross-crate-info/two-separate-out-dir/auxiliary/foxtrot.rs
@@ -0,0 +1,5 @@
+//@ unique-doc-out-dir
+//@ doc-flags:--parts-out-dir=info/doc.parts/foxtrot
+//@ doc-flags:-Zunstable-options
+
+pub trait Foxtrot {}
diff --git a/tests/rustdoc/merge-cross-crate-info/two-separate-out-dir/echo.rs b/tests/rustdoc/merge-cross-crate-info/two-separate-out-dir/echo.rs
new file mode 100644
index 0000000..ee2b646
--- /dev/null
+++ b/tests/rustdoc/merge-cross-crate-info/two-separate-out-dir/echo.rs
@@ -0,0 +1,16 @@
+//@ aux-build:foxtrot.rs
+//@ build-aux-docs
+//@ doc-flags:--include-parts-dir=info/doc.parts/foxtrot
+//@ doc-flags:-Zunstable-options
+
+//@ has echo/enum.Echo.html
+//@ hasraw echo/enum.Echo.html 'Foxtrot'
+//@ hasraw trait.impl/foxtrot/trait.Foxtrot.js 'enum.Echo.html'
+//@ hasraw search-index.js 'Foxtrot'
+//@ hasraw search-index.js 'Echo'
+
+// document two crates in different places, and merge their docs after
+// they are generated
+extern crate foxtrot;
+pub enum Echo {}
+impl foxtrot::Foxtrot for Echo {}
diff --git a/tests/ui-fulldeps/internal-lints/query_completeness.rs b/tests/ui-fulldeps/internal-lints/query_completeness.rs
new file mode 100644
index 0000000..50b0fb4
--- /dev/null
+++ b/tests/ui-fulldeps/internal-lints/query_completeness.rs
@@ -0,0 +1,16 @@
+//@ compile-flags: -Z unstable-options
+// #[cfg(bootstrap)]: We can stop ignoring next beta bump; afterward this ALWAYS should run.
+//@ ignore-stage1 (requires matching sysroot built with in-tree compiler)
+#![feature(rustc_private)]
+#![deny(rustc::untracked_query_information)]
+
+extern crate rustc_data_structures;
+
+use rustc_data_structures::steal::Steal;
+
+fn use_steal(x: Steal<()>) {
+ let _ = x.is_stolen();
+ //~^ ERROR `is_stolen` accesses information that is not tracked by the query system
+}
+
+fn main() {}
diff --git a/tests/ui-fulldeps/internal-lints/query_completeness.stderr b/tests/ui-fulldeps/internal-lints/query_completeness.stderr
new file mode 100644
index 0000000..35bb867
--- /dev/null
+++ b/tests/ui-fulldeps/internal-lints/query_completeness.stderr
@@ -0,0 +1,15 @@
+error: `is_stolen` accesses information that is not tracked by the query system
+ --> $DIR/query_completeness.rs:12:15
+ |
+LL | let _ = x.is_stolen();
+ | ^^^^^^^^^
+ |
+ = note: if you believe this case to be fine, allow this lint and add a comment explaining your rationale
+note: the lint level is defined here
+ --> $DIR/query_completeness.rs:5:9
+ |
+LL | #![deny(rustc::untracked_query_information)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/asm/const-refs-to-static.rs b/tests/ui/asm/const-refs-to-static.rs
new file mode 100644
index 0000000..9fc010b
--- /dev/null
+++ b/tests/ui/asm/const-refs-to-static.rs
@@ -0,0 +1,21 @@
+//@ needs-asm-support
+//@ ignore-nvptx64
+//@ ignore-spirv
+
+#![feature(const_refs_to_static)]
+
+use std::arch::{asm, global_asm};
+use std::ptr::addr_of;
+
+static FOO: u8 = 42;
+
+global_asm!("{}", const addr_of!(FOO));
+//~^ ERROR invalid type for `const` operand
+
+#[no_mangle]
+fn inline() {
+ unsafe { asm!("{}", const addr_of!(FOO)) };
+ //~^ ERROR invalid type for `const` operand
+}
+
+fn main() {}
diff --git a/tests/ui/asm/const-refs-to-static.stderr b/tests/ui/asm/const-refs-to-static.stderr
new file mode 100644
index 0000000..8fd69da
--- /dev/null
+++ b/tests/ui/asm/const-refs-to-static.stderr
@@ -0,0 +1,22 @@
+error: invalid type for `const` operand
+ --> $DIR/const-refs-to-static.rs:12:19
+ |
+LL | global_asm!("{}", const addr_of!(FOO));
+ | ^^^^^^-------------
+ | |
+ | is a `*const u8`
+ |
+ = help: `const` operands must be of an integer type
+
+error: invalid type for `const` operand
+ --> $DIR/const-refs-to-static.rs:17:25
+ |
+LL | unsafe { asm!("{}", const addr_of!(FOO)) };
+ | ^^^^^^-------------
+ | |
+ | is a `*const u8`
+ |
+ = help: `const` operands must be of an integer type
+
+error: aborting due to 2 previous errors
+
diff --git a/tests/ui/asm/naked-functions-inline.rs b/tests/ui/asm/naked-functions-inline.rs
index cfb38f2..74049e8 100644
--- a/tests/ui/asm/naked-functions-inline.rs
+++ b/tests/ui/asm/naked-functions-inline.rs
@@ -2,37 +2,37 @@
#![feature(naked_functions)]
#![crate_type = "lib"]
-use std::arch::asm;
+use std::arch::naked_asm;
#[naked]
pub unsafe extern "C" fn inline_none() {
- asm!("", options(noreturn));
+ naked_asm!("");
}
#[naked]
#[inline]
//~^ ERROR [E0736]
pub unsafe extern "C" fn inline_hint() {
- asm!("", options(noreturn));
+ naked_asm!("");
}
#[naked]
#[inline(always)]
//~^ ERROR [E0736]
pub unsafe extern "C" fn inline_always() {
- asm!("", options(noreturn));
+ naked_asm!("");
}
#[naked]
#[inline(never)]
//~^ ERROR [E0736]
pub unsafe extern "C" fn inline_never() {
- asm!("", options(noreturn));
+ naked_asm!("");
}
#[naked]
#[cfg_attr(all(), inline(never))]
//~^ ERROR [E0736]
pub unsafe extern "C" fn conditional_inline_never() {
- asm!("", options(noreturn));
+ naked_asm!("");
}
diff --git a/tests/ui/associated-types/associated-types-coherence-failure.stderr b/tests/ui/associated-types/associated-types-coherence-failure.stderr
index 211613b..25c22e5 100644
--- a/tests/ui/associated-types/associated-types-coherence-failure.stderr
+++ b/tests/ui/associated-types/associated-types-coherence-failure.stderr
@@ -1,20 +1,20 @@
-error[E0119]: conflicting implementations of trait `IntoCow<'_, _>` for type `Cow<'_, _>`
+error[E0119]: conflicting implementations of trait `IntoCow<'_, _>` for type `<_ as ToOwned>::Owned`
--> $DIR/associated-types-coherence-failure.rs:21:1
|
LL | impl<'a, B: ?Sized> IntoCow<'a, B> for <B as ToOwned>::Owned where B: ToOwned {
| ----------------------------------------------------------------------------- first implementation here
...
LL | impl<'a, B: ?Sized> IntoCow<'a, B> for Cow<'a, B> where B: ToOwned {
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `Cow<'_, _>`
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `<_ as ToOwned>::Owned`
-error[E0119]: conflicting implementations of trait `IntoCow<'_, _>` for type `&_`
+error[E0119]: conflicting implementations of trait `IntoCow<'_, _>` for type `<_ as ToOwned>::Owned`
--> $DIR/associated-types-coherence-failure.rs:28:1
|
LL | impl<'a, B: ?Sized> IntoCow<'a, B> for <B as ToOwned>::Owned where B: ToOwned {
| ----------------------------------------------------------------------------- first implementation here
...
LL | impl<'a, B: ?Sized> IntoCow<'a, B> for &'a B where B: ToOwned {
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `&_`
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `<_ as ToOwned>::Owned`
error: aborting due to 2 previous errors
diff --git a/tests/ui/async-await/async-closures/tainted-body-2.rs b/tests/ui/async-await/async-closures/tainted-body-2.rs
new file mode 100644
index 0000000..73c6bdc
--- /dev/null
+++ b/tests/ui/async-await/async-closures/tainted-body-2.rs
@@ -0,0 +1,18 @@
+//@ edition: 2021
+
+#![feature(async_closure)]
+
+// Ensure that building a by-ref async closure body doesn't ICE when the parent
+// body is tainted.
+
+fn main() {
+ missing;
+ //~^ ERROR cannot find value `missing` in this scope
+
+ // We don't do numerical inference fallback when the body is tainted.
+ // This leads to writeback folding the type of the coroutine-closure
+ // into an error type, since its signature contains that numerical
+ // infer var.
+ let c = async |_| {};
+ c(1);
+}
diff --git a/tests/ui/async-await/async-closures/tainted-body-2.stderr b/tests/ui/async-await/async-closures/tainted-body-2.stderr
new file mode 100644
index 0000000..798d470
--- /dev/null
+++ b/tests/ui/async-await/async-closures/tainted-body-2.stderr
@@ -0,0 +1,9 @@
+error[E0425]: cannot find value `missing` in this scope
+ --> $DIR/tainted-body-2.rs:9:5
+ |
+LL | missing;
+ | ^^^^^^^ 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/async-await/async-closures/validate-synthetic-body.rs b/tests/ui/async-await/async-closures/validate-synthetic-body.rs
new file mode 100644
index 0000000..67e683a
--- /dev/null
+++ b/tests/ui/async-await/async-closures/validate-synthetic-body.rs
@@ -0,0 +1,19 @@
+//@ check-pass
+//@ edition: 2021
+
+#![feature(async_closure)]
+
+// Make sure that we don't hit a query cycle when validating
+// the by-move coroutine body for an async closure.
+
+use std::future::Future;
+
+async fn test<Fut: Future>(operation: impl Fn() -> Fut) {
+ operation().await;
+}
+
+pub async fn orchestrate_simple_crud() {
+ test(async || async {}.await).await;
+}
+
+fn main() {}
diff --git a/tests/ui/async-await/async-drop.rs b/tests/ui/async-await/async-drop.rs
index 12f120a..4e60598 100644
--- a/tests/ui/async-await/async-drop.rs
+++ b/tests/ui/async-await/async-drop.rs
@@ -53,18 +53,20 @@ fn main() {
let i = 13;
let fut = pin!(async {
test_async_drop(Int(0), 0).await;
- test_async_drop(AsyncInt(0), 104).await;
- test_async_drop([AsyncInt(1), AsyncInt(2)], 152).await;
- test_async_drop((AsyncInt(3), AsyncInt(4)), 488).await;
+ // FIXME(#63818): niches in coroutines are disabled.
+ // Some of these sizes should be smaller, as indicated in comments.
+ test_async_drop(AsyncInt(0), /*104*/ 112).await;
+ test_async_drop([AsyncInt(1), AsyncInt(2)], /*152*/ 168).await;
+ test_async_drop((AsyncInt(3), AsyncInt(4)), /*488*/ 528).await;
test_async_drop(5, 0).await;
let j = 42;
test_async_drop(&i, 0).await;
test_async_drop(&j, 0).await;
- test_async_drop(AsyncStruct { b: AsyncInt(8), a: AsyncInt(7), i: 6 }, 1688).await;
+ test_async_drop(AsyncStruct { b: AsyncInt(8), a: AsyncInt(7), i: 6 }, /*1688*/ 1792).await;
test_async_drop(ManuallyDrop::new(AsyncInt(9)), 0).await;
let foo = AsyncInt(10);
- test_async_drop(AsyncReference { foo: &foo }, 104).await;
+ test_async_drop(AsyncReference { foo: &foo }, /*104*/ 112).await;
let foo = AsyncInt(11);
test_async_drop(
@@ -73,17 +75,17 @@ fn main() {
let foo = AsyncInt(10);
foo
},
- 120,
+ /*120*/ 136,
)
.await;
- test_async_drop(AsyncEnum::A(AsyncInt(12)), 680).await;
- test_async_drop(AsyncEnum::B(SyncInt(13)), 680).await;
+ test_async_drop(AsyncEnum::A(AsyncInt(12)), /*680*/ 736).await;
+ test_async_drop(AsyncEnum::B(SyncInt(13)), /*680*/ 736).await;
- test_async_drop(SyncInt(14), 16).await;
+ test_async_drop(SyncInt(14), /*16*/ 24).await;
test_async_drop(
SyncThenAsync { i: 15, a: AsyncInt(16), b: SyncInt(17), c: AsyncInt(18) },
- 3064,
+ /*3064*/ 3296,
)
.await;
@@ -99,11 +101,11 @@ fn main() {
black_box(core::future::ready(())).await;
foo
},
- 120,
+ /*120*/ 136,
)
.await;
- test_async_drop(AsyncUnion { signed: 21 }, 32).await;
+ test_async_drop(AsyncUnion { signed: 21 }, /*32*/ 40).await;
});
let res = fut.poll(&mut cx);
assert_eq!(res, Poll::Ready(()));
diff --git a/tests/ui/async-await/future-sizes/async-awaiting-fut.stdout b/tests/ui/async-await/future-sizes/async-awaiting-fut.stdout
index def967b..642e27b 100644
--- a/tests/ui/async-await/future-sizes/async-awaiting-fut.stdout
+++ b/tests/ui/async-await/future-sizes/async-awaiting-fut.stdout
@@ -14,28 +14,26 @@
print-type-size type: `{async fn body of calls_fut<{async fn body of big_fut()}>()}`: 3077 bytes, alignment: 1 bytes
print-type-size discriminant: 1 bytes
print-type-size variant `Unresumed`: 1025 bytes
-print-type-size upvar `.fut`: 1025 bytes, offset: 0 bytes, alignment: 1 bytes
+print-type-size upvar `.fut`: 1025 bytes
print-type-size variant `Suspend0`: 2052 bytes
-print-type-size upvar `.fut`: 1025 bytes, offset: 0 bytes, alignment: 1 bytes
-print-type-size padding: 1 bytes
-print-type-size local `.fut`: 1025 bytes, alignment: 1 bytes
+print-type-size upvar `.fut`: 1025 bytes
+print-type-size local `.fut`: 1025 bytes
print-type-size local `..coroutine_field4`: 1 bytes, type: bool
print-type-size local `.__awaitee`: 1 bytes, type: {async fn body of wait()}
print-type-size variant `Suspend1`: 3076 bytes
-print-type-size upvar `.fut`: 1025 bytes, offset: 0 bytes, alignment: 1 bytes
-print-type-size padding: 1026 bytes
+print-type-size upvar `.fut`: 1025 bytes
+print-type-size padding: 1025 bytes
print-type-size local `..coroutine_field4`: 1 bytes, alignment: 1 bytes, type: bool
print-type-size local `.__awaitee`: 1025 bytes, type: {async fn body of big_fut()}
print-type-size variant `Suspend2`: 2052 bytes
-print-type-size upvar `.fut`: 1025 bytes, offset: 0 bytes, alignment: 1 bytes
-print-type-size padding: 1 bytes
-print-type-size local `.fut`: 1025 bytes, alignment: 1 bytes
+print-type-size upvar `.fut`: 1025 bytes
+print-type-size local `.fut`: 1025 bytes
print-type-size local `..coroutine_field4`: 1 bytes, type: bool
print-type-size local `.__awaitee`: 1 bytes, type: {async fn body of wait()}
print-type-size variant `Returned`: 1025 bytes
-print-type-size upvar `.fut`: 1025 bytes, offset: 0 bytes, alignment: 1 bytes
+print-type-size upvar `.fut`: 1025 bytes
print-type-size variant `Panicked`: 1025 bytes
-print-type-size upvar `.fut`: 1025 bytes, offset: 0 bytes, alignment: 1 bytes
+print-type-size upvar `.fut`: 1025 bytes
print-type-size type: `std::mem::ManuallyDrop<{async fn body of big_fut()}>`: 1025 bytes, alignment: 1 bytes
print-type-size field `.value`: 1025 bytes
print-type-size type: `std::mem::MaybeUninit<{async fn body of big_fut()}>`: 1025 bytes, alignment: 1 bytes
diff --git a/tests/ui/auto-traits/opaque_type_candidate_selection.rs b/tests/ui/auto-traits/opaque_type_candidate_selection.rs
deleted file mode 100644
index d6973b7..0000000
--- a/tests/ui/auto-traits/opaque_type_candidate_selection.rs
+++ /dev/null
@@ -1,30 +0,0 @@
-//! used to ICE: #119272
-
-//@ check-pass
-
-#![feature(type_alias_impl_trait)]
-mod defining_scope {
- use super::*;
- pub type Alias<T> = impl Sized;
-
- pub fn cast<T>(x: Container<Alias<T>, T>) -> Container<T, T> {
- x
- }
-}
-
-struct Container<T: Trait<U>, U> {
- x: <T as Trait<U>>::Assoc,
-}
-
-trait Trait<T> {
- type Assoc;
-}
-
-impl<T> Trait<T> for T {
- type Assoc = Box<u32>;
-}
-impl<T> Trait<T> for defining_scope::Alias<T> {
- type Assoc = usize;
-}
-
-fn main() {}
diff --git a/tests/ui/cmse-nonsecure/cmse-nonsecure-call/generics.rs b/tests/ui/cmse-nonsecure/cmse-nonsecure-call/generics.rs
index e6b0bf3..9e0ffa7 100644
--- a/tests/ui/cmse-nonsecure/cmse-nonsecure-call/generics.rs
+++ b/tests/ui/cmse-nonsecure/cmse-nonsecure-call/generics.rs
@@ -12,10 +12,31 @@ impl Copy for u32 {}
struct Wrapper<T>(T);
struct Test<T: Copy> {
- f1: extern "C-cmse-nonsecure-call" fn<U: Copy>(U, u32, u32, u32) -> u64, //~ ERROR cannot find type `U` in this scope
- //~^ ERROR function pointer types may not have generic parameters
+ f1: extern "C-cmse-nonsecure-call" fn<U: Copy>(U, u32, u32, u32) -> u64,
+ //~^ ERROR cannot find type `U` in this scope
+ //~| ERROR function pointer types may not have generic parameters
f2: extern "C-cmse-nonsecure-call" fn(impl Copy, u32, u32, u32) -> u64,
//~^ ERROR `impl Trait` is not allowed in `fn` pointer parameters
f3: extern "C-cmse-nonsecure-call" fn(T, u32, u32, u32) -> u64, //~ ERROR [E0798]
f4: extern "C-cmse-nonsecure-call" fn(Wrapper<T>, u32, u32, u32) -> u64, //~ ERROR [E0798]
}
+
+type WithReference = extern "C-cmse-nonsecure-call" fn(&usize);
+
+trait Trait {}
+type WithTraitObject = extern "C-cmse-nonsecure-call" fn(&dyn Trait) -> &dyn Trait;
+//~^ ERROR return value of `"C-cmse-nonsecure-call"` function too large to pass via registers [E0798]
+
+type WithStaticTraitObject =
+ extern "C-cmse-nonsecure-call" fn(&'static dyn Trait) -> &'static dyn Trait;
+//~^ ERROR return value of `"C-cmse-nonsecure-call"` function too large to pass via registers [E0798]
+
+#[repr(transparent)]
+struct WrapperTransparent<'a>(&'a dyn Trait);
+
+type WithTransparentTraitObject =
+ extern "C-cmse-nonsecure-call" fn(WrapperTransparent) -> WrapperTransparent;
+//~^ ERROR return value of `"C-cmse-nonsecure-call"` function too large to pass via registers [E0798]
+
+type WithVarArgs = extern "C-cmse-nonsecure-call" fn(u32, ...);
+//~^ ERROR C-variadic function must have a compatible calling convention, like `C` or `cdecl` [E0045]
diff --git a/tests/ui/cmse-nonsecure/cmse-nonsecure-call/generics.stderr b/tests/ui/cmse-nonsecure/cmse-nonsecure-call/generics.stderr
index fa68d95..7cb8e13 100644
--- a/tests/ui/cmse-nonsecure/cmse-nonsecure-call/generics.stderr
+++ b/tests/ui/cmse-nonsecure/cmse-nonsecure-call/generics.stderr
@@ -22,7 +22,7 @@
| +++
error[E0562]: `impl Trait` is not allowed in `fn` pointer parameters
- --> $DIR/generics.rs:17:43
+ --> $DIR/generics.rs:18:43
|
LL | f2: extern "C-cmse-nonsecure-call" fn(impl Copy, u32, u32, u32) -> u64,
| ^^^^^^^^^
@@ -30,18 +30,51 @@
= note: `impl Trait` is only allowed in arguments and return types of functions and methods
error[E0798]: function pointers with the `"C-cmse-nonsecure-call"` ABI cannot contain generics in their type
- --> $DIR/generics.rs:19:9
+ --> $DIR/generics.rs:20:9
|
LL | f3: extern "C-cmse-nonsecure-call" fn(T, u32, u32, u32) -> u64,
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error[E0798]: function pointers with the `"C-cmse-nonsecure-call"` ABI cannot contain generics in their type
- --> $DIR/generics.rs:20:9
+ --> $DIR/generics.rs:21:9
|
LL | f4: extern "C-cmse-nonsecure-call" fn(Wrapper<T>, u32, u32, u32) -> u64,
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-error: aborting due to 5 previous errors
+error[E0798]: return value of `"C-cmse-nonsecure-call"` function too large to pass via registers
+ --> $DIR/generics.rs:27:73
+ |
+LL | type WithTraitObject = extern "C-cmse-nonsecure-call" fn(&dyn Trait) -> &dyn Trait;
+ | ^^^^^^^^^^ this type doesn't fit in the available registers
+ |
+ = note: functions with the `"C-cmse-nonsecure-call"` ABI must pass their result via the available return registers
+ = note: the result must either be a (transparently wrapped) i64, u64 or f64, or be at most 4 bytes in size
-Some errors have detailed explanations: E0412, E0562, E0798.
-For more information about an error, try `rustc --explain E0412`.
+error[E0798]: return value of `"C-cmse-nonsecure-call"` function too large to pass via registers
+ --> $DIR/generics.rs:31:62
+ |
+LL | extern "C-cmse-nonsecure-call" fn(&'static dyn Trait) -> &'static dyn Trait;
+ | ^^^^^^^^^^^^^^^^^^ this type doesn't fit in the available registers
+ |
+ = note: functions with the `"C-cmse-nonsecure-call"` ABI must pass their result via the available return registers
+ = note: the result must either be a (transparently wrapped) i64, u64 or f64, or be at most 4 bytes in size
+
+error[E0798]: return value of `"C-cmse-nonsecure-call"` function too large to pass via registers
+ --> $DIR/generics.rs:38:62
+ |
+LL | extern "C-cmse-nonsecure-call" fn(WrapperTransparent) -> WrapperTransparent;
+ | ^^^^^^^^^^^^^^^^^^ this type doesn't fit in the available registers
+ |
+ = note: functions with the `"C-cmse-nonsecure-call"` ABI must pass their result via the available return registers
+ = note: the result must either be a (transparently wrapped) i64, u64 or f64, or be at most 4 bytes in size
+
+error[E0045]: C-variadic function must have a compatible calling convention, like `C` or `cdecl`
+ --> $DIR/generics.rs:41:20
+ |
+LL | type WithVarArgs = extern "C-cmse-nonsecure-call" fn(u32, ...);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ C-variadic function must have a compatible calling convention
+
+error: aborting due to 9 previous errors
+
+Some errors have detailed explanations: E0045, E0412, E0562, E0798.
+For more information about an error, try `rustc --explain E0045`.
diff --git a/tests/ui/coherence/coherence-negative-outlives-lifetimes.stock.stderr b/tests/ui/coherence/coherence-negative-outlives-lifetimes.stock.stderr
index dbb22d8..1d28bb4 100644
--- a/tests/ui/coherence/coherence-negative-outlives-lifetimes.stock.stderr
+++ b/tests/ui/coherence/coherence-negative-outlives-lifetimes.stock.stderr
@@ -5,6 +5,8 @@
| ---------------------------------------------- first implementation here
LL | impl<'a, T> MyTrait<'a> for &'a T {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `&_`
+ |
+ = note: downstream crates may implement trait `MyPredicate<'_>` for type `&_`
error: aborting due to 1 previous error
diff --git a/tests/ui/coherence/coherence-negative-outlives-lifetimes.with_negative_coherence.stderr b/tests/ui/coherence/coherence-negative-outlives-lifetimes.with_negative_coherence.stderr
index dbb22d8..1d28bb4 100644
--- a/tests/ui/coherence/coherence-negative-outlives-lifetimes.with_negative_coherence.stderr
+++ b/tests/ui/coherence/coherence-negative-outlives-lifetimes.with_negative_coherence.stderr
@@ -5,6 +5,8 @@
| ---------------------------------------------- first implementation here
LL | impl<'a, T> MyTrait<'a> for &'a T {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `&_`
+ |
+ = note: downstream crates may implement trait `MyPredicate<'_>` for type `&_`
error: aborting due to 1 previous error
diff --git a/tests/ui/coherence/coherence-overlap-downstream-inherent.old.stderr b/tests/ui/coherence/coherence-overlap-downstream-inherent.old.stderr
deleted file mode 100644
index 2938bc6..0000000
--- a/tests/ui/coherence/coherence-overlap-downstream-inherent.old.stderr
+++ /dev/null
@@ -1,23 +0,0 @@
-error[E0592]: duplicate definitions with name `dummy`
- --> $DIR/coherence-overlap-downstream-inherent.rs:10:26
- |
-LL | impl<T:Sugar> Sweet<T> { fn dummy(&self) { } }
- | ^^^^^^^^^^^^^^^ duplicate definitions for `dummy`
-LL |
-LL | impl<T:Fruit> Sweet<T> { fn dummy(&self) { } }
- | --------------- other definition for `dummy`
-
-error[E0592]: duplicate definitions with name `f`
- --> $DIR/coherence-overlap-downstream-inherent.rs:16:38
- |
-LL | impl<X, T> A<T, X> where T: Bar<X> { fn f(&self) {} }
- | ^^^^^^^^^^^ duplicate definitions for `f`
-LL |
-LL | impl<X> A<i32, X> { fn f(&self) {} }
- | ----------- other definition for `f`
- |
- = note: downstream crates may implement trait `Bar<_>` for type `i32`
-
-error: aborting due to 2 previous errors
-
-For more information about this error, try `rustc --explain E0592`.
diff --git a/tests/ui/coherence/coherence-overlap-downstream-inherent.rs b/tests/ui/coherence/coherence-overlap-downstream-inherent.rs
index 3e90b7c..5dea33e 100644
--- a/tests/ui/coherence/coherence-overlap-downstream-inherent.rs
+++ b/tests/ui/coherence/coherence-overlap-downstream-inherent.rs
@@ -1,6 +1,3 @@
-//@ revisions: old next
-//@[next] compile-flags: -Znext-solver
-
// Tests that we consider `T: Sugar + Fruit` to be ambiguous, even
// though no impls are found.
diff --git a/tests/ui/coherence/coherence-overlap-downstream-inherent.next.stderr b/tests/ui/coherence/coherence-overlap-downstream-inherent.stderr
similarity index 87%
rename from tests/ui/coherence/coherence-overlap-downstream-inherent.next.stderr
rename to tests/ui/coherence/coherence-overlap-downstream-inherent.stderr
index 2938bc6..bbce4b5 100644
--- a/tests/ui/coherence/coherence-overlap-downstream-inherent.next.stderr
+++ b/tests/ui/coherence/coherence-overlap-downstream-inherent.stderr
@@ -1,5 +1,5 @@
error[E0592]: duplicate definitions with name `dummy`
- --> $DIR/coherence-overlap-downstream-inherent.rs:10:26
+ --> $DIR/coherence-overlap-downstream-inherent.rs:7:26
|
LL | impl<T:Sugar> Sweet<T> { fn dummy(&self) { } }
| ^^^^^^^^^^^^^^^ duplicate definitions for `dummy`
@@ -8,7 +8,7 @@
| --------------- other definition for `dummy`
error[E0592]: duplicate definitions with name `f`
- --> $DIR/coherence-overlap-downstream-inherent.rs:16:38
+ --> $DIR/coherence-overlap-downstream-inherent.rs:13:38
|
LL | impl<X, T> A<T, X> where T: Bar<X> { fn f(&self) {} }
| ^^^^^^^^^^^ duplicate definitions for `f`
diff --git a/tests/ui/coherence/coherence-overlap-downstream.old.stderr b/tests/ui/coherence/coherence-overlap-downstream.old.stderr
deleted file mode 100644
index 6c2e946..0000000
--- a/tests/ui/coherence/coherence-overlap-downstream.old.stderr
+++ /dev/null
@@ -1,21 +0,0 @@
-error[E0119]: conflicting implementations of trait `Sweet`
- --> $DIR/coherence-overlap-downstream.rs:11:1
- |
-LL | impl<T:Sugar> Sweet for T { }
- | ------------------------- first implementation here
-LL | impl<T:Fruit> Sweet for T { }
- | ^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation
-
-error[E0119]: conflicting implementations of trait `Foo<_>` for type `i32`
- --> $DIR/coherence-overlap-downstream.rs:17:1
- |
-LL | impl<X, T> Foo<X> for T where T: Bar<X> {}
- | --------------------------------------- first implementation here
-LL | impl<X> Foo<X> for i32 {}
- | ^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `i32`
- |
- = note: downstream crates may implement trait `Bar<_>` for type `i32`
-
-error: aborting due to 2 previous errors
-
-For more information about this error, try `rustc --explain E0119`.
diff --git a/tests/ui/coherence/coherence-overlap-downstream.rs b/tests/ui/coherence/coherence-overlap-downstream.rs
index 8b99296..738ec0e 100644
--- a/tests/ui/coherence/coherence-overlap-downstream.rs
+++ b/tests/ui/coherence/coherence-overlap-downstream.rs
@@ -1,6 +1,3 @@
-//@ revisions: old next
-//@[next] compile-flags: -Znext-solver
-
// Tests that we consider `T: Sugar + Fruit` to be ambiguous, even
// though no impls are found.
diff --git a/tests/ui/coherence/coherence-overlap-downstream.next.stderr b/tests/ui/coherence/coherence-overlap-downstream.stderr
similarity index 88%
rename from tests/ui/coherence/coherence-overlap-downstream.next.stderr
rename to tests/ui/coherence/coherence-overlap-downstream.stderr
index 6c2e946..9ab0994 100644
--- a/tests/ui/coherence/coherence-overlap-downstream.next.stderr
+++ b/tests/ui/coherence/coherence-overlap-downstream.stderr
@@ -1,5 +1,5 @@
error[E0119]: conflicting implementations of trait `Sweet`
- --> $DIR/coherence-overlap-downstream.rs:11:1
+ --> $DIR/coherence-overlap-downstream.rs:8:1
|
LL | impl<T:Sugar> Sweet for T { }
| ------------------------- first implementation here
@@ -7,7 +7,7 @@
| ^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation
error[E0119]: conflicting implementations of trait `Foo<_>` for type `i32`
- --> $DIR/coherence-overlap-downstream.rs:17:1
+ --> $DIR/coherence-overlap-downstream.rs:14:1
|
LL | impl<X, T> Foo<X> for T where T: Bar<X> {}
| --------------------------------------- first implementation here
diff --git a/tests/ui/coherence/coherence-overlap-issue-23516-inherent.old.stderr b/tests/ui/coherence/coherence-overlap-issue-23516-inherent.old.stderr
deleted file mode 100644
index 2f3ad62..0000000
--- a/tests/ui/coherence/coherence-overlap-issue-23516-inherent.old.stderr
+++ /dev/null
@@ -1,14 +0,0 @@
-error[E0592]: duplicate definitions with name `dummy`
- --> $DIR/coherence-overlap-issue-23516-inherent.rs:12:25
- |
-LL | impl<T:Sugar> Cake<T> { fn dummy(&self) { } }
- | ^^^^^^^^^^^^^^^ duplicate definitions for `dummy`
-LL |
-LL | impl<U:Sugar> Cake<Box<U>> { fn dummy(&self) { } }
- | --------------- other definition for `dummy`
- |
- = note: downstream crates may implement trait `Sugar` for type `std::boxed::Box<_>`
-
-error: aborting due to 1 previous error
-
-For more information about this error, try `rustc --explain E0592`.
diff --git a/tests/ui/coherence/coherence-overlap-issue-23516-inherent.rs b/tests/ui/coherence/coherence-overlap-issue-23516-inherent.rs
index 53b0a40..a272e62 100644
--- a/tests/ui/coherence/coherence-overlap-issue-23516-inherent.rs
+++ b/tests/ui/coherence/coherence-overlap-issue-23516-inherent.rs
@@ -1,6 +1,3 @@
-//@ revisions: old next
-//@[next] compile-flags: -Znext-solver
-
// Tests that we consider `Box<U>: !Sugar` to be ambiguous, even
// though we see no impl of `Sugar` for `Box`. Therefore, an overlap
// error is reported for the following pair of impls (#23516).
diff --git a/tests/ui/coherence/coherence-overlap-issue-23516-inherent.next.stderr b/tests/ui/coherence/coherence-overlap-issue-23516-inherent.stderr
similarity index 89%
rename from tests/ui/coherence/coherence-overlap-issue-23516-inherent.next.stderr
rename to tests/ui/coherence/coherence-overlap-issue-23516-inherent.stderr
index 2f3ad62..aacdeb5 100644
--- a/tests/ui/coherence/coherence-overlap-issue-23516-inherent.next.stderr
+++ b/tests/ui/coherence/coherence-overlap-issue-23516-inherent.stderr
@@ -1,5 +1,5 @@
error[E0592]: duplicate definitions with name `dummy`
- --> $DIR/coherence-overlap-issue-23516-inherent.rs:12:25
+ --> $DIR/coherence-overlap-issue-23516-inherent.rs:9:25
|
LL | impl<T:Sugar> Cake<T> { fn dummy(&self) { } }
| ^^^^^^^^^^^^^^^ duplicate definitions for `dummy`
diff --git a/tests/ui/coherence/coherence-overlap-issue-23516.old.stderr b/tests/ui/coherence/coherence-overlap-issue-23516.old.stderr
deleted file mode 100644
index b949477..0000000
--- a/tests/ui/coherence/coherence-overlap-issue-23516.old.stderr
+++ /dev/null
@@ -1,13 +0,0 @@
-error[E0119]: conflicting implementations of trait `Sweet` for type `Box<_>`
- --> $DIR/coherence-overlap-issue-23516.rs:11:1
- |
-LL | impl<T:Sugar> Sweet for T { }
- | ------------------------- first implementation here
-LL | impl<U:Sugar> Sweet for Box<U> { }
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `Box<_>`
- |
- = note: downstream crates may implement trait `Sugar` for type `std::boxed::Box<_>`
-
-error: aborting due to 1 previous error
-
-For more information about this error, try `rustc --explain E0119`.
diff --git a/tests/ui/coherence/coherence-overlap-issue-23516.rs b/tests/ui/coherence/coherence-overlap-issue-23516.rs
index 620e00c..63e42e8 100644
--- a/tests/ui/coherence/coherence-overlap-issue-23516.rs
+++ b/tests/ui/coherence/coherence-overlap-issue-23516.rs
@@ -1,6 +1,3 @@
-//@ revisions: old next
-//@[next] compile-flags: -Znext-solver
-
// Tests that we consider `Box<U>: !Sugar` to be ambiguous, even
// though we see no impl of `Sugar` for `Box`. Therefore, an overlap
// error is reported for the following pair of impls (#23516).
diff --git a/tests/ui/coherence/coherence-overlap-issue-23516.next.stderr b/tests/ui/coherence/coherence-overlap-issue-23516.stderr
similarity index 90%
rename from tests/ui/coherence/coherence-overlap-issue-23516.next.stderr
rename to tests/ui/coherence/coherence-overlap-issue-23516.stderr
index b949477..7b1b240 100644
--- a/tests/ui/coherence/coherence-overlap-issue-23516.next.stderr
+++ b/tests/ui/coherence/coherence-overlap-issue-23516.stderr
@@ -1,5 +1,5 @@
error[E0119]: conflicting implementations of trait `Sweet` for type `Box<_>`
- --> $DIR/coherence-overlap-issue-23516.rs:11:1
+ --> $DIR/coherence-overlap-issue-23516.rs:8:1
|
LL | impl<T:Sugar> Sweet for T { }
| ------------------------- first implementation here
diff --git a/tests/ui/coherence/coherence-overlap-negate-not-use-feature-gate.stderr b/tests/ui/coherence/coherence-overlap-negate-not-use-feature-gate.stderr
index 21c82ee..c5bb695 100644
--- a/tests/ui/coherence/coherence-overlap-negate-not-use-feature-gate.stderr
+++ b/tests/ui/coherence/coherence-overlap-negate-not-use-feature-gate.stderr
@@ -5,6 +5,8 @@
| --------------------------- first implementation here
LL | impl<U> Foo for &U {}
| ^^^^^^^^^^^^^^^^^^ conflicting implementation for `&_`
+ |
+ = note: downstream crates may implement trait `std::ops::DerefMut` for type `&_`
error: aborting due to 1 previous error
diff --git a/tests/ui/coherence/coherence-overlap-unnormalizable-projection-0.classic.stderr b/tests/ui/coherence/coherence-overlap-unnormalizable-projection-0.classic.stderr
deleted file mode 100644
index 2ffb600..0000000
--- a/tests/ui/coherence/coherence-overlap-unnormalizable-projection-0.classic.stderr
+++ /dev/null
@@ -1,19 +0,0 @@
-error[E0119]: conflicting implementations of trait `Trait` for type `Box<_>`
- --> $DIR/coherence-overlap-unnormalizable-projection-0.rs:27:1
- |
-LL | / impl<T> Trait for T
-LL | | where
-LL | | T: 'static,
-LL | | for<'a> T: WithAssoc<'a>,
-LL | | for<'a> <T as WithAssoc<'a>>::Assoc: WhereBound,
- | |____________________________________________________- first implementation here
-...
-LL | impl<T> Trait for Box<T> {}
- | ^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `Box<_>`
- |
- = note: downstream crates may implement trait `WithAssoc<'a>` for type `std::boxed::Box<_>`
- = note: downstream crates may implement trait `WhereBound` for type `<std::boxed::Box<_> as WithAssoc<'a>>::Assoc`
-
-error: aborting due to 1 previous error
-
-For more information about this error, try `rustc --explain E0119`.
diff --git a/tests/ui/coherence/coherence-overlap-unnormalizable-projection-0.rs b/tests/ui/coherence/coherence-overlap-unnormalizable-projection-0.rs
index b8b6d88..0695076 100644
--- a/tests/ui/coherence/coherence-overlap-unnormalizable-projection-0.rs
+++ b/tests/ui/coherence/coherence-overlap-unnormalizable-projection-0.rs
@@ -2,9 +2,6 @@
// "Coherence incorrectly considers `unnormalizable_projection: Trait` to not hold even if it could"
#![crate_type = "lib"]
-//@ revisions: classic next
-//@[next] compile-flags: -Znext-solver
-
trait WhereBound {}
impl WhereBound for () {}
diff --git a/tests/ui/coherence/coherence-overlap-unnormalizable-projection-0.next.stderr b/tests/ui/coherence/coherence-overlap-unnormalizable-projection-0.stderr
similarity index 90%
rename from tests/ui/coherence/coherence-overlap-unnormalizable-projection-0.next.stderr
rename to tests/ui/coherence/coherence-overlap-unnormalizable-projection-0.stderr
index 99abdf6..57befbe 100644
--- a/tests/ui/coherence/coherence-overlap-unnormalizable-projection-0.next.stderr
+++ b/tests/ui/coherence/coherence-overlap-unnormalizable-projection-0.stderr
@@ -1,5 +1,5 @@
error[E0119]: conflicting implementations of trait `Trait` for type `Box<_>`
- --> $DIR/coherence-overlap-unnormalizable-projection-0.rs:27:1
+ --> $DIR/coherence-overlap-unnormalizable-projection-0.rs:24:1
|
LL | / impl<T> Trait for T
LL | | where
diff --git a/tests/ui/coherence/coherence-overlap-unnormalizable-projection-1.classic.stderr b/tests/ui/coherence/coherence-overlap-unnormalizable-projection-1.classic.stderr
deleted file mode 100644
index 49b236f..0000000
--- a/tests/ui/coherence/coherence-overlap-unnormalizable-projection-1.classic.stderr
+++ /dev/null
@@ -1,19 +0,0 @@
-error[E0119]: conflicting implementations of trait `Trait` for type `Box<_>`
- --> $DIR/coherence-overlap-unnormalizable-projection-1.rs:26:1
- |
-LL | / impl<T> Trait for T
-LL | | where
-LL | | T: 'static,
-LL | | for<'a> T: WithAssoc<'a>,
-LL | | for<'a> Box<<T as WithAssoc<'a>>::Assoc>: WhereBound,
- | |_________________________________________________________- first implementation here
-...
-LL | impl<T> Trait for Box<T> {}
- | ^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `Box<_>`
- |
- = note: downstream crates may implement trait `WithAssoc<'a>` for type `std::boxed::Box<_>`
- = note: downstream crates may implement trait `WhereBound` for type `std::boxed::Box<<std::boxed::Box<_> as WithAssoc<'a>>::Assoc>`
-
-error: aborting due to 1 previous error
-
-For more information about this error, try `rustc --explain E0119`.
diff --git a/tests/ui/coherence/coherence-overlap-unnormalizable-projection-1.rs b/tests/ui/coherence/coherence-overlap-unnormalizable-projection-1.rs
index 8eeadb3..f5fb5ae 100644
--- a/tests/ui/coherence/coherence-overlap-unnormalizable-projection-1.rs
+++ b/tests/ui/coherence/coherence-overlap-unnormalizable-projection-1.rs
@@ -2,9 +2,6 @@
// "Coherence incorrectly considers `unnormalizable_projection: Trait` to not hold even if it could"
#![crate_type = "lib"]
-//@ revisions: classic next
-//@[next] compile-flags: -Znext-solver
-
pub trait WhereBound {}
impl WhereBound for () {}
diff --git a/tests/ui/coherence/coherence-overlap-unnormalizable-projection-1.next.stderr b/tests/ui/coherence/coherence-overlap-unnormalizable-projection-1.stderr
similarity index 91%
rename from tests/ui/coherence/coherence-overlap-unnormalizable-projection-1.next.stderr
rename to tests/ui/coherence/coherence-overlap-unnormalizable-projection-1.stderr
index 781ab0f..22673ce 100644
--- a/tests/ui/coherence/coherence-overlap-unnormalizable-projection-1.next.stderr
+++ b/tests/ui/coherence/coherence-overlap-unnormalizable-projection-1.stderr
@@ -1,5 +1,5 @@
error[E0119]: conflicting implementations of trait `Trait` for type `Box<_>`
- --> $DIR/coherence-overlap-unnormalizable-projection-1.rs:26:1
+ --> $DIR/coherence-overlap-unnormalizable-projection-1.rs:23:1
|
LL | / impl<T> Trait for T
LL | | where
diff --git a/tests/ui/coherence/coherent-due-to-fulfill.rs b/tests/ui/coherence/coherent-due-to-fulfill.rs
index 084f9be..f4555ee 100644
--- a/tests/ui/coherence/coherent-due-to-fulfill.rs
+++ b/tests/ui/coherence/coherent-due-to-fulfill.rs
@@ -1,6 +1,4 @@
-//@ compile-flags: -Znext-solver=coherence
//@ check-pass
-
trait Mirror {
type Assoc;
}
diff --git a/tests/ui/coherence/incoherent-even-though-we-fulfill.rs b/tests/ui/coherence/incoherent-even-though-we-fulfill.rs
index b3c9cf3..28e5b6d 100644
--- a/tests/ui/coherence/incoherent-even-though-we-fulfill.rs
+++ b/tests/ui/coherence/incoherent-even-though-we-fulfill.rs
@@ -1,5 +1,3 @@
-//@ compile-flags: -Znext-solver=coherence
-
trait Mirror {
type Assoc;
}
diff --git a/tests/ui/coherence/incoherent-even-though-we-fulfill.stderr b/tests/ui/coherence/incoherent-even-though-we-fulfill.stderr
index b16465d..0b15a4e 100644
--- a/tests/ui/coherence/incoherent-even-though-we-fulfill.stderr
+++ b/tests/ui/coherence/incoherent-even-though-we-fulfill.stderr
@@ -1,5 +1,5 @@
error[E0119]: conflicting implementations of trait `Foo` for type `()`
- --> $DIR/incoherent-even-though-we-fulfill.rs:17:1
+ --> $DIR/incoherent-even-though-we-fulfill.rs:15:1
|
LL | impl<T> Foo for T where (): Mirror<Assoc = T> {}
| --------------------------------------------- first implementation here
diff --git a/tests/ui/coherence/inter-crate-ambiguity-causes-notes.old.stderr b/tests/ui/coherence/inter-crate-ambiguity-causes-notes.old.stderr
deleted file mode 100644
index 74be598..0000000
--- a/tests/ui/coherence/inter-crate-ambiguity-causes-notes.old.stderr
+++ /dev/null
@@ -1,17 +0,0 @@
-error[E0119]: conflicting implementations of trait `From<()>` for type `S`
- --> $DIR/inter-crate-ambiguity-causes-notes.rs:12:1
- |
-LL | impl From<()> for S {
- | ------------------- first implementation here
-...
-LL | / impl<I> From<I> for S
-LL | |
-LL | | where
-LL | | I: Iterator<Item = ()>,
- | |___________________________^ conflicting implementation for `S`
- |
- = note: upstream crates may add a new impl of trait `std::iter::Iterator` for type `()` in future versions
-
-error: aborting due to 1 previous error
-
-For more information about this error, try `rustc --explain E0119`.
diff --git a/tests/ui/coherence/inter-crate-ambiguity-causes-notes.rs b/tests/ui/coherence/inter-crate-ambiguity-causes-notes.rs
index 3dead2f..5b11c78 100644
--- a/tests/ui/coherence/inter-crate-ambiguity-causes-notes.rs
+++ b/tests/ui/coherence/inter-crate-ambiguity-causes-notes.rs
@@ -1,6 +1,3 @@
-//@ revisions: old next
-//@[next] compile-flags: -Znext-solver
-
struct S;
impl From<()> for S {
diff --git a/tests/ui/coherence/inter-crate-ambiguity-causes-notes.next.stderr b/tests/ui/coherence/inter-crate-ambiguity-causes-notes.stderr
similarity index 90%
rename from tests/ui/coherence/inter-crate-ambiguity-causes-notes.next.stderr
rename to tests/ui/coherence/inter-crate-ambiguity-causes-notes.stderr
index 74be598..b322832 100644
--- a/tests/ui/coherence/inter-crate-ambiguity-causes-notes.next.stderr
+++ b/tests/ui/coherence/inter-crate-ambiguity-causes-notes.stderr
@@ -1,5 +1,5 @@
error[E0119]: conflicting implementations of trait `From<()>` for type `S`
- --> $DIR/inter-crate-ambiguity-causes-notes.rs:12:1
+ --> $DIR/inter-crate-ambiguity-causes-notes.rs:9:1
|
LL | impl From<()> for S {
| ------------------- first implementation here
diff --git a/tests/ui/coherence/negative-coherence-check-placeholder-outlives.stderr b/tests/ui/coherence/negative-coherence-check-placeholder-outlives.stderr
index f515c39..bf1ffcb 100644
--- a/tests/ui/coherence/negative-coherence-check-placeholder-outlives.stderr
+++ b/tests/ui/coherence/negative-coherence-check-placeholder-outlives.stderr
@@ -5,6 +5,8 @@
| ------------------------------ first implementation here
LL | impl<T> Bar for Box<T> {}
| ^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `Box<_>`
+ |
+ = note: downstream crates may implement trait `Foo` for type `std::boxed::Box<_>`
error: aborting due to 1 previous error
diff --git a/tests/ui/coherence/negative-coherence-considering-regions.any_lt.stderr b/tests/ui/coherence/negative-coherence-considering-regions.any_lt.stderr
index f24de10..97e2e97 100644
--- a/tests/ui/coherence/negative-coherence-considering-regions.any_lt.stderr
+++ b/tests/ui/coherence/negative-coherence-considering-regions.any_lt.stderr
@@ -6,6 +6,8 @@
...
LL | impl<T> Bar for &T {}
| ^^^^^^^^^^^^^^^^^^ conflicting implementation for `&_`
+ |
+ = note: downstream crates may implement trait `Foo` for type `&_`
error: aborting due to 1 previous error
diff --git a/tests/ui/coherence/negative-coherence-placeholder-region-constraints-on-unification.explicit.stderr b/tests/ui/coherence/negative-coherence-placeholder-region-constraints-on-unification.explicit.stderr
index 832c56a..8d59cbc 100644
--- a/tests/ui/coherence/negative-coherence-placeholder-region-constraints-on-unification.explicit.stderr
+++ b/tests/ui/coherence/negative-coherence-placeholder-region-constraints-on-unification.explicit.stderr
@@ -8,6 +8,7 @@
|
= warning: the behavior may change in a future release
= note: for more information, see issue #56105 <https://github.com/rust-lang/rust/issues/56105>
+ = note: downstream crates may implement trait `Marker` for type `&_`
= note: this behavior recently changed as a result of a bug fix; see rust-lang/rust#56105 for details
note: the lint level is defined here
--> $DIR/negative-coherence-placeholder-region-constraints-on-unification.rs:4:11
diff --git a/tests/ui/coherence/normalize-for-errors.current.stderr b/tests/ui/coherence/normalize-for-errors.current.stderr
deleted file mode 100644
index dcbb73b..0000000
--- a/tests/ui/coherence/normalize-for-errors.current.stderr
+++ /dev/null
@@ -1,14 +0,0 @@
-error[E0119]: conflicting implementations of trait `MyTrait<_>` for type `(Box<(MyType,)>, _)`
- --> $DIR/normalize-for-errors.rs:17:1
- |
-LL | impl<T: Copy, S: Iterator> MyTrait<S> for (T, S::Item) {}
- | ------------------------------------------------------ first implementation here
-LL |
-LL | impl<S: Iterator> MyTrait<S> for (Box<<(MyType,) as Mirror>::Assoc>, S::Item) {}
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `(Box<(MyType,)>, _)`
- |
- = note: upstream crates may add a new impl of trait `std::marker::Copy` for type `std::boxed::Box<(MyType,)>` in future versions
-
-error: aborting due to 1 previous error
-
-For more information about this error, try `rustc --explain E0119`.
diff --git a/tests/ui/coherence/normalize-for-errors.rs b/tests/ui/coherence/normalize-for-errors.rs
index c17bb76..3ef91eb 100644
--- a/tests/ui/coherence/normalize-for-errors.rs
+++ b/tests/ui/coherence/normalize-for-errors.rs
@@ -1,7 +1,3 @@
-//@ revisions: current next
-//@ ignore-compare-mode-next-solver (explicit revisions)
-//@[next] compile-flags: -Znext-solver
-
struct MyType;
trait MyTrait<S> {}
@@ -18,6 +14,6 @@ impl<S: Iterator> MyTrait<S> for (Box<<(MyType,) as Mirror>::Assoc>, S::Item) {}
//~^ ERROR conflicting implementations of trait `MyTrait<_>` for type `(Box<(MyType,)>,
//~| NOTE conflicting implementation for `(Box<(MyType,)>,
//~| NOTE upstream crates may add a new impl of trait `std::marker::Copy` for type `std::boxed::Box<(MyType,)>` in future versions
-//[next]~| NOTE upstream crates may add a new impl of trait `std::clone::Clone` for type `std::boxed::Box<(MyType,)>` in future versions
+//~| NOTE upstream crates may add a new impl of trait `std::clone::Clone` for type `std::boxed::Box<(MyType,)>` in future versions
fn main() {}
diff --git a/tests/ui/coherence/normalize-for-errors.next.stderr b/tests/ui/coherence/normalize-for-errors.stderr
similarity index 95%
rename from tests/ui/coherence/normalize-for-errors.next.stderr
rename to tests/ui/coherence/normalize-for-errors.stderr
index 44952dc..6fbcf5b 100644
--- a/tests/ui/coherence/normalize-for-errors.next.stderr
+++ b/tests/ui/coherence/normalize-for-errors.stderr
@@ -1,5 +1,5 @@
error[E0119]: conflicting implementations of trait `MyTrait<_>` for type `(Box<(MyType,)>, <_ as Iterator>::Item)`
- --> $DIR/normalize-for-errors.rs:17:1
+ --> $DIR/normalize-for-errors.rs:13:1
|
LL | impl<T: Copy, S: Iterator> MyTrait<S> for (T, S::Item) {}
| ------------------------------------------------------ first implementation here
diff --git a/tests/ui/coherence/occurs-check/associated-type.next.stderr b/tests/ui/coherence/occurs-check/associated-type.next.stderr
index 9544bdb..466b991 100644
--- a/tests/ui/coherence/occurs-check/associated-type.next.stderr
+++ b/tests/ui/coherence/occurs-check/associated-type.next.stderr
@@ -3,7 +3,7 @@
WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: [*const ?1t, '^0.Named(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), "'a")], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit), .. }
WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: [*const ?1t, '^0.Named(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), "'a")], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit), .. }
error[E0119]: conflicting implementations of trait `Overlap<for<'a> fn(&'a (), ())>` for type `for<'a> fn(&'a (), ())`
- --> $DIR/associated-type.rs:31:1
+ --> $DIR/associated-type.rs:32:1
|
LL | impl<T> Overlap<T> for T {
| ------------------------ first implementation here
@@ -17,7 +17,7 @@
= note: this behavior recently changed as a result of a bug fix; see rust-lang/rust#56105 for details
error[E0284]: type annotations needed: cannot normalize `<for<'a> fn(&'a (), ()) as Overlap<for<'a> fn(&'a (), ())>>::Assoc`
- --> $DIR/associated-type.rs:44:59
+ --> $DIR/associated-type.rs:45:59
|
LL | foo::<for<'a> fn(&'a (), ()), for<'a> fn(&'a (), ())>(3usize);
| ^^^^^^ cannot normalize `<for<'a> fn(&'a (), ()) as Overlap<for<'a> fn(&'a (), ())>>::Assoc`
diff --git a/tests/ui/coherence/occurs-check/associated-type.old.stderr b/tests/ui/coherence/occurs-check/associated-type.old.stderr
index ccc7f30..1e0345f 100644
--- a/tests/ui/coherence/occurs-check/associated-type.old.stderr
+++ b/tests/ui/coherence/occurs-check/associated-type.old.stderr
@@ -1,13 +1,9 @@
WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: [*const ?1t, '^0.Named(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), "'a")], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit), .. }
- WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: [*const ?1t, !2_0.Named(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), "'a")], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit), .. }
WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: [*const ?1t, '^0.Named(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), "'a")], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit), .. }
- WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: [*const ?1t, !2_0.Named(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), "'a")], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit), .. }
WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: [*const ?1t, '^0.Named(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), "'a")], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit), .. }
- WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: [*const ?1t, !2_0.Named(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), "'a")], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit), .. }
WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: [*const ?1t, '^0.Named(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), "'a")], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit), .. }
- WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: [*const ?1t, !2_0.Named(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), "'a")], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit), .. }
-error[E0119]: conflicting implementations of trait `Overlap<for<'a> fn(&'a (), _)>` for type `for<'a> fn(&'a (), _)`
- --> $DIR/associated-type.rs:31:1
+error[E0119]: conflicting implementations of trait `Overlap<for<'a> fn(&'a (), ())>` for type `for<'a> fn(&'a (), ())`
+ --> $DIR/associated-type.rs:32:1
|
LL | impl<T> Overlap<T> for T {
| ------------------------ first implementation here
@@ -16,7 +12,7 @@
LL | |
LL | | where
LL | | for<'a> *const T: ToUnit<'a>,
- | |_________________________________^ conflicting implementation for `for<'a> fn(&'a (), _)`
+ | |_________________________________^ conflicting implementation for `for<'a> fn(&'a (), ())`
|
= note: this behavior recently changed as a result of a bug fix; see rust-lang/rust#56105 for details
diff --git a/tests/ui/coherence/occurs-check/associated-type.rs b/tests/ui/coherence/occurs-check/associated-type.rs
index df03d5f..e450c33 100644
--- a/tests/ui/coherence/occurs-check/associated-type.rs
+++ b/tests/ui/coherence/occurs-check/associated-type.rs
@@ -1,4 +1,5 @@
//@ revisions: old next
+//@ ignore-compare-mode-next-solver (explicit revisions)
//@[next] compile-flags: -Znext-solver
// A regression test for #105787
diff --git a/tests/ui/coherence/occurs-check/opaques.current.stderr b/tests/ui/coherence/occurs-check/opaques.current.stderr
new file mode 100644
index 0000000..f3fc220
--- /dev/null
+++ b/tests/ui/coherence/occurs-check/opaques.current.stderr
@@ -0,0 +1,12 @@
+error[E0119]: conflicting implementations of trait `Trait<_>`
+ --> $DIR/opaques.rs:28:1
+ |
+LL | impl<T> Trait<T> for T {
+ | ---------------------- first implementation here
+...
+LL | impl<T> Trait<T> for defining_scope::Alias<T> {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0119`.
diff --git a/tests/ui/coherence/occurs-check/opaques.next.stderr b/tests/ui/coherence/occurs-check/opaques.next.stderr
index 11d1edc..3de4799 100644
--- a/tests/ui/coherence/occurs-check/opaques.next.stderr
+++ b/tests/ui/coherence/occurs-check/opaques.next.stderr
@@ -1,5 +1,5 @@
error[E0119]: conflicting implementations of trait `Trait<_>`
- --> $DIR/opaques.rs:30:1
+ --> $DIR/opaques.rs:28:1
|
LL | impl<T> Trait<T> for T {
| ---------------------- first implementation here
@@ -8,7 +8,7 @@
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation
error[E0282]: type annotations needed
- --> $DIR/opaques.rs:13:20
+ --> $DIR/opaques.rs:11:20
|
LL | pub fn cast<T>(x: Container<Alias<T>, T>) -> Container<T, T> {
| ^ cannot infer type
diff --git a/tests/ui/coherence/occurs-check/opaques.rs b/tests/ui/coherence/occurs-check/opaques.rs
index 241a247..e197256 100644
--- a/tests/ui/coherence/occurs-check/opaques.rs
+++ b/tests/ui/coherence/occurs-check/opaques.rs
@@ -1,10 +1,8 @@
-//@revisions: old next
+//@ revisions: current next
+//@ ignore-compare-mode-next-solver (explicit revisions)
//@[next] compile-flags: -Znext-solver
// A regression test for #105787
-
-//@[old] known-bug: #105787
-//@[old] check-pass
#![feature(type_alias_impl_trait)]
mod defining_scope {
use super::*;
@@ -28,7 +26,7 @@ impl<T> Trait<T> for T {
type Assoc = Box<u32>;
}
impl<T> Trait<T> for defining_scope::Alias<T> {
- //[next]~^ ERROR conflicting implementations of trait
+ //~^ ERROR conflicting implementations of trait
type Assoc = usize;
}
diff --git a/tests/ui/coherence/orphan-check-opaque-types-not-covering.next.stderr b/tests/ui/coherence/orphan-check-opaque-types-not-covering.next.stderr
deleted file mode 100644
index 44f76f3..0000000
--- a/tests/ui/coherence/orphan-check-opaque-types-not-covering.next.stderr
+++ /dev/null
@@ -1,21 +0,0 @@
-error[E0210]: type parameter `T` must be covered by another type when it appears before the first local type (`Local`)
- --> $DIR/orphan-check-opaque-types-not-covering.rs:17:6
- |
-LL | impl<T> foreign::Trait0<Local, T, ()> for Identity<T> {}
- | ^ type parameter `T` must be covered by another type when it appears before the first local type (`Local`)
- |
- = note: implementing a foreign trait is only possible if at least one of the types for which it is implemented is local, and no uncovered type parameters appear before that first local type
- = note: in this case, 'before' refers to the following order: `impl<..> ForeignTrait<T1, ..., Tn> for T0`, where `T0` is the first and `Tn` is the last
-
-error[E0210]: type parameter `T` must be covered by another type when it appears before the first local type (`Local`)
- --> $DIR/orphan-check-opaque-types-not-covering.rs:26:6
- |
-LL | impl<T> foreign::Trait1<Local, T> for Opaque<T> {}
- | ^ type parameter `T` must be covered by another type when it appears before the first local type (`Local`)
- |
- = note: implementing a foreign trait is only possible if at least one of the types for which it is implemented is local, and no uncovered type parameters appear before that first local type
- = note: in this case, 'before' refers to the following order: `impl<..> ForeignTrait<T1, ..., Tn> for T0`, where `T0` is the first and `Tn` is the last
-
-error: aborting due to 2 previous errors
-
-For more information about this error, try `rustc --explain E0210`.
diff --git a/tests/ui/coherence/orphan-check-opaque-types-not-covering.rs b/tests/ui/coherence/orphan-check-opaque-types-not-covering.rs
index 8dc02b0..02e9eb6 100644
--- a/tests/ui/coherence/orphan-check-opaque-types-not-covering.rs
+++ b/tests/ui/coherence/orphan-check-opaque-types-not-covering.rs
@@ -1,8 +1,5 @@
// Opaque types never cover type parameters.
-//@ revisions: classic next
-//@[next] compile-flags: -Znext-solver
-
//@ aux-crate:foreign=parametrized-trait.rs
//@ edition:2021
diff --git a/tests/ui/coherence/orphan-check-opaque-types-not-covering.classic.stderr b/tests/ui/coherence/orphan-check-opaque-types-not-covering.stderr
similarity index 92%
rename from tests/ui/coherence/orphan-check-opaque-types-not-covering.classic.stderr
rename to tests/ui/coherence/orphan-check-opaque-types-not-covering.stderr
index 44f76f3..57f5bbd 100644
--- a/tests/ui/coherence/orphan-check-opaque-types-not-covering.classic.stderr
+++ b/tests/ui/coherence/orphan-check-opaque-types-not-covering.stderr
@@ -1,5 +1,5 @@
error[E0210]: type parameter `T` must be covered by another type when it appears before the first local type (`Local`)
- --> $DIR/orphan-check-opaque-types-not-covering.rs:17:6
+ --> $DIR/orphan-check-opaque-types-not-covering.rs:14:6
|
LL | impl<T> foreign::Trait0<Local, T, ()> for Identity<T> {}
| ^ type parameter `T` must be covered by another type when it appears before the first local type (`Local`)
@@ -8,7 +8,7 @@
= note: in this case, 'before' refers to the following order: `impl<..> ForeignTrait<T1, ..., Tn> for T0`, where `T0` is the first and `Tn` is the last
error[E0210]: type parameter `T` must be covered by another type when it appears before the first local type (`Local`)
- --> $DIR/orphan-check-opaque-types-not-covering.rs:26:6
+ --> $DIR/orphan-check-opaque-types-not-covering.rs:23:6
|
LL | impl<T> foreign::Trait1<Local, T> for Opaque<T> {}
| ^ type parameter `T` must be covered by another type when it appears before the first local type (`Local`)
diff --git a/tests/ui/coherence/orphan-check-projections-covering.rs b/tests/ui/coherence/orphan-check-projections-covering.rs
index ae1917e..8047844 100644
--- a/tests/ui/coherence/orphan-check-projections-covering.rs
+++ b/tests/ui/coherence/orphan-check-projections-covering.rs
@@ -5,9 +5,6 @@
// first which would've lead to real-word regressions.
//@ check-pass
-//@ revisions: classic next
-//@[next] compile-flags: -Znext-solver
-
//@ aux-crate:foreign=parametrized-trait.rs
//@ edition:2021
diff --git a/tests/ui/coherence/orphan-check-weak-aliases-not-covering.next.stderr b/tests/ui/coherence/orphan-check-weak-aliases-not-covering.next.stderr
deleted file mode 100644
index 276833f..0000000
--- a/tests/ui/coherence/orphan-check-weak-aliases-not-covering.next.stderr
+++ /dev/null
@@ -1,12 +0,0 @@
-error[E0210]: type parameter `T` must be covered by another type when it appears before the first local type (`Local`)
- --> $DIR/orphan-check-weak-aliases-not-covering.rs:16:6
- |
-LL | impl<T> foreign::Trait1<Local, T> for Identity<T> {}
- | ^ type parameter `T` must be covered by another type when it appears before the first local type (`Local`)
- |
- = note: implementing a foreign trait is only possible if at least one of the types for which it is implemented is local, and no uncovered type parameters appear before that first local type
- = note: in this case, 'before' refers to the following order: `impl<..> ForeignTrait<T1, ..., Tn> for T0`, where `T0` is the first and `Tn` is the last
-
-error: aborting due to 1 previous error
-
-For more information about this error, try `rustc --explain E0210`.
diff --git a/tests/ui/coherence/orphan-check-weak-aliases-not-covering.rs b/tests/ui/coherence/orphan-check-weak-aliases-not-covering.rs
index 9ebc45a..6d9bccc 100644
--- a/tests/ui/coherence/orphan-check-weak-aliases-not-covering.rs
+++ b/tests/ui/coherence/orphan-check-weak-aliases-not-covering.rs
@@ -1,8 +1,5 @@
// Weak aliases might not cover type parameters.
-//@ revisions: classic next
-//@[next] compile-flags: -Znext-solver
-
//@ aux-crate:foreign=parametrized-trait.rs
//@ edition:2021
diff --git a/tests/ui/coherence/orphan-check-weak-aliases-not-covering.classic.stderr b/tests/ui/coherence/orphan-check-weak-aliases-not-covering.stderr
similarity index 92%
rename from tests/ui/coherence/orphan-check-weak-aliases-not-covering.classic.stderr
rename to tests/ui/coherence/orphan-check-weak-aliases-not-covering.stderr
index 276833f..df91514 100644
--- a/tests/ui/coherence/orphan-check-weak-aliases-not-covering.classic.stderr
+++ b/tests/ui/coherence/orphan-check-weak-aliases-not-covering.stderr
@@ -1,5 +1,5 @@
error[E0210]: type parameter `T` must be covered by another type when it appears before the first local type (`Local`)
- --> $DIR/orphan-check-weak-aliases-not-covering.rs:16:6
+ --> $DIR/orphan-check-weak-aliases-not-covering.rs:13:6
|
LL | impl<T> foreign::Trait1<Local, T> for Identity<T> {}
| ^ type parameter `T` must be covered by another type when it appears before the first local type (`Local`)
diff --git a/tests/ui/coherence/skip-reporting-if-references-err.current.stderr b/tests/ui/coherence/skip-reporting-if-references-err.current.stderr
deleted file mode 100644
index 5eef325..0000000
--- a/tests/ui/coherence/skip-reporting-if-references-err.current.stderr
+++ /dev/null
@@ -1,27 +0,0 @@
-error[E0726]: implicit elided lifetime not allowed here
- --> $DIR/skip-reporting-if-references-err.rs:10:9
- |
-LL | impl<T> ToUnit for T {}
- | ^^^^^^ expected lifetime parameter
- |
-help: indicate the anonymous lifetime
- |
-LL | impl<T> ToUnit<'_> for T {}
- | ++++
-
-error[E0277]: the trait bound `for<'a> (): ToUnit<'a>` is not satisfied
- --> $DIR/skip-reporting-if-references-err.rs:15:29
- |
-LL | impl Overlap for for<'a> fn(<() as ToUnit<'a>>::Unit) {}
- | ^^^^^^^^^^^^^^^^^^^^^^^^ the trait `for<'a> ToUnit<'a>` is not implemented for `()`
-
-error[E0277]: the trait bound `for<'a> (): ToUnit<'a>` is not satisfied
- --> $DIR/skip-reporting-if-references-err.rs:15:18
- |
-LL | impl Overlap for for<'a> fn(<() as ToUnit<'a>>::Unit) {}
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `for<'a> ToUnit<'a>` is not implemented for `()`
-
-error: aborting due to 3 previous errors
-
-Some errors have detailed explanations: E0277, E0726.
-For more information about an error, try `rustc --explain E0277`.
diff --git a/tests/ui/coherence/skip-reporting-if-references-err.rs b/tests/ui/coherence/skip-reporting-if-references-err.rs
index f9eaa49..dd8a71c 100644
--- a/tests/ui/coherence/skip-reporting-if-references-err.rs
+++ b/tests/ui/coherence/skip-reporting-if-references-err.rs
@@ -1,8 +1,4 @@
// Regression test for #121006.
-//@ revisions: current next
-//@ ignore-compare-mode-next-solver (explicit revisions)
-//@[next] compile-flags: -Znext-solver
-
trait ToUnit<'a> {
type Unit;
}
@@ -13,7 +9,5 @@ impl<T> ToUnit for T {}
trait Overlap {}
impl<U> Overlap for fn(U) {}
impl Overlap for for<'a> fn(<() as ToUnit<'a>>::Unit) {}
-//[current]~^ ERROR the trait bound `for<'a> (): ToUnit<'a>` is not satisfied
-//[current]~| ERROR the trait bound `for<'a> (): ToUnit<'a>` is not satisfied
fn main() {}
diff --git a/tests/ui/coherence/skip-reporting-if-references-err.next.stderr b/tests/ui/coherence/skip-reporting-if-references-err.stderr
similarity index 86%
rename from tests/ui/coherence/skip-reporting-if-references-err.next.stderr
rename to tests/ui/coherence/skip-reporting-if-references-err.stderr
index 5de4cf6..0ff3e88 100644
--- a/tests/ui/coherence/skip-reporting-if-references-err.next.stderr
+++ b/tests/ui/coherence/skip-reporting-if-references-err.stderr
@@ -1,5 +1,5 @@
error[E0726]: implicit elided lifetime not allowed here
- --> $DIR/skip-reporting-if-references-err.rs:10:9
+ --> $DIR/skip-reporting-if-references-err.rs:6:9
|
LL | impl<T> ToUnit for T {}
| ^^^^^^ expected lifetime parameter
diff --git a/tests/ui/coherence/super-traits/super-trait-knowable-1.current.stderr b/tests/ui/coherence/super-traits/super-trait-knowable-1.current.stderr
deleted file mode 100644
index fb01cf1..0000000
--- a/tests/ui/coherence/super-traits/super-trait-knowable-1.current.stderr
+++ /dev/null
@@ -1,13 +0,0 @@
-error[E0119]: conflicting implementations of trait `Overlap<_>` for type `()`
- --> $DIR/super-trait-knowable-1.rs:16:1
- |
-LL | impl<T, U: Sub<T>> Overlap<T> for U {}
- | ----------------------------------- first implementation here
-LL | impl<T> Overlap<T> for () {}
- | ^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `()`
- |
- = note: downstream crates may implement trait `Sub<_>` for type `()`
-
-error: aborting due to 1 previous error
-
-For more information about this error, try `rustc --explain E0119`.
diff --git a/tests/ui/coherence/super-traits/super-trait-knowable-1.rs b/tests/ui/coherence/super-traits/super-trait-knowable-1.rs
index 80df8c1..77af4d0 100644
--- a/tests/ui/coherence/super-traits/super-trait-knowable-1.rs
+++ b/tests/ui/coherence/super-traits/super-trait-knowable-1.rs
@@ -3,10 +3,7 @@
// We therefore elaborate super trait bounds in the implicit negative
// overlap check.
-//@ revisions: current next
-//@ ignore-compare-mode-next-solver (explicit revisions)
-//@[next] compile-flags: -Znext-solver
-//@[next] check-pass
+//@ check-pass
trait Super {}
trait Sub<T>: Super {}
@@ -14,6 +11,5 @@ trait Sub<T>: Super {}
trait Overlap<T> {}
impl<T, U: Sub<T>> Overlap<T> for U {}
impl<T> Overlap<T> for () {}
-//[current]~^ ERROR conflicting implementations
fn main() {}
diff --git a/tests/ui/coherence/super-traits/super-trait-knowable-2.rs b/tests/ui/coherence/super-traits/super-trait-knowable-2.rs
index d1f2e8d..323ee0b 100644
--- a/tests/ui/coherence/super-traits/super-trait-knowable-2.rs
+++ b/tests/ui/coherence/super-traits/super-trait-knowable-2.rs
@@ -9,9 +9,6 @@
// which caused the old solver to emit a `Tensor: TensorValue` goal in
// `fn normalize_to_error` which then failed, causing this test to pass.
-//@ revisions: current next
-//@ ignore-compare-mode-next-solver (explicit revisions)
-//@[next] compile-flags: -Znext-solver
//@ check-pass
pub trait TensorValue {
diff --git a/tests/ui/coherence/super-traits/super-trait-knowable-3.current.stderr b/tests/ui/coherence/super-traits/super-trait-knowable-3.current.stderr
deleted file mode 100644
index 542edb8..0000000
--- a/tests/ui/coherence/super-traits/super-trait-knowable-3.current.stderr
+++ /dev/null
@@ -1,13 +0,0 @@
-error[E0119]: conflicting implementations of trait `Overlap<_>` for type `()`
- --> $DIR/super-trait-knowable-3.rs:19:1
- |
-LL | impl<T, U: Bound<W<T>>> Overlap<T> for U {}
- | ---------------------------------------- first implementation here
-LL | impl<T> Overlap<T> for () {}
- | ^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `()`
- |
- = note: downstream crates may implement trait `Sub<_>` for type `()`
-
-error: aborting due to 1 previous error
-
-For more information about this error, try `rustc --explain E0119`.
diff --git a/tests/ui/coherence/super-traits/super-trait-knowable-3.rs b/tests/ui/coherence/super-traits/super-trait-knowable-3.rs
index 295d7ac..6198d3d 100644
--- a/tests/ui/coherence/super-traits/super-trait-knowable-3.rs
+++ b/tests/ui/coherence/super-traits/super-trait-knowable-3.rs
@@ -2,10 +2,7 @@
// super trait bound is in a nested goal so this would not
// compile if we were to only elaborate root goals.
-//@ revisions: current next
-//@ ignore-compare-mode-next-solver (explicit revisions)
-//@[next] compile-flags: -Znext-solver
-//@[next] check-pass
+//@ check-pass
trait Super {}
trait Sub<T>: Super {}
@@ -17,6 +14,5 @@ impl<T: Sub<U>, U> Bound<W<U>> for T {}
trait Overlap<T> {}
impl<T, U: Bound<W<T>>> Overlap<T> for U {}
impl<T> Overlap<T> for () {}
-//[current]~^ ERROR conflicting implementations of trait `Overlap<_>` for type `()`
fn main() {}
diff --git a/tests/ui/conditional-compilation/invalid-node-range-issue-129166.rs b/tests/ui/conditional-compilation/invalid-node-range-issue-129166.rs
new file mode 100644
index 0000000..794e6fa
--- /dev/null
+++ b/tests/ui/conditional-compilation/invalid-node-range-issue-129166.rs
@@ -0,0 +1,11 @@
+// This was triggering an assertion failure in `NodeRange::new`.
+
+#![feature(cfg_eval)]
+#![feature(stmt_expr_attributes)]
+
+fn f() -> u32 {
+ #[cfg_eval] #[cfg(not(FALSE))] 0
+ //~^ ERROR removing an expression is not supported in this position
+}
+
+fn main() {}
diff --git a/tests/ui/conditional-compilation/invalid-node-range-issue-129166.stderr b/tests/ui/conditional-compilation/invalid-node-range-issue-129166.stderr
new file mode 100644
index 0000000..0699e18
--- /dev/null
+++ b/tests/ui/conditional-compilation/invalid-node-range-issue-129166.stderr
@@ -0,0 +1,8 @@
+error: removing an expression is not supported in this position
+ --> $DIR/invalid-node-range-issue-129166.rs:7:17
+ |
+LL | #[cfg_eval] #[cfg(not(FALSE))] 0
+ | ^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/const-generics/generic_const_exprs/unevaluated-const-ice-119731.rs b/tests/ui/const-generics/generic_const_exprs/unevaluated-const-ice-119731.rs
index 05a3487..42c930f 100644
--- a/tests/ui/const-generics/generic_const_exprs/unevaluated-const-ice-119731.rs
+++ b/tests/ui/const-generics/generic_const_exprs/unevaluated-const-ice-119731.rs
@@ -22,6 +22,7 @@ pub struct v17<const v10: usize, const v7: v11> {
impl v17<512, v0> {
pub const fn v21() -> v18 {}
//~^ ERROR cannot find type `v18` in this scope
+ //~| ERROR duplicate definitions with name `v21`
}
impl<const v10: usize> v17<v10, v2> {
diff --git a/tests/ui/const-generics/generic_const_exprs/unevaluated-const-ice-119731.stderr b/tests/ui/const-generics/generic_const_exprs/unevaluated-const-ice-119731.stderr
index 39f022f..b336f2b 100644
--- a/tests/ui/const-generics/generic_const_exprs/unevaluated-const-ice-119731.stderr
+++ b/tests/ui/const-generics/generic_const_exprs/unevaluated-const-ice-119731.stderr
@@ -1,5 +1,5 @@
error[E0432]: unresolved import `v20::v13`
- --> $DIR/unevaluated-const-ice-119731.rs:37:15
+ --> $DIR/unevaluated-const-ice-119731.rs:38:15
|
LL | pub use v20::{v13, v17};
| ^^^
@@ -23,7 +23,7 @@
| ^^^ help: a type alias with a similar name exists: `v11`
error[E0412]: cannot find type `v18` in this scope
- --> $DIR/unevaluated-const-ice-119731.rs:30:31
+ --> $DIR/unevaluated-const-ice-119731.rs:31:31
|
LL | pub type v11 = [[usize; v4]; v4];
| --------------------------------- similarly named type alias `v11` defined here
@@ -32,7 +32,7 @@
| ^^^ help: a type alias with a similar name exists: `v11`
error[E0422]: cannot find struct, variant or union type `v18` in this scope
- --> $DIR/unevaluated-const-ice-119731.rs:32:13
+ --> $DIR/unevaluated-const-ice-119731.rs:33:13
|
LL | pub type v11 = [[usize; v4]; v4];
| --------------------------------- similarly named type alias `v11` defined here
@@ -73,20 +73,29 @@
|
error: maximum number of nodes exceeded in constant v20::v17::<v10, v2>::{constant#1}
- --> $DIR/unevaluated-const-ice-119731.rs:27:37
+ --> $DIR/unevaluated-const-ice-119731.rs:28:37
|
LL | impl<const v10: usize> v17<v10, v2> {
| ^^
error: maximum number of nodes exceeded in constant v20::v17::<v10, v2>::{constant#1}
- --> $DIR/unevaluated-const-ice-119731.rs:27:37
+ --> $DIR/unevaluated-const-ice-119731.rs:28:37
|
LL | impl<const v10: usize> v17<v10, v2> {
| ^^
|
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
-error: aborting due to 9 previous errors; 2 warnings emitted
+error[E0592]: duplicate definitions with name `v21`
+ --> $DIR/unevaluated-const-ice-119731.rs:23:9
+ |
+LL | pub const fn v21() -> v18 {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^ duplicate definitions for `v21`
+...
+LL | pub const fn v21() -> v18 {
+ | ------------------------- other definition for `v21`
-Some errors have detailed explanations: E0412, E0422, E0425, E0432.
+error: aborting due to 10 previous errors; 2 warnings emitted
+
+Some errors have detailed explanations: E0412, E0422, E0425, E0432, E0592.
For more information about an error, try `rustc --explain E0412`.
diff --git a/tests/ui/const-generics/generic_const_exprs/unknown-alias-defkind-anonconst-ice-116710.rs b/tests/ui/const-generics/generic_const_exprs/unknown-alias-defkind-anonconst-ice-116710.rs
index dd0b1e8..81ac997 100644
--- a/tests/ui/const-generics/generic_const_exprs/unknown-alias-defkind-anonconst-ice-116710.rs
+++ b/tests/ui/const-generics/generic_const_exprs/unknown-alias-defkind-anonconst-ice-116710.rs
@@ -10,6 +10,5 @@ trait Trait {}
impl<const N: u32> Trait for A<N> {}
impl<const N: u32> Trait for A<N> {}
-//~^ ERROR conflicting implementations of trait `Trait` for type `A<_>`
pub fn main() {}
diff --git a/tests/ui/const-generics/generic_const_exprs/unknown-alias-defkind-anonconst-ice-116710.stderr b/tests/ui/const-generics/generic_const_exprs/unknown-alias-defkind-anonconst-ice-116710.stderr
index 80ac96d..e29c49f 100644
--- a/tests/ui/const-generics/generic_const_exprs/unknown-alias-defkind-anonconst-ice-116710.stderr
+++ b/tests/ui/const-generics/generic_const_exprs/unknown-alias-defkind-anonconst-ice-116710.stderr
@@ -4,16 +4,6 @@
LL | struct A<const N: u32 = 1, const M: u32 = u8>;
| ^^ not a value
-error[E0119]: conflicting implementations of trait `Trait` for type `A<_>`
- --> $DIR/unknown-alias-defkind-anonconst-ice-116710.rs:12:1
- |
-LL | impl<const N: u32> Trait for A<N> {}
- | --------------------------------- first implementation here
-LL |
-LL | impl<const N: u32> Trait for A<N> {}
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `A<_>`
+error: aborting due to 1 previous error
-error: aborting due to 2 previous errors
-
-Some errors have detailed explanations: E0119, E0423.
-For more information about an error, try `rustc --explain E0119`.
+For more information about this error, try `rustc --explain E0423`.
diff --git a/tests/ui/const-generics/invariant.rs b/tests/ui/const-generics/invariant.rs
index ee4ad4e..95a28b6 100644
--- a/tests/ui/const-generics/invariant.rs
+++ b/tests/ui/const-generics/invariant.rs
@@ -5,7 +5,7 @@
trait SadBee {
const ASSOC: usize;
}
-// fn(&'static ())` is a supertype of `for<'a> fn(&'a ())` while
+// `fn(&'static ())` is a supertype of `for<'a> fn(&'a ())` while
// we allow two different impls for these types, leading
// to different const eval results.
impl SadBee for for<'a> fn(&'a ()) {
diff --git a/tests/ui/consts/const-float-bits-conv.rs b/tests/ui/consts/const-float-bits-conv.rs
index 3a526c5..869498d 100644
--- a/tests/ui/consts/const-float-bits-conv.rs
+++ b/tests/ui/consts/const-float-bits-conv.rs
@@ -1,10 +1,9 @@
//@ compile-flags: -Zmir-opt-level=0
//@ run-pass
-#![feature(const_float_bits_conv)]
#![feature(const_float_classify)]
-#![feature(f16)]
-#![feature(f128)]
+#![feature(f16, f16_const)]
+#![feature(f128, f128_const)]
#![allow(unused_macro_rules)]
// Don't promote
const fn nop<T>(x: T) -> T { x }
diff --git a/tests/ui/consts/const-float-classify.rs b/tests/ui/consts/const-float-classify.rs
index c64d31a..6e5097f 100644
--- a/tests/ui/consts/const-float-classify.rs
+++ b/tests/ui/consts/const-float-classify.rs
@@ -2,7 +2,6 @@
//@ known-bug: #110395
// FIXME(effects) run-pass
-#![feature(const_float_bits_conv)]
#![feature(const_float_classify)]
#![feature(const_trait_impl, effects)]
#![allow(incomplete_features)]
diff --git a/tests/ui/consts/const-float-classify.stderr b/tests/ui/consts/const-float-classify.stderr
index 38acb8a..a35de8a 100644
--- a/tests/ui/consts/const-float-classify.stderr
+++ b/tests/ui/consts/const-float-classify.stderr
@@ -1,5 +1,5 @@
error: const `impl` for trait `PartialEq` which is not marked with `#[const_trait]`
- --> $DIR/const-float-classify.rs:13:12
+ --> $DIR/const-float-classify.rs:12:12
|
LL | impl const PartialEq<NonDet> for bool {
| ^^^^^^^^^^^^^^^^^
diff --git a/tests/ui/consts/const-ptr-is-null.rs b/tests/ui/consts/const-ptr-is-null.rs
new file mode 100644
index 0000000..82c293c
--- /dev/null
+++ b/tests/ui/consts/const-ptr-is-null.rs
@@ -0,0 +1,20 @@
+#![feature(const_ptr_is_null)]
+use std::ptr;
+
+const IS_NULL: () = {
+ assert!(ptr::null::<u8>().is_null());
+};
+const IS_NOT_NULL: () = {
+ assert!(!ptr::null::<u8>().wrapping_add(1).is_null());
+};
+
+const MAYBE_NULL: () = {
+ let x = 15;
+ let ptr = &x as *const i32;
+ // This one is still unambiguous...
+ assert!(!ptr.is_null());
+ // but once we shift outside the allocation, we might become null.
+ assert!(!ptr.wrapping_sub(512).is_null()); //~inside `MAYBE_NULL`
+};
+
+fn main() {}
diff --git a/tests/ui/consts/const-ptr-is-null.stderr b/tests/ui/consts/const-ptr-is-null.stderr
new file mode 100644
index 0000000..20e44a1
--- /dev/null
+++ b/tests/ui/consts/const-ptr-is-null.stderr
@@ -0,0 +1,19 @@
+error[E0080]: evaluation of constant value failed
+ --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
+ |
+ = note: the evaluated program panicked at 'null-ness of this pointer cannot be determined in const context', $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
+ |
+note: inside `std::ptr::const_ptr::<impl *const T>::is_null::const_impl`
+ --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
+note: inside `std::ptr::const_ptr::<impl *const i32>::is_null`
+ --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
+note: inside `MAYBE_NULL`
+ --> $DIR/const-ptr-is-null.rs:17:14
+ |
+LL | assert!(!ptr.wrapping_sub(512).is_null());
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ = note: this error originates in the macro `$crate::panic::panic_2021` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0080`.
diff --git a/tests/ui/consts/missing_assoc_const_type.rs b/tests/ui/consts/missing_assoc_const_type.rs
index 8d95e3d..633998e 100644
--- a/tests/ui/consts/missing_assoc_const_type.rs
+++ b/tests/ui/consts/missing_assoc_const_type.rs
@@ -16,7 +16,7 @@ impl Range for TwoDigits {
const fn digits(x: u8) -> usize {
match x {
- TwoDigits::FIRST..=TwoDigits::LAST => 0,
+ TwoDigits::FIRST..=TwoDigits::LAST => 0, //~ ERROR: could not evaluate constant pattern
0..=9 | 100..=255 => panic!(),
}
}
diff --git a/tests/ui/consts/missing_assoc_const_type.stderr b/tests/ui/consts/missing_assoc_const_type.stderr
index 28af1f0..ef7ff96 100644
--- a/tests/ui/consts/missing_assoc_const_type.stderr
+++ b/tests/ui/consts/missing_assoc_const_type.stderr
@@ -4,5 +4,11 @@
LL | const FIRST: = 10;
| ^ help: provide a type for the associated constant: `u8`
-error: aborting due to 1 previous error
+error: could not evaluate constant pattern
+ --> $DIR/missing_assoc_const_type.rs:19:9
+ |
+LL | TwoDigits::FIRST..=TwoDigits::LAST => 0,
+ | ^^^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
diff --git a/tests/ui/coroutine/discriminant.rs b/tests/ui/coroutine/discriminant.rs
index d6879e2..ca4fced 100644
--- a/tests/ui/coroutine/discriminant.rs
+++ b/tests/ui/coroutine/discriminant.rs
@@ -124,12 +124,14 @@ fn main() {
};
assert_eq!(size_of_val(&gen_u8_tiny_niche()), 1);
- assert_eq!(size_of_val(&Some(gen_u8_tiny_niche())), 1); // uses niche
+ // FIXME(#63818): niches in coroutines are disabled.
+ // assert_eq!(size_of_val(&Some(gen_u8_tiny_niche())), 1); // uses niche
assert_eq!(size_of_val(&Some(Some(gen_u8_tiny_niche()))), 2); // cannot use niche anymore
assert_eq!(size_of_val(&gen_u8_full()), 1);
assert_eq!(size_of_val(&Some(gen_u8_full())), 2); // cannot use niche
assert_eq!(size_of_val(&gen_u16()), 2);
- assert_eq!(size_of_val(&Some(gen_u16())), 2); // uses niche
+ // FIXME(#63818): niches in coroutines are disabled.
+ // assert_eq!(size_of_val(&Some(gen_u16())), 2); // uses niche
cycle(gen_u8_tiny_niche(), 254);
cycle(gen_u8_full(), 255);
diff --git a/tests/ui/coroutine/niche-in-coroutine.rs b/tests/ui/coroutine/niche-in-coroutine.rs
index 117ee9e..f268ef0 100644
--- a/tests/ui/coroutine/niche-in-coroutine.rs
+++ b/tests/ui/coroutine/niche-in-coroutine.rs
@@ -15,5 +15,6 @@ fn main() {
take(x);
};
- assert_eq!(size_of_val(&gen1), size_of_val(&Some(gen1)));
+ // FIXME(#63818): niches in coroutines are disabled. Should be `assert_eq`.
+ assert_ne!(size_of_val(&gen1), size_of_val(&Some(gen1)));
}
diff --git a/tests/ui/delegation/generics/impl-to-free-fn-pass.rs b/tests/ui/delegation/generics/impl-to-free-fn-pass.rs
new file mode 100644
index 0000000..3b39a45
--- /dev/null
+++ b/tests/ui/delegation/generics/impl-to-free-fn-pass.rs
@@ -0,0 +1,29 @@
+//@ run-pass
+#![feature(fn_delegation)]
+#![allow(incomplete_features)]
+
+mod to_reuse {
+ pub fn foo<T, U>(_: T, y: U) -> U { y }
+}
+
+trait Trait<T> {
+ fn foo(&self, x: T) -> T { x }
+}
+struct F;
+impl<T> Trait<T> for F {}
+
+struct S<T>(F, T);
+
+impl<T, U> Trait<T> for S<U> {
+ reuse to_reuse::foo { &self.0 }
+}
+
+impl<T> S<T> {
+ reuse to_reuse::foo;
+}
+
+fn main() {
+ let s = S(F, 42);
+ assert_eq!(S::<i32>::foo(F, 1), 1);
+ assert_eq!(<S<_> as Trait<_>>::foo(&s, 1), 1);
+}
diff --git a/tests/ui/delegation/generics/impl-to-trait-method.rs b/tests/ui/delegation/generics/impl-to-trait-method.rs
new file mode 100644
index 0000000..39e32e2
--- /dev/null
+++ b/tests/ui/delegation/generics/impl-to-trait-method.rs
@@ -0,0 +1,44 @@
+#![feature(fn_delegation)]
+#![allow(incomplete_features)]
+
+mod bounds {
+ trait Trait0 {}
+
+ trait Trait1<T> {
+ fn foo<U>(&self)
+ where
+ T: Trait0,
+ U: Trait0,
+ Self: Trait0,
+ //~^ ERROR the trait bound `bounds::S: Trait0` is not satisfied
+ {
+ }
+ }
+
+ struct F;
+ impl<T> Trait1<T> for F {}
+
+ struct S(F);
+
+ impl<T> Trait1<T> for S {
+ reuse Trait1::<T>::foo { &self.0 }
+ //~^ ERROR the trait bound `bounds::F: Trait0` is not satisfied
+ }
+}
+
+mod unconstrained_parameter {
+ trait Trait<T> {
+ fn foo(&self) {}
+ }
+
+ struct F;
+ impl<T> Trait<T> for F {}
+
+ struct S(F);
+ impl S {
+ reuse Trait::foo { &self.0 }
+ //~^ ERROR type annotations needed
+ }
+}
+
+fn main() {}
diff --git a/tests/ui/delegation/generics/impl-to-trait-method.stderr b/tests/ui/delegation/generics/impl-to-trait-method.stderr
new file mode 100644
index 0000000..aeba30d
--- /dev/null
+++ b/tests/ui/delegation/generics/impl-to-trait-method.stderr
@@ -0,0 +1,49 @@
+error[E0277]: the trait bound `bounds::S: Trait0` is not satisfied
+ --> $DIR/impl-to-trait-method.rs:12:19
+ |
+LL | Self: Trait0,
+ | ^^^^^^ the trait `Trait0` is not implemented for `bounds::S`
+ |
+help: this trait has no implementations, consider adding one
+ --> $DIR/impl-to-trait-method.rs:5:5
+ |
+LL | trait Trait0 {}
+ | ^^^^^^^^^^^^
+ = help: see issue #48214
+help: add `#![feature(trivial_bounds)]` to the crate attributes to enable
+ |
+LL + #![feature(trivial_bounds)]
+ |
+
+error[E0277]: the trait bound `bounds::F: Trait0` is not satisfied
+ --> $DIR/impl-to-trait-method.rs:24:34
+ |
+LL | reuse Trait1::<T>::foo { &self.0 }
+ | --- ^^^^^^^ the trait `Trait0` is not implemented for `bounds::F`
+ | |
+ | required by a bound introduced by this call
+ |
+help: this trait has no implementations, consider adding one
+ --> $DIR/impl-to-trait-method.rs:5:5
+ |
+LL | trait Trait0 {}
+ | ^^^^^^^^^^^^
+note: required by a bound in `Trait1::foo`
+ --> $DIR/impl-to-trait-method.rs:12:19
+ |
+LL | fn foo<U>(&self)
+ | --- required by a bound in this associated function
+...
+LL | Self: Trait0,
+ | ^^^^^^ required by this bound in `Trait1::foo`
+
+error[E0282]: type annotations needed
+ --> $DIR/impl-to-trait-method.rs:39:22
+ |
+LL | reuse Trait::foo { &self.0 }
+ | ^^^ cannot infer type for type parameter `T` declared on the trait `Trait`
+
+error: aborting due to 3 previous errors
+
+Some errors have detailed explanations: E0277, E0282.
+For more information about an error, try `rustc --explain E0277`.
diff --git a/tests/ui/delegation/generics/impl-trait-to-trait-method-pass.rs b/tests/ui/delegation/generics/impl-trait-to-trait-method-pass.rs
new file mode 100644
index 0000000..72440fe
--- /dev/null
+++ b/tests/ui/delegation/generics/impl-trait-to-trait-method-pass.rs
@@ -0,0 +1,77 @@
+//@ run-pass
+
+#![feature(fn_delegation)]
+#![allow(incomplete_features)]
+
+use std::iter::{Iterator, Map};
+
+pub mod same_trait {
+ use super::*;
+
+ pub struct MapOuter<I, F> {
+ pub inner: Map<I, F>
+ }
+
+ impl<B, I: Iterator, F> Iterator for MapOuter<I, F>
+ where
+ F: FnMut(I::Item) -> B,
+ {
+ type Item = <Map<I, F> as Iterator>::Item;
+
+ reuse Iterator::{next, fold} { self.inner }
+ }
+}
+use same_trait::MapOuter;
+
+mod another_trait {
+ use super::*;
+
+ trait ZipImpl<A, B> {
+ type Item;
+
+ fn next(&mut self) -> Option<Self::Item>;
+ }
+
+ pub struct Zip<A, B> {
+ pub a: A,
+ pub b: B,
+ }
+
+ impl<A: Iterator, B: Iterator> ZipImpl<A, B> for Zip<A, B> {
+ type Item = (A::Item, B::Item);
+
+ fn next(&mut self) -> Option<(A::Item, B::Item)> {
+ let x = self.a.next()?;
+ let y = self.b.next()?;
+ Some((x, y))
+ }
+ }
+
+ impl<A: Iterator, B: Iterator> Iterator for Zip<A, B> {
+ type Item = (A::Item, B::Item);
+
+ // Parameters are inherited from `Iterator::next`, not from `ZipImpl::next`.
+ // Otherwise, there would be a compilation error due to an unconstrained parameter.
+ reuse ZipImpl::next;
+ }
+}
+use another_trait::Zip;
+
+fn main() {
+ {
+ let x = vec![1, 2, 3];
+ let iter = x.iter().map(|val| val * 2);
+ let outer_iter = MapOuter { inner: iter };
+ let val = outer_iter.fold(0, |acc, x| acc + x);
+ assert_eq!(val, 12);
+ }
+
+ {
+ let x = vec![1, 2];
+ let y = vec![4, 5];
+
+ let mut zip = Zip { a: x.iter(), b: y.iter() };
+ assert_eq!(zip.next(), Some((&1, &4)));
+ assert_eq!(zip.next(), Some((&2, &5)));
+ }
+}
diff --git a/tests/ui/delegation/generics/inherent-impl-to-trait-method-pass.rs b/tests/ui/delegation/generics/inherent-impl-to-trait-method-pass.rs
new file mode 100644
index 0000000..6f3bb17
--- /dev/null
+++ b/tests/ui/delegation/generics/inherent-impl-to-trait-method-pass.rs
@@ -0,0 +1,23 @@
+//@ run-pass
+
+#![feature(fn_delegation)]
+#![allow(incomplete_features)]
+
+trait Trait<T> {
+ fn foo<U>(&self, x: T, y: U) -> (T, U) {
+ (x, y)
+ }
+}
+
+impl<T> Trait<T> for () {}
+struct S<T>(T, ());
+
+impl<T> S<T> {
+ reuse Trait::foo { self.1 }
+}
+
+
+fn main() {
+ let s = S((), ());
+ assert_eq!(s.foo(1u32, 2i32), (1u32, 2i32));
+}
diff --git a/tests/ui/delegation/generics/trait-method-to-other-pass.rs b/tests/ui/delegation/generics/trait-method-to-other-pass.rs
new file mode 100644
index 0000000..2094705
--- /dev/null
+++ b/tests/ui/delegation/generics/trait-method-to-other-pass.rs
@@ -0,0 +1,30 @@
+//@ run-pass
+
+#![feature(fn_delegation)]
+#![allow(incomplete_features)]
+
+mod to_reuse {
+ pub fn foo<T>(x: T) -> T { x }
+}
+
+trait Trait1<T, U> {
+ fn foo(&self, _: T, x: U) -> U { x }
+}
+
+#[derive(Default)]
+struct F;
+
+impl<T, U> Trait1<T, U> for F {}
+
+trait Trait2<T> {
+ fn get_f(&self) -> &F { &F }
+ reuse Trait1::foo as bar { self.get_f() }
+ reuse to_reuse::foo as baz;
+}
+
+impl Trait2<u64> for F {}
+
+fn main() {
+ assert_eq!(F.bar(1u8, 2u16), 2u16);
+ assert_eq!(F::baz(1u8), 1u8);
+}
diff --git a/tests/ui/delegation/ice-issue-124347.rs b/tests/ui/delegation/ice-issue-124347.rs
index 3bfae8f..ee2bf9e 100644
--- a/tests/ui/delegation/ice-issue-124347.rs
+++ b/tests/ui/delegation/ice-issue-124347.rs
@@ -1,12 +1,12 @@
#![feature(fn_delegation)]
#![allow(incomplete_features)]
+// FIXME(fn_delegation): `recursive delegation` error should be emitted here
trait Trait {
reuse Trait::foo { &self.0 }
- //~^ ERROR recursive delegation is not supported yet
+ //~^ ERROR cycle detected when computing generics of `Trait::foo`
}
-// FIXME(fn_delegation): `recursive delegation` error should be emitted here
reuse foo;
//~^ ERROR cycle detected when computing generics of `foo`
diff --git a/tests/ui/delegation/ice-issue-124347.stderr b/tests/ui/delegation/ice-issue-124347.stderr
index 87dd75f..bd0bc97 100644
--- a/tests/ui/delegation/ice-issue-124347.stderr
+++ b/tests/ui/delegation/ice-issue-124347.stderr
@@ -1,8 +1,16 @@
-error: recursive delegation is not supported yet
- --> $DIR/ice-issue-124347.rs:5:18
+error[E0391]: cycle detected when computing generics of `Trait::foo`
+ --> $DIR/ice-issue-124347.rs:6:18
|
LL | reuse Trait::foo { &self.0 }
- | ^^^ callee defined here
+ | ^^^
+ |
+ = note: ...which immediately requires computing generics of `Trait::foo` again
+note: cycle used when inheriting delegation signature
+ --> $DIR/ice-issue-124347.rs:6:18
+ |
+LL | reuse Trait::foo { &self.0 }
+ | ^^^
+ = 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 generics of `foo`
--> $DIR/ice-issue-124347.rs:10:7
diff --git a/tests/ui/delegation/not-supported.rs b/tests/ui/delegation/not-supported.rs
deleted file mode 100644
index d5ac68e..0000000
--- a/tests/ui/delegation/not-supported.rs
+++ /dev/null
@@ -1,116 +0,0 @@
-#![feature(const_trait_impl)]
-#![feature(c_variadic)]
-#![feature(effects)]
-#![feature(fn_delegation)]
-#![allow(incomplete_features)]
-
-mod generics {
- trait GenericTrait<T> {
- fn bar(&self, x: T) -> T { x }
- fn bar1() {}
- }
- trait Trait {
- fn foo(&self, x: i32) -> i32 { x }
- fn foo1<'a>(&self, x: &'a i32) -> &'a i32 { x }
- fn foo2<T>(&self, x: T) -> T { x }
- fn foo3<'a: 'a>(_: &'a u32) {}
-
- reuse GenericTrait::bar;
- //~^ ERROR early bound generics are not supported for associated delegation items
- reuse GenericTrait::bar1;
- //~^ ERROR early bound generics are not supported for associated delegation items
- }
-
- struct F;
- impl Trait for F {}
- impl<T> GenericTrait<T> for F {}
-
- struct S(F);
-
- impl<T> GenericTrait<T> for S {
- reuse <F as GenericTrait<T>>::bar { &self.0 }
- //~^ ERROR early bound generics are not supported for associated delegation items
- reuse GenericTrait::<T>::bar1;
- //~^ ERROR early bound generics are not supported for associated delegation items
- }
-
- impl GenericTrait<()> for () {
- reuse GenericTrait::bar { &F }
- //~^ ERROR early bound generics are not supported for associated delegation items
- reuse GenericTrait::bar1;
- //~^ ERROR early bound generics are not supported for associated delegation items
- }
-
- impl Trait for &S {
- reuse Trait::foo;
- //~^ ERROR early bound generics are not supported for associated delegation items
- }
-
- impl Trait for S {
- reuse Trait::foo1 { &self.0 }
- reuse Trait::foo2 { &self.0 }
- //~^ ERROR early bound generics are not supported for associated delegation items
- //~| ERROR method `foo2` has 0 type parameters but its trait declaration has 1 type parameter
- reuse <F as Trait>::foo3;
- //~^ ERROR early bound generics are not supported for associated delegation items
- //~| ERROR lifetime parameters or bounds on associated function `foo3` do not match the trait declaration
- }
-
- struct GenericS<T>(T);
- impl<T> Trait for GenericS<T> {
- reuse Trait::foo { &self.0 }
- //~^ ERROR early bound generics are not supported for associated delegation items
- }
-}
-
-mod opaque {
- trait Trait {}
- impl Trait for () {}
-
- mod to_reuse {
- use super::Trait;
-
- pub fn opaque_ret() -> impl Trait { unimplemented!() }
- //~^ warn: this function depends on never type fallback being `()`
- //~| warn: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- }
-
- trait ToReuse {
- fn opaque_ret() -> impl Trait { unimplemented!() }
- //~^ warn: this function depends on never type fallback being `()`
- //~| warn: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- }
-
- // FIXME: Inherited `impl Trait`s create query cycles when used inside trait impls.
- impl ToReuse for u8 {
- reuse to_reuse::opaque_ret; //~ ERROR cycle detected when computing type
- }
- impl ToReuse for u16 {
- reuse ToReuse::opaque_ret; //~ ERROR cycle detected when computing type
- }
-}
-
-mod recursive {
- mod to_reuse1 {
- pub mod to_reuse2 {
- pub fn foo() {}
- }
-
- pub reuse to_reuse2::foo;
- }
-
- reuse to_reuse1::foo;
- //~^ ERROR recursive delegation is not supported yet
-}
-
-mod effects {
- #[const_trait]
- trait Trait {
- fn foo();
- }
-
- reuse Trait::foo;
- //~^ ERROR delegation to a function with effect parameter is not supported yet
-}
-
-fn main() {}
diff --git a/tests/ui/delegation/not-supported.stderr b/tests/ui/delegation/not-supported.stderr
deleted file mode 100644
index 14d6b37..0000000
--- a/tests/ui/delegation/not-supported.stderr
+++ /dev/null
@@ -1,204 +0,0 @@
-error: using `#![feature(effects)]` without enabling next trait solver globally
- |
- = note: the next trait solver must be enabled globally for the effects feature to work correctly
- = help: use `-Znext-solver` to enable
-
-error: early bound generics are not supported for associated delegation items
- --> $DIR/not-supported.rs:18:29
- |
-LL | fn bar(&self, x: T) -> T { x }
- | ------------------------ callee defined here
-...
-LL | reuse GenericTrait::bar;
- | ^^^
-
-error: early bound generics are not supported for associated delegation items
- --> $DIR/not-supported.rs:20:29
- |
-LL | fn bar1() {}
- | --------- callee defined here
-...
-LL | reuse GenericTrait::bar1;
- | ^^^^
-
-error: early bound generics are not supported for associated delegation items
- --> $DIR/not-supported.rs:31:39
- |
-LL | fn bar(&self, x: T) -> T { x }
- | ------------------------ callee defined here
-...
-LL | reuse <F as GenericTrait<T>>::bar { &self.0 }
- | ^^^
-
-error: early bound generics are not supported for associated delegation items
- --> $DIR/not-supported.rs:33:34
- |
-LL | fn bar1() {}
- | --------- callee defined here
-...
-LL | reuse GenericTrait::<T>::bar1;
- | ^^^^
-
-error: early bound generics are not supported for associated delegation items
- --> $DIR/not-supported.rs:38:29
- |
-LL | fn bar(&self, x: T) -> T { x }
- | ------------------------ callee defined here
-...
-LL | reuse GenericTrait::bar { &F }
- | ^^^
-
-error: early bound generics are not supported for associated delegation items
- --> $DIR/not-supported.rs:40:29
- |
-LL | fn bar1() {}
- | --------- callee defined here
-...
-LL | reuse GenericTrait::bar1;
- | ^^^^
-
-error: early bound generics are not supported for associated delegation items
- --> $DIR/not-supported.rs:45:22
- |
-LL | fn foo(&self, x: i32) -> i32 { x }
- | ---------------------------- callee defined here
-...
-LL | reuse Trait::foo;
- | ^^^
-
-error[E0049]: method `foo2` has 0 type parameters but its trait declaration has 1 type parameter
- --> $DIR/not-supported.rs:51:22
- |
-LL | fn foo2<T>(&self, x: T) -> T { x }
- | - expected 1 type parameter
-...
-LL | reuse Trait::foo2 { &self.0 }
- | ^^^^ found 0 type parameters
-
-error: early bound generics are not supported for associated delegation items
- --> $DIR/not-supported.rs:54:29
- |
-LL | fn foo3<'a: 'a>(_: &'a u32) {}
- | --------------------------- callee defined here
-...
-LL | reuse <F as Trait>::foo3;
- | ^^^^
-
-error[E0195]: lifetime parameters or bounds on associated function `foo3` do not match the trait declaration
- --> $DIR/not-supported.rs:54:29
- |
-LL | fn foo3<'a: 'a>(_: &'a u32) {}
- | -------- lifetimes in impl do not match this associated function in trait
-...
-LL | reuse <F as Trait>::foo3;
- | ^^^^ lifetimes do not match associated function in trait
-
-error: delegation to a function with effect parameter is not supported yet
- --> $DIR/not-supported.rs:112:18
- |
-LL | fn foo();
- | --------- callee defined here
-...
-LL | reuse Trait::foo;
- | ^^^
-
-error: early bound generics are not supported for associated delegation items
- --> $DIR/not-supported.rs:61:22
- |
-LL | fn foo(&self, x: i32) -> i32 { x }
- | ---------------------------- callee defined here
-...
-LL | reuse Trait::foo { &self.0 }
- | ^^^
-
-error: early bound generics are not supported for associated delegation items
- --> $DIR/not-supported.rs:51:22
- |
-LL | fn foo2<T>(&self, x: T) -> T { x }
- | ---------------------------- callee defined here
-...
-LL | reuse Trait::foo2 { &self.0 }
- | ^^^^
-
-warning: this function depends on never type fallback being `()`
- --> $DIR/not-supported.rs:79:9
- |
-LL | fn opaque_ret() -> impl Trait { unimplemented!() }
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- |
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #123748 <https://github.com/rust-lang/rust/issues/123748>
- = help: specify the types explicitly
-note: in edition 2024, the requirement `!: opaque::Trait` will fail
- --> $DIR/not-supported.rs:79:28
- |
-LL | fn opaque_ret() -> impl Trait { unimplemented!() }
- | ^^^^^^^^^^
- = note: `#[warn(dependency_on_unit_never_type_fallback)]` on by default
-
-error[E0391]: cycle detected when computing type of `opaque::<impl at $DIR/not-supported.rs:85:5: 85:24>::{synthetic#0}`
- --> $DIR/not-supported.rs:86:25
- |
-LL | reuse to_reuse::opaque_ret;
- | ^^^^^^^^^^
- |
-note: ...which requires comparing an impl and trait method signature, inferring any hidden `impl Trait` types in the process...
- --> $DIR/not-supported.rs:86:25
- |
-LL | reuse to_reuse::opaque_ret;
- | ^^^^^^^^^^
- = note: ...which again requires computing type of `opaque::<impl at $DIR/not-supported.rs:85:5: 85:24>::{synthetic#0}`, completing the cycle
-note: cycle used when checking that `opaque::<impl at $DIR/not-supported.rs:85:5: 85:24>` is well-formed
- --> $DIR/not-supported.rs:85:5
- |
-LL | impl ToReuse for u8 {
- | ^^^^^^^^^^^^^^^^^^^
- = 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
-
-warning: this function depends on never type fallback being `()`
- --> $DIR/not-supported.rs:73:9
- |
-LL | pub fn opaque_ret() -> impl Trait { unimplemented!() }
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- |
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #123748 <https://github.com/rust-lang/rust/issues/123748>
- = help: specify the types explicitly
-note: in edition 2024, the requirement `!: opaque::Trait` will fail
- --> $DIR/not-supported.rs:73:32
- |
-LL | pub fn opaque_ret() -> impl Trait { unimplemented!() }
- | ^^^^^^^^^^
-
-error[E0391]: cycle detected when computing type of `opaque::<impl at $DIR/not-supported.rs:88:5: 88:25>::{synthetic#0}`
- --> $DIR/not-supported.rs:89:24
- |
-LL | reuse ToReuse::opaque_ret;
- | ^^^^^^^^^^
- |
-note: ...which requires comparing an impl and trait method signature, inferring any hidden `impl Trait` types in the process...
- --> $DIR/not-supported.rs:89:24
- |
-LL | reuse ToReuse::opaque_ret;
- | ^^^^^^^^^^
- = note: ...which again requires computing type of `opaque::<impl at $DIR/not-supported.rs:88:5: 88:25>::{synthetic#0}`, completing the cycle
-note: cycle used when checking that `opaque::<impl at $DIR/not-supported.rs:88:5: 88:25>` is well-formed
- --> $DIR/not-supported.rs:88:5
- |
-LL | impl ToReuse for u16 {
- | ^^^^^^^^^^^^^^^^^^^^
- = 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: recursive delegation is not supported yet
- --> $DIR/not-supported.rs:102:22
- |
-LL | pub reuse to_reuse2::foo;
- | --- callee defined here
-...
-LL | reuse to_reuse1::foo;
- | ^^^
-
-error: aborting due to 17 previous errors; 2 warnings emitted
-
-Some errors have detailed explanations: E0049, E0195, E0391.
-For more information about an error, try `rustc --explain E0049`.
diff --git a/tests/ui/delegation/unsupported.rs b/tests/ui/delegation/unsupported.rs
new file mode 100644
index 0000000..e57efff
--- /dev/null
+++ b/tests/ui/delegation/unsupported.rs
@@ -0,0 +1,57 @@
+#![feature(const_trait_impl)]
+#![feature(c_variadic)]
+#![feature(effects)]
+#![feature(fn_delegation)]
+#![allow(incomplete_features)]
+
+mod opaque {
+ trait Trait {}
+ impl Trait for () {}
+
+ mod to_reuse {
+ use super::Trait;
+
+ pub fn opaque_ret() -> impl Trait { unimplemented!() }
+ //~^ warn: this function depends on never type fallback being `()`
+ //~| warn: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ }
+
+ trait ToReuse {
+ fn opaque_ret() -> impl Trait { unimplemented!() }
+ //~^ warn: this function depends on never type fallback being `()`
+ //~| warn: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ }
+
+ // FIXME: Inherited `impl Trait`s create query cycles when used inside trait impls.
+ impl ToReuse for u8 {
+ reuse to_reuse::opaque_ret; //~ ERROR cycle detected when computing type
+ }
+ impl ToReuse for u16 {
+ reuse ToReuse::opaque_ret; //~ ERROR cycle detected when computing type
+ }
+}
+
+mod recursive {
+ mod to_reuse1 {
+ pub mod to_reuse2 {
+ pub fn foo() {}
+ }
+
+ pub reuse to_reuse2::foo;
+ }
+
+ reuse to_reuse1::foo;
+ //~^ ERROR recursive delegation is not supported yet
+}
+
+mod effects {
+ #[const_trait]
+ trait Trait {
+ fn foo();
+ }
+
+ reuse Trait::foo;
+ //~^ ERROR delegation to a function with effect parameter is not supported yet
+}
+
+fn main() {}
diff --git a/tests/ui/delegation/unsupported.stderr b/tests/ui/delegation/unsupported.stderr
new file mode 100644
index 0000000..03ded30
--- /dev/null
+++ b/tests/ui/delegation/unsupported.stderr
@@ -0,0 +1,95 @@
+error: using `#![feature(effects)]` without enabling next trait solver globally
+ |
+ = note: the next trait solver must be enabled globally for the effects feature to work correctly
+ = help: use `-Znext-solver` to enable
+
+warning: this function depends on never type fallback being `()`
+ --> $DIR/unsupported.rs:20:9
+ |
+LL | fn opaque_ret() -> impl Trait { unimplemented!() }
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = note: for more information, see issue #123748 <https://github.com/rust-lang/rust/issues/123748>
+ = help: specify the types explicitly
+note: in edition 2024, the requirement `!: opaque::Trait` will fail
+ --> $DIR/unsupported.rs:20:28
+ |
+LL | fn opaque_ret() -> impl Trait { unimplemented!() }
+ | ^^^^^^^^^^
+ = note: `#[warn(dependency_on_unit_never_type_fallback)]` on by default
+
+error[E0391]: cycle detected when computing type of `opaque::<impl at $DIR/unsupported.rs:26:5: 26:24>::{synthetic#0}`
+ --> $DIR/unsupported.rs:27:25
+ |
+LL | reuse to_reuse::opaque_ret;
+ | ^^^^^^^^^^
+ |
+note: ...which requires comparing an impl and trait method signature, inferring any hidden `impl Trait` types in the process...
+ --> $DIR/unsupported.rs:27:25
+ |
+LL | reuse to_reuse::opaque_ret;
+ | ^^^^^^^^^^
+ = note: ...which again requires computing type of `opaque::<impl at $DIR/unsupported.rs:26:5: 26:24>::{synthetic#0}`, completing the cycle
+note: cycle used when checking that `opaque::<impl at $DIR/unsupported.rs:26:5: 26:24>` is well-formed
+ --> $DIR/unsupported.rs:26:5
+ |
+LL | impl ToReuse for u8 {
+ | ^^^^^^^^^^^^^^^^^^^
+ = 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
+
+warning: this function depends on never type fallback being `()`
+ --> $DIR/unsupported.rs:14:9
+ |
+LL | pub fn opaque_ret() -> impl Trait { unimplemented!() }
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = note: for more information, see issue #123748 <https://github.com/rust-lang/rust/issues/123748>
+ = help: specify the types explicitly
+note: in edition 2024, the requirement `!: opaque::Trait` will fail
+ --> $DIR/unsupported.rs:14:32
+ |
+LL | pub fn opaque_ret() -> impl Trait { unimplemented!() }
+ | ^^^^^^^^^^
+
+error[E0391]: cycle detected when computing type of `opaque::<impl at $DIR/unsupported.rs:29:5: 29:25>::{synthetic#0}`
+ --> $DIR/unsupported.rs:30:24
+ |
+LL | reuse ToReuse::opaque_ret;
+ | ^^^^^^^^^^
+ |
+note: ...which requires comparing an impl and trait method signature, inferring any hidden `impl Trait` types in the process...
+ --> $DIR/unsupported.rs:30:24
+ |
+LL | reuse ToReuse::opaque_ret;
+ | ^^^^^^^^^^
+ = note: ...which again requires computing type of `opaque::<impl at $DIR/unsupported.rs:29:5: 29:25>::{synthetic#0}`, completing the cycle
+note: cycle used when checking that `opaque::<impl at $DIR/unsupported.rs:29:5: 29:25>` is well-formed
+ --> $DIR/unsupported.rs:29:5
+ |
+LL | impl ToReuse for u16 {
+ | ^^^^^^^^^^^^^^^^^^^^
+ = 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: recursive delegation is not supported yet
+ --> $DIR/unsupported.rs:43:22
+ |
+LL | pub reuse to_reuse2::foo;
+ | --- callee defined here
+...
+LL | reuse to_reuse1::foo;
+ | ^^^
+
+error: delegation to a function with effect parameter is not supported yet
+ --> $DIR/unsupported.rs:53:18
+ |
+LL | fn foo();
+ | --------- callee defined here
+...
+LL | reuse Trait::foo;
+ | ^^^
+
+error: aborting due to 5 previous errors; 2 warnings emitted
+
+For more information about this error, try `rustc --explain E0391`.
diff --git a/tests/ui/error-codes/e0119/issue-23563.stderr b/tests/ui/error-codes/e0119/issue-23563.stderr
index 8673774..a308769 100644
--- a/tests/ui/error-codes/e0119/issue-23563.stderr
+++ b/tests/ui/error-codes/e0119/issue-23563.stderr
@@ -1,4 +1,4 @@
-error[E0119]: conflicting implementations of trait `LolFrom<&[_]>` for type `LocalType<_>`
+error[E0119]: conflicting implementations of trait `LolFrom<&[u8]>` for type `LocalType<u8>`
--> $DIR/issue-23563.rs:13:1
|
LL | impl<'a, T> LolFrom<&'a [T]> for LocalType<T> {
diff --git a/tests/ui/feature-gates/feature-gate-with_negative_coherence.stderr b/tests/ui/feature-gates/feature-gate-with_negative_coherence.stderr
index ba07656..b32f54a 100644
--- a/tests/ui/feature-gates/feature-gate-with_negative_coherence.stderr
+++ b/tests/ui/feature-gates/feature-gate-with_negative_coherence.stderr
@@ -6,6 +6,8 @@
LL |
LL | impl<T> Foo for &T { }
| ^^^^^^^^^^^^^^^^^^ conflicting implementation for `&_`
+ |
+ = note: downstream crates may implement trait `std::ops::DerefMut` for type `&_`
error: aborting due to 1 previous error
diff --git a/tests/ui/higher-ranked/leak-check/leak-check-in-selection-5-ambig.rs b/tests/ui/higher-ranked/leak-check/leak-check-in-selection-5-ambig.rs
index beda719..9a44fd2 100644
--- a/tests/ui/higher-ranked/leak-check/leak-check-in-selection-5-ambig.rs
+++ b/tests/ui/higher-ranked/leak-check/leak-check-in-selection-5-ambig.rs
@@ -3,9 +3,9 @@
//@ check-pass
// The new trait solver does not return region constraints if the goal
-// is still ambiguous. This causes the following test to fail with ambiguity,
-// even though `(): LeakCheckFailure<'!a, V>` would return `'!a: 'static`
-// which would have caused a leak check failure.
+// is still ambiguous. However, the `'!a = 'static` constraint from
+// `(): LeakCheckFailure<'!a, V>` is also returned via the canonical
+// var values, causing this test to compile.
trait Ambig {}
impl Ambig for u32 {}
diff --git a/tests/ui/higher-ranked/structually-relate-aliases.rs b/tests/ui/higher-ranked/structually-relate-aliases.rs
index 8df2470..6988245 100644
--- a/tests/ui/higher-ranked/structually-relate-aliases.rs
+++ b/tests/ui/higher-ranked/structually-relate-aliases.rs
@@ -11,7 +11,6 @@ trait Overlap<T> {}
impl<T> Overlap<T> for T {}
impl<T> Overlap<for<'a> fn(&'a (), Assoc<'a, T>)> for T {}
-//~^ ERROR 13:17: 13:49: the trait bound `for<'a> T: ToUnit<'a>` is not satisfied [E0277]
-//~| ERROR 13:36: 13:48: the trait bound `for<'a> T: ToUnit<'a>` is not satisfied [E0277]
+//~^ ERROR conflicting implementations of trait `Overlap<for<'a> fn(&'a (), _)>`
fn main() {}
diff --git a/tests/ui/higher-ranked/structually-relate-aliases.stderr b/tests/ui/higher-ranked/structually-relate-aliases.stderr
index 7de30ef..4ecd582 100644
--- a/tests/ui/higher-ranked/structually-relate-aliases.stderr
+++ b/tests/ui/higher-ranked/structually-relate-aliases.stderr
@@ -1,27 +1,18 @@
WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: [?1t, '^0.Named(DefId(0:15 ~ structually_relate_aliases[de75]::{impl#1}::'a), "'a")], def_id: DefId(0:5 ~ structually_relate_aliases[de75]::ToUnit::Unit), .. }
- WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: [?1t, !2_0.Named(DefId(0:15 ~ structually_relate_aliases[de75]::{impl#1}::'a), "'a")], def_id: DefId(0:5 ~ structually_relate_aliases[de75]::ToUnit::Unit), .. }
-error[E0277]: the trait bound `for<'a> T: ToUnit<'a>` is not satisfied
- --> $DIR/structually-relate-aliases.rs:13:36
+ WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: [?1t, '^0.Named(DefId(0:15 ~ structually_relate_aliases[de75]::{impl#1}::'a), "'a")], def_id: DefId(0:5 ~ structually_relate_aliases[de75]::ToUnit::Unit), .. }
+ WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: [?1t, '^0.Named(DefId(0:15 ~ structually_relate_aliases[de75]::{impl#1}::'a), "'a")], def_id: DefId(0:5 ~ structually_relate_aliases[de75]::ToUnit::Unit), .. }
+ WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: [?1t, '^0.Named(DefId(0:15 ~ structually_relate_aliases[de75]::{impl#1}::'a), "'a")], def_id: DefId(0:5 ~ structually_relate_aliases[de75]::ToUnit::Unit), .. }
+error[E0119]: conflicting implementations of trait `Overlap<for<'a> fn(&'a (), _)>` for type `for<'a> fn(&'a (), _)`
+ --> $DIR/structually-relate-aliases.rs:13:1
|
+LL | impl<T> Overlap<T> for T {}
+ | ------------------------ first implementation here
+LL |
LL | impl<T> Overlap<for<'a> fn(&'a (), Assoc<'a, T>)> for T {}
- | ^^^^^^^^^^^^ the trait `for<'a> ToUnit<'a>` is not implemented for `T`
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `for<'a> fn(&'a (), _)`
|
-help: consider restricting type parameter `T`
- |
-LL | impl<T: for<'a> ToUnit<'a>> Overlap<for<'a> fn(&'a (), Assoc<'a, T>)> for T {}
- | ++++++++++++++++++++
+ = note: this behavior recently changed as a result of a bug fix; see rust-lang/rust#56105 for details
-error[E0277]: the trait bound `for<'a> T: ToUnit<'a>` is not satisfied
- --> $DIR/structually-relate-aliases.rs:13:17
- |
-LL | impl<T> Overlap<for<'a> fn(&'a (), Assoc<'a, T>)> for T {}
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `for<'a> ToUnit<'a>` is not implemented for `T`
- |
-help: consider restricting type parameter `T`
- |
-LL | impl<T: for<'a> ToUnit<'a>> Overlap<for<'a> fn(&'a (), Assoc<'a, T>)> for T {}
- | ++++++++++++++++++++
+error: aborting due to 1 previous error
-error: aborting due to 2 previous errors
-
-For more information about this error, try `rustc --explain E0277`.
+For more information about this error, try `rustc --explain E0119`.
diff --git a/tests/ui/impl-trait/auto-trait-coherence.old.stderr b/tests/ui/impl-trait/auto-trait-coherence.old.stderr
index 3f979d1..cd91bfc 100644
--- a/tests/ui/impl-trait/auto-trait-coherence.old.stderr
+++ b/tests/ui/impl-trait/auto-trait-coherence.old.stderr
@@ -1,11 +1,11 @@
-error[E0119]: conflicting implementations of trait `AnotherTrait` for type `D<OpaqueType>`
+error[E0119]: conflicting implementations of trait `AnotherTrait` for type `D<_>`
--> $DIR/auto-trait-coherence.rs:24:1
|
LL | impl<T: Send> AnotherTrait for T {}
| -------------------------------- first implementation here
...
LL | impl AnotherTrait for D<OpaqueType> {
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `D<OpaqueType>`
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `D<_>`
error: aborting due to 1 previous error
diff --git a/tests/ui/impl-trait/auto-trait-coherence.rs b/tests/ui/impl-trait/auto-trait-coherence.rs
index e3036fd..0d7fef2 100644
--- a/tests/ui/impl-trait/auto-trait-coherence.rs
+++ b/tests/ui/impl-trait/auto-trait-coherence.rs
@@ -1,6 +1,3 @@
-//@ revisions: old next
-//@[next] compile-flags: -Znext-solver
-
// Tests that type alias impls traits do not leak auto-traits for
// the purposes of coherence checking
#![feature(type_alias_impl_trait)]
@@ -22,8 +19,7 @@ impl<T: Send> AnotherTrait for T {}
// (We treat opaque types as "foreign types" that could grow more impls
// in the future.)
impl AnotherTrait for D<OpaqueType> {
- //[old]~^ ERROR conflicting implementations of trait `AnotherTrait` for type `D<OpaqueType>`
- //[next]~^^ ERROR conflicting implementations of trait `AnotherTrait` for type `D<_>`
+ //~^ ERROR conflicting implementations of trait `AnotherTrait` for type `D<_>`
}
fn main() {}
diff --git a/tests/ui/impl-trait/auto-trait-coherence.stderr b/tests/ui/impl-trait/auto-trait-coherence.stderr
new file mode 100644
index 0000000..e0f4c85
--- /dev/null
+++ b/tests/ui/impl-trait/auto-trait-coherence.stderr
@@ -0,0 +1,12 @@
+error[E0119]: conflicting implementations of trait `AnotherTrait` for type `D<_>`
+ --> $DIR/auto-trait-coherence.rs:21:1
+ |
+LL | impl<T: Send> AnotherTrait for T {}
+ | -------------------------------- first implementation here
+...
+LL | impl AnotherTrait for D<OpaqueType> {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `D<_>`
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0119`.
diff --git a/tests/ui/impl-trait/coherence-treats-tait-ambig.rs b/tests/ui/impl-trait/coherence-treats-tait-ambig.rs
index df47208b..e8c1fcd 100644
--- a/tests/ui/impl-trait/coherence-treats-tait-ambig.rs
+++ b/tests/ui/impl-trait/coherence-treats-tait-ambig.rs
@@ -5,7 +5,7 @@
struct Foo;
impl Into<T> for Foo {
-//~^ ERROR conflicting implementations of trait `Into<T>` for type `Foo`
+//~^ ERROR conflicting implementations of trait `Into<_>` for type `Foo`
fn into(self) -> T {
Foo
}
diff --git a/tests/ui/impl-trait/coherence-treats-tait-ambig.stderr b/tests/ui/impl-trait/coherence-treats-tait-ambig.stderr
index faaad27..618bef1 100644
--- a/tests/ui/impl-trait/coherence-treats-tait-ambig.stderr
+++ b/tests/ui/impl-trait/coherence-treats-tait-ambig.stderr
@@ -1,4 +1,4 @@
-error[E0119]: conflicting implementations of trait `Into<T>` for type `Foo`
+error[E0119]: conflicting implementations of trait `Into<_>` for type `Foo`
--> $DIR/coherence-treats-tait-ambig.rs:7:1
|
LL | impl Into<T> for Foo {
diff --git a/tests/ui/impl-trait/negative-reasoning.rs b/tests/ui/impl-trait/negative-reasoning.rs
index 70e24a3..0474dc0 100644
--- a/tests/ui/impl-trait/negative-reasoning.rs
+++ b/tests/ui/impl-trait/negative-reasoning.rs
@@ -17,7 +17,7 @@ impl<T: std::fmt::Debug> AnotherTrait for T {}
// This is in error, because we cannot assume that `OpaqueType: !Debug`
impl AnotherTrait for D<OpaqueType> {
- //~^ ERROR conflicting implementations of trait `AnotherTrait` for type `D<OpaqueType>`
+ //~^ ERROR conflicting implementations of trait `AnotherTrait` for type `D<_>`
}
fn main() {}
diff --git a/tests/ui/impl-trait/negative-reasoning.stderr b/tests/ui/impl-trait/negative-reasoning.stderr
index 3cb4be1..631784c 100644
--- a/tests/ui/impl-trait/negative-reasoning.stderr
+++ b/tests/ui/impl-trait/negative-reasoning.stderr
@@ -1,13 +1,11 @@
-error[E0119]: conflicting implementations of trait `AnotherTrait` for type `D<OpaqueType>`
+error[E0119]: conflicting implementations of trait `AnotherTrait` for type `D<_>`
--> $DIR/negative-reasoning.rs:19:1
|
LL | impl<T: std::fmt::Debug> AnotherTrait for T {}
| ------------------------------------------- first implementation here
...
LL | impl AnotherTrait for D<OpaqueType> {
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `D<OpaqueType>`
- |
- = note: upstream crates may add a new impl of trait `std::marker::FnPtr` for type `OpaqueType` in future versions
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `D<_>`
error: aborting due to 1 previous error
diff --git a/tests/ui/impl-trait/precise-capturing/overcaptures-2024-but-fine.rs b/tests/ui/impl-trait/precise-capturing/overcaptures-2024-but-fine.rs
new file mode 100644
index 0000000..e30f785
--- /dev/null
+++ b/tests/ui/impl-trait/precise-capturing/overcaptures-2024-but-fine.rs
@@ -0,0 +1,15 @@
+//@ check-pass
+
+#![deny(impl_trait_overcaptures)]
+
+struct Ctxt<'tcx>(&'tcx ());
+
+// In `compute`, we don't care that we're "overcapturing" `'tcx`
+// in edition 2024, because it can be shortened at the call site
+// and we know it outlives `'_`.
+
+impl<'tcx> Ctxt<'tcx> {
+ fn compute(&self) -> impl Sized + '_ {}
+}
+
+fn main() {}
diff --git a/tests/ui/impl-unused-tps.rs b/tests/ui/impl-unused-tps.rs
index 3eb9dae..a5836db 100644
--- a/tests/ui/impl-unused-tps.rs
+++ b/tests/ui/impl-unused-tps.rs
@@ -1,34 +1,35 @@
-//~ ERROR overflow evaluating the requirement `([isize; 0], _): Sized
-
trait Foo<A> {
- fn get(&self, A: &A) { }
+ fn get(&self, A: &A) {}
}
trait Bar {
type Out;
}
-impl<T> Foo<T> for [isize;0] {
+impl<T> Foo<T> for [isize; 0] {
// OK, T is used in `Foo<T>`.
}
-impl<T,U> Foo<T> for [isize;1] {
+impl<T, U> Foo<T> for [isize; 1] {
//~^ ERROR the type parameter `U` is not constrained
}
-impl<T,U> Foo<T> for [isize;2] where T : Bar<Out=U> {
+impl<T, U> Foo<T> for [isize; 2]
+where
+ T: Bar<Out = U>,
+{
// OK, `U` is now constrained by the output type parameter.
}
-impl<T:Bar<Out=U>,U> Foo<T> for [isize;3] {
+impl<T: Bar<Out = U>, U> Foo<T> for [isize; 3] {
// OK, same as above but written differently.
}
-impl<T,U> Foo<T> for U {
+impl<T, U> Foo<T> for U {
//~^ ERROR conflicting implementations of trait `Foo<_>` for type `[isize; 0]`
}
-impl<T,U> Bar for T {
+impl<T, U> Bar for T {
//~^ ERROR the type parameter `U` is not constrained
type Out = U;
@@ -36,28 +37,33 @@ impl<T,U> Bar for T {
// Using `U` in an associated type within the impl is not good enough!
}
-impl<T,U> Bar for T
- where T : Bar<Out=U>
+impl<T, U> Bar for T
+where
+ T: Bar<Out = U>,
{
- //~^^^ ERROR the type parameter `U` is not constrained
-
+ //~^^^^ ERROR the type parameter `U` is not constrained by the impl trait, self type, or predicates
+ //~| ERROR conflicting implementations of trait `Bar`
// This crafty self-referential attempt is still no good.
}
-impl<T,U,V> Foo<T> for T
- where (T,U): Bar<Out=V>
+impl<T, U, V> Foo<T> for T
+where
+ (T, U): Bar<Out = V>,
{
- //~^^^ ERROR the type parameter `U` is not constrained
- //~| ERROR the type parameter `V` is not constrained
+ //~^^^^ ERROR the type parameter `U` is not constrained
+ //~| ERROR the type parameter `V` is not constrained
+ //~| ERROR conflicting implementations of trait `Foo<[isize; 0]>` for type `[isize; 0]`
// Here, `V` is bound by an output type parameter, but the inputs
// are not themselves constrained.
}
-impl<T,U,V> Foo<(T,U)> for T
- where (T,U): Bar<Out=V>
+impl<T, U, V> Foo<(T, U)> for T
+where
+ (T, U): Bar<Out = V>,
{
+ //~^^^^ ERROR conflicting implementations of trait `Foo<([isize; 0], _)>` for type `[isize; 0]`
// As above, but both T and U ARE constrained.
}
-fn main() { }
+fn main() {}
diff --git a/tests/ui/impl-unused-tps.stderr b/tests/ui/impl-unused-tps.stderr
index af427cb..da4589d 100644
--- a/tests/ui/impl-unused-tps.stderr
+++ b/tests/ui/impl-unused-tps.stderr
@@ -1,56 +1,76 @@
error[E0119]: conflicting implementations of trait `Foo<_>` for type `[isize; 0]`
- --> $DIR/impl-unused-tps.rs:27:1
+ --> $DIR/impl-unused-tps.rs:28:1
|
-LL | impl<T> Foo<T> for [isize;0] {
- | ---------------------------- first implementation here
+LL | impl<T> Foo<T> for [isize; 0] {
+ | ----------------------------- first implementation here
...
-LL | impl<T,U> Foo<T> for U {
- | ^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `[isize; 0]`
+LL | impl<T, U> Foo<T> for U {
+ | ^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `[isize; 0]`
-error[E0275]: overflow evaluating the requirement `([isize; 0], _): Sized`
+error[E0119]: conflicting implementations of trait `Bar`
+ --> $DIR/impl-unused-tps.rs:40:1
|
- = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`impl_unused_tps`)
-note: required for `([isize; 0], _)` to implement `Bar`
- --> $DIR/impl-unused-tps.rs:31:11
+LL | impl<T, U> Bar for T {
+ | -------------------- first implementation here
+...
+LL | / impl<T, U> Bar for T
+LL | | where
+LL | | T: Bar<Out = U>,
+ | |____________________^ conflicting implementation
+
+error[E0119]: conflicting implementations of trait `Foo<[isize; 0]>` for type `[isize; 0]`
+ --> $DIR/impl-unused-tps.rs:49:1
|
-LL | impl<T,U> Bar for T {
- | - ^^^ ^
- | |
- | unsatisfied trait bound introduced here
- = note: 126 redundant requirements hidden
- = note: required for `([isize; 0], _)` to implement `Bar`
+LL | impl<T> Foo<T> for [isize; 0] {
+ | ----------------------------- first implementation here
+...
+LL | / impl<T, U, V> Foo<T> for T
+LL | | where
+LL | | (T, U): Bar<Out = V>,
+ | |_________________________^ conflicting implementation for `[isize; 0]`
+
+error[E0119]: conflicting implementations of trait `Foo<([isize; 0], _)>` for type `[isize; 0]`
+ --> $DIR/impl-unused-tps.rs:61:1
+ |
+LL | impl<T> Foo<T> for [isize; 0] {
+ | ----------------------------- first implementation here
+...
+LL | / impl<T, U, V> Foo<(T, U)> for T
+LL | | where
+LL | | (T, U): Bar<Out = V>,
+ | |_________________________^ conflicting implementation for `[isize; 0]`
error[E0207]: the type parameter `U` is not constrained by the impl trait, self type, or predicates
- --> $DIR/impl-unused-tps.rs:15:8
+ --> $DIR/impl-unused-tps.rs:13:9
|
-LL | impl<T,U> Foo<T> for [isize;1] {
- | ^ unconstrained type parameter
+LL | impl<T, U> Foo<T> for [isize; 1] {
+ | ^ unconstrained type parameter
error[E0207]: the type parameter `U` is not constrained by the impl trait, self type, or predicates
- --> $DIR/impl-unused-tps.rs:31:8
+ --> $DIR/impl-unused-tps.rs:32:9
|
-LL | impl<T,U> Bar for T {
- | ^ unconstrained type parameter
+LL | impl<T, U> Bar for T {
+ | ^ unconstrained type parameter
error[E0207]: the type parameter `U` is not constrained by the impl trait, self type, or predicates
- --> $DIR/impl-unused-tps.rs:39:8
+ --> $DIR/impl-unused-tps.rs:40:9
|
-LL | impl<T,U> Bar for T
- | ^ unconstrained type parameter
+LL | impl<T, U> Bar for T
+ | ^ unconstrained type parameter
error[E0207]: the type parameter `U` is not constrained by the impl trait, self type, or predicates
- --> $DIR/impl-unused-tps.rs:47:8
+ --> $DIR/impl-unused-tps.rs:49:9
|
-LL | impl<T,U,V> Foo<T> for T
- | ^ unconstrained type parameter
+LL | impl<T, U, V> Foo<T> for T
+ | ^ unconstrained type parameter
error[E0207]: the type parameter `V` is not constrained by the impl trait, self type, or predicates
- --> $DIR/impl-unused-tps.rs:47:10
+ --> $DIR/impl-unused-tps.rs:49:12
|
-LL | impl<T,U,V> Foo<T> for T
- | ^ unconstrained type parameter
+LL | impl<T, U, V> Foo<T> for T
+ | ^ unconstrained type parameter
-error: aborting due to 7 previous errors
+error: aborting due to 9 previous errors
-Some errors have detailed explanations: E0119, E0207, E0275.
+Some errors have detailed explanations: E0119, E0207.
For more information about an error, try `rustc --explain E0119`.
diff --git a/tests/ui/implied-bounds/implied-bounds-on-nested-references-plus-variance-2.rs b/tests/ui/implied-bounds/implied-bounds-on-nested-references-plus-variance-2.rs
new file mode 100644
index 0000000..ca8b8b7
--- /dev/null
+++ b/tests/ui/implied-bounds/implied-bounds-on-nested-references-plus-variance-2.rs
@@ -0,0 +1,13 @@
+//@ check-pass
+//@ known-bug: #25860
+
+static UNIT: &'static &'static () = &&();
+
+fn foo<'a, 'b, T>(_: &'a &'b (), v: &'b T, _: &()) -> &'a T { v }
+
+fn bad<'a, T>(x: &'a T) -> &'static T {
+ let f: fn(_, &'a T, &()) -> &'static T = foo;
+ f(UNIT, x, &())
+}
+
+fn main() {}
diff --git a/tests/ui/implied-bounds/implied-bounds-on-nested-references-plus-variance-early-bound.rs b/tests/ui/implied-bounds/implied-bounds-on-nested-references-plus-variance-early-bound.rs
new file mode 100644
index 0000000..226a6fa
--- /dev/null
+++ b/tests/ui/implied-bounds/implied-bounds-on-nested-references-plus-variance-early-bound.rs
@@ -0,0 +1,13 @@
+// Regression test for #129021.
+
+static UNIT: &'static &'static () = &&();
+
+fn foo<'a: 'a, 'b: 'b, T>(_: &'a &'b (), v: &'b T) -> &'a T { v }
+
+fn bad<'a, T>(x: &'a T) -> &'static T {
+ let f: fn(_, &'a T) -> &'static T = foo;
+ //~^ ERROR lifetime may not live long enough
+ f(UNIT, x)
+}
+
+fn main() {}
diff --git a/tests/ui/implied-bounds/implied-bounds-on-nested-references-plus-variance-early-bound.stderr b/tests/ui/implied-bounds/implied-bounds-on-nested-references-plus-variance-early-bound.stderr
new file mode 100644
index 0000000..84d2a6d
--- /dev/null
+++ b/tests/ui/implied-bounds/implied-bounds-on-nested-references-plus-variance-early-bound.stderr
@@ -0,0 +1,10 @@
+error: lifetime may not live long enough
+ --> $DIR/implied-bounds-on-nested-references-plus-variance-early-bound.rs:8:12
+ |
+LL | fn bad<'a, T>(x: &'a T) -> &'static T {
+ | -- lifetime `'a` defined here
+LL | let f: fn(_, &'a T) -> &'static T = foo;
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^ type annotation requires that `'a` must outlive `'static`
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/implied-bounds/implied-bounds-on-nested-references-plus-variance-unnormalized.rs b/tests/ui/implied-bounds/implied-bounds-on-nested-references-plus-variance-unnormalized.rs
new file mode 100644
index 0000000..f306899
--- /dev/null
+++ b/tests/ui/implied-bounds/implied-bounds-on-nested-references-plus-variance-unnormalized.rs
@@ -0,0 +1,19 @@
+// Regression test for #129021.
+
+trait ToArg<T> {
+ type Arg;
+}
+impl<T, U> ToArg<T> for U {
+ type Arg = T;
+}
+
+fn extend_inner<'a, 'b>(x: &'a str) -> <&'b &'a () as ToArg<&'b str>>::Arg { x }
+fn extend<'a, 'b>(x: &'a str) -> &'b str {
+ (extend_inner as fn(_) -> _)(x)
+ //~^ ERROR lifetime may not live long enough
+}
+
+fn main() {
+ let y = extend(&String::from("Hello World"));
+ println!("{}", y);
+}
diff --git a/tests/ui/implied-bounds/implied-bounds-on-nested-references-plus-variance-unnormalized.stderr b/tests/ui/implied-bounds/implied-bounds-on-nested-references-plus-variance-unnormalized.stderr
new file mode 100644
index 0000000..4cdb959
--- /dev/null
+++ b/tests/ui/implied-bounds/implied-bounds-on-nested-references-plus-variance-unnormalized.stderr
@@ -0,0 +1,14 @@
+error: lifetime may not live long enough
+ --> $DIR/implied-bounds-on-nested-references-plus-variance-unnormalized.rs:12:5
+ |
+LL | fn extend<'a, 'b>(x: &'a str) -> &'b str {
+ | -- -- lifetime `'b` defined here
+ | |
+ | lifetime `'a` defined here
+LL | (extend_inner as fn(_) -> _)(x)
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function was supposed to return data with lifetime `'b` but it is returning data with lifetime `'a`
+ |
+ = help: consider adding the following bound: `'a: 'b`
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/implied-bounds/implied-bounds-on-nested-references-plus-variance.rs b/tests/ui/implied-bounds/implied-bounds-on-nested-references-plus-variance.rs
index f3401f3..6de81cb 100644
--- a/tests/ui/implied-bounds/implied-bounds-on-nested-references-plus-variance.rs
+++ b/tests/ui/implied-bounds/implied-bounds-on-nested-references-plus-variance.rs
@@ -1,8 +1,4 @@
-//@ check-pass
-//@ known-bug: #25860
-
-// Should fail. The combination of variance and implied bounds for nested
-// references allows us to infer a longer lifetime than we can prove.
+// Regression test for #129021.
static UNIT: &'static &'static () = &&();
@@ -10,6 +6,7 @@ fn foo<'a, 'b, T>(_: &'a &'b (), v: &'b T) -> &'a T { v }
fn bad<'a, T>(x: &'a T) -> &'static T {
let f: fn(_, &'a T) -> &'static T = foo;
+ //~^ ERROR lifetime may not live long enough
f(UNIT, x)
}
diff --git a/tests/ui/implied-bounds/implied-bounds-on-nested-references-plus-variance.stderr b/tests/ui/implied-bounds/implied-bounds-on-nested-references-plus-variance.stderr
new file mode 100644
index 0000000..c96fa92
--- /dev/null
+++ b/tests/ui/implied-bounds/implied-bounds-on-nested-references-plus-variance.stderr
@@ -0,0 +1,10 @@
+error: lifetime may not live long enough
+ --> $DIR/implied-bounds-on-nested-references-plus-variance.rs:8:12
+ |
+LL | fn bad<'a, T>(x: &'a T) -> &'static T {
+ | -- lifetime `'a` defined here
+LL | let f: fn(_, &'a T) -> &'static T = foo;
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^ type annotation requires that `'a` must outlive `'static`
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/issues/issue-48728.rs b/tests/ui/issues/issue-48728.rs
index 7ef05f4..8ad9289 100644
--- a/tests/ui/issues/issue-48728.rs
+++ b/tests/ui/issues/issue-48728.rs
@@ -1,12 +1,8 @@
// Regression test for #48728, an ICE that occurred computing
// coherence "help" information.
-//@ revisions: current next
-//@ ignore-compare-mode-next-solver (explicit revisions)
-//@[next] compile-flags: -Znext-solver
-//@[next] check-pass
-
-#[derive(Clone)] //[current]~ ERROR conflicting implementations of trait `Clone`
+//@ check-pass
+#[derive(Clone)]
struct Node<T: ?Sized>(Box<T>);
impl<T: Clone + ?Sized> Clone for Node<[T]> {
diff --git a/tests/ui/lexer/prefixed-lifetime.rs b/tests/ui/lexer/prefixed-lifetime.rs
new file mode 100644
index 0000000..6191b97
--- /dev/null
+++ b/tests/ui/lexer/prefixed-lifetime.rs
@@ -0,0 +1,10 @@
+//@ edition: 2021
+
+macro_rules! w {
+ ($($tt:tt)*) => {};
+}
+
+w!('foo#lifetime);
+//~^ ERROR prefix `'foo` is unknown
+
+fn main() {}
diff --git a/tests/ui/lexer/prefixed-lifetime.stderr b/tests/ui/lexer/prefixed-lifetime.stderr
new file mode 100644
index 0000000..39e8b5a
--- /dev/null
+++ b/tests/ui/lexer/prefixed-lifetime.stderr
@@ -0,0 +1,14 @@
+error: prefix `'foo` is unknown
+ --> $DIR/prefixed-lifetime.rs:7:4
+ |
+LL | w!('foo#lifetime);
+ | ^^^^ unknown prefix
+ |
+ = note: prefixed identifiers and literals are reserved since Rust 2021
+help: consider inserting whitespace here
+ |
+LL | w!('foo #lifetime);
+ | +
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/lifetimes/raw/gen-lt.e2024.stderr b/tests/ui/lifetimes/raw/gen-lt.e2024.stderr
new file mode 100644
index 0000000..232453d
--- /dev/null
+++ b/tests/ui/lifetimes/raw/gen-lt.e2024.stderr
@@ -0,0 +1,8 @@
+error: lifetimes cannot use keyword names
+ --> $DIR/gen-lt.rs:11:11
+ |
+LL | fn gen_lt<'gen>() {}
+ | ^^^^
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/lifetimes/raw/gen-lt.rs b/tests/ui/lifetimes/raw/gen-lt.rs
new file mode 100644
index 0000000..4f3ede5
--- /dev/null
+++ b/tests/ui/lifetimes/raw/gen-lt.rs
@@ -0,0 +1,14 @@
+//@ revisions: e2021 e2024
+
+//@[e2021] edition:2021
+//@[e2024] edition:2024
+//@[e2024] compile-flags: -Zunstable-options
+
+//@[e2021] check-pass
+
+fn raw_gen_lt<'r#gen>() {}
+
+fn gen_lt<'gen>() {}
+//[e2024]~^ ERROR lifetimes cannot use keyword names
+
+fn main() {}
diff --git a/tests/ui/lifetimes/raw/lifetimes-eq.rs b/tests/ui/lifetimes/raw/lifetimes-eq.rs
new file mode 100644
index 0000000..dddafb8
--- /dev/null
+++ b/tests/ui/lifetimes/raw/lifetimes-eq.rs
@@ -0,0 +1,8 @@
+//@ edition: 2021
+//@ check-pass
+
+// Test that `'r#a` is `'a`.
+
+fn test<'r#a>(x: &'a ()) {}
+
+fn main() {}
diff --git a/tests/ui/lifetimes/raw/macro-lt.rs b/tests/ui/lifetimes/raw/macro-lt.rs
new file mode 100644
index 0000000..d1167b0
--- /dev/null
+++ b/tests/ui/lifetimes/raw/macro-lt.rs
@@ -0,0 +1,12 @@
+//@ check-pass
+//@ edition: 2021
+
+macro_rules! lifetime {
+ ($lt:lifetime) => {
+ fn hello<$lt>() {}
+ }
+}
+
+lifetime!('r#struct);
+
+fn main() {}
diff --git a/tests/ui/lifetimes/raw/multiple-prefixes.rs b/tests/ui/lifetimes/raw/multiple-prefixes.rs
new file mode 100644
index 0000000..f335373
--- /dev/null
+++ b/tests/ui/lifetimes/raw/multiple-prefixes.rs
@@ -0,0 +1,6 @@
+//@ edition: 2021
+
+fn test(x: &'r#r#r ()) {}
+//~^ ERROR expected type, found `#`
+
+fn main() {}
diff --git a/tests/ui/lifetimes/raw/multiple-prefixes.stderr b/tests/ui/lifetimes/raw/multiple-prefixes.stderr
new file mode 100644
index 0000000..8d5479e
--- /dev/null
+++ b/tests/ui/lifetimes/raw/multiple-prefixes.stderr
@@ -0,0 +1,8 @@
+error: expected type, found `#`
+ --> $DIR/multiple-prefixes.rs:3:17
+ |
+LL | fn test(x: &'r#r#r ()) {}
+ | ^ expected type
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/lifetimes/raw/prim-lt.rs b/tests/ui/lifetimes/raw/prim-lt.rs
new file mode 100644
index 0000000..ca45efb
--- /dev/null
+++ b/tests/ui/lifetimes/raw/prim-lt.rs
@@ -0,0 +1,8 @@
+//@ check-pass
+//@ edition: 2021
+
+// Checks a primitive name can be defined as a lifetime.
+
+fn foo<'r#i32>() {}
+
+fn main() {}
diff --git a/tests/ui/lifetimes/raw/simple.rs b/tests/ui/lifetimes/raw/simple.rs
new file mode 100644
index 0000000..6f70a27
--- /dev/null
+++ b/tests/ui/lifetimes/raw/simple.rs
@@ -0,0 +1,21 @@
+//@ check-pass
+//@ edition: 2021
+
+fn foo<'r#struct>() {}
+
+fn hr<T>() where for<'r#struct> T: Into<&'r#struct ()> {}
+
+trait Foo<'r#struct> {}
+
+trait Bar<'r#struct> {
+ fn method(&'r#struct self) {}
+ fn method2(self: &'r#struct Self) {}
+}
+
+fn labeled() {
+ 'r#struct: loop {
+ break 'r#struct;
+ }
+}
+
+fn main() {}
diff --git a/tests/ui/lifetimes/raw/static-lt.rs b/tests/ui/lifetimes/raw/static-lt.rs
new file mode 100644
index 0000000..1fec709
--- /dev/null
+++ b/tests/ui/lifetimes/raw/static-lt.rs
@@ -0,0 +1,8 @@
+//@ check-pass
+//@ edition: 2021
+
+// Makes sure that `'r#static` is `'static`
+
+const FOO: &'r#static str = "hello, world";
+
+fn main() {}
diff --git a/tests/ui/lifetimes/raw/three-tokens.rs b/tests/ui/lifetimes/raw/three-tokens.rs
new file mode 100644
index 0000000..2ae54eb
--- /dev/null
+++ b/tests/ui/lifetimes/raw/three-tokens.rs
@@ -0,0 +1,12 @@
+//@ edition: 2015
+//@ check-pass
+// Ensure that we parse `'r#lt` as three tokens in edition 2015.
+
+macro_rules! ed2015 {
+ ('r # lt) => {};
+ ($lt:lifetime) => { compile_error!() };
+}
+
+ed2015!('r#lt);
+
+fn main() {}
diff --git a/tests/ui/lint/elided-named-lifetimes/example-from-issue48686.stderr b/tests/ui/lint/elided-named-lifetimes/example-from-issue48686.stderr
index 8c5426a..2d8c6e9 100644
--- a/tests/ui/lint/elided-named-lifetimes/example-from-issue48686.stderr
+++ b/tests/ui/lint/elided-named-lifetimes/example-from-issue48686.stderr
@@ -9,6 +9,10 @@
|
LL | #![deny(elided_named_lifetimes)]
| ^^^^^^^^^^^^^^^^^^^^^^
+help: consider specifying it explicitly
+ |
+LL | pub fn get_mut(&'static self, x: &mut u8) -> &'static mut u8 {
+ | +++++++
error: aborting due to 1 previous error
diff --git a/tests/ui/lint/elided-named-lifetimes/not-tied-to-crate.stderr b/tests/ui/lint/elided-named-lifetimes/not-tied-to-crate.stderr
index c465aab..3c01375 100644
--- a/tests/ui/lint/elided-named-lifetimes/not-tied-to-crate.stderr
+++ b/tests/ui/lint/elided-named-lifetimes/not-tied-to-crate.stderr
@@ -9,6 +9,10 @@
|
LL | #[warn(elided_named_lifetimes)]
| ^^^^^^^^^^^^^^^^^^^^^^
+help: consider specifying it explicitly
+ |
+LL | fn bar(x: &'static u8) -> &'static u8 {
+ | +++++++
error: elided lifetime has a name
--> $DIR/not-tied-to-crate.rs:11:31
@@ -21,6 +25,10 @@
|
LL | #[deny(elided_named_lifetimes)]
| ^^^^^^^^^^^^^^^^^^^^^^
+help: consider specifying it explicitly
+ |
+LL | fn baz(x: &'static u8) -> &'static u8 {
+ | +++++++
error: aborting due to 1 previous error; 1 warning emitted
diff --git a/tests/ui/lint/elided-named-lifetimes/static.stderr b/tests/ui/lint/elided-named-lifetimes/static.stderr
index d2e9776..fa2a2d3 100644
--- a/tests/ui/lint/elided-named-lifetimes/static.stderr
+++ b/tests/ui/lint/elided-named-lifetimes/static.stderr
@@ -9,24 +9,43 @@
|
LL | #![deny(elided_named_lifetimes)]
| ^^^^^^^^^^^^^^^^^^^^^^
+help: consider specifying it explicitly
+ |
+LL | fn ampersand(x: &'static u8) -> &'static u8 {
+ | +++++++
error: elided lifetime has a name
--> $DIR/static.rs:23:32
|
LL | fn brackets(x: &'static u8) -> Brackets {
| ^^^^^^^^ this elided lifetime gets resolved as `'static`
+ |
+help: consider specifying it explicitly
+ |
+LL | fn brackets(x: &'static u8) -> Brackets<'static> {
+ | +++++++++
error: elided lifetime has a name
--> $DIR/static.rs:30:34
|
LL | fn comma(x: &'static u8) -> Comma<u8> {
| ^ this elided lifetime gets resolved as `'static`
+ |
+help: consider specifying it explicitly
+ |
+LL | fn comma(x: &'static u8) -> Comma<'static, u8> {
+ | ++++++++
error: elided lifetime has a name
--> $DIR/static.rs:35:35
|
LL | fn underscore(x: &'static u8) -> &'_ u8 {
| ^^ this elided lifetime gets resolved as `'static`
+ |
+help: consider specifying it explicitly
+ |
+LL | fn underscore(x: &'static u8) -> &'static u8 {
+ | ~~~~~~~
error: aborting due to 4 previous errors
diff --git a/tests/ui/parser/extern-crate-unexpected-token.stderr b/tests/ui/parser/extern-crate-unexpected-token.stderr
index f83bb3e..951b027 100644
--- a/tests/ui/parser/extern-crate-unexpected-token.stderr
+++ b/tests/ui/parser/extern-crate-unexpected-token.stderr
@@ -3,6 +3,11 @@
|
LL | extern crte foo;
| ^^^^ expected one of `crate` or `{`
+ |
+help: there is a keyword `crate` with a similar name
+ |
+LL | extern crate foo;
+ | ~~~~~
error: aborting due to 1 previous error
diff --git a/tests/ui/parser/issues/issue-70549-resolve-after-recovered-self-ctor.stderr b/tests/ui/parser/issues/issue-70549-resolve-after-recovered-self-ctor.stderr
index 79c574e..00f372b 100644
--- a/tests/ui/parser/issues/issue-70549-resolve-after-recovered-self-ctor.stderr
+++ b/tests/ui/parser/issues/issue-70549-resolve-after-recovered-self-ctor.stderr
@@ -8,10 +8,16 @@
--> $DIR/issue-70549-resolve-after-recovered-self-ctor.rs:4:17
|
LL | fn foo(&mur Self) {}
- | -----^^^^
- | | |
- | | expected one of `:`, `@`, or `|`
- | help: declare the type after the parameter binding: `<identifier>: <type>`
+ | ^^^^ expected one of `:`, `@`, or `|`
+ |
+help: there is a keyword `mut` with a similar name
+ |
+LL | fn foo(&mut Self) {}
+ | ~~~
+help: declare the type after the parameter binding
+ |
+LL | fn foo(<identifier>: <type>) {}
+ | ~~~~~~~~~~~~~~~~~~~~
error: unexpected lifetime `'static` in pattern
--> $DIR/issue-70549-resolve-after-recovered-self-ctor.rs:8:13
@@ -35,16 +41,27 @@
--> $DIR/issue-70549-resolve-after-recovered-self-ctor.rs:8:25
|
LL | fn bar(&'static mur Self) {}
- | -------------^^^^
- | | |
- | | expected one of `:`, `@`, or `|`
- | help: declare the type after the parameter binding: `<identifier>: <type>`
+ | ^^^^ expected one of `:`, `@`, or `|`
+ |
+help: there is a keyword `mut` with a similar name
+ |
+LL | fn bar(&'static mut Self) {}
+ | ~~~
+help: declare the type after the parameter binding
+ |
+LL | fn bar(<identifier>: <type>) {}
+ | ~~~~~~~~~~~~~~~~~~~~
error: expected one of `:`, `@`, or `|`, found keyword `Self`
--> $DIR/issue-70549-resolve-after-recovered-self-ctor.rs:14:17
|
LL | fn baz(&mur Self @ _) {}
| ^^^^ expected one of `:`, `@`, or `|`
+ |
+help: there is a keyword `mut` with a similar name
+ |
+LL | fn baz(&mut Self @ _) {}
+ | ~~~
error[E0533]: expected unit struct, found self constructor `Self`
--> $DIR/issue-70549-resolve-after-recovered-self-ctor.rs:4:17
diff --git a/tests/ui/parser/misspelled-keywords/assoc-type.rs b/tests/ui/parser/misspelled-keywords/assoc-type.rs
new file mode 100644
index 0000000..a6b694a
--- /dev/null
+++ b/tests/ui/parser/misspelled-keywords/assoc-type.rs
@@ -0,0 +1,6 @@
+trait Animal {
+ Type Result = u8;
+ //~^ ERROR expected one of
+}
+
+fn main() {}
diff --git a/tests/ui/parser/misspelled-keywords/assoc-type.stderr b/tests/ui/parser/misspelled-keywords/assoc-type.stderr
new file mode 100644
index 0000000..677da53
--- /dev/null
+++ b/tests/ui/parser/misspelled-keywords/assoc-type.stderr
@@ -0,0 +1,18 @@
+error: expected one of `!` or `::`, found `Result`
+ --> $DIR/assoc-type.rs:2:10
+ |
+LL | trait Animal {
+ | - while parsing this item list starting here
+LL | Type Result = u8;
+ | ^^^^^^ expected one of `!` or `::`
+LL |
+LL | }
+ | - the item list ends here
+ |
+help: write keyword `type` in lowercase
+ |
+LL | type Result = u8;
+ | ~~~~
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/parser/misspelled-keywords/async-move.rs b/tests/ui/parser/misspelled-keywords/async-move.rs
new file mode 100644
index 0000000..702a905e
--- /dev/null
+++ b/tests/ui/parser/misspelled-keywords/async-move.rs
@@ -0,0 +1,6 @@
+//@ edition: 2018
+
+fn main() {
+ async Move {}
+ //~^ ERROR expected one of
+}
diff --git a/tests/ui/parser/misspelled-keywords/async-move.stderr b/tests/ui/parser/misspelled-keywords/async-move.stderr
new file mode 100644
index 0000000..4be4b56
--- /dev/null
+++ b/tests/ui/parser/misspelled-keywords/async-move.stderr
@@ -0,0 +1,13 @@
+error: expected one of `move`, `|`, or `||`, found `Move`
+ --> $DIR/async-move.rs:4:11
+ |
+LL | async Move {}
+ | ^^^^ expected one of `move`, `|`, or `||`
+ |
+help: write keyword `move` in lowercase
+ |
+LL | async move {}
+ | ~~~~
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/parser/misspelled-keywords/const-fn.rs b/tests/ui/parser/misspelled-keywords/const-fn.rs
new file mode 100644
index 0000000..c4174b6
--- /dev/null
+++ b/tests/ui/parser/misspelled-keywords/const-fn.rs
@@ -0,0 +1,5 @@
+cnst fn code() {}
+//~^ ERROR expected one of
+
+fn main() {
+}
diff --git a/tests/ui/parser/misspelled-keywords/const-fn.stderr b/tests/ui/parser/misspelled-keywords/const-fn.stderr
new file mode 100644
index 0000000..5646b26
--- /dev/null
+++ b/tests/ui/parser/misspelled-keywords/const-fn.stderr
@@ -0,0 +1,13 @@
+error: expected one of `!` or `::`, found keyword `fn`
+ --> $DIR/const-fn.rs:1:6
+ |
+LL | cnst fn code() {}
+ | ^^ expected one of `!` or `::`
+ |
+help: there is a keyword `const` with a similar name
+ |
+LL | const fn code() {}
+ | ~~~~~
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/parser/misspelled-keywords/const-generics.rs b/tests/ui/parser/misspelled-keywords/const-generics.rs
new file mode 100644
index 0000000..2df64a8
--- /dev/null
+++ b/tests/ui/parser/misspelled-keywords/const-generics.rs
@@ -0,0 +1,4 @@
+fn foo<consta N: usize>(_arr: [i32; N]) {}
+//~^ ERROR expected one of
+
+fn main() {}
diff --git a/tests/ui/parser/misspelled-keywords/const-generics.stderr b/tests/ui/parser/misspelled-keywords/const-generics.stderr
new file mode 100644
index 0000000..fd59999
--- /dev/null
+++ b/tests/ui/parser/misspelled-keywords/const-generics.stderr
@@ -0,0 +1,13 @@
+error: expected one of `,`, `:`, `=`, or `>`, found `N`
+ --> $DIR/const-generics.rs:1:15
+ |
+LL | fn foo<consta N: usize>(_arr: [i32; N]) {}
+ | ^ expected one of `,`, `:`, `=`, or `>`
+ |
+help: there is a keyword `const` with a similar name
+ |
+LL | fn foo<const N: usize>(_arr: [i32; N]) {}
+ | ~~~~~
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/parser/misspelled-keywords/const.rs b/tests/ui/parser/misspelled-keywords/const.rs
new file mode 100644
index 0000000..b481408
--- /dev/null
+++ b/tests/ui/parser/misspelled-keywords/const.rs
@@ -0,0 +1,4 @@
+cons A: u8 = 10;
+//~^ ERROR expected one of
+
+fn main() {}
diff --git a/tests/ui/parser/misspelled-keywords/const.stderr b/tests/ui/parser/misspelled-keywords/const.stderr
new file mode 100644
index 0000000..35e4d73
--- /dev/null
+++ b/tests/ui/parser/misspelled-keywords/const.stderr
@@ -0,0 +1,13 @@
+error: expected one of `!` or `::`, found `A`
+ --> $DIR/const.rs:1:6
+ |
+LL | cons A: u8 = 10;
+ | ^ expected one of `!` or `::`
+ |
+help: there is a keyword `const` with a similar name
+ |
+LL | const A: u8 = 10;
+ | ~~~~~
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/parser/misspelled-keywords/for-loop.rs b/tests/ui/parser/misspelled-keywords/for-loop.rs
new file mode 100644
index 0000000..6aba581
--- /dev/null
+++ b/tests/ui/parser/misspelled-keywords/for-loop.rs
@@ -0,0 +1,4 @@
+fn main() {
+ form i in 1..10 {}
+ //~^ ERROR expected one of
+}
diff --git a/tests/ui/parser/misspelled-keywords/for-loop.stderr b/tests/ui/parser/misspelled-keywords/for-loop.stderr
new file mode 100644
index 0000000..d2236ab
--- /dev/null
+++ b/tests/ui/parser/misspelled-keywords/for-loop.stderr
@@ -0,0 +1,13 @@
+error: expected one of `!`, `.`, `::`, `;`, `?`, `{`, `}`, or an operator, found `i`
+ --> $DIR/for-loop.rs:2:10
+ |
+LL | form i in 1..10 {}
+ | ^ expected one of 8 possible tokens
+ |
+help: there is a keyword `for` with a similar name
+ |
+LL | for i in 1..10 {}
+ | ~~~
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/parser/misspelled-keywords/hrdt.rs b/tests/ui/parser/misspelled-keywords/hrdt.rs
new file mode 100644
index 0000000..9ca9e1b
--- /dev/null
+++ b/tests/ui/parser/misspelled-keywords/hrdt.rs
@@ -0,0 +1,16 @@
+struct Closure<F> {
+ data: (u8, u16),
+ func: F,
+}
+
+impl<F> Closure<F>
+ Where for<'a> F: Fn(&'a (u8, u16)) -> &'a u8,
+//~^ ERROR expected one of
+{
+ fn call(&self) -> &u8 {
+ (self.func)(&self.data)
+ }
+}
+
+
+fn main() {}
diff --git a/tests/ui/parser/misspelled-keywords/hrdt.stderr b/tests/ui/parser/misspelled-keywords/hrdt.stderr
new file mode 100644
index 0000000..5393a73
--- /dev/null
+++ b/tests/ui/parser/misspelled-keywords/hrdt.stderr
@@ -0,0 +1,13 @@
+error: expected one of `!`, `(`, `+`, `::`, `<`, `where`, or `{`, found keyword `for`
+ --> $DIR/hrdt.rs:7:11
+ |
+LL | Where for<'a> F: Fn(&'a (u8, u16)) -> &'a u8,
+ | ^^^ expected one of 7 possible tokens
+ |
+help: write keyword `where` in lowercase (notice the capitalization difference)
+ |
+LL | where for<'a> F: Fn(&'a (u8, u16)) -> &'a u8,
+ | ~~~~~
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/parser/misspelled-keywords/impl-block.rs b/tests/ui/parser/misspelled-keywords/impl-block.rs
new file mode 100644
index 0000000..dc2570c
--- /dev/null
+++ b/tests/ui/parser/misspelled-keywords/impl-block.rs
@@ -0,0 +1,6 @@
+struct Human;
+
+ipml Human {}
+//~^ ERROR expected one of
+
+fn main() {}
diff --git a/tests/ui/parser/misspelled-keywords/impl-block.stderr b/tests/ui/parser/misspelled-keywords/impl-block.stderr
new file mode 100644
index 0000000..d86ae32
--- /dev/null
+++ b/tests/ui/parser/misspelled-keywords/impl-block.stderr
@@ -0,0 +1,13 @@
+error: expected one of `!` or `::`, found `Human`
+ --> $DIR/impl-block.rs:3:6
+ |
+LL | ipml Human {}
+ | ^^^^^ expected one of `!` or `::`
+ |
+help: there is a keyword `impl` with a similar name
+ |
+LL | impl Human {}
+ | ~~~~
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/parser/misspelled-keywords/impl-return.rs b/tests/ui/parser/misspelled-keywords/impl-return.rs
new file mode 100644
index 0000000..c9d1973
--- /dev/null
+++ b/tests/ui/parser/misspelled-keywords/impl-return.rs
@@ -0,0 +1,4 @@
+fn code() -> Impl Display {}
+//~^ ERROR expected one of
+
+fn main() {}
diff --git a/tests/ui/parser/misspelled-keywords/impl-return.stderr b/tests/ui/parser/misspelled-keywords/impl-return.stderr
new file mode 100644
index 0000000..883f5ce
--- /dev/null
+++ b/tests/ui/parser/misspelled-keywords/impl-return.stderr
@@ -0,0 +1,13 @@
+error: expected one of `!`, `(`, `+`, `::`, `<`, `where`, or `{`, found `Display`
+ --> $DIR/impl-return.rs:1:19
+ |
+LL | fn code() -> Impl Display {}
+ | ^^^^^^^ expected one of 7 possible tokens
+ |
+help: write keyword `impl` in lowercase (notice the capitalization difference)
+ |
+LL | fn code() -> impl Display {}
+ | ~~~~
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/parser/misspelled-keywords/impl-trait-for.rs b/tests/ui/parser/misspelled-keywords/impl-trait-for.rs
new file mode 100644
index 0000000..c6f3fcd
--- /dev/null
+++ b/tests/ui/parser/misspelled-keywords/impl-trait-for.rs
@@ -0,0 +1,6 @@
+struct Human;
+
+impl Debug form Human {}
+//~^ ERROR expected one of
+
+fn main() {}
diff --git a/tests/ui/parser/misspelled-keywords/impl-trait-for.stderr b/tests/ui/parser/misspelled-keywords/impl-trait-for.stderr
new file mode 100644
index 0000000..8dd5a46
--- /dev/null
+++ b/tests/ui/parser/misspelled-keywords/impl-trait-for.stderr
@@ -0,0 +1,13 @@
+error: expected one of `!`, `(`, `+`, `::`, `<`, `where`, or `{`, found `Human`
+ --> $DIR/impl-trait-for.rs:3:17
+ |
+LL | impl Debug form Human {}
+ | ^^^^^ expected one of 7 possible tokens
+ |
+help: there is a keyword `for` with a similar name
+ |
+LL | impl Debug for Human {}
+ | ~~~
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/parser/misspelled-keywords/impl-trait.rs b/tests/ui/parser/misspelled-keywords/impl-trait.rs
new file mode 100644
index 0000000..99380b8
--- /dev/null
+++ b/tests/ui/parser/misspelled-keywords/impl-trait.rs
@@ -0,0 +1,4 @@
+fn code<T: impll Debug>() -> u8 {}
+//~^ ERROR expected one of
+
+fn main() {}
diff --git a/tests/ui/parser/misspelled-keywords/impl-trait.stderr b/tests/ui/parser/misspelled-keywords/impl-trait.stderr
new file mode 100644
index 0000000..15a8f99
--- /dev/null
+++ b/tests/ui/parser/misspelled-keywords/impl-trait.stderr
@@ -0,0 +1,17 @@
+error: expected one of `(`, `+`, `,`, `::`, `<`, `=`, or `>`, found `Debug`
+ --> $DIR/impl-trait.rs:1:18
+ |
+LL | fn code<T: impll Debug>() -> u8 {}
+ | ^^^^^ expected one of 7 possible tokens
+ |
+help: there is a keyword `impl` with a similar name
+ |
+LL | fn code<T: impl Debug>() -> u8 {}
+ | ~~~~
+help: you might have meant to end the type parameters here
+ |
+LL | fn code<T: impll> Debug>() -> u8 {}
+ | +
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/parser/misspelled-keywords/let-else.rs b/tests/ui/parser/misspelled-keywords/let-else.rs
new file mode 100644
index 0000000..0d5a03e
--- /dev/null
+++ b/tests/ui/parser/misspelled-keywords/let-else.rs
@@ -0,0 +1,4 @@
+fn main() {
+ let Some(a) = Some(10) elze {}
+ //~^ ERROR expected one of
+}
diff --git a/tests/ui/parser/misspelled-keywords/let-else.stderr b/tests/ui/parser/misspelled-keywords/let-else.stderr
new file mode 100644
index 0000000..6f41a0d
--- /dev/null
+++ b/tests/ui/parser/misspelled-keywords/let-else.stderr
@@ -0,0 +1,13 @@
+error: expected one of `.`, `;`, `?`, `else`, or an operator, found `elze`
+ --> $DIR/let-else.rs:2:28
+ |
+LL | let Some(a) = Some(10) elze {}
+ | ^^^^ expected one of `.`, `;`, `?`, `else`, or an operator
+ |
+help: there is a keyword `else` with a similar name
+ |
+LL | let Some(a) = Some(10) else {}
+ | ~~~~
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/parser/misspelled-keywords/let-mut.rs b/tests/ui/parser/misspelled-keywords/let-mut.rs
new file mode 100644
index 0000000..83228fe
--- /dev/null
+++ b/tests/ui/parser/misspelled-keywords/let-mut.rs
@@ -0,0 +1,4 @@
+fn main() {
+ let muta a = 10;
+ //~^ ERROR expected one of
+}
diff --git a/tests/ui/parser/misspelled-keywords/let-mut.stderr b/tests/ui/parser/misspelled-keywords/let-mut.stderr
new file mode 100644
index 0000000..766d2a0
--- /dev/null
+++ b/tests/ui/parser/misspelled-keywords/let-mut.stderr
@@ -0,0 +1,13 @@
+error: expected one of `:`, `;`, `=`, `@`, or `|`, found `a`
+ --> $DIR/let-mut.rs:2:14
+ |
+LL | let muta a = 10;
+ | ^ expected one of `:`, `;`, `=`, `@`, or `|`
+ |
+help: there is a keyword `mut` with a similar name
+ |
+LL | let mut a = 10;
+ | ~~~
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/parser/misspelled-keywords/let.rs b/tests/ui/parser/misspelled-keywords/let.rs
new file mode 100644
index 0000000..461c3e5
--- /dev/null
+++ b/tests/ui/parser/misspelled-keywords/let.rs
@@ -0,0 +1,9 @@
+fn main() {
+ Let a = 10;
+ //~^ ERROR expected one of
+}
+
+fn code() {
+ lett a = 10;
+ //~^ ERROR expected one of
+}
diff --git a/tests/ui/parser/misspelled-keywords/let.stderr b/tests/ui/parser/misspelled-keywords/let.stderr
new file mode 100644
index 0000000..c2dcdef
--- /dev/null
+++ b/tests/ui/parser/misspelled-keywords/let.stderr
@@ -0,0 +1,24 @@
+error: expected one of `!`, `.`, `::`, `;`, `?`, `{`, `}`, or an operator, found `a`
+ --> $DIR/let.rs:2:9
+ |
+LL | Let a = 10;
+ | ^ expected one of 8 possible tokens
+ |
+help: write keyword `let` in lowercase
+ |
+LL | let a = 10;
+ | ~~~
+
+error: expected one of `!`, `.`, `::`, `;`, `?`, `{`, `}`, or an operator, found `a`
+ --> $DIR/let.rs:7:10
+ |
+LL | lett a = 10;
+ | ^ expected one of 8 possible tokens
+ |
+help: there is a keyword `let` with a similar name
+ |
+LL | let a = 10;
+ | ~~~
+
+error: aborting due to 2 previous errors
+
diff --git a/tests/ui/parser/misspelled-keywords/match.rs b/tests/ui/parser/misspelled-keywords/match.rs
new file mode 100644
index 0000000..a31840a
--- /dev/null
+++ b/tests/ui/parser/misspelled-keywords/match.rs
@@ -0,0 +1,5 @@
+fn main() {
+ let a = 10;
+ matche a {}
+ //~^ ERROR expected one of
+}
diff --git a/tests/ui/parser/misspelled-keywords/match.stderr b/tests/ui/parser/misspelled-keywords/match.stderr
new file mode 100644
index 0000000..90780eb
--- /dev/null
+++ b/tests/ui/parser/misspelled-keywords/match.stderr
@@ -0,0 +1,13 @@
+error: expected one of `!`, `.`, `::`, `;`, `?`, `{`, `}`, or an operator, found `a`
+ --> $DIR/match.rs:3:12
+ |
+LL | matche a {}
+ | ^ expected one of 8 possible tokens
+ |
+help: there is a keyword `match` with a similar name
+ |
+LL | match a {}
+ | ~~~~~
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/parser/misspelled-keywords/mod.rs b/tests/ui/parser/misspelled-keywords/mod.rs
new file mode 100644
index 0000000..24f0101
--- /dev/null
+++ b/tests/ui/parser/misspelled-keywords/mod.rs
@@ -0,0 +1,4 @@
+mode parser;
+//~^ ERROR expected one of
+
+fn main() {}
diff --git a/tests/ui/parser/misspelled-keywords/mod.stderr b/tests/ui/parser/misspelled-keywords/mod.stderr
new file mode 100644
index 0000000..6daeb4e
--- /dev/null
+++ b/tests/ui/parser/misspelled-keywords/mod.stderr
@@ -0,0 +1,13 @@
+error: expected one of `!` or `::`, found `parser`
+ --> $DIR/mod.rs:1:6
+ |
+LL | mode parser;
+ | ^^^^^^ expected one of `!` or `::`
+ |
+help: there is a keyword `mod` with a similar name
+ |
+LL | mod parser;
+ | ~~~
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/parser/misspelled-keywords/pub-fn.rs b/tests/ui/parser/misspelled-keywords/pub-fn.rs
new file mode 100644
index 0000000..50d7129
--- /dev/null
+++ b/tests/ui/parser/misspelled-keywords/pub-fn.rs
@@ -0,0 +1,5 @@
+puB fn code() {}
+//~^ ERROR expected one of
+
+fn main() {
+}
diff --git a/tests/ui/parser/misspelled-keywords/pub-fn.stderr b/tests/ui/parser/misspelled-keywords/pub-fn.stderr
new file mode 100644
index 0000000..82ca710
--- /dev/null
+++ b/tests/ui/parser/misspelled-keywords/pub-fn.stderr
@@ -0,0 +1,13 @@
+error: expected one of `#`, `async`, `auto`, `const`, `default`, `enum`, `extern`, `fn`, `gen`, `impl`, `macro_rules`, `macro`, `mod`, `pub`, `safe`, `static`, `struct`, `trait`, `type`, `unsafe`, or `use`, found `puB`
+ --> $DIR/pub-fn.rs:1:1
+ |
+LL | puB fn code() {}
+ | ^^^ expected one of 21 possible tokens
+ |
+help: write keyword `pub` in lowercase
+ |
+LL | pub fn code() {}
+ | ~~~
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/parser/misspelled-keywords/ref.rs b/tests/ui/parser/misspelled-keywords/ref.rs
new file mode 100644
index 0000000..76b367a
--- /dev/null
+++ b/tests/ui/parser/misspelled-keywords/ref.rs
@@ -0,0 +1,9 @@
+fn main() {
+ let a = Some(vec![1, 2]);
+ match a {
+ Some(refe list) => println!("{list:?}"),
+ //~^ ERROR expected one of
+ //~| ERROR this pattern has 2 fields,
+ _ => println!("none"),
+ }
+}
diff --git a/tests/ui/parser/misspelled-keywords/ref.stderr b/tests/ui/parser/misspelled-keywords/ref.stderr
new file mode 100644
index 0000000..3a79b7b
--- /dev/null
+++ b/tests/ui/parser/misspelled-keywords/ref.stderr
@@ -0,0 +1,27 @@
+error: expected one of `)`, `,`, `@`, or `|`, found `list`
+ --> $DIR/ref.rs:4:19
+ |
+LL | Some(refe list) => println!("{list:?}"),
+ | ^^^^ expected one of `)`, `,`, `@`, or `|`
+ |
+help: there is a keyword `ref` with a similar name
+ |
+LL | Some(ref list) => println!("{list:?}"),
+ | ~~~
+help: missing `,`
+ |
+LL | Some(refe, list) => println!("{list:?}"),
+ | +
+
+error[E0023]: this pattern has 2 fields, but the corresponding tuple variant has 1 field
+ --> $DIR/ref.rs:4:14
+ |
+LL | Some(refe list) => println!("{list:?}"),
+ | ^^^^ ^^^^ expected 1 field, found 2
+ --> $SRC_DIR/core/src/option.rs:LL:COL
+ |
+ = note: tuple variant has 1 field
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0023`.
diff --git a/tests/ui/parser/misspelled-keywords/return.rs b/tests/ui/parser/misspelled-keywords/return.rs
new file mode 100644
index 0000000..4bbe55d
--- /dev/null
+++ b/tests/ui/parser/misspelled-keywords/return.rs
@@ -0,0 +1,7 @@
+fn code() -> u8 {
+ let a = 10;
+ returnn a;
+ //~^ ERROR expected one of
+}
+
+fn main() {}
diff --git a/tests/ui/parser/misspelled-keywords/return.stderr b/tests/ui/parser/misspelled-keywords/return.stderr
new file mode 100644
index 0000000..efa45f3
--- /dev/null
+++ b/tests/ui/parser/misspelled-keywords/return.stderr
@@ -0,0 +1,13 @@
+error: expected one of `!`, `.`, `::`, `;`, `?`, `{`, `}`, or an operator, found `a`
+ --> $DIR/return.rs:3:13
+ |
+LL | returnn a;
+ | ^ expected one of 8 possible tokens
+ |
+help: there is a keyword `return` with a similar name
+ |
+LL | return a;
+ | ~~~~~~
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/parser/misspelled-keywords/static-mut.rs b/tests/ui/parser/misspelled-keywords/static-mut.rs
new file mode 100644
index 0000000..6509f62
--- /dev/null
+++ b/tests/ui/parser/misspelled-keywords/static-mut.rs
@@ -0,0 +1,5 @@
+static muta a: u8 = 0;
+//~^ ERROR expected one of
+//~| ERROR missing type for
+
+fn main() {}
diff --git a/tests/ui/parser/misspelled-keywords/static-mut.stderr b/tests/ui/parser/misspelled-keywords/static-mut.stderr
new file mode 100644
index 0000000..3c25af5
--- /dev/null
+++ b/tests/ui/parser/misspelled-keywords/static-mut.stderr
@@ -0,0 +1,24 @@
+error: expected one of `:`, `;`, or `=`, found `a`
+ --> $DIR/static-mut.rs:1:13
+ |
+LL | static muta a: u8 = 0;
+ | ^ expected one of `:`, `;`, or `=`
+ |
+help: there is a keyword `mut` with a similar name
+ |
+LL | static mut a: u8 = 0;
+ | ~~~
+
+error: missing type for `static` item
+ --> $DIR/static-mut.rs:1:12
+ |
+LL | static muta a: u8 = 0;
+ | ^
+ |
+help: provide a type for the item
+ |
+LL | static muta: <type> a: u8 = 0;
+ | ++++++++
+
+error: aborting due to 2 previous errors
+
diff --git a/tests/ui/parser/misspelled-keywords/static.rs b/tests/ui/parser/misspelled-keywords/static.rs
new file mode 100644
index 0000000..240f4f5
--- /dev/null
+++ b/tests/ui/parser/misspelled-keywords/static.rs
@@ -0,0 +1,4 @@
+Static a = 0;
+//~^ ERROR expected one of
+
+fn main() {}
diff --git a/tests/ui/parser/misspelled-keywords/static.stderr b/tests/ui/parser/misspelled-keywords/static.stderr
new file mode 100644
index 0000000..003aa39
--- /dev/null
+++ b/tests/ui/parser/misspelled-keywords/static.stderr
@@ -0,0 +1,13 @@
+error: expected one of `!` or `::`, found `a`
+ --> $DIR/static.rs:1:8
+ |
+LL | Static a = 0;
+ | ^ expected one of `!` or `::`
+ |
+help: write keyword `static` in lowercase (notice the capitalization difference)
+ |
+LL | static a = 0;
+ | ~~~~~~
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/parser/misspelled-keywords/struct.rs b/tests/ui/parser/misspelled-keywords/struct.rs
new file mode 100644
index 0000000..0f64dec
--- /dev/null
+++ b/tests/ui/parser/misspelled-keywords/struct.rs
@@ -0,0 +1,4 @@
+Struct Foor {
+//~^ ERROR expected one of
+ hello: String,
+}
diff --git a/tests/ui/parser/misspelled-keywords/struct.stderr b/tests/ui/parser/misspelled-keywords/struct.stderr
new file mode 100644
index 0000000..559182f
--- /dev/null
+++ b/tests/ui/parser/misspelled-keywords/struct.stderr
@@ -0,0 +1,13 @@
+error: expected one of `!` or `::`, found `Foor`
+ --> $DIR/struct.rs:1:8
+ |
+LL | Struct Foor {
+ | ^^^^ expected one of `!` or `::`
+ |
+help: write keyword `struct` in lowercase (notice the capitalization difference)
+ |
+LL | struct Foor {
+ | ~~~~~~
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/parser/misspelled-keywords/unsafe-fn.rs b/tests/ui/parser/misspelled-keywords/unsafe-fn.rs
new file mode 100644
index 0000000..49a1322
--- /dev/null
+++ b/tests/ui/parser/misspelled-keywords/unsafe-fn.rs
@@ -0,0 +1,4 @@
+unsafee fn code() {}
+//~^ ERROR expected one of
+
+fn main() {}
diff --git a/tests/ui/parser/misspelled-keywords/unsafe-fn.stderr b/tests/ui/parser/misspelled-keywords/unsafe-fn.stderr
new file mode 100644
index 0000000..b13281b
--- /dev/null
+++ b/tests/ui/parser/misspelled-keywords/unsafe-fn.stderr
@@ -0,0 +1,13 @@
+error: expected one of `!` or `::`, found keyword `fn`
+ --> $DIR/unsafe-fn.rs:1:9
+ |
+LL | unsafee fn code() {}
+ | ^^ expected one of `!` or `::`
+ |
+help: there is a keyword `unsafe` with a similar name
+ |
+LL | unsafe fn code() {}
+ | ~~~~~~
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/parser/misspelled-keywords/use.rs b/tests/ui/parser/misspelled-keywords/use.rs
new file mode 100644
index 0000000..f491165
--- /dev/null
+++ b/tests/ui/parser/misspelled-keywords/use.rs
@@ -0,0 +1,4 @@
+usee a::b;
+//~^ ERROR expected one of
+
+fn main() {}
diff --git a/tests/ui/parser/misspelled-keywords/use.stderr b/tests/ui/parser/misspelled-keywords/use.stderr
new file mode 100644
index 0000000..db6dffd
--- /dev/null
+++ b/tests/ui/parser/misspelled-keywords/use.stderr
@@ -0,0 +1,13 @@
+error: expected one of `!` or `::`, found `a`
+ --> $DIR/use.rs:1:6
+ |
+LL | usee a::b;
+ | ^ expected one of `!` or `::`
+ |
+help: there is a keyword `use` with a similar name
+ |
+LL | use a::b;
+ | ~~~
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/parser/misspelled-keywords/where-clause.rs b/tests/ui/parser/misspelled-keywords/where-clause.rs
new file mode 100644
index 0000000..c03d04d
--- /dev/null
+++ b/tests/ui/parser/misspelled-keywords/where-clause.rs
@@ -0,0 +1,8 @@
+fn code<T>() -> u8
+wheree
+//~^ ERROR expected one of
+ T: Debug,
+{
+}
+
+fn main() {}
diff --git a/tests/ui/parser/misspelled-keywords/where-clause.stderr b/tests/ui/parser/misspelled-keywords/where-clause.stderr
new file mode 100644
index 0000000..5143c30
--- /dev/null
+++ b/tests/ui/parser/misspelled-keywords/where-clause.stderr
@@ -0,0 +1,15 @@
+error: expected one of `!`, `(`, `+`, `::`, `<`, `where`, or `{`, found `wheree`
+ --> $DIR/where-clause.rs:2:1
+ |
+LL | fn code<T>() -> u8
+ | - expected one of 7 possible tokens
+LL | wheree
+ | ^^^^^^ unexpected token
+ |
+help: there is a keyword `where` with a similar name
+ |
+LL | where
+ |
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/parser/misspelled-keywords/while-loop.rs b/tests/ui/parser/misspelled-keywords/while-loop.rs
new file mode 100644
index 0000000..37d337f
--- /dev/null
+++ b/tests/ui/parser/misspelled-keywords/while-loop.rs
@@ -0,0 +1,5 @@
+fn main() {
+ whilee a < b {
+ //~^ ERROR expected one of
+ }
+}
diff --git a/tests/ui/parser/misspelled-keywords/while-loop.stderr b/tests/ui/parser/misspelled-keywords/while-loop.stderr
new file mode 100644
index 0000000..7d15044
--- /dev/null
+++ b/tests/ui/parser/misspelled-keywords/while-loop.stderr
@@ -0,0 +1,13 @@
+error: expected one of `!`, `.`, `::`, `;`, `?`, `{`, `}`, or an operator, found `a`
+ --> $DIR/while-loop.rs:2:12
+ |
+LL | whilee a < b {
+ | ^ expected one of 8 possible tokens
+ |
+help: there is a keyword `while` with a similar name
+ |
+LL | while a < b {
+ | ~~~~~
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/parser/misspelled-keywords/while-without-identifiers.rs b/tests/ui/parser/misspelled-keywords/while-without-identifiers.rs
new file mode 100644
index 0000000..203db83
--- /dev/null
+++ b/tests/ui/parser/misspelled-keywords/while-without-identifiers.rs
@@ -0,0 +1,4 @@
+fn main() {
+ whilee 2 > 1 {}
+ //~^ ERROR expected one of
+}
diff --git a/tests/ui/parser/misspelled-keywords/while-without-identifiers.stderr b/tests/ui/parser/misspelled-keywords/while-without-identifiers.stderr
new file mode 100644
index 0000000..121e393
--- /dev/null
+++ b/tests/ui/parser/misspelled-keywords/while-without-identifiers.stderr
@@ -0,0 +1,8 @@
+error: expected one of `!`, `.`, `::`, `;`, `?`, `{`, `}`, or an operator, found `2`
+ --> $DIR/while-without-identifiers.rs:2:12
+ |
+LL | whilee 2 > 1 {}
+ | ^ expected one of 8 possible tokens
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/proc-macro/macro-rules-derive-cfg.rs b/tests/ui/proc-macro/macro-rules-derive-cfg.rs
index 68026a6..c34f169 100644
--- a/tests/ui/proc-macro/macro-rules-derive-cfg.rs
+++ b/tests/ui/proc-macro/macro-rules-derive-cfg.rs
@@ -14,17 +14,15 @@
macro_rules! produce_it {
($expr:expr) => {
#[derive(Print)]
- struct Foo {
- val: [bool; {
- let a = #[cfg_attr(not(FALSE), rustc_dummy(first))] $expr;
- 0
- }]
- }
+ struct Foo(
+ [bool; #[cfg_attr(not(FALSE), rustc_dummy(first))] $expr]
+ );
}
}
produce_it!(#[cfg_attr(not(FALSE), rustc_dummy(second))] {
- #![cfg_attr(not(FALSE), allow(unused))]
+ #![cfg_attr(not(FALSE), rustc_dummy(third))]
+ #[cfg_attr(not(FALSE), rustc_dummy(fourth))]
30
});
diff --git a/tests/ui/proc-macro/macro-rules-derive-cfg.stdout b/tests/ui/proc-macro/macro-rules-derive-cfg.stdout
index fadf210..c1e46b5 100644
--- a/tests/ui/proc-macro/macro-rules-derive-cfg.stdout
+++ b/tests/ui/proc-macro/macro-rules-derive-cfg.stdout
@@ -1,21 +1,9 @@
-PRINT-DERIVE INPUT (DISPLAY): struct Foo
-{
- val :
- [bool;
- {
- let a = #[rustc_dummy(first)] #[rustc_dummy(second)]
- { #![allow(unused)] 30 }; 0
- }]
-}
-PRINT-DERIVE DEEP-RE-COLLECTED (DISPLAY): struct Foo
-{
- val :
- [bool;
- {
- let a = #[rustc_dummy(first)] #[rustc_dummy(second)]
- { #! [allow(unused)] 30 }; 0
- }]
-}
+PRINT-DERIVE INPUT (DISPLAY): struct
+Foo([bool; #[rustc_dummy(first)] #[rustc_dummy(second)]
+{ #![rustc_dummy(third)] #[rustc_dummy(fourth)] 30 }]);
+PRINT-DERIVE DEEP-RE-COLLECTED (DISPLAY): struct
+Foo([bool; #[rustc_dummy(first)] #[rustc_dummy(second)]
+{ #! [rustc_dummy(third)] #[rustc_dummy(fourth)] 30 }]);
PRINT-DERIVE INPUT (DEBUG): TokenStream [
Ident {
ident: "struct",
@@ -26,155 +14,146 @@
span: $DIR/macro-rules-derive-cfg.rs:17:16: 17:19 (#3),
},
Group {
- delimiter: Brace,
+ delimiter: Parenthesis,
stream: TokenStream [
- Ident {
- ident: "val",
- span: $DIR/macro-rules-derive-cfg.rs:18:13: 18:16 (#3),
- },
- Punct {
- ch: ':',
- spacing: Alone,
- span: $DIR/macro-rules-derive-cfg.rs:18:16: 18:17 (#3),
- },
Group {
delimiter: Bracket,
stream: TokenStream [
Ident {
ident: "bool",
- span: $DIR/macro-rules-derive-cfg.rs:18:19: 18:23 (#3),
+ span: $DIR/macro-rules-derive-cfg.rs:18:14: 18:18 (#3),
},
Punct {
ch: ';',
spacing: Alone,
- span: $DIR/macro-rules-derive-cfg.rs:18:23: 18:24 (#3),
+ span: $DIR/macro-rules-derive-cfg.rs:18:18: 18:19 (#3),
+ },
+ Punct {
+ ch: '#',
+ spacing: Alone,
+ span: $DIR/macro-rules-derive-cfg.rs:18:20: 18:21 (#3),
+ },
+ Group {
+ delimiter: Bracket,
+ stream: TokenStream [
+ Ident {
+ ident: "rustc_dummy",
+ span: $DIR/macro-rules-derive-cfg.rs:18:43: 18:54 (#3),
+ },
+ Group {
+ delimiter: Parenthesis,
+ stream: TokenStream [
+ Ident {
+ ident: "first",
+ span: $DIR/macro-rules-derive-cfg.rs:18:55: 18:60 (#3),
+ },
+ ],
+ span: $DIR/macro-rules-derive-cfg.rs:18:54: 18:61 (#3),
+ },
+ ],
+ span: $DIR/macro-rules-derive-cfg.rs:18:21: 18:63 (#3),
+ },
+ Punct {
+ ch: '#',
+ spacing: Alone,
+ span: $DIR/macro-rules-derive-cfg.rs:23:13: 23:14 (#0),
+ },
+ Group {
+ delimiter: Bracket,
+ stream: TokenStream [
+ Ident {
+ ident: "rustc_dummy",
+ span: $DIR/macro-rules-derive-cfg.rs:23:36: 23:47 (#0),
+ },
+ Group {
+ delimiter: Parenthesis,
+ stream: TokenStream [
+ Ident {
+ ident: "second",
+ span: $DIR/macro-rules-derive-cfg.rs:23:48: 23:54 (#0),
+ },
+ ],
+ span: $DIR/macro-rules-derive-cfg.rs:23:47: 23:55 (#0),
+ },
+ ],
+ span: $DIR/macro-rules-derive-cfg.rs:23:14: 23:57 (#0),
},
Group {
delimiter: Brace,
stream: TokenStream [
- Ident {
- ident: "let",
- span: $DIR/macro-rules-derive-cfg.rs:19:17: 19:20 (#3),
- },
- Ident {
- ident: "a",
- span: $DIR/macro-rules-derive-cfg.rs:19:21: 19:22 (#3),
- },
- Punct {
- ch: '=',
- spacing: Alone,
- span: $DIR/macro-rules-derive-cfg.rs:19:23: 19:24 (#3),
- },
Punct {
ch: '#',
+ spacing: Joint,
+ span: $DIR/macro-rules-derive-cfg.rs:24:5: 24:6 (#0),
+ },
+ Punct {
+ ch: '!',
spacing: Alone,
- span: $DIR/macro-rules-derive-cfg.rs:19:25: 19:26 (#3),
+ span: $DIR/macro-rules-derive-cfg.rs:24:6: 24:7 (#0),
},
Group {
delimiter: Bracket,
stream: TokenStream [
Ident {
ident: "rustc_dummy",
- span: $DIR/macro-rules-derive-cfg.rs:19:48: 19:59 (#3),
+ span: $DIR/macro-rules-derive-cfg.rs:24:29: 24:40 (#0),
},
Group {
delimiter: Parenthesis,
stream: TokenStream [
Ident {
- ident: "first",
- span: $DIR/macro-rules-derive-cfg.rs:19:60: 19:65 (#3),
+ ident: "third",
+ span: $DIR/macro-rules-derive-cfg.rs:24:41: 24:46 (#0),
},
],
- span: $DIR/macro-rules-derive-cfg.rs:19:59: 19:66 (#3),
+ span: $DIR/macro-rules-derive-cfg.rs:24:40: 24:47 (#0),
},
],
- span: $DIR/macro-rules-derive-cfg.rs:19:26: 19:68 (#3),
+ span: $DIR/macro-rules-derive-cfg.rs:24:7: 24:49 (#0),
},
Punct {
ch: '#',
spacing: Alone,
- span: $DIR/macro-rules-derive-cfg.rs:26:13: 26:14 (#0),
+ span: $DIR/macro-rules-derive-cfg.rs:25:5: 25:6 (#0),
},
Group {
delimiter: Bracket,
stream: TokenStream [
Ident {
ident: "rustc_dummy",
- span: $DIR/macro-rules-derive-cfg.rs:26:36: 26:47 (#0),
+ span: $DIR/macro-rules-derive-cfg.rs:25:28: 25:39 (#0),
},
Group {
delimiter: Parenthesis,
stream: TokenStream [
Ident {
- ident: "second",
- span: $DIR/macro-rules-derive-cfg.rs:26:48: 26:54 (#0),
+ ident: "fourth",
+ span: $DIR/macro-rules-derive-cfg.rs:25:40: 25:46 (#0),
},
],
- span: $DIR/macro-rules-derive-cfg.rs:26:47: 26:55 (#0),
+ span: $DIR/macro-rules-derive-cfg.rs:25:39: 25:47 (#0),
},
],
- span: $DIR/macro-rules-derive-cfg.rs:26:14: 26:57 (#0),
- },
- Group {
- delimiter: Brace,
- stream: TokenStream [
- Punct {
- ch: '#',
- spacing: Joint,
- span: $DIR/macro-rules-derive-cfg.rs:27:5: 27:6 (#0),
- },
- Punct {
- ch: '!',
- spacing: Alone,
- span: $DIR/macro-rules-derive-cfg.rs:27:6: 27:7 (#0),
- },
- Group {
- delimiter: Bracket,
- stream: TokenStream [
- Ident {
- ident: "allow",
- span: $DIR/macro-rules-derive-cfg.rs:27:29: 27:34 (#0),
- },
- Group {
- delimiter: Parenthesis,
- stream: TokenStream [
- Ident {
- ident: "unused",
- span: $DIR/macro-rules-derive-cfg.rs:27:35: 27:41 (#0),
- },
- ],
- span: $DIR/macro-rules-derive-cfg.rs:27:34: 27:42 (#0),
- },
- ],
- span: $DIR/macro-rules-derive-cfg.rs:27:7: 27:44 (#0),
- },
- Literal {
- kind: Integer,
- symbol: "30",
- suffix: None,
- span: $DIR/macro-rules-derive-cfg.rs:28:5: 28:7 (#0),
- },
- ],
- span: $DIR/macro-rules-derive-cfg.rs:26:58: 29:2 (#0),
- },
- Punct {
- ch: ';',
- spacing: Alone,
- span: $DIR/macro-rules-derive-cfg.rs:19:74: 19:75 (#3),
+ span: $DIR/macro-rules-derive-cfg.rs:25:6: 25:49 (#0),
},
Literal {
kind: Integer,
- symbol: "0",
+ symbol: "30",
suffix: None,
- span: $DIR/macro-rules-derive-cfg.rs:20:17: 20:18 (#3),
+ span: $DIR/macro-rules-derive-cfg.rs:26:5: 26:7 (#0),
},
],
- span: $DIR/macro-rules-derive-cfg.rs:18:25: 21:14 (#3),
+ span: $DIR/macro-rules-derive-cfg.rs:23:58: 27:2 (#0),
},
],
- span: $DIR/macro-rules-derive-cfg.rs:18:18: 21:15 (#3),
+ span: $DIR/macro-rules-derive-cfg.rs:18:13: 18:70 (#3),
},
],
- span: $DIR/macro-rules-derive-cfg.rs:17:20: 22:10 (#3),
+ span: $DIR/macro-rules-derive-cfg.rs:17:19: 19:10 (#3),
+ },
+ Punct {
+ ch: ';',
+ spacing: Alone,
+ span: $DIR/macro-rules-derive-cfg.rs:19:10: 19:11 (#3),
},
]
diff --git a/tests/ui/rust-2024/gen-kw.e2015.stderr b/tests/ui/rust-2024/gen-kw.e2015.stderr
index b1074f7..ff552f6 100644
--- a/tests/ui/rust-2024/gen-kw.e2015.stderr
+++ b/tests/ui/rust-2024/gen-kw.e2015.stderr
@@ -31,5 +31,14 @@
= warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2024!
= note: for more information, see issue #49716 <https://github.com/rust-lang/rust/issues/49716>
-error: aborting due to 3 previous errors
+error: `gen` is a keyword in the 2024 edition
+ --> $DIR/gen-kw.rs:25:9
+ |
+LL | fn test<'gen>() {}
+ | ^^^^ help: you can use a raw identifier to stay compatible: `'r#gen`
+ |
+ = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2024!
+ = note: for more information, see issue #49716 <https://github.com/rust-lang/rust/issues/49716>
+
+error: aborting due to 4 previous errors
diff --git a/tests/ui/rust-2024/gen-kw.e2018.stderr b/tests/ui/rust-2024/gen-kw.e2018.stderr
index b902cff..efa8120 100644
--- a/tests/ui/rust-2024/gen-kw.e2018.stderr
+++ b/tests/ui/rust-2024/gen-kw.e2018.stderr
@@ -31,5 +31,14 @@
= warning: this is accepted in the current edition (Rust 2018) but is a hard error in Rust 2024!
= note: for more information, see issue #49716 <https://github.com/rust-lang/rust/issues/49716>
-error: aborting due to 3 previous errors
+error: `gen` is a keyword in the 2024 edition
+ --> $DIR/gen-kw.rs:25:9
+ |
+LL | fn test<'gen>() {}
+ | ^^^^ help: you can use a raw identifier to stay compatible: `'r#gen`
+ |
+ = warning: this is accepted in the current edition (Rust 2018) but is a hard error in Rust 2024!
+ = note: for more information, see issue #49716 <https://github.com/rust-lang/rust/issues/49716>
+
+error: aborting due to 4 previous errors
diff --git a/tests/ui/rust-2024/gen-kw.rs b/tests/ui/rust-2024/gen-kw.rs
index 04251cb..5a65847 100644
--- a/tests/ui/rust-2024/gen-kw.rs
+++ b/tests/ui/rust-2024/gen-kw.rs
@@ -22,4 +22,9 @@ macro_rules! t {
//[e2018]~| WARNING this is accepted in the current edition (Rust 2018) but is a hard error in Rust 2024!
}
+fn test<'gen>() {}
+//~^ ERROR `gen` is a keyword in the 2024 edition
+//[e2015]~| WARNING this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2024!
+//[e2018]~| WARNING this is accepted in the current edition (Rust 2018) but is a hard error in Rust 2024!
+
t!();
diff --git a/tests/crashes/118987-2.rs b/tests/ui/specialization/coherence/default-impl-normalization-ambig-2.rs
similarity index 73%
rename from tests/crashes/118987-2.rs
rename to tests/ui/specialization/coherence/default-impl-normalization-ambig-2.rs
index 4382a7b..1691530 100644
--- a/tests/crashes/118987-2.rs
+++ b/tests/ui/specialization/coherence/default-impl-normalization-ambig-2.rs
@@ -1,4 +1,4 @@
-//@ known-bug: #118987
+// regression test for #118987
#![feature(specialization)] //~ WARN the feature `specialization` is incomplete
trait Assoc {
@@ -15,3 +15,5 @@ trait Foo {}
impl Foo for <u8 as Assoc>::Output {}
impl Foo for <u16 as Assoc>::Output {}
+//~^ ERROR the trait bound `u16: Assoc` is not satisfied
+fn main() {}
diff --git a/tests/ui/specialization/coherence/default-impl-normalization-ambig-2.stderr b/tests/ui/specialization/coherence/default-impl-normalization-ambig-2.stderr
new file mode 100644
index 0000000..a2fca2e
--- /dev/null
+++ b/tests/ui/specialization/coherence/default-impl-normalization-ambig-2.stderr
@@ -0,0 +1,21 @@
+warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
+ --> $DIR/default-impl-normalization-ambig-2.rs:2:12
+ |
+LL | #![feature(specialization)]
+ | ^^^^^^^^^^^^^^
+ |
+ = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
+ = help: consider using `min_specialization` instead, which is more stable and complete
+ = note: `#[warn(incomplete_features)]` on by default
+
+error[E0277]: the trait bound `u16: Assoc` is not satisfied
+ --> $DIR/default-impl-normalization-ambig-2.rs:17:14
+ |
+LL | impl Foo for <u16 as Assoc>::Output {}
+ | ^^^^^^^^^^^^^^^^^^^^^^ the trait `Assoc` is not implemented for `u16`
+ |
+ = help: the trait `Assoc` is implemented for `u8`
+
+error: aborting due to 1 previous error; 1 warning emitted
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/specialization/coherence/default-item-normalization-ambig-1.rs b/tests/ui/specialization/coherence/default-item-normalization-ambig-1.rs
new file mode 100644
index 0000000..af7cf33
--- /dev/null
+++ b/tests/ui/specialization/coherence/default-item-normalization-ambig-1.rs
@@ -0,0 +1,25 @@
+// regression test for #73299.
+#![feature(specialization)] //~ WARN the feature `specialization` is incomplete
+
+trait X {
+ type U;
+ fn f(&self) -> Self::U {
+ loop {}
+ }
+}
+
+impl<T> X for T {
+ default type U = ();
+}
+
+trait Y {
+ fn g(&self) {}
+}
+
+impl Y for <() as X>::U {}
+impl Y for <i32 as X>::U {}
+//~^ ERROR conflicting implementations of trait `Y` for type `<() as X>::U`
+
+fn main() {
+ ().f().g();
+}
diff --git a/tests/ui/specialization/coherence/default-item-normalization-ambig-1.stderr b/tests/ui/specialization/coherence/default-item-normalization-ambig-1.stderr
new file mode 100644
index 0000000..a15151c
--- /dev/null
+++ b/tests/ui/specialization/coherence/default-item-normalization-ambig-1.stderr
@@ -0,0 +1,21 @@
+warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
+ --> $DIR/default-item-normalization-ambig-1.rs:2:12
+ |
+LL | #![feature(specialization)]
+ | ^^^^^^^^^^^^^^
+ |
+ = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
+ = help: consider using `min_specialization` instead, which is more stable and complete
+ = note: `#[warn(incomplete_features)]` on by default
+
+error[E0119]: conflicting implementations of trait `Y` for type `<() as X>::U`
+ --> $DIR/default-item-normalization-ambig-1.rs:20:1
+ |
+LL | impl Y for <() as X>::U {}
+ | ----------------------- first implementation here
+LL | impl Y for <i32 as X>::U {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `<() as X>::U`
+
+error: aborting due to 1 previous error; 1 warning emitted
+
+For more information about this error, try `rustc --explain E0119`.
diff --git a/tests/ui/specialization/defaultimpl/specialization-no-default.rs b/tests/ui/specialization/defaultimpl/specialization-no-default.rs
index 661724e..ddc3233 100644
--- a/tests/ui/specialization/defaultimpl/specialization-no-default.rs
+++ b/tests/ui/specialization/defaultimpl/specialization-no-default.rs
@@ -71,7 +71,8 @@ fn redundant(&self) {}
}
default impl Redundant for i32 {
- fn redundant(&self) {} //~ ERROR E0520
+ fn redundant(&self) {}
+ //~^ ERROR `redundant` specializes an item from a parent `impl`, but that item is not marked `default`
}
fn main() {}
diff --git a/tests/ui/specialization/specialization-default-items-drop-coherence.current.stderr b/tests/ui/specialization/specialization-default-items-drop-coherence.current.stderr
new file mode 100644
index 0000000..36df6bf
--- /dev/null
+++ b/tests/ui/specialization/specialization-default-items-drop-coherence.current.stderr
@@ -0,0 +1,12 @@
+error[E0119]: conflicting implementations of trait `Overlap` for type `u32`
+ --> $DIR/specialization-default-items-drop-coherence.rs:26:1
+ |
+LL | impl Overlap for u32 {
+ | -------------------- first implementation here
+...
+LL | impl Overlap for <u32 as Default>::Id {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `u32`
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0119`.
diff --git a/tests/ui/specialization/specialization-default-items-drop-coherence.next.stderr b/tests/ui/specialization/specialization-default-items-drop-coherence.next.stderr
index e9498a0..36df6bf 100644
--- a/tests/ui/specialization/specialization-default-items-drop-coherence.next.stderr
+++ b/tests/ui/specialization/specialization-default-items-drop-coherence.next.stderr
@@ -1,5 +1,5 @@
error[E0119]: conflicting implementations of trait `Overlap` for type `u32`
- --> $DIR/specialization-default-items-drop-coherence.rs:29:1
+ --> $DIR/specialization-default-items-drop-coherence.rs:26:1
|
LL | impl Overlap for u32 {
| -------------------- first implementation here
diff --git a/tests/ui/specialization/specialization-default-items-drop-coherence.rs b/tests/ui/specialization/specialization-default-items-drop-coherence.rs
index 6dc0127..b3c1f72 100644
--- a/tests/ui/specialization/specialization-default-items-drop-coherence.rs
+++ b/tests/ui/specialization/specialization-default-items-drop-coherence.rs
@@ -1,8 +1,5 @@
-//@ revisions: classic coherence next
+//@ revisions: current next
//@[next] compile-flags: -Znext-solver
-//@[coherence] compile-flags: -Znext-solver=coherence
-//@[classic] check-pass
-//@[classic] known-bug: #105782
// Should fail. Default items completely drop candidates instead of ambiguity,
// which is unsound during coherence, since coherence requires completeness.
@@ -27,8 +24,7 @@ impl Overlap for u32 {
}
impl Overlap for <u32 as Default>::Id {
- //[coherence]~^ ERROR conflicting implementations of trait `Overlap` for type `u32`
- //[next]~^^ ERROR conflicting implementations of trait `Overlap` for type `u32`
+ //~^ ERROR conflicting implementations of trait `Overlap` for type `u32`
type Assoc = Box<usize>;
}
diff --git a/tests/ui/specialization/specialization-overlap-projection.current.stderr b/tests/ui/specialization/specialization-overlap-projection.current.stderr
index a69826f..4e77cb1 100644
--- a/tests/ui/specialization/specialization-overlap-projection.current.stderr
+++ b/tests/ui/specialization/specialization-overlap-projection.current.stderr
@@ -1,5 +1,5 @@
warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
- --> $DIR/specialization-overlap-projection.rs:10:12
+ --> $DIR/specialization-overlap-projection.rs:4:12
|
LL | #![feature(specialization)]
| ^^^^^^^^^^^^^^
@@ -8,5 +8,23 @@
= help: consider using `min_specialization` instead, which is more stable and complete
= note: `#[warn(incomplete_features)]` on by default
-warning: 1 warning emitted
+error[E0119]: conflicting implementations of trait `Foo` for type `u32`
+ --> $DIR/specialization-overlap-projection.rs:19:1
+ |
+LL | impl Foo for u32 {}
+ | ---------------- first implementation here
+LL | impl Foo for <u8 as Assoc>::Output {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `u32`
+error[E0119]: conflicting implementations of trait `Foo` for type `u32`
+ --> $DIR/specialization-overlap-projection.rs:21:1
+ |
+LL | impl Foo for u32 {}
+ | ---------------- first implementation here
+...
+LL | impl Foo for <u16 as Assoc>::Output {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `u32`
+
+error: aborting due to 2 previous errors; 1 warning emitted
+
+For more information about this error, try `rustc --explain E0119`.
diff --git a/tests/ui/specialization/specialization-overlap-projection.next.stderr b/tests/ui/specialization/specialization-overlap-projection.next.stderr
index 5b17696..4e77cb1 100644
--- a/tests/ui/specialization/specialization-overlap-projection.next.stderr
+++ b/tests/ui/specialization/specialization-overlap-projection.next.stderr
@@ -1,5 +1,5 @@
warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
- --> $DIR/specialization-overlap-projection.rs:10:12
+ --> $DIR/specialization-overlap-projection.rs:4:12
|
LL | #![feature(specialization)]
| ^^^^^^^^^^^^^^
@@ -9,7 +9,7 @@
= note: `#[warn(incomplete_features)]` on by default
error[E0119]: conflicting implementations of trait `Foo` for type `u32`
- --> $DIR/specialization-overlap-projection.rs:25:1
+ --> $DIR/specialization-overlap-projection.rs:19:1
|
LL | impl Foo for u32 {}
| ---------------- first implementation here
@@ -17,7 +17,7 @@
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `u32`
error[E0119]: conflicting implementations of trait `Foo` for type `u32`
- --> $DIR/specialization-overlap-projection.rs:27:1
+ --> $DIR/specialization-overlap-projection.rs:21:1
|
LL | impl Foo for u32 {}
| ---------------- first implementation here
diff --git a/tests/ui/specialization/specialization-overlap-projection.rs b/tests/ui/specialization/specialization-overlap-projection.rs
index 16dccf8..f7a2a79 100644
--- a/tests/ui/specialization/specialization-overlap-projection.rs
+++ b/tests/ui/specialization/specialization-overlap-projection.rs
@@ -1,13 +1,8 @@
-//@ revisions: current next
-//@ ignore-compare-mode-next-solver (explicit revisions)
-//@[next] compile-flags: -Znext-solver
-//@[current] check-pass
-
// Test that impls on projected self types can resolve overlap, even when the
// projections involve specialization, so long as the associated type is
// provided by the most specialized impl.
-
-#![feature(specialization)] //~ WARN the feature `specialization` is incomplete
+#![feature(specialization)]
+//~^ WARN the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
trait Assoc {
type Output;
@@ -23,8 +18,8 @@ impl<T> Assoc for T {
trait Foo {}
impl Foo for u32 {}
impl Foo for <u8 as Assoc>::Output {}
-//[next]~^ ERROR conflicting implementations of trait `Foo` for type `u32`
+//~^ ERROR conflicting implementations of trait `Foo` for type `u32`
impl Foo for <u16 as Assoc>::Output {}
-//[next]~^ ERROR conflicting implementations of trait `Foo` for type `u32`
+//~^ ERROR conflicting implementations of trait `Foo` for type `u32`
fn main() {}
diff --git a/tests/ui/specialization/specialization-overlap-projection.stderr b/tests/ui/specialization/specialization-overlap-projection.stderr
new file mode 100644
index 0000000..5f3cd9c
--- /dev/null
+++ b/tests/ui/specialization/specialization-overlap-projection.stderr
@@ -0,0 +1,30 @@
+warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
+ --> $DIR/specialization-overlap-projection.rs:4:12
+ |
+LL | #![feature(specialization)]
+ | ^^^^^^^^^^^^^^
+ |
+ = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
+ = help: consider using `min_specialization` instead, which is more stable and complete
+ = note: `#[warn(incomplete_features)]` on by default
+
+error[E0119]: conflicting implementations of trait `Foo` for type `u32`
+ --> $DIR/specialization-overlap-projection.rs:20:1
+ |
+LL | impl Foo for u32 {}
+ | ---------------- first implementation here
+LL | impl Foo for <u8 as Assoc>::Output {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `u32`
+
+error[E0119]: conflicting implementations of trait `Foo` for type `u32`
+ --> $DIR/specialization-overlap-projection.rs:22:1
+ |
+LL | impl Foo for u32 {}
+ | ---------------- first implementation here
+...
+LL | impl Foo for <u16 as Assoc>::Output {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `u32`
+
+error: aborting due to 2 previous errors; 1 warning emitted
+
+For more information about this error, try `rustc --explain E0119`.
diff --git a/tests/ui/static/missing-type.rs b/tests/ui/static/missing-type.rs
new file mode 100644
index 0000000..2569f47
--- /dev/null
+++ b/tests/ui/static/missing-type.rs
@@ -0,0 +1,5 @@
+// reported as #124164
+static S_COUNT: = std::sync::atomic::AtomicUsize::new(0);
+//~^ ERROR: missing type for `static` item
+
+fn main() {}
diff --git a/tests/ui/static/missing-type.stderr b/tests/ui/static/missing-type.stderr
new file mode 100644
index 0000000..6489ceb
--- /dev/null
+++ b/tests/ui/static/missing-type.stderr
@@ -0,0 +1,8 @@
+error: missing type for `static` item
+ --> $DIR/missing-type.rs:2:16
+ |
+LL | static S_COUNT: = std::sync::atomic::AtomicUsize::new(0);
+ | ^ help: provide a type for the static variable: `AtomicUsize`
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/traits/alias/issue-83613.rs b/tests/ui/traits/alias/issue-83613.rs
index 2462e70..6f0012b 100644
--- a/tests/ui/traits/alias/issue-83613.rs
+++ b/tests/ui/traits/alias/issue-83613.rs
@@ -8,5 +8,5 @@ fn mk_opaque() -> OpaqueType {
trait AnotherTrait {}
impl<T: Send> AnotherTrait for T {}
impl AnotherTrait for OpaqueType {}
-//~^ ERROR conflicting implementations of trait `AnotherTrait` for type `OpaqueType`
+//~^ ERROR conflicting implementations of trait `AnotherTrait`
fn main() {}
diff --git a/tests/ui/traits/alias/issue-83613.stderr b/tests/ui/traits/alias/issue-83613.stderr
index 847fda4..47181c3 100644
--- a/tests/ui/traits/alias/issue-83613.stderr
+++ b/tests/ui/traits/alias/issue-83613.stderr
@@ -1,10 +1,10 @@
-error[E0119]: conflicting implementations of trait `AnotherTrait` for type `OpaqueType`
+error[E0119]: conflicting implementations of trait `AnotherTrait`
--> $DIR/issue-83613.rs:10:1
|
LL | impl<T: Send> AnotherTrait for T {}
| -------------------------------- first implementation here
LL | impl AnotherTrait for OpaqueType {}
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `OpaqueType`
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation
error: aborting due to 1 previous error
diff --git a/tests/ui/traits/issue-105231.rs b/tests/ui/traits/issue-105231.rs
index 7338642..83c3158 100644
--- a/tests/ui/traits/issue-105231.rs
+++ b/tests/ui/traits/issue-105231.rs
@@ -1,4 +1,3 @@
-//~ ERROR overflow evaluating the requirement `A<A<A<A<A<A<A<...>>>>>>>: Send`
struct A<T>(B<T>);
//~^ ERROR recursive types `A` and `B` have infinite size
//~| ERROR `T` is only used recursively
@@ -7,5 +6,5 @@
trait Foo {}
impl<T> Foo for T where T: Send {}
impl Foo for B<u8> {}
-
+//~^ ERROR conflicting implementations of trait `Foo` for type `B<u8>`
fn main() {}
diff --git a/tests/ui/traits/issue-105231.stderr b/tests/ui/traits/issue-105231.stderr
index d3014a7..e113f83 100644
--- a/tests/ui/traits/issue-105231.stderr
+++ b/tests/ui/traits/issue-105231.stderr
@@ -1,5 +1,5 @@
error[E0072]: recursive types `A` and `B` have infinite size
- --> $DIR/issue-105231.rs:2:1
+ --> $DIR/issue-105231.rs:1:1
|
LL | struct A<T>(B<T>);
| ^^^^^^^^^^^ ---- recursive without indirection
@@ -16,7 +16,7 @@
|
error: type parameter `T` is only used recursively
- --> $DIR/issue-105231.rs:2:15
+ --> $DIR/issue-105231.rs:1:15
|
LL | struct A<T>(B<T>);
| - ^
@@ -27,7 +27,7 @@
= note: all type parameters must be used in a non-recursive way in order to constrain their variance
error: type parameter `T` is only used recursively
- --> $DIR/issue-105231.rs:5:17
+ --> $DIR/issue-105231.rs:4:17
|
LL | struct B<T>(A<A<T>>);
| - ^
@@ -37,16 +37,18 @@
= help: consider removing `T`, referring to it in a field, or using a marker such as `PhantomData`
= note: all type parameters must be used in a non-recursive way in order to constrain their variance
-error[E0275]: overflow evaluating the requirement `A<A<A<A<A<A<A<...>>>>>>>: Send`
+error[E0119]: conflicting implementations of trait `Foo` for type `B<u8>`
+ --> $DIR/issue-105231.rs:8:1
|
+LL | impl<T> Foo for T where T: Send {}
+ | ------------------------------- first implementation here
+LL | impl Foo for B<u8> {}
+ | ^^^^^^^^^^^^^^^^^^ conflicting implementation for `B<u8>`
+ |
+ = note: overflow evaluating the requirement `B<u8>: Send`
= help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`issue_105231`)
-note: required because it appears within the type `B<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<u8>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
- --> $DIR/issue-105231.rs:5:8
- |
-LL | struct B<T>(A<A<T>>);
- | ^
error: aborting due to 4 previous errors
-Some errors have detailed explanations: E0072, E0275.
+Some errors have detailed explanations: E0072, E0119.
For more information about an error, try `rustc --explain E0072`.
diff --git a/tests/ui/traits/next-solver/global-cache-and-parallel-frontend.rs b/tests/ui/traits/next-solver/global-cache-and-parallel-frontend.rs
new file mode 100644
index 0000000..2b4f7ba
--- /dev/null
+++ b/tests/ui/traits/next-solver/global-cache-and-parallel-frontend.rs
@@ -0,0 +1,27 @@
+//@ compile-flags: -Zthreads=16
+
+// original issue: https://github.com/rust-lang/rust/issues/129112
+// Previously, the "next" solver asserted that each successful solution is only obtained once.
+// This test exhibits a repro that, with next-solver + -Zthreads, triggered that old assert.
+// In the presence of multithreaded solving, it's possible to concurrently evaluate things twice,
+// which leads to replacing already-solved solutions in the global solution cache!
+// We assume this is fine if we check to make sure they are solved the same way each time.
+
+// This test only nondeterministically fails but that's okay, as it will be rerun by CI many times,
+// so it should almost always fail before anything is merged. As other thread tests already exist,
+// we already face this difficulty, probably. If we need to fix this by reducing the error margin,
+// we should improve compiletest.
+
+#[derive(Clone, Eq)] //~ ERROR [E0277]
+pub struct Struct<T>(T);
+
+impl<T: Clone, U> PartialEq<U> for Struct<T>
+where
+ U: Into<Struct<T>> + Clone
+{
+ fn eq(&self, _other: &U) -> bool {
+ todo!()
+ }
+}
+
+fn main() {}
diff --git a/tests/ui/traits/next-solver/global-cache-and-parallel-frontend.stderr b/tests/ui/traits/next-solver/global-cache-and-parallel-frontend.stderr
new file mode 100644
index 0000000..65e7dd2
--- /dev/null
+++ b/tests/ui/traits/next-solver/global-cache-and-parallel-frontend.stderr
@@ -0,0 +1,24 @@
+error[E0277]: the trait bound `T: Clone` is not satisfied
+ --> $DIR/global-cache-and-parallel-frontend.rs:15:17
+ |
+LL | #[derive(Clone, Eq)]
+ | ^^ the trait `Clone` is not implemented for `T`, which is required by `Struct<T>: PartialEq`
+ |
+note: required for `Struct<T>` to implement `PartialEq`
+ --> $DIR/global-cache-and-parallel-frontend.rs:18:19
+ |
+LL | impl<T: Clone, U> PartialEq<U> for Struct<T>
+ | ----- ^^^^^^^^^^^^ ^^^^^^^^^
+ | |
+ | unsatisfied trait bound introduced here
+note: required by a bound in `Eq`
+ --> $SRC_DIR/core/src/cmp.rs:LL:COL
+ = note: this error originates in the derive macro `Eq` (in Nightly builds, run with -Z macro-backtrace for more info)
+help: consider restricting type parameter `T`
+ |
+LL | pub struct Struct<T: std::clone::Clone>(T);
+ | +++++++++++++++++++
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/traits/solver-cycles/cycle-via-builtin-auto-trait-impl.rs b/tests/ui/traits/solver-cycles/cycle-via-builtin-auto-trait-impl.rs
index d37943b..43443be 100644
--- a/tests/ui/traits/solver-cycles/cycle-via-builtin-auto-trait-impl.rs
+++ b/tests/ui/traits/solver-cycles/cycle-via-builtin-auto-trait-impl.rs
@@ -1,4 +1,3 @@
-//~ ERROR overflow
// A regression test for #111729 checking that we correctly
// track recursion depth for obligations returned by confirmation.
use std::panic::RefUnwindSafe;
@@ -18,6 +17,7 @@ impl<T: RefUnwindSafe> Database for T {
type Storage = SalsaStorage;
}
impl Database for RootDatabase {
+ //~^ ERROR conflicting implementations of trait `Database` for type `RootDatabase`
type Storage = SalsaStorage;
}
diff --git a/tests/ui/traits/solver-cycles/cycle-via-builtin-auto-trait-impl.stderr b/tests/ui/traits/solver-cycles/cycle-via-builtin-auto-trait-impl.stderr
index 2ab150f..1da7671 100644
--- a/tests/ui/traits/solver-cycles/cycle-via-builtin-auto-trait-impl.stderr
+++ b/tests/ui/traits/solver-cycles/cycle-via-builtin-auto-trait-impl.stderr
@@ -1,24 +1,12 @@
-error[E0275]: overflow evaluating the requirement `Runtime<RootDatabase>: RefUnwindSafe`
- |
- = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`cycle_via_builtin_auto_trait_impl`)
-note: required because it appears within the type `RootDatabase`
- --> $DIR/cycle-via-builtin-auto-trait-impl.rs:13:8
- |
-LL | struct RootDatabase {
- | ^^^^^^^^^^^^
-note: required for `RootDatabase` to implement `Database`
- --> $DIR/cycle-via-builtin-auto-trait-impl.rs:17:24
+error[E0119]: conflicting implementations of trait `Database` for type `RootDatabase`
+ --> $DIR/cycle-via-builtin-auto-trait-impl.rs:19:1
|
LL | impl<T: RefUnwindSafe> Database for T {
- | ------------- ^^^^^^^^ ^
- | |
- | unsatisfied trait bound introduced here
-note: required because it appears within the type `Runtime<RootDatabase>`
- --> $DIR/cycle-via-builtin-auto-trait-impl.rs:24:8
- |
-LL | struct Runtime<DB: Database> {
- | ^^^^^^^
+ | ------------------------------------- first implementation here
+...
+LL | impl Database for RootDatabase {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `RootDatabase`
error: aborting due to 1 previous error
-For more information about this error, try `rustc --explain E0275`.
+For more information about this error, try `rustc --explain E0119`.
diff --git a/tests/crashes/124207.rs b/tests/ui/transmutability/malformed-program-gracefulness/coherence-bikeshed-intrinsic-from.rs
similarity index 62%
rename from tests/crashes/124207.rs
rename to tests/ui/transmutability/malformed-program-gracefulness/coherence-bikeshed-intrinsic-from.rs
index a11eedb..0cebc99 100644
--- a/tests/crashes/124207.rs
+++ b/tests/ui/transmutability/malformed-program-gracefulness/coherence-bikeshed-intrinsic-from.rs
@@ -1,9 +1,11 @@
-//@ known-bug: #124207
#![feature(transmutability)]
#![feature(type_alias_impl_trait)]
trait OpaqueTrait {}
type OpaqueType = impl OpaqueTrait;
+//~^ ERROR unconstrained opaque type
trait AnotherTrait {}
impl<T: std::mem::TransmuteFrom<(), ()>> AnotherTrait for T {}
+//~^ ERROR type provided when a constant was expected
impl AnotherTrait for OpaqueType {}
+//~^ ERROR conflicting implementations of trait `AnotherTrait`
pub fn main() {}
diff --git a/tests/ui/transmutability/malformed-program-gracefulness/coherence-bikeshed-intrinsic-from.stderr b/tests/ui/transmutability/malformed-program-gracefulness/coherence-bikeshed-intrinsic-from.stderr
new file mode 100644
index 0000000..2424541
--- /dev/null
+++ b/tests/ui/transmutability/malformed-program-gracefulness/coherence-bikeshed-intrinsic-from.stderr
@@ -0,0 +1,27 @@
+error: unconstrained opaque type
+ --> $DIR/coherence-bikeshed-intrinsic-from.rs:4:19
+ |
+LL | type OpaqueType = impl OpaqueTrait;
+ | ^^^^^^^^^^^^^^^^
+ |
+ = note: `OpaqueType` must be used in combination with a concrete type within the same module
+
+error[E0747]: type provided when a constant was expected
+ --> $DIR/coherence-bikeshed-intrinsic-from.rs:7:37
+ |
+LL | impl<T: std::mem::TransmuteFrom<(), ()>> AnotherTrait for T {}
+ | ^^
+
+error[E0119]: conflicting implementations of trait `AnotherTrait`
+ --> $DIR/coherence-bikeshed-intrinsic-from.rs:9:1
+ |
+LL | impl<T: std::mem::TransmuteFrom<(), ()>> AnotherTrait for T {}
+ | ----------------------------------------------------------- first implementation here
+LL |
+LL | impl AnotherTrait for OpaqueType {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation
+
+error: aborting due to 3 previous errors
+
+Some errors have detailed explanations: E0119, E0747.
+For more information about an error, try `rustc --explain E0119`.
diff --git a/tests/ui/type-alias-impl-trait/impl_trait_for_same_tait.stderr b/tests/ui/type-alias-impl-trait/impl_trait_for_same_tait.stderr
index e35913b..aaf75cc 100644
--- a/tests/ui/type-alias-impl-trait/impl_trait_for_same_tait.stderr
+++ b/tests/ui/type-alias-impl-trait/impl_trait_for_same_tait.stderr
@@ -15,8 +15,6 @@
...
LL | impl Bop for Barr {}
| ^^^^^^^^^^^^^^^^^ conflicting implementation for `Bar<()>`
- |
- = note: upstream crates may add a new impl of trait `std::marker::FnPtr` for type `Barr` in future versions
error[E0119]: conflicting implementations of trait `Bop` for type `Bar<()>`
--> $DIR/impl_trait_for_same_tait.rs:30:1
diff --git a/tests/ui/type-alias-impl-trait/issue-104817.rs b/tests/ui/type-alias-impl-trait/issue-104817.rs
index 4679d02..4914632 100644
--- a/tests/ui/type-alias-impl-trait/issue-104817.rs
+++ b/tests/ui/type-alias-impl-trait/issue-104817.rs
@@ -14,6 +14,6 @@ fn mk_opaque() -> OpaqueType {
trait AnotherTrait {}
impl<T: Send> AnotherTrait for T {}
impl AnotherTrait for OpaqueType {}
-//[stock]~^ conflicting implementations of trait `AnotherTrait` for type `OpaqueType`
+//[stock]~^ conflicting implementations of trait `AnotherTrait`
fn main() {}
diff --git a/tests/ui/type-alias-impl-trait/issue-104817.stock.stderr b/tests/ui/type-alias-impl-trait/issue-104817.stock.stderr
index 41c5206..df5a6c3 100644
--- a/tests/ui/type-alias-impl-trait/issue-104817.stock.stderr
+++ b/tests/ui/type-alias-impl-trait/issue-104817.stock.stderr
@@ -1,10 +1,10 @@
-error[E0119]: conflicting implementations of trait `AnotherTrait` for type `OpaqueType`
+error[E0119]: conflicting implementations of trait `AnotherTrait`
--> $DIR/issue-104817.rs:16:1
|
LL | impl<T: Send> AnotherTrait for T {}
| -------------------------------- first implementation here
LL | impl AnotherTrait for OpaqueType {}
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `OpaqueType`
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation
error: aborting due to 1 previous error
diff --git a/tests/ui/type-alias-impl-trait/taint.rs b/tests/ui/type-alias-impl-trait/taint.rs
new file mode 100644
index 0000000..dfb9476
--- /dev/null
+++ b/tests/ui/type-alias-impl-trait/taint.rs
@@ -0,0 +1,17 @@
+//@ compile-flags: -Zvalidate-mir -Zinline-mir=yes
+
+// reported as rust-lang/rust#126896
+
+#![feature(type_alias_impl_trait)]
+type Two<'a, 'b> = impl std::fmt::Debug;
+
+fn set(x: &mut isize) -> isize {
+ *x
+}
+
+fn d(x: Two) {
+ let c1 = || set(x); //~ ERROR: expected generic lifetime parameter, found `'_`
+ c1;
+}
+
+fn main() {}
diff --git a/tests/ui/type-alias-impl-trait/taint.stderr b/tests/ui/type-alias-impl-trait/taint.stderr
new file mode 100644
index 0000000..17fcd4b
--- /dev/null
+++ b/tests/ui/type-alias-impl-trait/taint.stderr
@@ -0,0 +1,12 @@
+error[E0792]: expected generic lifetime parameter, found `'_`
+ --> $DIR/taint.rs:13:17
+ |
+LL | type Two<'a, 'b> = impl std::fmt::Debug;
+ | -- this generic parameter must be used with a generic lifetime parameter
+...
+LL | let c1 = || set(x);
+ | ^^^^^^
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0792`.
diff --git a/tests/ui/wf/ice-wf-missing-span-in-error-130012.rs b/tests/ui/wf/ice-wf-missing-span-in-error-130012.rs
new file mode 100644
index 0000000..e107069
--- /dev/null
+++ b/tests/ui/wf/ice-wf-missing-span-in-error-130012.rs
@@ -0,0 +1,18 @@
+// Regression test for ICE #130012
+// Checks that we do not ICE while reporting
+// lifetime mistmatch error
+
+trait Fun {
+ type Assoc;
+}
+
+trait MyTrait: for<'a> Fun<Assoc = &'a ()> {}
+//~^ ERROR binding for associated type `Assoc` references lifetime `'a`, which does not appear in the trait input types
+//~| ERROR binding for associated type `Assoc` references lifetime `'a`, which does not appear in the trait input types
+//~| ERROR binding for associated type `Assoc` references lifetime `'a`, which does not appear in the trait input types
+
+impl<F: for<'b> Fun<Assoc = &'b ()>> MyTrait for F {}
+//~^ ERROR binding for associated type `Assoc` references lifetime `'b`, which does not appear in the trait input types
+//~| ERROR mismatched types
+
+fn main() {}
diff --git a/tests/ui/wf/ice-wf-missing-span-in-error-130012.stderr b/tests/ui/wf/ice-wf-missing-span-in-error-130012.stderr
new file mode 100644
index 0000000..357e504
--- /dev/null
+++ b/tests/ui/wf/ice-wf-missing-span-in-error-130012.stderr
@@ -0,0 +1,41 @@
+error[E0582]: binding for associated type `Assoc` references lifetime `'a`, which does not appear in the trait input types
+ --> $DIR/ice-wf-missing-span-in-error-130012.rs:9:28
+ |
+LL | trait MyTrait: for<'a> Fun<Assoc = &'a ()> {}
+ | ^^^^^^^^^^^^^^
+
+error[E0582]: binding for associated type `Assoc` references lifetime `'a`, which does not appear in the trait input types
+ --> $DIR/ice-wf-missing-span-in-error-130012.rs:9:28
+ |
+LL | trait MyTrait: for<'a> Fun<Assoc = &'a ()> {}
+ | ^^^^^^^^^^^^^^
+ |
+ = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+
+error[E0582]: binding for associated type `Assoc` references lifetime `'a`, which does not appear in the trait input types
+ --> $DIR/ice-wf-missing-span-in-error-130012.rs:9:28
+ |
+LL | trait MyTrait: for<'a> Fun<Assoc = &'a ()> {}
+ | ^^^^^^^^^^^^^^
+ |
+ = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+
+error[E0582]: binding for associated type `Assoc` references lifetime `'b`, which does not appear in the trait input types
+ --> $DIR/ice-wf-missing-span-in-error-130012.rs:14:21
+ |
+LL | impl<F: for<'b> Fun<Assoc = &'b ()>> MyTrait for F {}
+ | ^^^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+ --> $DIR/ice-wf-missing-span-in-error-130012.rs:14:50
+ |
+LL | impl<F: for<'b> Fun<Assoc = &'b ()>> MyTrait for F {}
+ | ^ lifetime mismatch
+ |
+ = note: expected reference `&()`
+ found reference `&'b ()`
+
+error: aborting due to 5 previous errors
+
+Some errors have detailed explanations: E0308, E0582.
+For more information about an error, try `rustc --explain E0308`.
diff --git a/triagebot.toml b/triagebot.toml
index 1afcad7..f379f8c 100644
--- a/triagebot.toml
+++ b/triagebot.toml
@@ -914,6 +914,7 @@
warn_non_default_branch = true
contributing_url = "https://rustc-dev-guide.rust-lang.org/getting-started.html"
users_on_vacation = [
+ "fmease",
"jhpratt",
"joboet",
"jyn514",