1
Fork 0

Auto merge of #8272 - flip1995:rustup, r=flip1995

Rustup

r? `@ghost`

changelog: none
This commit is contained in:
bors 2022-01-13 11:55:36 +00:00
commit 97a5daa659
27 changed files with 139 additions and 93 deletions

View file

@ -1,6 +1,6 @@
[package] [package]
name = "clippy" name = "clippy"
version = "0.1.59" version = "0.1.60"
description = "A bunch of helpful lints to avoid common pitfalls in Rust" description = "A bunch of helpful lints to avoid common pitfalls in Rust"
repository = "https://github.com/rust-lang/rust-clippy" repository = "https://github.com/rust-lang/rust-clippy"
readme = "README.md" readme = "README.md"

View file

@ -1,6 +1,6 @@
[package] [package]
name = "clippy_lints" name = "clippy_lints"
version = "0.1.59" version = "0.1.60"
description = "A bunch of helpful lints to avoid common pitfalls in Rust" description = "A bunch of helpful lints to avoid common pitfalls in Rust"
repository = "https://github.com/rust-lang/rust-clippy" repository = "https://github.com/rust-lang/rust-clippy"
readme = "README.md" readme = "README.md"
@ -13,7 +13,7 @@ cargo_metadata = "0.14"
clippy_utils = { path = "../clippy_utils" } clippy_utils = { path = "../clippy_utils" }
if_chain = "1.0" if_chain = "1.0"
itertools = "0.10" itertools = "0.10"
pulldown-cmark = { version = "0.8", default-features = false } pulldown-cmark = { version = "0.9", default-features = false }
quine-mc_cluskey = "0.2" quine-mc_cluskey = "0.2"
regex-syntax = "0.6" regex-syntax = "0.6"
serde = { version = "1.0", features = ["derive"] } serde = { version = "1.0", features = ["derive"] }

View file

