1
Fork 0

Rollup merge of #133589 - voidc:remove-array-len, r=boxyuwu

Remove `hir::ArrayLen`

This refactoring removes `hir::ArrayLen`, replacing it with `hir::ConstArg`. To represent inferred array lengths (previously `hir::ArrayLen::Infer`), a new variant `ConstArgKind::Infer` is added.

r? `@BoxyUwU`
This commit is contained in:
Jacob Pratt 2024-12-01 22:10:23 -05:00 committed by GitHub
commit 811eaebf7e
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
24 changed files with 105 additions and 182 deletions

View file

@ -116,7 +116,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
} }
ExprKind::Repeat(expr, count) => { ExprKind::Repeat(expr, count) => {
let expr = self.lower_expr(expr); 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) hir::ExprKind::Repeat(expr, count)
} }
ExprKind::Tup(elts) => hir::ExprKind::Tup(self.lower_exprs(elts)), 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) { fn visit_anon_const(&mut self, constant: &'hir AnonConst) {
// FIXME: use real span? self.insert(constant.span, constant.hir_id, Node::AnonConst(constant));
self.insert(DUMMY_SP, constant.hir_id, Node::AnonConst(constant));
self.with_parent(constant.hir_id, |this| { self.with_parent(constant.hir_id, |this| {
intravisit::walk_anon_const(this, constant); 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>) { fn visit_const_arg(&mut self, const_arg: &'hir ConstArg<'hir>) {
// FIXME: use real span? self.insert(const_arg.span(), const_arg.hir_id, Node::ConstArg(const_arg));
self.insert(DUMMY_SP, const_arg.hir_id, Node::ConstArg(const_arg));
self.with_parent(const_arg.hir_id, |this| { self.with_parent(const_arg.hir_id, |this| {
intravisit::walk_const_arg(this, const_arg); 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>) { fn visit_pattern_type_pattern(&mut self, p: &'hir hir::Pat<'hir>) {
self.visit_pat(p) self.visit_pat(p)
} }

View file

@ -1257,9 +1257,10 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
}), }),
)) ))
} }
TyKind::Array(ty, length) => { TyKind::Array(ty, length) => hir::TyKind::Array(
hir::TyKind::Array(self.lower_ty(ty, itctx), self.lower_array_length(length)) 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::Typeof(expr) => hir::TyKind::Typeof(self.lower_anon_const_to_anon_const(expr)),
TyKind::TraitObject(bounds, kind) => { TyKind::TraitObject(bounds, kind) => {
let mut lifetime_bound = None; let mut lifetime_bound = None;
@ -2007,14 +2008,12 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
self.expr_block(block) 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 { match c.value.kind {
ExprKind::Underscore => { ExprKind::Underscore => {
if self.tcx.features().generic_arg_infer() { if self.tcx.features().generic_arg_infer() {
hir::ArrayLen::Infer(hir::InferArg { let ct_kind = hir::ConstArgKind::Infer(self.lower_span(c.value.span));
hir_id: self.lower_node_id(c.id), self.arena.alloc(hir::ConstArg { hir_id: self.next_id(), kind: ct_kind })
span: self.lower_span(c.value.span),
})
} else { } else {
feature_err( feature_err(
&self.tcx.sess, &self.tcx.sess,
@ -2023,10 +2022,10 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
fluent_generated::ast_lowering_underscore_array_length_unstable, fluent_generated::ast_lowering_underscore_array_length_unstable,
) )
.stash(c.value.span, StashKey::UnderscoreForArrayLengths); .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 { match self.kind {
ConstArgKind::Path(path) => path.span(), ConstArgKind::Path(path) => path.span(),
ConstArgKind::Anon(anon) => anon.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. /// However, in the future, we'll be using it for all of those.
Path(QPath<'hir>), Path(QPath<'hir>),
Anon(&'hir AnonConst), 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)] #[derive(Clone, Copy, Debug, HashStable_Generic)]
@ -308,6 +314,10 @@ pub enum GenericArg<'hir> {
Lifetime(&'hir Lifetime), Lifetime(&'hir Lifetime),
Type(&'hir Ty<'hir>), Type(&'hir Ty<'hir>),
Const(&'hir ConstArg<'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), Infer(InferArg),
} }
@ -1645,29 +1655,6 @@ impl fmt::Display for ConstContext {
/// A literal. /// A literal.
pub type Lit = Spanned<LitKind>; 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, /// A constant (expression) that's not an item or associated item,
/// but needs its own `DefId` for type-checking, const-eval, etc. /// but needs its own `DefId` for type-checking, const-eval, etc.
/// These are usually found nested inside types (e.g., array lengths) /// 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 /// E.g., `[1; 5]`. The first expression is the element
/// to be repeated; the second is the number of times to repeat it. /// 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>`). /// A suspension point for coroutines (i.e., `yield <expr>`).
Yield(&'hir Expr<'hir>, YieldSource), Yield(&'hir Expr<'hir>, YieldSource),
@ -2625,7 +2612,7 @@ impl<'hir> Ty<'hir> {
TyKind::Infer => true, TyKind::Infer => true,
TyKind::Slice(ty) => ty.is_suggestable_infer_ty(), TyKind::Slice(ty) => ty.is_suggestable_infer_ty(),
TyKind::Array(ty, length) => { 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::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(), 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]`). /// A variable length slice (i.e., `[T]`).
Slice(&'hir Ty<'hir>), Slice(&'hir Ty<'hir>),
/// A fixed length array (i.e., `[T; n]`). /// 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`). /// A raw pointer (i.e., `*const T` or `*mut T`).
Ptr(MutTy<'hir>), Ptr(MutTy<'hir>),
/// A reference (i.e., `&'a T` or `&'a mut T`). /// A reference (i.e., `&'a T` or `&'a mut T`).
@ -2861,6 +2848,11 @@ pub enum TyKind<'hir> {
Typeof(&'hir AnonConst), Typeof(&'hir AnonConst),
/// `TyKind::Infer` means the type should be inferred instead of it having been /// `TyKind::Infer` means the type should be inferred instead of it having been
/// specified. This can appear anywhere in a type. /// 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, Infer,
/// Placeholder for a type that has failed to be defined. /// Placeholder for a type that has failed to be defined.
Err(rustc_span::ErrorGuaranteed), Err(rustc_span::ErrorGuaranteed),
@ -3801,8 +3793,6 @@ pub enum Node<'hir> {
Crate(&'hir Mod<'hir>), Crate(&'hir Mod<'hir>),
Infer(&'hir InferArg), Infer(&'hir InferArg),
WherePredicate(&'hir WherePredicate<'hir>), WherePredicate(&'hir WherePredicate<'hir>),
// FIXME: Merge into `Node::Infer`.
ArrayLenInfer(&'hir InferArg),
PreciseCapturingNonLifetimeArg(&'hir PreciseCapturingNonLifetimeArg), PreciseCapturingNonLifetimeArg(&'hir PreciseCapturingNonLifetimeArg),
// Created by query feeding // Created by query feeding
Synthetic, Synthetic,
@ -3856,7 +3846,6 @@ impl<'hir> Node<'hir> {
| Node::OpaqueTy(..) | Node::OpaqueTy(..)
| Node::Infer(..) | Node::Infer(..)
| Node::WherePredicate(..) | Node::WherePredicate(..)
| Node::ArrayLenInfer(..)
| Node::Synthetic | Node::Synthetic
| Node::Err(..) => None, | 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 { fn visit_pat_field(&mut self, f: &'v PatField<'v>) -> Self::Result {
walk_pat_field(self, f) 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 { fn visit_anon_const(&mut self, c: &'v AnonConst) -> Self::Result {
walk_anon_const(self, c) 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) 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 { 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)); try_visit!(visitor.visit_id(constant.hir_id));
visitor.visit_nested_body(constant.body) visitor.visit_nested_body(constant.body)
@ -739,6 +728,7 @@ pub fn walk_const_arg<'v, V: Visitor<'v>>(
match &const_arg.kind { match &const_arg.kind {
ConstArgKind::Path(qpath) => visitor.visit_qpath(qpath, const_arg.hir_id, qpath.span()), ConstArgKind::Path(qpath) => visitor.visit_qpath(qpath, const_arg.hir_id, qpath.span()),
ConstArgKind::Anon(anon) => visitor.visit_anon_const(*anon), 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) => { ExprKind::Repeat(ref element, ref count) => {
try_visit!(visitor.visit_expr(element)); 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) => { ExprKind::Struct(ref qpath, fields, ref optional_base) => {
try_visit!(visitor.visit_qpath(qpath, expression.hir_id, expression.span)); 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) => { TyKind::Array(ref ty, ref length) => {
try_visit!(visitor.visit_ty(ty)); 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) => { TyKind::TraitObject(bounds, ref lifetime, _syntax) => {
for bound in bounds { 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>) { fn visit_const_arg(&mut self, const_arg: &'v hir::ConstArg<'v>) {
if let hir::ArrayLen::Infer(inf) = length { if let hir::ConstArgKind::Infer(span) = const_arg.kind {
self.0.push(inf.span); 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 // expressions' count (i.e. `N` in `[x; N]`), and explicit
// `enum` discriminants (i.e. `D` in `enum Foo { Bar = D }`), // `enum` discriminants (i.e. `D` in `enum Foo { Bar = D }`),
// as they shouldn't be able to cause query cycle errors. // 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) => if ct.anon_const_hir_id() == Some(hir_id) =>
{ {
Some(parent_did) 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. // Easy case: arrays repeat expressions.
Node::Ty(&hir::Ty { kind: TyKind::Array(_, ref constant), .. }) Node::Ty(&hir::Ty { kind: TyKind::Array(_, ref constant), .. })
| Node::Expr(&Expr { kind: ExprKind::Repeat(_, 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; 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), x => bug!("unexpected non-type Node::GenericParam: {:?}", x),
}, },
Node::ArrayLenInfer(_) => tcx.types.usize,
x => { x => {
bug!("unexpected sort of node in type_of(): {:?}", 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), .. }), GenericArg::Type(hir::Ty { kind: hir::TyKind::Array(_, len), .. }),
GenericParamDefKind::Const { .. }, GenericParamDefKind::Const { .. },
) if tcx.type_of(param.def_id).skip_binder() == tcx.types.usize => { ) 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 { if let Ok(snippet) = snippet {
err.span_suggestion( err.span_suggestion(
arg.span(), arg.span(),

View file

@ -2090,6 +2090,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
format!("Const::lower_const_arg: invalid qpath {qpath:?}"), format!("Const::lower_const_arg: invalid qpath {qpath:?}"),
), ),
hir::ConstArgKind::Anon(anon) => Const::from_anon_const(tcx, anon.def_id), 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) tcx.at(span).type_of(def_id).instantiate(tcx, args)
} }
hir::TyKind::Array(ty, length) => { hir::TyKind::Array(ty, length) => {
let length = match length { let length = self.lower_const_arg(length, FeedConstTy::No);
hir::ArrayLen::Infer(inf) => self.ct_infer(None, inf.span),
hir::ArrayLen::Body(constant) => {
self.lower_const_arg(constant, FeedConstTy::No)
}
};
Ty::new_array_with_const_len(tcx, self.lower_ty(ty), length) Ty::new_array_with_const_len(tcx, self.lower_ty(ty), length)
} }
hir::TyKind::Typeof(e) => tcx.type_of(e.def_id).instantiate_identity(), 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::LetStmt(a) => self.print_local_decl(a),
Node::Crate(..) => panic!("cannot print Crate"), Node::Crate(..) => panic!("cannot print Crate"),
Node::WherePredicate(pred) => self.print_where_predicate(pred), Node::WherePredicate(pred) => self.print_where_predicate(pred),
Node::ArrayLenInfer(_) => self.word("_"),
Node::Synthetic => unreachable!(), Node::Synthetic => unreachable!(),
Node::Err(_) => self.word("/*ERROR*/"), Node::Err(_) => self.word("/*ERROR*/"),
} }
@ -315,7 +314,7 @@ impl<'a> State<'a> {
self.word("["); self.word("[");
self.print_type(ty); self.print_type(ty);
self.word("; "); self.word("; ");
self.print_array_length(length); self.print_const_arg(length);
self.word("]"); self.word("]");
} }
hir::TyKind::Typeof(ref e) => { hir::TyKind::Typeof(ref e) => {
@ -986,13 +985,6 @@ impl<'a> State<'a> {
self.print_else(elseopt) 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) { fn print_anon_const(&mut self, constant: &hir::AnonConst) {
self.ann.nested(self, Nested::Body(constant.body)) self.ann.nested(self, Nested::Body(constant.body))
} }
@ -1001,6 +993,7 @@ impl<'a> State<'a> {
match &const_arg.kind { match &const_arg.kind {
ConstArgKind::Path(qpath) => self.print_qpath(qpath, true), ConstArgKind::Path(qpath) => self.print_qpath(qpath, true),
ConstArgKind::Anon(anon) => self.print_anon_const(anon), ConstArgKind::Anon(anon) => self.print_anon_const(anon),
ConstArgKind::Infer(..) => self.word("_"),
} }
} }
@ -1073,12 +1066,12 @@ impl<'a> State<'a> {
self.end() 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.ibox(INDENT_UNIT);
self.word("["); self.word("[");
self.print_expr(element); self.print_expr(element);
self.word_space(";"); self.word_space(";");
self.print_array_length(count); self.print_const_arg(count);
self.word("]"); self.word("]");
self.end() self.end()
} }

View file

@ -19,7 +19,7 @@ use rustc_hir::def_id::DefId;
use rustc_hir::intravisit::Visitor; use rustc_hir::intravisit::Visitor;
use rustc_hir::lang_items::LangItem; use rustc_hir::lang_items::LangItem;
use rustc_hir::{ExprKind, HirId, QPath}; 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;
use rustc_infer::infer::{DefineOpaqueTypes, InferOk}; use rustc_infer::infer::{DefineOpaqueTypes, InferOk};
use rustc_infer::traits::ObligationCause; use rustc_infer::traits::ObligationCause;
@ -425,7 +425,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
| hir::Node::Crate(_) | hir::Node::Crate(_)
| hir::Node::Infer(_) | hir::Node::Infer(_)
| hir::Node::WherePredicate(_) | hir::Node::WherePredicate(_)
| hir::Node::ArrayLenInfer(_)
| hir::Node::PreciseCapturingNonLifetimeArg(_) | hir::Node::PreciseCapturingNonLifetimeArg(_)
| hir::Node::OpaqueTy(_) => { | hir::Node::OpaqueTy(_) => {
unreachable!("no sub-expr expected for {parent_node:?}") unreachable!("no sub-expr expected for {parent_node:?}")
@ -1673,9 +1672,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
else { else {
return; return;
}; };
if let hir::TyKind::Array(_, length) = ty.peel_refs().kind if let hir::TyKind::Array(_, ct) = ty.peel_refs().kind {
&& let hir::ArrayLen::Body(ct) = length
{
let span = ct.span(); let span = ct.span();
self.dcx().try_steal_modify_and_emit_err( self.dcx().try_steal_modify_and_emit_err(
span, span,
@ -1713,13 +1710,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
fn check_expr_repeat( fn check_expr_repeat(
&self, &self,
element: &'tcx hir::Expr<'tcx>, element: &'tcx hir::Expr<'tcx>,
count: &'tcx hir::ArrayLen<'tcx>, count: &'tcx hir::ConstArg<'tcx>,
expected: Expectation<'tcx>, expected: Expectation<'tcx>,
expr: &'tcx hir::Expr<'tcx>, expr: &'tcx hir::Expr<'tcx>,
) -> Ty<'tcx> { ) -> Ty<'tcx> {
let tcx = self.tcx; let tcx = self.tcx;
let count_span = count.span(); 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) { if let Some(count) = count.try_to_target_usize(tcx) {
self.suggest_array_len(expr, count); 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( pub(crate) fn lower_const_arg(
&self, &self,
const_arg: &'tcx hir::ConstArg<'tcx>, const_arg: &'tcx hir::ConstArg<'tcx>,
param_def_id: DefId, feed: FeedConstTy,
) -> ty::Const<'tcx> { ) -> 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( self.register_wf_obligation(
ct.into(), ct.into(),
self.tcx.hir().span(const_arg.hir_id), 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() self.fcx.lower_ty(ty).raw.into()
} }
(GenericParamDefKind::Const { .. }, GenericArg::Const(ct)) => { (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)) => { (GenericParamDefKind::Type { .. }, GenericArg::Infer(inf)) => {
self.fcx.ty_infer(Some(param), inf.span).into() 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, check_generic_arg_count_for_call, lower_generic_args,
}; };
use rustc_hir_analysis::hir_ty_lowering::{ 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_infer::infer::{self, DefineOpaqueTypes, InferOk};
use rustc_middle::traits::{ObligationCauseCode, UnifyReceiverContext}; use rustc_middle::traits::{ObligationCauseCode, UnifyReceiverContext};
@ -429,7 +429,7 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
self.cfcx.lower_ty(ty).raw.into() self.cfcx.lower_ty(ty).raw.into()
} }
(GenericParamDefKind::Const { .. }, GenericArg::Const(ct)) => { (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)) => { (GenericParamDefKind::Type { .. }, GenericArg::Infer(inf)) => {
self.cfcx.ty_infer(Some(param), inf.span).into() 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::LetStmt(local) => local.span,
Node::Crate(item) => item.spans.inner_span, Node::Crate(item) => item.spans.inner_span,
Node::WherePredicate(pred) => pred.span, Node::WherePredicate(pred) => pred.span,
Node::ArrayLenInfer(inf) => inf.span,
Node::PreciseCapturingNonLifetimeArg(param) => param.ident.span, Node::PreciseCapturingNonLifetimeArg(param) => param.ident.span,
Node::Synthetic => unreachable!(), Node::Synthetic => unreachable!(),
Node::Err(span) => span, 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::Crate(..) => String::from("(root_crate)"),
Node::WherePredicate(_) => node_str("where predicate"), Node::WherePredicate(_) => node_str("where predicate"),
Node::ArrayLenInfer(_) => node_str("array len infer"),
Node::Synthetic => unreachable!(), Node::Synthetic => unreachable!(),
Node::Err(_) => node_str("error"), Node::Err(_) => node_str("error"),
Node::PreciseCapturingNonLifetimeArg(_param) => node_str("parameter"), Node::PreciseCapturingNonLifetimeArg(_param) => node_str("parameter"),

View file

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

View file

@ -290,6 +290,7 @@ pub(crate) fn clean_const<'tcx>(
ConstantKind::Path { path: qpath_to_string(qpath).into() } ConstantKind::Path { path: qpath_to_string(qpath).into() }
} }
hir::ConstArgKind::Anon(anon) => ConstantKind::Anonymous { body: anon.body }, hir::ConstArgKind::Anon(anon) => ConstantKind::Anonymous { body: anon.body },
hir::ConstArgKind::Infer(..) => ConstantKind::Infer,
} }
} }
@ -1803,10 +1804,7 @@ 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::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::Pat(ty, pat) => Type::Pat(Box::new(clean_ty(ty, cx)), format!("{pat:?}").into()),
TyKind::Array(ty, ref length) => { TyKind::Array(ty, ref const_arg) => {
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 // 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 // as we currently do not supply the parent generics to anonymous constants
// but do allow `ConstKind::Param`. // but do allow `ConstKind::Param`.
@ -1814,19 +1812,19 @@ pub(crate) fn clean_ty<'tcx>(ty: &hir::Ty<'tcx>, cx: &mut DocContext<'tcx>) -> T
// `const_eval_poly` tries to first substitute generic parameters which // `const_eval_poly` tries to first substitute generic parameters which
// results in an ICE while manually constructing the constant and using `eval` // results in an ICE while manually constructing the constant and using `eval`
// does nothing for `ConstKind::Param`. // 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 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); let typing_env = ty::TypingEnv::post_analysis(cx.tcx, *def_id);
cx.tcx.normalize_erasing_regions(typing_env, ct) let ct = cx.tcx.normalize_erasing_regions(typing_env, ct);
} else { print_const(cx, ct)
ct }
}; hir::ConstArgKind::Path(..) => {
let ct = lower_const_arg_for_rustdoc(cx.tcx, const_arg, FeedConstTy::No);
print_const(cx, ct) print_const(cx, ct)
} }
}; };
Array(Box::new(clean_ty(ty, cx)), length.into()) Array(Box::new(clean_ty(ty, cx)), length.into())
} }
TyKind::Tup(tys) => Tuple(tys.iter().map(|ty| clean_ty(ty, cx)).collect()), 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 }, Extern { def_id: DefId },
/// `const FOO: u32 = ...;` /// `const FOO: u32 = ...;`
Local { def_id: DefId, body: BodyId }, Local { def_id: DefId, body: BodyId },
/// An inferred constant as in `[10u8; _]`.
Infer,
} }
impl Constant { impl Constant {
@ -2424,6 +2426,7 @@ impl ConstantKind {
ConstantKind::Local { body, .. } | ConstantKind::Anonymous { body } => { ConstantKind::Local { body, .. } | ConstantKind::Anonymous { body } => {
rendered_const(tcx, tcx.hir().body(body), tcx.hir().body_owner_def_id(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 { match *self {
ConstantKind::TyConst { .. } ConstantKind::TyConst { .. }
| ConstantKind::Path { .. } | ConstantKind::Path { .. }
| ConstantKind::Anonymous { .. } => None, | ConstantKind::Anonymous { .. }
| ConstantKind::Infer => None,
ConstantKind::Extern { def_id } | ConstantKind::Local { def_id, .. } => { ConstantKind::Extern { def_id } | ConstantKind::Local { def_id, .. } => {
print_evaluated_const(tcx, def_id, true, true) print_evaluated_const(tcx, def_id, true, true)
} }
@ -2442,7 +2446,8 @@ impl ConstantKind {
match *self { match *self {
ConstantKind::TyConst { .. } ConstantKind::TyConst { .. }
| ConstantKind::Extern { .. } | ConstantKind::Extern { .. }
| ConstantKind::Path { .. } => false, | ConstantKind::Path { .. }
| ConstantKind::Infer => false,
ConstantKind::Local { body, .. } | ConstantKind::Anonymous { body } => { ConstantKind::Local { body, .. } | ConstantKind::Anonymous { body } => {
is_literal_expr(tcx, body.hir_id) 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::is_from_proc_macro;
use clippy_utils::macros::macro_backtrace; use clippy_utils::macros::macro_backtrace;
use clippy_utils::source::snippet; 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_lint::{LateContext, LateLintPass};
use rustc_middle::ty::layout::LayoutOf; use rustc_middle::ty::layout::LayoutOf;
use rustc_middle::ty::{self, ConstKind}; 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. /// 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 { 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. /// 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 /// This is a fail-safe to a case where even the `is_from_proc_macro` is unable to determain the
/// correct result. /// correct result.
fn repeat_expr_might_be_expanded(expr: &Expr<'_>) -> bool { 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; return false;
}; };
!expr.span.contains(len_ct.span()) !expr.span.contains(len_ct.span())

View file

@ -3,7 +3,7 @@ use rustc_ast::LitIntType;
use rustc_ast::ast::{LitFloatType, LitKind}; use rustc_ast::ast::{LitFloatType, LitKind};
use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::fx::FxHashMap;
use rustc_hir::{ 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, ExprKind, FnRetTy, HirId, Lit, PatKind, QPath, StmtKind, TyKind,
}; };
use rustc_lint::{LateContext, LateLintPass, LintContext}; 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"); chain!(self, "let ConstArgKind::Anon({anon_const}) = {const_arg}.kind");
self.body(field!(anon_const.body)); 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); bind!(self, value, length);
kind!("Repeat({value}, {length})"); kind!("Repeat({value}, {length})");
self.expr(value); self.expr(value);
match length.value { self.const_arg(length);
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);
},
}
}, },
ExprKind::Err(_) => kind!("Err(_)"), ExprKind::Err(_) => kind!("Err(_)"),
ExprKind::DropTemps(expr) => { ExprKind::DropTemps(expr) => {

View file

@ -5,7 +5,7 @@ use clippy_utils::visitors::for_each_expr_without_closures;
use rustc_ast::LitKind; use rustc_ast::LitKind;
use rustc_data_structures::packed::Pu128; use rustc_data_structures::packed::Pu128;
use rustc_errors::Applicability; use rustc_errors::Applicability;
use rustc_hir::{ArrayLen, ConstArgKind, ExprKind, Node}; use rustc_hir::{ConstArgKind, ExprKind, Node};
use rustc_lint::{LateContext, LateLintPass}; use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::ty::Ty; use rustc_middle::ty::Ty;
use rustc_session::declare_lint_pass; 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. // 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 // the const item depends on `#[cfg]s` and has different values in different compilation
// sessions). // sessions).
else if let ExprKind::Repeat(inner_expr, length) = expr.kind else if let ExprKind::Repeat(inner_expr, const_arg) = expr.kind
&& let ArrayLen::Body(const_arg) = length
&& let ConstArgKind::Anon(anon_const) = const_arg.kind && let ConstArgKind::Anon(anon_const) = const_arg.kind
&& let length_expr = hir_map.body(anon_const.body).value && let length_expr = hir_map.body(anon_const.body).value
&& !length_expr.span.from_expansion() && !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::MatchSource::TryDesugar;
use rustc_hir::def::{DefKind, Res}; use rustc_hir::def::{DefKind, Res};
use rustc_hir::{ 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, ExprField, ExprKind, FnRetTy, GenericArg, GenericArgs, HirId, HirIdMap, InlineAsmOperand, LetExpr, Lifetime,
LifetimeName, Pat, PatField, PatKind, Path, PathSegment, PrimTy, QPath, Stmt, StmtKind, TraitBoundModifiers, Ty, LifetimeName, Pat, PatField, PatKind, Path, PathSegment, PrimTy, QPath, Stmt, StmtKind, TraitBoundModifiers, Ty,
TyKind, 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 { pub fn eq_body(&mut self, left: BodyId, right: BodyId) -> bool {
// swap out TypeckResults when hashing a body // swap out TypeckResults when hashing a body
let old_maybe_typeck_results = self.inner.maybe_typeck_results.replace(( 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::Path(l), ExprKind::Path(r)) => self.eq_qpath(l, r),
(&ExprKind::Repeat(le, ll), &ExprKind::Repeat(re, rl)) => { (&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::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)) => { (&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) { match (&left.kind, &right.kind) {
(ConstArgKind::Path(l_p), ConstArgKind::Path(r_p)) => self.eq_qpath(l_p, r_p), (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::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. // 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 false
}, },
} }
@ -589,7 +583,7 @@ impl HirEqInterExpr<'_, '_, '_> {
pub fn eq_ty(&mut self, left: &Ty<'_>, right: &Ty<'_>) -> bool { pub fn eq_ty(&mut self, left: &Ty<'_>, right: &Ty<'_>) -> bool {
match (&left.kind, &right.kind) { match (&left.kind, &right.kind) {
(&TyKind::Slice(l_vec), &TyKind::Slice(r_vec)) => self.eq_ty(l_vec, r_vec), (&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::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)) => { (TyKind::Ref(_, l_rmut), TyKind::Ref(_, r_rmut)) => {
l_rmut.mutbl == r_rmut.mutbl && self.eq_ty(l_rmut.ty, r_rmut.ty) 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) => { ExprKind::Repeat(e, len) => {
self.hash_expr(e); self.hash_expr(e);
self.hash_array_length(len); self.hash_const_arg(len);
}, },
ExprKind::Ret(ref e) => { ExprKind::Ret(ref e) => {
if let Some(e) = *e { if let Some(e) = *e {
@ -1201,7 +1195,7 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> {
}, },
&TyKind::Array(ty, len) => { &TyKind::Array(ty, len) => {
self.hash_ty(ty); self.hash_ty(ty);
self.hash_array_length(len); self.hash_const_arg(len);
}, },
TyKind::Pat(ty, pat) => { TyKind::Pat(ty, pat) => {
self.hash_ty(ty); 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) { pub fn hash_body(&mut self, body_id: BodyId) {
// swap out TypeckResults when hashing a body // swap out TypeckResults when hashing a body
let old_maybe_typeck_results = self.maybe_typeck_results.replace(self.cx.tcx.typeck_body(body_id)); 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 { match &const_arg.kind {
ConstArgKind::Path(path) => self.hash_qpath(path), ConstArgKind::Path(path) => self.hash_qpath(path),
ConstArgKind::Anon(anon) => self.hash_body(anon.body), 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::hir_id::{HirIdMap, HirIdSet};
use rustc_hir::intravisit::{FnKind, Visitor, walk_expr}; use rustc_hir::intravisit::{FnKind, Visitor, walk_expr};
use rustc_hir::{ 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, Destination, Expr, ExprField, ExprKind, FnDecl, FnRetTy, GenericArgs, HirId, Impl, ImplItem, ImplItemKind,
ImplItemRef, Item, ItemKind, LangItem, LetStmt, MatchSource, Mutability, Node, OwnerId, OwnerNode, Param, Pat, ImplItemRef, Item, ItemKind, LangItem, LetStmt, MatchSource, Mutability, Node, OwnerId, OwnerNode, Param, Pat,
PatKind, Path, PathSegment, PrimTy, QPath, Stmt, StmtKind, TraitItem, TraitItemKind, TraitItemRef, TraitRef, 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, _ => false,
}, },
ExprKind::Tup(items) | ExprKind::Array(items) => items.iter().all(|x| is_default_equivalent(cx, x)), 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 if let ConstArgKind::Anon(anon_const) = len.kind
&& let ExprKind::Lit(const_lit) = cx.tcx.hir().body(anon_const.body).value.kind && let ExprKind::Lit(const_lit) = cx.tcx.hir().body(anon_const.body).value.kind
&& let LitKind::Int(v, _) = const_lit.node && 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), }) => return sym.is_empty() && is_path_lang_item(cx, ty, LangItem::String),
ExprKind::Array([]) => return is_path_diagnostic_item(cx, ty, sym::Vec), 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 if let ConstArgKind::Anon(anon_const) = len.kind
&& let ExprKind::Lit(const_lit) = cx.tcx.hir().body(anon_const.body).value.kind && let ExprKind::Lit(const_lit) = cx.tcx.hir().body(anon_const.body).value.kind
&& let LitKind::Int(v, _) = const_lit.node && let LitKind::Int(v, _) = const_lit.node

View file

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