mirror of
https://github.com/rust-lang/rust-clippy
synced 2024-11-27 15:11:30 +00:00
Auto merge of #11563 - flip1995:rustup, r=flip1995
Rustup r? `@ghost` changelog: none
This commit is contained in:
commit
7671c283a5
51 changed files with 450 additions and 498 deletions
|
@ -15,7 +15,6 @@ clippy_utils = { path = "../clippy_utils" }
|
|||
declare_clippy_lint = { path = "../declare_clippy_lint" }
|
||||
if_chain = "1.0"
|
||||
itertools = "0.10.1"
|
||||
pulldown-cmark = { version = "0.9", default-features = false }
|
||||
quine-mc_cluskey = "0.2"
|
||||
regex-syntax = "0.7"
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
|
|
|
@ -2,9 +2,9 @@ use clippy_utils::diagnostics::span_lint_and_then;
|
|||
use clippy_utils::{match_def_path, paths};
|
||||
use rustc_data_structures::fx::FxHashMap;
|
||||
use rustc_hir::def_id::DefId;
|
||||
use rustc_hir::{AsyncGeneratorKind, Body, BodyId, GeneratorKind};
|
||||
use rustc_hir::{AsyncGeneratorKind, Body, GeneratorKind};
|
||||
use rustc_lint::{LateContext, LateLintPass};
|
||||
use rustc_middle::ty::GeneratorInteriorTypeCause;
|
||||
use rustc_middle::mir::GeneratorLayout;
|
||||
use rustc_session::{declare_tool_lint, impl_lint_pass};
|
||||
use rustc_span::{sym, Span};
|
||||
|
||||
|
@ -197,28 +197,35 @@ impl LateLintPass<'_> for AwaitHolding {
|
|||
fn check_body(&mut self, cx: &LateContext<'_>, body: &'_ Body<'_>) {
|
||||
use AsyncGeneratorKind::{Block, Closure, Fn};
|
||||
if let Some(GeneratorKind::Async(Block | Closure | Fn)) = body.generator_kind {
|
||||
let body_id = BodyId {
|
||||
hir_id: body.value.hir_id,
|
||||
};
|
||||
let typeck_results = cx.tcx.typeck_body(body_id);
|
||||
self.check_interior_types(
|
||||
cx,
|
||||
typeck_results.generator_interior_types.as_ref().skip_binder(),
|
||||
body.value.span,
|
||||
);
|
||||
let def_id = cx.tcx.hir().body_owner_def_id(body.id());
|
||||
if let Some(generator_layout) = cx.tcx.mir_generator_witnesses(def_id) {
|
||||
self.check_interior_types(cx, generator_layout);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl AwaitHolding {
|
||||
fn check_interior_types(&self, cx: &LateContext<'_>, ty_causes: &[GeneratorInteriorTypeCause<'_>], span: Span) {
|
||||
for ty_cause in ty_causes {
|
||||
fn check_interior_types(&self, cx: &LateContext<'_>, generator: &GeneratorLayout<'_>) {
|
||||
for (ty_index, ty_cause) in generator.field_tys.iter_enumerated() {
|
||||
if let rustc_middle::ty::Adt(adt, _) = ty_cause.ty.kind() {
|
||||
let await_points = || {
|
||||
generator
|
||||
.variant_source_info
|
||||
.iter_enumerated()
|
||||
.filter_map(|(variant, source_info)| {
|
||||
generator.variant_fields[variant]
|
||||
.raw
|
||||
.contains(&ty_index)
|
||||
.then_some(source_info.span)
|
||||
})
|
||||
.collect::<Vec<_>>()
|
||||
};
|
||||
if is_mutex_guard(cx, adt.did()) {
|
||||
span_lint_and_then(
|
||||
cx,
|
||||
AWAIT_HOLDING_LOCK,
|
||||
ty_cause.span,
|
||||
ty_cause.source_info.span,
|
||||
"this `MutexGuard` is held across an `await` point",
|
||||
|diag| {
|
||||
diag.help(
|
||||
|
@ -226,7 +233,7 @@ impl AwaitHolding {
|
|||
`MutexGuard` is dropped before calling await",
|
||||
);
|
||||
diag.span_note(
|
||||
ty_cause.scope_span.unwrap_or(span),
|
||||
await_points(),
|
||||
"these are all the `await` points this lock is held through",
|
||||
);
|
||||
},
|
||||
|
@ -235,18 +242,18 @@ impl AwaitHolding {
|
|||
span_lint_and_then(
|
||||
cx,
|
||||
AWAIT_HOLDING_REFCELL_REF,
|
||||
ty_cause.span,
|
||||
ty_cause.source_info.span,
|
||||
"this `RefCell` reference is held across an `await` point",
|
||||
|diag| {
|
||||
diag.help("ensure the reference is dropped before calling `await`");
|
||||
diag.span_note(
|
||||
ty_cause.scope_span.unwrap_or(span),
|
||||
await_points(),
|
||||
"these are all the `await` points this reference is held through",
|
||||
);
|
||||
},
|
||||
);
|
||||
} else if let Some(disallowed) = self.def_ids.get(&adt.did()) {
|
||||
emit_invalid_type(cx, ty_cause.span, disallowed);
|
||||
emit_invalid_type(cx, ty_cause.source_info.span, disallowed);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -844,7 +844,6 @@ impl TyCoercionStability {
|
|||
| ty::FnDef(..)
|
||||
| ty::Generator(..)
|
||||
| ty::GeneratorWitness(..)
|
||||
| ty::GeneratorWitnessMIR(..)
|
||||
| ty::Closure(..)
|
||||
| ty::Never
|
||||
| ty::Tuple(_)
|
||||
|
|
|
@ -343,7 +343,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().next().is_some() {
|
||||
if ty_subs.non_erasable_generics(cx.tcx, ty_adt.did()).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, _)
|
||||
|
|
|
@ -1,18 +1,16 @@
|
|||
use clippy_utils::attrs::is_doc_hidden;
|
||||
use clippy_utils::diagnostics::{span_lint, span_lint_and_help, span_lint_and_note, span_lint_and_then};
|
||||
use clippy_utils::macros::{is_panic, root_macro_call_first_node};
|
||||
use clippy_utils::source::{first_line_of_span, snippet_with_applicability};
|
||||
use clippy_utils::source::snippet_with_applicability;
|
||||
use clippy_utils::ty::{implements_trait, is_type_diagnostic_item};
|
||||
use clippy_utils::{is_entrypoint_fn, method_chain_args, return_ty};
|
||||
use if_chain::if_chain;
|
||||
use itertools::Itertools;
|
||||
use pulldown_cmark::Event::{
|
||||
Code, End, FootnoteReference, HardBreak, Html, Rule, SoftBreak, Start, TaskListMarker, Text,
|
||||
};
|
||||
use pulldown_cmark::Tag::{CodeBlock, Heading, Item, Link, Paragraph};
|
||||
use pulldown_cmark::{BrokenLink, CodeBlockKind, CowStr, Options};
|
||||
use rustc_ast::ast::{Async, AttrKind, Attribute, Fn, FnRetTy, ItemKind};
|
||||
use rustc_ast::token::CommentKind;
|
||||
use rustc_ast::ast::{Async, Attribute, Fn, FnRetTy, ItemKind};
|
||||
use rustc_data_structures::fx::FxHashSet;
|
||||
use rustc_data_structures::sync::Lrc;
|
||||
use rustc_errors::emitter::EmitterWriter;
|
||||
|
@ -26,6 +24,9 @@ use rustc_middle::lint::in_external_macro;
|
|||
use rustc_middle::ty;
|
||||
use rustc_parse::maybe_new_parser_from_source_str;
|
||||
use rustc_parse::parser::ForceCollect;
|
||||
use rustc_resolve::rustdoc::{
|
||||
add_doc_fragment, attrs_to_doc_fragments, main_body_opts, source_span_for_markdown_range, DocFragment,
|
||||
};
|
||||
use rustc_session::parse::ParseSess;
|
||||
use rustc_session::{declare_tool_lint, impl_lint_pass};
|
||||
use rustc_span::edition::Edition;
|
||||
|
@ -450,53 +451,16 @@ fn lint_for_missing_headers(
|
|||
}
|
||||
}
|
||||
|
||||
/// Cleanup documentation decoration.
|
||||
///
|
||||
/// We can't use `rustc_ast::attr::AttributeMethods::with_desugared_doc` or
|
||||
/// `rustc_ast::parse::lexer::comments::strip_doc_comment_decoration` because we
|
||||
/// need to keep track of
|
||||
/// the spans but this function is inspired from the later.
|
||||
#[expect(clippy::cast_possible_truncation)]
|
||||
#[must_use]
|
||||
pub fn strip_doc_comment_decoration(doc: &str, comment_kind: CommentKind, span: Span) -> (String, Vec<(usize, Span)>) {
|
||||
// one-line comments lose their prefix
|
||||
if comment_kind == CommentKind::Line {
|
||||
let mut doc = doc.to_owned();
|
||||
doc.push('\n');
|
||||
let len = doc.len();
|
||||
// +3 skips the opening delimiter
|
||||
return (doc, vec![(len, span.with_lo(span.lo() + BytePos(3)))]);
|
||||
}
|
||||
#[derive(Copy, Clone)]
|
||||
struct Fragments<'a> {
|
||||
doc: &'a str,
|
||||
fragments: &'a [DocFragment],
|
||||
}
|
||||
|
||||
let mut sizes = vec![];
|
||||
let mut contains_initial_stars = false;
|
||||
for line in doc.lines() {
|
||||
let offset = line.as_ptr() as usize - doc.as_ptr() as usize;
|
||||
debug_assert_eq!(offset as u32 as usize, offset);
|
||||
contains_initial_stars |= line.trim_start().starts_with('*');
|
||||
// +1 adds the newline, +3 skips the opening delimiter
|
||||
sizes.push((line.len() + 1, span.with_lo(span.lo() + BytePos(3 + offset as u32))));
|
||||
impl Fragments<'_> {
|
||||
fn span(self, cx: &LateContext<'_>, range: Range<usize>) -> Option<Span> {
|
||||
source_span_for_markdown_range(cx.tcx, self.doc, &range, self.fragments)
|
||||
}
|
||||
if !contains_initial_stars {
|
||||
return (doc.to_string(), sizes);
|
||||
}
|
||||
// remove the initial '*'s if any
|
||||
let mut no_stars = String::with_capacity(doc.len());
|
||||
for line in doc.lines() {
|
||||
let mut chars = line.chars();
|
||||
for c in &mut chars {
|
||||
if c.is_whitespace() {
|
||||
no_stars.push(c);
|
||||
} else {
|
||||
no_stars.push(if c == '*' { ' ' } else { c });
|
||||
break;
|
||||
}
|
||||
}
|
||||
no_stars.push_str(chars.as_str());
|
||||
no_stars.push('\n');
|
||||
}
|
||||
|
||||
(no_stars, sizes)
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Default)]
|
||||
|
@ -515,27 +479,16 @@ fn check_attrs(cx: &LateContext<'_>, valid_idents: &FxHashSet<String>, attrs: &[
|
|||
Some(("fake".into(), "fake".into()))
|
||||
}
|
||||
|
||||
if is_doc_hidden(attrs) {
|
||||
return None;
|
||||
}
|
||||
|
||||
let (fragments, _) = attrs_to_doc_fragments(attrs.iter().map(|attr| (attr, None)), true);
|
||||
let mut doc = String::new();
|
||||
let mut spans = vec![];
|
||||
|
||||
for attr in attrs {
|
||||
if let AttrKind::DocComment(comment_kind, comment) = attr.kind {
|
||||
let (comment, current_spans) = strip_doc_comment_decoration(comment.as_str(), comment_kind, attr.span);
|
||||
spans.extend_from_slice(¤t_spans);
|
||||
doc.push_str(&comment);
|
||||
} else if attr.has_name(sym::doc) {
|
||||
// ignore mix of sugared and non-sugared doc
|
||||
// don't trigger the safety or errors check
|
||||
return None;
|
||||
}
|
||||
}
|
||||
|
||||
let mut current = 0;
|
||||
for &mut (ref mut offset, _) in &mut spans {
|
||||
let offset_copy = *offset;
|
||||
*offset = current;
|
||||
current += offset_copy;
|
||||
for fragment in &fragments {
|
||||
add_doc_fragment(&mut doc, fragment);
|
||||
}
|
||||
doc.pop();
|
||||
|
||||
if doc.is_empty() {
|
||||
return Some(DocHeaders::default());
|
||||
|
@ -543,32 +496,29 @@ fn check_attrs(cx: &LateContext<'_>, valid_idents: &FxHashSet<String>, attrs: &[
|
|||
|
||||
let mut cb = fake_broken_link_callback;
|
||||
|
||||
let parser =
|
||||
pulldown_cmark::Parser::new_with_broken_link_callback(&doc, Options::empty(), Some(&mut cb)).into_offset_iter();
|
||||
// Iterate over all `Events` and combine consecutive events into one
|
||||
let events = parser.coalesce(|previous, current| {
|
||||
let previous_range = previous.1;
|
||||
let current_range = current.1;
|
||||
// disable smart punctuation to pick up ['link'] more easily
|
||||
let opts = main_body_opts() - Options::ENABLE_SMART_PUNCTUATION;
|
||||
let parser = pulldown_cmark::Parser::new_with_broken_link_callback(&doc, opts, Some(&mut cb));
|
||||
|
||||
match (previous.0, current.0) {
|
||||
(Text(previous), Text(current)) => {
|
||||
let mut previous = previous.to_string();
|
||||
previous.push_str(¤t);
|
||||
Ok((Text(previous.into()), previous_range))
|
||||
},
|
||||
(previous, current) => Err(((previous, previous_range), (current, current_range))),
|
||||
}
|
||||
});
|
||||
Some(check_doc(cx, valid_idents, events, &spans))
|
||||
Some(check_doc(
|
||||
cx,
|
||||
valid_idents,
|
||||
parser.into_offset_iter(),
|
||||
Fragments {
|
||||
fragments: &fragments,
|
||||
doc: &doc,
|
||||
},
|
||||
))
|
||||
}
|
||||
|
||||
const RUST_CODE: &[&str] = &["rust", "no_run", "should_panic", "compile_fail"];
|
||||
|
||||
#[allow(clippy::too_many_lines)] // Only a big match statement
|
||||
fn check_doc<'a, Events: Iterator<Item = (pulldown_cmark::Event<'a>, Range<usize>)>>(
|
||||
cx: &LateContext<'_>,
|
||||
valid_idents: &FxHashSet<String>,
|
||||
events: Events,
|
||||
spans: &[(usize, Span)],
|
||||
fragments: Fragments<'_>,
|
||||
) -> DocHeaders {
|
||||
// true if a safety header was found
|
||||
let mut headers = DocHeaders::default();
|
||||
|
@ -579,8 +529,8 @@ fn check_doc<'a, Events: Iterator<Item = (pulldown_cmark::Event<'a>, Range<usize
|
|||
let mut no_test = false;
|
||||
let mut edition = None;
|
||||
let mut ticks_unbalanced = false;
|
||||
let mut text_to_check: Vec<(CowStr<'_>, Span)> = Vec::new();
|
||||
let mut paragraph_span = spans.get(0).expect("function isn't called if doc comment is empty").1;
|
||||
let mut text_to_check: Vec<(CowStr<'_>, Range<usize>)> = Vec::new();
|
||||
let mut paragraph_range = 0..0;
|
||||
for (event, range) in events {
|
||||
match event {
|
||||
Start(CodeBlock(ref kind)) => {
|
||||
|
@ -613,25 +563,28 @@ fn check_doc<'a, Events: Iterator<Item = (pulldown_cmark::Event<'a>, Range<usize
|
|||
in_heading = true;
|
||||
}
|
||||
ticks_unbalanced = false;
|
||||
let (_, span) = get_current_span(spans, range.start);
|
||||
paragraph_span = first_line_of_span(cx, span);
|
||||
paragraph_range = range;
|
||||
},
|
||||
End(Heading(_, _, _) | Paragraph | Item) => {
|
||||
if let End(Heading(_, _, _)) = event {
|
||||
in_heading = false;
|
||||
}
|
||||
if ticks_unbalanced {
|
||||
if ticks_unbalanced
|
||||
&& let Some(span) = fragments.span(cx, paragraph_range.clone())
|
||||
{
|
||||
span_lint_and_help(
|
||||
cx,
|
||||
DOC_MARKDOWN,
|
||||
paragraph_span,
|
||||
span,
|
||||
"backticks are unbalanced",
|
||||
None,
|
||||
"a backtick may be missing a pair",
|
||||
);
|
||||
} else {
|
||||
for (text, span) in text_to_check {
|
||||
check_text(cx, valid_idents, &text, span);
|
||||
for (text, range) in text_to_check {
|
||||
if let Some(span) = fragments.span(cx, range) {
|
||||
check_text(cx, valid_idents, &text, span);
|
||||
}
|
||||
}
|
||||
}
|
||||
text_to_check = Vec::new();
|
||||
|
@ -640,8 +593,7 @@ fn check_doc<'a, Events: Iterator<Item = (pulldown_cmark::Event<'a>, Range<usize
|
|||
Html(_html) => (), // HTML is weird, just ignore it
|
||||
SoftBreak | HardBreak | TaskListMarker(_) | Code(_) | Rule => (),
|
||||
FootnoteReference(text) | Text(text) => {
|
||||
let (begin, span) = get_current_span(spans, range.start);
|
||||
paragraph_span = paragraph_span.with_hi(span.hi());
|
||||
paragraph_range.end = range.end;
|
||||
ticks_unbalanced |= text.contains('`') && !in_code;
|
||||
if Some(&text) == in_link.as_ref() || ticks_unbalanced {
|
||||
// Probably a link of the form `<http://example.com>`
|
||||
|
@ -658,19 +610,19 @@ fn check_doc<'a, Events: Iterator<Item = (pulldown_cmark::Event<'a>, Range<usize
|
|||
if in_code {
|
||||
if is_rust && !no_test {
|
||||
let edition = edition.unwrap_or_else(|| cx.tcx.sess.edition());
|
||||
check_code(cx, &text, edition, span);
|
||||
check_code(cx, &text, edition, range.clone(), fragments);
|
||||
}
|
||||
} else {
|
||||
check_link_quotes(cx, in_link.is_some(), trimmed_text, span, &range, begin, text.len());
|
||||
// Adjust for the beginning of the current `Event`
|
||||
let span = span.with_lo(span.lo() + BytePos::from_usize(range.start - begin));
|
||||
if in_link.is_some() {
|
||||
check_link_quotes(cx, trimmed_text, range.clone(), fragments);
|
||||
}
|
||||
if let Some(link) = in_link.as_ref()
|
||||
&& let Ok(url) = Url::parse(link)
|
||||
&& (url.scheme() == "https" || url.scheme() == "http") {
|
||||
// Don't check the text associated with external URLs
|
||||
continue;
|
||||
}
|
||||
text_to_check.push((text, span));
|
||||
text_to_check.push((text, range));
|
||||
}
|
||||
},
|
||||
}
|
||||
|
@ -678,36 +630,21 @@ fn check_doc<'a, Events: Iterator<Item = (pulldown_cmark::Event<'a>, Range<usize
|
|||
headers
|
||||
}
|
||||
|
||||
fn check_link_quotes(
|
||||
cx: &LateContext<'_>,
|
||||
in_link: bool,
|
||||
trimmed_text: &str,
|
||||
span: Span,
|
||||
range: &Range<usize>,
|
||||
begin: usize,
|
||||
text_len: usize,
|
||||
) {
|
||||
if in_link && trimmed_text.starts_with('\'') && trimmed_text.ends_with('\'') {
|
||||
// fix the span to only point at the text within the link
|
||||
let lo = span.lo() + BytePos::from_usize(range.start - begin);
|
||||
fn check_link_quotes(cx: &LateContext<'_>, trimmed_text: &str, range: Range<usize>, fragments: Fragments<'_>) {
|
||||
if trimmed_text.starts_with('\'')
|
||||
&& trimmed_text.ends_with('\'')
|
||||
&& let Some(span) = fragments.span(cx, range)
|
||||
{
|
||||
span_lint(
|
||||
cx,
|
||||
DOC_LINK_WITH_QUOTES,
|
||||
span.with_lo(lo).with_hi(lo + BytePos::from_usize(text_len)),
|
||||
span,
|
||||
"possible intra-doc link using quotes instead of backticks",
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
fn get_current_span(spans: &[(usize, Span)], idx: usize) -> (usize, Span) {
|
||||
let index = match spans.binary_search_by(|c| c.0.cmp(&idx)) {
|
||||
Ok(o) => o,
|
||||
Err(e) => e - 1,
|
||||
};
|
||||
spans[index]
|
||||
}
|
||||
|
||||
fn check_code(cx: &LateContext<'_>, text: &str, edition: Edition, span: Span) {
|
||||
fn check_code(cx: &LateContext<'_>, text: &str, edition: Edition, range: Range<usize>, fragments: Fragments<'_>) {
|
||||
fn has_needless_main(code: String, edition: Edition) -> bool {
|
||||
rustc_driver::catch_fatal_errors(|| {
|
||||
rustc_span::create_session_globals_then(edition, || {
|
||||
|
@ -774,12 +711,13 @@ fn check_code(cx: &LateContext<'_>, text: &str, edition: Edition, span: Span) {
|
|||
.unwrap_or_default()
|
||||
}
|
||||
|
||||
let trailing_whitespace = text.len() - text.trim_end().len();
|
||||
|
||||
// Because of the global session, we need to create a new session in a different thread with
|
||||
// the edition we need.
|
||||
let text = text.to_owned();
|
||||
if thread::spawn(move || has_needless_main(text, edition))
|
||||
.join()
|
||||
.expect("thread::spawn failed")
|
||||
if thread::spawn(move || has_needless_main(text, edition)).join().expect("thread::spawn failed")
|
||||
&& let Some(span) = fragments.span(cx, range.start..range.end - trailing_whitespace)
|
||||
{
|
||||
span_lint(cx, NEEDLESS_DOCTEST_MAIN, span, "needless `fn main` in doctest");
|
||||
}
|
||||
|
|
|
@ -50,7 +50,7 @@ impl<'tcx> LateLintPass<'tcx> for UnportableVariant {
|
|||
.tcx
|
||||
.const_eval_poly(def_id.to_def_id())
|
||||
.ok()
|
||||
.map(|val| rustc_middle::mir::ConstantKind::from_value(val, ty));
|
||||
.map(|val| rustc_middle::mir::Const::from_value(val, ty));
|
||||
if let Some(Constant::Int(val)) = constant.and_then(|c| miri_to_const(cx, c)) {
|
||||
if let ty::Adt(adt, _) = ty.kind() {
|
||||
if adt.is_enum() {
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
|
||||
// FIXME: switch to something more ergonomic here, once available.
|
||||
// (Currently there is no way to opt into sysroot crates without `extern crate`.)
|
||||
extern crate pulldown_cmark;
|
||||
extern crate rustc_arena;
|
||||
extern crate rustc_ast;
|
||||
extern crate rustc_ast_pretty;
|
||||
|
@ -37,6 +38,7 @@ extern crate rustc_lexer;
|
|||
extern crate rustc_lint;
|
||||
extern crate rustc_middle;
|
||||
extern crate rustc_parse;
|
||||
extern crate rustc_resolve;
|
||||
extern crate rustc_session;
|
||||
extern crate rustc_span;
|
||||
extern crate rustc_target;
|
||||
|
|
|
@ -37,22 +37,14 @@ fn all_ranges<'tcx>(cx: &LateContext<'tcx>, arms: &'tcx [Arm<'_>], ty: Ty<'tcx>)
|
|||
Some(lhs) => constant(cx, cx.typeck_results(), lhs)?,
|
||||
None => {
|
||||
let min_val_const = ty.numeric_min_val(cx.tcx)?;
|
||||
let min_constant = mir::ConstantKind::from_value(
|
||||
cx.tcx.valtree_to_const_val((ty, min_val_const.to_valtree())),
|
||||
ty,
|
||||
);
|
||||
miri_to_const(cx, min_constant)?
|
||||
miri_to_const(cx, mir::Const::from_ty_const(min_val_const, cx.tcx))?
|
||||
},
|
||||
};
|
||||
let rhs_const = match rhs {
|
||||
Some(rhs) => constant(cx, cx.typeck_results(), rhs)?,
|
||||
None => {
|
||||
let max_val_const = ty.numeric_max_val(cx.tcx)?;
|
||||
let max_constant = mir::ConstantKind::from_value(
|
||||
cx.tcx.valtree_to_const_val((ty, max_val_const.to_valtree())),
|
||||
ty,
|
||||
);
|
||||
miri_to_const(cx, max_constant)?
|
||||
miri_to_const(cx, mir::Const::from_ty_const(max_val_const, cx.tcx))?
|
||||
},
|
||||
};
|
||||
let lhs_val = lhs_const.int_value(cx, ty)?;
|
||||
|
|
|
@ -203,7 +203,7 @@ fn is_value_unfrozen_raw<'tcx>(
|
|||
// similar to 2., but with the a frozen variant) (e.g. borrowing
|
||||
// `borrow_interior_mutable_const::enums::AssocConsts::TO_BE_FROZEN_VARIANT`).
|
||||
// I chose this way because unfrozen enums as assoc consts are rare (or, hopefully, none).
|
||||
err == ErrorHandled::TooGeneric
|
||||
matches!(err, ErrorHandled::TooGeneric(..))
|
||||
},
|
||||
|val| val.map_or(true, |val| inner(cx, val, ty)),
|
||||
)
|
||||
|
@ -243,8 +243,8 @@ pub fn const_eval_resolve<'tcx>(
|
|||
};
|
||||
tcx.const_eval_global_id_for_typeck(param_env, cid, span)
|
||||
},
|
||||
Ok(None) => Err(ErrorHandled::TooGeneric),
|
||||
Err(err) => Err(ErrorHandled::Reported(err.into())),
|
||||
Ok(None) => Err(ErrorHandled::TooGeneric(span.unwrap_or(rustc_span::DUMMY_SP))),
|
||||
Err(err) => Err(ErrorHandled::Reported(err.into(), span.unwrap_or(rustc_span::DUMMY_SP))),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -315,7 +315,7 @@ impl<'tcx> LateLintPass<'tcx> for ArithmeticSideEffects {
|
|||
let body_owner_def_id = cx.tcx.hir().body_owner_def_id(body.id());
|
||||
|
||||
let body_owner_kind = cx.tcx.hir().body_owner_kind(body_owner_def_id);
|
||||
if let hir::BodyOwnerKind::Const | hir::BodyOwnerKind::Static(_) = body_owner_kind {
|
||||
if let hir::BodyOwnerKind::Const { .. } | hir::BodyOwnerKind::Static(_) = body_owner_kind {
|
||||
let body_span = cx.tcx.hir().span_with_body(body_owner);
|
||||
if let Some(span) = self.const_span && span.contains(body_span) {
|
||||
return;
|
||||
|
|
|
@ -72,7 +72,7 @@ impl Context {
|
|||
let body_owner_def_id = cx.tcx.hir().body_owner_def_id(body.id());
|
||||
|
||||
match cx.tcx.hir().body_owner_kind(body_owner_def_id) {
|
||||
hir::BodyOwnerKind::Static(_) | hir::BodyOwnerKind::Const => {
|
||||
hir::BodyOwnerKind::Static(_) | hir::BodyOwnerKind::Const { .. } => {
|
||||
let body_span = cx.tcx.hir().span_with_body(body_owner);
|
||||
|
||||
if let Some(span) = self.const_span {
|
||||
|
|
|
@ -89,11 +89,20 @@ impl EarlyLintPass for RawStrings {
|
|||
let r_pos = expr.span.lo() + BytePos::from_usize(prefix.len() - 1);
|
||||
let start = start.with_lo(r_pos);
|
||||
|
||||
diag.multipart_suggestion(
|
||||
"try",
|
||||
vec![(start, String::new()), (end, String::new())],
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
if end.is_empty() {
|
||||
diag.span_suggestion(
|
||||
start,
|
||||
"use a string literal instead",
|
||||
format!("\"{str}\""),
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
} else {
|
||||
diag.multipart_suggestion(
|
||||
"try",
|
||||
vec![(start, String::new()), (end, String::new())],
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
}
|
||||
},
|
||||
);
|
||||
if !matches!(cx.get_lint_level(NEEDLESS_RAW_STRINGS), rustc_lint::Allow) {
|
||||
|
|
|
@ -10,6 +10,7 @@ use rustc_hir::intravisit::{Visitor as HirVisitor, Visitor};
|
|||
use rustc_lint::{LateContext, LateLintPass};
|
||||
use rustc_middle::hir::nested_filter;
|
||||
use rustc_middle::lint::in_external_macro;
|
||||
use rustc_middle::ty;
|
||||
use rustc_session::{declare_lint_pass, declare_tool_lint};
|
||||
|
||||
declare_clippy_lint! {
|
||||
|
@ -84,7 +85,7 @@ fn find_innermost_closure<'tcx>(
|
|||
cx: &LateContext<'tcx>,
|
||||
mut expr: &'tcx hir::Expr<'tcx>,
|
||||
mut steps: usize,
|
||||
) -> Option<(&'tcx hir::Expr<'tcx>, &'tcx hir::FnDecl<'tcx>, hir::IsAsync)> {
|
||||
) -> Option<(&'tcx hir::Expr<'tcx>, &'tcx hir::FnDecl<'tcx>, ty::Asyncness)> {
|
||||
let mut data = None;
|
||||
|
||||
while let hir::ExprKind::Closure(closure) = expr.kind
|
||||
|
@ -98,9 +99,9 @@ fn find_innermost_closure<'tcx>(
|
|||
{
|
||||
expr = body.value;
|
||||
data = Some((body.value, closure.fn_decl, if is_async_closure(body) {
|
||||
hir::IsAsync::Async
|
||||
ty::Asyncness::Yes
|
||||
} else {
|
||||
hir::IsAsync::NotAsync
|
||||
ty::Asyncness::No
|
||||
}));
|
||||
steps -= 1;
|
||||
}
|
||||
|
|
|
@ -586,7 +586,7 @@ fn ident_difference_expr_with_base_location(
|
|||
| (ForLoop(_, _, _, _), ForLoop(_, _, _, _))
|
||||
| (While(_, _, _), While(_, _, _))
|
||||
| (If(_, _, _), If(_, _, _))
|
||||
| (Let(_, _, _), Let(_, _, _))
|
||||
| (Let(_, _, _, _), Let(_, _, _, _))
|
||||
| (Type(_, _), Type(_, _))
|
||||
| (Cast(_, _), Cast(_, _))
|
||||
| (Lit(_), Lit(_))
|
||||
|
|
|
@ -483,20 +483,18 @@ fn item_has_safety_comment(cx: &LateContext<'_>, item: &hir::Item<'_>) -> HasSaf
|
|||
&& Lrc::ptr_eq(&unsafe_line.sf, &comment_start_line.sf)
|
||||
&& let Some(src) = unsafe_line.sf.src.as_deref()
|
||||
{
|
||||
return unsafe_line.sf.lines(|lines| {
|
||||
if comment_start_line.line >= unsafe_line.line {
|
||||
HasSafetyComment::No
|
||||
} else {
|
||||
match text_has_safety_comment(
|
||||
src,
|
||||
&lines[comment_start_line.line + 1..=unsafe_line.line],
|
||||
unsafe_line.sf.start_pos,
|
||||
) {
|
||||
Some(b) => HasSafetyComment::Yes(b),
|
||||
None => HasSafetyComment::No,
|
||||
}
|
||||
return if comment_start_line.line >= unsafe_line.line {
|
||||
HasSafetyComment::No
|
||||
} else {
|
||||
match text_has_safety_comment(
|
||||
src,
|
||||
&unsafe_line.sf.lines()[comment_start_line.line + 1..=unsafe_line.line],
|
||||
unsafe_line.sf.start_pos,
|
||||
) {
|
||||
Some(b) => HasSafetyComment::Yes(b),
|
||||
None => HasSafetyComment::No,
|
||||
}
|
||||
});
|
||||
};
|
||||
}
|
||||
}
|
||||
HasSafetyComment::Maybe
|
||||
|
@ -527,20 +525,18 @@ fn stmt_has_safety_comment(cx: &LateContext<'_>, span: Span, hir_id: HirId) -> H
|
|||
&& Lrc::ptr_eq(&unsafe_line.sf, &comment_start_line.sf)
|
||||
&& let Some(src) = unsafe_line.sf.src.as_deref()
|
||||
{
|
||||
return unsafe_line.sf.lines(|lines| {
|
||||
if comment_start_line.line >= unsafe_line.line {
|
||||
HasSafetyComment::No
|
||||
} else {
|
||||
match text_has_safety_comment(
|
||||
src,
|
||||
&lines[comment_start_line.line + 1..=unsafe_line.line],
|
||||
unsafe_line.sf.start_pos,
|
||||
) {
|
||||
Some(b) => HasSafetyComment::Yes(b),
|
||||
None => HasSafetyComment::No,
|
||||
}
|
||||
return if comment_start_line.line >= unsafe_line.line {
|
||||
HasSafetyComment::No
|
||||
} else {
|
||||
match text_has_safety_comment(
|
||||
src,
|
||||
&unsafe_line.sf.lines()[comment_start_line.line + 1..=unsafe_line.line],
|
||||
unsafe_line.sf.start_pos,
|
||||
) {
|
||||
Some(b) => HasSafetyComment::Yes(b),
|
||||
None => HasSafetyComment::No,
|
||||
}
|
||||
});
|
||||
};
|
||||
}
|
||||
}
|
||||
HasSafetyComment::Maybe
|
||||
|
@ -590,20 +586,18 @@ fn span_from_macro_expansion_has_safety_comment(cx: &LateContext<'_>, span: Span
|
|||
&& Lrc::ptr_eq(&unsafe_line.sf, ¯o_line.sf)
|
||||
&& let Some(src) = unsafe_line.sf.src.as_deref()
|
||||
{
|
||||
unsafe_line.sf.lines(|lines| {
|
||||
if macro_line.line < unsafe_line.line {
|
||||
match text_has_safety_comment(
|
||||
src,
|
||||
&lines[macro_line.line + 1..=unsafe_line.line],
|
||||
unsafe_line.sf.start_pos,
|
||||
) {
|
||||
Some(b) => HasSafetyComment::Yes(b),
|
||||
None => HasSafetyComment::No,
|
||||
}
|
||||
} else {
|
||||
HasSafetyComment::No
|
||||
if macro_line.line < unsafe_line.line {
|
||||
match text_has_safety_comment(
|
||||
src,
|
||||
&unsafe_line.sf.lines()[macro_line.line + 1..=unsafe_line.line],
|
||||
unsafe_line.sf.start_pos,
|
||||
) {
|
||||
Some(b) => HasSafetyComment::Yes(b),
|
||||
None => HasSafetyComment::No,
|
||||
}
|
||||
})
|
||||
} else {
|
||||
HasSafetyComment::No
|
||||
}
|
||||
} else {
|
||||
// Problem getting source text. Pretend a comment was found.
|
||||
HasSafetyComment::Maybe
|
||||
|
@ -654,13 +648,11 @@ fn span_has_safety_comment(cx: &LateContext<'_>, span: Span) -> bool {
|
|||
// Get the text from the start of function body to the unsafe block.
|
||||
// fn foo() { some_stuff; unsafe { stuff }; other_stuff; }
|
||||
// ^-------------^
|
||||
unsafe_line.sf.lines(|lines| {
|
||||
body_line.line < unsafe_line.line && text_has_safety_comment(
|
||||
src,
|
||||
&lines[body_line.line + 1..=unsafe_line.line],
|
||||
unsafe_line.sf.start_pos,
|
||||
).is_some()
|
||||
})
|
||||
body_line.line < unsafe_line.line && text_has_safety_comment(
|
||||
src,
|
||||
&unsafe_line.sf.lines()[body_line.line + 1..=unsafe_line.line],
|
||||
unsafe_line.sf.start_pos,
|
||||
).is_some()
|
||||
} else {
|
||||
// Problem getting source text. Pretend a comment was found.
|
||||
true
|
||||
|
|
|
@ -68,7 +68,7 @@ impl EarlyLintPass for UnnestedOrPatterns {
|
|||
|
||||
fn check_expr(&mut self, cx: &EarlyContext<'_>, e: &ast::Expr) {
|
||||
if self.msrv.meets(msrvs::OR_PATTERNS) {
|
||||
if let ast::ExprKind::Let(pat, _, _) = &e.kind {
|
||||
if let ast::ExprKind::Let(pat, _, _, _) = &e.kind {
|
||||
lint_unnested_or_patterns(cx, pat);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,7 +10,7 @@ use rustc_hir::def::{DefKind, Res};
|
|||
use rustc_hir::def_id::DefId;
|
||||
use rustc_hir::{BinOpKind, Expr, ExprKind, UnOp};
|
||||
use rustc_lint::{LateContext, LateLintPass};
|
||||
use rustc_middle::mir::interpret::ConstValue;
|
||||
use rustc_middle::mir::ConstValue;
|
||||
use rustc_middle::ty;
|
||||
use rustc_session::{declare_tool_lint, impl_lint_pass};
|
||||
use rustc_span::symbol::Symbol;
|
||||
|
|
|
@ -10,7 +10,8 @@ use rustc_hir::def::{DefKind, Res};
|
|||
use rustc_hir::def_id::DefId;
|
||||
use rustc_hir::{Expr, ExprKind, Local, Mutability, Node};
|
||||
use rustc_lint::{LateContext, LateLintPass};
|
||||
use rustc_middle::mir::interpret::{Allocation, ConstValue, GlobalAlloc};
|
||||
use rustc_middle::mir::interpret::{Allocation, GlobalAlloc};
|
||||
use rustc_middle::mir::ConstValue;
|
||||
use rustc_middle::ty::{self, Ty};
|
||||
use rustc_session::{declare_tool_lint, impl_lint_pass};
|
||||
use rustc_span::symbol::Symbol;
|
||||
|
@ -232,7 +233,8 @@ fn path_to_matched_type(cx: &LateContext<'_>, expr: &hir::Expr<'_>) -> Option<Ve
|
|||
cx.tcx.type_of(def_id).instantiate_identity(),
|
||||
),
|
||||
Res::Def(DefKind::Const, def_id) => match cx.tcx.const_eval_poly(def_id).ok()? {
|
||||
ConstValue::ByRef { alloc, offset } if offset.bytes() == 0 => {
|
||||
ConstValue::Indirect { alloc_id, offset } if offset.bytes() == 0 => {
|
||||
let alloc = cx.tcx.global_alloc(alloc_id).unwrap_memory();
|
||||
read_mir_alloc_def_path(cx, alloc.inner(), cx.tcx.type_of(def_id).instantiate_identity())
|
||||
},
|
||||
_ => None,
|
||||
|
|
|
@ -166,7 +166,7 @@ pub fn eq_expr(l: &Expr, r: &Expr) -> bool {
|
|||
(Unary(lo, l), Unary(ro, r)) => mem::discriminant(lo) == mem::discriminant(ro) && eq_expr(l, r),
|
||||
(Lit(l), Lit(r)) => l == r,
|
||||
(Cast(l, lt), Cast(r, rt)) | (Type(l, lt), Type(r, rt)) => eq_expr(l, r) && eq_ty(lt, rt),
|
||||
(Let(lp, le, _), Let(rp, re, _)) => eq_pat(lp, rp) && eq_expr(le, re),
|
||||
(Let(lp, le, _, _), Let(rp, re, _, _)) => eq_pat(lp, rp) && eq_expr(le, re),
|
||||
(If(lc, lt, le), If(rc, rt, re)) => eq_expr(lc, rc) && eq_block(lt, rt) && eq_expr_opt(le, re),
|
||||
(While(lc, lt, ll), While(rc, rt, rl)) => eq_label(ll, rl) && eq_expr(lc, rc) && eq_block(lt, rt),
|
||||
(ForLoop(lp, li, lt, ll), ForLoop(rp, ri, rt, rl)) => {
|
||||
|
|
|
@ -21,7 +21,7 @@ use std::iter;
|
|||
/// A `LitKind`-like enum to fold constant `Expr`s into.
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum Constant<'tcx> {
|
||||
Adt(rustc_middle::mir::ConstantKind<'tcx>),
|
||||
Adt(rustc_middle::mir::Const<'tcx>),
|
||||
/// A `String` (e.g., "abc").
|
||||
Str(String),
|
||||
/// A binary string (e.g., `b"abc"`).
|
||||
|
@ -482,7 +482,7 @@ impl<'a, 'tcx> ConstEvalLateContext<'a, 'tcx> {
|
|||
.tcx
|
||||
.const_eval_resolve(self.param_env, mir::UnevaluatedConst::new(def_id, args), None)
|
||||
.ok()
|
||||
.map(|val| rustc_middle::mir::ConstantKind::from_value(val, ty))?;
|
||||
.map(|val| rustc_middle::mir::Const::from_value(val, ty))?;
|
||||
let result = miri_to_const(self.lcx, result)?;
|
||||
self.source = ConstantSource::Constant;
|
||||
Some(result)
|
||||
|
@ -655,10 +655,10 @@ impl<'a, 'tcx> ConstEvalLateContext<'a, 'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn miri_to_const<'tcx>(lcx: &LateContext<'tcx>, result: mir::ConstantKind<'tcx>) -> Option<Constant<'tcx>> {
|
||||
use rustc_middle::mir::interpret::ConstValue;
|
||||
pub fn miri_to_const<'tcx>(lcx: &LateContext<'tcx>, result: mir::Const<'tcx>) -> Option<Constant<'tcx>> {
|
||||
use rustc_middle::mir::ConstValue;
|
||||
match result {
|
||||
mir::ConstantKind::Val(ConstValue::Scalar(Scalar::Int(int)), _) => match result.ty().kind() {
|
||||
mir::Const::Val(ConstValue::Scalar(Scalar::Int(int)), _) => match result.ty().kind() {
|
||||
ty::Adt(adt_def, _) if adt_def.is_struct() => Some(Constant::Adt(result)),
|
||||
ty::Bool => Some(Constant::Bool(int == ScalarInt::TRUE)),
|
||||
ty::Uint(_) | ty::Int(_) => Some(Constant::Int(int.assert_bits(int.size()))),
|
||||
|
@ -671,47 +671,42 @@ pub fn miri_to_const<'tcx>(lcx: &LateContext<'tcx>, result: mir::ConstantKind<'t
|
|||
ty::RawPtr(_) => Some(Constant::RawPtr(int.assert_bits(int.size()))),
|
||||
_ => None,
|
||||
},
|
||||
mir::ConstantKind::Val(ConstValue::Slice { data, start, end }, _) => match result.ty().kind() {
|
||||
ty::Ref(_, tam, _) => match tam.kind() {
|
||||
ty::Str => String::from_utf8(
|
||||
data.inner()
|
||||
.inspect_with_uninit_and_ptr_outside_interpreter(start..end)
|
||||
.to_owned(),
|
||||
)
|
||||
.ok()
|
||||
.map(Constant::Str),
|
||||
_ => None,
|
||||
},
|
||||
_ => None,
|
||||
mir::Const::Val(cv, _) if matches!(result.ty().kind(), ty::Ref(_, inner_ty, _) if matches!(inner_ty.kind(), ty::Str)) =>
|
||||
{
|
||||
let data = cv.try_get_slice_bytes_for_diagnostics(lcx.tcx)?;
|
||||
String::from_utf8(data.to_owned()).ok().map(Constant::Str)
|
||||
},
|
||||
mir::ConstantKind::Val(ConstValue::ByRef { alloc, offset: _ }, _) => match result.ty().kind() {
|
||||
ty::Adt(adt_def, _) if adt_def.is_struct() => Some(Constant::Adt(result)),
|
||||
ty::Array(sub_type, len) => match sub_type.kind() {
|
||||
ty::Float(FloatTy::F32) => match len.try_to_target_usize(lcx.tcx) {
|
||||
Some(len) => alloc
|
||||
.inner()
|
||||
.inspect_with_uninit_and_ptr_outside_interpreter(0..(4 * usize::try_from(len).unwrap()))
|
||||
.to_owned()
|
||||
.array_chunks::<4>()
|
||||
.map(|&chunk| Some(Constant::F32(f32::from_le_bytes(chunk))))
|
||||
.collect::<Option<Vec<Constant<'tcx>>>>()
|
||||
.map(Constant::Vec),
|
||||
_ => None,
|
||||
},
|
||||
ty::Float(FloatTy::F64) => match len.try_to_target_usize(lcx.tcx) {
|
||||
Some(len) => alloc
|
||||
.inner()
|
||||
.inspect_with_uninit_and_ptr_outside_interpreter(0..(8 * usize::try_from(len).unwrap()))
|
||||
.to_owned()
|
||||
.array_chunks::<8>()
|
||||
.map(|&chunk| Some(Constant::F64(f64::from_le_bytes(chunk))))
|
||||
.collect::<Option<Vec<Constant<'tcx>>>>()
|
||||
.map(Constant::Vec),
|
||||
mir::Const::Val(ConstValue::Indirect { alloc_id, offset: _ }, _) => {
|
||||
let alloc = lcx.tcx.global_alloc(alloc_id).unwrap_memory();
|
||||
match result.ty().kind() {
|
||||
ty::Adt(adt_def, _) if adt_def.is_struct() => Some(Constant::Adt(result)),
|
||||
ty::Array(sub_type, len) => match sub_type.kind() {
|
||||
ty::Float(FloatTy::F32) => match len.try_to_target_usize(lcx.tcx) {
|
||||
Some(len) => alloc
|
||||
.inner()
|
||||
.inspect_with_uninit_and_ptr_outside_interpreter(0..(4 * usize::try_from(len).unwrap()))
|
||||
.to_owned()
|
||||
.array_chunks::<4>()
|
||||
.map(|&chunk| Some(Constant::F32(f32::from_le_bytes(chunk))))
|
||||
.collect::<Option<Vec<Constant<'tcx>>>>()
|
||||
.map(Constant::Vec),
|
||||
_ => None,
|
||||
},
|
||||
ty::Float(FloatTy::F64) => match len.try_to_target_usize(lcx.tcx) {
|
||||
Some(len) => alloc
|
||||
.inner()
|
||||
.inspect_with_uninit_and_ptr_outside_interpreter(0..(8 * usize::try_from(len).unwrap()))
|
||||
.to_owned()
|
||||
.array_chunks::<8>()
|
||||
.map(|&chunk| Some(Constant::F64(f64::from_le_bytes(chunk))))
|
||||
.collect::<Option<Vec<Constant<'tcx>>>>()
|
||||
.map(Constant::Vec),
|
||||
_ => None,
|
||||
},
|
||||
_ => None,
|
||||
},
|
||||
_ => None,
|
||||
},
|
||||
_ => None,
|
||||
}
|
||||
},
|
||||
_ => None,
|
||||
}
|
||||
|
@ -720,17 +715,17 @@ pub fn miri_to_const<'tcx>(lcx: &LateContext<'tcx>, result: mir::ConstantKind<'t
|
|||
fn field_of_struct<'tcx>(
|
||||
adt_def: ty::AdtDef<'tcx>,
|
||||
lcx: &LateContext<'tcx>,
|
||||
result: mir::ConstantKind<'tcx>,
|
||||
result: mir::Const<'tcx>,
|
||||
field: &Ident,
|
||||
) -> Option<mir::ConstantKind<'tcx>> {
|
||||
if let mir::ConstantKind::Val(result, ty) = result
|
||||
&& let Some(dc) = lcx.tcx.try_destructure_mir_constant_for_diagnostics((result, ty))
|
||||
) -> Option<mir::Const<'tcx>> {
|
||||
if let mir::Const::Val(result, ty) = result
|
||||
&& let Some(dc) = lcx.tcx.try_destructure_mir_constant_for_diagnostics(result, ty)
|
||||
&& let Some(dc_variant) = dc.variant
|
||||
&& let Some(variant) = adt_def.variants().get(dc_variant)
|
||||
&& let Some(field_idx) = variant.fields.iter().position(|el| el.name == field.name)
|
||||
&& let Some(&(val, ty)) = dc.fields.get(field_idx)
|
||||
{
|
||||
Some(mir::ConstantKind::Val(val, ty))
|
||||
Some(mir::Const::Val(val, ty))
|
||||
}
|
||||
else {
|
||||
None
|
||||
|
|
|
@ -90,14 +90,14 @@ use rustc_hir::intravisit::{walk_expr, FnKind, Visitor};
|
|||
use rustc_hir::LangItem::{OptionNone, OptionSome, ResultErr, ResultOk};
|
||||
use rustc_hir::{
|
||||
self as hir, def, Arm, ArrayLen, BindingAnnotation, Block, BlockCheckMode, Body, Closure, Destination, Expr,
|
||||
ExprField, ExprKind, FnDecl, FnRetTy, GenericArgs, HirId, Impl, ImplItem, ImplItemKind, ImplItemRef, IsAsync, Item,
|
||||
ExprField, ExprKind, FnDecl, FnRetTy, GenericArgs, HirId, Impl, ImplItem, ImplItemKind, ImplItemRef, Item,
|
||||
ItemKind, LangItem, Local, MatchSource, Mutability, Node, OwnerId, Param, Pat, PatKind, Path, PathSegment, PrimTy,
|
||||
QPath, Stmt, StmtKind, TraitItem, TraitItemKind, TraitItemRef, TraitRef, TyKind, UnOp,
|
||||
};
|
||||
use rustc_lexer::{tokenize, TokenKind};
|
||||
use rustc_lint::{LateContext, Level, Lint, LintContext};
|
||||
use rustc_middle::hir::place::PlaceBase;
|
||||
use rustc_middle::mir::ConstantKind;
|
||||
use rustc_middle::mir::Const;
|
||||
use rustc_middle::ty::adjustment::{Adjust, Adjustment, AutoBorrow};
|
||||
use rustc_middle::ty::binding::BindingMode;
|
||||
use rustc_middle::ty::fast_reject::SimplifiedType;
|
||||
|
@ -1510,7 +1510,7 @@ pub fn is_range_full(cx: &LateContext<'_>, expr: &Expr<'_>, container_path: Opti
|
|||
&& let bnd_ty = subst.type_at(0)
|
||||
&& let Some(min_val) = bnd_ty.numeric_min_val(cx.tcx)
|
||||
&& let const_val = cx.tcx.valtree_to_const_val((bnd_ty, min_val.to_valtree()))
|
||||
&& let min_const_kind = ConstantKind::from_value(const_val, bnd_ty)
|
||||
&& let min_const_kind = Const::from_value(const_val, bnd_ty)
|
||||
&& let Some(min_const) = miri_to_const(cx, min_const_kind)
|
||||
&& let Some(start_const) = constant(cx, cx.typeck_results(), start)
|
||||
{
|
||||
|
@ -1526,7 +1526,7 @@ pub fn is_range_full(cx: &LateContext<'_>, expr: &Expr<'_>, container_path: Opti
|
|||
&& let bnd_ty = subst.type_at(0)
|
||||
&& let Some(max_val) = bnd_ty.numeric_max_val(cx.tcx)
|
||||
&& let const_val = cx.tcx.valtree_to_const_val((bnd_ty, max_val.to_valtree()))
|
||||
&& let max_const_kind = ConstantKind::from_value(const_val, bnd_ty)
|
||||
&& let max_const_kind = Const::from_value(const_val, bnd_ty)
|
||||
&& let Some(max_const) = miri_to_const(cx, max_const_kind)
|
||||
&& let Some(end_const) = constant(cx, cx.typeck_results(), end)
|
||||
{
|
||||
|
@ -1985,8 +1985,8 @@ pub fn if_sequence<'tcx>(mut expr: &'tcx Expr<'tcx>) -> (Vec<&'tcx Expr<'tcx>>,
|
|||
/// Checks if the given function kind is an async function.
|
||||
pub fn is_async_fn(kind: FnKind<'_>) -> bool {
|
||||
match kind {
|
||||
FnKind::ItemFn(_, _, header) => header.asyncness == IsAsync::Async,
|
||||
FnKind::Method(_, sig) => sig.header.asyncness == IsAsync::Async,
|
||||
FnKind::ItemFn(_, _, header) => header.asyncness.is_async(),
|
||||
FnKind::Method(_, sig) => sig.header.asyncness.is_async(),
|
||||
FnKind::Closure => false,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -118,7 +118,7 @@ fn first_char_in_first_line<T: LintContext>(cx: &T, span: Span) -> Option<BytePo
|
|||
fn line_span<T: LintContext>(cx: &T, span: Span) -> Span {
|
||||
let span = original_sp(span, DUMMY_SP);
|
||||
let SourceFileAndLine { sf, line } = cx.sess().source_map().lookup_line(span.lo()).unwrap();
|
||||
let line_start = sf.lines(|lines| lines[line]);
|
||||
let line_start = sf.lines()[line];
|
||||
let line_start = sf.absolute_position(line_start);
|
||||
span.with_lo(line_start)
|
||||
}
|
||||
|
|
|
@ -13,7 +13,8 @@ use rustc_hir::{Expr, FnDecl, LangItem, TyKind, Unsafety};
|
|||
use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
|
||||
use rustc_infer::infer::TyCtxtInferExt;
|
||||
use rustc_lint::LateContext;
|
||||
use rustc_middle::mir::interpret::{ConstValue, Scalar};
|
||||
use rustc_middle::mir::interpret::Scalar;
|
||||
use rustc_middle::mir::ConstValue;
|
||||
use rustc_middle::traits::EvaluationResult;
|
||||
use rustc_middle::ty::layout::ValidityRequirement;
|
||||
use rustc_middle::ty::{
|
||||
|
|
|
@ -207,8 +207,8 @@ fn path_segment_certainty(
|
|||
// Checking `res_generics_def_id(..)` before calling `generics_of` avoids an ICE.
|
||||
if cx.tcx.res_generics_def_id(path_segment.res).is_some() {
|
||||
let generics = cx.tcx.generics_of(def_id);
|
||||
let lhs = if (parent_certainty.is_certain() || generics.parent_count == 0) && generics.params.is_empty()
|
||||
{
|
||||
let count = generics.params.len() - usize::from(generics.host_effect_index.is_some());
|
||||
let lhs = if (parent_certainty.is_certain() || generics.parent_count == 0) && count == 0 {
|
||||
Certainty::Certain(None)
|
||||
} else {
|
||||
Certainty::Uncertain
|
||||
|
@ -299,10 +299,11 @@ fn type_is_inferrable_from_arguments(cx: &LateContext<'_>, expr: &Expr<'_>) -> b
|
|||
|
||||
// Check that all type parameters appear in the functions input types.
|
||||
(0..(generics.parent_count + generics.params.len()) as u32).all(|index| {
|
||||
fn_sig
|
||||
.inputs()
|
||||
.iter()
|
||||
.any(|input_ty| contains_param(*input_ty.skip_binder(), index))
|
||||
Some(index as usize) == generics.host_effect_index
|
||||
|| fn_sig
|
||||
.inputs()
|
||||
.iter()
|
||||
.any(|input_ty| contains_param(*input_ty.skip_binder(), index))
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
[toolchain]
|
||||
channel = "nightly-2023-09-07"
|
||||
channel = "nightly-2023-09-25"
|
||||
components = ["cargo", "llvm-tools", "rust-src", "rust-std", "rustc", "rustc-dev", "rustfmt"]
|
||||
|
|
|
@ -7,8 +7,10 @@ async fn bad() -> u32 {
|
|||
}
|
||||
|
||||
async fn bad_reason() -> u32 {
|
||||
let _x = Ipv4Addr::new(127, 0, 0, 1);
|
||||
baz().await
|
||||
let x = Ipv4Addr::new(127, 0, 0, 1);
|
||||
let y = baz().await;
|
||||
let _x = x;
|
||||
y
|
||||
}
|
||||
|
||||
async fn good() -> u32 {
|
||||
|
|
|
@ -11,11 +11,11 @@ LL | let _x = String::from("hello");
|
|||
error: `std::net::Ipv4Addr` may not be held across an `await` point per `clippy.toml`
|
||||
--> $DIR/await_holding_invalid_type.rs:10:9
|
||||
|
|
||||
LL | let _x = Ipv4Addr::new(127, 0, 0, 1);
|
||||
| ^^
|
||||
LL | let x = Ipv4Addr::new(127, 0, 0, 1);
|
||||
| ^
|
||||
|
||||
error: `std::string::String` may not be held across an `await` point per `clippy.toml`
|
||||
--> $DIR/await_holding_invalid_type.rs:31:13
|
||||
--> $DIR/await_holding_invalid_type.rs:33:13
|
||||
|
|
||||
LL | let _x = String::from("hi!");
|
||||
| ^^
|
||||
|
|
|
@ -69,6 +69,14 @@ error: use of a disallowed macro `macros::binop`
|
|||
LL | let _ = macros::binop!(1);
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: use of a disallowed macro `macros::attr`
|
||||
--> $DIR/disallowed_macros.rs:28:1
|
||||
|
|
||||
LL | / macros::attr! {
|
||||
LL | | struct S;
|
||||
LL | | }
|
||||
| |_^
|
||||
|
||||
error: use of a disallowed macro `macros::item`
|
||||
--> $DIR/disallowed_macros.rs:33:5
|
||||
|
|
||||
|
@ -87,13 +95,5 @@ error: use of a disallowed macro `macros::item`
|
|||
LL | macros::item!();
|
||||
| ^^^^^^^^^^^^^^^
|
||||
|
||||
error: use of a disallowed macro `macros::attr`
|
||||
--> $DIR/disallowed_macros.rs:28:1
|
||||
|
|
||||
LL | / macros::attr! {
|
||||
LL | | struct S;
|
||||
LL | | }
|
||||
| |_^
|
||||
|
||||
error: aborting due to 15 previous errors
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@ error[E0080]: evaluation of `main::{constant#3}` failed
|
|||
LL | const { &ARR[idx4()] }; // Ok, should not produce stderr, since `suppress-restriction-lint-in-const` is set true.
|
||||
| ^^^^^^^^^^^ index out of bounds: the length is 2 but the index is 4
|
||||
|
||||
note: erroneous constant used
|
||||
note: erroneous constant encountered
|
||||
--> $DIR/test.rs:37:5
|
||||
|
|
||||
LL | const { &ARR[idx4()] }; // Ok, should not produce stderr, since `suppress-restriction-lint-in-const` is set true.
|
||||
|
|
|
@ -22,6 +22,13 @@ struct T4;
|
|||
#[cfg_attr(panic = "unwind", expect(dead_code))]
|
||||
struct CfgT;
|
||||
|
||||
#[allow(clippy::allow_attributes, unused)]
|
||||
struct Allowed;
|
||||
|
||||
#[expect(clippy::allow_attributes)]
|
||||
#[allow(unused)]
|
||||
struct Expected;
|
||||
|
||||
fn ignore_external() {
|
||||
external! {
|
||||
#[allow(clippy::needless_borrow)] // Should not lint
|
||||
|
|
|
@ -22,6 +22,13 @@ struct T4;
|
|||
#[cfg_attr(panic = "unwind", allow(dead_code))]
|
||||
struct CfgT;
|
||||
|
||||
#[allow(clippy::allow_attributes, unused)]
|
||||
struct Allowed;
|
||||
|
||||
#[expect(clippy::allow_attributes)]
|
||||
#[allow(unused)]
|
||||
struct Expected;
|
||||
|
||||
fn ignore_external() {
|
||||
external! {
|
||||
#[allow(clippy::needless_borrow)] // Should not lint
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
arithmetic_overflow,
|
||||
unconditional_panic
|
||||
)]
|
||||
#![feature(const_mut_refs, inline_const, saturating_int_impl)]
|
||||
#![feature(const_mut_refs, inline_const)]
|
||||
#![warn(clippy::arithmetic_side_effects)]
|
||||
|
||||
extern crate proc_macro_derive;
|
||||
|
|
|
@ -6,13 +6,10 @@ LL | let guard = x.lock().unwrap();
|
|||
|
|
||||
= help: consider using an async-aware `Mutex` type or ensuring the `MutexGuard` is dropped before calling await
|
||||
note: these are all the `await` points this lock is held through
|
||||
--> $DIR/await_holding_lock.rs:9:9
|
||||
--> $DIR/await_holding_lock.rs:11:15
|
||||
|
|
||||
LL | / let guard = x.lock().unwrap();
|
||||
LL | |
|
||||
LL | | baz().await
|
||||
LL | | }
|
||||
| |_____^
|
||||
LL | baz().await
|
||||
| ^^^^^
|
||||
= note: `-D clippy::await-holding-lock` implied by `-D warnings`
|
||||
= help: to override `-D warnings` add `#[allow(clippy::await_holding_lock)]`
|
||||
|
||||
|
@ -24,13 +21,10 @@ LL | let guard = x.read().unwrap();
|
|||
|
|
||||
= help: consider using an async-aware `Mutex` type or ensuring the `MutexGuard` is dropped before calling await
|
||||
note: these are all the `await` points this lock is held through
|
||||
--> $DIR/await_holding_lock.rs:25:9
|
||||
--> $DIR/await_holding_lock.rs:27:15
|
||||
|
|
||||
LL | / let guard = x.read().unwrap();
|
||||
LL | |
|
||||
LL | | baz().await
|
||||
LL | | }
|
||||
| |_____^
|
||||
LL | baz().await
|
||||
| ^^^^^
|
||||
|
||||
error: this `MutexGuard` is held across an `await` point
|
||||
--> $DIR/await_holding_lock.rs:31:13
|
||||
|
@ -40,13 +34,10 @@ LL | let mut guard = x.write().unwrap();
|
|||
|
|
||||
= help: consider using an async-aware `Mutex` type or ensuring the `MutexGuard` is dropped before calling await
|
||||
note: these are all the `await` points this lock is held through
|
||||
--> $DIR/await_holding_lock.rs:31:9
|
||||
--> $DIR/await_holding_lock.rs:33:15
|
||||
|
|
||||
LL | / let mut guard = x.write().unwrap();
|
||||
LL | |
|
||||
LL | | baz().await
|
||||
LL | | }
|
||||
| |_____^
|
||||
LL | baz().await
|
||||
| ^^^^^
|
||||
|
||||
error: this `MutexGuard` is held across an `await` point
|
||||
--> $DIR/await_holding_lock.rs:53:13
|
||||
|
@ -56,16 +47,13 @@ LL | let guard = x.lock().unwrap();
|
|||
|
|
||||
= help: consider using an async-aware `Mutex` type or ensuring the `MutexGuard` is dropped before calling await
|
||||
note: these are all the `await` points this lock is held through
|
||||
--> $DIR/await_holding_lock.rs:53:9
|
||||
--> $DIR/await_holding_lock.rs:56:28
|
||||
|
|
||||
LL | / let guard = x.lock().unwrap();
|
||||
LL | |
|
||||
LL | |
|
||||
LL | | let second = baz().await;
|
||||
... |
|
||||
LL | | first + second + third
|
||||
LL | | }
|
||||
| |_____^
|
||||
LL | let second = baz().await;
|
||||
| ^^^^^
|
||||
LL |
|
||||
LL | let third = baz().await;
|
||||
| ^^^^^
|
||||
|
||||
error: this `MutexGuard` is held across an `await` point
|
||||
--> $DIR/await_holding_lock.rs:67:17
|
||||
|
@ -75,13 +63,10 @@ LL | let guard = x.lock().unwrap();
|
|||
|
|
||||
= help: consider using an async-aware `Mutex` type or ensuring the `MutexGuard` is dropped before calling await
|
||||
note: these are all the `await` points this lock is held through
|
||||
--> $DIR/await_holding_lock.rs:67:13
|
||||
--> $DIR/await_holding_lock.rs:69:19
|
||||
|
|
||||
LL | / let guard = x.lock().unwrap();
|
||||
LL | |
|
||||
LL | | baz().await
|
||||
LL | | };
|
||||
| |_________^
|
||||
LL | baz().await
|
||||
| ^^^^^
|
||||
|
||||
error: this `MutexGuard` is held across an `await` point
|
||||
--> $DIR/await_holding_lock.rs:80:17
|
||||
|
@ -91,13 +76,10 @@ LL | let guard = x.lock().unwrap();
|
|||
|
|
||||
= help: consider using an async-aware `Mutex` type or ensuring the `MutexGuard` is dropped before calling await
|
||||
note: these are all the `await` points this lock is held through
|
||||
--> $DIR/await_holding_lock.rs:80:13
|
||||
--> $DIR/await_holding_lock.rs:82:19
|
||||
|
|
||||
LL | / let guard = x.lock().unwrap();
|
||||
LL | |
|
||||
LL | | baz().await
|
||||
LL | | }
|
||||
| |_________^
|
||||
LL | baz().await
|
||||
| ^^^^^
|
||||
|
||||
error: this `MutexGuard` is held across an `await` point
|
||||
--> $DIR/await_holding_lock.rs:93:13
|
||||
|
@ -107,13 +89,10 @@ LL | let guard = x.lock();
|
|||
|
|
||||
= help: consider using an async-aware `Mutex` type or ensuring the `MutexGuard` is dropped before calling await
|
||||
note: these are all the `await` points this lock is held through
|
||||
--> $DIR/await_holding_lock.rs:93:9
|
||||
--> $DIR/await_holding_lock.rs:95:15
|
||||
|
|
||||
LL | / let guard = x.lock();
|
||||
LL | |
|
||||
LL | | baz().await
|
||||
LL | | }
|
||||
| |_____^
|
||||
LL | baz().await
|
||||
| ^^^^^
|
||||
|
||||
error: this `MutexGuard` is held across an `await` point
|
||||
--> $DIR/await_holding_lock.rs:109:13
|
||||
|
@ -123,13 +102,10 @@ LL | let guard = x.read();
|
|||
|
|
||||
= help: consider using an async-aware `Mutex` type or ensuring the `MutexGuard` is dropped before calling await
|
||||
note: these are all the `await` points this lock is held through
|
||||
--> $DIR/await_holding_lock.rs:109:9
|
||||
--> $DIR/await_holding_lock.rs:111:15
|
||||
|
|
||||
LL | / let guard = x.read();
|
||||
LL | |
|
||||
LL | | baz().await
|
||||
LL | | }
|
||||
| |_____^
|
||||
LL | baz().await
|
||||
| ^^^^^
|
||||
|
||||
error: this `MutexGuard` is held across an `await` point
|
||||
--> $DIR/await_holding_lock.rs:115:13
|
||||
|
@ -139,13 +115,10 @@ LL | let mut guard = x.write();
|
|||
|
|
||||
= help: consider using an async-aware `Mutex` type or ensuring the `MutexGuard` is dropped before calling await
|
||||
note: these are all the `await` points this lock is held through
|
||||
--> $DIR/await_holding_lock.rs:115:9
|
||||
--> $DIR/await_holding_lock.rs:117:15
|
||||
|
|
||||
LL | / let mut guard = x.write();
|
||||
LL | |
|
||||
LL | | baz().await
|
||||
LL | | }
|
||||
| |_____^
|
||||
LL | baz().await
|
||||
| ^^^^^
|
||||
|
||||
error: this `MutexGuard` is held across an `await` point
|
||||
--> $DIR/await_holding_lock.rs:137:13
|
||||
|
@ -155,16 +128,13 @@ LL | let guard = x.lock();
|
|||
|
|
||||
= help: consider using an async-aware `Mutex` type or ensuring the `MutexGuard` is dropped before calling await
|
||||
note: these are all the `await` points this lock is held through
|
||||
--> $DIR/await_holding_lock.rs:137:9
|
||||
--> $DIR/await_holding_lock.rs:140:28
|
||||
|
|
||||
LL | / let guard = x.lock();
|
||||
LL | |
|
||||
LL | |
|
||||
LL | | let second = baz().await;
|
||||
... |
|
||||
LL | | first + second + third
|
||||
LL | | }
|
||||
| |_____^
|
||||
LL | let second = baz().await;
|
||||
| ^^^^^
|
||||
LL |
|
||||
LL | let third = baz().await;
|
||||
| ^^^^^
|
||||
|
||||
error: this `MutexGuard` is held across an `await` point
|
||||
--> $DIR/await_holding_lock.rs:151:17
|
||||
|
@ -174,13 +144,10 @@ LL | let guard = x.lock();
|
|||
|
|
||||
= help: consider using an async-aware `Mutex` type or ensuring the `MutexGuard` is dropped before calling await
|
||||
note: these are all the `await` points this lock is held through
|
||||
--> $DIR/await_holding_lock.rs:151:13
|
||||
--> $DIR/await_holding_lock.rs:153:19
|
||||
|
|
||||
LL | / let guard = x.lock();
|
||||
LL | |
|
||||
LL | | baz().await
|
||||
LL | | };
|
||||
| |_________^
|
||||
LL | baz().await
|
||||
| ^^^^^
|
||||
|
||||
error: this `MutexGuard` is held across an `await` point
|
||||
--> $DIR/await_holding_lock.rs:164:17
|
||||
|
@ -190,13 +157,10 @@ LL | let guard = x.lock();
|
|||
|
|
||||
= help: consider using an async-aware `Mutex` type or ensuring the `MutexGuard` is dropped before calling await
|
||||
note: these are all the `await` points this lock is held through
|
||||
--> $DIR/await_holding_lock.rs:164:13
|
||||
--> $DIR/await_holding_lock.rs:166:19
|
||||
|
|
||||
LL | / let guard = x.lock();
|
||||
LL | |
|
||||
LL | | baz().await
|
||||
LL | | }
|
||||
| |_________^
|
||||
LL | baz().await
|
||||
| ^^^^^
|
||||
|
||||
error: this `MutexGuard` is held across an `await` point
|
||||
--> $DIR/await_holding_lock.rs:185:9
|
||||
|
@ -206,15 +170,10 @@ LL | let mut guard = x.lock().unwrap();
|
|||
|
|
||||
= help: consider using an async-aware `Mutex` type or ensuring the `MutexGuard` is dropped before calling await
|
||||
note: these are all the `await` points this lock is held through
|
||||
--> $DIR/await_holding_lock.rs:185:5
|
||||
--> $DIR/await_holding_lock.rs:189:11
|
||||
|
|
||||
LL | / let mut guard = x.lock().unwrap();
|
||||
LL | |
|
||||
LL | | *guard += 1;
|
||||
LL | | drop(guard);
|
||||
LL | | baz().await;
|
||||
LL | | }
|
||||
| |_^
|
||||
LL | baz().await;
|
||||
| ^^^^^
|
||||
|
||||
error: aborting due to 13 previous errors
|
||||
|
||||
|
|
|
@ -6,13 +6,10 @@ LL | let b = x.borrow();
|
|||
|
|
||||
= help: ensure the reference is dropped before calling `await`
|
||||
note: these are all the `await` points this reference is held through
|
||||
--> $DIR/await_holding_refcell_ref.rs:6:5
|
||||
--> $DIR/await_holding_refcell_ref.rs:8:11
|
||||
|
|
||||
LL | / let b = x.borrow();
|
||||
LL | |
|
||||
LL | | baz().await
|
||||
LL | | }
|
||||
| |_^
|
||||
LL | baz().await
|
||||
| ^^^^^
|
||||
= note: `-D clippy::await-holding-refcell-ref` implied by `-D warnings`
|
||||
= help: to override `-D warnings` add `#[allow(clippy::await_holding_refcell_ref)]`
|
||||
|
||||
|
@ -24,13 +21,10 @@ LL | let b = x.borrow_mut();
|
|||
|
|
||||
= help: ensure the reference is dropped before calling `await`
|
||||
note: these are all the `await` points this reference is held through
|
||||
--> $DIR/await_holding_refcell_ref.rs:12:5
|
||||
--> $DIR/await_holding_refcell_ref.rs:14:11
|
||||
|
|
||||
LL | / let b = x.borrow_mut();
|
||||
LL | |
|
||||
LL | | baz().await
|
||||
LL | | }
|
||||
| |_^
|
||||
LL | baz().await
|
||||
| ^^^^^
|
||||
|
||||
error: this `RefCell` reference is held across an `await` point
|
||||
--> $DIR/await_holding_refcell_ref.rs:34:9
|
||||
|
@ -40,16 +34,13 @@ LL | let b = x.borrow_mut();
|
|||
|
|
||||
= help: ensure the reference is dropped before calling `await`
|
||||
note: these are all the `await` points this reference is held through
|
||||
--> $DIR/await_holding_refcell_ref.rs:34:5
|
||||
--> $DIR/await_holding_refcell_ref.rs:37:24
|
||||
|
|
||||
LL | / let b = x.borrow_mut();
|
||||
LL | |
|
||||
LL | |
|
||||
LL | | let second = baz().await;
|
||||
... |
|
||||
LL | | first + second + third
|
||||
LL | | }
|
||||
| |_^
|
||||
LL | let second = baz().await;
|
||||
| ^^^^^
|
||||
LL |
|
||||
LL | let third = baz().await;
|
||||
| ^^^^^
|
||||
|
||||
error: this `RefCell` reference is held across an `await` point
|
||||
--> $DIR/await_holding_refcell_ref.rs:47:9
|
||||
|
@ -59,16 +50,10 @@ LL | let b = x.borrow_mut();
|
|||
|
|
||||
= help: ensure the reference is dropped before calling `await`
|
||||
note: these are all the `await` points this reference is held through
|
||||
--> $DIR/await_holding_refcell_ref.rs:47:5
|
||||
--> $DIR/await_holding_refcell_ref.rs:50:24
|
||||
|
|
||||
LL | / let b = x.borrow_mut();
|
||||
LL | |
|
||||
LL | |
|
||||
LL | | let second = baz().await;
|
||||
... |
|
||||
LL | | first + second + third
|
||||
LL | | }
|
||||
| |_^
|
||||
LL | let second = baz().await;
|
||||
| ^^^^^
|
||||
|
||||
error: this `RefCell` reference is held across an `await` point
|
||||
--> $DIR/await_holding_refcell_ref.rs:63:13
|
||||
|
@ -78,13 +63,10 @@ LL | let b = x.borrow_mut();
|
|||
|
|
||||
= help: ensure the reference is dropped before calling `await`
|
||||
note: these are all the `await` points this reference is held through
|
||||
--> $DIR/await_holding_refcell_ref.rs:63:9
|
||||
--> $DIR/await_holding_refcell_ref.rs:65:15
|
||||
|
|
||||
LL | / let b = x.borrow_mut();
|
||||
LL | |
|
||||
LL | | baz().await
|
||||
LL | | };
|
||||
| |_____^
|
||||
LL | baz().await
|
||||
| ^^^^^
|
||||
|
||||
error: this `RefCell` reference is held across an `await` point
|
||||
--> $DIR/await_holding_refcell_ref.rs:76:13
|
||||
|
@ -94,13 +76,10 @@ LL | let b = x.borrow_mut();
|
|||
|
|
||||
= help: ensure the reference is dropped before calling `await`
|
||||
note: these are all the `await` points this reference is held through
|
||||
--> $DIR/await_holding_refcell_ref.rs:76:9
|
||||
--> $DIR/await_holding_refcell_ref.rs:78:15
|
||||
|
|
||||
LL | / let b = x.borrow_mut();
|
||||
LL | |
|
||||
LL | | baz().await
|
||||
LL | | }
|
||||
| |_____^
|
||||
LL | baz().await
|
||||
| ^^^^^
|
||||
|
||||
error: aborting due to 6 previous errors
|
||||
|
||||
|
|
|
@ -1,10 +1,3 @@
|
|||
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
|
||||
--> $DIR/blanket_clippy_restriction_lints.rs:6:9
|
||||
|
|
||||
|
@ -12,6 +5,8 @@ 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
|
||||
--> $DIR/blanket_clippy_restriction_lints.rs:8:9
|
||||
|
@ -29,5 +24,10 @@ 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
|
||||
|
||||
|
|
|
@ -36,7 +36,7 @@ fn main() {
|
|||
issue_10381();
|
||||
|
||||
// `Box::<Option<_>>::default()` would be valid here, but not `Box::default()` or
|
||||
// `Box::<Option<[closure@...]>::default()`
|
||||
// `Box::<Option<{closure@...}>::default()`
|
||||
//
|
||||
// Would have a suggestion after https://github.com/rust-lang/rust/blob/fdd030127cc68afec44a8d3f6341525dd34e50ae/compiler/rustc_middle/src/ty/diagnostics.rs#L554-L563
|
||||
let mut unnameable = Box::new(Option::default());
|
||||
|
|
|
@ -36,7 +36,7 @@ fn main() {
|
|||
issue_10381();
|
||||
|
||||
// `Box::<Option<_>>::default()` would be valid here, but not `Box::default()` or
|
||||
// `Box::<Option<[closure@...]>::default()`
|
||||
// `Box::<Option<{closure@...}>::default()`
|
||||
//
|
||||
// Would have a suggestion after https://github.com/rust-lang/rust/blob/fdd030127cc68afec44a8d3f6341525dd34e50ae/compiler/rustc_middle/src/ty/diagnostics.rs#L554-L563
|
||||
let mut unnameable = Box::new(Option::default());
|
||||
|
|
|
@ -27,7 +27,7 @@ LL | fn bug<T>() -> impl Iterator<Item = [(); { |x: [u8]| x }]> {
|
|||
| ^^^^^^^^^^^ expected `usize`, found closure
|
||||
|
|
||||
= note: expected type `usize`
|
||||
found closure `[closure@$DIR/ice-6251.rs:4:44: 4:53]`
|
||||
found closure `{closure@$DIR/ice-6251.rs:4:44: 4:53}`
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
|
||||
|
|
|
@ -198,6 +198,16 @@ fn pulldown_cmark_crash() {}
|
|||
/// [plain text][path::to::item]
|
||||
fn intra_doc_link() {}
|
||||
|
||||
/// Ignore escaped\_underscores
|
||||
///
|
||||
/// \\[
|
||||
/// \\prod\_{x\\in X} p\_x
|
||||
/// \\]
|
||||
fn issue_2581() {}
|
||||
|
||||
/// Foo \[bar\] \[baz\] \[qux\]. `DocMarkdownLint`
|
||||
fn lint_after_escaped_chars() {}
|
||||
|
||||
// issue #7033 - generic_const_exprs ICE
|
||||
struct S<T, const N: usize>
|
||||
where [(); N.checked_next_power_of_two().unwrap()]: {
|
||||
|
|
|
@ -198,6 +198,16 @@ fn pulldown_cmark_crash() {}
|
|||
/// [plain text][path::to::item]
|
||||
fn intra_doc_link() {}
|
||||
|
||||
/// Ignore escaped\_underscores
|
||||
///
|
||||
/// \\[
|
||||
/// \\prod\_{x\\in X} p\_x
|
||||
/// \\]
|
||||
fn issue_2581() {}
|
||||
|
||||
/// Foo \[bar\] \[baz\] \[qux\]. DocMarkdownLint
|
||||
fn lint_after_escaped_chars() {}
|
||||
|
||||
// issue #7033 - generic_const_exprs ICE
|
||||
struct S<T, const N: usize>
|
||||
where [(); N.checked_next_power_of_two().unwrap()]: {
|
||||
|
|
|
@ -308,5 +308,16 @@ help: try
|
|||
LL | /// An iterator over `mycrate::Collection`'s values.
|
||||
| ~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
error: aborting due to 28 previous errors
|
||||
error: item in documentation is missing backticks
|
||||
--> $DIR/doc-fixable.rs:208:34
|
||||
|
|
||||
LL | /// Foo \[bar\] \[baz\] \[qux\]. DocMarkdownLint
|
||||
| ^^^^^^^^^^^^^^^
|
||||
|
|
||||
help: try
|
||||
|
|
||||
LL | /// Foo \[bar\] \[baz\] \[qux\]. `DocMarkdownLint`
|
||||
| ~~~~~~~~~~~~~~~~~
|
||||
|
||||
error: aborting due to 29 previous errors
|
||||
|
||||
|
|
|
@ -48,4 +48,4 @@ fn other_markdown() {}
|
|||
/// /// `lol`
|
||||
/// pub struct Struct;
|
||||
/// ```
|
||||
fn iss_7421() {}
|
||||
fn issue_7421() {}
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
error: backticks are unbalanced
|
||||
--> $DIR/unbalanced_ticks.rs:7:1
|
||||
--> $DIR/unbalanced_ticks.rs:7:5
|
||||
|
|
||||
LL | / /// This is a doc comment with `unbalanced_tick marks and several words that
|
||||
LL | /// This is a doc comment with `unbalanced_tick marks and several words that
|
||||
| _____^
|
||||
LL | |
|
||||
LL | | /// should be `encompassed_by` tick marks because they `contain_underscores`.
|
||||
LL | | /// Because of the initial `unbalanced_tick` pair, the error message is
|
||||
|
@ -13,10 +14,10 @@ LL | | /// very `confusing_and_misleading`.
|
|||
= help: to override `-D warnings` add `#[allow(clippy::doc_markdown)]`
|
||||
|
||||
error: backticks are unbalanced
|
||||
--> $DIR/unbalanced_ticks.rs:14:1
|
||||
--> $DIR/unbalanced_ticks.rs:14:5
|
||||
|
|
||||
LL | /// This paragraph has `unbalanced_tick marks and should stop_linting.
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= help: a backtick may be missing a pair
|
||||
|
||||
|
@ -32,10 +33,10 @@ LL | /// This paragraph is fine and `should_be` linted normally.
|
|||
| ~~~~~~~~~~~
|
||||
|
||||
error: backticks are unbalanced
|
||||
--> $DIR/unbalanced_ticks.rs:20:1
|
||||
--> $DIR/unbalanced_ticks.rs:20:5
|
||||
|
|
||||
LL | /// Double unbalanced backtick from ``here to here` should lint.
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= help: a backtick may be missing a pair
|
||||
|
||||
|
@ -51,18 +52,18 @@ LL | /// ## `not_fine`
|
|||
| ~~~~~~~~~~
|
||||
|
||||
error: backticks are unbalanced
|
||||
--> $DIR/unbalanced_ticks.rs:37:1
|
||||
--> $DIR/unbalanced_ticks.rs:37:5
|
||||
|
|
||||
LL | /// ### `unbalanced
|
||||
| ^^^^^^^^^^^^^^^^^^^
|
||||
| ^^^^^^^^^^^^^^^
|
||||
|
|
||||
= help: a backtick may be missing a pair
|
||||
|
||||
error: backticks are unbalanced
|
||||
--> $DIR/unbalanced_ticks.rs:40:1
|
||||
--> $DIR/unbalanced_ticks.rs:40:5
|
||||
|
|
||||
LL | /// - This `item has unbalanced tick marks
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= help: a backtick may be missing a pair
|
||||
|
||||
|
|
|
@ -85,6 +85,27 @@ impl Struct1 {
|
|||
async fn async_priv_method_missing_errors_header() -> Result<(), ()> {
|
||||
unimplemented!();
|
||||
}
|
||||
|
||||
/**
|
||||
# Errors
|
||||
A description of the errors goes here.
|
||||
*/
|
||||
fn block_comment() -> Result<(), ()> {
|
||||
unimplemented!();
|
||||
}
|
||||
|
||||
/**
|
||||
* # Errors
|
||||
* A description of the errors goes here.
|
||||
*/
|
||||
fn block_comment_leading_asterisks() -> Result<(), ()> {
|
||||
unimplemented!();
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
fn doc_hidden() -> Result<(), ()> {
|
||||
unimplemented!();
|
||||
}
|
||||
}
|
||||
|
||||
pub trait Trait1 {
|
||||
|
@ -95,6 +116,11 @@ pub trait Trait1 {
|
|||
/// # Errors
|
||||
/// A description of the errors goes here.
|
||||
fn trait_method_with_errors_header() -> Result<(), ()>;
|
||||
|
||||
#[doc(hidden)]
|
||||
fn doc_hidden() -> Result<(), ()> {
|
||||
unimplemented!();
|
||||
}
|
||||
}
|
||||
|
||||
impl Trait1 for Struct1 {
|
||||
|
@ -107,6 +133,11 @@ impl Trait1 for Struct1 {
|
|||
}
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
pub trait DocHidden {
|
||||
fn f() -> Result<(), ()>;
|
||||
}
|
||||
|
||||
fn main() -> Result<(), ()> {
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
@ -38,7 +38,7 @@ LL | pub async fn async_pub_method_missing_errors_header() -> Result<(), ()>
|
|||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: docs for function returning `Result` missing `# Errors` section
|
||||
--> $DIR/doc_errors.rs:92:5
|
||||
--> $DIR/doc_errors.rs:113:5
|
||||
|
|
||||
LL | fn trait_method_missing_errors_header() -> Result<(), ()>;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
|
@ -59,6 +59,7 @@ where
|
|||
{
|
||||
let rt = &t;
|
||||
async { true }.await;
|
||||
let _ = rt;
|
||||
t
|
||||
}
|
||||
|
||||
|
|
|
@ -12,19 +12,12 @@ LL | async fn private_future(rc: Rc<[u8]>, cell: &Cell<usize>) -> bool {
|
|||
LL |
|
||||
LL | async { true }.await
|
||||
| ^^^^^ await occurs here, with `rc` maybe used later
|
||||
LL | }
|
||||
| - `rc` is later dropped here
|
||||
= note: `std::rc::Rc<[u8]>` doesn't implement `std::marker::Send`
|
||||
note: future is not `Send` as this value is used across an await
|
||||
--> $DIR/future_not_send.rs:9:20
|
||||
note: captured value is not `Send` because `&` references cannot be sent unless their referent is `Sync`
|
||||
--> $DIR/future_not_send.rs:7:39
|
||||
|
|
||||
LL | async fn private_future(rc: Rc<[u8]>, cell: &Cell<usize>) -> bool {
|
||||
| ---- has type `&std::cell::Cell<usize>` which is not `Send`
|
||||
LL |
|
||||
LL | async { true }.await
|
||||
| ^^^^^ await occurs here, with `cell` maybe used later
|
||||
LL | }
|
||||
| - `cell` is later dropped here
|
||||
| ^^^^ has type `&std::cell::Cell<usize>` which is not `Send`, because `std::cell::Cell<usize>` is not `Sync`
|
||||
= note: `std::cell::Cell<usize>` doesn't implement `std::marker::Sync`
|
||||
= note: `-D clippy::future-not-send` implied by `-D warnings`
|
||||
= help: to override `-D warnings` add `#[allow(clippy::future_not_send)]`
|
||||
|
@ -43,8 +36,6 @@ LL | pub async fn public_future(rc: Rc<[u8]>) {
|
|||
LL |
|
||||
LL | async { true }.await;
|
||||
| ^^^^^ await occurs here, with `rc` maybe used later
|
||||
LL | }
|
||||
| - `rc` is later dropped here
|
||||
= note: `std::rc::Rc<[u8]>` doesn't implement `std::marker::Send`
|
||||
|
||||
error: future cannot be sent between threads safely
|
||||
|
@ -93,9 +84,6 @@ LL | async fn private_future(&self) -> usize {
|
|||
LL |
|
||||
LL | async { true }.await;
|
||||
| ^^^^^ await occurs here, with `&self` maybe used later
|
||||
LL | self.rc.len()
|
||||
LL | }
|
||||
| - `&self` is later dropped here
|
||||
= note: `std::rc::Rc<[u8]>` doesn't implement `std::marker::Sync`
|
||||
|
||||
error: future cannot be sent between threads safely
|
||||
|
@ -104,16 +92,11 @@ error: future cannot be sent between threads safely
|
|||
LL | pub async fn public_future(&self) {
|
||||
| ^ future returned by `public_future` is not `Send`
|
||||
|
|
||||
note: future is not `Send` as this value is used across an await
|
||||
--> $DIR/future_not_send.rs:46:31
|
||||
note: captured value is not `Send` because `&` references cannot be sent unless their referent is `Sync`
|
||||
--> $DIR/future_not_send.rs:44:32
|
||||
|
|
||||
LL | pub async fn public_future(&self) {
|
||||
| ----- has type `&Dummy` which is not `Send`
|
||||
LL |
|
||||
LL | self.private_future().await;
|
||||
| ^^^^^ await occurs here, with `&self` maybe used later
|
||||
LL | }
|
||||
| - `&self` is later dropped here
|
||||
| ^^^^^ has type `&Dummy` which is not `Send`, because `Dummy` is not `Sync`
|
||||
= note: `std::rc::Rc<[u8]>` doesn't implement `std::marker::Sync`
|
||||
|
||||
error: future cannot be sent between threads safely
|
||||
|
@ -129,19 +112,16 @@ LL | let rt = &t;
|
|||
| -- has type `&T` which is not `Send`
|
||||
LL | async { true }.await;
|
||||
| ^^^^^ await occurs here, with `rt` maybe used later
|
||||
LL | t
|
||||
LL | }
|
||||
| - `rt` is later dropped here
|
||||
= note: `T` doesn't implement `std::marker::Sync`
|
||||
|
||||
error: future cannot be sent between threads safely
|
||||
--> $DIR/future_not_send.rs:72:34
|
||||
--> $DIR/future_not_send.rs:73:34
|
||||
|
|
||||
LL | async fn unclear_future<T>(t: T) {}
|
||||
| ^ future returned by `unclear_future` is not `Send`
|
||||
|
|
||||
note: captured value is not `Send`
|
||||
--> $DIR/future_not_send.rs:72:28
|
||||
--> $DIR/future_not_send.rs:73:28
|
||||
|
|
||||
LL | async fn unclear_future<T>(t: T) {}
|
||||
| ^ has type `T` which is not `Send`
|
||||
|
|
|
@ -24,7 +24,7 @@ error[E0080]: evaluation of `main::{constant#3}` failed
|
|||
LL | const { &ARR[idx4()] };
|
||||
| ^^^^^^^^^^^ index out of bounds: the length is 2 but the index is 4
|
||||
|
||||
note: erroneous constant used
|
||||
note: erroneous constant encountered
|
||||
--> $DIR/indexing_slicing_index.rs:48:5
|
||||
|
|
||||
LL | const { &ARR[idx4()] };
|
||||
|
|
|
@ -29,8 +29,9 @@
|
|||
///
|
||||
/// This one too.
|
||||
/// ```no_run
|
||||
/// fn main() {
|
||||
/// // the fn is not always the first line
|
||||
//~^ ERROR: needless `fn main` in doctest
|
||||
/// fn main() {
|
||||
/// unimplemented!();
|
||||
/// }
|
||||
/// ```
|
||||
|
|
|
@ -1,29 +1,47 @@
|
|||
error: needless `fn main` in doctest
|
||||
--> $DIR/needless_doc_main.rs:7:4
|
||||
--> $DIR/needless_doc_main.rs:7:5
|
||||
|
|
||||
LL | /// fn main() {
|
||||
| ^^^^^^^^^^^^
|
||||
LL | /// fn main() {
|
||||
| _____^
|
||||
LL | |
|
||||
LL | |
|
||||
LL | | /// unimplemented!();
|
||||
LL | | /// }
|
||||
| |_____^
|
||||
|
|
||||
= note: `-D clippy::needless-doctest-main` implied by `-D warnings`
|
||||
= help: to override `-D warnings` add `#[allow(clippy::needless_doctest_main)]`
|
||||
|
||||
error: needless `fn main` in doctest
|
||||
--> $DIR/needless_doc_main.rs:16:4
|
||||
--> $DIR/needless_doc_main.rs:16:5
|
||||
|
|
||||
LL | /// fn main() -> () {
|
||||
| ^^^^^^^^^^^^^^^^^^
|
||||
LL | /// fn main() -> () {
|
||||
| _____^
|
||||
LL | |
|
||||
LL | | /// unimplemented!();
|
||||
LL | | /// }
|
||||
| |_____^
|
||||
|
||||
error: needless `fn main` in doctest
|
||||
--> $DIR/needless_doc_main.rs:24:4
|
||||
--> $DIR/needless_doc_main.rs:24:5
|
||||
|
|
||||
LL | /// fn main() {
|
||||
| ^^^^^^^^^^^^
|
||||
LL | /// fn main() {
|
||||
| _____^
|
||||
LL | |
|
||||
LL | | /// unimplemented!();
|
||||
LL | | /// }
|
||||
| |_____^
|
||||
|
||||
error: needless `fn main` in doctest
|
||||
--> $DIR/needless_doc_main.rs:32:4
|
||||
--> $DIR/needless_doc_main.rs:32:5
|
||||
|
|
||||
LL | /// fn main() {
|
||||
| ^^^^^^^^^^^^
|
||||
LL | /// // the fn is not always the first line
|
||||
| _____^
|
||||
LL | |
|
||||
LL | | /// fn main() {
|
||||
LL | | /// unimplemented!();
|
||||
LL | | /// }
|
||||
| |_____^
|
||||
|
||||
error: aborting due to 4 previous errors
|
||||
|
||||
|
|
|
@ -2,15 +2,12 @@ error: unnecessary raw string literal
|
|||
--> $DIR/write_literal_2.rs:13:24
|
||||
|
|
||||
LL | writeln!(v, r"{}", r"{hello}");
|
||||
| ^^^^^^^^^^
|
||||
| -^^^^^^^^^
|
||||
| |
|
||||
| help: use a string literal instead: `"{hello}"`
|
||||
|
|
||||
= note: `-D clippy::needless-raw-strings` implied by `-D warnings`
|
||||
= help: to override `-D warnings` add `#[allow(clippy::needless_raw_strings)]`
|
||||
help: try
|
||||
|
|
||||
LL - writeln!(v, r"{}", r"{hello}");
|
||||
LL + writeln!(v, r"{}", "{hello}");
|
||||
|
|
||||
|
||||
error: literal with an empty format string
|
||||
--> $DIR/write_literal_2.rs:10:23
|
||||
|
|
Loading…
Reference in a new issue