@ -198,7 +198,7 @@ impl<'tcx> LateLintPass<'tcx> for Default {
let ext_with_default = !variant let ext_with_default = !variant
.fields .fields
.iter() .iter()
.all(|field| assigned_fields.iter().any(|(a, _)| a == &field.ident.name)); .all(|field| assigned_fields.iter().any(|(a, _)| a == &field.name));
let field_list = assigned_fields let field_list = assigned_fields
.into_iter() .into_iter()

View file

@ -161,7 +161,7 @@ impl<'a, 'tcx> Visitor<'tcx> for NumericFallbackVisitor<'a, 'tcx> {
fields_def fields_def
.iter() .iter()
.find_map(|f_def| { .find_map(|f_def| {
if f_def.ident == field.ident if f_def.ident(self.cx.tcx) == field.ident
{ Some(self.cx.tcx.type_of(f_def.did)) } { Some(self.cx.tcx.type_of(f_def.did)) }
else { None } else { None }
}); });

View file

@ -543,16 +543,16 @@ fn check_doc<'a, Events: Iterator<Item = (pulldown_cmark::Event<'a>, Range<usize
}, },
Start(Link(_, url, _)) => in_link = Some(url), Start(Link(_, url, _)) => in_link = Some(url),
End(Link(..)) => in_link = None, End(Link(..)) => in_link = None,
Start(Heading(_) | Paragraph | Item) => { Start(Heading(_, _, _) | Paragraph | Item) => {
if let Start(Heading(_)) = event { if let Start(Heading(_, _, _)) = event {
in_heading = true; in_heading = true;
} }
ticks_unbalanced = false; ticks_unbalanced = false;
let (_, span) = get_current_span(spans, range.start); let (_, span) = get_current_span(spans, range.start);
paragraph_span = first_line_of_span(cx, span); paragraph_span = first_line_of_span(cx, span);
}, },
End(Heading(_) | Paragraph | Item) => { End(Heading(_, _, _) | Paragraph | Item) => {
if let End(Heading(_)) = event { if let End(Heading(_, _, _)) = event {
in_heading = false; in_heading = false;
} }
if ticks_unbalanced { if ticks_unbalanced {

View file

@ -76,7 +76,7 @@ impl<'tcx> LateLintPass<'tcx> for InconsistentStructConstructor {
then { then {
let mut def_order_map = FxHashMap::default(); let mut def_order_map = FxHashMap::default();
for (idx, field) in variant.fields.iter().enumerate() { for (idx, field) in variant.fields.iter().enumerate() {
def_order_map.insert(field.ident.name, idx); def_order_map.insert(field.name, idx);
} }
if is_consistent_order(fields, &def_order_map) { if is_consistent_order(fields, &def_order_map) {

View file

@ -214,14 +214,14 @@ fn check_trait_items(cx: &LateContext<'_>, visited_trait: &Item<'_>, trait_items
{ {
let mut current_and_super_traits = DefIdSet::default(); let mut current_and_super_traits = DefIdSet::default();
fill_trait_set(visited_trait.def_id.to_def_id(), &mut current_and_super_traits, cx); fill_trait_set(visited_trait.def_id.to_def_id(), &mut current_and_super_traits, cx);
let is_empty = sym!(is_empty);
let is_empty_method_found = current_and_super_traits let is_empty_method_found = current_and_super_traits
.iter() .iter()
.flat_map(|&i| cx.tcx.associated_items(i).in_definition_order()) .flat_map(|&i| cx.tcx.associated_items(i).filter_by_name_unhygienic(is_empty))
.any(|i| { .any(|i| {
i.kind == ty::AssocKind::Fn i.kind == ty::AssocKind::Fn
&& i.fn_has_self_parameter && i.fn_has_self_parameter
&& i.ident.name == sym!(is_empty)
&& cx.tcx.fn_sig(i.def_id).inputs().skip_binder().len() == 1 && cx.tcx.fn_sig(i.def_id).inputs().skip_binder().len() == 1
}); });
@ -458,7 +458,7 @@ fn is_empty_array(expr: &Expr<'_>) -> bool {
fn has_is_empty(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool { fn has_is_empty(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
/// Gets an `AssocItem` and return true if it matches `is_empty(self)`. /// Gets an `AssocItem` and return true if it matches `is_empty(self)`.
fn is_is_empty(cx: &LateContext<'_>, item: &ty::AssocItem) -> bool { fn is_is_empty(cx: &LateContext<'_>, item: &ty::AssocItem) -> bool {
if item.kind == ty::AssocKind::Fn && item.ident.name.as_str() == "is_empty" { if item.kind == ty::AssocKind::Fn {
let sig = cx.tcx.fn_sig(item.def_id); let sig = cx.tcx.fn_sig(item.def_id);
let ty = sig.skip_binder(); let ty = sig.skip_binder();
ty.inputs().len() == 1 ty.inputs().len() == 1
@ -469,10 +469,11 @@ fn has_is_empty(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
/// Checks the inherent impl's items for an `is_empty(self)` method. /// Checks the inherent impl's items for an `is_empty(self)` method.
fn has_is_empty_impl(cx: &LateContext<'_>, id: DefId) -> bool { fn has_is_empty_impl(cx: &LateContext<'_>, id: DefId) -> bool {
let is_empty = sym!(is_empty);
cx.tcx.inherent_impls(id).iter().any(|imp| { cx.tcx.inherent_impls(id).iter().any(|imp| {
cx.tcx cx.tcx
.associated_items(*imp) .associated_items(*imp)
.in_definition_order() .filter_by_name_unhygienic(is_empty)
.any(|item| is_is_empty(cx, item)) .any(|item| is_is_empty(cx, item))
}) })
} }
@ -480,9 +481,10 @@ fn has_is_empty(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
let ty = &cx.typeck_results().expr_ty(expr).peel_refs(); let ty = &cx.typeck_results().expr_ty(expr).peel_refs();
match ty.kind() { match ty.kind() {
ty::Dynamic(tt, ..) => tt.principal().map_or(false, |principal| { ty::Dynamic(tt, ..) => tt.principal().map_or(false, |principal| {
let is_empty = sym!(is_empty);
cx.tcx cx.tcx
.associated_items(principal.def_id()) .associated_items(principal.def_id())
.in_definition_order() .filter_by_name_unhygienic(is_empty)
.any(|item| is_is_empty(cx, item)) .any(|item| is_is_empty(cx, item))
}), }),
ty::Projection(ref proj) => has_is_empty_impl(cx, proj.item_def_id), ty::Projection(ref proj) => has_is_empty_impl(cx, proj.item_def_id),

View file

@ -8,7 +8,6 @@ use rustc_errors::Applicability;
use rustc_hir as hir; use rustc_hir as hir;
use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_lint::{LateContext, LateLintPass, LintContext};
use rustc_session::{declare_tool_lint, impl_lint_pass}; use rustc_session::{declare_tool_lint, impl_lint_pass};
use rustc_span::hygiene::ExpnKind;
use rustc_span::{edition::Edition, sym, Span}; use rustc_span::{edition::Edition, sym, Span};
declare_clippy_lint! { declare_clippy_lint! {
@ -97,7 +96,7 @@ impl<'tcx> LateLintPass<'tcx> for MacroUseImports {
if let Res::Def(DefKind::Mod, id) = path.res; if let Res::Def(DefKind::Mod, id) = path.res;
if !id.is_local(); if !id.is_local();
then { then {
for kid in cx.tcx.item_children(id).iter() { for kid in cx.tcx.module_children(id).iter() {
if let Res::Def(DefKind::Macro(_mac_type), mac_id) = kid.res { if let Res::Def(DefKind::Macro(_mac_type), mac_id) = kid.res {
let span = mac_attr.span; let span = mac_attr.span;
let def_path = cx.tcx.def_path_str(mac_id); let def_path = cx.tcx.def_path_str(mac_id);
@ -105,34 +104,34 @@ impl<'tcx> LateLintPass<'tcx> for MacroUseImports {
} }
} }
} else { } else {
if in_macro(item.span) { if item.span.from_expansion() {
self.push_unique_macro_pat_ty(cx, item.span); self.push_unique_macro_pat_ty(cx, item.span);
} }
} }
} }
} }
fn check_attribute(&mut self, cx: &LateContext<'_>, attr: &ast::Attribute) { fn check_attribute(&mut self, cx: &LateContext<'_>, attr: &ast::Attribute) {
if in_macro(attr.span) { if attr.span.from_expansion() {
self.push_unique_macro(cx, attr.span); self.push_unique_macro(cx, attr.span);
} }
} }
fn check_expr(&mut self, cx: &LateContext<'_>, expr: &hir::Expr<'_>) { fn check_expr(&mut self, cx: &LateContext<'_>, expr: &hir::Expr<'_>) {
if in_macro(expr.span) { if expr.span.from_expansion() {
self.push_unique_macro(cx, expr.span); self.push_unique_macro(cx, expr.span);
} }
} }
fn check_stmt(&mut self, cx: &LateContext<'_>, stmt: &hir::Stmt<'_>) { fn check_stmt(&mut self, cx: &LateContext<'_>, stmt: &hir::Stmt<'_>) {
if in_macro(stmt.span) { if stmt.span.from_expansion() {
self.push_unique_macro(cx, stmt.span); self.push_unique_macro(cx, stmt.span);
} }
} }
fn check_pat(&mut self, cx: &LateContext<'_>, pat: &hir::Pat<'_>) { fn check_pat(&mut self, cx: &LateContext<'_>, pat: &hir::Pat<'_>) {
if in_macro(pat.span) { if pat.span.from_expansion() {
self.push_unique_macro_pat_ty(cx, pat.span); self.push_unique_macro_pat_ty(cx, pat.span);
} }
} }
fn check_ty(&mut self, cx: &LateContext<'_>, ty: &hir::Ty<'_>) { fn check_ty(&mut self, cx: &LateContext<'_>, ty: &hir::Ty<'_>) {
if in_macro(ty.span) { if ty.span.from_expansion() {
self.push_unique_macro_pat_ty(cx, ty.span); self.push_unique_macro_pat_ty(cx, ty.span);
} }
} }
@ -214,7 +213,3 @@ impl<'tcx> LateLintPass<'tcx> for MacroUseImports {
} }
} }
} }
fn in_macro(span: Span) -> bool {
span.from_expansion() && !matches!(span.ctxt().outer_expn_data().kind, ExpnKind::Desugaring(..))
}

View file

@ -1138,7 +1138,7 @@ fn check_wild_enum_match(cx: &LateContext<'_>, ex: &Expr<'_>, arms: &[Arm<'_>])
s.push_str("::"); s.push_str("::");
s s
}, },
variant.ident.name, variant.name,
match variant.ctor_kind { match variant.ctor_kind {
CtorKind::Fn if variant.fields.len() == 1 => "(_)", CtorKind::Fn if variant.fields.len() == 1 => "(_)",
CtorKind::Fn => "(..)", CtorKind::Fn => "(..)",

View file

@ -12,11 +12,10 @@ use rustc_hir::def_id::DefId;
use rustc_hir::{ use rustc_hir::{
BodyId, Expr, ExprKind, HirId, Impl, ImplItem, ImplItemKind, Item, ItemKind, Node, TraitItem, TraitItemKind, UnOp, BodyId, Expr, ExprKind, HirId, Impl, ImplItem, ImplItemKind, Item, ItemKind, Node, TraitItem, TraitItemKind, UnOp,
}; };
use rustc_infer::traits::specialization_graph;
use rustc_lint::{LateContext, LateLintPass, Lint}; use rustc_lint::{LateContext, LateLintPass, Lint};
use rustc_middle::mir::interpret::{ConstValue, ErrorHandled}; use rustc_middle::mir::interpret::{ConstValue, ErrorHandled};
use rustc_middle::ty::adjustment::Adjust; use rustc_middle::ty::adjustment::Adjust;
use rustc_middle::ty::{self, AssocKind, Const, Ty}; use rustc_middle::ty::{self, Const, Ty};
use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_session::{declare_lint_pass, declare_tool_lint};
use rustc_span::{InnerSpan, Span, DUMMY_SP}; use rustc_span::{InnerSpan, Span, DUMMY_SP};
use rustc_typeck::hir_ty_to_ty; use rustc_typeck::hir_ty_to_ty;
@ -293,8 +292,10 @@ impl<'tcx> LateLintPass<'tcx> for NonCopyConst {
// Lint a trait impl item only when the definition is a generic type, // Lint a trait impl item only when the definition is a generic type,
// assuming an assoc const is not meant to be an interior mutable type. // assuming an assoc const is not meant to be an interior mutable type.
if let Some(of_trait_def_id) = of_trait_ref.trait_def_id(); if let Some(of_trait_def_id) = of_trait_ref.trait_def_id();
if let Some(of_assoc_item) = specialization_graph::Node::Trait(of_trait_def_id) if let Some(of_assoc_item) = cx
.item(cx.tcx, impl_item.ident, AssocKind::Const, of_trait_def_id); .tcx
.associated_item(impl_item.def_id)
.trait_item_def_id;
if cx if cx
.tcx .tcx
.layout_of(cx.tcx.param_env(of_trait_def_id).and( .layout_of(cx.tcx.param_env(of_trait_def_id).and(
@ -303,7 +304,7 @@ impl<'tcx> LateLintPass<'tcx> for NonCopyConst {
// and, in that case, the definition is *not* generic. // and, in that case, the definition is *not* generic.
cx.tcx.normalize_erasing_regions( cx.tcx.normalize_erasing_regions(
cx.tcx.param_env(of_trait_def_id), cx.tcx.param_env(of_trait_def_id),
cx.tcx.type_of(of_assoc_item.def_id), cx.tcx.type_of(of_assoc_item),
), ),
)) ))
.is_err(); .is_err();

View file

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

View file

@ -13,7 +13,6 @@ use rustc_hir::{
}; };
use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_lint::{LateContext, LateLintPass, LintContext};
use rustc_middle::hir::map::Map; use rustc_middle::hir::map::Map;
use rustc_middle::ty::AssocKind;
use rustc_semver::RustcVersion; use rustc_semver::RustcVersion;
use rustc_session::{declare_tool_lint, impl_lint_pass}; use rustc_session::{declare_tool_lint, impl_lint_pass};
use rustc_span::Span; use rustc_span::Span;
@ -143,10 +142,10 @@ impl<'tcx> LateLintPass<'tcx> for UseSelf {
// trait, not in the impl of the trait. // trait, not in the impl of the trait.
let trait_method = cx let trait_method = cx
.tcx .tcx
.associated_items(impl_trait_ref.def_id) .associated_item(impl_item.def_id)
.find_by_name_and_kind(cx.tcx, impl_item.ident, AssocKind::Fn, impl_trait_ref.def_id) .trait_item_def_id
.expect("impl method matches a trait method"); .expect("impl method matches a trait method");
let trait_method_sig = cx.tcx.fn_sig(trait_method.def_id); let trait_method_sig = cx.tcx.fn_sig(trait_method);
let trait_method_sig = cx.tcx.erase_late_bound_regions(trait_method_sig); let trait_method_sig = cx.tcx.erase_late_bound_regions(trait_method_sig);
// `impl_inputs_outputs` is an iterator over the types (`hir::Ty`) declared in the // `impl_inputs_outputs` is an iterator over the types (`hir::Ty`) declared in the

View file

@ -6,7 +6,7 @@ use rustc_ast::ast::{LitFloatType, LitKind};
use rustc_ast::LitIntType; use rustc_ast::LitIntType;
use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::fx::FxHashMap;
use rustc_hir as hir; 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_lint::{LateContext, LateLintPass, LintContext};
use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_session::{declare_lint_pass, declare_tool_lint};
use rustc_span::symbol::{Ident, Symbol}; use rustc_span::symbol::{Ident, Symbol};
@ -567,7 +567,14 @@ 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);
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::Err => kind!("Err"),
ExprKind::DropTemps(expr) => { ExprKind::DropTemps(expr) => {

View file

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

View file

@ -929,9 +929,20 @@ pub fn check_path(cx: &LateContext<'_>, path: &[&str]) -> bool {
let lang_item_path = cx.get_def_path(*item_def_id); let lang_item_path = cx.get_def_path(*item_def_id);
if path_syms.starts_with(&lang_item_path) { if path_syms.starts_with(&lang_item_path) {
if let [item] = &path_syms[lang_item_path.len()..] { if let [item] = &path_syms[lang_item_path.len()..] {
for child in cx.tcx.item_children(*item_def_id) { if matches!(
if child.ident.name == *item { cx.tcx.def_kind(*item_def_id),
return true; DefKind::Mod | DefKind::Enum | DefKind::Trait
) {
for child in cx.tcx.module_children(*item_def_id) {
if child.ident.name == *item {
return true;
}
}
} else {
for child in cx.tcx.associated_item_def_ids(*item_def_id) {
if cx.tcx.item_name(*child) == *item {
return true;
}
} }
} }
} }
@ -989,7 +1000,7 @@ impl<'tcx> LateLintPass<'tcx> for InterningDefinedSymbol {
for &module in &[&paths::KW_MODULE, &paths::SYM_MODULE] { for &module in &[&paths::KW_MODULE, &paths::SYM_MODULE] {
if let Some(def_id) = path_to_res(cx, module).opt_def_id() { if let Some(def_id) = path_to_res(cx, module).opt_def_id() {
for item in cx.tcx.item_children(def_id).iter() { for item in cx.tcx.module_children(def_id).iter() {
if_chain! { if_chain! {
if let Res::Def(DefKind::Const, item_def_id) = item.res; if let Res::Def(DefKind::Const, item_def_id) = item.res;
let ty = cx.tcx.type_of(item_def_id); let ty = cx.tcx.type_of(item_def_id);

View file

@ -1,6 +1,6 @@
[package] [package]
name = "clippy_utils" name = "clippy_utils"
version = "0.1.59" version = "0.1.60"
edition = "2021" edition = "2021"
publish = false publish = false

View file

@ -6,7 +6,7 @@ use rustc_data_structures::fx::FxHasher;
use rustc_hir::def::Res; use rustc_hir::def::Res;
use rustc_hir::HirIdMap; use rustc_hir::HirIdMap;
use rustc_hir::{ use rustc_hir::{
BinOpKind, Block, BodyId, Expr, ExprField, ExprKind, FnRetTy, GenericArg, GenericArgs, Guard, HirId, ArrayLen, BinOpKind, Block, BodyId, Expr, ExprField, ExprKind, FnRetTy, GenericArg, GenericArgs, Guard, HirId,
InlineAsmOperand, Let, Lifetime, LifetimeName, ParamName, Pat, PatField, PatKind, Path, PathSegment, QPath, Stmt, InlineAsmOperand, Let, Lifetime, LifetimeName, ParamName, Pat, PatField, PatKind, Path, PathSegment, QPath, Stmt,
StmtKind, Ty, TyKind, TypeBinding, StmtKind, Ty, TyKind, TypeBinding,
}; };
@ -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 { pub fn eq_body(&mut self, left: BodyId, right: BodyId) -> bool {
let cx = self.inner.cx; let cx = self.inner.cx;
let eval_const = |body| constant_context(cx, cx.tcx.typeck_body(body)).expr(&cx.tcx.hir().body(body).value); 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 ( let is_eq = match (
&reduce_exprkind(self.inner.cx, &left.kind), reduce_exprkind(self.inner.cx, &left.kind),
&reduce_exprkind(self.inner.cx, &right.kind), reduce_exprkind(self.inner.cx, &right.kind),
) { ) {
(&ExprKind::AddrOf(lb, l_mut, le), &ExprKind::AddrOf(rb, r_mut, re)) => { (&ExprKind::AddrOf(lb, l_mut, le), &ExprKind::AddrOf(rb, r_mut, re)) => {
lb == rb && l_mut == r_mut && self.eq_expr(le, 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::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)) => { (&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)) => { (&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) 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, _)) => { (&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) 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)) => { (&ExprKind::Repeat(le, ll), &ExprKind::Repeat(re, rl)) => {
self.eq_expr(le, re) && self.eq_body(ll_id.body, rl_id.body) 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::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), (&ExprKind::Path(ref l), &ExprKind::Path(ref r)) => self.eq_qpath(l, r),
@ -391,9 +399,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, ref ll_id), &TyKind::Array(rt, ref rl_id)) => { (&TyKind::Array(lt, ll), &TyKind::Array(rt, rl)) => self.eq_ty(lt, rt) && self.eq_array_length(ll, rl),
self.eq_ty(lt, rt) && self.eq_body(ll_id.body, rl_id.body)
},
(&TyKind::Ptr(ref l_mut), &TyKind::Ptr(ref r_mut)) => { (&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) l_mut.mutbl == r_mut.mutbl && self.eq_ty(&*l_mut.ty, &*r_mut.ty)
}, },
@ -714,9 +720,9 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> {
ExprKind::ConstBlock(ref l_id) => { ExprKind::ConstBlock(ref l_id) => {
self.hash_body(l_id.body); self.hash_body(l_id.body);
}, },
ExprKind::Repeat(e, ref l_id) => { ExprKind::Repeat(e, len) => {
self.hash_expr(e); self.hash_expr(e);
self.hash_body(l_id.body); self.hash_array_length(len);
}, },
ExprKind::Ret(ref e) => { ExprKind::Ret(ref e) => {
if let Some(e) = *e { if let Some(e) = *e {
@ -908,9 +914,9 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> {
TyKind::Slice(ty) => { TyKind::Slice(ty) => {
self.hash_ty(ty); self.hash_ty(ty);
}, },
TyKind::Array(ty, anon_const) => { &TyKind::Array(ty, len) => {
self.hash_ty(ty); self.hash_ty(ty);
self.hash_body(anon_const.body); self.hash_array_length(len);
}, },
TyKind::Ptr(ref mut_ty) => { TyKind::Ptr(ref mut_ty) => {
self.hash_ty(mut_ty.ty); self.hash_ty(mut_ty.ty);
@ -955,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) { 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));

View file

@ -76,13 +76,12 @@ use rustc_hir::intravisit::{walk_expr, ErasedMap, FnKind, NestedVisitorMap, Visi
use rustc_hir::itemlikevisit::ItemLikeVisitor; use rustc_hir::itemlikevisit::ItemLikeVisitor;
use rustc_hir::LangItem::{OptionNone, ResultErr, ResultOk}; use rustc_hir::LangItem::{OptionNone, ResultErr, ResultOk};
use rustc_hir::{ use rustc_hir::{
def, lang_items, Arm, BindingAnnotation, Block, BlockCheckMode, Body, Constness, Destination, Expr, ExprKind, def, lang_items, Arm, ArrayLen, BindingAnnotation, Block, BlockCheckMode, Body, Constness, Destination, Expr,
FnDecl, ForeignItem, GenericArgs, HirId, Impl, ImplItem, ImplItemKind, IsAsync, Item, ItemKind, LangItem, Local, ExprKind, FnDecl, ForeignItem, GenericArgs, HirId, Impl, ImplItem, ImplItemKind, IsAsync, Item, ItemKind, LangItem,
MatchSource, Mutability, Node, Param, Pat, PatKind, Path, PathSegment, PrimTy, QPath, Stmt, StmtKind, Target, Local, MatchSource, Mutability, Node, Param, Pat, PatKind, Path, PathSegment, PrimTy, QPath, Stmt, StmtKind,
TraitItem, TraitItemKind, TraitRef, TyKind, UnOp, Target, TraitItem, TraitItemKind, TraitRef, TyKind, UnOp,
}; };
use rustc_lint::{LateContext, Level, Lint, LintContext}; use rustc_lint::{LateContext, Level, Lint, LintContext};
use rustc_middle::hir::exports::Export;
use rustc_middle::hir::map::Map; use rustc_middle::hir::map::Map;
use rustc_middle::hir::place::PlaceBase; use rustc_middle::hir::place::PlaceBase;
use rustc_middle::ty as rustc_ty; use rustc_middle::ty as rustc_ty;
@ -520,10 +519,21 @@ pub fn path_to_res(cx: &LateContext<'_>, path: &[&str]) -> Res {
} }
}; };
} }
fn item_child_by_name<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, name: &str) -> Option<&'tcx Export> { fn item_child_by_name(tcx: TyCtxt<'_>, def_id: DefId, name: &str) -> Option<Res> {
tcx.item_children(def_id) match tcx.def_kind(def_id) {
.iter() DefKind::Mod | DefKind::Enum | DefKind::Trait => tcx
.find(|item| item.ident.name.as_str() == name) .module_children(def_id)
.iter()
.find(|item| item.ident.name.as_str() == name)
.map(|child| child.res.expect_non_local()),
DefKind::Impl => tcx
.associated_item_def_ids(def_id)
.iter()
.copied()
.find(|assoc_def_id| tcx.item_name(*assoc_def_id).as_str() == name)
.map(|assoc_def_id| Res::Def(tcx.def_kind(assoc_def_id), assoc_def_id)),
_ => None,
}
} }
fn find_primitive(tcx: TyCtxt<'_>, name: &str) -> Option<DefId> { fn find_primitive(tcx: TyCtxt<'_>, name: &str) -> Option<DefId> {
if let Some(&(index, Target::Impl)) = lang_items::ITEM_REFS.get(&Symbol::intern(name)) { if let Some(&(index, Target::Impl)) = lang_items::ITEM_REFS.get(&Symbol::intern(name)) {
@ -556,15 +566,12 @@ pub fn path_to_res(cx: &LateContext<'_>, path: &[&str]) -> Res {
let last = path let last = path
.iter() .iter()
.copied() .copied()
// `get_def_path` seems to generate these empty segments for extern blocks.
// We can just ignore them.
.filter(|segment| !segment.is_empty())
// for each segment, find the child item // for each segment, find the child item
.try_fold(first, |item, segment| { .try_fold(first, |res, segment| {
let def_id = item.res.def_id(); let def_id = res.def_id();
if let Some(item) = item_child_by_name(tcx, def_id, segment) { if let Some(item) = item_child_by_name(tcx, def_id, segment) {
Some(item) Some(item)
} else if matches!(item.res, Res::Def(DefKind::Enum | DefKind::Struct, _)) { } else if matches!(res, Res::Def(DefKind::Enum | DefKind::Struct, _)) {
// it is not a child item so check inherent impl items // it is not a child item so check inherent impl items
tcx.inherent_impls(def_id) tcx.inherent_impls(def_id)
.iter() .iter()
@ -573,7 +580,7 @@ pub fn path_to_res(cx: &LateContext<'_>, path: &[&str]) -> Res {
None None
} }
}); });
try_res!(last).res.expect_non_local() try_res!(last).expect_non_local()
} }
/// Convenience function to get the `DefId` of a trait by path. /// Convenience function to get the `DefId` of a trait by path.
@ -737,8 +744,8 @@ 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, y) => if_chain! { ExprKind::Repeat(x, ArrayLen::Body(len)) => if_chain! {
if let ExprKind::Lit(ref const_lit) = cx.tcx.hir().body(y.body).value.kind; if let ExprKind::Lit(ref const_lit) = cx.tcx.hir().body(len.body).value.kind;
if let LitKind::Int(v, _) = const_lit.node; if let LitKind::Int(v, _) = const_lit.node;
if v <= 32 && is_default_equivalent(cx, x); if v <= 32 && is_default_equivalent(cx, x);
then { then {

View file

@ -199,7 +199,6 @@ fn check_rvalue<'tcx>(
} }
}, },
Rvalue::NullaryOp(NullOp::SizeOf | NullOp::AlignOf, _) | Rvalue::ShallowInitBox(_, _) => Ok(()), Rvalue::NullaryOp(NullOp::SizeOf | NullOp::AlignOf, _) | Rvalue::ShallowInitBox(_, _) => Ok(()),
Rvalue::NullaryOp(NullOp::Box, _) => Err((span, "heap allocations are not allowed in const fn".into())),
Rvalue::UnaryOp(_, operand) => { Rvalue::UnaryOp(_, operand) => {
let ty = operand.ty(body, tcx); let ty = operand.ty(body, tcx);
if ty.is_integral() || ty.is_bool() { if ty.is_integral() || ty.is_bool() {

View file

@ -1,3 +1,3 @@
[toolchain] [toolchain]
channel = "nightly-2021-12-30" channel = "nightly-2022-01-13"
components = ["cargo", "llvm-tools-preview", "rust-src", "rust-std", "rustc", "rustc-dev", "rustfmt"] components = ["cargo", "llvm-tools-preview", "rust-src", "rust-std", "rustc", "rustc-dev", "rustfmt"]

View file

@ -1,10 +1,16 @@
error: invalid path
--> $DIR/invalid_paths.rs:15:5
|
LL | pub const TRANSMUTE: [&str; 4] = ["core", "intrinsics", "", "transmute"];
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: `-D clippy::invalid-paths` implied by `-D warnings`
error: invalid path error: invalid path
--> $DIR/invalid_paths.rs:18:5 --> $DIR/invalid_paths.rs:18:5
| |
LL | pub const BAD_CRATE_PATH: [&str; 2] = ["bad", "path"]; LL | pub const BAD_CRATE_PATH: [&str; 2] = ["bad", "path"];
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: `-D clippy::invalid-paths` implied by `-D warnings`
error: invalid path error: invalid path
--> $DIR/invalid_paths.rs:21:5 --> $DIR/invalid_paths.rs:21:5
@ -12,5 +18,5 @@ error: invalid path
LL | pub const BAD_MOD_PATH: [&str; 2] = ["std", "xxx"]; LL | pub const BAD_MOD_PATH: [&str; 2] = ["std", "xxx"];
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: aborting due to 2 previous errors error: aborting due to 3 previous errors

View file

@ -2,7 +2,8 @@ if_chain! {
if let ExprKind::Repeat(value, length) = expr.kind; if let ExprKind::Repeat(value, length) = expr.kind;
if let ExprKind::Lit(ref lit) = value.kind; if let ExprKind::Lit(ref lit) = value.kind;
if let LitKind::Int(1, LitIntType::Unsigned(UintTy::U8)) = lit.node; 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 ExprKind::Lit(ref lit1) = expr1.kind;
if let LitKind::Int(5, LitIntType::Unsuffixed) = lit1.node; if let LitKind::Int(5, LitIntType::Unsuffixed) = lit1.node;
then { then {

View file

@ -40,7 +40,7 @@ mod a {
} }
} }
// issue #7015, ICE due to calling `item_children` with local `DefId` // issue #7015, ICE due to calling `module_children` with local `DefId`
#[macro_use] #[macro_use]
use a as b; use a as b;

View file

@ -40,7 +40,7 @@ mod a {
} }
} }
// issue #7015, ICE due to calling `item_children` with local `DefId` // issue #7015, ICE due to calling `module_children` with local `DefId`
#[macro_use] #[macro_use]
use a as b; use a as b;

View file

@ -30,7 +30,7 @@ fn main() {
1_234.123_f32, 1_234.123_f32,
1.123_4_f32, 1.123_4_f32,
); );
let _bad = (0b11_0110_i64, 0xcafe_babe_usize, 123_456_f32, 1.234_567_f32); let _bad = (0b11_0110_i64, 0x1234_5678_usize, 123_456_f32, 1.234_567_f32);
let _good_sci = 1.1234e1; let _good_sci = 1.1234e1;
let _bad_sci = 1.123_456e1; let _bad_sci = 1.123_456e1;

View file

@ -30,7 +30,7 @@ fn main() {
1_234.123_f32, 1_234.123_f32,
1.123_4_f32, 1.123_4_f32,
); );
let _bad = (0b110110_i64, 0xcafebabe_usize, 123456_f32, 1.234567_f32); let _bad = (0b110110_i64, 0x12345678_usize, 123456_f32, 1.234567_f32);
let _good_sci = 1.1234e1; let _good_sci = 1.1234e1;
let _bad_sci = 1.123456e1; let _bad_sci = 1.123456e1;

View file

@ -9,7 +9,7 @@ LL | 0x1_234_567,
error: long literal lacking separators error: long literal lacking separators
--> $DIR/unreadable_literal.rs:33:17 --> $DIR/unreadable_literal.rs:33:17
| |
LL | let _bad = (0b110110_i64, 0xcafebabe_usize, 123456_f32, 1.234567_f32); LL | let _bad = (0b110110_i64, 0x12345678_usize, 123456_f32, 1.234567_f32);
| ^^^^^^^^^^^^ help: consider: `0b11_0110_i64` | ^^^^^^^^^^^^ help: consider: `0b11_0110_i64`
| |
= note: `-D clippy::unreadable-literal` implied by `-D warnings` = note: `-D clippy::unreadable-literal` implied by `-D warnings`
@ -17,19 +17,19 @@ LL | let _bad = (0b110110_i64, 0xcafebabe_usize, 123456_f32, 1.234567_f32);
error: long literal lacking separators error: long literal lacking separators
--> $DIR/unreadable_literal.rs:33:31 --> $DIR/unreadable_literal.rs:33:31
| |
LL | let _bad = (0b110110_i64, 0xcafebabe_usize, 123456_f32, 1.234567_f32); LL | let _bad = (0b110110_i64, 0x12345678_usize, 123456_f32, 1.234567_f32);
| ^^^^^^^^^^^^^^^^ help: consider: `0xcafe_babe_usize` | ^^^^^^^^^^^^^^^^ help: consider: `0x1234_5678_usize`
error: long literal lacking separators error: long literal lacking separators
--> $DIR/unreadable_literal.rs:33:49 --> $DIR/unreadable_literal.rs:33:49
| |
LL | let _bad = (0b110110_i64, 0xcafebabe_usize, 123456_f32, 1.234567_f32); LL | let _bad = (0b110110_i64, 0x12345678_usize, 123456_f32, 1.234567_f32);
| ^^^^^^^^^^ help: consider: `123_456_f32` | ^^^^^^^^^^ help: consider: `123_456_f32`
error: long literal lacking separators error: long literal lacking separators
--> $DIR/unreadable_literal.rs:33:61 --> $DIR/unreadable_literal.rs:33:61
| |
LL | let _bad = (0b110110_i64, 0xcafebabe_usize, 123456_f32, 1.234567_f32); LL | let _bad = (0b110110_i64, 0x12345678_usize, 123456_f32, 1.234567_f32);
| ^^^^^^^^^^^^ help: consider: `1.234_567_f32` | ^^^^^^^^^^^^ help: consider: `1.234_567_f32`
error: long literal lacking separators error: long literal lacking separators