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

Rustup

r? `@ghost`

changelog: none
This commit is contained in:
bors 2023-09-25 08:36:06 +00:00
commit 7671c283a5
51 changed files with 450 additions and 498 deletions

View file

@ -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"] }

View file

@ -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);
}
}
}

View file

@ -844,7 +844,6 @@ impl TyCoercionStability {
| ty::FnDef(..)
| ty::Generator(..)
| ty::GeneratorWitness(..)
| ty::GeneratorWitnessMIR(..)
| ty::Closure(..)
| ty::Never
| ty::Tuple(_)

View file

@ -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(&copy_id).map_or(false, |impls| {
impls.iter().any(|&id| {
matches!(cx.tcx.type_of(id).instantiate_identity().kind(), ty::Adt(adt, _)

View file

@ -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(&current_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(&current);
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");
}

View file

@ -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() {

View file

@ -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;

View file

@ -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)?;

View file

@ -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))),
}
}

View file

@ -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;

View file

@ -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 {

View file

@ -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) {

View file

@ -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;
}

View file

@ -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(_))

View file

@ -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, &macro_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

View file

@ -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);
}
}

View file

@ -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;

View file

@ -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,

View file

@ -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)) => {

View file

@ -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

View file

@ -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,
}
}

View file

@ -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)
}

View file

@ -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::{

View file

@ -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))
})
}

View file

@ -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"]

View file

@ -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 {

View file

@ -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!");
| ^^

View file

@ -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

View file

@ -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.

View file

@ -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

View file

@ -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

View file

@ -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;

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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());

View file

@ -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());

View file

@ -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

View file

@ -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()]: {

View file

@ -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()]: {

View file

@ -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

View file

@ -48,4 +48,4 @@ fn other_markdown() {}
/// /// `lol`
/// pub struct Struct;
/// ```
fn iss_7421() {}
fn issue_7421() {}

View file

@ -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

View file

@ -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(())
}

View file

@ -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<(), ()>;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

View file

@ -59,6 +59,7 @@ where
{
let rt = &t;
async { true }.await;
let _ = rt;
t
}

View file

@ -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`

View file

@ -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()] };

View file

@ -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!();
/// }
/// ```

View file

@ -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

View file

@ -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