Auto merge of #133728 - jhpratt:rollup-k1i60pg, r=jhpratt

Rollup of 4 pull requests

Successful merges:

 - #133589 (Remove `hir::ArrayLen`)
 - #133672 (Remove a bunch of unnecessary const stability noise)
 - #133678 (Stabilize `ptr::fn_addr_eq`)
 - #133727 (Update mailmap)

r? `@ghost`
`@rustbot` modify labels: rollup
This commit is contained in:
bors 2024-12-02 12:17:12 +00:00
commit 3bff51ea91
40 changed files with 108 additions and 232 deletions

View File

@ -254,6 +254,7 @@ Jack Huey <jack.huey@umassmed.edu> <jackh726@gmail.com>
Jacob <jacob.macritchie@gmail.com>
Jacob Greenfield <xales@naveria.com>
Jacob Pratt <jacob@jhpratt.dev> <the.z.cuber@gmail.com>
Jacob Pratt <jacob@jhpratt.dev> <jacopratt@tesla.com>
Jake Vossen <jake@vossen.dev>
Jakob Degen <jakob.e.degen@gmail.com> <jakob@degen.com>
Jakob Lautrup Nysom <jako3047@gmail.com>

View File

@ -116,7 +116,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
}
ExprKind::Repeat(expr, count) => {
let expr = self.lower_expr(expr);
let count = self.lower_array_length(count);
let count = self.lower_array_length_to_const_arg(count);
hir::ExprKind::Repeat(expr, count)
}
ExprKind::Tup(elts) => hir::ExprKind::Tup(self.lower_exprs(elts)),

View File

@ -235,8 +235,7 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> {
}
fn visit_anon_const(&mut self, constant: &'hir AnonConst) {
// FIXME: use real span?
self.insert(DUMMY_SP, constant.hir_id, Node::AnonConst(constant));
self.insert(constant.span, constant.hir_id, Node::AnonConst(constant));
self.with_parent(constant.hir_id, |this| {
intravisit::walk_anon_const(this, constant);
@ -252,8 +251,7 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> {
}
fn visit_const_arg(&mut self, const_arg: &'hir ConstArg<'hir>) {
// FIXME: use real span?
self.insert(DUMMY_SP, const_arg.hir_id, Node::ConstArg(const_arg));
self.insert(const_arg.span(), const_arg.hir_id, Node::ConstArg(const_arg));
self.with_parent(const_arg.hir_id, |this| {
intravisit::walk_const_arg(this, const_arg);
@ -387,13 +385,6 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> {
});
}
fn visit_array_length(&mut self, len: &'hir ArrayLen<'hir>) {
match len {
ArrayLen::Infer(inf) => self.insert(inf.span, inf.hir_id, Node::ArrayLenInfer(inf)),
ArrayLen::Body(..) => intravisit::walk_array_len(self, len),
}
}
fn visit_pattern_type_pattern(&mut self, p: &'hir hir::Pat<'hir>) {
self.visit_pat(p)
}

View File

@ -1257,9 +1257,10 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
}),
))
}
TyKind::Array(ty, length) => {
hir::TyKind::Array(self.lower_ty(ty, itctx), self.lower_array_length(length))
}
TyKind::Array(ty, length) => hir::TyKind::Array(
self.lower_ty(ty, itctx),
self.lower_array_length_to_const_arg(length),
),
TyKind::Typeof(expr) => hir::TyKind::Typeof(self.lower_anon_const_to_anon_const(expr)),
TyKind::TraitObject(bounds, kind) => {
let mut lifetime_bound = None;
@ -2007,14 +2008,12 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
self.expr_block(block)
}
fn lower_array_length(&mut self, c: &AnonConst) -> hir::ArrayLen<'hir> {
fn lower_array_length_to_const_arg(&mut self, c: &AnonConst) -> &'hir hir::ConstArg<'hir> {
match c.value.kind {
ExprKind::Underscore => {
if self.tcx.features().generic_arg_infer() {
hir::ArrayLen::Infer(hir::InferArg {
hir_id: self.lower_node_id(c.id),
span: self.lower_span(c.value.span),
})
let ct_kind = hir::ConstArgKind::Infer(self.lower_span(c.value.span));
self.arena.alloc(hir::ConstArg { hir_id: self.next_id(), kind: ct_kind })
} else {
feature_err(
&self.tcx.sess,
@ -2023,10 +2022,10 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
fluent_generated::ast_lowering_underscore_array_length_unstable,
)
.stash(c.value.span, StashKey::UnderscoreForArrayLengths);
hir::ArrayLen::Body(self.lower_anon_const_to_const_arg(c))
self.lower_anon_const_to_const_arg(c)
}
}
_ => hir::ArrayLen::Body(self.lower_anon_const_to_const_arg(c)),
_ => self.lower_anon_const_to_const_arg(c),
}
}

View File

