Merge commit '7248d06384' into sync-from-clippy
This commit is contained in:
parent
0dc24ca376
commit
4d015293d1
111 changed files with 2040 additions and 1674 deletions
|
|
@ -501,8 +501,8 @@ impl<'a, 'tcx> ConstEvalLateContext<'a, 'tcx> {
|
|||
BinOpKind::Mul => l.checked_mul(r).map(zext),
|
||||
BinOpKind::Div if r != 0 => l.checked_div(r).map(zext),
|
||||
BinOpKind::Rem if r != 0 => l.checked_rem(r).map(zext),
|
||||
BinOpKind::Shr => l.checked_shr(r.try_into().expect("invalid shift")).map(zext),
|
||||
BinOpKind::Shl => l.checked_shl(r.try_into().expect("invalid shift")).map(zext),
|
||||
BinOpKind::Shr => l.checked_shr(r.try_into().ok()?).map(zext),
|
||||
BinOpKind::Shl => l.checked_shl(r.try_into().ok()?).map(zext),
|
||||
BinOpKind::BitXor => Some(zext(l ^ r)),
|
||||
BinOpKind::BitOr => Some(zext(l | r)),
|
||||
BinOpKind::BitAnd => Some(zext(l & r)),
|
||||
|
|
@ -521,8 +521,8 @@ impl<'a, 'tcx> ConstEvalLateContext<'a, 'tcx> {
|
|||
BinOpKind::Mul => l.checked_mul(r).map(Constant::Int),
|
||||
BinOpKind::Div => l.checked_div(r).map(Constant::Int),
|
||||
BinOpKind::Rem => l.checked_rem(r).map(Constant::Int),
|
||||
BinOpKind::Shr => l.checked_shr(r.try_into().expect("shift too large")).map(Constant::Int),
|
||||
BinOpKind::Shl => l.checked_shl(r.try_into().expect("shift too large")).map(Constant::Int),
|
||||
BinOpKind::Shr => l.checked_shr(r.try_into().ok()?).map(Constant::Int),
|
||||
BinOpKind::Shl => l.checked_shl(r.try_into().ok()?).map(Constant::Int),
|
||||
BinOpKind::BitXor => Some(Constant::Int(l ^ r)),
|
||||
BinOpKind::BitOr => Some(Constant::Int(l | r)),
|
||||
BinOpKind::BitAnd => Some(Constant::Int(l & r)),
|
||||
|
|
|
|||
|
|
@ -7,8 +7,8 @@ use crate::visitors::expr_visitor_no_bodies;
|
|||
use arrayvec::ArrayVec;
|
||||
use itertools::{izip, Either, Itertools};
|
||||
use rustc_ast::ast::LitKind;
|
||||
use rustc_hir::intravisit::Visitor;
|
||||
use rustc_hir::{self as hir, Expr, ExprKind, HirId, Node, QPath};
|
||||
use rustc_hir::intravisit::{walk_expr, Visitor};
|
||||
use rustc_hir::{self as hir, Expr, ExprField, ExprKind, HirId, Node, QPath};
|
||||
use rustc_lexer::unescape::unescape_literal;
|
||||
use rustc_lexer::{tokenize, unescape, LiteralKind, TokenKind};
|
||||
use rustc_lint::LateContext;
|
||||
|
|
@ -485,64 +485,49 @@ struct ParamPosition {
|
|||
precision: Option<usize>,
|
||||
}
|
||||
|
||||
/// Parses the `fmt` arg of `Arguments::new_v1_formatted(pieces, args, fmt, _)`
|
||||
fn parse_rt_fmt<'tcx>(fmt_arg: &'tcx Expr<'tcx>) -> Option<impl Iterator<Item = ParamPosition> + 'tcx> {
|
||||
fn parse_count(expr: &Expr<'_>) -> Option<usize> {
|
||||
// ::core::fmt::rt::v1::Count::Param(1usize),
|
||||
if let ExprKind::Call(ctor, [val]) = expr.kind
|
||||
&& let ExprKind::Path(QPath::Resolved(_, path)) = ctor.kind
|
||||
&& path.segments.last()?.ident.name == sym::Param
|
||||
&& let ExprKind::Lit(lit) = &val.kind
|
||||
&& let LitKind::Int(pos, _) = lit.node
|
||||
{
|
||||
Some(pos as usize)
|
||||
} else {
|
||||
None
|
||||
impl<'tcx> Visitor<'tcx> for ParamPosition {
|
||||
fn visit_expr_field(&mut self, field: &'tcx ExprField<'tcx>) {
|
||||
fn parse_count(expr: &Expr<'_>) -> Option<usize> {
|
||||
// ::core::fmt::rt::v1::Count::Param(1usize),
|
||||
if let ExprKind::Call(ctor, [val]) = expr.kind
|
||||
&& let ExprKind::Path(QPath::Resolved(_, path)) = ctor.kind
|
||||
&& path.segments.last()?.ident.name == sym::Param
|
||||
&& let ExprKind::Lit(lit) = &val.kind
|
||||
&& let LitKind::Int(pos, _) = lit.node
|
||||
{
|
||||
Some(pos as usize)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
match field.ident.name {
|
||||
sym::position => {
|
||||
if let ExprKind::Lit(lit) = &field.expr.kind
|
||||
&& let LitKind::Int(pos, _) = lit.node
|
||||
{
|
||||
self.value = pos as usize;
|
||||
}
|
||||
},
|
||||
sym::precision => {
|
||||
self.precision = parse_count(field.expr);
|
||||
},
|
||||
sym::width => {
|
||||
self.width = parse_count(field.expr);
|
||||
},
|
||||
_ => walk_expr(self, field.expr),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Parses the `fmt` arg of `Arguments::new_v1_formatted(pieces, args, fmt, _)`
|
||||
fn parse_rt_fmt<'tcx>(fmt_arg: &'tcx Expr<'tcx>) -> Option<impl Iterator<Item = ParamPosition> + 'tcx> {
|
||||
if let ExprKind::AddrOf(.., array) = fmt_arg.kind
|
||||
&& let ExprKind::Array(specs) = array.kind
|
||||
{
|
||||
Some(specs.iter().map(|spec| {
|
||||
let mut position = ParamPosition::default();
|
||||
|
||||
// ::core::fmt::rt::v1::Argument {
|
||||
// position: 0usize,
|
||||
// format: ::core::fmt::rt::v1::FormatSpec {
|
||||
// ..
|
||||
// precision: ::core::fmt::rt::v1::Count::Implied,
|
||||
// width: ::core::fmt::rt::v1::Count::Implied,
|
||||
// },
|
||||
// }
|
||||
|
||||
// TODO: this can be made much nicer next sync with `Visitor::visit_expr_field`
|
||||
if let ExprKind::Struct(_, fields, _) = spec.kind {
|
||||
for field in fields {
|
||||
match (field.ident.name, &field.expr.kind) {
|
||||
(sym::position, ExprKind::Lit(lit)) => {
|
||||
if let LitKind::Int(pos, _) = lit.node {
|
||||
position.value = pos as usize;
|
||||
}
|
||||
},
|
||||
(sym::format, &ExprKind::Struct(_, spec_fields, _)) => {
|
||||
for spec_field in spec_fields {
|
||||
match spec_field.ident.name {
|
||||
sym::precision => {
|
||||
position.precision = parse_count(spec_field.expr);
|
||||
},
|
||||
sym::width => {
|
||||
position.width = parse_count(spec_field.expr);
|
||||
},
|
||||
_ => {},
|
||||
}
|
||||
}
|
||||
},
|
||||
_ => {},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
position.visit_expr(spec);
|
||||
position
|
||||
}))
|
||||
} else {
|
||||
|
|
@ -711,9 +696,14 @@ impl<'tcx> FormatSpec<'tcx> {
|
|||
})
|
||||
}
|
||||
|
||||
/// Returns true if this format spec would change the contents of a string when formatted
|
||||
pub fn has_string_formatting(&self) -> bool {
|
||||
self.r#trait != sym::Display || !self.width.is_implied() || !self.precision.is_implied()
|
||||
/// Returns true if this format spec is unchanged from the default. e.g. returns true for `{}`,
|
||||
/// `{foo}` and `{2}`, but false for `{:?}`, `{foo:5}` and `{3:.5}`
|
||||
pub fn is_default(&self) -> bool {
|
||||
self.r#trait == sym::Display
|
||||
&& self.width.is_implied()
|
||||
&& self.precision.is_implied()
|
||||
&& self.align == Alignment::AlignUnknown
|
||||
&& self.flags == 0
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ use std::fmt::{Display, Write as _};
|
|||
use std::ops::{Add, Neg, Not, Sub};
|
||||
|
||||
/// A helper type to build suggestion correctly handling parentheses.
|
||||
#[derive(Clone, PartialEq)]
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
pub enum Sugg<'a> {
|
||||
/// An expression that never needs parentheses such as `1337` or `[0; 42]`.
|
||||
NonParen(Cow<'a, str>),
|
||||
|
|
@ -155,8 +155,8 @@ impl<'a> Sugg<'a> {
|
|||
| hir::ExprKind::Ret(..)
|
||||
| hir::ExprKind::Struct(..)
|
||||
| hir::ExprKind::Tup(..)
|
||||
| hir::ExprKind::DropTemps(_)
|
||||
| hir::ExprKind::Err => Sugg::NonParen(get_snippet(expr.span)),
|
||||
hir::ExprKind::DropTemps(inner) => Self::hir_from_snippet(inner, get_snippet),
|
||||
hir::ExprKind::Assign(lhs, rhs, _) => {
|
||||
Sugg::BinOp(AssocOp::Assign, get_snippet(lhs.span), get_snippet(rhs.span))
|
||||
},
|
||||
|
|
@ -177,11 +177,11 @@ impl<'a> Sugg<'a> {
|
|||
pub fn ast(cx: &EarlyContext<'_>, expr: &ast::Expr, default: &'a str) -> Self {
|
||||
use rustc_ast::ast::RangeLimits;
|
||||
|
||||
let get_whole_snippet = || {
|
||||
if expr.span.from_expansion() {
|
||||
snippet_with_macro_callsite(cx, expr.span, default)
|
||||
let snippet_without_expansion = |cx, span: Span, default| {
|
||||
if span.from_expansion() {
|
||||
snippet_with_macro_callsite(cx, span, default)
|
||||
} else {
|
||||
snippet(cx, expr.span, default)
|
||||
snippet(cx, span, default)
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -192,7 +192,7 @@ impl<'a> Sugg<'a> {
|
|||
| ast::ExprKind::If(..)
|
||||
| ast::ExprKind::Let(..)
|
||||
| ast::ExprKind::Unary(..)
|
||||
| ast::ExprKind::Match(..) => Sugg::MaybeParen(get_whole_snippet()),
|
||||
| ast::ExprKind::Match(..) => Sugg::MaybeParen(snippet_without_expansion(cx, expr.span, default)),
|
||||
ast::ExprKind::Async(..)
|
||||
| ast::ExprKind::Block(..)
|
||||
| ast::ExprKind::Break(..)
|
||||
|
|
@ -221,41 +221,45 @@ impl<'a> Sugg<'a> {
|
|||
| ast::ExprKind::Array(..)
|
||||
| ast::ExprKind::While(..)
|
||||
| ast::ExprKind::Await(..)
|
||||
| ast::ExprKind::Err => Sugg::NonParen(get_whole_snippet()),
|
||||
| ast::ExprKind::Err => Sugg::NonParen(snippet_without_expansion(cx, expr.span, default)),
|
||||
ast::ExprKind::Range(ref lhs, ref rhs, RangeLimits::HalfOpen) => Sugg::BinOp(
|
||||
AssocOp::DotDot,
|
||||
lhs.as_ref().map_or("".into(), |lhs| snippet(cx, lhs.span, default)),
|
||||
rhs.as_ref().map_or("".into(), |rhs| snippet(cx, rhs.span, default)),
|
||||
lhs.as_ref()
|
||||
.map_or("".into(), |lhs| snippet_without_expansion(cx, lhs.span, default)),
|
||||
rhs.as_ref()
|
||||
.map_or("".into(), |rhs| snippet_without_expansion(cx, rhs.span, default)),
|
||||
),
|
||||
ast::ExprKind::Range(ref lhs, ref rhs, RangeLimits::Closed) => Sugg::BinOp(
|
||||
AssocOp::DotDotEq,
|
||||
lhs.as_ref().map_or("".into(), |lhs| snippet(cx, lhs.span, default)),
|
||||
rhs.as_ref().map_or("".into(), |rhs| snippet(cx, rhs.span, default)),
|
||||
lhs.as_ref()
|
||||
.map_or("".into(), |lhs| snippet_without_expansion(cx, lhs.span, default)),
|
||||
rhs.as_ref()
|
||||
.map_or("".into(), |rhs| snippet_without_expansion(cx, rhs.span, default)),
|
||||
),
|
||||
ast::ExprKind::Assign(ref lhs, ref rhs, _) => Sugg::BinOp(
|
||||
AssocOp::Assign,
|
||||
snippet(cx, lhs.span, default),
|
||||
snippet(cx, rhs.span, default),
|
||||
snippet_without_expansion(cx, lhs.span, default),
|
||||
snippet_without_expansion(cx, rhs.span, default),
|
||||
),
|
||||
ast::ExprKind::AssignOp(op, ref lhs, ref rhs) => Sugg::BinOp(
|
||||
astbinop2assignop(op),
|
||||
snippet(cx, lhs.span, default),
|
||||
snippet(cx, rhs.span, default),
|
||||
snippet_without_expansion(cx, lhs.span, default),
|
||||
snippet_without_expansion(cx, rhs.span, default),
|
||||
),
|
||||
ast::ExprKind::Binary(op, ref lhs, ref rhs) => Sugg::BinOp(
|
||||
AssocOp::from_ast_binop(op.node),
|
||||
snippet(cx, lhs.span, default),
|
||||
snippet(cx, rhs.span, default),
|
||||
snippet_without_expansion(cx, lhs.span, default),
|
||||
snippet_without_expansion(cx, rhs.span, default),
|
||||
),
|
||||
ast::ExprKind::Cast(ref lhs, ref ty) => Sugg::BinOp(
|
||||
AssocOp::As,
|
||||
snippet(cx, lhs.span, default),
|
||||
snippet(cx, ty.span, default),
|
||||
snippet_without_expansion(cx, lhs.span, default),
|
||||
snippet_without_expansion(cx, ty.span, default),
|
||||
),
|
||||
ast::ExprKind::Type(ref lhs, ref ty) => Sugg::BinOp(
|
||||
AssocOp::Colon,
|
||||
snippet(cx, lhs.span, default),
|
||||
snippet(cx, ty.span, default),
|
||||
snippet_without_expansion(cx, lhs.span, default),
|
||||
snippet_without_expansion(cx, ty.span, default),
|
||||
),
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -31,6 +31,13 @@ pub fn is_copy<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool {
|
|||
ty.is_copy_modulo_regions(cx.tcx.at(DUMMY_SP), cx.param_env)
|
||||
}
|
||||
|
||||
/// This checks whether a given type is known to implement Debug.
|
||||
pub fn has_debug_impl<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool {
|
||||
cx.tcx
|
||||
.get_diagnostic_item(sym::Debug)
|
||||
.map_or(false, |debug| implements_trait(cx, ty, debug, &[]))
|
||||
}
|
||||
|
||||
/// Checks whether a type can be partially moved.
|
||||
pub fn can_partially_move_ty<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool {
|
||||
if has_drop(cx, ty) || is_copy(cx, ty) {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue