diff --git a/RELEASES.md b/RELEASES.md
index 29c872eb44896..b49470c307569 100644
--- a/RELEASES.md
+++ b/RELEASES.md
@@ -34,7 +34,6 @@ Compiler
- [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 @@ Compatibility Notes
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)
+
diff --git a/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs b/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs
index 91b02a36d0046..c720b0928feb0 100644
--- a/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs
@@ -662,9 +662,10 @@ impl<'tcx> MirBorrowckCtxt<'_, '_, '_, 'tcx> {
// `&dyn Trait`
ty::Ref(_, ty, _) if ty.is_trait() => true,
// `Box`
- _ 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 5ab66963409a8..878ce6162e0f9 100644
--- a/compiler/rustc_borrowck/src/diagnostics/mod.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/mod.rs
@@ -345,9 +345,9 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, '_, 'infcx, 'tcx> {
variant_index: Option,
including_tuple_field: IncludingTupleField,
) -> Option {
- 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, _) => {
diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs
index ffb350b1d1f0f..d40dcfa58054a 100644
--- a/compiler/rustc_borrowck/src/lib.rs
+++ b/compiler/rustc_borrowck/src/lib.rs
@@ -2522,7 +2522,7 @@ mod diags {
}
pub(crate) fn emit_errors(&mut self) -> Option {
- 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/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs
index 224f8d5c893d7..3c9a43883ad64 100644
--- a/compiler/rustc_borrowck/src/type_check/mod.rs
+++ b/compiler/rustc_borrowck/src/type_check/mod.rs
@@ -1979,19 +1979,76 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
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 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
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 9eabe817359c0..164be73f49296 100644
--- a/compiler/rustc_borrowck/src/universal_regions.rs
+++ b/compiler/rustc_borrowck/src/universal_regions.rs
@@ -29,7 +29,8 @@ use rustc_macros::extension;
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};
@@ -688,7 +689,8 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> {
defining_ty: DefiningTy<'tcx>,
) -> ty::Binder<'tcx, &'tcx ty::List>> {
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 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> {
// "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 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> {
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_codegen_llvm/src/debuginfo/metadata.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs
index 17a9630c6557b..d231b103964b6 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_const_eval/src/interpret/call.rs b/compiler/rustc_const_eval/src/interpret/call.rs
index 82438eb5e7828..568a9a3a637be 100644
--- a/compiler/rustc_const_eval/src/interpret/call.rs
+++ b/compiler/rustc_const_eval/src/interpret/call.rs
@@ -189,7 +189,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
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_data_structures/src/steal.rs b/compiler/rustc_data_structures/src/steal.rs
index 0f2c0eee27d2f..aaa95f6b7f19e 100644
--- a/compiler/rustc_data_structures/src/steal.rs
+++ b/compiler/rustc_data_structures/src/steal.rs
@@ -57,6 +57,7 @@ impl Steal {
///
/// 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_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs
index e2491922b8df6..e86421f2150db 100644
--- a/compiler/rustc_feature/src/builtin_attrs.rs
+++ b/compiler/rustc_feature/src/builtin_attrs.rs
@@ -793,6 +793,12 @@ pub const BUILTIN_ATTRIBUTES: &[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!(
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 0790c6f9a5992..ac5e1040803e0 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 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// 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 2fdba8446bdad..c5ffcdd566a49 100644
--- a/compiler/rustc_hir_typeck/src/method/probe.rs
+++ b/compiler/rustc_hir_typeck/src/method/probe.rs
@@ -1485,8 +1485,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
// 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_lint/messages.ftl b/compiler/rustc_lint/messages.ftl
index 353345958337c..759320b9eb65f 100644
--- a/compiler/rustc_lint/messages.ftl
+++ b/compiler/rustc_lint/messages.ftl
@@ -699,6 +699,9 @@ lint_ptr_null_checks_ref = references are not nullable, so checking them for nul
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
diff --git a/compiler/rustc_lint/src/internal.rs b/compiler/rustc_lint/src/internal.rs
index 2e8116b8ba892..9d637c1eb7f84 100644
--- a/compiler/rustc_lint/src/internal.rs
+++ b/compiler/rustc_lint/src/internal.rs
@@ -17,8 +17,8 @@ use tracing::debug;
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 @@ declare_tool_lint! {
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` 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 @@ impl LateLintPass<'_> for QueryStability {
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 bb7de4739fbdd..a9627e9b78907 100644
--- a/compiler/rustc_lint/src/lib.rs
+++ b/compiler/rustc_lint/src/lib.rs
@@ -610,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 7ca282b7c8541..9050f36acba7b 100644
--- a/compiler/rustc_lint/src/lints.rs
+++ b/compiler/rustc_lint/src/lints.rs
@@ -894,6 +894,13 @@ pub(crate) struct QueryInstability {
pub query: Symbol,
}
+#[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;
diff --git a/compiler/rustc_lint/src/shadowed_into_iter.rs b/compiler/rustc_lint/src/shadowed_into_iter.rs
index bb9c7d85c2efc..bb122509d0a89 100644
--- a/compiler/rustc_lint/src/shadowed_into_iter.rs
+++ b/compiler/rustc_lint/src/shadowed_into_iter.rs
@@ -94,12 +94,9 @@ impl<'tcx> LateLintPass<'tcx> for ShadowedIntoIter {
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 @@ impl<'tcx> LateLintPass<'tcx> for ShadowedIntoIter {
.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 f2f7c0eaa4df8..b5e501b92f0d6 100644
--- a/compiler/rustc_lint/src/types.rs
+++ b/compiler/rustc_lint/src/types.rs
@@ -1304,8 +1304,10 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
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 761d30bac715a..b7f7b782c7722 100644
--- a/compiler/rustc_lint/src/unused.rs
+++ b/compiler/rustc_lint/src/unused.rs
@@ -283,9 +283,8 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults {
}
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_middle/src/mir/syntax.rs b/compiler/rustc_middle/src/mir/syntax.rs
index 748ca047754a9..22a4b688c517c 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/layout.rs b/compiler/rustc_middle/src/ty/layout.rs
index d0a9039441dc4..8cec8eac1898a 100644
--- a/compiler/rustc_middle/src/ty/layout.rs
+++ b/compiler/rustc_middle/src/ty/layout.rs
@@ -1075,11 +1075,13 @@ where
// 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/sty.rs b/compiler/rustc_middle/src/ty/sty.rs
index 89ef30fa768e0..1f4f2c62d7084 100644
--- a/compiler/rustc_middle/src/ty/sty.rs
+++ b/compiler/rustc_middle/src/ty/sty.rs
@@ -1170,14 +1170,19 @@ impl<'tcx> Ty<'tcx> {
}
}
- /// Panics if called on any type other than `Box`.
- pub fn boxed_ty(self) -> Ty<'tcx> {
+ pub fn boxed_ty(self) -> Option> {
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`.
+ 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 +1328,7 @@ impl<'tcx> Ty<'tcx> {
/// Some types -- notably unsafe ptrs -- can only be dereferenced explicitly.
pub fn builtin_deref(self, explicit: bool) -> Option> {
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/util.rs b/compiler/rustc_middle/src/ty/util.rs
index efbccca77c1f0..d70ff8258d04c 100644
--- a/compiler/rustc_middle/src/ty/util.rs
+++ b/compiler/rustc_middle/src/ty/util.rs
@@ -1628,7 +1628,7 @@ impl<'tcx> 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_transform/src/elaborate_box_derefs.rs b/compiler/rustc_mir_transform/src/elaborate_box_derefs.rs
index 5dd82f40163da..66e49d556e23c 100644
--- a/compiler/rustc_mir_transform/src/elaborate_box_derefs.rs
+++ b/compiler/rustc_mir_transform/src/elaborate_box_derefs.rs
@@ -62,11 +62,13 @@ impl<'tcx, 'a> MutVisitor<'tcx> for ElaborateBoxDerefVisitor<'tcx, 'a> {
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);
@@ -120,13 +122,15 @@ impl<'tcx> crate::MirPass<'tcx> for ElaborateBoxDerefs {
for (base, elem) in place.iter_projections() {
let base_ty = base.ty(&body.local_decls, tcx).ty;
- if elem == PlaceElem::Deref && base_ty.is_box() {
+ 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());
let (unique_ty, nonnull_ty, ptr_ty) =
- build_ptr_tys(tcx, base_ty.boxed_ty(), unique_did, nonnull_did);
+ build_ptr_tys(tcx, boxed_ty, unique_did, nonnull_did);
new_projections.extend_from_slice(&build_projection(
unique_ty, nonnull_ty, ptr_ty,
diff --git a/compiler/rustc_monomorphize/src/collector.rs b/compiler/rustc_monomorphize/src/collector.rs
index 8515ab45de217..093697a290c00 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 b22e8e30465ea..91101ddd59022 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_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs
index 21478a44b0e14..e41f89a3c9da9 100644
--- a/compiler/rustc_passes/src/check_attr.rs
+++ b/compiler/rustc_passes/src/check_attr.rs
@@ -125,7 +125,9 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
[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 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
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 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
}
}
- /// 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 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
}
}
- /// 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_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs
index 36b31d10c4d29..418d1078900ac 100644
--- a/compiler/rustc_span/src/symbol.rs
+++ b/compiler/rustc_span/src/symbol.rs
@@ -1654,6 +1654,7 @@ symbols! {
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,
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 bff2a184b19f0..65d21518491da 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 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
}
}
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/library/core/src/ptr/mod.rs b/library/core/src/ptr/mod.rs
index d7ed4edcc0041..08d06cad55d06 100644
--- a/library/core/src/ptr/mod.rs
+++ b/library/core/src/ptr/mod.rs
@@ -2277,6 +2277,14 @@ impl fmt::Debug for F {
/// `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/time.rs b/library/core/src/time.rs
index 0390bb59a8984..c19eeedb35426 100644
--- a/library/core/src/time.rs
+++ b/library/core/src/time.rs
@@ -250,7 +250,7 @@ impl 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 @@ impl 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 @@ impl Duration {
/// ```
/// 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 @@ impl Duration {
/// ```
/// 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 @@ impl Duration {
/// ```
/// 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 @@ impl Duration {
/// ```
/// 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 @@ impl Duration {
/// ```
/// 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 @@ impl Duration {
/// ```
/// 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 @@ impl Duration {
/// 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 @@ impl Duration {
/// 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 @@ impl 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/src/bootstrap/src/core/build_steps/check.rs b/src/bootstrap/src/core/build_steps/check.rs
index 7f7faf077d047..ba12e64c4a26f 100644
--- a/src/bootstrap/src/core/build_steps/check.rs
+++ b/src/bootstrap/src/core/build_steps/check.rs
@@ -228,7 +228,7 @@ impl Step for Rustc {
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 a2bb03cd5ac81..a0992350722fe 100644
--- a/src/bootstrap/src/core/build_steps/clippy.rs
+++ b/src/bootstrap/src/core/build_steps/clippy.rs
@@ -197,7 +197,7 @@ impl Step for Rustc {
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 eef548033f1c6..de4fbebe4d393 100644
--- a/src/bootstrap/src/core/build_steps/compile.rs
+++ b/src/bootstrap/src/core/build_steps/compile.rs
@@ -931,7 +931,12 @@ impl Step for Rustc {
// 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 @@ impl Step for Rustc {
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"));
diff --git a/src/bootstrap/src/core/build_steps/doc.rs b/src/bootstrap/src/core/build_steps/doc.rs
index ffb617c642baf..73d9e3f6793e5 100644
--- a/src/bootstrap/src/core/build_steps/doc.rs
+++ b/src/bootstrap/src/core/build_steps/doc.rs
@@ -826,7 +826,7 @@ impl Step for Rustc {
// 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 @@ impl Step for RustcBook {
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/test.rs b/src/bootstrap/src/core/build_steps/test.rs
index a8e1254047363..3ef8c0ea4b2c9 100644
--- a/src/bootstrap/src/core/build_steps/test.rs
+++ b/src/bootstrap/src/core/build_steps/test.rs
@@ -2690,7 +2690,7 @@ impl Step for Crate {
}
}
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"),
};
diff --git a/src/bootstrap/src/core/metadata.rs b/src/bootstrap/src/core/metadata.rs
index 1016607fc8318..d665544f59339 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,
targets: Vec,
+ features: BTreeMap>,
}
/// 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 5751c398f30fc..fc12b359e0a34 100644
--- a/src/bootstrap/src/lib.rs
+++ b/src/bootstrap/src/lib.rs
@@ -183,6 +183,7 @@ struct Crate {
deps: HashSet,
path: PathBuf,
has_lib: bool,
+ features: Vec,
}
impl Crate {
@@ -332,14 +333,20 @@ impl 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");
@@ -666,16 +673,24 @@ impl Build {
}
/// 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 +702,7 @@ impl Build {
// 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");
}
diff --git a/src/tools/clippy/clippy_lints/src/escape.rs b/src/tools/clippy/clippy_lints/src/escape.rs
index a5da52b0be50a..803606979410b 100644
--- a/src/tools/clippy/clippy_lints/src/escape.rs
+++ b/src/tools/clippy/clippy_lints/src/escape.rs
@@ -50,7 +50,7 @@ declare_clippy_lint! {
}
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 @@ impl<'a, 'tcx> Delegate<'tcx> for EscapeDelegate<'a, 'tcx> {
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 d7126990edb1d..f61bb3a6bf481 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 @@ impl SelfKind {
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 0d2b0a3131763..fe860e5ae2601 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 @@ pub(super) fn derefs_to_slice<'tcx>(
} 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/unnecessary_box_returns.rs b/src/tools/clippy/clippy_lints/src/unnecessary_box_returns.rs
index 3f130bf5a6731..14f4aa6676b65 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 @@ impl UnnecessaryBoxReturns {
.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 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 f80981c11af65..585134209ca3a 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(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> Option> {
- 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/lint-docs/src/lib.rs b/src/tools/lint-docs/src/lib.rs
index 72bb9db7e7414..532a27b22aa6f 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 @@ impl<'a> LintExtractor<'a> {
}
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 2055fed2b480c..e377283b1a453 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> {
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> {
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> {
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/rust-analyzer/crates/hir-expand/src/inert_attr_macro.rs b/src/tools/rust-analyzer/crates/hir-expand/src/inert_attr_macro.rs
index ee15b1b5ce9d5..5c25a55362e64 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 @@ pub const INERT_ATTRIBUTES: &[BuiltinAttribute] = &[
// 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/tests/ui-fulldeps/internal-lints/query_completeness.rs b/tests/ui-fulldeps/internal-lints/query_completeness.rs
new file mode 100644
index 0000000000000..50b0fb4c3fc02
--- /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 0000000000000..35bb867f40e8f
--- /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 0000000000000..9fc010b576309
--- /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 0000000000000..8fd69da0d1e92
--- /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/consts/missing_assoc_const_type.rs b/tests/ui/consts/missing_assoc_const_type.rs
index 8d95e3dca633c..633998e9bc157 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 28af1f0f321e6..ef7ff962d2d12 100644
--- a/tests/ui/consts/missing_assoc_const_type.stderr
+++ b/tests/ui/consts/missing_assoc_const_type.stderr
@@ -4,5 +4,11 @@ error: missing type for `const` item
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/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 0000000000000..ca8b8b7e4d92b
--- /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 0000000000000..226a6fa30163c
--- /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 0000000000000..84d2a6d2b6a62
--- /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 0000000000000..f30689901893c
--- /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 {
+ type Arg;
+}
+impl ToArg 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 0000000000000..4cdb959786a56
--- /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 f3401f34eec73..6de81cba7281a 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 0000000000000..c96fa92937b0c
--- /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/crashes/124164.rs b/tests/ui/static/missing-type.rs
similarity index 52%
rename from tests/crashes/124164.rs
rename to tests/ui/static/missing-type.rs
index 8c9b4bddbe80d..2569f47b7c38c 100644
--- a/tests/crashes/124164.rs
+++ b/tests/ui/static/missing-type.rs
@@ -1,4 +1,5 @@
-//@ known-bug: #124164
+// 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 0000000000000..6489ceb700a2e
--- /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/crashes/126896.rs b/tests/ui/type-alias-impl-trait/taint.rs
similarity index 59%
rename from tests/crashes/126896.rs
rename to tests/ui/type-alias-impl-trait/taint.rs
index 49c539d7acc8a..dfb947637c042 100644
--- a/tests/crashes/126896.rs
+++ b/tests/ui/type-alias-impl-trait/taint.rs
@@ -1,6 +1,7 @@
-//@ known-bug: rust-lang/rust#126896
//@ 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;
@@ -9,9 +10,8 @@ fn set(x: &mut isize) -> isize {
}
fn d(x: Two) {
- let c1 = || set(x);
+ let c1 = || set(x); //~ ERROR: expected generic lifetime parameter, found `'_`
c1;
}
-fn main() {
-}
+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 0000000000000..17fcd4b7e9325
--- /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/triagebot.toml b/triagebot.toml
index 1afcad7d1315c..f379f8cc7af50 100644
--- a/triagebot.toml
+++ b/triagebot.toml
@@ -914,6 +914,7 @@ cc = ["@kobzol"]
warn_non_default_branch = true
contributing_url = "https://rustc-dev-guide.rust-lang.org/getting-started.html"
users_on_vacation = [
+ "fmease",
"jhpratt",
"joboet",
"jyn514",