Auto merge of #3630 - rust-lang:rustup-2024-05-25, r=saethlin

Automatic Rustup
This commit is contained in:
bors 2024-05-25 12:46:16 +00:00
commit 331bb3f10d
72 changed files with 811 additions and 586 deletions

View file

@ -4252,6 +4252,7 @@ dependencies = [
"rustc_fluent_macro",
"rustc_hir",
"rustc_index",
"rustc_infer",
"rustc_macros",
"rustc_middle",
"rustc_mir_build",

View file

@ -29,8 +29,8 @@ use rustc_middle::middle::debugger_visualizer::{DebuggerVisualizerFile, Debugger
use rustc_middle::middle::exported_symbols;
use rustc_middle::middle::exported_symbols::SymbolExportKind;
use rustc_middle::middle::lang_items;
use rustc_middle::mir::BinOp;
use rustc_middle::mir::mono::{CodegenUnit, CodegenUnitNameBuilder, MonoItem};
use rustc_middle::mir::BinOp;
use rustc_middle::query::Providers;
use rustc_middle::ty::layout::{HasTyCtxt, LayoutOf, TyAndLayout};
use rustc_middle::ty::{self, Instance, Ty, TyCtxt};

View file

@ -139,10 +139,9 @@ where
ErrorHandled::TooGeneric(span)
}
err_inval!(AlreadyReported(guar)) => ErrorHandled::Reported(guar, span),
err_inval!(Layout(LayoutError::ReferencesError(guar))) => ErrorHandled::Reported(
ReportedErrorInfo::tainted_by_errors(guar),
span,
),
err_inval!(Layout(LayoutError::ReferencesError(guar))) => {
ErrorHandled::Reported(ReportedErrorInfo::tainted_by_errors(guar), span)
}
// Report remaining errors.
_ => {
let (our_span, frames) = get_span_and_frames();

View file

@ -14,10 +14,10 @@
#![feature(yeet_expr)]
#![feature(if_let_guard)]
pub mod check_consts;
pub mod const_eval;
mod errors;
pub mod interpret;
pub mod transform;
pub mod util;
use std::sync::atomic::AtomicBool;

View file

@ -1,2 +0,0 @@
pub mod check_consts;
pub mod validate;

View file

@ -164,9 +164,8 @@ pub fn check_intrinsic_type(
) {
let generics = tcx.generics_of(intrinsic_id);
let param = |n| {
if let Some(&ty::GenericParamDef {
name, kind: ty::GenericParamDefKind::Type { .. }, ..
}) = generics.opt_param_at(n as usize, tcx)
if let &ty::GenericParamDef { name, kind: ty::GenericParamDefKind::Type { .. }, .. } =
generics.param_at(n as usize, tcx)
{
Ty::new_param(tcx, n, name)
} else {

View file

@ -461,12 +461,10 @@ pub(super) fn explicit_predicates_of<'tcx>(
}
}
} else {
if matches!(def_kind, DefKind::AnonConst) && tcx.features().generic_const_exprs {
let hir_id = tcx.local_def_id_to_hir_id(def_id);
let parent_def_id = tcx.hir().get_parent_item(hir_id);
if let Some(defaulted_param_def_id) =
tcx.hir().opt_const_param_default_param_def_id(hir_id)
if matches!(def_kind, DefKind::AnonConst)
&& tcx.features().generic_const_exprs
&& let Some(defaulted_param_def_id) =
tcx.hir().opt_const_param_default_param_def_id(tcx.local_def_id_to_hir_id(def_id))
{
// In `generics_of` we set the generics' parent to be our parent's parent which means that
// we lose out on the predicates of our actual parent if we dont return those predicates here.
@ -480,6 +478,7 @@ pub(super) fn explicit_predicates_of<'tcx>(
//
// In the above code we want the anon const to have predicates in its param env for `T: Trait`
// and we would be calling `explicit_predicates_of(Foo)` here
let parent_def_id = tcx.local_parent(def_id);
let parent_preds = tcx.explicit_predicates_of(parent_def_id);
// If we dont filter out `ConstArgHasType` predicates then every single defaulted const parameter
@ -512,33 +511,6 @@ pub(super) fn explicit_predicates_of<'tcx>(
predicates: { tcx.arena.alloc_from_iter(filtered_predicates) },
};
}
let parent_def_kind = tcx.def_kind(parent_def_id);
if matches!(parent_def_kind, DefKind::OpaqueTy) {
// In `instantiate_identity` we inherit the predicates of our parent.
// However, opaque types do not have a parent (see `gather_explicit_predicates_of`), which means
// that we lose out on the predicates of our actual parent if we dont return those predicates here.
//
//
// fn foo<T: Trait>() -> impl Iterator<Output = Another<{ <T as Trait>::ASSOC }> > { todo!() }
// ^^^^^^^^^^^^^^^^^^^ the def id we are calling
// explicit_predicates_of on
//
// In the above code we want the anon const to have predicates in its param env for `T: Trait`.
// However, the anon const cannot inherit predicates from its parent since it's opaque.
//
// To fix this, we call `explicit_predicates_of` directly on `foo`, the parent's parent.
// In the above example this is `foo::{opaque#0}` or `impl Iterator`
let parent_hir_id = tcx.local_def_id_to_hir_id(parent_def_id.def_id);
// In the above example this is the function `foo`
let item_def_id = tcx.hir().get_parent_item(parent_hir_id);
// In the above code example we would be calling `explicit_predicates_of(foo)` here
return tcx.explicit_predicates_of(item_def_id);
}
}
gather_explicit_predicates_of(tcx, def_id)
}
}

View file

@ -137,6 +137,10 @@ hir_typeck_rpit_change_return_type = you could change the return type to be a bo
hir_typeck_rustcall_incorrect_args =
functions with the "rust-call" ABI must take a single non-self tuple argument
hir_typeck_self_ctor_from_outer_item = can't reference `Self` constructor from outer item
.label = the inner item doesn't inherit generics from this impl, so `Self` is invalid to reference
.suggestion = replace `Self` with the actual type
hir_typeck_struct_expr_non_exhaustive =
cannot create non-exhaustive {$what} using struct expression

View file

@ -651,3 +651,31 @@ pub enum SuggestBoxingForReturnImplTrait {
ends: Vec<Span>,
},
}
#[derive(Diagnostic)]
#[diag(hir_typeck_self_ctor_from_outer_item, code = E0401)]
pub struct SelfCtorFromOuterItem {
#[primary_span]
pub span: Span,
#[label]
pub impl_span: Span,
#[subdiagnostic]
pub sugg: Option<ReplaceWithName>,
}
#[derive(LintDiagnostic)]
#[diag(hir_typeck_self_ctor_from_outer_item)]
pub struct SelfCtorFromOuterItemLint {
#[label]
pub impl_span: Span,
#[subdiagnostic]
pub sugg: Option<ReplaceWithName>,
}
#[derive(Subdiagnostic)]
#[suggestion(hir_typeck_suggestion, code = "{name}", applicability = "machine-applicable")]
pub struct ReplaceWithName {
#[primary_span]
pub span: Span,
pub name: String,
}

View file