@ -275,6 +275,7 @@ impl<'hir> ConstArg<'hir> {
match self.kind {
ConstArgKind::Path(path) => path.span(),
ConstArgKind::Anon(anon) => anon.span,
ConstArgKind::Infer(span) => span,
}
}
}
@ -289,6 +290,11 @@ pub enum ConstArgKind<'hir> {
/// However, in the future, we'll be using it for all of those.
Path(QPath<'hir>),
Anon(&'hir AnonConst),
/// **Note:** Not all inferred consts are represented as
/// `ConstArgKind::Infer`. In cases where it is ambiguous whether
/// a generic arg is a type or a const, inference variables are
/// represented as `GenericArg::Infer` instead.
Infer(Span),
}
#[derive(Clone, Copy, Debug, HashStable_Generic)]
@ -308,6 +314,10 @@ pub enum GenericArg<'hir> {
Lifetime(&'hir Lifetime),
Type(&'hir Ty<'hir>),
Const(&'hir ConstArg<'hir>),
/// **Note:** Inference variables are only represented as
/// `GenericArg::Infer` in cases where it is ambiguous whether
/// a generic arg is a type or a const. Otherwise, inference variables
/// are represented as `TyKind::Infer` or `ConstArgKind::Infer`.
Infer(InferArg),
}
@ -1645,29 +1655,6 @@ impl fmt::Display for ConstContext {
/// A literal.
pub type Lit = Spanned<LitKind>;
#[derive(Copy, Clone, Debug, HashStable_Generic)]
pub enum ArrayLen<'hir> {
Infer(InferArg),
Body(&'hir ConstArg<'hir>),
}
impl ArrayLen<'_> {
pub fn span(self) -> Span {
match self {
ArrayLen::Infer(arg) => arg.span,
ArrayLen::Body(body) => body.span(),
}
}
pub fn hir_id(self) -> HirId {
match self {
ArrayLen::Infer(InferArg { hir_id, .. }) | ArrayLen::Body(&ConstArg { hir_id, .. }) => {
hir_id
}
}
}
}
/// A constant (expression) that's not an item or associated item,
/// but needs its own `DefId` for type-checking, const-eval, etc.
/// These are usually found nested inside types (e.g., array lengths)
@ -2115,7 +2102,7 @@ pub enum ExprKind<'hir> {
///
/// E.g., `[1; 5]`. The first expression is the element
/// to be repeated; the second is the number of times to repeat it.
Repeat(&'hir Expr<'hir>, ArrayLen<'hir>),
Repeat(&'hir Expr<'hir>, &'hir ConstArg<'hir>),
/// A suspension point for coroutines (i.e., `yield <expr>`).
Yield(&'hir Expr<'hir>, YieldSource),
@ -2625,7 +2612,7 @@ impl<'hir> Ty<'hir> {
TyKind::Infer => true,
TyKind::Slice(ty) => ty.is_suggestable_infer_ty(),
TyKind::Array(ty, length) => {
ty.is_suggestable_infer_ty() || matches!(length, ArrayLen::Infer(..))
ty.is_suggestable_infer_ty() || matches!(length.kind, ConstArgKind::Infer(..))
}
TyKind::Tup(tys) => tys.iter().any(Self::is_suggestable_infer_ty),
TyKind::Ptr(mut_ty) | TyKind::Ref(_, mut_ty) => mut_ty.ty.is_suggestable_infer_ty(),
@ -2834,7 +2821,7 @@ pub enum TyKind<'hir> {
/// A variable length slice (i.e., `[T]`).
Slice(&'hir Ty<'hir>),
/// A fixed length array (i.e., `[T; n]`).
Array(&'hir Ty<'hir>, ArrayLen<'hir>),
Array(&'hir Ty<'hir>, &'hir ConstArg<'hir>),
/// A raw pointer (i.e., `*const T` or `*mut T`).
Ptr(MutTy<'hir>),
/// A reference (i.e., `&'a T` or `&'a mut T`).
@ -2861,6 +2848,11 @@ pub enum TyKind<'hir> {
Typeof(&'hir AnonConst),
/// `TyKind::Infer` means the type should be inferred instead of it having been
/// specified. This can appear anywhere in a type.
///
/// **Note:** Not all inferred types are represented as
/// `TyKind::Infer`. In cases where it is ambiguous whether
/// a generic arg is a type or a const, inference variables are
/// represented as `GenericArg::Infer` instead.
Infer,
/// Placeholder for a type that has failed to be defined.
Err(rustc_span::ErrorGuaranteed),
@ -3801,8 +3793,6 @@ pub enum Node<'hir> {
Crate(&'hir Mod<'hir>),
Infer(&'hir InferArg),
WherePredicate(&'hir WherePredicate<'hir>),
// FIXME: Merge into `Node::Infer`.
ArrayLenInfer(&'hir InferArg),
PreciseCapturingNonLifetimeArg(&'hir PreciseCapturingNonLifetimeArg),
// Created by query feeding
Synthetic,
@ -3856,7 +3846,6 @@ impl<'hir> Node<'hir> {
| Node::OpaqueTy(..)
| Node::Infer(..)
| Node::WherePredicate(..)
| Node::ArrayLenInfer(..)
| Node::Synthetic
| Node::Err(..) => None,
}

View File

@ -343,9 +343,6 @@ pub trait Visitor<'v>: Sized {
fn visit_pat_field(&mut self, f: &'v PatField<'v>) -> Self::Result {
walk_pat_field(self, f)
}
fn visit_array_length(&mut self, len: &'v ArrayLen<'v>) -> Self::Result {
walk_array_len(self, len)
}
fn visit_anon_const(&mut self, c: &'v AnonConst) -> Self::Result {
walk_anon_const(self, c)
}
@ -710,14 +707,6 @@ pub fn walk_pat_field<'v, V: Visitor<'v>>(visitor: &mut V, field: &'v PatField<'
visitor.visit_pat(field.pat)
}
pub fn walk_array_len<'v, V: Visitor<'v>>(visitor: &mut V, len: &'v ArrayLen<'v>) -> V::Result {
match len {
// FIXME: Use `visit_infer` here.
ArrayLen::Infer(InferArg { hir_id, span: _ }) => visitor.visit_id(*hir_id),
ArrayLen::Body(c) => visitor.visit_const_arg(c),
}
}
pub fn walk_anon_const<'v, V: Visitor<'v>>(visitor: &mut V, constant: &'v AnonConst) -> V::Result {
try_visit!(visitor.visit_id(constant.hir_id));
visitor.visit_nested_body(constant.body)
@ -739,6 +728,7 @@ pub fn walk_const_arg<'v, V: Visitor<'v>>(
match &const_arg.kind {
ConstArgKind::Path(qpath) => visitor.visit_qpath(qpath, const_arg.hir_id, qpath.span()),
ConstArgKind::Anon(anon) => visitor.visit_anon_const(*anon),
ConstArgKind::Infer(..) => V::Result::output(),
}
}
@ -753,7 +743,7 @@ pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr<'v>)
}
ExprKind::Repeat(ref element, ref count) => {
try_visit!(visitor.visit_expr(element));
try_visit!(visitor.visit_array_length(count));
try_visit!(visitor.visit_const_arg(count));
}
ExprKind::Struct(ref qpath, fields, ref optional_base) => {
try_visit!(visitor.visit_qpath(qpath, expression.hir_id, expression.span));
@ -901,7 +891,7 @@ pub fn walk_ty<'v, V: Visitor<'v>>(visitor: &mut V, typ: &'v Ty<'v>) -> V::Resul
}
TyKind::Array(ref ty, ref length) => {
try_visit!(visitor.visit_ty(ty));
try_visit!(visitor.visit_array_length(length));
try_visit!(visitor.visit_const_arg(length));
}
TyKind::TraitObject(bounds, ref lifetime, _syntax) => {
for bound in bounds {

View File

@ -151,11 +151,11 @@ impl<'v> Visitor<'v> for HirPlaceholderCollector {
_ => {}
}
}
fn visit_array_length(&mut self, length: &'v hir::ArrayLen<'v>) {
if let hir::ArrayLen::Infer(inf) = length {
self.0.push(inf.span);
fn visit_const_arg(&mut self, const_arg: &'v hir::ConstArg<'v>) {
if let hir::ConstArgKind::Infer(span) = const_arg.kind {
self.0.push(span);
}
intravisit::walk_array_len(self, length)
intravisit::walk_const_arg(self, const_arg)
}
}

View File

@ -181,7 +181,7 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics {
// expressions' count (i.e. `N` in `[x; N]`), and explicit
// `enum` discriminants (i.e. `D` in `enum Foo { Bar = D }`),
// as they shouldn't be able to cause query cycle errors.
Node::Expr(Expr { kind: ExprKind::Repeat(_, ArrayLen::Body(ct)), .. })
Node::Expr(Expr { kind: ExprKind::Repeat(_, ct), .. })
if ct.anon_const_hir_id() == Some(hir_id) =>
{
Some(parent_did)

View File

@ -145,7 +145,7 @@ fn const_arg_anon_type_of<'tcx>(tcx: TyCtxt<'tcx>, arg_hir_id: HirId, span: Span
// Easy case: arrays repeat expressions.
Node::Ty(&hir::Ty { kind: TyKind::Array(_, ref constant), .. })
| Node::Expr(&Expr { kind: ExprKind::Repeat(_, ref constant), .. })
if constant.hir_id() == arg_hir_id =>
if constant.hir_id == arg_hir_id =>
{
return tcx.types.usize;
}
@ -579,8 +579,6 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<'_
x => bug!("unexpected non-type Node::GenericParam: {:?}", x),
},
Node::ArrayLenInfer(_) => tcx.types.usize,
x => {
bug!("unexpected sort of node in type_of(): {:?}", x);
}

View File

@ -104,7 +104,7 @@ fn generic_arg_mismatch_err(
GenericArg::Type(hir::Ty { kind: hir::TyKind::Array(_, len), .. }),
GenericParamDefKind::Const { .. },
) if tcx.type_of(param.def_id).skip_binder() == tcx.types.usize => {
let snippet = sess.source_map().span_to_snippet(tcx.hir().span(len.hir_id()));
let snippet = sess.source_map().span_to_snippet(tcx.hir().span(len.hir_id));
if let Ok(snippet) = snippet {
err.span_suggestion(
arg.span(),

View File

@ -2090,6 +2090,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
format!("Const::lower_const_arg: invalid qpath {qpath:?}"),
),
hir::ConstArgKind::Anon(anon) => Const::from_anon_const(tcx, anon.def_id),
hir::ConstArgKind::Infer(span) => self.ct_infer(None, span),
}
}
@ -2310,13 +2311,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
tcx.at(span).type_of(def_id).instantiate(tcx, args)
}
hir::TyKind::Array(ty, length) => {
let length = match length {
hir::ArrayLen::Infer(inf) => self.ct_infer(None, inf.span),
hir::ArrayLen::Body(constant) => {
self.lower_const_arg(constant, FeedConstTy::No)
}
};
let length = self.lower_const_arg(length, FeedConstTy::No);
Ty::new_array_with_const_len(tcx, self.lower_ty(ty), length)
}
hir::TyKind::Typeof(e) => tcx.type_of(e.def_id).instantiate_identity(),

View File

@ -118,7 +118,6 @@ impl<'a> State<'a> {
Node::LetStmt(a) => self.print_local_decl(a),
Node::Crate(..) => panic!("cannot print Crate"),
Node::WherePredicate(pred) => self.print_where_predicate(pred),
Node::ArrayLenInfer(_) => self.word("_"),
Node::Synthetic => unreachable!(),
Node::Err(_) => self.word("/*ERROR*/"),
}
@ -315,7 +314,7 @@ impl<'a> State<'a> {
self.word("[");
self.print_type(ty);
self.word("; ");
self.print_array_length(length);
self.print_const_arg(length);
self.word("]");
}
hir::TyKind::Typeof(ref e) => {
@ -986,13 +985,6 @@ impl<'a> State<'a> {
self.print_else(elseopt)
}
fn print_array_length(&mut self, len: &hir::ArrayLen<'_>) {
match len {
hir::ArrayLen::Infer(..) => self.word("_"),
hir::ArrayLen::Body(ct) => self.print_const_arg(ct),
}
}
fn print_anon_const(&mut self, constant: &hir::AnonConst) {
self.ann.nested(self, Nested::Body(constant.body))
}
@ -1001,6 +993,7 @@ impl<'a> State<'a> {
match &const_arg.kind {
ConstArgKind::Path(qpath) => self.print_qpath(qpath, true),
ConstArgKind::Anon(anon) => self.print_anon_const(anon),
ConstArgKind::Infer(..) => self.word("_"),
}
}
@ -1073,12 +1066,12 @@ impl<'a> State<'a> {
self.end()
}
fn print_expr_repeat(&mut self, element: &hir::Expr<'_>, count: &hir::ArrayLen<'_>) {
fn print_expr_repeat(&mut self, element: &hir::Expr<'_>, count: &hir::ConstArg<'_>) {
self.ibox(INDENT_UNIT);
self.word("[");
self.print_expr(element);
self.word_space(";");
self.print_array_length(count);
self.print_const_arg(count);
self.word("]");
self.end()
}

View File

@ -19,7 +19,7 @@ use rustc_hir::def_id::DefId;
use rustc_hir::intravisit::Visitor;
use rustc_hir::lang_items::LangItem;
use rustc_hir::{ExprKind, HirId, QPath};
use rustc_hir_analysis::hir_ty_lowering::HirTyLowerer as _;
use rustc_hir_analysis::hir_ty_lowering::{FeedConstTy, HirTyLowerer as _};
use rustc_infer::infer;
use rustc_infer::infer::{DefineOpaqueTypes, InferOk};
use rustc_infer::traits::ObligationCause;
@ -425,7 +425,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
| hir::Node::Crate(_)
| hir::Node::Infer(_)
| hir::Node::WherePredicate(_)
| hir::Node::ArrayLenInfer(_)
| hir::Node::PreciseCapturingNonLifetimeArg(_)
| hir::Node::OpaqueTy(_) => {
unreachable!("no sub-expr expected for {parent_node:?}")
@ -1673,9 +1672,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
else {
return;
};
if let hir::TyKind::Array(_, length) = ty.peel_refs().kind
&& let hir::ArrayLen::Body(ct) = length
{
if let hir::TyKind::Array(_, ct) = ty.peel_refs().kind {
let span = ct.span();
self.dcx().try_steal_modify_and_emit_err(
span,
@ -1713,13 +1710,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
fn check_expr_repeat(
&self,
element: &'tcx hir::Expr<'tcx>,
count: &'tcx hir::ArrayLen<'tcx>,
count: &'tcx hir::ConstArg<'tcx>,
expected: Expectation<'tcx>,
expr: &'tcx hir::Expr<'tcx>,
) -> Ty<'tcx> {
let tcx = self.tcx;
let count_span = count.span();
let count = self.try_structurally_resolve_const(count_span, self.lower_array_length(count));
let count = self.try_structurally_resolve_const(
count_span,
self.normalize(count_span, self.lower_const_arg(count, FeedConstTy::No)),
);
if let Some(count) = count.try_to_target_usize(tcx) {
self.suggest_array_len(expr, count);

View File

@ -487,24 +487,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}
}
pub(crate) fn lower_array_length(&self, length: &hir::ArrayLen<'tcx>) -> ty::Const<'tcx> {
match length {
hir::ArrayLen::Infer(inf) => self.ct_infer(None, inf.span),
hir::ArrayLen::Body(const_arg) => {
let span = const_arg.span();
let c = self.lowerer().lower_const_arg(const_arg, FeedConstTy::No);
self.register_wf_obligation(c.into(), span, ObligationCauseCode::WellFormed(None));
self.normalize(span, c)
}
}
}
pub(crate) fn lower_const_arg(
&self,
const_arg: &'tcx hir::ConstArg<'tcx>,
param_def_id: DefId,
feed: FeedConstTy,
) -> ty::Const<'tcx> {
let ct = self.lowerer().lower_const_arg(const_arg, FeedConstTy::Param(param_def_id));
let ct = self.lowerer().lower_const_arg(const_arg, feed);
self.register_wf_obligation(
ct.into(),
self.tcx.hir().span(const_arg.hir_id),
@ -1279,7 +1267,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
self.fcx.lower_ty(ty).raw.into()
}
(GenericParamDefKind::Const { .. }, GenericArg::Const(ct)) => {
self.fcx.lower_const_arg(ct, param.def_id).into()
self.fcx.lower_const_arg(ct, FeedConstTy::Param(param.def_id)).into()
}
(GenericParamDefKind::Type { .. }, GenericArg::Infer(inf)) => {
self.fcx.ty_infer(Some(param), inf.span).into()

View File

@ -7,7 +7,7 @@ use rustc_hir_analysis::hir_ty_lowering::generics::{
check_generic_arg_count_for_call, lower_generic_args,
};
use rustc_hir_analysis::hir_ty_lowering::{
GenericArgsLowerer, HirTyLowerer, IsMethodCall, RegionInferReason,
FeedConstTy, GenericArgsLowerer, HirTyLowerer, IsMethodCall, RegionInferReason,
};
use rustc_infer::infer::{self, DefineOpaqueTypes, InferOk};
use rustc_middle::traits::{ObligationCauseCode, UnifyReceiverContext};
@ -429,7 +429,7 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
self.cfcx.lower_ty(ty).raw.into()
}
(GenericParamDefKind::Const { .. }, GenericArg::Const(ct)) => {
self.cfcx.lower_const_arg(ct, param.def_id).into()
self.cfcx.lower_const_arg(ct, FeedConstTy::Param(param.def_id)).into()
}
(GenericParamDefKind::Type { .. }, GenericArg::Infer(inf)) => {
self.cfcx.ty_infer(Some(param), inf.span).into()

View File

@ -948,7 +948,6 @@ impl<'hir> Map<'hir> {
Node::LetStmt(local) => local.span,
Node::Crate(item) => item.spans.inner_span,
Node::WherePredicate(pred) => pred.span,
Node::ArrayLenInfer(inf) => inf.span,
Node::PreciseCapturingNonLifetimeArg(param) => param.ident.span,
Node::Synthetic => unreachable!(),
Node::Err(span) => span,
@ -1226,7 +1225,6 @@ fn hir_id_to_string(map: Map<'_>, id: HirId) -> String {
}
Node::Crate(..) => String::from("(root_crate)"),
Node::WherePredicate(_) => node_str("where predicate"),
Node::ArrayLenInfer(_) => node_str("array len infer"),
Node::Synthetic => unreachable!(),
Node::Err(_) => node_str("error"),
Node::PreciseCapturingNonLifetimeArg(_param) => node_str("parameter"),

View File

@ -1837,11 +1837,10 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
};
if let Some(tykind) = tykind
&& let hir::TyKind::Array(_, length) = tykind
&& let hir::ArrayLen::Body(ct) = length
&& let Some((scalar, ty)) = sz.found.try_to_scalar()
&& ty == self.tcx.types.usize
{
let span = ct.span();
let span = length.span();
Some(TypeErrorAdditionalDiags::ConsiderSpecifyingLength {
span,
length: scalar.to_target_usize(&self.tcx).unwrap(),

View File

@ -486,7 +486,6 @@ impl<T: Ord, A: Allocator> BinaryHeap<T, A> {
/// heap.push(4);
/// ```
#[unstable(feature = "allocator_api", issue = "32838")]
#[rustc_const_unstable(feature = "const_binary_heap_new_in", issue = "125961")]
#[must_use]
pub const fn new_in(alloc: A) -> BinaryHeap<T, A> {
BinaryHeap { data: Vec::new_in(alloc) }

View File

@ -91,8 +91,6 @@
//
// Library features:
// tidy-alphabetical-start
#![cfg_attr(not(no_global_oom_handling), feature(const_alloc_error))]
#![cfg_attr(not(no_global_oom_handling), feature(const_btree_len))]
#![cfg_attr(test, feature(str_as_str))]
#![feature(alloc_layout_extra)]
#![feature(allocator_api)]
@ -107,13 +105,8 @@
#![feature(box_uninit_write)]
#![feature(clone_to_uninit)]
#![feature(coerce_unsized)]
#![feature(const_align_of_val)]
#![feature(const_box)]
#![feature(const_eval_select)]
#![feature(const_heap)]
#![feature(const_maybe_uninit_write)]
#![feature(const_size_of_val)]
#![feature(const_vec_string_slice)]
#![feature(core_intrinsics)]
#![feature(deprecated_suggestion)]
#![feature(deref_pure_trait)]
@ -170,7 +163,6 @@
#![feature(allow_internal_unstable)]
#![feature(cfg_sanitize)]
#![feature(const_precise_live_drops)]
#![feature(const_try)]
#![feature(decl_macro)]
#![feature(dropck_eyepatch)]
#![feature(fundamental)]

View File

@ -4,8 +4,6 @@
#![feature(assert_matches)]
#![feature(btree_extract_if)]
#![feature(cow_is_borrowed)]
#![feature(const_heap)]
#![feature(const_try)]
#![feature(core_intrinsics)]
#![feature(extract_if)]
#![feature(exact_size_is_empty)]

View File

@ -713,7 +713,6 @@ impl<T, const N: usize> Cell<[T; N]> {
/// let array_cell: &[Cell<i32>; 3] = cell_array.as_array_of_cells();
/// ```
#[unstable(feature = "as_array_of_cells", issue = "88248")]
#[rustc_const_unstable(feature = "as_array_of_cells", issue = "88248")]
pub const fn as_array_of_cells(&self) -> &[Cell<T>; N] {
// SAFETY: `Cell<T>` has the same memory layout as `T`.
unsafe { &*(self as *const Cell<[T; N]> as *const [Cell<T>; N]) }

View File

@ -109,23 +109,7 @@
// tidy-alphabetical-start
#![feature(array_ptr_get)]
#![feature(asm_experimental_arch)]
#![feature(const_align_of_val)]
#![feature(const_align_of_val_raw)]
#![feature(const_alloc_layout)]
#![feature(const_black_box)]
#![feature(const_eq_ignore_ascii_case)]
#![feature(const_eval_select)]
#![feature(const_heap)]
#![feature(const_nonnull_new)]
#![feature(const_ptr_sub_ptr)]
#![feature(const_raw_ptr_comparison)]
#![feature(const_size_of_val)]
#![feature(const_size_of_val_raw)]
#![feature(const_sockaddr_setters)]
#![feature(const_swap)]
#![feature(const_try)]
#![feature(const_type_id)]
#![feature(const_type_name)]
#![feature(const_typed_swap)]
#![feature(core_intrinsics)]
#![feature(coverage_attribute)]
@ -165,10 +149,7 @@
#![feature(cfg_target_has_atomic)]
#![feature(cfg_target_has_atomic_equal_alignment)]
#![feature(cfg_ub_checks)]
#![feature(const_for)]
#![feature(const_is_char_boundary)]
#![feature(const_precise_live_drops)]
#![feature(const_str_split_at)]
#![feature(const_trait_impl)]
#![feature(decl_macro)]
#![feature(deprecated_suggestion)]

View File

@ -614,7 +614,6 @@ macro_rules! nonzero_integer {
/// ```
///
#[unstable(feature = "non_zero_count_ones", issue = "120287")]
#[rustc_const_unstable(feature = "non_zero_count_ones", issue = "120287")]
#[doc(alias = "popcount")]
#[doc(alias = "popcnt")]
#[must_use = "this returns the result of the operation, \

View File

@ -3162,7 +3162,6 @@ macro_rules! uint_impl {
#[inline]
#[unstable(feature = "wrapping_next_power_of_two", issue = "32463",
reason = "needs decision on wrapping behavior")]
#[rustc_const_unstable(feature = "wrapping_next_power_of_two", issue = "32463")]
#[must_use = "this returns the result of the operation, \
without modifying the original"]
pub const fn wrapping_next_power_of_two(self) -> Self {

View File

@ -346,7 +346,6 @@ impl<T: ?Sized> *const T {
/// ```
#[inline]
#[unstable(feature = "ptr_as_uninit", issue = "75402")]
#[rustc_const_unstable(feature = "ptr_as_uninit", issue = "75402")]
pub const unsafe fn as_uninit_ref<'a>(self) -> Option<&'a MaybeUninit<T>>
where
T: Sized,
@ -1528,7 +1527,6 @@ impl<T> *const [T] {
///
/// If `N` is not exactly equal to the length of `self`, then this method returns `None`.
#[unstable(feature = "slice_as_array", issue = "133508")]
#[rustc_const_unstable(feature = "slice_as_array", issue = "133508")]
#[inline]
#[must_use]
pub const fn as_array<const N: usize>(self) -> Option<*const [T; N]> {
@ -1608,7 +1606,6 @@ impl<T> *const [T] {
/// [allocated object]: crate::ptr#allocated-object
#[inline]
#[unstable(feature = "ptr_as_uninit", issue = "75402")]
#[rustc_const_unstable(feature = "ptr_as_uninit", issue = "75402")]
pub const unsafe fn as_uninit_slice<'a>(self) -> Option<&'a [MaybeUninit<T>]> {
if self.is_null() {
None

View File

@ -2111,7 +2111,6 @@ pub fn addr_eq<T: ?Sized, U: ?Sized>(p: *const T, q: *const U) -> bool {
/// when compiled with optimization:
///
/// ```
/// # #![feature(ptr_fn_addr_eq)]
/// let f: fn(i32) -> i32 = |x| x;
/// let g: fn(i32) -> i32 = |x| x + 0; // different closure, different body
/// let h: fn(u32) -> u32 = |x| x + 0; // different signature too
@ -2136,7 +2135,6 @@ pub fn addr_eq<T: ?Sized, U: ?Sized>(p: *const T, q: *const U) -> bool {
/// # Examples
///
/// ```
/// #![feature(ptr_fn_addr_eq)]
/// use std::ptr;
///
/// fn a() { println!("a"); }
@ -2145,7 +2143,7 @@ pub fn addr_eq<T: ?Sized, U: ?Sized>(p: *const T, q: *const U) -> bool {
/// ```
///
/// [subtype]: https://doc.rust-lang.org/reference/subtyping.html
#[unstable(feature = "ptr_fn_addr_eq", issue = "129322")]
#[stable(feature = "ptr_fn_addr_eq", since = "CURRENT_RUSTC_VERSION")]
#[inline(always)]
#[must_use = "function pointer comparison produces a value"]
pub fn fn_addr_eq<T: FnPtr, U: FnPtr>(f: T, g: U) -> bool {

View File

@ -342,7 +342,6 @@ impl<T: ?Sized> *mut T {
/// ```
#[inline]
#[unstable(feature = "ptr_as_uninit", issue = "75402")]
#[rustc_const_unstable(feature = "ptr_as_uninit", issue = "75402")]
pub const unsafe fn as_uninit_ref<'a>(self) -> Option<&'a MaybeUninit<T>>
where
T: Sized,
@ -676,7 +675,6 @@ impl<T: ?Sized> *mut T {
/// the pointer is [convertible to a reference](crate::ptr#pointer-to-reference-conversion).
#[inline]
#[unstable(feature = "ptr_as_uninit", issue = "75402")]
#[rustc_const_unstable(feature = "ptr_as_uninit", issue = "75402")]
pub const unsafe fn as_uninit_mut<'a>(self) -> Option<&'a mut MaybeUninit<T>>
where
T: Sized,
@ -1762,7 +1760,6 @@ impl<T> *mut [T] {
///
/// If `N` is not exactly equal to the length of `self`, then this method returns `None`.
#[unstable(feature = "slice_as_array", issue = "133508")]
#[rustc_const_unstable(feature = "slice_as_array", issue = "133508")]
#[inline]
#[must_use]
pub const fn as_mut_array<const N: usize>(self) -> Option<*mut [T; N]> {
@ -1963,7 +1960,6 @@ impl<T> *mut [T] {
/// [allocated object]: crate::ptr#allocated-object
#[inline]
#[unstable(feature = "ptr_as_uninit", issue = "75402")]
#[rustc_const_unstable(feature = "ptr_as_uninit", issue = "75402")]
pub const unsafe fn as_uninit_slice<'a>(self) -> Option<&'a [MaybeUninit<T>]> {
if self.is_null() {
None
@ -2015,7 +2011,6 @@ impl<T> *mut [T] {
/// [allocated object]: crate::ptr#allocated-object
#[inline]
#[unstable(feature = "ptr_as_uninit", issue = "75402")]
#[rustc_const_unstable(feature = "ptr_as_uninit", issue = "75402")]
pub const unsafe fn as_uninit_slice_mut<'a>(self) -> Option<&'a mut [MaybeUninit<T>]> {
if self.is_null() {
None

View File

@ -92,6 +92,7 @@ impl<T: ?Sized> Unique<T> {
/// Creates a new `Unique` if `ptr` is non-null.
#[inline]
// rustc_const_unstable attribute can be removed when `const_nonnull_new` is stable
#[rustc_const_unstable(feature = "ptr_internals", issue = "none")]
pub const fn new(ptr: *mut T) -> Option<Self> {
if let Some(pointer) = NonNull::new(ptr) {

View File

@ -860,7 +860,6 @@ impl<T> [T] {
///
/// If `N` is not exactly equal to slice's the length of `self`, then this method returns `None`.
#[unstable(feature = "slice_as_array", issue = "133508")]
#[rustc_const_unstable(feature = "slice_as_array", issue = "133508")]
#[inline]
#[must_use]
pub const fn as_array<const N: usize>(&self) -> Option<&[T; N]> {
@ -879,7 +878,6 @@ impl<T> [T] {
///
/// If `N` is not exactly equal to the length of `self`, then this method returns `None`.
#[unstable(feature = "slice_as_array", issue = "133508")]
#[rustc_const_unstable(feature = "slice_as_array", issue = "133508")]
#[inline]
#[must_use]
pub const fn as_mut_array<const N: usize>(&mut self) -> Option<&mut [T; N]> {

View File

@ -16,7 +16,6 @@
#![feature(const_align_of_val_raw)]
#![feature(const_black_box)]
#![feature(const_eval_select)]
#![feature(const_heap)]
#![feature(const_nonnull_new)]
#![feature(const_swap)]
#![feature(const_trait_impl)]

View File

@ -22,7 +22,6 @@
// This library is copied into rust-analyzer to allow loading rustc compiled proc macros.
// Please avoid unstable features where possible to minimize the amount of changes necessary
// to make it compile with rust-analyzer on stable.
#![feature(rustc_allow_const_fn_unstable)]
#![feature(staged_api)]
#![feature(allow_internal_unstable)]
#![feature(decl_macro)]

View File

@ -409,9 +409,7 @@
//
// Only for const-ness:
// tidy-alphabetical-start
#![feature(const_collections_with_hasher)]
#![feature(io_const_error)]
#![feature(thread_local_internals)]
// tidy-alphabetical-end
//
#![default_lib_allocator]

View File

@ -290,6 +290,7 @@ pub(crate) fn clean_const<'tcx>(
ConstantKind::Path { path: qpath_to_string(qpath).into() }
}
hir::ConstArgKind::Anon(anon) => ConstantKind::Anonymous { body: anon.body },
hir::ConstArgKind::Infer(..) => ConstantKind::Infer,
}
}
@ -1803,30 +1804,27 @@ pub(crate) fn clean_ty<'tcx>(ty: &hir::Ty<'tcx>, cx: &mut DocContext<'tcx>) -> T
}
TyKind::Slice(ty) => Slice(Box::new(clean_ty(ty, cx))),
TyKind::Pat(ty, pat) => Type::Pat(Box::new(clean_ty(ty, cx)), format!("{pat:?}").into()),
TyKind::Array(ty, ref length) => {
let length = match length {
hir::ArrayLen::Infer(..) => "_".to_string(),
hir::ArrayLen::Body(const_arg) => {
// NOTE(min_const_generics): We can't use `const_eval_poly` for constants
// as we currently do not supply the parent generics to anonymous constants
// but do allow `ConstKind::Param`.
//
// `const_eval_poly` tries to first substitute generic parameters which
// results in an ICE while manually constructing the constant and using `eval`
// does nothing for `ConstKind::Param`.
TyKind::Array(ty, ref const_arg) => {
// NOTE(min_const_generics): We can't use `const_eval_poly` for constants
// as we currently do not supply the parent generics to anonymous constants
// but do allow `ConstKind::Param`.
//
// `const_eval_poly` tries to first substitute generic parameters which
// results in an ICE while manually constructing the constant and using `eval`
// does nothing for `ConstKind::Param`.
let length = match const_arg.kind {
hir::ConstArgKind::Infer(..) => "_".to_string(),
hir::ConstArgKind::Anon(hir::AnonConst { def_id, .. }) => {
let ct = lower_const_arg_for_rustdoc(cx.tcx, const_arg, FeedConstTy::No);
let typing_env = ty::TypingEnv::post_analysis(cx.tcx, *def_id);
let ct = cx.tcx.normalize_erasing_regions(typing_env, ct);
print_const(cx, ct)
}
hir::ConstArgKind::Path(..) => {
let ct = lower_const_arg_for_rustdoc(cx.tcx, const_arg, FeedConstTy::No);
let ct = if let hir::ConstArgKind::Anon(hir::AnonConst { def_id, .. }) =
const_arg.kind
{
let typing_env = ty::TypingEnv::post_analysis(cx.tcx, *def_id);
cx.tcx.normalize_erasing_regions(typing_env, ct)
} else {
ct
};
print_const(cx, ct)
}
};
Array(Box::new(clean_ty(ty, cx)), length.into())
}
TyKind::Tup(tys) => Tuple(tys.iter().map(|ty| clean_ty(ty, cx)).collect()),

View File

@ -2399,6 +2399,8 @@ pub(crate) enum ConstantKind {
Extern { def_id: DefId },
/// `const FOO: u32 = ...;`
Local { def_id: DefId, body: BodyId },
/// An inferred constant as in `[10u8; _]`.
Infer,
}
impl Constant {
@ -2424,6 +2426,7 @@ impl ConstantKind {
ConstantKind::Local { body, .. } | ConstantKind::Anonymous { body } => {
rendered_const(tcx, tcx.hir().body(body), tcx.hir().body_owner_def_id(body))
}
ConstantKind::Infer { .. } => "_".to_string(),
}
}
@ -2431,7 +2434,8 @@ impl ConstantKind {
match *self {
ConstantKind::TyConst { .. }
| ConstantKind::Path { .. }
| ConstantKind::Anonymous { .. } => None,
| ConstantKind::Anonymous { .. }
| ConstantKind::Infer => None,
ConstantKind::Extern { def_id } | ConstantKind::Local { def_id, .. } => {
print_evaluated_const(tcx, def_id, true, true)
}
@ -2442,7 +2446,8 @@ impl ConstantKind {
match *self {
ConstantKind::TyConst { .. }
| ConstantKind::Extern { .. }
| ConstantKind::Path { .. } => false,
| ConstantKind::Path { .. }
| ConstantKind::Infer => false,
ConstantKind::Local { body, .. } | ConstantKind::Anonymous { body } => {
is_literal_expr(tcx, body.hir_id)
}

View File

@ -5,7 +5,7 @@ use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::is_from_proc_macro;
use clippy_utils::macros::macro_backtrace;
use clippy_utils::source::snippet;
use rustc_hir::{ArrayLen, Expr, ExprKind, Item, ItemKind, Node};
use rustc_hir::{Expr, ExprKind, Item, ItemKind, Node};
use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::ty::layout::LayoutOf;
use rustc_middle::ty::{self, ConstKind};
@ -118,13 +118,13 @@ impl<'tcx> LateLintPass<'tcx> for LargeStackArrays {
/// Only giving help messages if the expr does not contains macro expanded codes.
fn might_be_expanded<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'tcx>) -> bool {
/// Check if the span of `ArrayLen` of a repeat expression is within the expr's span,
/// Check if the span of `ConstArg` of a repeat expression is within the expr's span,
/// if not, meaning this repeat expr is definitely from some proc-macro.
///
/// This is a fail-safe to a case where even the `is_from_proc_macro` is unable to determain the
/// correct result.
fn repeat_expr_might_be_expanded(expr: &Expr<'_>) -> bool {
let ExprKind::Repeat(_, ArrayLen::Body(len_ct)) = expr.kind else {
let ExprKind::Repeat(_, len_ct) = expr.kind else {
return false;
};
!expr.span.contains(len_ct.span())

View File

@ -3,7 +3,7 @@ use rustc_ast::LitIntType;
use rustc_ast::ast::{LitFloatType, LitKind};
use rustc_data_structures::fx::FxHashMap;
use rustc_hir::{
self as hir, ArrayLen, BindingMode, CaptureBy, Closure, ClosureKind, ConstArg, ConstArgKind, CoroutineKind,
self as hir, BindingMode, CaptureBy, Closure, ClosureKind, ConstArg, ConstArgKind, CoroutineKind,
ExprKind, FnRetTy, HirId, Lit, PatKind, QPath, StmtKind, TyKind,
};
use rustc_lint::{LateContext, LateLintPass, LintContext};
@ -278,6 +278,7 @@ impl<'a, 'tcx> PrintVisitor<'a, 'tcx> {
chain!(self, "let ConstArgKind::Anon({anon_const}) = {const_arg}.kind");
self.body(field!(anon_const.body));
},
ConstArgKind::Infer(..) => chain!(self, "let ConstArgKind::Infer(..) = {const_arg}.kind"),
}
}
@ -611,14 +612,7 @@ impl<'a, 'tcx> PrintVisitor<'a, 'tcx> {
bind!(self, value, length);
kind!("Repeat({value}, {length})");
self.expr(value);
match length.value {
ArrayLen::Infer(..) => chain!(self, "let ArrayLen::Infer(..) = length"),
ArrayLen::Body(const_arg) => {
bind!(self, const_arg);
chain!(self, "let ArrayLen::Body({const_arg}) = {length}");
self.const_arg(const_arg);
},
}
self.const_arg(length);
},
ExprKind::Err(_) => kind!("Err(_)"),
ExprKind::DropTemps(expr) => {

View File

@ -5,7 +5,7 @@ use clippy_utils::visitors::for_each_expr_without_closures;
use rustc_ast::LitKind;
use rustc_data_structures::packed::Pu128;
use rustc_errors::Applicability;
use rustc_hir::{ArrayLen, ConstArgKind, ExprKind, Node};
use rustc_hir::{ConstArgKind, ExprKind, Node};
use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::ty::Ty;
use rustc_session::declare_lint_pass;
@ -60,8 +60,7 @@ impl LateLintPass<'_> for ZeroRepeatSideEffects {
// doesn't seem as confusing as `[f(); 0]`. It would also have false positives when eg.
// the const item depends on `#[cfg]s` and has different values in different compilation
// sessions).
else if let ExprKind::Repeat(inner_expr, length) = expr.kind
&& let ArrayLen::Body(const_arg) = length
else if let ExprKind::Repeat(inner_expr, const_arg) = expr.kind
&& let ConstArgKind::Anon(anon_const) = const_arg.kind
&& let length_expr = hir_map.body(anon_const.body).value
&& !length_expr.span.from_expansion()

View File

@ -7,7 +7,7 @@ use rustc_data_structures::fx::FxHasher;
use rustc_hir::MatchSource::TryDesugar;
use rustc_hir::def::{DefKind, Res};
use rustc_hir::{
ArrayLen, AssocItemConstraint, BinOpKind, BindingMode, Block, BodyId, Closure, ConstArg, ConstArgKind, Expr,
AssocItemConstraint, BinOpKind, BindingMode, Block, BodyId, Closure, ConstArg, ConstArgKind, Expr,
ExprField, ExprKind, FnRetTy, GenericArg, GenericArgs, HirId, HirIdMap, InlineAsmOperand, LetExpr, Lifetime,
LifetimeName, Pat, PatField, PatKind, Path, PathSegment, PrimTy, QPath, Stmt, StmtKind, TraitBoundModifiers, Ty,
TyKind,
@ -266,14 +266,6 @@ impl HirEqInterExpr<'_, '_, '_> {
})
}
pub fn eq_array_length(&mut self, left: ArrayLen<'_>, right: ArrayLen<'_>) -> bool {
match (left, right) {
(ArrayLen::Infer(..), ArrayLen::Infer(..)) => true,
(ArrayLen::Body(l_ct), ArrayLen::Body(r_ct)) => self.eq_const_arg(l_ct, r_ct),
(_, _) => false,
}
}
pub fn eq_body(&mut self, left: BodyId, right: BodyId) -> bool {
// swap out TypeckResults when hashing a body
let old_maybe_typeck_results = self.inner.maybe_typeck_results.replace((
@ -383,7 +375,7 @@ impl HirEqInterExpr<'_, '_, '_> {
},
(ExprKind::Path(l), ExprKind::Path(r)) => self.eq_qpath(l, r),
(&ExprKind::Repeat(le, ll), &ExprKind::Repeat(re, rl)) => {
self.eq_expr(le, re) && self.eq_array_length(ll, rl)
self.eq_expr(le, re) && self.eq_const_arg(ll, rl)
},
(ExprKind::Ret(l), ExprKind::Ret(r)) => both(l.as_ref(), r.as_ref(), |l, r| self.eq_expr(l, r)),
(&ExprKind::Struct(l_path, lf, ref lo), &ExprKind::Struct(r_path, rf, ref ro)) => {
@ -469,8 +461,10 @@ impl HirEqInterExpr<'_, '_, '_> {
match (&left.kind, &right.kind) {
(ConstArgKind::Path(l_p), ConstArgKind::Path(r_p)) => self.eq_qpath(l_p, r_p),
(ConstArgKind::Anon(l_an), ConstArgKind::Anon(r_an)) => self.eq_body(l_an.body, r_an.body),
(ConstArgKind::Infer(..), ConstArgKind::Infer(..)) => true,
// Use explicit match for now since ConstArg is undergoing flux.
(ConstArgKind::Path(..), ConstArgKind::Anon(..)) | (ConstArgKind::Anon(..), ConstArgKind::Path(..)) => {
(ConstArgKind::Path(..), ConstArgKind::Anon(..)) | (ConstArgKind::Anon(..), ConstArgKind::Path(..))
| (ConstArgKind::Infer(..), _) | (_, ConstArgKind::Infer(..)) => {
false
},
}
@ -589,7 +583,7 @@ impl HirEqInterExpr<'_, '_, '_> {
pub fn eq_ty(&mut self, left: &Ty<'_>, right: &Ty<'_>) -> bool {
match (&left.kind, &right.kind) {
(&TyKind::Slice(l_vec), &TyKind::Slice(r_vec)) => self.eq_ty(l_vec, r_vec),
(&TyKind::Array(lt, ll), &TyKind::Array(rt, rl)) => self.eq_ty(lt, rt) && self.eq_array_length(ll, rl),
(&TyKind::Array(lt, ll), &TyKind::Array(rt, rl)) => self.eq_ty(lt, rt) && self.eq_const_arg(ll, rl),
(TyKind::Ptr(l_mut), TyKind::Ptr(r_mut)) => l_mut.mutbl == r_mut.mutbl && self.eq_ty(l_mut.ty, r_mut.ty),
(TyKind::Ref(_, l_rmut), TyKind::Ref(_, r_rmut)) => {
l_rmut.mutbl == r_rmut.mutbl && self.eq_ty(l_rmut.ty, r_rmut.ty)
@ -1008,7 +1002,7 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> {
},
ExprKind::Repeat(e, len) => {
self.hash_expr(e);
self.hash_array_length(len);
self.hash_const_arg(len);
},
ExprKind::Ret(ref e) => {
if let Some(e) = *e {
@ -1201,7 +1195,7 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> {
},
&TyKind::Array(ty, len) => {
self.hash_ty(ty);
self.hash_array_length(len);
self.hash_const_arg(len);
},
TyKind::Pat(ty, pat) => {
self.hash_ty(ty);
@ -1252,13 +1246,6 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> {
}
}
pub fn hash_array_length(&mut self, length: ArrayLen<'_>) {
match length {
ArrayLen::Infer(..) => {},
ArrayLen::Body(ct) => self.hash_const_arg(ct),
}
}
pub fn hash_body(&mut self, body_id: BodyId) {
// swap out TypeckResults when hashing a body
let old_maybe_typeck_results = self.maybe_typeck_results.replace(self.cx.tcx.typeck_body(body_id));
@ -1270,6 +1257,7 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> {
match &const_arg.kind {
ConstArgKind::Path(path) => self.hash_qpath(path),
ConstArgKind::Anon(anon) => self.hash_body(anon.body),
ConstArgKind::Infer(..) => {},
}
}

View File

@ -103,7 +103,7 @@ use rustc_hir::definitions::{DefPath, DefPathData};
use rustc_hir::hir_id::{HirIdMap, HirIdSet};
use rustc_hir::intravisit::{FnKind, Visitor, walk_expr};
use rustc_hir::{
self as hir, Arm, ArrayLen, BindingMode, Block, BlockCheckMode, Body, ByRef, Closure, ConstArgKind, ConstContext,
self as hir, Arm, BindingMode, Block, BlockCheckMode, Body, ByRef, Closure, ConstArgKind, ConstContext,
Destination, Expr, ExprField, ExprKind, FnDecl, FnRetTy, GenericArgs, HirId, Impl, ImplItem, ImplItemKind,
ImplItemRef, Item, ItemKind, LangItem, LetStmt, MatchSource, Mutability, Node, OwnerId, OwnerNode, Param, Pat,
PatKind, Path, PathSegment, PrimTy, QPath, Stmt, StmtKind, TraitItem, TraitItemKind, TraitItemRef, TraitRef,
@ -910,7 +910,7 @@ pub fn is_default_equivalent(cx: &LateContext<'_>, e: &Expr<'_>) -> bool {
_ => false,
},
ExprKind::Tup(items) | ExprKind::Array(items) => items.iter().all(|x| is_default_equivalent(cx, x)),
ExprKind::Repeat(x, ArrayLen::Body(len)) => {
ExprKind::Repeat(x, len) => {
if let ConstArgKind::Anon(anon_const) = len.kind
&& let ExprKind::Lit(const_lit) = cx.tcx.hir().body(anon_const.body).value.kind
&& let LitKind::Int(v, _) = const_lit.node
@ -940,7 +940,7 @@ fn is_default_equivalent_from(cx: &LateContext<'_>, from_func: &Expr<'_>, arg: &
..
}) => return sym.is_empty() && is_path_lang_item(cx, ty, LangItem::String),
ExprKind::Array([]) => return is_path_diagnostic_item(cx, ty, sym::Vec),
ExprKind::Repeat(_, ArrayLen::Body(len)) => {
ExprKind::Repeat(_, len) => {
if let ConstArgKind::Anon(anon_const) = len.kind
&& let ExprKind::Lit(const_lit) = cx.tcx.hir().body(anon_const.body).value.kind
&& let LitKind::Int(v, _) = const_lit.node

View File

@ -1,8 +1,7 @@
if let ExprKind::Repeat(value, length) = expr.kind
&& let ExprKind::Lit(ref lit) = value.kind
&& let LitKind::Int(1, LitIntType::Unsigned(UintTy::U8)) = lit.node
&& let ArrayLen::Body(const_arg) = length
&& let ConstArgKind::Anon(anon_const) = const_arg.kind
&& let ConstArgKind::Anon(anon_const) = length.kind
&& expr1 = &cx.tcx.hir().body(anon_const.body).value
&& let ExprKind::Lit(ref lit1) = expr1.kind
&& let LitKind::Int(5, LitIntType::Unsuffixed) = lit1.node