Rollup merge of #91907 - lcnr:const-arg-infer, r=BoxyUwU

Allow `_` as the length of array types and repeat expressions

r? `@BoxyUwU` cc `@varkor`
This commit is contained in:
Matthias Krüger 2022-01-04 21:23:06 +01:00 committed by GitHub
commit d7a60337fc
6 changed files with 50 additions and 20 deletions

View file

@ -59,6 +59,7 @@ fn is_struct_with_trailing_zero_sized_array(cx: &LateContext<'tcx>, item: &'tcx
if let ItemKind::Struct(data, _) = &item.kind;
if let Some(last_field) = data.fields().last();
if let rustc_hir::TyKind::Array(_, length) = last_field.ty.kind;
if let rustc_hir::ArrayLen::Body(length) = length;
// Then check if that that array zero-sized
let length_ldid = cx.tcx.hir().local_def_id(length.hir_id);

View file

@ -6,7 +6,7 @@ use rustc_ast::ast::{LitFloatType, LitKind};
use rustc_ast::LitIntType;
use rustc_data_structures::fx::FxHashMap;
use rustc_hir as hir;
use rustc_hir::{ExprKind, FnRetTy, HirId, Lit, PatKind, QPath, StmtKind, TyKind};
use rustc_hir::{ArrayLen, ExprKind, FnRetTy, HirId, Lit, PatKind, QPath, StmtKind, TyKind};
use rustc_lint::{LateContext, LateLintPass, LintContext};
use rustc_session::{declare_lint_pass, declare_tool_lint};
use rustc_span::symbol::{Ident, Symbol};
@ -567,7 +567,14 @@ impl<'a, 'tcx> PrintVisitor<'a, 'tcx> {
bind!(self, value, length);
kind!("Repeat({value}, {length})");
self.expr(value);
self.body(field!(length.body));
match length.value {
ArrayLen::Infer(..) => out!("if let ArrayLen::Infer(..) = length;"),
ArrayLen::Body(anon_const) => {
bind!(self, anon_const);
out!("if let ArrayLen::Body({anon_const}) = {length};");
self.body(field!(anon_const.body));
}
}
},
ExprKind::Err => kind!("Err"),
ExprKind::DropTemps(expr) => {

View file

@ -334,12 +334,17 @@ fn print_expr(cx: &LateContext<'_>, expr: &hir::Expr<'_>, indent: usize) {
println!("{}anon_const:", ind);
print_expr(cx, &cx.tcx.hir().body(anon_const.body).value, indent + 1);
},
hir::ExprKind::Repeat(val, ref anon_const) => {
hir::ExprKind::Repeat(val, length) => {
println!("{}Repeat", ind);
println!("{}value:", ind);
print_expr(cx, val, indent + 1);
println!("{}repeat count:", ind);
print_expr(cx, &cx.tcx.hir().body(anon_const.body).value, indent + 1);
match length {
hir::ArrayLen::Infer(_, _) => println!("{}repeat count: _", ind),
hir::ArrayLen::Body(anon_const) => {
print_expr(cx, &cx.tcx.hir().body(anon_const.body).value, indent + 1)
}
}
},
hir::ExprKind::Err => {
println!("{}Err", ind);

View file

@ -8,7 +8,7 @@ use rustc_hir::HirIdMap;
use rustc_hir::{
BinOpKind, Block, BodyId, Expr, ExprField, ExprKind, FnRetTy, GenericArg, GenericArgs, Guard, HirId,
InlineAsmOperand, Let, Lifetime, LifetimeName, ParamName, Pat, PatField, PatKind, Path, PathSegment, QPath, Stmt,
StmtKind, Ty, TyKind, TypeBinding,
StmtKind, Ty, TyKind, TypeBinding, ArrayLen
};
use rustc_lexer::{tokenize, TokenKind};
use rustc_lint::LateContext;
@ -170,6 +170,14 @@ 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_body(l_ct.body, r_ct.body),
(_, _) => false,
}
}
pub fn eq_body(&mut self, left: BodyId, right: BodyId) -> bool {
let cx = self.inner.cx;
let eval_const = |body| constant_context(cx, cx.tcx.typeck_body(body)).expr(&cx.tcx.hir().body(body).value);
@ -194,8 +202,8 @@ impl HirEqInterExpr<'_, '_, '_> {
}
let is_eq = match (
&reduce_exprkind(self.inner.cx, &left.kind),
&reduce_exprkind(self.inner.cx, &right.kind),
reduce_exprkind(self.inner.cx, &left.kind),
reduce_exprkind(self.inner.cx, &right.kind),
) {
(&ExprKind::AddrOf(lb, l_mut, le), &ExprKind::AddrOf(rb, r_mut, re)) => {
lb == rb && l_mut == r_mut && self.eq_expr(le, re)
@ -232,7 +240,7 @@ impl HirEqInterExpr<'_, '_, '_> {
},
(&ExprKind::Index(la, li), &ExprKind::Index(ra, ri)) => self.eq_expr(la, ra) && self.eq_expr(li, ri),
(&ExprKind::If(lc, lt, ref le), &ExprKind::If(rc, rt, ref re)) => {
self.eq_expr(lc, rc) && self.eq_expr(&**lt, &**rt) && both(le, re, |l, r| self.eq_expr(l, r))
self.eq_expr(lc, rc) && self.eq_expr(lt, rt) && both(le, re, |l, r| self.eq_expr(l, r))
},
(&ExprKind::Let(l), &ExprKind::Let(r)) => {
self.eq_pat(l.pat, r.pat) && both(&l.ty, &r.ty, |l, r| self.eq_ty(l, r)) && self.eq_expr(l.init, r.init)
@ -253,8 +261,8 @@ impl HirEqInterExpr<'_, '_, '_> {
(&ExprKind::MethodCall(l_path, _, l_args, _), &ExprKind::MethodCall(r_path, _, r_args, _)) => {
self.inner.allow_side_effects && self.eq_path_segment(l_path, r_path) && self.eq_exprs(l_args, r_args)
},
(&ExprKind::Repeat(le, ref ll_id), &ExprKind::Repeat(re, ref rl_id)) => {
self.eq_expr(le, re) && self.eq_body(ll_id.body, rl_id.body)
(&ExprKind::Repeat(le, ll), &ExprKind::Repeat(re, rl)) => {
self.eq_expr(le, re) && self.eq_array_length(ll, rl)
},
(&ExprKind::Ret(ref l), &ExprKind::Ret(ref r)) => both(l, r, |l, r| self.eq_expr(l, r)),
(&ExprKind::Path(ref l), &ExprKind::Path(ref r)) => self.eq_qpath(l, r),
@ -391,8 +399,8 @@ impl HirEqInterExpr<'_, '_, '_> {
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, ref ll_id), &TyKind::Array(rt, ref rl_id)) => {
self.eq_ty(lt, rt) && self.eq_body(ll_id.body, rl_id.body)
(&TyKind::Array(lt, ll), &TyKind::Array(rt, rl)) => {
self.eq_ty(lt, rt) && self.eq_array_length(ll, rl)
},
(&TyKind::Ptr(ref l_mut), &TyKind::Ptr(ref r_mut)) => {
l_mut.mutbl == r_mut.mutbl && self.eq_ty(&*l_mut.ty, &*r_mut.ty)
@ -714,9 +722,9 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> {
ExprKind::ConstBlock(ref l_id) => {
self.hash_body(l_id.body);
},
ExprKind::Repeat(e, ref l_id) => {
ExprKind::Repeat(e, len) => {
self.hash_expr(e);
self.hash_body(l_id.body);
self.hash_array_length(len);
},
ExprKind::Ret(ref e) => {
if let Some(e) = *e {
@ -906,9 +914,9 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> {
TyKind::Slice(ty) => {
self.hash_ty(ty);
},
TyKind::Array(ty, anon_const) => {
&TyKind::Array(ty, len) => {
self.hash_ty(ty);
self.hash_body(anon_const.body);
self.hash_array_length(len);
},
TyKind::Ptr(ref mut_ty) => {
self.hash_ty(mut_ty.ty);
@ -953,6 +961,13 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> {
}
}
pub fn hash_array_length(&mut self, length: ArrayLen) {
match length {
ArrayLen::Infer(..) => {}
ArrayLen::Body(anon_const) => self.hash_body(anon_const.body),
}
}
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));

View file

@ -79,7 +79,7 @@ use rustc_hir::{
def, Arm, BindingAnnotation, Block, BlockCheckMode, Body, Constness, Destination, Expr, ExprKind, FnDecl,
ForeignItem, GenericArgs, HirId, Impl, ImplItem, ImplItemKind, IsAsync, Item, ItemKind, LangItem, Local,
MatchSource, Mutability, Node, Param, Pat, PatKind, Path, PathSegment, PrimTy, QPath, Stmt, StmtKind, TraitItem,
TraitItemKind, TraitRef, TyKind, UnOp,
TraitItemKind, TraitRef, TyKind, UnOp, ArrayLen
};
use rustc_lint::{LateContext, Level, Lint, LintContext};
use rustc_middle::hir::exports::Export;
@ -703,8 +703,9 @@ 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, y) => if_chain! {
if let ExprKind::Lit(ref const_lit) = cx.tcx.hir().body(y.body).value.kind;
ExprKind::Repeat(x, len) => if_chain! {
if let ArrayLen::Body(len) = len;
if let ExprKind::Lit(ref const_lit) = cx.tcx.hir().body(len.body).value.kind;
if let LitKind::Int(v, _) = const_lit.node;
if v <= 32 && is_default_equivalent(cx, x);
then {

View file

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