@ -1,5 +1,5 @@
use crate::callee::{self, DeferredCallResolution};
use crate::errors::CtorIsPrivate;
use crate::errors::{self, CtorIsPrivate};
use crate::method::{self, MethodCallee, SelfSource};
use crate::rvalue_scopes;
use crate::{BreakableCtxt, Diverges, Expectation, FnCtxt, LoweredTy};
@ -21,6 +21,7 @@ use rustc_hir_analysis::hir_ty_lowering::{
use rustc_infer::infer::canonical::{Canonical, OriginalQueryValues, QueryResponse};
use rustc_infer::infer::error_reporting::TypeAnnotationNeeded::E0282;
use rustc_infer::infer::{DefineOpaqueTypes, InferResult};
use rustc_lint::builtin::SELF_CONSTRUCTOR_FROM_OUTER_ITEM;
use rustc_middle::ty::adjustment::{Adjust, Adjustment, AutoBorrow, AutoBorrowMutability};
use rustc_middle::ty::error::TypeError;
use rustc_middle::ty::fold::TypeFoldable;
@ -1156,6 +1157,43 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
span,
tcx.at(span).type_of(impl_def_id).instantiate_identity(),
);
// Firstly, check that this SelfCtor even comes from the item we're currently
// typechecking. This can happen because we never validated the resolution of
// SelfCtors, and when we started doing so, we noticed regressions. After
// sufficiently long time, we can remove this check and turn it into a hard
// error in `validate_res_from_ribs` -- it's just difficult to tell whether the
// self type has any generic types during rustc_resolve, which is what we use
// to determine if this is a hard error or warning.
if std::iter::successors(Some(self.body_id.to_def_id()), |def_id| {
self.tcx.generics_of(def_id).parent
})
.all(|def_id| def_id != impl_def_id)
{
let sugg = ty.normalized.ty_adt_def().map(|def| errors::ReplaceWithName {
span: path_span,
name: self.tcx.item_name(def.did()).to_ident_string(),
});
if ty.raw.has_param() {
let guar = self.tcx.dcx().emit_err(errors::SelfCtorFromOuterItem {
span: path_span,
impl_span: tcx.def_span(impl_def_id),
sugg,
});
return (Ty::new_error(self.tcx, guar), res);
} else {
self.tcx.emit_node_span_lint(
SELF_CONSTRUCTOR_FROM_OUTER_ITEM,
hir_id,
path_span,
errors::SelfCtorFromOuterItemLint {
impl_span: tcx.def_span(impl_def_id),
sugg,
},
);
}
}
match ty.normalized.ty_adt_def() {
Some(adt_def) if adt_def.has_ctor() => {
let (ctor_kind, ctor_def_id) = adt_def.non_enum_variant().ctor.unwrap();

View file

@ -235,11 +235,17 @@ fn infer_type_if_missing<'tcx>(fcx: &FnCtxt<'_, 'tcx>, node: Node<'tcx>) -> Opti
if let Some(item) = tcx.opt_associated_item(def_id.into())
&& let ty::AssocKind::Const = item.kind
&& let ty::ImplContainer = item.container
&& let Some(trait_item) = item.trait_item_def_id
&& let Some(trait_item_def_id) = item.trait_item_def_id
{
let args =
tcx.impl_trait_ref(item.container_id(tcx)).unwrap().instantiate_identity().args;
Some(tcx.type_of(trait_item).instantiate(tcx, args))
let impl_def_id = item.container_id(tcx);
let impl_trait_ref = tcx.impl_trait_ref(impl_def_id).unwrap().instantiate_identity();
let args = ty::GenericArgs::identity_for_item(tcx, def_id).rebase_onto(
tcx,
impl_def_id,
impl_trait_ref.args,
);
tcx.check_args_compatible(trait_item_def_id, args)
.then(|| tcx.type_of(trait_item_def_id).instantiate(tcx, args))
} else {
Some(fcx.next_ty_var(span))
}

View file

@ -381,10 +381,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let maybe_missing_semi = self.check_for_missing_semi(expr, &mut err);
// We defer to the later error produced by `check_lhs_assignable`.
// We only downgrade this if it's the LHS, though.
// We only downgrade this if it's the LHS, though, and if this is a
// valid assignment statement.
if maybe_missing_semi
&& let hir::Node::Expr(parent) = self.tcx.parent_hir_node(expr.hir_id)
&& let hir::ExprKind::Assign(lhs, _, _) = parent.kind
&& let hir::Node::Stmt(stmt) = self.tcx.parent_hir_node(parent.hir_id)
&& let hir::StmtKind::Expr(_) | hir::StmtKind::Semi(_) = stmt.kind
&& lhs.hir_id == expr.hir_id
{
err.downgrade_to_delayed_bug();

View file

@ -116,8 +116,7 @@ fn load_dep_graph(sess: &Session) -> LoadResult<(Arc<SerializedDepGraph>, WorkPr
if let LoadResult::Ok { data: (work_products_data, start_pos) } = load_result {
// Decode the list of work_products
let Ok(mut work_product_decoder) =
MemDecoder::new(&work_products_data[..], start_pos)
let Ok(mut work_product_decoder) = MemDecoder::new(&work_products_data[..], start_pos)
else {
sess.dcx().emit_warn(errors::CorruptFile { path: &work_products_path });
return LoadResult::DataOutOfDate;

View file

@ -54,18 +54,14 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
}
(ty::Param(expected), ty::Param(found)) => {
let generics = tcx.generics_of(body_owner_def_id);
if let Some(param) = generics.opt_type_param(expected, tcx) {
let e_span = tcx.def_span(param.def_id);
let e_span = tcx.def_span(generics.type_param(expected, tcx).def_id);
if !sp.contains(e_span) {
diag.span_label(e_span, "expected type parameter");
}
}
if let Some(param) = generics.opt_type_param(found, tcx) {
let f_span = tcx.def_span(param.def_id);
let f_span = tcx.def_span(generics.type_param(found, tcx).def_id);
if !sp.contains(f_span) {
diag.span_label(f_span, "found type parameter");
}
}
diag.note(
"a type parameter was expected, but a different one was found; \
you might be missing a type parameter or trait bound",
@ -87,10 +83,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
| (ty::Alias(ty::Projection, proj), ty::Param(p))
if !tcx.is_impl_trait_in_trait(proj.def_id) =>
{
let parent = tcx
.generics_of(body_owner_def_id)
.opt_type_param(p, tcx)
.and_then(|param| {
let param = tcx.generics_of(body_owner_def_id).type_param(p, tcx);
let p_def_id = param.def_id;
let p_span = tcx.def_span(p_def_id);
let expected = match (values.expected.kind(), values.found.kind()) {
@ -99,16 +92,12 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
_ => "",
};
if !sp.contains(p_span) {
diag.span_label(
p_span,
format!("{expected}this type parameter"),
);
diag.span_label(p_span, format!("{expected}this type parameter"));
}
p_def_id.as_local().and_then(|id| {
let parent = p_def_id.as_local().and_then(|id| {
let local_id = tcx.local_def_id_to_hir_id(id);
let generics = tcx.parent_hir_node(local_id).generics()?;
Some((id, generics))
})
});
let mut note = true;
if let Some((local_id, generics)) = parent {
@ -183,8 +172,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
(ty::Param(p), ty::Dynamic(..) | ty::Alias(ty::Opaque, ..))
| (ty::Dynamic(..) | ty::Alias(ty::Opaque, ..), ty::Param(p)) => {
let generics = tcx.generics_of(body_owner_def_id);
if let Some(param) = generics.opt_type_param(p, tcx) {
let p_span = tcx.def_span(param.def_id);
let p_span = tcx.def_span(generics.type_param(p, tcx).def_id);
let expected = match (values.expected.kind(), values.found.kind()) {
(ty::Param(_), _) => "expected ",
(_, ty::Param(_)) => "found ",
@ -193,7 +181,6 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
if !sp.contains(p_span) {
diag.span_label(p_span, format!("{expected}this type parameter"));
}
}
diag.help("type parameters must be constrained to match other types");
if tcx.sess.teach(diag.code.unwrap()) {
diag.help(
@ -233,12 +220,10 @@ impl<T> Trait<T> for X {
ty::Closure(..) | ty::CoroutineClosure(..) | ty::Coroutine(..),
) => {
let generics = tcx.generics_of(body_owner_def_id);
if let Some(param) = generics.opt_type_param(p, tcx) {
let p_span = tcx.def_span(param.def_id);
let p_span = tcx.def_span(generics.type_param(p, tcx).def_id);
if !sp.contains(p_span) {
diag.span_label(p_span, "expected this type parameter");
}
}
diag.help(format!(
"every closure has a distinct type and so could not always match the \
caller-chosen type of parameter `{p}`"
@ -246,8 +231,7 @@ impl<T> Trait<T> for X {
}
(ty::Param(p), _) | (_, ty::Param(p)) => {
let generics = tcx.generics_of(body_owner_def_id);
if let Some(param) = generics.opt_type_param(p, tcx) {
let p_span = tcx.def_span(param.def_id);
let p_span = tcx.def_span(generics.type_param(p, tcx).def_id);
let expected = match (values.expected.kind(), values.found.kind()) {
(ty::Param(_), _) => "expected ",
(_, ty::Param(_)) => "found ",
@ -257,7 +241,6 @@ impl<T> Trait<T> for X {
diag.span_label(p_span, format!("{expected}this type parameter"));
}
}
}
(ty::Alias(ty::Projection | ty::Inherent, proj_ty), _)
if !tcx.is_impl_trait_in_trait(proj_ty.def_id) =>
{
@ -545,10 +528,8 @@ impl<T> Trait<T> for X {
return false;
};
let generics = tcx.generics_of(body_owner_def_id);
let Some(param) = generics.opt_type_param(param_ty, tcx) else {
return false;
};
let Some(def_id) = param.def_id.as_local() else {
let def_id = generics.type_param(param_ty, tcx).def_id;
let Some(def_id) = def_id.as_local() else {
return false;
};

View file

@ -957,27 +957,14 @@ impl<'tcx> InferCtxt<'tcx> {
(&ty::Infer(ty::TyVar(a_vid)), &ty::Infer(ty::TyVar(b_vid))) => {
return Err((a_vid, b_vid));
}
// We don't silently want to constrain hidden types here, so we assert that either one side is
// an infer var, so it'll get constrained to whatever the other side is, or there are no opaque
// types involved.
// We don't expect this to actually get hit, but if it does, we now at least know how to write
// a test for it.
(_, ty::Infer(ty::TyVar(_))) => {}
(ty::Infer(ty::TyVar(_)), _) => {}
_ if r_a != r_b && (r_a, r_b).has_opaque_types() => {
span_bug!(
cause.span(),
"opaque types got hidden types registered from within subtype predicate: {r_a:?} vs {r_b:?}"
)
}
_ => {}
}
self.enter_forall(predicate, |ty::SubtypePredicate { a_is_expected, a, b }| {
if a_is_expected {
Ok(self.at(cause, param_env).sub(DefineOpaqueTypes::Yes, a, b))
Ok(self.at(cause, param_env).sub(DefineOpaqueTypes::No, a, b))
} else {
Ok(self.at(cause, param_env).sup(DefineOpaqueTypes::Yes, b, a))
Ok(self.at(cause, param_env).sup(DefineOpaqueTypes::No, b, a))
}
})
}

View file

@ -62,7 +62,9 @@ impl<'tcx> LateLintPass<'tcx> for ForLoopsOverFallibles {
};
let (article, ty, var) = match adt.did() {
did if cx.tcx.is_diagnostic_item(sym::Option, did) && ref_mutability.is_some() => ("a", "Option", "Some"),
did if cx.tcx.is_diagnostic_item(sym::Option, did) && ref_mutability.is_some() => {
("a", "Option", "Some")
}
did if cx.tcx.is_diagnostic_item(sym::Option, did) => ("an", "Option", "Some"),
did if cx.tcx.is_diagnostic_item(sym::Result, did) => ("a", "Result", "Ok"),
_ => return,

View file

@ -90,6 +90,7 @@ declare_lint_pass! {
RUST_2021_PREFIXES_INCOMPATIBLE_SYNTAX,
RUST_2021_PRELUDE_COLLISIONS,
RUST_2024_INCOMPATIBLE_PAT,
SELF_CONSTRUCTOR_FROM_OUTER_ITEM,
SEMICOLON_IN_EXPRESSIONS_FROM_MACROS,
SINGLE_USE_LIFETIMES,
SOFT_UNSTABLE,
@ -3149,6 +3150,47 @@ declare_lint! {
"detects `#[unstable]` on stable trait implementations for stable types"
}
declare_lint! {
/// The `self_constructor_from_outer_item` lint detects cases where the `Self` constructor
/// was silently allowed due to a bug in the resolver, and which may produce surprising
/// and unintended behavior.
///
/// Using a `Self` type alias from an outer item was never intended, but was silently allowed.
/// This is deprecated -- and is a hard error when the `Self` type alias references generics
/// that are not in scope.
///
/// ### Example
///
/// ```rust,compile_fail
/// #![deny(self_constructor_from_outer_item)]
///
/// struct S0(usize);
///
/// impl S0 {
/// fn foo() {
/// const C: S0 = Self(0);
/// fn bar() -> S0 {
/// Self(0)
/// }
/// }
/// }
/// ```
///
/// {{produces}}
///
/// ### Explanation
///
/// The `Self` type alias should not be reachable because nested items are not associated with
/// the scope of the parameters from the parent item.
pub SELF_CONSTRUCTOR_FROM_OUTER_ITEM,
Warn,
"detect unsupported use of `Self` from outer item",
@future_incompatible = FutureIncompatibleInfo {
reason: FutureIncompatibilityReason::FutureReleaseErrorDontReportInDeps,
reference: "issue #124186 <https://github.com/rust-lang/rust/issues/124186>",
};
}
declare_lint! {
/// The `semicolon_in_expressions_from_macros` lint detects trailing semicolons
/// in macro bodies when the macro is invoked in expression position.

View file

@ -245,20 +245,6 @@ impl<'tcx> Generics {
}
}
/// Returns the `GenericParamDef` with the given index if available.
pub fn opt_param_at(
&'tcx self,
param_index: usize,
tcx: TyCtxt<'tcx>,
) -> Option<&'tcx GenericParamDef> {
if let Some(index) = param_index.checked_sub(self.parent_count) {
self.own_params.get(index)
} else {
tcx.generics_of(self.parent.expect("parent_count > 0 but no parent?"))
.opt_param_at(param_index, tcx)
}
}
pub fn params_to(&'tcx self, param_index: usize, tcx: TyCtxt<'tcx>) -> &'tcx [GenericParamDef] {
if let Some(index) = param_index.checked_sub(self.parent_count) {
&self.own_params[..index]
@ -290,20 +276,6 @@ impl<'tcx> Generics {
}
}
/// Returns the `GenericParamDef` associated with this `ParamTy` if it belongs to this
/// `Generics`.
pub fn opt_type_param(
&'tcx self,
param: ParamTy,
tcx: TyCtxt<'tcx>,
) -> Option<&'tcx GenericParamDef> {
let param = self.opt_param_at(param.index as usize, tcx)?;
match param.kind {
GenericParamDefKind::Type { .. } => Some(param),
_ => None,
}
}
/// Returns the `GenericParamDef` associated with this `ParamConst`.
pub fn const_param(&'tcx self, param: ParamConst, tcx: TyCtxt<'tcx>) -> &GenericParamDef {
let param = self.param_at(param.index as usize, tcx);

View file

@ -16,6 +16,7 @@ rustc_errors = { path = "../rustc_errors" }
rustc_fluent_macro = { path = "../rustc_fluent_macro" }
rustc_hir = { path = "../rustc_hir" }
rustc_index = { path = "../rustc_index" }
rustc_infer = { path = "../rustc_infer" }
rustc_macros = { path = "../rustc_macros" }
rustc_middle = { path = "../rustc_middle" }
rustc_mir_build = { path = "../rustc_mir_build" }

View file

@ -1,7 +1,6 @@
//! Inlining pass for MIR functions
use crate::deref_separator::deref_finder;
use rustc_attr::InlineAttr;
use rustc_const_eval::transform::validate::validate_types;
use rustc_hir::def::DefKind;
use rustc_hir::def_id::DefId;
use rustc_index::bit_set::BitSet;
@ -21,6 +20,7 @@ use rustc_target::spec::abi::Abi;
use crate::cost_checker::CostChecker;
use crate::simplify::simplify_cfg;
use crate::util;
use crate::validate::validate_types;
use std::iter;
use std::ops::{Range, RangeFrom};

View file

@ -109,9 +109,9 @@ mod simplify_comparison_integral;
mod sroa;
mod unreachable_enum_branching;
mod unreachable_prop;
mod validate;
use rustc_const_eval::transform::check_consts::{self, ConstCx};
use rustc_const_eval::transform::validate;
use rustc_const_eval::check_consts::{self, ConstCx};
use rustc_mir_dataflow::rustc_peek;
rustc_fluent_macro::fluent_messages! { "../messages.ftl" }

View file

@ -30,7 +30,7 @@ use std::assert_matches::assert_matches;
use std::cell::Cell;
use std::{cmp, iter, mem};
use rustc_const_eval::transform::check_consts::{qualifs, ConstCx};
use rustc_const_eval::check_consts::{qualifs, ConstCx};
/// A `MirPass` for promotion.
///

View file

@ -685,6 +685,15 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
check_equal(self, location, *f_ty);
}
ty::Adt(adt_def, args) => {
// see <https://github.com/rust-lang/rust/blob/7601adcc764d42c9f2984082b49948af652df986/compiler/rustc_middle/src/ty/layout.rs#L861-L864>
if Some(adt_def.did()) == self.tcx.lang_items().dyn_metadata() {
self.fail(
location,
format!("You can't project to field {f:?} of `DynMetadata` because \
layout is weird and thinks it doesn't have fields."),
);
}
let var = parent_ty.variant_index.unwrap_or(FIRST_VARIANT);
let Some(field) = adt_def.variant(var).fields.get(f) else {
fail_out_of_bounds(self, location);

View file

@ -44,7 +44,7 @@ fn ascii_escapes(b: &mut Bencher) {
assert_fmt(
s,
r#""some\tmore\tascii\ttext\nthis time with some \"escapes\", also 64 byte""#,
21,
15,
);
b.iter(|| {
black_box(format!("{:?}", black_box(s)));
@ -72,7 +72,7 @@ fn mostly_unicode(b: &mut Bencher) {
#[bench]
fn mixed(b: &mut Bencher) {
let s = "\"❤️\"\n\"hűha ez betű\"\n\"кириллических букв\".";
assert_fmt(s, r#""\"❤\u{fe0f}\"\n\"hűha ez betű\"\n\"кириллических букв\".""#, 36);
assert_fmt(s, r#""\"❤\u{fe0f}\"\n\"hűha ez betű\"\n\"кириллических букв\".""#, 21);
b.iter(|| {
black_box(format!("{:?}", black_box(s)));
});

View file

@ -898,6 +898,7 @@ pub trait Ord: Eq + PartialOrd<Self> {
/// assert_eq!(2.clamp(-2, 1), 1);
/// ```
#[must_use]
#[inline]
#[stable(feature = "clamp", since = "1.50.0")]
fn clamp(self, min: Self, max: Self) -> Self
where

View file

@ -2402,23 +2402,47 @@ impl Display for bool {
impl Debug for str {
fn fmt(&self, f: &mut Formatter<'_>) -> Result {
f.write_char('"')?;
let mut from = 0;
for (i, c) in self.char_indices() {
// substring we know is printable
let mut printable_range = 0..0;
fn needs_escape(b: u8) -> bool {
b > 0x7E || b < 0x20 || b == b'\\' || b == b'"'
}
// the loop here first skips over runs of printable ASCII as a fast path.
// other chars (unicode, or ASCII that needs escaping) are then handled per-`char`.
let mut rest = self;
while rest.len() > 0 {
let Some(non_printable_start) = rest.as_bytes().iter().position(|&b| needs_escape(b))
else {
printable_range.end += rest.len();
break;
};
printable_range.end += non_printable_start;
// SAFETY: the position was derived from an iterator, so is known to be within bounds, and at a char boundary
rest = unsafe { rest.get_unchecked(non_printable_start..) };
let mut chars = rest.chars();
if let Some(c) = chars.next() {
let esc = c.escape_debug_ext(EscapeDebugExtArgs {
escape_grapheme_extended: true,
escape_single_quote: false,
escape_double_quote: true,
});
// If char needs escaping, flush backlog so far and write, else skip
if esc.len() != 1 {
f.write_str(&self[from..i])?;
for c in esc {
f.write_char(c)?;
f.write_str(&self[printable_range.clone()])?;
Display::fmt(&esc, f)?;
printable_range.start = printable_range.end + c.len_utf8();
}
from = i + c.len_utf8();
printable_range.end += c.len_utf8();
}
rest = chars.as_str();
}
f.write_str(&self[from..])?;
f.write_str(&self[printable_range])?;
f.write_char('"')
}
}
@ -2434,13 +2458,12 @@ impl Display for str {
impl Debug for char {
fn fmt(&self, f: &mut Formatter<'_>) -> Result {
f.write_char('\'')?;
for c in self.escape_debug_ext(EscapeDebugExtArgs {
let esc = self.escape_debug_ext(EscapeDebugExtArgs {
escape_grapheme_extended: true,
escape_single_quote: true,
escape_double_quote: false,
}) {
f.write_char(c)?
}
});
Display::fmt(&esc, f)?;
f.write_char('\'')
}
}

View file

@ -152,7 +152,7 @@ extern "rust-intrinsic" {
#[rustc_nounwind]
pub fn simd_fabs<T>(x: T) -> T;
/// Elementwise minimum of a vector.
/// Elementwise minimum of two vectors.
///
/// `T` must be a vector of floating-point primitive types.
///
@ -160,7 +160,7 @@ extern "rust-intrinsic" {
#[rustc_nounwind]
pub fn simd_fmin<T>(x: T, y: T) -> T;
/// Elementwise maximum of a vector.
/// Elementwise maximum of two vectors.
///
/// `T` must be a vector of floating-point primitive types.
///
@ -387,7 +387,7 @@ extern "rust-intrinsic" {
#[rustc_nounwind]
pub fn simd_reduce_mul_ordered<T, U>(x: T, y: U) -> U;
/// Add elements within a vector in arbitrary order. May also be re-associated with
/// Multiply elements within a vector in arbitrary order. May also be re-associated with
/// unordered additions on the inputs/outputs.
///
/// `T` must be a vector of integer or floating-point primitive types.
@ -405,7 +405,7 @@ extern "rust-intrinsic" {
#[rustc_nounwind]
pub fn simd_reduce_all<T>(x: T) -> bool;
/// Check if all mask values are true.
/// Check if any mask value is true.
///
/// `T` must be a vector of integer primitive types.
///

View file

@ -178,8 +178,8 @@ impl<T: ?Sized> Clone for PtrComponents<T> {
/// compare equal (since identical vtables can be deduplicated within a codegen unit).
#[lang = "dyn_metadata"]
pub struct DynMetadata<Dyn: ?Sized> {
vtable_ptr: &'static VTable,
phantom: crate::marker::PhantomData<Dyn>,
_vtable_ptr: &'static VTable,
_phantom: crate::marker::PhantomData<Dyn>,
}
extern "C" {
@ -191,6 +191,17 @@ extern "C" {
}
impl<Dyn: ?Sized> DynMetadata<Dyn> {
/// One of the things that rustc_middle does with this being a lang item is
/// give it `FieldsShape::Primitive`, which means that as far as codegen can
/// tell, it *is* a reference, and thus doesn't have any fields.
/// That means we can't use field access, and have to transmute it instead.
#[inline]
fn vtable_ptr(self) -> *const VTable {
// SAFETY: this layout assumption is hard-coded into the compiler.
// If it's somehow not a size match, the transmute will error.
unsafe { crate::mem::transmute::<Self, &'static VTable>(self) }
}
/// Returns the size of the type associated with this vtable.
#[inline]
pub fn size_of(self) -> usize {
@ -199,7 +210,7 @@ impl<Dyn: ?Sized> DynMetadata<Dyn> {
// `Send` part!
// SAFETY: DynMetadata always contains a valid vtable pointer
return unsafe {
crate::intrinsics::vtable_size(self.vtable_ptr as *const VTable as *const ())
crate::intrinsics::vtable_size(self.vtable_ptr() as *const ())
};
}
@ -208,7 +219,7 @@ impl<Dyn: ?Sized> DynMetadata<Dyn> {
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 VTable as *const ())
crate::intrinsics::vtable_align(self.vtable_ptr() as *const ())
};
}
@ -226,7 +237,7 @@ unsafe impl<Dyn: ?Sized> Sync for DynMetadata<Dyn> {}
impl<Dyn: ?Sized> fmt::Debug for DynMetadata<Dyn> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_tuple("DynMetadata").field(&(self.vtable_ptr as *const VTable)).finish()
f.debug_tuple("DynMetadata").field(&self.vtable_ptr()).finish()
}
}
@ -248,7 +259,7 @@ impl<Dyn: ?Sized> Eq for DynMetadata<Dyn> {}
impl<Dyn: ?Sized> PartialEq for DynMetadata<Dyn> {
#[inline]
fn eq(&self, other: &Self) -> bool {
crate::ptr::eq::<VTable>(self.vtable_ptr, other.vtable_ptr)
crate::ptr::eq::<VTable>(self.vtable_ptr(), other.vtable_ptr())
}
}
@ -256,7 +267,7 @@ impl<Dyn: ?Sized> Ord for DynMetadata<Dyn> {
#[inline]
#[allow(ambiguous_wide_pointer_comparisons)]
fn cmp(&self, other: &Self) -> crate::cmp::Ordering {
(self.vtable_ptr as *const VTable).cmp(&(other.vtable_ptr as *const VTable))
<*const VTable>::cmp(&self.vtable_ptr(), &other.vtable_ptr())
}
}
@ -270,6 +281,6 @@ impl<Dyn: ?Sized> PartialOrd for DynMetadata<Dyn> {
impl<Dyn: ?Sized> Hash for DynMetadata<Dyn> {
#[inline]
fn hash<H: Hasher>(&self, hasher: &mut H) {
crate::ptr::hash::<VTable, _>(self.vtable_ptr, hasher)
crate::ptr::hash::<VTable, _>(self.vtable_ptr(), hasher)
}
}

View file

@ -9,8 +9,6 @@ pub mod cmath;
pub mod os_str;
pub mod path;
pub mod sync;
#[allow(dead_code)]
#[allow(unused_imports)]
pub mod thread_local;
// FIXME(117276): remove this, move feature implementations into individual

View file

@ -1,6 +1,5 @@
use crate::cell::UnsafeCell;
use crate::hint::unreachable_unchecked;
use crate::mem::forget;
use crate::ptr;
use crate::sys::thread_local::abort_on_dtor_unwind;
use crate::sys::thread_local_dtor::register_dtor;

View file

@ -1,4 +1,5 @@
#![unstable(feature = "thread_local_internals", reason = "should not be necessary", issue = "none")]
#![cfg_attr(test, allow(unused))]
// There are three thread-local implementations: "static", "fast", "OS".
// The "OS" thread local key type is accessed via platform-specific API calls and is slow, while the
@ -24,94 +25,12 @@ cfg_if::cfg_if! {
}
}
// Not used by the fast-local TLS anymore.
// FIXME(#110897): remove this.
#[allow(unused)]
mod lazy {
use crate::cell::UnsafeCell;
use crate::hint;
use crate::mem;
pub struct LazyKeyInner<T> {
inner: UnsafeCell<Option<T>>,
}
impl<T> LazyKeyInner<T> {
pub const fn new() -> LazyKeyInner<T> {
LazyKeyInner { inner: UnsafeCell::new(None) }
}
pub unsafe fn get(&self) -> Option<&'static T> {
// SAFETY: The caller must ensure no reference is ever handed out to
// the inner cell nor mutable reference to the Option<T> inside said
// cell. This make it safe to hand a reference, though the lifetime
// of 'static is itself unsafe, making the get method unsafe.
unsafe { (*self.inner.get()).as_ref() }
}
/// The caller must ensure that no reference is active: this method
/// needs unique access.
pub unsafe fn initialize<F: FnOnce() -> T>(&self, init: F) -> &'static T {
// Execute the initialization up front, *then* move it into our slot,
// just in case initialization fails.
let value = init();
let ptr = self.inner.get();
// SAFETY:
//
// note that this can in theory just be `*ptr = Some(value)`, but due to
// the compiler will currently codegen that pattern with something like:
//
// ptr::drop_in_place(ptr)
// ptr::write(ptr, Some(value))
//
// Due to this pattern it's possible for the destructor of the value in
// `ptr` (e.g., if this is being recursively initialized) to re-access
// TLS, in which case there will be a `&` and `&mut` pointer to the same
// value (an aliasing violation). To avoid setting the "I'm running a
// destructor" flag we just use `mem::replace` which should sequence the
// operations a little differently and make this safe to call.
//
// The precondition also ensures that we are the only one accessing
// `self` at the moment so replacing is fine.
unsafe {
let _ = mem::replace(&mut *ptr, Some(value));
}
// SAFETY: With the call to `mem::replace` it is guaranteed there is
// a `Some` behind `ptr`, not a `None` so `unreachable_unchecked`
// will never be reached.
unsafe {
// After storing `Some` we want to get a reference to the contents of
// what we just stored. While we could use `unwrap` here and it should
// always work it empirically doesn't seem to always get optimized away,
// which means that using something like `try_with` can pull in
// panicking code and cause a large size bloat.
match *ptr {
Some(ref x) => x,
None => hint::unreachable_unchecked(),
}
}
}
/// Watch out: unsynchronized internal mutability!
///
/// # Safety
/// Causes UB if any reference to the value is used after this.
#[allow(unused)]
pub(crate) unsafe fn take(&self) -> Option<T> {
let mutable: *mut _ = UnsafeCell::get(&self.inner);
// SAFETY: That's the caller's problem.
unsafe { mutable.replace(None) }
}
}
}
/// Run a callback in a scenario which must not unwind (such as a `extern "C"
/// fn` declared in a user crate). If the callback unwinds anyway, then
/// `rtabort` with a message about thread local panicking on drop.
#[inline]
pub fn abort_on_dtor_unwind(f: impl FnOnce()) {
#[allow(dead_code)]
fn abort_on_dtor_unwind(f: impl FnOnce()) {
// Using a guard like this is lower cost.
let guard = DtorUnwindGuard;
f();

View file

@ -1,7 +1,8 @@
use super::lazy::LazyKeyInner;
use super::abort_on_dtor_unwind;
use crate::cell::Cell;
use crate::sys_common::thread_local_key::StaticKey as OsStaticKey;
use crate::{fmt, marker, panic, ptr};
use crate::marker::PhantomData;
use crate::ptr;
use crate::sys_common::thread_local_key::StaticKey as OsKey;
#[doc(hidden)]
#[allow_internal_unstable(thread_local_internals)]
@ -10,38 +11,9 @@ use crate::{fmt, marker, panic, ptr};
#[rustc_macro_transparency = "semitransparent"]
pub macro thread_local_inner {
// used to generate the `LocalKey` value for const-initialized thread locals
(@key $t:ty, const $init:expr) => {{
#[inline]
#[deny(unsafe_op_in_unsafe_fn)]
unsafe fn __getit(
_init: $crate::option::Option<&mut $crate::option::Option<$t>>,
) -> $crate::option::Option<&'static $t> {
const INIT_EXPR: $t = $init;
// On platforms without `#[thread_local]` we fall back to the
// same implementation as below for os thread locals.
#[inline]
const fn __init() -> $t { INIT_EXPR }
static __KEY: $crate::thread::local_impl::Key<$t> =
$crate::thread::local_impl::Key::new();
unsafe {
__KEY.get(move || {
if let $crate::option::Option::Some(init) = _init {
if let $crate::option::Option::Some(value) = init.take() {
return value;
} else if $crate::cfg!(debug_assertions) {
$crate::unreachable!("missing initial value");
}
}
__init()
})
}
}
unsafe {
$crate::thread::LocalKey::new(__getit)
}
}},
(@key $t:ty, const $init:expr) => {
$crate::thread::local_impl::thread_local_inner!(@key $t, { const INIT_EXPR: $t = $init; INIT_EXPR })
},
// used to generate the `LocalKey` value for `thread_local!`
(@key $t:ty, $init:expr) => {
@ -55,20 +27,11 @@ pub macro thread_local_inner {
unsafe fn __getit(
init: $crate::option::Option<&mut $crate::option::Option<$t>>,
) -> $crate::option::Option<&'static $t> {
static __KEY: $crate::thread::local_impl::Key<$t> =
$crate::thread::local_impl::Key::new();
use $crate::thread::local_impl::Key;
static __KEY: Key<$t> = Key::new();
unsafe {
__KEY.get(move || {
if let $crate::option::Option::Some(init) = init {
if let $crate::option::Option::Some(value) = init.take() {
return value;
} else if $crate::cfg!(debug_assertions) {
$crate::unreachable!("missing default value");
}
}
__init()
})
__KEY.get(init, __init)
}
}
@ -85,78 +48,78 @@ pub macro thread_local_inner {
/// Use a regular global static to store this key; the state provided will then be
/// thread-local.
#[allow(missing_debug_implementations)]
pub struct Key<T> {
// OS-TLS key that we'll use to key off.
os: OsStaticKey,
marker: marker::PhantomData<Cell<T>>,
}
impl<T> fmt::Debug for Key<T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("Key").finish_non_exhaustive()
}
os: OsKey,
marker: PhantomData<Cell<T>>,
}
unsafe impl<T> Sync for Key<T> {}
struct Value<T: 'static> {
inner: LazyKeyInner<T>,
value: T,
key: &'static Key<T>,
}
impl<T: 'static> Key<T> {
#[rustc_const_unstable(feature = "thread_local_internals", issue = "none")]
pub const fn new() -> Key<T> {
Key { os: OsStaticKey::new(Some(destroy_value::<T>)), marker: marker::PhantomData }
Key { os: OsKey::new(Some(destroy_value::<T>)), marker: PhantomData }
}
/// It is a requirement for the caller to ensure that no mutable
/// reference is active when this method is called.
pub unsafe fn get(&'static self, init: impl FnOnce() -> T) -> Option<&'static T> {
// SAFETY: See the documentation for this method.
/// Get the value associated with this key, initializating it if necessary.
///
/// # Safety
/// * the returned reference must not be used after recursive initialization
/// or thread destruction occurs.
pub unsafe fn get(
&'static self,
i: Option<&mut Option<T>>,
f: impl FnOnce() -> T,
) -> Option<&'static T> {
// SAFETY: (FIXME: get should actually be safe)
let ptr = unsafe { self.os.get() as *mut Value<T> };
if ptr.addr() > 1 {
// SAFETY: the check ensured the pointer is safe (its destructor
// is not running) + it is coming from a trusted source (self).
if let Some(ref value) = unsafe { (*ptr).inner.get() } {
return Some(value);
}
}
unsafe { Some(&(*ptr).value) }
} else {
// SAFETY: At this point we are sure we have no value and so
// initializing (or trying to) is safe.
unsafe { self.try_initialize(init) }
unsafe { self.try_initialize(ptr, i, f) }
}
}
// `try_initialize` is only called once per os thread local variable,
// except in corner cases where thread_local dtors reference other
// thread_local's, or it is being recursively initialized.
unsafe fn try_initialize(&'static self, init: impl FnOnce() -> T) -> Option<&'static T> {
// SAFETY: No mutable references are ever handed out meaning getting
// the value is ok.
let ptr = unsafe { self.os.get() as *mut Value<T> };
unsafe fn try_initialize(
&'static self,
ptr: *mut Value<T>,
i: Option<&mut Option<T>>,
f: impl FnOnce() -> T,
) -> Option<&'static T> {
if ptr.addr() == 1 {
// destructor is running
return None;
}
let ptr = if ptr.is_null() {
// If the lookup returned null, we haven't initialized our own
// local copy, so do that now.
let ptr = Box::into_raw(Box::new(Value { inner: LazyKeyInner::new(), key: self }));
// SAFETY: At this point we are sure there is no value inside
// ptr so setting it will not affect anyone else.
let value = i.and_then(Option::take).unwrap_or_else(f);
let ptr = Box::into_raw(Box::new(Value { value, key: self }));
// SAFETY: (FIXME: get should actually be safe)
let old = unsafe { self.os.get() as *mut Value<T> };
// SAFETY: `ptr` is a correct pointer that can be destroyed by the key destructor.
unsafe {
self.os.set(ptr as *mut u8);
}
ptr
} else {
// recursive initialization
ptr
};
if !old.is_null() {
// If the variable was recursively initialized, drop the old value.
// SAFETY: We cannot be inside a `LocalKey::with` scope, as the
// initializer has already returned and the next scope only starts
// after we return the pointer. Therefore, there can be no references
// to the old value.
drop(unsafe { Box::from_raw(old) });
}
// SAFETY: ptr has been ensured as non-NUL just above an so can be
// dereferenced safely.
unsafe { Some((*ptr).inner.initialize(init)) }
// SAFETY: We just created this value above.
unsafe { Some(&(*ptr).value) }
}
}
@ -170,16 +133,11 @@ unsafe extern "C" fn destroy_value<T: 'static>(ptr: *mut u8) {
//
// Note that to prevent an infinite loop we reset it back to null right
// before we return from the destructor ourselves.
//
// Wrap the call in a catch to ensure unwinding is caught in the event
// a panic takes place in a destructor.
if let Err(_) = panic::catch_unwind(|| unsafe {
let ptr = Box::from_raw(ptr as *mut Value<T>);
abort_on_dtor_unwind(|| {
let ptr = unsafe { Box::from_raw(ptr as *mut Value<T>) };
let key = ptr.key;
key.os.set(ptr::without_provenance_mut(1));
unsafe { key.os.set(ptr::without_provenance_mut(1)) };
drop(ptr);
key.os.set(ptr::null_mut());
}) {
rtabort!("thread local panicked on drop");
}
unsafe { key.os.set(ptr::null_mut()) };
});
}

View file

@ -98,7 +98,7 @@ fn fmt_thousands_sep(mut n: f64, sep: char) -> String {
(0, true) => write!(output, "{:06.2}", n / base as f64).unwrap(),
(0, false) => write!(output, "{:.2}", n / base as f64).unwrap(),
(_, true) => write!(output, "{:03}", n as usize / base).unwrap(),
_ => write!(output, "{}", n as usize / base).unwrap()
_ => write!(output, "{}", n as usize / base).unwrap(),
}
if pow != 0 {
output.push(sep);

View file

@ -6,7 +6,7 @@ and some of the technical details of the build system.
Note that this README only covers internal information, not how to use the tool.
Please check [bootstrapping dev guide][bootstrapping-dev-guide] for further information.
[bootstrapping-dev-guide]: https://rustc-dev-guide.rust-lang.org/building/bootstrapping.html
[bootstrapping-dev-guide]: https://rustc-dev-guide.rust-lang.org/building/bootstrapping/intro.html
## Introduction

View file

@ -60,7 +60,14 @@ fn check_cli<const N: usize>(paths: [&str; N]) {
macro_rules! std {
($host:ident => $target:ident, stage = $stage:literal) => {
compile::Std::new(
Compiler { host: TargetSelection::from_user(concat!(stringify!($host), "-", stringify!($host))), stage: $stage },
Compiler {
host: TargetSelection::from_user(concat!(
stringify!($host),
"-",
stringify!($host)
)),
stage: $stage,
},
TargetSelection::from_user(concat!(stringify!($target), "-", stringify!($target))),
)
};
@ -83,7 +90,14 @@ macro_rules! doc_std {
macro_rules! rustc {
($host:ident => $target:ident, stage = $stage:literal) => {
compile::Rustc::new(
Compiler { host: TargetSelection::from_user(concat!(stringify!($host), "-", stringify!($host))), stage: $stage },
Compiler {
host: TargetSelection::from_user(concat!(
stringify!($host),
"-",
stringify!($host)
)),
stage: $stage,
},
TargetSelection::from_user(concat!(stringify!($target), "-", stringify!($target))),
)
};
@ -141,10 +155,14 @@ fn check_missing_paths_for_x_test_tests() {
// Skip if not a test directory.
if path.ends_with("tests/auxiliary") || !path.is_dir() {
continue
continue;
}
assert!(tests_remap_paths.iter().any(|item| path.ends_with(*item)), "{} is missing in PATH_REMAP tests list.", path.display());
assert!(
tests_remap_paths.iter().any(|item| path.ends_with(*item)),
"{} is missing in PATH_REMAP tests list.",
path.display()
);
}
}
@ -185,7 +203,8 @@ fn alias_and_path_for_library() {
&[std!(A => A, stage = 0), std!(A => A, stage = 1)]
);
let mut cache = run_build(&["library".into(), "core".into()], configure("doc", &["A-A"], &["A-A"]));
let mut cache =
run_build(&["library".into(), "core".into()], configure("doc", &["A-A"], &["A-A"]));
assert_eq!(first(cache.all::<doc::Std>()), &[doc_std!(A => A, stage = 0)]);
}

View file

@ -199,11 +199,15 @@ than building it.
if !["A-A", "B-B", "C-C"].contains(&target_str.as_str()) {
let mut has_target = false;
let missing_targets_hashset: HashSet<_> = STAGE0_MISSING_TARGETS.iter().map(|t| t.to_string()).collect();
let duplicated_targets: Vec<_> = stage0_supported_target_list.intersection(&missing_targets_hashset).collect();
let missing_targets_hashset: HashSet<_> =
STAGE0_MISSING_TARGETS.iter().map(|t| t.to_string()).collect();
let duplicated_targets: Vec<_> =
stage0_supported_target_list.intersection(&missing_targets_hashset).collect();
if !duplicated_targets.is_empty() {
println!("Following targets supported from the stage0 compiler, please remove them from STAGE0_MISSING_TARGETS list.");
println!(
"Following targets supported from the stage0 compiler, please remove them from STAGE0_MISSING_TARGETS list."
);
for duplicated_target in duplicated_targets {
println!(" {duplicated_target}");
}

View file

@ -1,5 +1,5 @@
pub mod ci;
pub mod git;
pub mod metrics;
pub mod util;
pub mod stage0_parser;
pub mod util;

View file

@ -6,7 +6,7 @@
use clippy_config::msrvs::{self, Msrv};
use hir::LangItem;
use rustc_attr::StableSince;
use rustc_const_eval::transform::check_consts::ConstCx;
use rustc_const_eval::check_consts::ConstCx;
use rustc_hir as hir;
use rustc_hir::def_id::DefId;
use rustc_infer::infer::TyCtxtInferExt;

View file

@ -1 +1 @@
78dd504f2fd87c0cfabff7d9174253411caf2f80
21e6de7eb64c09102de3f100420a09edc1a2a8d7

View file

@ -1,4 +1,4 @@
thread 'rustc' panicked at compiler/rustc_const_eval/src/transform/validate.rs:LL:CC:
thread 'rustc' panicked at compiler/rustc_mir_transform/src/validate.rs:LL:CC:
broken MIR in Item(DefId) (after phase change to runtime-optimized) at bb0[1]:
(*(_2.0: *mut i32)), has deref at the wrong place
stack backtrace:

View file

@ -228,7 +228,6 @@ run-make/rmeta-preferred/Makefile
run-make/rustc-macro-dep-files/Makefile
run-make/rustdoc-io-error/Makefile
run-make/rustdoc-verify-output-files/Makefile
run-make/rustdoc-with-output-option/Makefile
run-make/sanitizer-cdylib-link/Makefile
run-make/sanitizer-dylib-link/Makefile
run-make/sanitizer-staticlib-link/Makefile

View file

@ -1,8 +0,0 @@
//@ known-bug: #118403
#![feature(generic_const_exprs)]
pub struct X<const N: usize> {}
impl<const Z: usize> X<Z> {
pub fn y<'a, U: 'a>(&'a self) -> impl Iterator<Item = impl Iterator<Item = [u8; Z]> + '_> {
(0..1).map(move |_| (0..1).map(move |_| loop {}))
}
}

View file

@ -1,8 +0,0 @@
//@ known-bug: #121574
#![feature(generic_const_exprs)]
pub struct DimName<const N: usize> {}
impl<const Z: usize> X<Z> {
pub fn y<'a, U: 'a>(&'a self) -> impl Iterator<Item = impl Iterator<Item = [u8; Z]> + '_> {
"0".as_bytes(move |_| (0..1).map(move |_| loop {}))
}
}

View file

@ -1,6 +0,0 @@
//@ known-bug: #121574
#![feature(generic_const_exprs)]
impl<const Z: usize> X<Z> {
pub fn y<'a, U: 'a>(&'a self) -> impl Iterator<Item = impl Iterator<Item = [u8; Z]> + '_> {}
}

View file

@ -1,10 +0,0 @@
//@ known-bug: rust-lang/rust#124833
#![feature(generic_const_items)]
trait Trait {
const C<'a>: &'a str;
}
impl Trait for () {
const C<'a>: = "C";
}

View file

@ -1,22 +0,0 @@
//@ known-bug: rust-lang/rust#124891
type Tait = impl FnOnce() -> ();
fn reify_as_tait() -> Thunk<Tait> {
Thunk::new(|cont| cont)
}
struct Thunk<F>(F);
impl<F> Thunk<F> {
fn new(f: F)
where
F: ContFn,
{
todo!();
}
}
trait ContFn {}
impl<F: FnOnce(Tait) -> ()> ContFn for F {}

View file

@ -1,8 +0,0 @@
include ../tools.mk
OUTPUT_DIR := "$(TMPDIR)/rustdoc"
all:
$(RUSTDOC) src/lib.rs --crate-name foobar --crate-type lib --output $(OUTPUT_DIR)
$(HTMLDOCCK) $(OUTPUT_DIR) src/lib.rs

View file

@ -0,0 +1,16 @@
use run_make_support::{htmldocck, rustdoc, tmp_dir};
fn main() {
let out_dir = tmp_dir().join("rustdoc");
rustdoc()
.input("src/lib.rs")
.crate_name("foobar")
.crate_type("lib")
// This is intentionally using `--output` option flag and not the `output()` method.
.arg("--output")
.arg(&out_dir)
.run();
assert!(htmldocck().arg(out_dir).arg("src/lib.rs").status().unwrap().success());
}

View file

@ -0,0 +1,20 @@
// Ensure keyword docs are present with --document-private-items
//@ compile-flags: --document-private-items
#![feature(rustdoc_internals)]
// @!has "$.index[*][?(@.name=='match')]"
// @has "$.index[*][?(@.name=='foo')]"
// @is "$.index[*][?(@.name=='foo')].attrs" '["#[doc(keyword = \"match\")]"]'
// @is "$.index[*][?(@.name=='foo')].docs" '"this is a test!"'
#[doc(keyword = "match")]
/// this is a test!
pub mod foo {}
// @!has "$.index[*][?(@.name=='hello')]"
// @has "$.index[*][?(@.name=='bar')]"
// @is "$.index[*][?(@.name=='bar')].attrs" '["#[doc(keyword = \"hello\")]"]'
// @is "$.index[*][?(@.name=='bar')].docs" '"hello"'
#[doc(keyword = "hello")]
/// hello
mod bar {}

View file

@ -0,0 +1,14 @@
pub fn bad(x: &mut bool) {
if true
*x = true {}
//~^ ERROR cannot multiply `bool` by `&mut bool`
}
pub fn bad2(x: &mut bool) {
let y: bool;
y = true
*x = true;
//~^ ERROR cannot multiply `bool` by `&mut bool`
}
fn main() {}

View file

@ -0,0 +1,29 @@
error[E0369]: cannot multiply `bool` by `&mut bool`
--> $DIR/nested-assignment-may-be-deref.rs:3:5
|
LL | if true
| ---- bool
LL | *x = true {}
| ^- &mut bool
|
help: you might have meant to write a semicolon here
|
LL | if true;
| +
error[E0369]: cannot multiply `bool` by `&mut bool`
--> $DIR/nested-assignment-may-be-deref.rs:10:5
|
LL | y = true
| ---- bool
LL | *x = true;
| ^- &mut bool
|
help: you might have meant to write a semicolon here
|
LL | y = true;
| +
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0369`.

View file

@ -0,0 +1,13 @@
//@ check-pass
#![feature(generic_const_exprs)]
//~^ WARN the feature `generic_const_exprs` is incomplete and may not be safe to use
pub fn y<'a, U: 'a>() -> impl IntoIterator<Item = impl IntoIterator<Item = [u8; { 1 + 2 }]> + 'a> {
[[[1, 2, 3]]]
}
// Make sure that the `predicates_of` for `{ 1 + 2 }` don't mention the duplicated lifetimes of
// the *outer* iterator. Whether they should mention the duplicated lifetimes of the *inner*
// iterator are another question, but not really something we need to answer immediately.
fn main() {}

View file

@ -0,0 +1,11 @@
warning: the feature `generic_const_exprs` is incomplete and may not be safe to use and/or cause compiler crashes
--> $DIR/double-opaque-parent-predicates.rs:3:12
|
LL | #![feature(generic_const_exprs)]
| ^^^^^^^^^^^^^^^^^^^
|
= note: see issue #76560 <https://github.com/rust-lang/rust/issues/76560> for more information
= note: `#[warn(incomplete_features)]` on by default
warning: 1 warning emitted

View file

@ -0,0 +1,21 @@
// Ensure that we properly deal with missing/placeholder types inside GACs.
// issue: rust-lang/rust#124833
#![feature(generic_const_items)]
#![allow(incomplete_features)]
trait Trait {
const K<T>: T;
const Q<'a>: &'a str;
}
impl Trait for () {
const K<T> = ();
//~^ ERROR missing type for `const` item
//~| ERROR mismatched types
//~| ERROR mismatched types
const Q = "";
//~^ ERROR missing type for `const` item
//~| ERROR lifetime parameters or bounds on const `Q` do not match the trait declaration
}
fn main() {}

View file

@ -0,0 +1,48 @@
error[E0308]: mismatched types
--> $DIR/assoc-const-missing-type.rs:12:18
|
LL | const K<T> = ();
| - ^^ expected type parameter `T`, found `()`
| |
| expected this type parameter
|
= note: expected type parameter `T`
found unit type `()`
error: missing type for `const` item
--> $DIR/assoc-const-missing-type.rs:12:15
|
LL | const K<T> = ();
| ^ help: provide a type for the associated constant: `()`
error[E0195]: lifetime parameters or bounds on const `Q` do not match the trait declaration
--> $DIR/assoc-const-missing-type.rs:16:12
|
LL | const Q<'a>: &'a str;
| ---- lifetimes in impl do not match this const in trait
...
LL | const Q = "";
| ^ lifetimes do not match const in trait
error: missing type for `const` item
--> $DIR/assoc-const-missing-type.rs:16:12
|
LL | const Q = "";
| ^ help: provide a type for the associated constant: `: &str`
error[E0308]: mismatched types
--> $DIR/assoc-const-missing-type.rs:12:18
|
LL | const K<T> = ();
| - ^^ expected type parameter `T`, found `()`
| |
| expected this type parameter
|
= note: expected type parameter `T`
found unit type `()`
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
error: aborting due to 5 previous errors
Some errors have detailed explanations: E0195, E0308.
For more information about an error, try `rustc --explain E0195`.

View file

@ -0,0 +1,59 @@
//! This test checks that we allow subtyping predicates that contain opaque types.
//! No hidden types are being constrained in the subtyping predicate, but type and
//! lifetime variables get subtyped in the generic parameter list of the opaque.
use std::iter;
mod either {
pub enum Either<L, R> {
Left(L),
Right(R),
}
impl<L: Iterator, R: Iterator<Item = L::Item>> Iterator for Either<L, R> {
type Item = L::Item;
fn next(&mut self) -> Option<Self::Item> {
todo!()
}
}
pub use self::Either::{Left, Right};
}
pub enum BabeConsensusLogRef<'a> {
NextEpochData(BabeNextEpochRef<'a>),
NextConfigData,
}
impl<'a> BabeConsensusLogRef<'a> {
pub fn scale_encoding(
&self,
) -> impl Iterator<Item = impl AsRef<[u8]> + Clone + 'a> + Clone + 'a {
//~^ ERROR is not satisfied
//~| ERROR is not satisfied
//~| ERROR is not satisfied
match self {
BabeConsensusLogRef::NextEpochData(digest) => either::Left(either::Left(
digest.scale_encoding().map(either::Left).map(either::Left),
)),
BabeConsensusLogRef::NextConfigData => either::Right(
// The Opaque type from ``scale_encoding` gets used opaquely here, while the `R`
// generic parameter of `Either` contains type variables that get subtyped and the
// opaque type contains lifetime variables that get subtyped.
iter::once(either::Right(either::Left([1])))
.chain(std::iter::once([1]).map(either::Right).map(either::Right)),
),
}
}
}
pub struct BabeNextEpochRef<'a>(&'a ());
impl<'a> BabeNextEpochRef<'a> {
pub fn scale_encoding(
&self,
) -> impl Iterator<Item = impl AsRef<[u8]> + Clone + 'a> + Clone + 'a {
std::iter::once([1])
}
}
fn main() {}

View file

@ -0,0 +1,21 @@
error[E0277]: the trait bound `Either<Either<Map<Map<impl Iterator<Item = impl AsRef<[u8]> + Clone + '_> + Clone + '_, fn(impl AsRef<[u8]> + Clone + '_) -> Either<impl AsRef<[u8]> + Clone + '_, _> {Either::<impl AsRef<[u8]> + Clone + '_, _>::Left}>, fn(Either<impl AsRef<[u8]> + Clone + '_, _>) -> Either<Either<impl AsRef<[u8]> + Clone + '_, _>, Either<[{integer}; 1], [{integer}; 1]>> {Either::<Either<impl AsRef<[u8]> + Clone + '_, _>, Either<[{integer}; 1], [{integer}; 1]>>::Left}>, _>, std::iter::Chain<std::iter::Once<Either<Either<impl AsRef<[u8]> + Clone + '_, _>, Either<[{integer}; 1], [{integer}; 1]>>>, Map<Map<std::iter::Once<[{integer}; 1]>, fn([{integer}; 1]) -> Either<[{integer}; 1], [{integer}; 1]> {Either::<[{integer}; 1], [{integer}; 1]>::Right}>, fn(Either<[{integer}; 1], [{integer}; 1]>) -> Either<Either<impl AsRef<[u8]> + Clone + '_, _>, Either<[{integer}; 1], [{integer}; 1]>> {Either::<Either<impl AsRef<[u8]> + Clone + '_, _>, Either<[{integer}; 1], [{integer}; 1]>>::Right}>>>: Clone` is not satisfied
--> $DIR/lazy_subtyping_of_opaques.rs:30:10
|
LL | ) -> impl Iterator<Item = impl AsRef<[u8]> + Clone + 'a> + Clone + 'a {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `Either<Either<Map<Map<impl Iterator<Item = impl AsRef<[u8]> + Clone + '_> + Clone + '_, fn(impl AsRef<[u8]> + Clone + '_) -> Either<impl AsRef<[u8]> + Clone + '_, _> {Either::<impl AsRef<[u8]> + Clone + '_, _>::Left}>, fn(Either<impl AsRef<[u8]> + Clone + '_, _>) -> Either<Either<impl AsRef<[u8]> + Clone + '_, _>, Either<[{integer}; 1], [{integer}; 1]>> {Either::<Either<impl AsRef<[u8]> + Clone + '_, _>, Either<[{integer}; 1], [{integer}; 1]>>::Left}>, _>, std::iter::Chain<std::iter::Once<Either<Either<impl AsRef<[u8]> + Clone + '_, _>, Either<[{integer}; 1], [{integer}; 1]>>>, Map<Map<std::iter::Once<[{integer}; 1]>, fn([{integer}; 1]) -> Either<[{integer}; 1], [{integer}; 1]> {Either::<[{integer}; 1], [{integer}; 1]>::Right}>, fn(Either<[{integer}; 1], [{integer}; 1]>) -> Either<Either<impl AsRef<[u8]> + Clone + '_, _>, Either<[{integer}; 1], [{integer}; 1]>> {Either::<Either<impl AsRef<[u8]> + Clone + '_, _>, Either<[{integer}; 1], [{integer}; 1]>>::Right}>>>`
error[E0277]: the trait bound `Either<Either<impl AsRef<[u8]> + Clone + '_, _>, Either<[{integer}; 1], [{integer}; 1]>>: AsRef<[u8]>` is not satisfied
--> $DIR/lazy_subtyping_of_opaques.rs:30:31
|
LL | ) -> impl Iterator<Item = impl AsRef<[u8]> + Clone + 'a> + Clone + 'a {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `AsRef<[u8]>` is not implemented for `Either<Either<impl AsRef<[u8]> + Clone + '_, _>, Either<[{integer}; 1], [{integer}; 1]>>`
error[E0277]: the trait bound `Either<Either<impl AsRef<[u8]> + Clone + '_, _>, Either<[{integer}; 1], [{integer}; 1]>>: Clone` is not satisfied
--> $DIR/lazy_subtyping_of_opaques.rs:30:31
|
LL | ) -> impl Iterator<Item = impl AsRef<[u8]> + Clone + 'a> + Clone + 'a {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `Either<Either<impl AsRef<[u8]> + Clone + '_, _>, Either<[{integer}; 1], [{integer}; 1]>>`
error: aborting due to 3 previous errors
For more information about this error, try `rustc --explain E0277`.

View file

@ -1,7 +1,12 @@
struct A<B>(B);
impl<B>A<B>{fn d(){fn d(){Self(1)}}}
//~^ ERROR the size for values of type `B` cannot be known at compilation time
//~| ERROR the size for values of type `B` cannot be known at compilation time
//~| ERROR mismatched types
//~| ERROR mismatched types
//~| ERROR `main` function not found in crate
impl<B> A<B> {
fn d() {
fn d() {
Self(1)
//~^ ERROR can't reference `Self` constructor from outer item
}
}
}
fn main() {}

View file

@ -1,79 +1,12 @@
error[E0601]: `main` function not found in crate `do_not_ice_on_note_and_explain`
--> $DIR/do-not-ice-on-note_and_explain.rs:2:37
error[E0401]: can't reference `Self` constructor from outer item
--> $DIR/do-not-ice-on-note_and_explain.rs:6:13
|
LL | impl<B>A<B>{fn d(){fn d(){Self(1)}}}
| ^ consider adding a `main` function to `$DIR/do-not-ice-on-note_and_explain.rs`
LL | impl<B> A<B> {
| ------------ the inner item doesn't inherit generics from this impl, so `Self` is invalid to reference
...
LL | Self(1)
| ^^^^ help: replace `Self` with the actual type: `A`
error[E0277]: the size for values of type `B` cannot be known at compilation time
--> $DIR/do-not-ice-on-note_and_explain.rs:2:32
|
LL | impl<B>A<B>{fn d(){fn d(){Self(1)}}}
| - ---- ^ doesn't have a size known at compile-time
| | |
| | required by a bound introduced by this call
| this type parameter needs to be `Sized`
|
note: required by a bound in `A`
--> $DIR/do-not-ice-on-note_and_explain.rs:1:10
|
LL | struct A<B>(B);
| ^ required by this bound in `A`
error: aborting due to 1 previous error
error[E0308]: mismatched types
--> $DIR/do-not-ice-on-note_and_explain.rs:2:32
|
LL | impl<B>A<B>{fn d(){fn d(){Self(1)}}}
| ---- ^ expected type parameter `B`, found integer
| |
| arguments to this function are incorrect
|
= note: expected type parameter `B`
found type `{integer}`
note: tuple struct defined here
--> $DIR/do-not-ice-on-note_and_explain.rs:1:8
|
LL | struct A<B>(B);
| ^
error[E0308]: mismatched types
--> $DIR/do-not-ice-on-note_and_explain.rs:2:27
|
LL | impl<B>A<B>{fn d(){fn d(){Self(1)}}}
| ^^^^^^^ expected `()`, found `A<B>`
|
= note: expected unit type `()`
found struct `A<B>`
help: consider using a semicolon here
|
LL | impl<B>A<B>{fn d(){fn d(){Self(1);}}}
| +
help: try adding a return type
|
LL | impl<B>A<B>{fn d(){fn d() -> A<B>{Self(1)}}}
| +++++++
error[E0277]: the size for values of type `B` cannot be known at compilation time
--> $DIR/do-not-ice-on-note_and_explain.rs:2:27
|
LL | impl<B>A<B>{fn d(){fn d(){Self(1)}}}
| - ^^^^^^^ doesn't have a size known at compile-time
| |
| this type parameter needs to be `Sized`
|
note: required by an implicit `Sized` bound in `A`
--> $DIR/do-not-ice-on-note_and_explain.rs:1:10
|
LL | struct A<B>(B);
| ^ required by the implicit `Sized` requirement on this type parameter in `A`
help: you could relax the implicit `Sized` bound on `B` if it were used through indirection like `&B` or `Box<B>`
--> $DIR/do-not-ice-on-note_and_explain.rs:1:10
|
LL | struct A<B>(B);
| ^ - ...if indirection were used here: `Box<B>`
| |
| this could be changed to `B: ?Sized`...
error: aborting due to 5 previous errors
Some errors have detailed explanations: E0277, E0308, E0601.
For more information about an error, try `rustc --explain E0277`.
For more information about this error, try `rustc --explain E0401`.

View file

@ -6,8 +6,12 @@ struct S0(usize);
impl S0 {
fn foo() {
const C: S0 = Self(0);
//~^ WARN can't reference `Self` constructor from outer item
//~| WARN this was previously accepted by the compiler but is being phased out
fn bar() -> S0 {
Self(0)
//~^ WARN can't reference `Self` constructor from outer item
//~| WARN this was previously accepted by the compiler but is being phased out
}
}
}

View file

@ -0,0 +1,27 @@
warning: can't reference `Self` constructor from outer item
--> $DIR/self-ctor-nongeneric.rs:8:23
|
LL | impl S0 {
| ------- the inner item doesn't inherit generics from this impl, so `Self` is invalid to reference
LL | fn foo() {
LL | const C: S0 = Self(0);
| ^^^^ help: replace `Self` with the actual type: `S0`
|
= 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 #124186 <https://github.com/rust-lang/rust/issues/124186>
= note: `#[warn(self_constructor_from_outer_item)]` on by default
warning: can't reference `Self` constructor from outer item
--> $DIR/self-ctor-nongeneric.rs:12:13
|
LL | impl S0 {
| ------- the inner item doesn't inherit generics from this impl, so `Self` is invalid to reference
...
LL | Self(0)
| ^^^^ help: replace `Self` with the actual type: `S0`
|
= 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 #124186 <https://github.com/rust-lang/rust/issues/124186>
warning: 2 warnings emitted

View file

@ -0,0 +1,14 @@
struct S0<T>(T);
impl<T> S0<T> {
fn foo() {
const C: S0<i32> = Self(0);
//~^ ERROR can't reference `Self` constructor from outer item
fn bar() -> S0<i32> {
Self(0)
//~^ ERROR can't reference `Self` constructor from outer item
}
}
}
fn main() {}

View file

@ -0,0 +1,21 @@
error[E0401]: can't reference `Self` constructor from outer item
--> $DIR/self-ctor.rs:5:28
|
LL | impl<T> S0<T> {
| ------------- the inner item doesn't inherit generics from this impl, so `Self` is invalid to reference
LL | fn foo() {
LL | const C: S0<i32> = Self(0);
| ^^^^ help: replace `Self` with the actual type: `S0`
error[E0401]: can't reference `Self` constructor from outer item
--> $DIR/self-ctor.rs:8:13
|
LL | impl<T> S0<T> {
| ------------- the inner item doesn't inherit generics from this impl, so `Self` is invalid to reference
...
LL | Self(0)
| ^^^^ help: replace `Self` with the actual type: `S0`
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0401`.

View file

@ -0,0 +1,30 @@
#![feature(type_alias_impl_trait)]
//! This test used to ICE rust-lang/rust#124891
//! because we added an assertion for catching cases where opaque types get
//! registered during the processing of subtyping predicates.
type Tait = impl FnOnce() -> ();
fn reify_as_tait() -> Thunk<Tait> {
Thunk::new(|cont| cont)
//~^ ERROR: mismatched types
//~| ERROR: mismatched types
}
struct Thunk<F>(F);
impl<F> Thunk<F> {
fn new(f: F)
where
F: ContFn,
{
todo!();
}
}
trait ContFn {}
impl<F: FnOnce(Tait) -> ()> ContFn for F {}
fn main() {}

View file

@ -0,0 +1,26 @@
error[E0308]: mismatched types
--> $DIR/lazy_subtyping_of_opaques.rs:10:23
|
LL | type Tait = impl FnOnce() -> ();
| ------------------- the found opaque type
...
LL | Thunk::new(|cont| cont)
| ^^^^ expected `()`, found opaque type
|
= note: expected unit type `()`
found opaque type `Tait`
error[E0308]: mismatched types
--> $DIR/lazy_subtyping_of_opaques.rs:10:5
|
LL | fn reify_as_tait() -> Thunk<Tait> {
| ----------- expected `Thunk<_>` because of return type
LL | Thunk::new(|cont| cont)
| ^^^^^^^^^^^^^^^^^^^^^^^ expected `Thunk<_>`, found `()`
|
= note: expected struct `Thunk<_>`
found unit type `()`
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0308`.

View file

@ -389,8 +389,11 @@ exclude_labels = [
[autolabel."WG-trait-system-refactor"]
trigger_files = [
"compiler/rustc_middle/src/traits/solve",
"compiler/rustc_next_trait_solver",
"compiler/rustc_trait_selection/src/solve",
"compiler/rustc_middle/src/traits/solve"
"compiler/rustc_type_ir/src/solve",
"tests/ui/traits/next-solver",
]
[autolabel."PG-exploit-mitigations"]