commit
3518178443
@ -1,6 +1,5 @@
|
||||
# Clippy
|
||||
|
||||
[![Clippy Test](https://github.com/rust-lang/rust-clippy/workflows/Clippy%20Test%20(bors)/badge.svg?branch=auto&event=push)](https://github.com/rust-lang/rust-clippy/actions?query=workflow%3A%22Clippy+Test+(bors)%22+event%3Apush+branch%3Aauto)
|
||||
[![License: MIT OR Apache-2.0](https://img.shields.io/crates/l/clippy.svg)](#license)
|
||||
|
||||
A collection of lints to catch common mistakes and improve your [Rust](https://github.com/rust-lang/rust) code.
|
||||
|
@ -1,6 +1,5 @@
|
||||
# Clippy
|
||||
|
||||
[![Clippy Test](https://github.com/rust-lang/rust-clippy/workflows/Clippy%20Test%20(bors)/badge.svg?branch=auto&event=push)](https://github.com/rust-lang/rust-clippy/actions?query=workflow%3A%22Clippy+Test+(bors)%22+event%3Apush+branch%3Aauto)
|
||||
[![License: MIT OR Apache-2.0](https://img.shields.io/crates/l/clippy.svg)](https://github.com/rust-lang/rust-clippy#license)
|
||||
|
||||
A collection of lints to catch common mistakes and improve your
|
||||
|
@ -762,13 +762,19 @@ fn parse_contents(contents: &str, module: &str, lints: &mut Vec<Lint>) {
|
||||
Literal{..}(desc)
|
||||
);
|
||||
|
||||
if let Some(LintDeclSearchResult {
|
||||
token_kind: TokenKind::CloseBrace,
|
||||
range,
|
||||
..
|
||||
}) = iter.next()
|
||||
{
|
||||
lints.push(Lint::new(name, group, desc, module, start..range.end));
|
||||
if let Some(end) = iter.find_map(|t| {
|
||||
if let LintDeclSearchResult {
|
||||
token_kind: TokenKind::CloseBrace,
|
||||
range,
|
||||
..
|
||||
} = t
|
||||
{
|
||||
Some(range.end)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}) {
|
||||
lints.push(Lint::new(name, group, desc, module, start..end));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3,11 +3,11 @@
|
||||
use clippy_utils::is_from_proc_macro;
|
||||
use rustc_ast::{AttrStyle, Attribute};
|
||||
use rustc_errors::Applicability;
|
||||
use rustc_lint::{LateContext, LintContext};
|
||||
use rustc_lint::{EarlyContext, LintContext};
|
||||
use rustc_middle::lint::in_external_macro;
|
||||
|
||||
// Separate each crate's features.
|
||||
pub fn check<'cx>(cx: &LateContext<'cx>, attr: &'cx Attribute) {
|
||||
pub fn check<'cx>(cx: &EarlyContext<'cx>, attr: &'cx Attribute) {
|
||||
if !in_external_macro(cx.sess(), attr.span)
|
||||
&& let AttrStyle::Outer = attr.style
|
||||
&& let Some(ident) = attr.ident()
|
||||
|
@ -2,12 +2,12 @@
|
||||
use clippy_utils::diagnostics::span_lint_and_then;
|
||||
use clippy_utils::is_from_proc_macro;
|
||||
use rustc_ast::{MetaItemInner, MetaItemKind};
|
||||
use rustc_lint::{LateContext, LintContext};
|
||||
use rustc_lint::{EarlyContext, LintContext};
|
||||
use rustc_middle::lint::in_external_macro;
|
||||
use rustc_span::sym;
|
||||
use rustc_span::symbol::Symbol;
|
||||
|
||||
pub(super) fn check<'cx>(cx: &LateContext<'cx>, name: Symbol, items: &[MetaItemInner], attr: &'cx Attribute) {
|
||||
pub(super) fn check<'cx>(cx: &EarlyContext<'cx>, name: Symbol, items: &[MetaItemInner], attr: &'cx Attribute) {
|
||||
// Check if the reason is present
|
||||
if let Some(item) = items.last().and_then(MetaItemInner::meta_item)
|
||||
&& let MetaItemKind::NameValue(_) = &item.kind
|
||||
|
@ -2,11 +2,11 @@
|
||||
use super::utils::extract_clippy_lint;
|
||||
use clippy_utils::diagnostics::{span_lint_and_help, span_lint_and_then};
|
||||
use rustc_ast::MetaItemInner;
|
||||
use rustc_lint::{LateContext, Level, LintContext};
|
||||
use rustc_lint::{EarlyContext, Level, LintContext};
|
||||
use rustc_span::symbol::Symbol;
|
||||
use rustc_span::{DUMMY_SP, sym};
|
||||
|
||||
pub(super) fn check(cx: &LateContext<'_>, name: Symbol, items: &[MetaItemInner]) {
|
||||
pub(super) fn check(cx: &EarlyContext<'_>, name: Symbol, items: &[MetaItemInner]) {
|
||||
for lint in items {
|
||||
if let Some(lint_name) = extract_clippy_lint(lint) {
|
||||
if lint_name.as_str() == "restriction" && name != sym::allow {
|
||||
@ -23,7 +23,7 @@ pub(super) fn check(cx: &LateContext<'_>, name: Symbol, items: &[MetaItemInner])
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) fn check_command_line(cx: &LateContext<'_>) {
|
||||
pub(super) fn check_command_line(cx: &EarlyContext<'_>) {
|
||||
for (name, level) in &cx.sess().opts.lint_opts {
|
||||
if name == "clippy::restriction" && *level > Level::Allow {
|
||||
span_lint_and_then(
|
||||
|
@ -1,11 +1,11 @@
|
||||
use super::DEPRECATED_SEMVER;
|
||||
use clippy_utils::diagnostics::span_lint;
|
||||
use rustc_ast::{LitKind, MetaItemLit};
|
||||
use rustc_lint::LateContext;
|
||||
use rustc_lint::EarlyContext;
|
||||
use rustc_span::Span;
|
||||
use semver::Version;
|
||||
|
||||
pub(super) fn check(cx: &LateContext<'_>, span: Span, lit: &MetaItemLit) {
|
||||
pub(super) fn check(cx: &EarlyContext<'_>, span: Span, lit: &MetaItemLit) {
|
||||
if let LitKind::Str(is, _) = lit.kind {
|
||||
if is.as_str() == "TBD" || Version::parse(is.as_str()).is_ok() {
|
||||
return;
|
||||
|
@ -2,12 +2,12 @@
|
||||
use clippy_utils::diagnostics::span_lint_and_then;
|
||||
use rustc_ast::{Attribute, MetaItem};
|
||||
use rustc_data_structures::fx::FxHashMap;
|
||||
use rustc_lint::LateContext;
|
||||
use rustc_lint::EarlyContext;
|
||||
use rustc_span::{Span, sym};
|
||||
use std::collections::hash_map::Entry;
|
||||
|
||||
fn emit_if_duplicated(
|
||||
cx: &LateContext<'_>,
|
||||
cx: &EarlyContext<'_>,
|
||||
attr: &MetaItem,
|
||||
attr_paths: &mut FxHashMap<String, Span>,
|
||||
complete_path: String,
|
||||
@ -26,7 +26,7 @@ fn emit_if_duplicated(
|
||||
}
|
||||
|
||||
fn check_duplicated_attr(
|
||||
cx: &LateContext<'_>,
|
||||
cx: &EarlyContext<'_>,
|
||||
attr: &MetaItem,
|
||||
attr_paths: &mut FxHashMap<String, Span>,
|
||||
parent: &mut Vec<String>,
|
||||
@ -65,7 +65,7 @@ fn check_duplicated_attr(
|
||||
}
|
||||
}
|
||||
|
||||
pub fn check(cx: &LateContext<'_>, attrs: &[Attribute]) {
|
||||
pub fn check(cx: &EarlyContext<'_>, attrs: &[Attribute]) {
|
||||
let mut attr_paths = FxHashMap::default();
|
||||
|
||||
for attr in attrs {
|
||||
|
@ -3,7 +3,7 @@
|
||||
use rustc_ast::{AttrKind, AttrStyle, Attribute};
|
||||
use rustc_data_structures::fx::FxHashSet;
|
||||
use rustc_data_structures::sync::Lrc;
|
||||
use rustc_lint::{LateContext, LintContext};
|
||||
use rustc_lint::{EarlyContext, LintContext};
|
||||
use rustc_span::source_map::SourceMap;
|
||||
use rustc_span::{SourceFile, Span, Symbol};
|
||||
|
||||
@ -32,7 +32,7 @@ fn from(value: &AttrKind) -> Self {
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) fn check(cx: &LateContext<'_>, item_span: Span, attrs: &[Attribute]) {
|
||||
pub(super) fn check(cx: &EarlyContext<'_>, item_span: Span, attrs: &[Attribute]) {
|
||||
let mut inner_attr_kind: FxHashSet<SimpleAttrKind> = FxHashSet::default();
|
||||
let mut outer_attr_kind: FxHashSet<SimpleAttrKind> = FxHashSet::default();
|
||||
|
||||
@ -64,7 +64,7 @@ pub(super) fn check(cx: &LateContext<'_>, item_span: Span, attrs: &[Attribute])
|
||||
}
|
||||
}
|
||||
|
||||
fn lint_mixed_attrs(cx: &LateContext<'_>, attrs: &[Attribute]) {
|
||||
fn lint_mixed_attrs(cx: &EarlyContext<'_>, attrs: &[Attribute]) {
|
||||
let mut attrs_iter = attrs.iter().filter(|attr| !attr.span.from_expansion());
|
||||
let span = if let (Some(first), Some(last)) = (attrs_iter.next(), attrs_iter.last()) {
|
||||
first.span.with_hi(last.span.hi())
|
||||
|
@ -14,8 +14,8 @@
|
||||
|
||||
use clippy_config::Conf;
|
||||
use clippy_config::msrvs::{self, Msrv};
|
||||
use rustc_ast::{Attribute, MetaItemInner, MetaItemKind};
|
||||
use rustc_hir::{ImplItem, Item, ItemKind, TraitItem};
|
||||
use rustc_ast::{self as ast, Attribute, MetaItemInner, MetaItemKind};
|
||||
use rustc_hir::{ImplItem, Item, TraitItem};
|
||||
use rustc_lint::{EarlyContext, EarlyLintPass, LateContext, LateLintPass};
|
||||
use rustc_session::impl_lint_pass;
|
||||
use rustc_span::sym;
|
||||
@ -414,15 +414,7 @@ pub struct Attributes {
|
||||
}
|
||||
|
||||
impl_lint_pass!(Attributes => [
|
||||
ALLOW_ATTRIBUTES,
|
||||
ALLOW_ATTRIBUTES_WITHOUT_REASON,
|
||||
INLINE_ALWAYS,
|
||||
DEPRECATED_SEMVER,
|
||||
USELESS_ATTRIBUTE,
|
||||
BLANKET_CLIPPY_RESTRICTION_LINTS,
|
||||
SHOULD_PANIC_WITHOUT_EXPECT,
|
||||
MIXED_ATTRIBUTES_STYLE,
|
||||
DUPLICATED_ATTRIBUTES,
|
||||
]);
|
||||
|
||||
impl Attributes {
|
||||
@ -434,53 +426,11 @@ pub fn new(conf: &'static Conf) -> Self {
|
||||
}
|
||||
|
||||
impl<'tcx> LateLintPass<'tcx> for Attributes {
|
||||
fn check_crate(&mut self, cx: &LateContext<'tcx>) {
|
||||
blanket_clippy_restriction_lints::check_command_line(cx);
|
||||
duplicated_attributes::check(cx, cx.tcx.hir().krate_attrs());
|
||||
}
|
||||
|
||||
fn check_attribute(&mut self, cx: &LateContext<'tcx>, attr: &'tcx Attribute) {
|
||||
if let Some(items) = &attr.meta_item_list() {
|
||||
if let Some(ident) = attr.ident() {
|
||||
if is_lint_level(ident.name, attr.id) {
|
||||
blanket_clippy_restriction_lints::check(cx, ident.name, items);
|
||||
}
|
||||
if matches!(ident.name, sym::allow) && self.msrv.meets(msrvs::LINT_REASONS_STABILIZATION) {
|
||||
allow_attributes::check(cx, attr);
|
||||
}
|
||||
if matches!(ident.name, sym::allow | sym::expect) && self.msrv.meets(msrvs::LINT_REASONS_STABILIZATION)
|
||||
{
|
||||
allow_attributes_without_reason::check(cx, ident.name, items, attr);
|
||||
}
|
||||
if items.is_empty() || !attr.has_name(sym::deprecated) {
|
||||
return;
|
||||
}
|
||||
for item in items {
|
||||
if let MetaItemInner::MetaItem(mi) = &item
|
||||
&& let MetaItemKind::NameValue(lit) = &mi.kind
|
||||
&& mi.has_name(sym::since)
|
||||
{
|
||||
deprecated_semver::check(cx, item.span(), lit);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if attr.has_name(sym::should_panic) {
|
||||
should_panic_without_expect::check(cx, attr);
|
||||
}
|
||||
}
|
||||
|
||||
fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) {
|
||||
let attrs = cx.tcx.hir().attrs(item.hir_id());
|
||||
if is_relevant_item(cx, item) {
|
||||
inline_always::check(cx, item.span, item.ident.name, attrs);
|
||||
}
|
||||
match item.kind {
|
||||
ItemKind::ExternCrate(..) | ItemKind::Use(..) => useless_attribute::check(cx, item, attrs),
|
||||
_ => {},
|
||||
}
|
||||
mixed_attributes_style::check(cx, item.span, attrs);
|
||||
duplicated_attributes::check(cx, attrs);
|
||||
}
|
||||
|
||||
fn check_impl_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx ImplItem<'_>) {
|
||||
@ -526,3 +476,77 @@ fn check_attribute(&mut self, cx: &EarlyContext<'_>, attr: &Attribute) {
|
||||
|
||||
extract_msrv_attr!(EarlyContext);
|
||||
}
|
||||
|
||||
pub struct PostExpansionEarlyAttributes {
|
||||
msrv: Msrv,
|
||||
}
|
||||
|
||||
impl PostExpansionEarlyAttributes {
|
||||
pub fn new(conf: &'static Conf) -> Self {
|
||||
Self {
|
||||
msrv: conf.msrv.clone(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl_lint_pass!(PostExpansionEarlyAttributes => [
|
||||
ALLOW_ATTRIBUTES,
|
||||
ALLOW_ATTRIBUTES_WITHOUT_REASON,
|
||||
DEPRECATED_SEMVER,
|
||||
USELESS_ATTRIBUTE,
|
||||
BLANKET_CLIPPY_RESTRICTION_LINTS,
|
||||
SHOULD_PANIC_WITHOUT_EXPECT,
|
||||
MIXED_ATTRIBUTES_STYLE,
|
||||
DUPLICATED_ATTRIBUTES,
|
||||
]);
|
||||
|
||||
impl EarlyLintPass for PostExpansionEarlyAttributes {
|
||||
fn check_crate(&mut self, cx: &EarlyContext<'_>, krate: &ast::Crate) {
|
||||
blanket_clippy_restriction_lints::check_command_line(cx);
|
||||
duplicated_attributes::check(cx, &krate.attrs);
|
||||
}
|
||||
|
||||
fn check_attribute(&mut self, cx: &EarlyContext<'_>, attr: &Attribute) {
|
||||
if let Some(items) = &attr.meta_item_list() {
|
||||
if let Some(ident) = attr.ident() {
|
||||
if matches!(ident.name, sym::allow) && self.msrv.meets(msrvs::LINT_REASONS_STABILIZATION) {
|
||||
allow_attributes::check(cx, attr);
|
||||
}
|
||||
if matches!(ident.name, sym::allow | sym::expect) && self.msrv.meets(msrvs::LINT_REASONS_STABILIZATION)
|
||||
{
|
||||
allow_attributes_without_reason::check(cx, ident.name, items, attr);
|
||||
}
|
||||
if is_lint_level(ident.name, attr.id) {
|
||||
blanket_clippy_restriction_lints::check(cx, ident.name, items);
|
||||
}
|
||||
if items.is_empty() || !attr.has_name(sym::deprecated) {
|
||||
return;
|
||||
}
|
||||
for item in items {
|
||||
if let MetaItemInner::MetaItem(mi) = &item
|
||||
&& let MetaItemKind::NameValue(lit) = &mi.kind
|
||||
&& mi.has_name(sym::since)
|
||||
{
|
||||
deprecated_semver::check(cx, item.span(), lit);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if attr.has_name(sym::should_panic) {
|
||||
should_panic_without_expect::check(cx, attr);
|
||||
}
|
||||
}
|
||||
|
||||
fn check_item(&mut self, cx: &EarlyContext<'_>, item: &'_ ast::Item) {
|
||||
match item.kind {
|
||||
ast::ItemKind::ExternCrate(..) | ast::ItemKind::Use(..) => useless_attribute::check(cx, item, &item.attrs),
|
||||
_ => {},
|
||||
}
|
||||
|
||||
mixed_attributes_style::check(cx, item.span, &item.attrs);
|
||||
duplicated_attributes::check(cx, &item.attrs);
|
||||
}
|
||||
|
||||
extract_msrv_attr!(EarlyContext);
|
||||
}
|
||||
|
@ -4,12 +4,12 @@
|
||||
use rustc_ast::tokenstream::TokenTree;
|
||||
use rustc_ast::{AttrArgs, AttrArgsEq, AttrKind};
|
||||
use rustc_errors::Applicability;
|
||||
use rustc_lint::LateContext;
|
||||
use rustc_lint::EarlyContext;
|
||||
use rustc_span::sym;
|
||||
|
||||
pub(super) fn check(cx: &LateContext<'_>, attr: &Attribute) {
|
||||
pub(super) fn check(cx: &EarlyContext<'_>, attr: &Attribute) {
|
||||
if let AttrKind::Normal(normal_attr) = &attr.kind {
|
||||
if let AttrArgs::Eq(_, AttrArgsEq::Hir(_)) = &normal_attr.item.args {
|
||||
if let AttrArgs::Eq(_, AttrArgsEq::Ast(_)) = &normal_attr.item.args {
|
||||
// `#[should_panic = ".."]` found, good
|
||||
return;
|
||||
}
|
||||
|
@ -1,15 +1,14 @@
|
||||
use super::USELESS_ATTRIBUTE;
|
||||
use super::utils::{extract_clippy_lint, is_lint_level, is_word};
|
||||
use super::{Attribute, USELESS_ATTRIBUTE};
|
||||
use clippy_utils::diagnostics::span_lint_and_then;
|
||||
use clippy_utils::source::{SpanRangeExt, first_line_of_span};
|
||||
use rustc_ast::MetaItemInner;
|
||||
use rustc_ast::{Attribute, Item, ItemKind, MetaItemInner};
|
||||
use rustc_errors::Applicability;
|
||||
use rustc_hir::{Item, ItemKind};
|
||||
use rustc_lint::{LateContext, LintContext};
|
||||
use rustc_lint::{EarlyContext, LintContext};
|
||||
use rustc_middle::lint::in_external_macro;
|
||||
use rustc_span::sym;
|
||||
|
||||
pub(super) fn check(cx: &LateContext<'_>, item: &Item<'_>, attrs: &[Attribute]) {
|
||||
pub(super) fn check(cx: &EarlyContext<'_>, item: &Item, attrs: &[Attribute]) {
|
||||
let skip_unused_imports = attrs.iter().any(|attr| attr.has_name(sym::macro_use));
|
||||
|
||||
for attr in attrs {
|
||||
|
@ -30,7 +30,8 @@
|
||||
#[clippy::version = "1.35.0"]
|
||||
pub COGNITIVE_COMPLEXITY,
|
||||
nursery,
|
||||
"functions that should be split up into multiple functions"
|
||||
"functions that should be split up into multiple functions",
|
||||
@eval_always = true
|
||||
}
|
||||
|
||||
pub struct CognitiveComplexity {
|
||||
|
26
clippy_lints/src/ctfe.rs
Normal file
26
clippy_lints/src/ctfe.rs
Normal file
@ -0,0 +1,26 @@
|
||||
use rustc_hir::def_id::LocalDefId;
|
||||
use rustc_hir::intravisit::FnKind;
|
||||
use rustc_hir::{Body, FnDecl};
|
||||
use rustc_lint::{LateContext, LateLintPass};
|
||||
use rustc_session::declare_lint_pass;
|
||||
use rustc_span::Span;
|
||||
|
||||
declare_lint_pass! {
|
||||
/// Ensures that Constant-time Function Evaluation is being done (specifically, MIR lint passes).
|
||||
/// As Clippy deactivates codegen, this lint ensures that CTFE (used in hard errors) is still ran.
|
||||
ClippyCtfe => []
|
||||
}
|
||||
|
||||
impl<'tcx> LateLintPass<'tcx> for ClippyCtfe {
|
||||
fn check_fn(
|
||||
&mut self,
|
||||
cx: &LateContext<'_>,
|
||||
_: FnKind<'tcx>,
|
||||
_: &'tcx FnDecl<'tcx>,
|
||||
_: &'tcx Body<'tcx>,
|
||||
_: Span,
|
||||
defid: LocalDefId,
|
||||
) {
|
||||
cx.tcx.ensure().mir_drops_elaborated_and_const_checked(defid); // Lint
|
||||
}
|
||||
}
|
@ -4,19 +4,21 @@ macro_rules! declare_clippy_lint {
|
||||
(@
|
||||
$(#[doc = $lit:literal])*
|
||||
pub $lint_name:ident,
|
||||
$category:ident,
|
||||
$level:ident,
|
||||
$lintcategory:expr,
|
||||
$desc:literal,
|
||||
$version_expr:expr,
|
||||
$version_lit:literal
|
||||
$(, $eval_always: literal)?
|
||||
) => {
|
||||
rustc_session::declare_tool_lint! {
|
||||
$(#[doc = $lit])*
|
||||
#[clippy::version = $version_lit]
|
||||
pub clippy::$lint_name,
|
||||
$category,
|
||||
$level,
|
||||
$desc,
|
||||
report_in_external_macro:true
|
||||
$(, @eval_always = $eval_always)?
|
||||
}
|
||||
|
||||
pub(crate) static ${concat($lint_name, _INFO)}: &'static crate::LintInfo = &crate::LintInfo {
|
||||
@ -33,11 +35,13 @@ macro_rules! declare_clippy_lint {
|
||||
pub $lint_name:ident,
|
||||
restriction,
|
||||
$desc:literal
|
||||
$(, @eval_always = $eval_always: literal)?
|
||||
) => {
|
||||
declare_clippy_lint! {@
|
||||
$(#[doc = $lit])*
|
||||
pub $lint_name, Allow, crate::LintCategory::Restriction, $desc,
|
||||
Some($version), $version
|
||||
$(, $eval_always)?
|
||||
}
|
||||
};
|
||||
(
|
||||
@ -46,12 +50,13 @@ macro_rules! declare_clippy_lint {
|
||||
pub $lint_name:ident,
|
||||
style,
|
||||
$desc:literal
|
||||
$(, @eval_always = $eval_always: literal)?
|
||||
) => {
|
||||
declare_clippy_lint! {@
|
||||
$(#[doc = $lit])*
|
||||
pub $lint_name, Warn, crate::LintCategory::Style, $desc,
|
||||
Some($version), $version
|
||||
|
||||
$(, $eval_always)?
|
||||
}
|
||||
};
|
||||
(
|
||||
@ -60,11 +65,13 @@ macro_rules! declare_clippy_lint {
|
||||
pub $lint_name:ident,
|
||||
correctness,
|
||||
$desc:literal
|
||||
$(, @eval_always = $eval_always: literal)?
|
||||
) => {
|
||||
declare_clippy_lint! {@
|
||||
$(#[doc = $lit])*
|
||||
pub $lint_name, Deny, crate::LintCategory::Correctness, $desc,
|
||||
Some($version), $version
|
||||
$(, $eval_always)?
|
||||
|
||||
}
|
||||
};
|
||||
@ -74,11 +81,13 @@ macro_rules! declare_clippy_lint {
|
||||
pub $lint_name:ident,
|
||||
perf,
|
||||
$desc:literal
|
||||
$(, @eval_always = $eval_always: literal)?
|
||||
) => {
|
||||
declare_clippy_lint! {@
|
||||
$(#[doc = $lit])*
|
||||
pub $lint_name, Warn, crate::LintCategory::Perf, $desc,
|
||||
Some($version), $version
|
||||
$(, $eval_always)?
|
||||
}
|
||||
};
|
||||
(
|
||||
@ -87,11 +96,13 @@ macro_rules! declare_clippy_lint {
|
||||
pub $lint_name:ident,
|
||||
complexity,
|
||||
$desc:literal
|
||||
$(, @eval_always = $eval_always: literal)?
|
||||
) => {
|
||||
declare_clippy_lint! {@
|
||||
$(#[doc = $lit])*
|
||||
pub $lint_name, Warn, crate::LintCategory::Complexity, $desc,
|
||||
Some($version), $version
|
||||
$(, $eval_always)?
|
||||
}
|
||||
};
|
||||
(
|
||||
@ -100,11 +111,13 @@ macro_rules! declare_clippy_lint {
|
||||
pub $lint_name:ident,
|
||||
suspicious,
|
||||
$desc:literal
|
||||
$(, @eval_always = $eval_always: literal)?
|
||||
) => {
|
||||
declare_clippy_lint! {@
|
||||
$(#[doc = $lit])*
|
||||
pub $lint_name, Warn, crate::LintCategory::Suspicious, $desc,
|
||||
Some($version), $version
|
||||
$(, $eval_always)?
|
||||
}
|
||||
};
|
||||
(
|
||||
@ -113,11 +126,13 @@ macro_rules! declare_clippy_lint {
|
||||
pub $lint_name:ident,
|
||||
nursery,
|
||||
$desc:literal
|
||||
$(, @eval_always = $eval_always: literal)?
|
||||
) => {
|
||||
declare_clippy_lint! {@
|
||||
$(#[doc = $lit])*
|
||||
pub $lint_name, Allow, crate::LintCategory::Nursery, $desc,
|
||||
Some($version), $version
|
||||
$(, $eval_always)?
|
||||
}
|
||||
};
|
||||
(
|
||||
@ -126,11 +141,13 @@ macro_rules! declare_clippy_lint {
|
||||
pub $lint_name:ident,
|
||||
pedantic,
|
||||
$desc:literal
|
||||
$(, @eval_always = $eval_always: literal)?
|
||||
) => {
|
||||
declare_clippy_lint! {@
|
||||
$(#[doc = $lit])*
|
||||
pub $lint_name, Allow, crate::LintCategory::Pedantic, $desc,
|
||||
Some($version), $version
|
||||
$(, $eval_always)?
|
||||
}
|
||||
};
|
||||
(
|
||||
@ -139,11 +156,13 @@ macro_rules! declare_clippy_lint {
|
||||
pub $lint_name:ident,
|
||||
cargo,
|
||||
$desc:literal
|
||||
$(, @eval_always = $eval_always: literal)?
|
||||
) => {
|
||||
declare_clippy_lint! {@
|
||||
$(#[doc = $lit])*
|
||||
pub $lint_name, Allow, crate::LintCategory::Cargo, $desc,
|
||||
Some($version), $version
|
||||
$(, $eval_always)?
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -166,7 +166,7 @@ macro_rules! declare_with_version {
|
||||
#[clippy::version = ""]
|
||||
("clippy::positional_named_format_parameters", "named_arguments_used_positionally"),
|
||||
#[clippy::version = ""]
|
||||
("clippy::temporary_cstring_as_ptr", "temporary_cstring_as_ptr"),
|
||||
("clippy::temporary_cstring_as_ptr", "dangling_pointers_from_temporaries"),
|
||||
#[clippy::version = ""]
|
||||
("clippy::undropped_manually_drops", "undropped_manually_drops"),
|
||||
#[clippy::version = ""]
|
||||
|
@ -418,7 +418,7 @@ fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
|
||||
let (required_refs, msg) = if can_auto_borrow {
|
||||
(1, if deref_count == 1 { borrow_msg } else { deref_msg })
|
||||
} else if let Some(&Adjustment {
|
||||
kind: Adjust::Borrow(AutoBorrow::Ref(_, mutability)),
|
||||
kind: Adjust::Borrow(AutoBorrow::Ref(mutability)),
|
||||
..
|
||||
}) = next_adjust
|
||||
&& matches!(mutability, AutoBorrowMutability::Mut { .. })
|
||||
|
@ -326,7 +326,7 @@ fn check_copy_clone<'tcx>(cx: &LateContext<'tcx>, item: &Item<'_>, trait_ref: &h
|
||||
// If the current self type doesn't implement Copy (due to generic constraints), search to see if
|
||||
// there's a Copy impl for any instance of the adt.
|
||||
if !is_copy(cx, ty) {
|
||||
if ty_subs.non_erasable_generics(cx.tcx, ty_adt.did()).next().is_some() {
|
||||
if ty_subs.non_erasable_generics().next().is_some() {
|
||||
let has_copy_impl = cx.tcx.all_local_trait_impls(()).get(©_id).map_or(false, |impls| {
|
||||
impls.iter().any(|&id| {
|
||||
matches!(cx.tcx.type_of(id).instantiate_identity().kind(), ty::Adt(adt, _)
|
||||
|
@ -64,7 +64,7 @@ impl LateLintPass<'_> for EmptyEnum {
|
||||
fn check_item(&mut self, cx: &LateContext<'_>, item: &Item<'_>) {
|
||||
if let ItemKind::Enum(..) = item.kind
|
||||
// Only suggest the `never_type` if the feature is enabled
|
||||
&& cx.tcx.features().never_type
|
||||
&& cx.tcx.features().never_type()
|
||||
&& let Some(adt) = cx.tcx.type_of(item.owner_id).instantiate_identity().ty_adt_def()
|
||||
&& adt.variants().is_empty()
|
||||
{
|
||||
|
@ -203,11 +203,16 @@ fn check_clousure<'tcx>(cx: &LateContext<'tcx>, outer_receiver: Option<&Expr<'tc
|
||||
// 'cuz currently nothing changes after deleting this check.
|
||||
local_used_in(cx, l, args) || local_used_after_expr(cx, l, expr)
|
||||
}) {
|
||||
match cx.tcx.infer_ctxt().build().err_ctxt().type_implements_fn_trait(
|
||||
cx.param_env,
|
||||
Binder::bind_with_vars(callee_ty_adjusted, List::empty()),
|
||||
ty::PredicatePolarity::Positive,
|
||||
) {
|
||||
match cx
|
||||
.tcx
|
||||
.infer_ctxt()
|
||||
.build(cx.typing_mode())
|
||||
.err_ctxt()
|
||||
.type_implements_fn_trait(
|
||||
cx.param_env,
|
||||
Binder::bind_with_vars(callee_ty_adjusted, List::empty()),
|
||||
ty::PredicatePolarity::Positive,
|
||||
) {
|
||||
// Mutable closure is used after current expr; we cannot consume it.
|
||||
Ok((ClosureKind::FnMut, _)) => snippet = format!("&mut {snippet}"),
|
||||
Ok((ClosureKind::Fn, _)) if !callee_ty_raw.is_ref() => {
|
||||
|
@ -117,7 +117,7 @@ fn check_needless_must_use(
|
||||
} else if attr.value_str().is_none() && is_must_use_ty(cx, return_ty(cx, item_id)) {
|
||||
// Ignore async functions unless Future::Output type is a must_use type
|
||||
if sig.header.is_async() {
|
||||
let infcx = cx.tcx.infer_ctxt().build();
|
||||
let infcx = cx.tcx.infer_ctxt().build(cx.typing_mode());
|
||||
if let Some(future_ty) = infcx.err_ctxt().get_impl_future_output_ty(return_ty(cx, item_id))
|
||||
&& !is_must_use_ty(cx, future_ty)
|
||||
{
|
||||
|
@ -74,7 +74,7 @@ fn check_fn(
|
||||
if is_future {
|
||||
let send_trait = cx.tcx.get_diagnostic_item(sym::Send).unwrap();
|
||||
let span = decl.output.span();
|
||||
let infcx = cx.tcx.infer_ctxt().build();
|
||||
let infcx = cx.tcx.infer_ctxt().build(cx.typing_mode());
|
||||
let ocx = ObligationCtxt::new_with_diagnostics(&infcx);
|
||||
let cause = traits::ObligationCause::misc(span, fn_def_id);
|
||||
ocx.register_bound(cause, cx.param_env, ret_ty, send_trait);
|
||||
|
@ -3,7 +3,7 @@
|
||||
use rustc_errors::{Applicability, SuggestionStyle};
|
||||
use rustc_hir::def_id::DefId;
|
||||
use rustc_hir::{
|
||||
AssocItemConstraint, GenericArg, GenericBound, GenericBounds, PredicateOrigin, TraitBoundModifier, TyKind,
|
||||
AssocItemConstraint, GenericArg, GenericBound, GenericBounds, PredicateOrigin, TraitBoundModifiers, TyKind,
|
||||
WherePredicate,
|
||||
};
|
||||
use rustc_hir_analysis::lower_ty;
|
||||
@ -190,15 +190,6 @@ fn is_same_generics<'tcx>(
|
||||
.enumerate()
|
||||
.skip(1) // skip `Self` implicit arg
|
||||
.all(|(arg_index, arg)| {
|
||||
if [
|
||||
implied_by_generics.host_effect_index,
|
||||
implied_generics.host_effect_index,
|
||||
]
|
||||
.contains(&Some(arg_index))
|
||||
{
|
||||
// skip host effect params in determining whether generics are same
|
||||
return true;
|
||||
}
|
||||
if let Some(ty) = arg.as_type() {
|
||||
if let &ty::Param(ty::ParamTy { index, .. }) = ty.kind()
|
||||
// `index == 0` means that it's referring to `Self`,
|
||||
@ -243,7 +234,7 @@ fn collect_supertrait_bounds<'tcx>(cx: &LateContext<'tcx>, bounds: GenericBounds
|
||||
.iter()
|
||||
.filter_map(|bound| {
|
||||
if let GenericBound::Trait(poly_trait) = bound
|
||||
&& let TraitBoundModifier::None = poly_trait.modifiers
|
||||
&& let TraitBoundModifiers::NONE = poly_trait.modifiers
|
||||
&& let [.., path] = poly_trait.trait_ref.path.segments
|
||||
&& poly_trait.bound_generic_params.is_empty()
|
||||
&& let Some(trait_def_id) = path.res.opt_def_id()
|
||||
@ -309,7 +300,7 @@ fn check<'tcx>(cx: &LateContext<'tcx>, bounds: GenericBounds<'tcx>) {
|
||||
// simply comparing trait `DefId`s won't be enough. We also need to compare the generics.
|
||||
for (index, bound) in bounds.iter().enumerate() {
|
||||
if let GenericBound::Trait(poly_trait) = bound
|
||||
&& let TraitBoundModifier::None = poly_trait.modifiers
|
||||
&& let TraitBoundModifiers::NONE = poly_trait.modifiers
|
||||
&& let [.., path] = poly_trait.trait_ref.path.segments
|
||||
&& let implied_args = path.args.map_or([].as_slice(), |a| a.args)
|
||||
&& let implied_constraints = path.args.map_or([].as_slice(), |a| a.constraints)
|
||||
|
@ -114,7 +114,7 @@ fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
|
||||
if let Some(range) = higher::Range::hir(index) {
|
||||
// Ranged indexes, i.e., &x[n..m], &x[n..], &x[..n] and &x[..]
|
||||
if let ty::Array(_, s) = ty.kind() {
|
||||
let size: u128 = if let Some(size) = s.try_eval_target_usize(cx.tcx, cx.param_env) {
|
||||
let size: u128 = if let Some(size) = s.try_to_target_usize(cx.tcx) {
|
||||
size.into()
|
||||
} else {
|
||||
return;
|
||||
@ -183,7 +183,7 @@ fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
|
||||
&& let ty::Uint(utype) = cx.typeck_results().expr_ty(index).kind()
|
||||
&& *utype == ty::UintTy::Usize
|
||||
&& let ty::Array(_, s) = ty.kind()
|
||||
&& let Some(size) = s.try_eval_target_usize(cx.tcx, cx.param_env)
|
||||
&& let Some(size) = s.try_to_target_usize(cx.tcx)
|
||||
{
|
||||
// get constant offset and check whether it is in bounds
|
||||
let off = usize::try_from(off).unwrap();
|
||||
|
@ -56,7 +56,7 @@ fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) {
|
||||
&& !item.span.from_expansion()
|
||||
&& let ty = cx.tcx.type_of(item.owner_id).instantiate_identity()
|
||||
&& let ty::Array(element_type, cst) = ty.kind()
|
||||
&& let Ok((_, ty::ValTree::Leaf(element_count))) = cst.eval(cx.tcx, ParamEnv::empty(), item.span)
|
||||
&& let Ok((_, ty::ValTree::Leaf(element_count))) = cst.eval_valtree(cx.tcx, ParamEnv::empty(), item.span)
|
||||
&& let element_count = element_count.to_target_usize(cx.tcx)
|
||||
&& let Ok(element_size) = cx.layout_of(*element_type).map(|l| l.size.bytes())
|
||||
&& u128::from(self.maximum_allowed_size) < u128::from(element_count) * u128::from(element_size)
|
||||
|
@ -65,6 +65,7 @@
|
||||
#[cfg_attr(feature = "internal", allow(clippy::missing_clippy_version_attribute))]
|
||||
mod utils;
|
||||
|
||||
pub mod ctfe; // Very important lint, do not remove (rust#125116)
|
||||
pub mod declared_lints;
|
||||
pub mod deprecated_lints;
|
||||
|
||||
@ -412,6 +413,8 @@
|
||||
pub fn register_pre_expansion_lints(store: &mut rustc_lint::LintStore, conf: &'static Conf) {
|
||||
// NOTE: Do not add any more pre-expansion passes. These should be removed eventually.
|
||||
store.register_pre_expansion_pass(move || Box::new(attrs::EarlyAttributes::new(conf)));
|
||||
|
||||
store.register_early_pass(move || Box::new(attrs::PostExpansionEarlyAttributes::new(conf)));
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
@ -607,6 +610,8 @@ pub fn register_lints(store: &mut rustc_lint::LintStore, conf: &'static Conf) {
|
||||
store.register_late_pass(|_| Box::new(utils::internal_lints::slow_symbol_comparisons::SlowSymbolComparisons));
|
||||
}
|
||||
|
||||
store.register_late_pass(|_| Box::new(ctfe::ClippyCtfe));
|
||||
|
||||
store.register_late_pass(move |_| Box::new(operators::arithmetic_side_effects::ArithmeticSideEffects::new(conf)));
|
||||
store.register_late_pass(|_| Box::new(utils::dump_hir::DumpHir));
|
||||
store.register_late_pass(|_| Box::new(utils::author::Author));
|
||||
|
@ -420,15 +420,6 @@ fn visit_poly_trait_ref(&mut self, poly_tref: &'tcx PolyTraitRef<'tcx>) {
|
||||
|
||||
fn visit_ty(&mut self, ty: &'tcx Ty<'_>) {
|
||||
match ty.kind {
|
||||
TyKind::OpaqueDef(opaque, bounds) => {
|
||||
let len = self.lts.len();
|
||||
self.visit_opaque_ty(opaque);
|
||||
self.lts.truncate(len);
|
||||
self.lts.extend(bounds.iter().filter_map(|bound| match bound {
|
||||
&GenericArg::Lifetime(l) => Some(l),
|
||||
_ => None,
|
||||
}));
|
||||
},
|
||||
TyKind::BareFn(&BareFnTy { decl, .. }) => {
|
||||
let mut sub_visitor = RefVisitor::new(self.cx);
|
||||
sub_visitor.visit_fn_decl(decl);
|
||||
|
@ -53,7 +53,7 @@ pub(super) fn check(cx: &LateContext<'_>, self_arg: &Expr<'_>, call_expr: &Expr<
|
||||
[] => AdjustKind::None,
|
||||
&[
|
||||
Adjustment {
|
||||
kind: Adjust::Borrow(AutoBorrow::Ref(_, mutbl)),
|
||||
kind: Adjust::Borrow(AutoBorrow::Ref(mutbl)),
|
||||
..
|
||||
},
|
||||
] => AdjustKind::borrow(mutbl),
|
||||
@ -62,7 +62,7 @@ pub(super) fn check(cx: &LateContext<'_>, self_arg: &Expr<'_>, call_expr: &Expr<
|
||||
kind: Adjust::Deref(_), ..
|
||||
},
|
||||
Adjustment {
|
||||
kind: Adjust::Borrow(AutoBorrow::Ref(_, mutbl)),
|
||||
kind: Adjust::Borrow(AutoBorrow::Ref(mutbl)),
|
||||
target,
|
||||
},
|
||||
] => {
|
||||
|
@ -29,11 +29,7 @@ pub(super) fn check(
|
||||
if !msrv.meets(msrvs::ARRAY_INTO_ITERATOR) {
|
||||
return;
|
||||
}
|
||||
} else if count
|
||||
.try_eval_target_usize(cx.tcx, cx.param_env)
|
||||
.map_or(true, |x| x > 32)
|
||||
&& !msrv.meets(msrvs::ARRAY_IMPL_ANY_LEN)
|
||||
{
|
||||
} else if count.try_to_target_usize(cx.tcx).map_or(true, |x| x > 32) && !msrv.meets(msrvs::ARRAY_IMPL_ANY_LEN) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -199,7 +195,7 @@ fn is_ref_iterable<'tcx>(
|
||||
kind: Adjust::Deref(_), ..
|
||||
},
|
||||
Adjustment {
|
||||
kind: Adjust::Borrow(AutoBorrow::Ref(_, mutbl)),
|
||||
kind: Adjust::Borrow(AutoBorrow::Ref(mutbl)),
|
||||
target,
|
||||
},
|
||||
..,
|
||||
@ -236,7 +232,7 @@ fn is_ref_iterable<'tcx>(
|
||||
},
|
||||
&[
|
||||
Adjustment {
|
||||
kind: Adjust::Borrow(AutoBorrow::Ref(_, mutbl)),
|
||||
kind: Adjust::Borrow(AutoBorrow::Ref(mutbl)),
|
||||
target,
|
||||
},
|
||||
..,
|
||||
|
@ -158,14 +158,11 @@ fn is_never_return(ret_ty: FnRetTy<'_>) -> bool {
|
||||
|
||||
match hir_ty.kind {
|
||||
TyKind::Never => true,
|
||||
TyKind::OpaqueDef(
|
||||
hir::OpaqueTy {
|
||||
origin: hir::OpaqueTyOrigin::AsyncFn { .. },
|
||||
bounds,
|
||||
..
|
||||
},
|
||||
_,
|
||||
) => {
|
||||
TyKind::OpaqueDef(hir::OpaqueTy {
|
||||
origin: hir::OpaqueTyOrigin::AsyncFn { .. },
|
||||
bounds,
|
||||
..
|
||||
}) => {
|
||||
if let Some(trait_ref) = bounds.iter().find_map(|b| b.trait_ref())
|
||||
&& let Some(segment) = trait_ref
|
||||
.path
|
||||
|
@ -472,7 +472,7 @@ fn extract_lit_value(expr: &Expr<'_>) -> Option<u128> {
|
||||
let arr_ty = cx.typeck_results().expr_ty(arr).peel_refs();
|
||||
|
||||
if let ty::Array(_, s) = arr_ty.kind() {
|
||||
let size: u128 = if let Some(size) = s.try_eval_target_usize(cx.tcx, cx.param_env) {
|
||||
let size: u128 = if let Some(size) = s.try_to_target_usize(cx.tcx) {
|
||||
size.into()
|
||||
} else {
|
||||
return false;
|
||||
|
@ -80,7 +80,7 @@ impl<'tcx> Delegate<'tcx> for MutatePairDelegate<'_, 'tcx> {
|
||||
fn consume(&mut self, _: &PlaceWithHirId<'tcx>, _: HirId) {}
|
||||
|
||||
fn borrow(&mut self, cmt: &PlaceWithHirId<'tcx>, diag_expr_id: HirId, bk: ty::BorrowKind) {
|
||||
if bk == ty::BorrowKind::MutBorrow {
|
||||
if bk == ty::BorrowKind::Mutable {
|
||||
if let PlaceBase::Local(id) = cmt.place.base {
|
||||
if Some(id) == self.hir_id_low && !BreakAfterExprVisitor::is_found(self.cx, diag_expr_id) {
|
||||
self.span_low = Some(self.cx.tcx.hir().span(diag_expr_id));
|
||||
|
@ -207,7 +207,7 @@ fn is_end_eq_array_len<'tcx>(
|
||||
if let ExprKind::Lit(lit) = end.kind
|
||||
&& let ast::LitKind::Int(end_int, _) = lit.node
|
||||
&& let ty::Array(_, arr_len_const) = indexed_ty.kind()
|
||||
&& let Some(arr_len) = arr_len_const.try_eval_target_usize(cx.tcx, cx.param_env)
|
||||
&& let Some(arr_len) = arr_len_const.try_to_target_usize(cx.tcx)
|
||||
{
|
||||
return match limits {
|
||||
ast::RangeLimits::Closed => end_int.get() + 1 >= arr_len.into(),
|
||||
|
@ -4,9 +4,11 @@
|
||||
use rustc_hir::intravisit::FnKind;
|
||||
use rustc_hir::{
|
||||
Block, Body, Closure, ClosureKind, CoroutineDesugaring, CoroutineKind, CoroutineSource, Expr, ExprKind, FnDecl,
|
||||
FnRetTy, GenericArg, GenericBound, ImplItem, Item, LifetimeName, Node, TraitRef, Ty, TyKind,
|
||||
FnRetTy, GenericBound, ImplItem, Item, Node, OpaqueTy, TraitRef, Ty, TyKind,
|
||||
};
|
||||
use rustc_lint::{LateContext, LateLintPass};
|
||||
use rustc_middle::middle::resolve_bound_vars::ResolvedArg;
|
||||
use rustc_middle::ty;
|
||||
use rustc_session::declare_lint_pass;
|
||||
use rustc_span::def_id::LocalDefId;
|
||||
use rustc_span::{Span, sym};
|
||||
@ -44,21 +46,22 @@ fn check_fn(
|
||||
decl: &'tcx FnDecl<'_>,
|
||||
body: &'tcx Body<'_>,
|
||||
span: Span,
|
||||
def_id: LocalDefId,
|
||||
fn_def_id: LocalDefId,
|
||||
) {
|
||||
if let Some(header) = kind.header()
|
||||
&& !header.asyncness.is_async()
|
||||
// Check that this function returns `impl Future`
|
||||
&& let FnRetTy::Return(ret_ty) = decl.output
|
||||
&& let Some((trait_ref, output_lifetimes)) = future_trait_ref(cx, ret_ty)
|
||||
&& let TyKind::OpaqueDef(opaque) = ret_ty.kind
|
||||
&& let Some(trait_ref) = future_trait_ref(cx, opaque)
|
||||
&& let Some(output) = future_output_ty(trait_ref)
|
||||
&& captures_all_lifetimes(decl.inputs, &output_lifetimes)
|
||||
&& captures_all_lifetimes(cx, fn_def_id, opaque.def_id)
|
||||
// Check that the body of the function consists of one async block
|
||||
&& let ExprKind::Block(block, _) = body.value.kind
|
||||
&& block.stmts.is_empty()
|
||||
&& let Some(closure_body) = desugared_async_block(cx, block)
|
||||
&& let Node::Item(Item {vis_span, ..}) | Node::ImplItem(ImplItem {vis_span, ..}) =
|
||||
cx.tcx.hir_node_by_def_id(def_id)
|
||||
cx.tcx.hir_node_by_def_id(fn_def_id)
|
||||
{
|
||||
let header_span = span.with_hi(ret_ty.span.hi());
|
||||
|
||||
@ -101,32 +104,16 @@ fn check_fn(
|
||||
}
|
||||
}
|
||||
|
||||
fn future_trait_ref<'tcx>(
|
||||
cx: &LateContext<'tcx>,
|
||||
ty: &'tcx Ty<'tcx>,
|
||||
) -> Option<(&'tcx TraitRef<'tcx>, Vec<LifetimeName>)> {
|
||||
if let TyKind::OpaqueDef(opaque, bounds) = ty.kind
|
||||
&& let Some(trait_ref) = opaque.bounds.iter().find_map(|bound| {
|
||||
if let GenericBound::Trait(poly) = bound {
|
||||
Some(&poly.trait_ref)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
&& trait_ref.trait_def_id() == cx.tcx.lang_items().future_trait()
|
||||
fn future_trait_ref<'tcx>(cx: &LateContext<'tcx>, opaque: &'tcx OpaqueTy<'tcx>) -> Option<&'tcx TraitRef<'tcx>> {
|
||||
if let Some(trait_ref) = opaque.bounds.iter().find_map(|bound| {
|
||||
if let GenericBound::Trait(poly) = bound {
|
||||
Some(&poly.trait_ref)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}) && trait_ref.trait_def_id() == cx.tcx.lang_items().future_trait()
|
||||
{
|
||||
let output_lifetimes = bounds
|
||||
.iter()
|
||||
.filter_map(|bound| {
|
||||
if let GenericArg::Lifetime(lt) = bound {
|
||||
Some(lt.res)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
.collect();
|
||||
|
||||
return Some((trait_ref, output_lifetimes));
|
||||
return Some(trait_ref);
|
||||
}
|
||||
|
||||
None
|
||||
@ -145,27 +132,37 @@ fn future_output_ty<'tcx>(trait_ref: &'tcx TraitRef<'tcx>) -> Option<&'tcx Ty<'t
|
||||
None
|
||||
}
|
||||
|
||||
fn captures_all_lifetimes(inputs: &[Ty<'_>], output_lifetimes: &[LifetimeName]) -> bool {
|
||||
let input_lifetimes: Vec<LifetimeName> = inputs
|
||||
.iter()
|
||||
.filter_map(|ty| {
|
||||
if let TyKind::Ref(lt, _) = ty.kind {
|
||||
Some(lt.res)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
.collect();
|
||||
fn captures_all_lifetimes(cx: &LateContext<'_>, fn_def_id: LocalDefId, opaque_def_id: LocalDefId) -> bool {
|
||||
let early_input_params = ty::GenericArgs::identity_for_item(cx.tcx, fn_def_id);
|
||||
let late_input_params = cx.tcx.late_bound_vars(cx.tcx.local_def_id_to_hir_id(fn_def_id));
|
||||
|
||||
// The lint should trigger in one of these cases:
|
||||
// - There are no input lifetimes
|
||||
// - There's only one output lifetime bound using `+ '_`
|
||||
// - All input lifetimes are explicitly bound to the output
|
||||
input_lifetimes.is_empty()
|
||||
|| (output_lifetimes.len() == 1 && matches!(output_lifetimes[0], LifetimeName::Infer))
|
||||
|| input_lifetimes
|
||||
.iter()
|
||||
.all(|in_lt| output_lifetimes.iter().any(|out_lt| in_lt == out_lt))
|
||||
let num_early_lifetimes = early_input_params
|
||||
.iter()
|
||||
.filter(|param| param.as_region().is_some())
|
||||
.count();
|
||||
let num_late_lifetimes = late_input_params
|
||||
.iter()
|
||||
.filter(|param_kind| matches!(param_kind, ty::BoundVariableKind::Region(_)))
|
||||
.count();
|
||||
|
||||
// There is no lifetime, so they are all captured.
|
||||
if num_early_lifetimes == 0 && num_late_lifetimes == 0 {
|
||||
return true;
|
||||
}
|
||||
|
||||
// By construction, each captured lifetime only appears once in `opaque_captured_lifetimes`.
|
||||
let num_captured_lifetimes = cx
|
||||
.tcx
|
||||
.opaque_captured_lifetimes(opaque_def_id)
|
||||
.iter()
|
||||
.filter(|&(lifetime, _)| {
|
||||
matches!(
|
||||
*lifetime,
|
||||
ResolvedArg::EarlyBound(_) | ResolvedArg::LateBound(ty::INNERMOST, _, _)
|
||||
)
|
||||
})
|
||||
.count();
|
||||
num_captured_lifetimes == num_early_lifetimes + num_late_lifetimes
|
||||
}
|
||||
|
||||
fn desugared_async_block<'tcx>(cx: &LateContext<'tcx>, block: &'tcx Block<'tcx>) -> Option<&'tcx Body<'tcx>> {
|
||||
|
@ -111,11 +111,7 @@ fn check_int_ty_and_feature(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
|
||||
let expr_ty = cx.typeck_results().expr_ty(expr);
|
||||
match expr_ty.peel_refs().kind() {
|
||||
ty::Uint(_) => true,
|
||||
ty::Int(_) => cx
|
||||
.tcx
|
||||
.features()
|
||||
.declared_features
|
||||
.contains(&Symbol::intern("int_roundings")),
|
||||
ty::Int(_) => cx.tcx.features().enabled(Symbol::intern("int_roundings")),
|
||||
|
||||
_ => false,
|
||||
}
|
||||
|
@ -114,7 +114,7 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, arms: &'tcx [Arm<'_>]) {
|
||||
let indexed_arms: Vec<(usize, &Arm<'_>)> = arms.iter().enumerate().collect();
|
||||
for (&(i, arm1), &(j, arm2)) in search_same(&indexed_arms, hash, eq) {
|
||||
if matches!(arm2.pat.kind, PatKind::Wild) {
|
||||
if !cx.tcx.features().non_exhaustive_omitted_patterns_lint
|
||||
if !cx.tcx.features().non_exhaustive_omitted_patterns_lint()
|
||||
|| is_lint_allowed(cx, NON_EXHAUSTIVE_OMITTED_PATTERNS, arm2.hir_id)
|
||||
{
|
||||
let arm_span = adjusted_arm_span(cx, arm1.span);
|
||||
|
@ -251,7 +251,7 @@ fn emit_redundant_guards<'tcx>(
|
||||
fn expr_can_be_pat(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
|
||||
for_each_expr_without_closures(expr, |expr| {
|
||||
if match expr.kind {
|
||||
ExprKind::ConstBlock(..) => cx.tcx.features().inline_const_pat,
|
||||
ExprKind::ConstBlock(..) => cx.tcx.features().inline_const_pat(),
|
||||
ExprKind::Call(c, ..) if let ExprKind::Path(qpath) = c.kind => {
|
||||
// Allow ctors
|
||||
matches!(cx.qpath_res(&qpath, c.hir_id), Res::Def(DefKind::Ctor(..), ..))
|
||||
|
@ -11,7 +11,7 @@
|
||||
use rustc_hir::intravisit::{Visitor, walk_pat};
|
||||
use rustc_hir::{Arm, Expr, ExprKind, HirId, Node, Pat, PatKind, QPath, StmtKind};
|
||||
use rustc_lint::LateContext;
|
||||
use rustc_middle::ty::{self, AdtDef, ParamEnv, TyCtxt, TypeckResults, VariantDef};
|
||||
use rustc_middle::ty::{self, AdtDef, TyCtxt, TypeckResults, VariantDef};
|
||||
use rustc_span::{Span, sym};
|
||||
|
||||
use super::{MATCH_BOOL, SINGLE_MATCH, SINGLE_MATCH_ELSE};
|
||||
@ -67,7 +67,6 @@ pub(crate) fn check<'tcx>(cx: &LateContext<'tcx>, ex: &'tcx Expr<'_>, arms: &'tc
|
||||
if v.has_enum {
|
||||
let cx = PatCtxt {
|
||||
tcx: cx.tcx,
|
||||
param_env: cx.param_env,
|
||||
typeck,
|
||||
arena: DroplessArena::default(),
|
||||
};
|
||||
@ -185,7 +184,6 @@ fn visit_pat(&mut self, pat: &'tcx Pat<'_>) -> Self::Result {
|
||||
/// The context needed to manipulate a `PatState`.
|
||||
struct PatCtxt<'tcx> {
|
||||
tcx: TyCtxt<'tcx>,
|
||||
param_env: ParamEnv<'tcx>,
|
||||
typeck: &'tcx TypeckResults<'tcx>,
|
||||
arena: DroplessArena,
|
||||
}
|
||||
@ -337,7 +335,7 @@ fn add_pat<'tcx>(&mut self, cx: &'a PatCtxt<'tcx>, pat: &'tcx Pat<'_>) -> bool {
|
||||
if match *cx.typeck.pat_ty(pat).peel_refs().kind() {
|
||||
ty::Adt(adt, _) => adt.is_enum() || (adt.is_struct() && !adt.non_enum_variant().fields.is_empty()),
|
||||
ty::Tuple(tys) => !tys.is_empty(),
|
||||
ty::Array(_, len) => len.try_eval_target_usize(cx.tcx, cx.param_env) != Some(1),
|
||||
ty::Array(_, len) => len.try_to_target_usize(cx.tcx) != Some(1),
|
||||
ty::Slice(..) => true,
|
||||
_ => false,
|
||||
} =>
|
||||
@ -356,7 +354,7 @@ fn add_pat<'tcx>(&mut self, cx: &'a PatCtxt<'tcx>, pat: &'tcx Pat<'_>) -> bool {
|
||||
},
|
||||
PatKind::Slice([sub_pat], _, []) | PatKind::Slice([], _, [sub_pat])
|
||||
if let ty::Array(_, len) = *cx.typeck.pat_ty(pat).kind()
|
||||
&& len.try_eval_target_usize(cx.tcx, cx.param_env) == Some(1) =>
|
||||
&& len.try_to_target_usize(cx.tcx) == Some(1) =>
|
||||
{
|
||||
self.add_pat(cx, sub_pat)
|
||||
},
|
||||
|
@ -29,16 +29,13 @@ fn get_iterator_length<'tcx>(cx: &LateContext<'tcx>, iter: &'tcx Expr<'tcx>) ->
|
||||
if cx.tcx.is_diagnostic_item(sym::ArrayIntoIter, did) {
|
||||
// For array::IntoIter<T, const N: usize>, the length is the second generic
|
||||
// parameter.
|
||||
substs
|
||||
.const_at(1)
|
||||
.try_eval_target_usize(cx.tcx, cx.param_env)
|
||||
.map(u128::from)
|
||||
substs.const_at(1).try_to_target_usize(cx.tcx).map(u128::from)
|
||||
} else if cx.tcx.is_diagnostic_item(sym::SliceIter, did)
|
||||
&& let ExprKind::MethodCall(_, recv, ..) = iter.kind
|
||||
{
|
||||
if let ty::Array(_, len) = cx.typeck_results().expr_ty(recv).peel_refs().kind() {
|
||||
// For slice::Iter<'_, T>, the receiver might be an array literal: [1,2,3].iter().skip(..)
|
||||
len.try_eval_target_usize(cx.tcx, cx.param_env).map(u128::from)
|
||||
len.try_to_target_usize(cx.tcx).map(u128::from)
|
||||
} else if let Some(args) = VecArgs::hir(cx, expr_or_init(cx, recv)) {
|
||||
match args {
|
||||
VecArgs::Vec(vec) => vec.len().try_into().ok(),
|
||||
|
@ -137,7 +137,7 @@ pub(crate) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, arg: &Expr<'_>, name:
|
||||
_ if matches!(
|
||||
typeck.expr_adjustments(prev_expr).first(),
|
||||
Some(Adjustment {
|
||||
kind: Adjust::Borrow(AutoBorrow::Ref(_, AutoBorrowMutability::Not))
|
||||
kind: Adjust::Borrow(AutoBorrow::Ref(AutoBorrowMutability::Not))
|
||||
| Adjust::Deref(_),
|
||||
..
|
||||
})
|
||||
@ -230,7 +230,7 @@ fn check_use<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) -> (UseKind<'tcx>,
|
||||
if use_cx
|
||||
.adjustments
|
||||
.first()
|
||||
.is_some_and(|a| matches!(a.kind, Adjust::Borrow(AutoBorrow::Ref(_, AutoBorrowMutability::Not)))) =>
|
||||
.is_some_and(|a| matches!(a.kind, Adjust::Borrow(AutoBorrow::Ref(AutoBorrowMutability::Not)))) =>
|
||||
{
|
||||
UseKind::AutoBorrowed
|
||||
},
|
||||
|
@ -5293,7 +5293,7 @@ fn lifetime_param_cond(&self, impl_item: &hir::ImplItem<'_>) -> bool {
|
||||
}
|
||||
|
||||
#[rustfmt::skip]
|
||||
static TRAIT_METHODS: [ShouldImplTraitCase; 30] = [
|
||||
const TRAIT_METHODS: [ShouldImplTraitCase; 30] = [
|
||||
ShouldImplTraitCase::new("std::ops::Add", "add", 2, FN_HEADER, SelfKind::Value, OutType::Any, true),
|
||||
ShouldImplTraitCase::new("std::convert::AsMut", "as_mut", 1, FN_HEADER, SelfKind::RefMut, OutType::Ref, true),
|
||||
ShouldImplTraitCase::new("std::convert::AsRef", "as_ref", 1, FN_HEADER, SelfKind::Ref, OutType::Ref, true),
|
||||
|
@ -568,7 +568,7 @@ fn can_change_type<'a>(cx: &LateContext<'a>, mut expr: &'a Expr<'a>, mut ty: Ty<
|
||||
let obligation = Obligation::new(cx.tcx, ObligationCause::dummy(), cx.param_env, predicate);
|
||||
!cx.tcx
|
||||
.infer_ctxt()
|
||||
.build()
|
||||
.build(cx.typing_mode())
|
||||
.predicate_must_hold_modulo_regions(&obligation)
|
||||
}) {
|
||||
return false;
|
||||
|
@ -18,7 +18,7 @@ fn may_slice<'a>(cx: &LateContext<'a>, ty: Ty<'a>) -> bool {
|
||||
ty::Slice(_) => true,
|
||||
ty::Adt(..) if let Some(boxed) = ty.boxed_ty() => may_slice(cx, boxed),
|
||||
ty::Adt(..) => is_type_diagnostic_item(cx, ty, sym::Vec),
|
||||
ty::Array(_, size) => size.try_eval_target_usize(cx.tcx, cx.param_env).is_some(),
|
||||
ty::Array(_, size) => size.try_to_target_usize(cx.tcx).is_some(),
|
||||
ty::Ref(_, inner, _) => may_slice(cx, *inner),
|
||||
_ => false,
|
||||
}
|
||||
|
@ -2,6 +2,7 @@
|
||||
use rustc_ast::ast;
|
||||
use rustc_hir as hir;
|
||||
use rustc_lint::{LateContext, LateLintPass, LintContext};
|
||||
use rustc_middle::ty::AssocItemContainer;
|
||||
use rustc_session::declare_lint_pass;
|
||||
use rustc_span::{Span, sym};
|
||||
|
||||
@ -138,7 +139,6 @@ fn check_item(&mut self, cx: &LateContext<'tcx>, it: &'tcx hir::Item<'_>) {
|
||||
}
|
||||
|
||||
fn check_impl_item(&mut self, cx: &LateContext<'tcx>, impl_item: &'tcx hir::ImplItem<'_>) {
|
||||
use rustc_middle::ty::{ImplContainer, TraitContainer};
|
||||
if rustc_middle::lint::in_external_macro(cx.sess(), impl_item.span) || is_executable_or_proc_macro(cx) {
|
||||
return;
|
||||
}
|
||||
@ -156,8 +156,8 @@ fn check_impl_item(&mut self, cx: &LateContext<'tcx>, impl_item: &'tcx hir::Impl
|
||||
let assoc_item = cx.tcx.associated_item(impl_item.owner_id);
|
||||
let container_id = assoc_item.container_id(cx.tcx);
|
||||
let trait_def_id = match assoc_item.container {
|
||||
TraitContainer => Some(container_id),
|
||||
ImplContainer => cx.tcx.impl_trait_ref(container_id).map(|t| t.skip_binder().def_id),
|
||||
AssocItemContainer::Trait => Some(container_id),
|
||||
AssocItemContainer::Impl => cx.tcx.impl_trait_ref(container_id).map(|t| t.skip_binder().def_id),
|
||||
};
|
||||
|
||||
if let Some(trait_def_id) = trait_def_id {
|
||||
|
@ -278,7 +278,7 @@ fn needless_borrow_count<'tcx>(
|
||||
|
||||
let predicate = EarlyBinder::bind(predicate).instantiate(cx.tcx, &args_with_referent_ty[..]);
|
||||
let obligation = Obligation::new(cx.tcx, ObligationCause::dummy(), cx.param_env, predicate);
|
||||
let infcx = cx.tcx.infer_ctxt().build();
|
||||
let infcx = cx.tcx.infer_ctxt().build(cx.typing_mode());
|
||||
infcx.predicate_must_hold_modulo_regions(&obligation)
|
||||
})
|
||||
};
|
||||
|
@ -1,7 +1,7 @@
|
||||
use clippy_utils::diagnostics::span_lint_and_then;
|
||||
use rustc_errors::Applicability;
|
||||
use rustc_hir::def_id::{DefId, DefIdMap};
|
||||
use rustc_hir::{GenericBound, Generics, PolyTraitRef, TraitBoundModifier, WherePredicate};
|
||||
use rustc_hir::{BoundPolarity, GenericBound, Generics, PolyTraitRef, TraitBoundModifiers, WherePredicate};
|
||||
use rustc_lint::{LateContext, LateLintPass};
|
||||
use rustc_middle::ty::{ClauseKind, PredicatePolarity};
|
||||
use rustc_session::declare_lint_pass;
|
||||
@ -118,13 +118,13 @@ fn check_generics(&mut self, cx: &LateContext<'_>, generics: &Generics<'_>) {
|
||||
let maybe_sized_params: DefIdMap<_> = type_param_bounds(generics)
|
||||
.filter(|bound| {
|
||||
bound.trait_bound.trait_ref.trait_def_id() == Some(sized_trait)
|
||||
&& bound.trait_bound.modifiers == TraitBoundModifier::Maybe
|
||||
&& matches!(bound.trait_bound.modifiers.polarity, BoundPolarity::Maybe(_))
|
||||
})
|
||||
.map(|bound| (bound.param, bound))
|
||||
.collect();
|
||||
|
||||
for bound in type_param_bounds(generics) {
|
||||
if bound.trait_bound.modifiers == TraitBoundModifier::None
|
||||
if bound.trait_bound.modifiers == TraitBoundModifiers::NONE
|
||||
&& let Some(sized_bound) = maybe_sized_params.get(&bound.param)
|
||||
&& let Some(path) = path_to_sized_bound(cx, bound.trait_bound)
|
||||
{
|
||||
|
@ -417,8 +417,8 @@ fn borrow(&mut self, cmt: &euv::PlaceWithHirId<'tcx>, id: HirId, borrow: ty::Bor
|
||||
// a closure, it'll return this variant whereas if you have just an index access, it'll
|
||||
// return `ImmBorrow`. So if there is "Unique" and it's a mutable reference, we add it
|
||||
// to the mutably used variables set.
|
||||
if borrow == ty::BorrowKind::MutBorrow
|
||||
|| (borrow == ty::BorrowKind::UniqueImmBorrow && base_ty.ref_mutability() == Some(Mutability::Mut))
|
||||
if borrow == ty::BorrowKind::Mutable
|
||||
|| (borrow == ty::BorrowKind::UniqueImmutable && base_ty.ref_mutability() == Some(Mutability::Mut))
|
||||
{
|
||||
self.add_mutably_used_var(*vid);
|
||||
} else if self.is_in_unsafe_block(id) {
|
||||
@ -426,7 +426,7 @@ fn borrow(&mut self, cmt: &euv::PlaceWithHirId<'tcx>, id: HirId, borrow: ty::Bor
|
||||
// upon!
|
||||
self.add_mutably_used_var(*vid);
|
||||
}
|
||||
} else if borrow == ty::ImmBorrow {
|
||||
} else if borrow == ty::BorrowKind::Immutable {
|
||||
// If there is an `async block`, it'll contain a call to a closure which we need to
|
||||
// go into to ensure all "mutate" checks are found.
|
||||
if let Node::Expr(Expr {
|
||||
|
@ -159,8 +159,12 @@ fn check_no_effect(&mut self, cx: &LateContext<'_>, stmt: &Stmt<'_>) -> bool {
|
||||
|
||||
// Remove `impl Future<Output = T>` to get `T`
|
||||
if cx.tcx.ty_is_opaque_future(ret_ty)
|
||||
&& let Some(true_ret_ty) =
|
||||
cx.tcx.infer_ctxt().build().err_ctxt().get_impl_future_output_ty(ret_ty)
|
||||
&& let Some(true_ret_ty) = cx
|
||||
.tcx
|
||||
.infer_ctxt()
|
||||
.build(cx.typing_mode())
|
||||
.err_ctxt()
|
||||
.get_impl_future_output_ty(ret_ty)
|
||||
{
|
||||
ret_ty = true_ret_ty;
|
||||
}
|
||||
|
@ -102,7 +102,7 @@ fn imm_borrows_in_expr(cx: &LateContext<'_>, e: &hir::Expr<'_>) -> HirIdSet {
|
||||
struct S(HirIdSet);
|
||||
impl Delegate<'_> for S {
|
||||
fn borrow(&mut self, place: &PlaceWithHirId<'_>, _: HirId, kind: BorrowKind) {
|
||||
if matches!(kind, BorrowKind::ImmBorrow | BorrowKind::UniqueImmBorrow) {
|
||||
if matches!(kind, BorrowKind::Immutable | BorrowKind::UniqueImmutable) {
|
||||
self.0.insert(match place.place.base {
|
||||
PlaceBase::Local(id) => id,
|
||||
PlaceBase::Upvar(id) => id.var_path.hir_id,
|
||||
@ -127,7 +127,7 @@ fn mut_borrows_in_expr(cx: &LateContext<'_>, e: &hir::Expr<'_>) -> HirIdSet {
|
||||
struct S(HirIdSet);
|
||||
impl Delegate<'_> for S {
|
||||
fn borrow(&mut self, place: &PlaceWithHirId<'_>, _: HirId, kind: BorrowKind) {
|
||||
if matches!(kind, BorrowKind::MutBorrow) {
|
||||
if matches!(kind, BorrowKind::Mutable) {
|
||||
self.0.insert(match place.place.base {
|
||||
PlaceBase::Local(id) => id,
|
||||
PlaceBase::Upvar(id) => id.var_path.hir_id,
|
||||
|
@ -695,7 +695,7 @@ fn matches_preds<'tcx>(
|
||||
ty: Ty<'tcx>,
|
||||
preds: &'tcx [ty::PolyExistentialPredicate<'tcx>],
|
||||
) -> bool {
|
||||
let infcx = cx.tcx.infer_ctxt().build();
|
||||
let infcx = cx.tcx.infer_ctxt().build(cx.typing_mode());
|
||||
preds
|
||||
.iter()
|
||||
.all(|&p| match cx.tcx.instantiate_bound_regions_with_erased(p) {
|
||||
|
@ -110,7 +110,7 @@ fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
|
||||
) || cx.typeck_results().expr_adjustments(expr).first().map_or(false, |a| {
|
||||
matches!(
|
||||
a.kind,
|
||||
Adjust::Borrow(AutoBorrow::Ref(_, AutoBorrowMutability::Mut { .. }))
|
||||
Adjust::Borrow(AutoBorrow::Ref(AutoBorrowMutability::Mut { .. }))
|
||||
)
|
||||
}) || (matches!(
|
||||
cx.typeck_results().expr_ty(indexed).ref_mutability(),
|
||||
|
@ -2,7 +2,7 @@
|
||||
use clippy_utils::has_repr_attr;
|
||||
use rustc_hir::{Item, ItemKind};
|
||||
use rustc_lint::{LateContext, LateLintPass};
|
||||
use rustc_middle::ty::{Const, FeedConstTy};
|
||||
use rustc_middle::ty;
|
||||
use rustc_session::declare_lint_pass;
|
||||
|
||||
declare_clippy_lint! {
|
||||
@ -55,16 +55,14 @@ fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'tcx>) {
|
||||
|
||||
fn is_struct_with_trailing_zero_sized_array<'tcx>(cx: &LateContext<'tcx>, item: &Item<'tcx>) -> bool {
|
||||
if let ItemKind::Struct(data, _) = &item.kind
|
||||
// First check if last field is an array
|
||||
&& let Some(last_field) = data.fields().last()
|
||||
&& let rustc_hir::TyKind::Array(_, rustc_hir::ArrayLen::Body(length)) = last_field.ty.kind
|
||||
|
||||
// Then check if that array is zero-sized
|
||||
&& let length = Const::from_const_arg(cx.tcx, length, FeedConstTy::No)
|
||||
&& let length = length.try_eval_target_usize(cx.tcx, cx.param_env)
|
||||
&& let Some(length) = length
|
||||
&& let field_ty = cx
|
||||
.tcx
|
||||
.normalize_erasing_regions(cx.param_env, cx.tcx.type_of(last_field.def_id).instantiate_identity())
|
||||
&& let ty::Array(_, array_len) = *field_ty.kind()
|
||||
&& let Some(0) = array_len.try_to_target_usize(cx.tcx)
|
||||
{
|
||||
length == 0
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
|
@ -10,8 +10,8 @@
|
||||
use rustc_errors::Applicability;
|
||||
use rustc_hir::def::Res;
|
||||
use rustc_hir::{
|
||||
GenericBound, Generics, Item, ItemKind, LangItem, Node, Path, PathSegment, PredicateOrigin, QPath,
|
||||
TraitBoundModifier, TraitItem, TraitRef, Ty, TyKind, WherePredicate,
|
||||
BoundPolarity, GenericBound, Generics, Item, ItemKind, LangItem, Node, Path, PathSegment, PredicateOrigin, QPath,
|
||||
TraitBoundModifiers, TraitItem, TraitRef, Ty, TyKind, WherePredicate,
|
||||
};
|
||||
use rustc_lint::{LateContext, LateLintPass};
|
||||
use rustc_session::impl_lint_pass;
|
||||
@ -233,7 +233,7 @@ impl TraitBounds {
|
||||
fn cannot_combine_maybe_bound(&self, cx: &LateContext<'_>, bound: &GenericBound<'_>) -> bool {
|
||||
if !self.msrv.meets(msrvs::MAYBE_BOUND_IN_WHERE)
|
||||
&& let GenericBound::Trait(tr) = bound
|
||||
&& let TraitBoundModifier::Maybe = tr.modifiers
|
||||
&& let BoundPolarity::Maybe(_) = tr.modifiers.polarity
|
||||
{
|
||||
cx.tcx.lang_items().get(LangItem::Sized) == tr.trait_ref.path.res.opt_def_id()
|
||||
} else {
|
||||
@ -374,12 +374,12 @@ fn check_trait_bound_duplication<'tcx>(cx: &LateContext<'tcx>, generics: &'_ Gen
|
||||
struct ComparableTraitRef<'a, 'tcx> {
|
||||
cx: &'a LateContext<'tcx>,
|
||||
trait_ref: &'tcx TraitRef<'tcx>,
|
||||
modifier: TraitBoundModifier,
|
||||
modifiers: TraitBoundModifiers,
|
||||
}
|
||||
|
||||
impl PartialEq for ComparableTraitRef<'_, '_> {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
self.modifier == other.modifier
|
||||
SpanlessEq::eq_modifiers(self.modifiers, other.modifiers)
|
||||
&& SpanlessEq::new(self.cx)
|
||||
.paths_by_resolution()
|
||||
.eq_path(self.trait_ref.path, other.trait_ref.path)
|
||||
@ -390,8 +390,8 @@ impl Hash for ComparableTraitRef<'_, '_> {
|
||||
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||
let mut s = SpanlessHash::new(self.cx).paths_by_resolution();
|
||||
s.hash_path(self.trait_ref.path);
|
||||
s.hash_modifiers(self.modifiers);
|
||||
state.write_u64(s.finish());
|
||||
self.modifier.hash(state);
|
||||
}
|
||||
}
|
||||
|
||||
@ -400,7 +400,7 @@ fn get_trait_info_from_bound<'a>(bound: &'a GenericBound<'_>) -> Option<(Res, &'
|
||||
let trait_path = t.trait_ref.path;
|
||||
let trait_span = {
|
||||
let path_span = trait_path.span;
|
||||
if let TraitBoundModifier::Maybe = t.modifiers {
|
||||
if let BoundPolarity::Maybe(_) = t.modifiers.polarity {
|
||||
path_span.with_lo(path_span.lo() - BytePos(1)) // include the `?`
|
||||
} else {
|
||||
path_span
|
||||
@ -427,7 +427,7 @@ fn rollup_traits<'cx, 'tcx>(
|
||||
ComparableTraitRef {
|
||||
cx,
|
||||
trait_ref: &t.trait_ref,
|
||||
modifier: t.modifiers,
|
||||
modifiers: t.modifiers,
|
||||
},
|
||||
t.span,
|
||||
))
|
||||
|
@ -190,7 +190,7 @@ fn all_bindings_are_for_conv<'tcx>(
|
||||
tys.len() == elements.len() && tys.iter().chain(final_tys.iter().copied()).all_equal()
|
||||
},
|
||||
(ToType::Tuple, ty::Array(ty, len)) => {
|
||||
let Some(len) = len.try_eval_target_usize(cx.tcx, cx.param_env) else { return false };
|
||||
let Some(len) = len.try_to_target_usize(cx.tcx) else { return false };
|
||||
len as usize == elements.len() && final_tys.iter().chain(once(ty)).all_equal()
|
||||
},
|
||||
_ => false,
|
||||
|
@ -217,7 +217,7 @@ fn is_option_as_mut_use(tcx: TyCtxt<'_>, expr_id: HirId) -> bool {
|
||||
|
||||
impl<'tcx> Delegate<'tcx> for MutationVisitor<'tcx> {
|
||||
fn borrow(&mut self, cat: &PlaceWithHirId<'tcx>, diag_expr_id: HirId, bk: ty::BorrowKind) {
|
||||
if let ty::BorrowKind::MutBorrow = bk
|
||||
if let ty::BorrowKind::Mutable = bk
|
||||
&& is_potentially_local_place(self.local_id, &cat.place)
|
||||
&& !is_option_as_mut_use(self.tcx, diag_expr_id)
|
||||
{
|
||||
|
@ -114,7 +114,7 @@ fn into_iter_bound<'tcx>(
|
||||
if !cx
|
||||
.tcx
|
||||
.infer_ctxt()
|
||||
.build()
|
||||
.build(cx.typing_mode())
|
||||
.predicate_must_hold_modulo_regions(&obligation)
|
||||
{
|
||||
return None;
|
||||
|
@ -21,7 +21,7 @@
|
||||
///
|
||||
/// ### Why is this bad?
|
||||
/// The compiler only knows lints via a `LintPass`. Without
|
||||
/// putting a lint to a `LintPass::get_lints()`'s return, the compiler will not
|
||||
/// putting a lint to a `LintPass::lint_vec()`'s return, the compiler will not
|
||||
/// know the name of the lint.
|
||||
///
|
||||
/// ### Known problems
|
||||
@ -159,8 +159,8 @@ fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) {
|
||||
let body = cx.tcx.hir().body_owned_by(
|
||||
impl_item_refs
|
||||
.iter()
|
||||
.find(|iiref| iiref.ident.as_str() == "get_lints")
|
||||
.expect("LintPass needs to implement get_lints")
|
||||
.find(|iiref| iiref.ident.as_str() == "lint_vec")
|
||||
.expect("LintPass needs to implement lint_vec")
|
||||
.id
|
||||
.owner_id
|
||||
.def_id,
|
||||
|
@ -39,7 +39,7 @@ fn from(attr: &Attribute) -> Self {
|
||||
struct IdentCollector(Vec<Ident>);
|
||||
|
||||
impl Visitor<'_> for IdentCollector {
|
||||
fn visit_ident(&mut self, ident: Ident) {
|
||||
self.0.push(ident);
|
||||
fn visit_ident(&mut self, ident: &Ident) {
|
||||
self.0.push(*ident);
|
||||
}
|
||||
}
|
||||
|
@ -21,7 +21,7 @@
|
||||
ImplItem, ImplItemKind, IsAuto, Item, ItemKind, Lit, LoopSource, MatchSource, MutTy, Node, Path, QPath, Safety,
|
||||
TraitItem, TraitItemKind, Ty, TyKind, UnOp, UnsafeSource, Variant, VariantData, YieldSource,
|
||||
};
|
||||
use rustc_lint::{LateContext, LintContext};
|
||||
use rustc_lint::{EarlyContext, LateContext, LintContext};
|
||||
use rustc_middle::ty::TyCtxt;
|
||||
use rustc_session::Session;
|
||||
use rustc_span::symbol::{Ident, kw};
|
||||
@ -435,11 +435,12 @@ fn span(&self) -> Span {
|
||||
impl_with_search_pat!((_cx: LateContext<'tcx>, self: FieldDef<'_>) => field_def_search_pat(self));
|
||||
impl_with_search_pat!((_cx: LateContext<'tcx>, self: Variant<'_>) => variant_search_pat(self));
|
||||
impl_with_search_pat!((_cx: LateContext<'tcx>, self: Ty<'_>) => ty_search_pat(self));
|
||||
impl_with_search_pat!((_cx: LateContext<'tcx>, self: Attribute) => attr_search_pat(self));
|
||||
impl_with_search_pat!((_cx: LateContext<'tcx>, self: Ident) => ident_search_pat(*self));
|
||||
impl_with_search_pat!((_cx: LateContext<'tcx>, self: Lit) => lit_search_pat(&self.node));
|
||||
impl_with_search_pat!((_cx: LateContext<'tcx>, self: Path<'_>) => path_search_pat(self));
|
||||
|
||||
impl_with_search_pat!((_cx: EarlyContext<'tcx>, self: Attribute) => attr_search_pat(self));
|
||||
|
||||
impl<'cx> WithSearchPat<'cx> for (&FnKind<'cx>, &Body<'cx>, HirId, Span) {
|
||||
type Context = LateContext<'cx>;
|
||||
|
||||
|
@ -478,7 +478,7 @@ fn expr(&self, e: &Expr<'_>) -> Option<Constant<'tcx>> {
|
||||
ExprKind::Tup(tup) => self.multi(tup).map(Constant::Tuple),
|
||||
ExprKind::Repeat(value, _) => {
|
||||
let n = match self.typeck.expr_ty(e).kind() {
|
||||
ty::Array(_, n) => n.try_eval_target_usize(self.tcx, self.param_env)?,
|
||||
ty::Array(_, n) => n.try_to_target_usize(self.tcx)?,
|
||||
_ => span_bug!(e.span, "typeck error"),
|
||||
};
|
||||
self.expr(value).map(|v| Constant::Repeat(Box::new(v), n))
|
||||
@ -559,7 +559,7 @@ pub fn eval_is_empty(&self, e: &Expr<'_>) -> Option<bool> {
|
||||
ExprKind::Array(vec) => self.multi(vec).map(|v| v.is_empty()),
|
||||
ExprKind::Repeat(..) => {
|
||||
if let ty::Array(_, n) = self.typeck.expr_ty(e).kind() {
|
||||
Some(n.try_eval_target_usize(self.tcx, self.param_env)? == 0)
|
||||
Some(n.try_to_target_usize(self.tcx)? == 0)
|
||||
} else {
|
||||
span_bug!(e.span, "typeck error");
|
||||
}
|
||||
|
@ -9,7 +9,8 @@
|
||||
use rustc_hir::{
|
||||
ArrayLen, AssocItemConstraint, BinOpKind, BindingMode, Block, BodyId, Closure, ConstArg, ConstArgKind, Expr,
|
||||
ExprField, ExprKind, FnRetTy, GenericArg, GenericArgs, HirId, HirIdMap, InlineAsmOperand, LetExpr, Lifetime,
|
||||
LifetimeName, Pat, PatField, PatKind, Path, PathSegment, PrimTy, QPath, Stmt, StmtKind, Ty, TyKind,
|
||||
LifetimeName, Pat, PatField, PatKind, Path, PathSegment, PrimTy, QPath, Stmt, StmtKind, TraitBoundModifiers, Ty,
|
||||
TyKind,
|
||||
};
|
||||
use rustc_lexer::{TokenKind, tokenize};
|
||||
use rustc_lint::LateContext;
|
||||
@ -126,6 +127,11 @@ pub fn eq_path_segment(&mut self, left: &PathSegment<'_>, right: &PathSegment<'_
|
||||
pub fn eq_path_segments(&mut self, left: &[PathSegment<'_>], right: &[PathSegment<'_>]) -> bool {
|
||||
self.inter_expr().eq_path_segments(left, right)
|
||||
}
|
||||
|
||||
pub fn eq_modifiers(left: TraitBoundModifiers, right: TraitBoundModifiers) -> bool {
|
||||
std::mem::discriminant(&left.constness) == std::mem::discriminant(&right.constness)
|
||||
&& std::mem::discriminant(&left.polarity) == std::mem::discriminant(&right.polarity)
|
||||
}
|
||||
}
|
||||
|
||||
pub struct HirEqInterExpr<'a, 'b, 'tcx> {
|
||||
@ -1143,6 +1149,12 @@ pub fn hash_path(&mut self, path: &Path<'_>) {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn hash_modifiers(&mut self, modifiers: TraitBoundModifiers) {
|
||||
let TraitBoundModifiers { constness, polarity } = modifiers;
|
||||
std::mem::discriminant(&polarity).hash(&mut self.s);
|
||||
std::mem::discriminant(&constness).hash(&mut self.s);
|
||||
}
|
||||
|
||||
pub fn hash_stmt(&mut self, b: &Stmt<'_>) {
|
||||
std::mem::discriminant(&b.kind).hash(&mut self.s);
|
||||
|
||||
@ -1219,16 +1231,18 @@ pub fn hash_tykind(&mut self, ty: &TyKind<'_>) {
|
||||
}
|
||||
},
|
||||
TyKind::Path(qpath) => self.hash_qpath(qpath),
|
||||
TyKind::OpaqueDef(_, arg_list) => {
|
||||
self.hash_generic_args(arg_list);
|
||||
},
|
||||
TyKind::TraitObject(_, lifetime, _) => {
|
||||
self.hash_lifetime(lifetime);
|
||||
},
|
||||
TyKind::Typeof(anon_const) => {
|
||||
self.hash_body(anon_const.body);
|
||||
},
|
||||
TyKind::Err(_) | TyKind::Infer | TyKind::Never | TyKind::InferDelegation(..) | TyKind::AnonAdt(_) => {},
|
||||
TyKind::Err(_)
|
||||
| TyKind::Infer
|
||||
| TyKind::Never
|
||||
| TyKind::InferDelegation(..)
|
||||
| TyKind::OpaqueDef(_)
|
||||
| TyKind::AnonAdt(_) => {},
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1210,8 +1210,8 @@ fn visit_expr(&mut self, e: &'tcx Expr<'_>) {
|
||||
let capture = match capture.info.capture_kind {
|
||||
UpvarCapture::ByValue => CaptureKind::Value,
|
||||
UpvarCapture::ByRef(kind) => match kind {
|
||||
BorrowKind::ImmBorrow => CaptureKind::Ref(Mutability::Not),
|
||||
BorrowKind::UniqueImmBorrow | BorrowKind::MutBorrow => {
|
||||
BorrowKind::Immutable => CaptureKind::Ref(Mutability::Not),
|
||||
BorrowKind::UniqueImmutable | BorrowKind::Mutable => {
|
||||
CaptureKind::Ref(Mutability::Mut)
|
||||
},
|
||||
},
|
||||
@ -3338,8 +3338,8 @@ pub fn get_path_from_caller_to_method_type<'tcx>(
|
||||
let assoc_item = tcx.associated_item(method);
|
||||
let def_id = assoc_item.container_id(tcx);
|
||||
match assoc_item.container {
|
||||
rustc_ty::TraitContainer => get_path_to_callee(tcx, from, def_id),
|
||||
rustc_ty::ImplContainer => {
|
||||
rustc_ty::AssocItemContainer::Trait => get_path_to_callee(tcx, from, def_id),
|
||||
rustc_ty::AssocItemContainer::Impl => {
|
||||
let ty = tcx.type_of(def_id).instantiate_identity();
|
||||
get_path_to_ty(tcx, from, ty, args)
|
||||
},
|
||||
|
@ -185,9 +185,7 @@ pub fn new(cx: &LateContext<'tcx>, mir: &'b mir::Body<'tcx>) -> Self {
|
||||
vis.into_map(cx)
|
||||
};
|
||||
let maybe_storage_live_result = MaybeStorageLive::new(Cow::Owned(BitSet::new_empty(mir.local_decls.len())))
|
||||
.into_engine(cx.tcx, mir)
|
||||
.pass_name("redundant_clone")
|
||||
.iterate_to_fixpoint()
|
||||
.iterate_to_fixpoint(cx.tcx, mir, Some("redundant_clone"))
|
||||
.into_results_cursor(mir);
|
||||
let mut vis = PossibleBorrowerVisitor::new(cx, mir, possible_origin);
|
||||
vis.visit_body(mir);
|
||||
|
@ -334,7 +334,7 @@ fn check_terminator<'tcx>(
|
||||
| TerminatorKind::TailCall { func, args, fn_span: _ } => {
|
||||
let fn_ty = func.ty(body, tcx);
|
||||
if let ty::FnDef(fn_def_id, _) = *fn_ty.kind() {
|
||||
if !is_const_fn(tcx, fn_def_id, msrv) {
|
||||
if !is_stable_const_fn(tcx, fn_def_id, msrv) {
|
||||
return Err((
|
||||
span,
|
||||
format!(
|
||||
@ -377,12 +377,12 @@ fn check_terminator<'tcx>(
|
||||
}
|
||||
}
|
||||
|
||||
fn is_const_fn(tcx: TyCtxt<'_>, def_id: DefId, msrv: &Msrv) -> bool {
|
||||
fn is_stable_const_fn(tcx: TyCtxt<'_>, def_id: DefId, msrv: &Msrv) -> bool {
|
||||
tcx.is_const_fn(def_id)
|
||||
&& tcx.lookup_const_stability(def_id).map_or(true, |const_stab| {
|
||||
&& tcx.lookup_const_stability(def_id).is_none_or(|const_stab| {
|
||||
if let rustc_attr::StabilityLevel::Stable { since, .. } = const_stab.level {
|
||||
// Checking MSRV is manually necessary because `rustc` has no such concept. This entire
|
||||
// function could be removed if `rustc` provided a MSRV-aware version of `is_const_fn`.
|
||||
// function could be removed if `rustc` provided a MSRV-aware version of `is_stable_const_fn`.
|
||||
// as a part of an unimplemented MSRV check https://github.com/rust-lang/rust/issues/65262.
|
||||
|
||||
let const_stab_rust_version = match since {
|
||||
@ -393,14 +393,18 @@ fn is_const_fn(tcx: TyCtxt<'_>, def_id: DefId, msrv: &Msrv) -> bool {
|
||||
|
||||
msrv.meets(const_stab_rust_version)
|
||||
} else {
|
||||
// Unstable const fn with the feature enabled.
|
||||
msrv.current().is_none()
|
||||
// Unstable const fn, check if the feature is enabled. We need both the regular stability
|
||||
// feature and (if set) the const stability feature to const-call this function.
|
||||
let stab = tcx.lookup_stability(def_id);
|
||||
let is_enabled = stab.is_some_and(|s| s.is_stable() || tcx.features().enabled(s.feature))
|
||||
&& const_stab.feature.is_none_or(|f| tcx.features().enabled(f));
|
||||
is_enabled && msrv.current().is_none()
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
fn is_ty_const_destruct<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, body: &Body<'tcx>) -> bool {
|
||||
// FIXME(effects, fee1-dead) revert to const destruct once it works again
|
||||
// FIXME(const_trait_impl, fee1-dead) revert to const destruct once it works again
|
||||
#[expect(unused)]
|
||||
fn is_ty_const_destruct_unused<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, body: &Body<'tcx>) -> bool {
|
||||
// Avoid selecting for simple cases, such as builtin types.
|
||||
@ -408,7 +412,7 @@ fn is_ty_const_destruct_unused<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, body: &Bod
|
||||
return true;
|
||||
}
|
||||
|
||||
// FIXME(effects) constness
|
||||
// FIXME(const_trait_impl) constness
|
||||
let obligation = Obligation::new(
|
||||
tcx,
|
||||
ObligationCause::dummy_with_span(body.span),
|
||||
@ -416,7 +420,7 @@ fn is_ty_const_destruct_unused<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, body: &Bod
|
||||
TraitRef::new(tcx, tcx.require_lang_item(LangItem::Destruct, Some(body.span)), [ty]),
|
||||
);
|
||||
|
||||
let infcx = tcx.infer_ctxt().build();
|
||||
let infcx = tcx.infer_ctxt().build(body.typing_mode(tcx));
|
||||
let mut selcx = SelectionContext::new(&infcx);
|
||||
let Some(impl_src) = selcx.select(&obligation).ok().flatten() else {
|
||||
return false;
|
||||
|
@ -19,7 +19,7 @@
|
||||
use rustc_middle::ty::{
|
||||
self, AdtDef, AliasTy, AssocItem, AssocKind, Binder, BoundRegion, FnSig, GenericArg, GenericArgKind,
|
||||
GenericArgsRef, GenericParamDefKind, IntTy, ParamEnv, Region, RegionKind, TraitRef, Ty, TyCtxt, TypeSuperVisitable,
|
||||
TypeVisitable, TypeVisitableExt, TypeVisitor, UintTy, Upcast, VariantDef, VariantDiscr,
|
||||
TypeVisitable, TypeVisitableExt, TypeVisitor, TypingMode, UintTy, Upcast, VariantDef, VariantDiscr,
|
||||
};
|
||||
use rustc_span::symbol::Ident;
|
||||
use rustc_span::{DUMMY_SP, Span, Symbol, sym};
|
||||
@ -268,30 +268,13 @@ pub fn implements_trait_with_env_from_iter<'tcx>(
|
||||
return false;
|
||||
}
|
||||
|
||||
let infcx = tcx.infer_ctxt().build();
|
||||
let infcx = tcx.infer_ctxt().build(TypingMode::from_param_env(param_env));
|
||||
let args = args
|
||||
.into_iter()
|
||||
.map(|arg| arg.into().unwrap_or_else(|| infcx.next_ty_var(DUMMY_SP).into()))
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
// If an effect arg was not specified, we need to specify it.
|
||||
let effect_arg = if tcx
|
||||
.generics_of(trait_id)
|
||||
.host_effect_index
|
||||
.is_some_and(|x| args.get(x - 1).is_none())
|
||||
{
|
||||
Some(GenericArg::from(callee_id.map_or(tcx.consts.true_, |def_id| {
|
||||
tcx.expected_host_effect_param_for_body(def_id)
|
||||
})))
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
let trait_ref = TraitRef::new(
|
||||
tcx,
|
||||
trait_id,
|
||||
[GenericArg::from(ty)].into_iter().chain(args).chain(effect_arg),
|
||||
);
|
||||
let trait_ref = TraitRef::new(tcx, trait_id, [GenericArg::from(ty)].into_iter().chain(args));
|
||||
|
||||
debug_assert_matches!(
|
||||
tcx.def_kind(trait_id),
|
||||
@ -375,7 +358,7 @@ fn is_normalizable_helper<'tcx>(
|
||||
}
|
||||
// prevent recursive loops, false-negative is better than endless loop leading to stack overflow
|
||||
cache.insert(ty, false);
|
||||
let infcx = cx.tcx.infer_ctxt().build();
|
||||
let infcx = cx.tcx.infer_ctxt().build(cx.typing_mode());
|
||||
let cause = ObligationCause::dummy();
|
||||
let result = if infcx.at(&cause, param_env).query_normalize(ty).is_ok() {
|
||||
match ty.kind() {
|
||||
@ -988,9 +971,7 @@ pub fn approx_ty_size<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> u64 {
|
||||
match (cx.layout_of(ty).map(|layout| layout.size.bytes()), ty.kind()) {
|
||||
(Ok(size), _) => size,
|
||||
(Err(_), ty::Tuple(list)) => list.iter().map(|t| approx_ty_size(cx, t)).sum(),
|
||||
(Err(_), ty::Array(t, n)) => {
|
||||
n.try_eval_target_usize(cx.tcx, cx.param_env).unwrap_or_default() * approx_ty_size(cx, *t)
|
||||
},
|
||||
(Err(_), ty::Array(t, n)) => n.try_to_target_usize(cx.tcx).unwrap_or_default() * approx_ty_size(cx, *t),
|
||||
(Err(_), ty::Adt(def, subst)) if def.is_struct() => def
|
||||
.variants()
|
||||
.iter()
|
||||
@ -1207,7 +1188,7 @@ pub fn interior_mut_ty_chain(&mut self, cx: &LateContext<'tcx>, ty: Ty<'tcx>) ->
|
||||
let chain = match *ty.kind() {
|
||||
ty::RawPtr(inner_ty, _) if !self.ignore_pointers => self.interior_mut_ty_chain(cx, inner_ty),
|
||||
ty::Ref(_, inner_ty, _) | ty::Slice(inner_ty) => self.interior_mut_ty_chain(cx, inner_ty),
|
||||
ty::Array(inner_ty, size) if size.try_eval_target_usize(cx.tcx, cx.param_env) != Some(0) => {
|
||||
ty::Array(inner_ty, size) if size.try_to_target_usize(cx.tcx) != Some(0) => {
|
||||
self.interior_mut_ty_chain(cx, inner_ty)
|
||||
},
|
||||
ty::Tuple(fields) => fields.iter().find_map(|ty| self.interior_mut_ty_chain(cx, ty)),
|
||||
@ -1281,7 +1262,7 @@ fn helper<'tcx>(tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>, ty: AliasTy<'tcx>)
|
||||
let cause = ObligationCause::dummy();
|
||||
match tcx
|
||||
.infer_ctxt()
|
||||
.build()
|
||||
.build(TypingMode::from_param_env(param_env))
|
||||
.at(&cause, param_env)
|
||||
.query_normalize(Ty::new_projection_from_args(tcx, ty.def_id, ty.args))
|
||||
{
|
||||
@ -1297,7 +1278,12 @@ fn helper<'tcx>(tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>, ty: AliasTy<'tcx>)
|
||||
|
||||
pub fn normalize_with_regions<'tcx>(tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>, ty: Ty<'tcx>) -> Ty<'tcx> {
|
||||
let cause = ObligationCause::dummy();
|
||||
match tcx.infer_ctxt().build().at(&cause, param_env).query_normalize(ty) {
|
||||
match tcx
|
||||
.infer_ctxt()
|
||||
.build(TypingMode::from_param_env(param_env))
|
||||
.at(&cause, param_env)
|
||||
.query_normalize(ty)
|
||||
{
|
||||
Ok(ty) => ty.value,
|
||||
Err(_) => ty,
|
||||
}
|
||||
|
@ -207,16 +207,7 @@ fn path_segment_certainty(
|
||||
if cx.tcx.res_generics_def_id(path_segment.res).is_some() {
|
||||
let generics = cx.tcx.generics_of(def_id);
|
||||
|
||||
let own_count = generics.own_params.len()
|
||||
- usize::from(generics.host_effect_index.is_some_and(|index| {
|
||||
// Check that the host index actually belongs to this resolution.
|
||||
// E.g. for `Add::add`, host_effect_index is `Some(2)`, but it's part of the parent `Add`
|
||||
// trait's generics.
|
||||
// Add params: [Self#0, Rhs#1, host#2] parent_count=0, count=3
|
||||
// Add::add params: [] parent_count=3, count=3
|
||||
// (3..3).contains(&host_effect_index) => false
|
||||
(generics.parent_count..generics.count()).contains(&index)
|
||||
}));
|
||||
let own_count = generics.own_params.len();
|
||||
let lhs = if (parent_certainty.is_certain() || generics.parent_count == 0) && own_count == 0 {
|
||||
Certainty::Certain(None)
|
||||
} else {
|
||||
@ -310,11 +301,10 @@ fn type_is_inferable_from_arguments(cx: &LateContext<'_>, expr: &Expr<'_>) -> bo
|
||||
|
||||
// Check that all type parameters appear in the functions input types.
|
||||
(0..(generics.parent_count + generics.own_params.len()) as u32).all(|index| {
|
||||
Some(index as usize) == generics.host_effect_index
|
||||
|| fn_sig
|
||||
.inputs()
|
||||
.iter()
|
||||
.any(|input_ty| contains_param(*input_ty.skip_binder(), index))
|
||||
fn_sig
|
||||
.inputs()
|
||||
.iter()
|
||||
.any(|input_ty| contains_param(*input_ty.skip_binder(), index))
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -67,7 +67,7 @@ impl<'tcx> Delegate<'tcx> for MutVarsDelegate {
|
||||
fn consume(&mut self, _: &PlaceWithHirId<'tcx>, _: HirId) {}
|
||||
|
||||
fn borrow(&mut self, cmt: &PlaceWithHirId<'tcx>, _: HirId, bk: ty::BorrowKind) {
|
||||
if bk == ty::BorrowKind::MutBorrow {
|
||||
if bk == ty::BorrowKind::Mutable {
|
||||
self.update(cmt);
|
||||
}
|
||||
}
|
||||
|
@ -344,13 +344,13 @@ fn visit_expr(&mut self, e: &'tcx Expr<'_>) -> Self::Result {
|
||||
.cx
|
||||
.qpath_res(p, hir_id)
|
||||
.opt_def_id()
|
||||
.map_or(false, |id| self.cx.tcx.is_const_fn_raw(id)) => {},
|
||||
.map_or(false, |id| self.cx.tcx.is_const_fn(id)) => {},
|
||||
ExprKind::MethodCall(..)
|
||||
if self
|
||||
.cx
|
||||
.typeck_results()
|
||||
.type_dependent_def_id(e.hir_id)
|
||||
.map_or(false, |id| self.cx.tcx.is_const_fn_raw(id)) => {},
|
||||
.map_or(false, |id| self.cx.tcx.is_const_fn(id)) => {},
|
||||
ExprKind::Binary(_, lhs, rhs)
|
||||
if self.cx.typeck_results().expr_ty(lhs).peel_refs().is_primitive_ty()
|
||||
&& self.cx.typeck_results().expr_ty(rhs).peel_refs().is_primitive_ty() => {},
|
||||
|
@ -1,4 +1,4 @@
|
||||
[toolchain]
|
||||
channel = "nightly-2024-10-18"
|
||||
channel = "nightly-2024-11-07"
|
||||
components = ["cargo", "llvm-tools", "rust-src", "rust-std", "rustc", "rustc-dev", "rustfmt"]
|
||||
profile = "minimal"
|
||||
|
@ -7,7 +7,7 @@
|
||||
#[macro_use]
|
||||
extern crate rustc_session;
|
||||
extern crate rustc_lint;
|
||||
use rustc_lint::LintPass;
|
||||
use rustc_lint::{LintPass, LintVec};
|
||||
|
||||
declare_tool_lint! {
|
||||
pub clippy::TEST_LINT,
|
||||
@ -35,6 +35,9 @@ impl LintPass for Pass {
|
||||
fn name(&self) -> &'static str {
|
||||
"TEST_LINT"
|
||||
}
|
||||
fn get_lints(&self) -> LintVec {
|
||||
vec![TEST_LINT]
|
||||
}
|
||||
}
|
||||
|
||||
declare_lint_pass!(Pass2 => [TEST_LINT_REGISTERED]);
|
||||
|
@ -19,13 +19,5 @@ error: #[allow] attribute found
|
||||
LL | #[allow(unused)]
|
||||
| ^^^^^ help: replace it with: `expect`
|
||||
|
||||
error: #[allow] attribute found
|
||||
--> tests/ui/allow_attributes.rs:53:7
|
||||
|
|
||||
LL | #[allow(unused)]
|
||||
| ^^^^^ help: replace it with: `expect`
|
||||
|
|
||||
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
|
||||
|
||||
error: aborting due to 4 previous errors
|
||||
error: aborting due to 3 previous errors
|
||||
|
||||
|
@ -43,14 +43,5 @@ LL | #[allow(unused)]
|
||||
|
|
||||
= help: try adding a reason at the end with `, reason = ".."`
|
||||
|
||||
error: `allow` attribute without specifying a reason
|
||||
--> tests/ui/allow_attributes_without_reason.rs:46:5
|
||||
|
|
||||
LL | #[allow(unused)]
|
||||
| ^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= help: try adding a reason at the end with `, reason = ".."`
|
||||
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
|
||||
|
||||
error: aborting due to 6 previous errors
|
||||
error: aborting due to 5 previous errors
|
||||
|
||||
|
@ -1,12 +1,3 @@
|
||||
error: you have declared `#[inline(always)]` on `test_attr_lint`. This is usually a bad idea
|
||||
--> tests/ui/attrs.rs:5:1
|
||||
|
|
||||
LL | #[inline(always)]
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: `-D clippy::inline-always` implied by `-D warnings`
|
||||
= help: to override `-D warnings` add `#[allow(clippy::inline_always)]`
|
||||
|
||||
error: the since field must contain a semver-compliant version
|
||||
--> tests/ui/attrs.rs:27:14
|
||||
|
|
||||
@ -22,5 +13,14 @@ error: the since field must contain a semver-compliant version
|
||||
LL | #[deprecated(since = "1")]
|
||||
| ^^^^^^^^^^^
|
||||
|
||||
error: you have declared `#[inline(always)]` on `test_attr_lint`. This is usually a bad idea
|
||||
--> tests/ui/attrs.rs:5:1
|
||||
|
|
||||
LL | #[inline(always)]
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: `-D clippy::inline-always` implied by `-D warnings`
|
||||
= help: to override `-D warnings` add `#[allow(clippy::inline_always)]`
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
|
||||
|
@ -1,3 +1,10 @@
|
||||
error: `clippy::restriction` is not meant to be enabled as a group
|
||||
|
|
||||
= note: because of the command line `--warn clippy::restriction`
|
||||
= help: enable the restriction lints you need individually
|
||||
= note: `-D clippy::blanket-clippy-restriction-lints` implied by `-D warnings`
|
||||
= help: to override `-D warnings` add `#[allow(clippy::blanket_clippy_restriction_lints)]`
|
||||
|
||||
error: `clippy::restriction` is not meant to be enabled as a group
|
||||
--> tests/ui/blanket_clippy_restriction_lints.rs:6:9
|
||||
|
|
||||
@ -5,8 +12,6 @@ LL | #![warn(clippy::restriction)]
|
||||
| ^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= help: enable the restriction lints you need individually
|
||||
= note: `-D clippy::blanket-clippy-restriction-lints` implied by `-D warnings`
|
||||
= help: to override `-D warnings` add `#[allow(clippy::blanket_clippy_restriction_lints)]`
|
||||
|
||||
error: `clippy::restriction` is not meant to be enabled as a group
|
||||
--> tests/ui/blanket_clippy_restriction_lints.rs:8:9
|
||||
@ -24,10 +29,5 @@ LL | #![forbid(clippy::restriction)]
|
||||
|
|
||||
= help: enable the restriction lints you need individually
|
||||
|
||||
error: `clippy::restriction` is not meant to be enabled as a group
|
||||
|
|
||||
= note: because of the command line `--warn clippy::restriction`
|
||||
= help: enable the restriction lints you need individually
|
||||
|
||||
error: aborting due to 4 previous errors
|
||||
|
||||
|
@ -1,7 +1,6 @@
|
||||
//@no-rustfix
|
||||
|
||||
#![feature(repr128)]
|
||||
#![feature(isqrt)]
|
||||
#![allow(incomplete_features)]
|
||||
#![warn(
|
||||
clippy::cast_precision_loss,
|
||||
|
@ -1,5 +1,5 @@
|
||||
error: casting `i32` to `f32` causes a loss of precision (`i32` is 32 bits wide, but `f32`'s mantissa is only 23 bits wide)
|
||||
--> tests/ui/cast.rs:26:5
|
||||
--> tests/ui/cast.rs:25:5
|
||||
|
|
||||
LL | x0 as f32;
|
||||
| ^^^^^^^^^
|
||||
@ -8,37 +8,37 @@ LL | x0 as f32;
|
||||
= help: to override `-D warnings` add `#[allow(clippy::cast_precision_loss)]`
|
||||
|
||||
error: casting `i64` to `f32` causes a loss of precision (`i64` is 64 bits wide, but `f32`'s mantissa is only 23 bits wide)
|
||||
--> tests/ui/cast.rs:30:5
|
||||
--> tests/ui/cast.rs:29:5
|
||||
|
|
||||
LL | x1 as f32;
|
||||
| ^^^^^^^^^
|
||||
|
||||
error: casting `i64` to `f64` causes a loss of precision (`i64` is 64 bits wide, but `f64`'s mantissa is only 52 bits wide)
|
||||
--> tests/ui/cast.rs:32:5
|
||||
--> tests/ui/cast.rs:31:5
|
||||
|
|
||||
LL | x1 as f64;
|
||||
| ^^^^^^^^^
|
||||
|
||||
error: casting `u32` to `f32` causes a loss of precision (`u32` is 32 bits wide, but `f32`'s mantissa is only 23 bits wide)
|
||||
--> tests/ui/cast.rs:35:5
|
||||
--> tests/ui/cast.rs:34:5
|
||||
|
|
||||
LL | x2 as f32;
|
||||
| ^^^^^^^^^
|
||||
|
||||
error: casting `u64` to `f32` causes a loss of precision (`u64` is 64 bits wide, but `f32`'s mantissa is only 23 bits wide)
|
||||
--> tests/ui/cast.rs:38:5
|
||||
--> tests/ui/cast.rs:37:5
|
||||
|
|
||||
LL | x3 as f32;
|
||||
| ^^^^^^^^^
|
||||
|
||||
error: casting `u64` to `f64` causes a loss of precision (`u64` is 64 bits wide, but `f64`'s mantissa is only 52 bits wide)
|
||||
--> tests/ui/cast.rs:40:5
|
||||
--> tests/ui/cast.rs:39:5
|
||||
|
|
||||
LL | x3 as f64;
|
||||
| ^^^^^^^^^
|
||||
|
||||
error: casting `f32` to `i32` may truncate the value
|
||||
--> tests/ui/cast.rs:43:5
|
||||
--> tests/ui/cast.rs:42:5
|
||||
|
|
||||
LL | 1f32 as i32;
|
||||
| ^^^^^^^^^^^
|
||||
@ -48,7 +48,7 @@ LL | 1f32 as i32;
|
||||
= help: to override `-D warnings` add `#[allow(clippy::cast_possible_truncation)]`
|
||||
|
||||
error: casting `f32` to `u32` may truncate the value
|
||||
--> tests/ui/cast.rs:45:5
|
||||
--> tests/ui/cast.rs:44:5
|
||||
|
|
||||
LL | 1f32 as u32;
|
||||
| ^^^^^^^^^^^
|
||||
@ -56,7 +56,7 @@ LL | 1f32 as u32;
|
||||
= help: if this is intentional allow the lint with `#[allow(clippy::cast_possible_truncation)]` ...
|
||||
|
||||
error: casting `f32` to `u32` may lose the sign of the value
|
||||
--> tests/ui/cast.rs:45:5
|
||||
--> tests/ui/cast.rs:44:5
|
||||
|
|
||||
LL | 1f32 as u32;
|
||||
| ^^^^^^^^^^^
|
||||
@ -65,7 +65,7 @@ LL | 1f32 as u32;
|
||||
= help: to override `-D warnings` add `#[allow(clippy::cast_sign_loss)]`
|
||||
|
||||
error: casting `f64` to `f32` may truncate the value
|
||||
--> tests/ui/cast.rs:49:5
|
||||
--> tests/ui/cast.rs:48:5
|
||||
|
|
||||
LL | 1f64 as f32;
|
||||
| ^^^^^^^^^^^
|
||||
@ -73,7 +73,7 @@ LL | 1f64 as f32;
|
||||
= help: if this is intentional allow the lint with `#[allow(clippy::cast_possible_truncation)]` ...
|
||||
|
||||
error: casting `i32` to `i8` may truncate the value
|
||||
--> tests/ui/cast.rs:51:5
|
||||
--> tests/ui/cast.rs:50:5
|
||||
|
|
||||
LL | 1i32 as i8;
|
||||
| ^^^^^^^^^^
|
||||
@ -85,7 +85,7 @@ LL | i8::try_from(1i32);
|
||||
| ~~~~~~~~~~~~~~~~~~
|
||||
|
||||
error: casting `i32` to `u8` may truncate the value
|
||||
--> tests/ui/cast.rs:53:5
|
||||
--> tests/ui/cast.rs:52:5
|
||||
|
|
||||
LL | 1i32 as u8;
|
||||
| ^^^^^^^^^^
|
||||
@ -97,7 +97,7 @@ LL | u8::try_from(1i32);
|
||||
| ~~~~~~~~~~~~~~~~~~
|
||||
|
||||
error: casting `f64` to `isize` may truncate the value
|
||||
--> tests/ui/cast.rs:55:5
|
||||
--> tests/ui/cast.rs:54:5
|
||||
|
|
||||
LL | 1f64 as isize;
|
||||
| ^^^^^^^^^^^^^
|
||||
@ -105,7 +105,7 @@ LL | 1f64 as isize;
|
||||
= help: if this is intentional allow the lint with `#[allow(clippy::cast_possible_truncation)]` ...
|
||||
|
||||
error: casting `f64` to `usize` may truncate the value
|
||||
--> tests/ui/cast.rs:57:5
|
||||
--> tests/ui/cast.rs:56:5
|
||||
|
|
||||
LL | 1f64 as usize;
|
||||
| ^^^^^^^^^^^^^
|
||||
@ -113,13 +113,13 @@ LL | 1f64 as usize;
|
||||
= help: if this is intentional allow the lint with `#[allow(clippy::cast_possible_truncation)]` ...
|
||||
|
||||
error: casting `f64` to `usize` may lose the sign of the value
|
||||
--> tests/ui/cast.rs:57:5
|
||||
--> tests/ui/cast.rs:56:5
|
||||
|
|
||||
LL | 1f64 as usize;
|
||||
| ^^^^^^^^^^^^^
|
||||
|
||||
error: casting `u32` to `u16` may truncate the value
|
||||
--> tests/ui/cast.rs:60:5
|
||||
--> tests/ui/cast.rs:59:5
|
||||
|
|
||||
LL | 1f32 as u32 as u16;
|
||||
| ^^^^^^^^^^^^^^^^^^
|
||||
@ -131,7 +131,7 @@ LL | u16::try_from(1f32 as u32);
|
||||
| ~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
error: casting `f32` to `u32` may truncate the value
|
||||
--> tests/ui/cast.rs:60:5
|
||||
--> tests/ui/cast.rs:59:5
|
||||
|
|
||||
LL | 1f32 as u32 as u16;
|
||||
| ^^^^^^^^^^^
|
||||
@ -139,13 +139,13 @@ LL | 1f32 as u32 as u16;
|
||||
= help: if this is intentional allow the lint with `#[allow(clippy::cast_possible_truncation)]` ...
|
||||
|
||||
error: casting `f32` to `u32` may lose the sign of the value
|
||||
--> tests/ui/cast.rs:60:5
|
||||
--> tests/ui/cast.rs:59:5
|
||||
|
|
||||
LL | 1f32 as u32 as u16;
|
||||
| ^^^^^^^^^^^
|
||||
|
||||
error: casting `i32` to `i8` may truncate the value
|
||||
--> tests/ui/cast.rs:65:22
|
||||
--> tests/ui/cast.rs:64:22
|
||||
|
|
||||
LL | let _x: i8 = 1i32 as _;
|
||||
| ^^^^^^^^^
|
||||
@ -157,7 +157,7 @@ LL | let _x: i8 = 1i32.try_into();
|
||||
| ~~~~~~~~~~~~~~~
|
||||
|
||||
error: casting `f32` to `i32` may truncate the value
|
||||
--> tests/ui/cast.rs:67:9
|
||||
--> tests/ui/cast.rs:66:9
|
||||
|
|
||||
LL | 1f32 as i32;
|
||||
| ^^^^^^^^^^^
|
||||
@ -165,7 +165,7 @@ LL | 1f32 as i32;
|
||||
= help: if this is intentional allow the lint with `#[allow(clippy::cast_possible_truncation)]` ...
|
||||
|
||||
error: casting `f64` to `i32` may truncate the value
|
||||
--> tests/ui/cast.rs:69:9
|
||||
--> tests/ui/cast.rs:68:9
|
||||
|
|
||||
LL | 1f64 as i32;
|
||||
| ^^^^^^^^^^^
|
||||
@ -173,7 +173,7 @@ LL | 1f64 as i32;
|
||||
= help: if this is intentional allow the lint with `#[allow(clippy::cast_possible_truncation)]` ...
|
||||
|
||||
error: casting `f32` to `u8` may truncate the value
|
||||
--> tests/ui/cast.rs:71:9
|
||||
--> tests/ui/cast.rs:70:9
|
||||
|
|
||||
LL | 1f32 as u8;
|
||||
| ^^^^^^^^^^
|
||||
@ -181,13 +181,13 @@ LL | 1f32 as u8;
|
||||
= help: if this is intentional allow the lint with `#[allow(clippy::cast_possible_truncation)]` ...
|
||||
|
||||
error: casting `f32` to `u8` may lose the sign of the value
|
||||
--> tests/ui/cast.rs:71:9
|
||||
--> tests/ui/cast.rs:70:9
|
||||
|
|
||||
LL | 1f32 as u8;
|
||||
| ^^^^^^^^^^
|
||||
|
||||
error: casting `u8` to `i8` may wrap around the value
|
||||
--> tests/ui/cast.rs:76:5
|
||||
--> tests/ui/cast.rs:75:5
|
||||
|
|
||||
LL | 1u8 as i8;
|
||||
| ^^^^^^^^^
|
||||
@ -196,31 +196,31 @@ LL | 1u8 as i8;
|
||||
= help: to override `-D warnings` add `#[allow(clippy::cast_possible_wrap)]`
|
||||
|
||||
error: casting `u16` to `i16` may wrap around the value
|
||||
--> tests/ui/cast.rs:79:5
|
||||
--> tests/ui/cast.rs:78:5
|
||||
|
|
||||
LL | 1u16 as i16;
|
||||
| ^^^^^^^^^^^
|
||||
|
||||
error: casting `u32` to `i32` may wrap around the value
|
||||
--> tests/ui/cast.rs:81:5
|
||||
--> tests/ui/cast.rs:80:5
|
||||
|
|
||||
LL | 1u32 as i32;
|
||||
| ^^^^^^^^^^^
|
||||
|
||||
error: casting `u64` to `i64` may wrap around the value
|
||||
--> tests/ui/cast.rs:83:5
|
||||
--> tests/ui/cast.rs:82:5
|
||||
|
|
||||
LL | 1u64 as i64;
|
||||
| ^^^^^^^^^^^
|
||||
|
||||
error: casting `usize` to `isize` may wrap around the value
|
||||
--> tests/ui/cast.rs:85:5
|
||||
--> tests/ui/cast.rs:84:5
|
||||
|
|
||||
LL | 1usize as isize;
|
||||
| ^^^^^^^^^^^^^^^
|
||||
|
||||
error: casting `usize` to `i8` may truncate the value
|
||||
--> tests/ui/cast.rs:88:5
|
||||
--> tests/ui/cast.rs:87:5
|
||||
|
|
||||
LL | 1usize as i8;
|
||||
| ^^^^^^^^^^^^
|
||||
@ -232,7 +232,7 @@ LL | i8::try_from(1usize);
|
||||
| ~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
error: casting `usize` to `i16` may truncate the value
|
||||
--> tests/ui/cast.rs:91:5
|
||||
--> tests/ui/cast.rs:90:5
|
||||
|
|
||||
LL | 1usize as i16;
|
||||
| ^^^^^^^^^^^^^
|
||||
@ -244,7 +244,7 @@ LL | i16::try_from(1usize);
|
||||
| ~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
error: casting `usize` to `i16` may wrap around the value on targets with 16-bit wide pointers
|
||||
--> tests/ui/cast.rs:91:5
|
||||
--> tests/ui/cast.rs:90:5
|
||||
|
|
||||
LL | 1usize as i16;
|
||||
| ^^^^^^^^^^^^^
|
||||
@ -253,7 +253,7 @@ LL | 1usize as i16;
|
||||
= note: for more information see https://doc.rust-lang.org/reference/types/numeric.html#machine-dependent-integer-types
|
||||
|
||||
error: casting `usize` to `i32` may truncate the value on targets with 64-bit wide pointers
|
||||
--> tests/ui/cast.rs:96:5
|
||||
--> tests/ui/cast.rs:95:5
|
||||
|
|
||||
LL | 1usize as i32;
|
||||
| ^^^^^^^^^^^^^
|
||||
@ -265,19 +265,19 @@ LL | i32::try_from(1usize);
|
||||
| ~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
error: casting `usize` to `i32` may wrap around the value on targets with 32-bit wide pointers
|
||||
--> tests/ui/cast.rs:96:5
|
||||
--> tests/ui/cast.rs:95:5
|
||||
|
|
||||
LL | 1usize as i32;
|
||||
| ^^^^^^^^^^^^^
|
||||
|
||||
error: casting `usize` to `i64` may wrap around the value on targets with 64-bit wide pointers
|
||||
--> tests/ui/cast.rs:100:5
|
||||
--> tests/ui/cast.rs:99:5
|
||||
|
|
||||
LL | 1usize as i64;
|
||||
| ^^^^^^^^^^^^^
|
||||
|
||||
error: casting `u16` to `isize` may wrap around the value on targets with 16-bit wide pointers
|
||||
--> tests/ui/cast.rs:105:5
|
||||
--> tests/ui/cast.rs:104:5
|
||||
|
|
||||
LL | 1u16 as isize;
|
||||
| ^^^^^^^^^^^^^
|
||||
@ -286,13 +286,13 @@ LL | 1u16 as isize;
|
||||
= note: for more information see https://doc.rust-lang.org/reference/types/numeric.html#machine-dependent-integer-types
|
||||
|
||||
error: casting `u32` to `isize` may wrap around the value on targets with 32-bit wide pointers
|
||||
--> tests/ui/cast.rs:109:5
|
||||
--> tests/ui/cast.rs:108:5
|
||||
|
|
||||
LL | 1u32 as isize;
|
||||
| ^^^^^^^^^^^^^
|
||||
|
||||
error: casting `u64` to `isize` may truncate the value on targets with 32-bit wide pointers
|
||||
--> tests/ui/cast.rs:112:5
|
||||
--> tests/ui/cast.rs:111:5
|
||||
|
|
||||
LL | 1u64 as isize;
|
||||
| ^^^^^^^^^^^^^
|
||||
@ -304,55 +304,55 @@ LL | isize::try_from(1u64);
|
||||
| ~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
error: casting `u64` to `isize` may wrap around the value on targets with 64-bit wide pointers
|
||||
--> tests/ui/cast.rs:112:5
|
||||
--> tests/ui/cast.rs:111:5
|
||||
|
|
||||
LL | 1u64 as isize;
|
||||
| ^^^^^^^^^^^^^
|
||||
|
||||
error: casting `i32` to `u32` may lose the sign of the value
|
||||
--> tests/ui/cast.rs:117:5
|
||||
--> tests/ui/cast.rs:116:5
|
||||
|
|
||||
LL | -1i32 as u32;
|
||||
| ^^^^^^^^^^^^
|
||||
|
||||
error: casting `isize` to `usize` may lose the sign of the value
|
||||
--> tests/ui/cast.rs:120:5
|
||||
--> tests/ui/cast.rs:119:5
|
||||
|
|
||||
LL | -1isize as usize;
|
||||
| ^^^^^^^^^^^^^^^^
|
||||
|
||||
error: casting `i8` to `u8` may lose the sign of the value
|
||||
--> tests/ui/cast.rs:131:5
|
||||
--> tests/ui/cast.rs:130:5
|
||||
|
|
||||
LL | (i8::MIN).abs() as u8;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: casting `i64` to `u64` may lose the sign of the value
|
||||
--> tests/ui/cast.rs:135:5
|
||||
--> tests/ui/cast.rs:134:5
|
||||
|
|
||||
LL | (-1i64).abs() as u64;
|
||||
| ^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: casting `isize` to `usize` may lose the sign of the value
|
||||
--> tests/ui/cast.rs:136:5
|
||||
--> tests/ui/cast.rs:135:5
|
||||
|
|
||||
LL | (-1isize).abs() as usize;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: casting `i64` to `u64` may lose the sign of the value
|
||||
--> tests/ui/cast.rs:143:5
|
||||
--> tests/ui/cast.rs:142:5
|
||||
|
|
||||
LL | (unsafe { (-1i64).checked_abs().unwrap_unchecked() }) as u64;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: casting `i64` to `u64` may lose the sign of the value
|
||||
--> tests/ui/cast.rs:158:5
|
||||
--> tests/ui/cast.rs:157:5
|
||||
|
|
||||
LL | (unsafe { (-1i64).checked_isqrt().unwrap_unchecked() }) as u64;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: casting `i64` to `i8` may truncate the value
|
||||
--> tests/ui/cast.rs:209:5
|
||||
--> tests/ui/cast.rs:208:5
|
||||
|
|
||||
LL | (-99999999999i64).min(1) as i8;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
@ -364,7 +364,7 @@ LL | i8::try_from((-99999999999i64).min(1));
|
||||
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
error: casting `u64` to `u8` may truncate the value
|
||||
--> tests/ui/cast.rs:223:5
|
||||
--> tests/ui/cast.rs:222:5
|
||||
|
|
||||
LL | 999999u64.clamp(0, 256) as u8;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
@ -376,7 +376,7 @@ LL | u8::try_from(999999u64.clamp(0, 256));
|
||||
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
error: casting `main::E2` to `u8` may truncate the value
|
||||
--> tests/ui/cast.rs:246:21
|
||||
--> tests/ui/cast.rs:245:21
|
||||
|
|
||||
LL | let _ = self as u8;
|
||||
| ^^^^^^^^^^
|
||||
@ -388,7 +388,7 @@ LL | let _ = u8::try_from(self);
|
||||
| ~~~~~~~~~~~~~~~~~~
|
||||
|
||||
error: casting `main::E2::B` to `u8` will truncate the value
|
||||
--> tests/ui/cast.rs:248:21
|
||||
--> tests/ui/cast.rs:247:21
|
||||
|
|
||||
LL | let _ = Self::B as u8;
|
||||
| ^^^^^^^^^^^^^
|
||||
@ -397,7 +397,7 @@ LL | let _ = Self::B as u8;
|
||||
= help: to override `-D warnings` add `#[allow(clippy::cast_enum_truncation)]`
|
||||
|
||||
error: casting `main::E5` to `i8` may truncate the value
|
||||
--> tests/ui/cast.rs:290:21
|
||||
--> tests/ui/cast.rs:289:21
|
||||
|
|
||||
LL | let _ = self as i8;
|
||||
| ^^^^^^^^^^
|
||||
@ -409,13 +409,13 @@ LL | let _ = i8::try_from(self);
|
||||
| ~~~~~~~~~~~~~~~~~~
|
||||
|
||||
error: casting `main::E5::A` to `i8` will truncate the value
|
||||
--> tests/ui/cast.rs:292:21
|
||||
--> tests/ui/cast.rs:291:21
|
||||
|
|
||||
LL | let _ = Self::A as i8;
|
||||
| ^^^^^^^^^^^^^
|
||||
|
||||
error: casting `main::E6` to `i16` may truncate the value
|
||||
--> tests/ui/cast.rs:309:21
|
||||
--> tests/ui/cast.rs:308:21
|
||||
|
|
||||
LL | let _ = self as i16;
|
||||
| ^^^^^^^^^^^
|
||||
@ -427,7 +427,7 @@ LL | let _ = i16::try_from(self);
|
||||
| ~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
error: casting `main::E7` to `usize` may truncate the value on targets with 32-bit wide pointers
|
||||
--> tests/ui/cast.rs:328:21
|
||||
--> tests/ui/cast.rs:327:21
|
||||
|
|
||||
LL | let _ = self as usize;
|
||||
| ^^^^^^^^^^^^^
|
||||
@ -439,7 +439,7 @@ LL | let _ = usize::try_from(self);
|
||||
| ~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
error: casting `main::E10` to `u16` may truncate the value
|
||||
--> tests/ui/cast.rs:375:21
|
||||
--> tests/ui/cast.rs:374:21
|
||||
|
|
||||
LL | let _ = self as u16;
|
||||
| ^^^^^^^^^^^
|
||||
@ -451,7 +451,7 @@ LL | let _ = u16::try_from(self);
|
||||
| ~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
error: casting `u32` to `u8` may truncate the value
|
||||
--> tests/ui/cast.rs:386:13
|
||||
--> tests/ui/cast.rs:385:13
|
||||
|
|
||||
LL | let c = (q >> 16) as u8;
|
||||
| ^^^^^^^^^^^^^^^
|
||||
@ -463,7 +463,7 @@ LL | let c = u8::try_from(q >> 16);
|
||||
| ~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
error: casting `u32` to `u8` may truncate the value
|
||||
--> tests/ui/cast.rs:390:13
|
||||
--> tests/ui/cast.rs:389:13
|
||||
|
|
||||
LL | let c = (q / 1000) as u8;
|
||||
| ^^^^^^^^^^^^^^^^
|
||||
@ -475,85 +475,85 @@ LL | let c = u8::try_from(q / 1000);
|
||||
| ~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
error: casting `i32` to `u32` may lose the sign of the value
|
||||
--> tests/ui/cast.rs:402:9
|
||||
--> tests/ui/cast.rs:401:9
|
||||
|
|
||||
LL | (x * x) as u32;
|
||||
| ^^^^^^^^^^^^^^
|
||||
|
||||
error: casting `i32` to `u32` may lose the sign of the value
|
||||
--> tests/ui/cast.rs:407:32
|
||||
--> tests/ui/cast.rs:406:32
|
||||
|
|
||||
LL | let _a = |x: i32| -> u32 { (x * x * x * x) as u32 };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: casting `i32` to `u32` may lose the sign of the value
|
||||
--> tests/ui/cast.rs:409:5
|
||||
--> tests/ui/cast.rs:408:5
|
||||
|
|
||||
LL | (2_i32).checked_pow(3).unwrap() as u32;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: casting `i32` to `u32` may lose the sign of the value
|
||||
--> tests/ui/cast.rs:410:5
|
||||
--> tests/ui/cast.rs:409:5
|
||||
|
|
||||
LL | (-2_i32).pow(3) as u32;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: casting `i32` to `u32` may lose the sign of the value
|
||||
--> tests/ui/cast.rs:415:5
|
||||
--> tests/ui/cast.rs:414:5
|
||||
|
|
||||
LL | (-5_i32 % 2) as u32;
|
||||
| ^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: casting `i32` to `u32` may lose the sign of the value
|
||||
--> tests/ui/cast.rs:417:5
|
||||
--> tests/ui/cast.rs:416:5
|
||||
|
|
||||
LL | (-5_i32 % -2) as u32;
|
||||
| ^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: casting `i32` to `u32` may lose the sign of the value
|
||||
--> tests/ui/cast.rs:420:5
|
||||
--> tests/ui/cast.rs:419:5
|
||||
|
|
||||
LL | (-2_i32 >> 1) as u32;
|
||||
| ^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: casting `i32` to `u32` may lose the sign of the value
|
||||
--> tests/ui/cast.rs:424:5
|
||||
--> tests/ui/cast.rs:423:5
|
||||
|
|
||||
LL | (x * x) as u32;
|
||||
| ^^^^^^^^^^^^^^
|
||||
|
||||
error: casting `i32` to `u32` may lose the sign of the value
|
||||
--> tests/ui/cast.rs:425:5
|
||||
--> tests/ui/cast.rs:424:5
|
||||
|
|
||||
LL | (x * x * x) as u32;
|
||||
| ^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: casting `i16` to `u16` may lose the sign of the value
|
||||
--> tests/ui/cast.rs:429:5
|
||||
--> tests/ui/cast.rs:428:5
|
||||
|
|
||||
LL | (y * y * y * y * -2) as u16;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: casting `i16` to `u16` may lose the sign of the value
|
||||
--> tests/ui/cast.rs:431:5
|
||||
--> tests/ui/cast.rs:430:5
|
||||
|
|
||||
LL | (y * y * y / y * 2) as u16;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: casting `i16` to `u16` may lose the sign of the value
|
||||
--> tests/ui/cast.rs:432:5
|
||||
--> tests/ui/cast.rs:431:5
|
||||
|
|
||||
LL | (y * y / y * 2) as u16;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: casting `i16` to `u16` may lose the sign of the value
|
||||
--> tests/ui/cast.rs:434:5
|
||||
--> tests/ui/cast.rs:433:5
|
||||
|
|
||||
LL | (y / y * y * -2) as u16;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: equal expressions as operands to `/`
|
||||
--> tests/ui/cast.rs:434:6
|
||||
--> tests/ui/cast.rs:433:6
|
||||
|
|
||||
LL | (y / y * y * -2) as u16;
|
||||
| ^^^^^
|
||||
@ -561,97 +561,97 @@ LL | (y / y * y * -2) as u16;
|
||||
= note: `#[deny(clippy::eq_op)]` on by default
|
||||
|
||||
error: casting `i16` to `u16` may lose the sign of the value
|
||||
--> tests/ui/cast.rs:437:5
|
||||
--> tests/ui/cast.rs:436:5
|
||||
|
|
||||
LL | (y + y + y + -2) as u16;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: casting `i16` to `u16` may lose the sign of the value
|
||||
--> tests/ui/cast.rs:439:5
|
||||
--> tests/ui/cast.rs:438:5
|
||||
|
|
||||
LL | (y + y + y + 2) as u16;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: casting `i16` to `u16` may lose the sign of the value
|
||||
--> tests/ui/cast.rs:443:5
|
||||
--> tests/ui/cast.rs:442:5
|
||||
|
|
||||
LL | (z + -2) as u16;
|
||||
| ^^^^^^^^^^^^^^^
|
||||
|
||||
error: casting `i16` to `u16` may lose the sign of the value
|
||||
--> tests/ui/cast.rs:445:5
|
||||
--> tests/ui/cast.rs:444:5
|
||||
|
|
||||
LL | (z + z + 2) as u16;
|
||||
| ^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: casting `i32` to `u32` may lose the sign of the value
|
||||
--> tests/ui/cast.rs:448:9
|
||||
--> tests/ui/cast.rs:447:9
|
||||
|
|
||||
LL | (a * a * b * b * c * c) as u32;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: casting `i32` to `u32` may lose the sign of the value
|
||||
--> tests/ui/cast.rs:449:9
|
||||
--> tests/ui/cast.rs:448:9
|
||||
|
|
||||
LL | (a * b * c) as u32;
|
||||
| ^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: casting `i32` to `u32` may lose the sign of the value
|
||||
--> tests/ui/cast.rs:451:9
|
||||
--> tests/ui/cast.rs:450:9
|
||||
|
|
||||
LL | (a * -b * c) as u32;
|
||||
| ^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: casting `i32` to `u32` may lose the sign of the value
|
||||
--> tests/ui/cast.rs:453:9
|
||||
--> tests/ui/cast.rs:452:9
|
||||
|
|
||||
LL | (a * b * c * c) as u32;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: casting `i32` to `u32` may lose the sign of the value
|
||||
--> tests/ui/cast.rs:454:9
|
||||
--> tests/ui/cast.rs:453:9
|
||||
|
|
||||
LL | (a * -2) as u32;
|
||||
| ^^^^^^^^^^^^^^^
|
||||
|
||||
error: casting `i32` to `u32` may lose the sign of the value
|
||||
--> tests/ui/cast.rs:456:9
|
||||
--> tests/ui/cast.rs:455:9
|
||||
|
|
||||
LL | (a * b * c * -2) as u32;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: casting `i32` to `u32` may lose the sign of the value
|
||||
--> tests/ui/cast.rs:458:9
|
||||
--> tests/ui/cast.rs:457:9
|
||||
|
|
||||
LL | (a / b) as u32;
|
||||
| ^^^^^^^^^^^^^^
|
||||
|
||||
error: casting `i32` to `u32` may lose the sign of the value
|
||||
--> tests/ui/cast.rs:459:9
|
||||
--> tests/ui/cast.rs:458:9
|
||||
|
|
||||
LL | (a / b * c) as u32;
|
||||
| ^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: casting `i32` to `u32` may lose the sign of the value
|
||||
--> tests/ui/cast.rs:461:9
|
||||
--> tests/ui/cast.rs:460:9
|
||||
|
|
||||
LL | (a / b + b * c) as u32;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: casting `i32` to `u32` may lose the sign of the value
|
||||
--> tests/ui/cast.rs:463:9
|
||||
--> tests/ui/cast.rs:462:9
|
||||
|
|
||||
LL | a.saturating_pow(3) as u32;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: casting `i32` to `u32` may lose the sign of the value
|
||||
--> tests/ui/cast.rs:465:9
|
||||
--> tests/ui/cast.rs:464:9
|
||||
|
|
||||
LL | (a.abs() * b.pow(2) / c.abs()) as u32
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: casting `i32` to `u32` may lose the sign of the value
|
||||
--> tests/ui/cast.rs:473:21
|
||||
--> tests/ui/cast.rs:472:21
|
||||
|
|
||||
LL | let _ = i32::MIN as u32; // cast_sign_loss
|
||||
| ^^^^^^^^^^^^^^^
|
||||
@ -662,7 +662,7 @@ LL | m!();
|
||||
= note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
|
||||
error: casting `u32` to `u8` may truncate the value
|
||||
--> tests/ui/cast.rs:474:21
|
||||
--> tests/ui/cast.rs:473:21
|
||||
|
|
||||
LL | let _ = u32::MAX as u8; // cast_possible_truncation
|
||||
| ^^^^^^^^^^^^^^
|
||||
@ -678,7 +678,7 @@ LL | let _ = u8::try_from(u32::MAX); // cast_possible_truncation
|
||||
| ~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
error: casting `f64` to `f32` may truncate the value
|
||||
--> tests/ui/cast.rs:475:21
|
||||
--> tests/ui/cast.rs:474:21
|
||||
|
|
||||
LL | let _ = std::f64::consts::PI as f32; // cast_possible_truncation
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
@ -690,7 +690,7 @@ LL | m!();
|
||||
= note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
|
||||
error: casting `i64` to `usize` may truncate the value on targets with 32-bit wide pointers
|
||||
--> tests/ui/cast.rs:484:5
|
||||
--> tests/ui/cast.rs:483:5
|
||||
|
|
||||
LL | bar.unwrap().unwrap() as usize
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
@ -702,13 +702,13 @@ LL | usize::try_from(bar.unwrap().unwrap())
|
||||
|
|
||||
|
||||
error: casting `i64` to `usize` may lose the sign of the value
|
||||
--> tests/ui/cast.rs:484:5
|
||||
--> tests/ui/cast.rs:483:5
|
||||
|
|
||||
LL | bar.unwrap().unwrap() as usize
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: casting `u64` to `u8` may truncate the value
|
||||
--> tests/ui/cast.rs:499:5
|
||||
--> tests/ui/cast.rs:498:5
|
||||
|
|
||||
LL | (256 & 999999u64) as u8;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^
|
||||
@ -720,7 +720,7 @@ LL | u8::try_from(256 & 999999u64);
|
||||
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
error: casting `u64` to `u8` may truncate the value
|
||||
--> tests/ui/cast.rs:501:5
|
||||
--> tests/ui/cast.rs:500:5
|
||||
|
|
||||
LL | (255 % 999999u64) as u8;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
@ -11,7 +11,7 @@ error: the following explicit lifetimes could be elided: 'a
|
||||
--> tests/ui/issue_4266.rs:10:21
|
||||
|
|
||||
LL | async fn one_to_one<'a>(s: &'a str) -> &'a str {
|
||||
| ^^ ^^
|
||||
| ^^ ^^ ^^
|
||||
|
||||
error: methods called `new` usually take no `self`
|
||||
--> tests/ui/issue_4266.rs:31:22
|
||||
|
@ -1,7 +1,6 @@
|
||||
#![warn(clippy::missing_const_for_fn)]
|
||||
#![allow(incomplete_features, clippy::let_and_return, clippy::missing_transmute_annotations)]
|
||||
#![allow(unsupported_calling_conventions)]
|
||||
#![feature(const_trait_impl)]
|
||||
#![feature(const_trait_impl, abi_vectorcall)]
|
||||
|
||||
use std::mem::transmute;
|
||||
|
||||
@ -104,7 +103,7 @@ fn main() {}
|
||||
|
||||
struct D;
|
||||
|
||||
/* FIXME(effects)
|
||||
/* FIXME(const_trait_impl)
|
||||
impl const Drop for D {
|
||||
fn drop(&mut self) {
|
||||
todo!();
|
||||
@ -113,7 +112,7 @@ impl const Drop for D {
|
||||
*/
|
||||
|
||||
// Lint this, since it can be dropped in const contexts
|
||||
// FIXME(effects)
|
||||
// FIXME(const_trait_impl)
|
||||
const fn d(this: D) {}
|
||||
//~^ ERROR: this could be a `const fn`
|
||||
|
||||
@ -212,8 +211,8 @@ mod extern_fn {
|
||||
//~^ ERROR: this could be a `const fn`
|
||||
const extern "system-unwind" fn system_unwind() {}
|
||||
//~^ ERROR: this could be a `const fn`
|
||||
pub const extern "stdcall" fn std_call() {}
|
||||
pub const extern "vectorcall" fn std_call() {}
|
||||
//~^ ERROR: this could be a `const fn`
|
||||
pub const extern "stdcall-unwind" fn std_call_unwind() {}
|
||||
pub const extern "vectorcall-unwind" fn std_call_unwind() {}
|
||||
//~^ ERROR: this could be a `const fn`
|
||||
}
|
||||
|
@ -1,7 +1,6 @@
|
||||
#![warn(clippy::missing_const_for_fn)]
|
||||
#![allow(incomplete_features, clippy::let_and_return, clippy::missing_transmute_annotations)]
|
||||
#![allow(unsupported_calling_conventions)]
|
||||
#![feature(const_trait_impl)]
|
||||
#![feature(const_trait_impl, abi_vectorcall)]
|
||||
|
||||
use std::mem::transmute;
|
||||
|
||||
@ -104,7 +103,7 @@ fn main() {}
|
||||
|
||||
struct D;
|
||||
|
||||
/* FIXME(effects)
|
||||
/* FIXME(const_trait_impl)
|
||||
impl const Drop for D {
|
||||
fn drop(&mut self) {
|
||||
todo!();
|
||||
@ -113,7 +112,7 @@ fn drop(&mut self) {
|
||||
*/
|
||||
|
||||
// Lint this, since it can be dropped in const contexts
|
||||
// FIXME(effects)
|
||||
// FIXME(const_trait_impl)
|
||||
fn d(this: D) {}
|
||||
//~^ ERROR: this could be a `const fn`
|
||||
|
||||
@ -212,8 +211,8 @@ extern "system" fn system() {}
|
||||
//~^ ERROR: this could be a `const fn`
|
||||
extern "system-unwind" fn system_unwind() {}
|
||||
//~^ ERROR: this could be a `const fn`
|
||||
pub extern "stdcall" fn std_call() {}
|
||||
pub extern "vectorcall" fn std_call() {}
|
||||
//~^ ERROR: this could be a `const fn`
|
||||
pub extern "stdcall-unwind" fn std_call_unwind() {}
|
||||
pub extern "vectorcall-unwind" fn std_call_unwind() {}
|
||||
//~^ ERROR: this could be a `const fn`
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
error: this could be a `const fn`
|
||||
--> tests/ui/missing_const_for_fn/could_be_const.rs:14:5
|
||||
--> tests/ui/missing_const_for_fn/could_be_const.rs:13:5
|
||||
|
|
||||
LL | / pub fn new() -> Self {
|
||||
LL | |
|
||||
@ -16,7 +16,7 @@ LL | pub const fn new() -> Self {
|
||||
| +++++
|
||||
|
||||
error: this could be a `const fn`
|
||||
--> tests/ui/missing_const_for_fn/could_be_const.rs:20:5
|
||||
--> tests/ui/missing_const_for_fn/could_be_const.rs:19:5
|
||||
|
|
||||
LL | / fn const_generic_params<'a, T, const N: usize>(&self, b: &'a [T; N]) -> &'a [T; N] {
|
||||
LL | |
|
||||
@ -30,7 +30,7 @@ LL | const fn const_generic_params<'a, T, const N: usize>(&self, b: &'a [T;
|
||||
| +++++
|
||||
|
||||
error: this could be a `const fn`
|
||||
--> tests/ui/missing_const_for_fn/could_be_const.rs:27:1
|
||||
--> tests/ui/missing_const_for_fn/could_be_const.rs:26:1
|
||||
|
|
||||
LL | / fn one() -> i32 {
|
||||
LL | |
|
||||
@ -44,7 +44,7 @@ LL | const fn one() -> i32 {
|
||||
| +++++
|
||||
|
||||
error: this could be a `const fn`
|
||||
--> tests/ui/missing_const_for_fn/could_be_const.rs:33:1
|
||||
--> tests/ui/missing_const_for_fn/could_be_const.rs:32:1
|
||||
|
|
||||
LL | / fn two() -> i32 {
|
||||
LL | |
|
||||
@ -59,7 +59,7 @@ LL | const fn two() -> i32 {
|
||||
| +++++
|
||||
|
||||
error: this could be a `const fn`
|
||||
--> tests/ui/missing_const_for_fn/could_be_const.rs:40:1
|
||||
--> tests/ui/missing_const_for_fn/could_be_const.rs:39:1
|
||||
|
|
||||
LL | / fn string() -> String {
|
||||
LL | |
|
||||
@ -73,7 +73,7 @@ LL | const fn string() -> String {
|
||||
| +++++
|
||||
|
||||
error: this could be a `const fn`
|
||||
--> tests/ui/missing_const_for_fn/could_be_const.rs:46:1
|
||||
--> tests/ui/missing_const_for_fn/could_be_const.rs:45:1
|
||||
|
|
||||
LL | / unsafe fn four() -> i32 {
|
||||
LL | |
|
||||
@ -87,7 +87,7 @@ LL | const unsafe fn four() -> i32 {
|
||||
| +++++
|
||||
|
||||
error: this could be a `const fn`
|
||||
--> tests/ui/missing_const_for_fn/could_be_const.rs:52:1
|
||||
--> tests/ui/missing_const_for_fn/could_be_const.rs:51:1
|
||||
|
|
||||
LL | / fn generic<T>(t: T) -> T {
|
||||
LL | |
|
||||
@ -101,7 +101,7 @@ LL | const fn generic<T>(t: T) -> T {
|
||||
| +++++
|
||||
|
||||
error: this could be a `const fn`
|
||||
--> tests/ui/missing_const_for_fn/could_be_const.rs:61:1
|
||||
--> tests/ui/missing_const_for_fn/could_be_const.rs:60:1
|
||||
|
|
||||
LL | / fn generic_arr<T: Copy>(t: [T; 1]) -> T {
|
||||
LL | |
|
||||
@ -115,7 +115,7 @@ LL | const fn generic_arr<T: Copy>(t: [T; 1]) -> T {
|
||||
| +++++
|
||||
|
||||
error: this could be a `const fn`
|
||||
--> tests/ui/missing_const_for_fn/could_be_const.rs:75:9
|
||||
--> tests/ui/missing_const_for_fn/could_be_const.rs:74:9
|
||||
|
|
||||
LL | / pub fn b(self, a: &A) -> B {
|
||||
LL | |
|
||||
@ -129,7 +129,7 @@ LL | pub const fn b(self, a: &A) -> B {
|
||||
| +++++
|
||||
|
||||
error: this could be a `const fn`
|
||||
--> tests/ui/missing_const_for_fn/could_be_const.rs:85:5
|
||||
--> tests/ui/missing_const_for_fn/could_be_const.rs:84:5
|
||||
|
|
||||
LL | / fn const_fn_stabilized_before_msrv(byte: u8) {
|
||||
LL | |
|
||||
@ -143,7 +143,7 @@ LL | const fn const_fn_stabilized_before_msrv(byte: u8) {
|
||||
| +++++
|
||||
|
||||
error: this could be a `const fn`
|
||||
--> tests/ui/missing_const_for_fn/could_be_const.rs:97:1
|
||||
--> tests/ui/missing_const_for_fn/could_be_const.rs:96:1
|
||||
|
|
||||
LL | / fn msrv_1_46() -> i32 {
|
||||
LL | |
|
||||
@ -157,7 +157,7 @@ LL | const fn msrv_1_46() -> i32 {
|
||||
| +++++
|
||||
|
||||
error: this could be a `const fn`
|
||||
--> tests/ui/missing_const_for_fn/could_be_const.rs:117:1
|
||||
--> tests/ui/missing_const_for_fn/could_be_const.rs:116:1
|
||||
|
|
||||
LL | fn d(this: D) {}
|
||||
| ^^^^^^^^^^^^^^^^
|
||||
@ -168,7 +168,7 @@ LL | const fn d(this: D) {}
|
||||
| +++++
|
||||
|
||||
error: this could be a `const fn`
|
||||
--> tests/ui/missing_const_for_fn/could_be_const.rs:125:9
|
||||
--> tests/ui/missing_const_for_fn/could_be_const.rs:124:9
|
||||
|
|
||||
LL | / fn deref_ptr_can_be_const(self) -> usize {
|
||||
LL | |
|
||||
@ -182,7 +182,7 @@ LL | const fn deref_ptr_can_be_const(self) -> usize {
|
||||
| +++++
|
||||
|
||||
error: this could be a `const fn`
|
||||
--> tests/ui/missing_const_for_fn/could_be_const.rs:130:9
|
||||
--> tests/ui/missing_const_for_fn/could_be_const.rs:129:9
|
||||
|
|
||||
LL | / fn deref_copied_val(self) -> usize {
|
||||
LL | |
|
||||
@ -196,7 +196,7 @@ LL | const fn deref_copied_val(self) -> usize {
|
||||
| +++++
|
||||
|
||||
error: this could be a `const fn`
|
||||
--> tests/ui/missing_const_for_fn/could_be_const.rs:141:5
|
||||
--> tests/ui/missing_const_for_fn/could_be_const.rs:140:5
|
||||
|
|
||||
LL | / fn union_access_can_be_const() {
|
||||
LL | |
|
||||
@ -211,7 +211,7 @@ LL | const fn union_access_can_be_const() {
|
||||
| +++++
|
||||
|
||||
error: this could be a `const fn`
|
||||
--> tests/ui/missing_const_for_fn/could_be_const.rs:149:9
|
||||
--> tests/ui/missing_const_for_fn/could_be_const.rs:148:9
|
||||
|
|
||||
LL | extern "C" fn c() {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^
|
||||
@ -222,7 +222,7 @@ LL | const extern "C" fn c() {}
|
||||
| +++++
|
||||
|
||||
error: this could be a `const fn`
|
||||
--> tests/ui/missing_const_for_fn/could_be_const.rs:153:9
|
||||
--> tests/ui/missing_const_for_fn/could_be_const.rs:152:9
|
||||
|
|
||||
LL | extern fn implicit_c() {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
@ -233,7 +233,7 @@ LL | const extern fn implicit_c() {}
|
||||
| +++++
|
||||
|
||||
error: this could be a `const fn`
|
||||
--> tests/ui/missing_const_for_fn/could_be_const.rs:170:9
|
||||
--> tests/ui/missing_const_for_fn/could_be_const.rs:169:9
|
||||
|
|
||||
LL | / pub fn new(strings: Vec<String>) -> Self {
|
||||
LL | | Self { strings }
|
||||
@ -246,7 +246,7 @@ LL | pub const fn new(strings: Vec<String>) -> Self {
|
||||
| +++++
|
||||
|
||||
error: this could be a `const fn`
|
||||
--> tests/ui/missing_const_for_fn/could_be_const.rs:175:9
|
||||
--> tests/ui/missing_const_for_fn/could_be_const.rs:174:9
|
||||
|
|
||||
LL | / pub fn empty() -> Self {
|
||||
LL | | Self { strings: Vec::new() }
|
||||
@ -259,7 +259,7 @@ LL | pub const fn empty() -> Self {
|
||||
| +++++
|
||||
|
||||
error: this could be a `const fn`
|
||||
--> tests/ui/missing_const_for_fn/could_be_const.rs:186:9
|
||||
--> tests/ui/missing_const_for_fn/could_be_const.rs:185:9
|
||||
|
|
||||
LL | / pub fn new(text: String) -> Self {
|
||||
LL | | let vec = Vec::new();
|
||||
@ -273,7 +273,7 @@ LL | pub const fn new(text: String) -> Self {
|
||||
| +++++
|
||||
|
||||
error: this could be a `const fn`
|
||||
--> tests/ui/missing_const_for_fn/could_be_const.rs:205:5
|
||||
--> tests/ui/missing_const_for_fn/could_be_const.rs:204:5
|
||||
|
|
||||
LL | fn alias_ty_is_projection(bar: <() as FooTrait>::Foo) {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
@ -284,7 +284,7 @@ LL | const fn alias_ty_is_projection(bar: <() as FooTrait>::Foo) {}
|
||||
| +++++
|
||||
|
||||
error: this could be a `const fn`
|
||||
--> tests/ui/missing_const_for_fn/could_be_const.rs:209:5
|
||||
--> tests/ui/missing_const_for_fn/could_be_const.rs:208:5
|
||||
|
|
||||
LL | extern "C-unwind" fn c_unwind() {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
@ -295,7 +295,7 @@ LL | const extern "C-unwind" fn c_unwind() {}
|
||||
| +++++
|
||||
|
||||
error: this could be a `const fn`
|
||||
--> tests/ui/missing_const_for_fn/could_be_const.rs:211:5
|
||||
--> tests/ui/missing_const_for_fn/could_be_const.rs:210:5
|
||||
|
|
||||
LL | extern "system" fn system() {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
@ -306,7 +306,7 @@ LL | const extern "system" fn system() {}
|
||||
| +++++
|
||||
|
||||
error: this could be a `const fn`
|
||||
--> tests/ui/missing_const_for_fn/could_be_const.rs:213:5
|
||||
--> tests/ui/missing_const_for_fn/could_be_const.rs:212:5
|
||||
|
|
||||
LL | extern "system-unwind" fn system_unwind() {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
@ -317,25 +317,25 @@ LL | const extern "system-unwind" fn system_unwind() {}
|
||||
| +++++
|
||||
|
||||
error: this could be a `const fn`
|
||||
--> tests/ui/missing_const_for_fn/could_be_const.rs:215:5
|
||||
--> tests/ui/missing_const_for_fn/could_be_const.rs:214:5
|
||||
|
|
||||
LL | pub extern "stdcall" fn std_call() {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
LL | pub extern "vectorcall" fn std_call() {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
help: make the function `const`
|
||||
|
|
||||
LL | pub const extern "stdcall" fn std_call() {}
|
||||
LL | pub const extern "vectorcall" fn std_call() {}
|
||||
| +++++
|
||||
|
||||
error: this could be a `const fn`
|
||||
--> tests/ui/missing_const_for_fn/could_be_const.rs:217:5
|
||||
--> tests/ui/missing_const_for_fn/could_be_const.rs:216:5
|
||||
|
|
||||
LL | pub extern "stdcall-unwind" fn std_call_unwind() {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
LL | pub extern "vectorcall-unwind" fn std_call_unwind() {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
help: make the function `const`
|
||||
|
|
||||
LL | pub const extern "stdcall-unwind" fn std_call_unwind() {}
|
||||
LL | pub const extern "vectorcall-unwind" fn std_call_unwind() {}
|
||||
| +++++
|
||||
|
||||
error: aborting due to 26 previous errors
|
||||
|
@ -54,7 +54,7 @@
|
||||
#![allow(enum_intrinsics_non_enums)]
|
||||
#![allow(non_fmt_panics)]
|
||||
#![allow(named_arguments_used_positionally)]
|
||||
#![allow(temporary_cstring_as_ptr)]
|
||||
#![allow(dangling_pointers_from_temporaries)]
|
||||
#![allow(undropped_manually_drops)]
|
||||
#![allow(unknown_lints)]
|
||||
#![allow(unused_labels)]
|
||||
@ -120,7 +120,7 @@
|
||||
#![warn(unexpected_cfgs)] //~ ERROR: lint `clippy::mismatched_target_os`
|
||||
#![warn(non_fmt_panics)] //~ ERROR: lint `clippy::panic_params`
|
||||
#![warn(named_arguments_used_positionally)] //~ ERROR: lint `clippy::positional_named_format_parameters`
|
||||
#![warn(temporary_cstring_as_ptr)] //~ ERROR: lint `clippy::temporary_cstring_as_ptr`
|
||||
#![warn(dangling_pointers_from_temporaries)] //~ ERROR: lint `clippy::temporary_cstring_as_ptr`
|
||||
#![warn(undropped_manually_drops)] //~ ERROR: lint `clippy::undropped_manually_drops`
|
||||
#![warn(unknown_lints)] //~ ERROR: lint `clippy::unknown_clippy_lints`
|
||||
#![warn(unused_labels)] //~ ERROR: lint `clippy::unused_label`
|
||||
|
@ -54,7 +54,7 @@
|
||||
#![allow(enum_intrinsics_non_enums)]
|
||||
#![allow(non_fmt_panics)]
|
||||
#![allow(named_arguments_used_positionally)]
|
||||
#![allow(temporary_cstring_as_ptr)]
|
||||
#![allow(dangling_pointers_from_temporaries)]
|
||||
#![allow(undropped_manually_drops)]
|
||||
#![allow(unknown_lints)]
|
||||
#![allow(unused_labels)]
|
||||
|
@ -361,11 +361,11 @@ error: lint `clippy::positional_named_format_parameters` has been renamed to `na
|
||||
LL | #![warn(clippy::positional_named_format_parameters)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `named_arguments_used_positionally`
|
||||
|
||||
error: lint `clippy::temporary_cstring_as_ptr` has been renamed to `temporary_cstring_as_ptr`
|
||||
error: lint `clippy::temporary_cstring_as_ptr` has been renamed to `dangling_pointers_from_temporaries`
|
||||
--> tests/ui/rename.rs:123:9
|
||||
|
|
||||
LL | #![warn(clippy::temporary_cstring_as_ptr)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `temporary_cstring_as_ptr`
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `dangling_pointers_from_temporaries`
|
||||
|
||||
error: lint `clippy::undropped_manually_drops` has been renamed to `undropped_manually_drops`
|
||||
--> tests/ui/rename.rs:124:9
|
||||
|
Loading…
Reference in New Issue
Block a user