diff --git a/compiler/rustc_hir_typeck/src/demand.rs b/compiler/rustc_hir_typeck/src/demand.rs index 5454b282d5226..6e4d6aa80a63a 100644 --- a/compiler/rustc_hir_typeck/src/demand.rs +++ b/compiler/rustc_hir_typeck/src/demand.rs @@ -40,6 +40,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { || self.suggest_semicolon_in_repeat_expr(err, expr, expr_ty) || self.suggest_deref_ref_or_into(err, expr, expected, expr_ty, expected_ty_expr) || self.suggest_option_to_bool(err, expr, expr_ty, expected) + || self.suggest_collect(err, expr, expected, expr_ty) || self.suggest_compatible_variants(err, expr, expected, expr_ty) || self.suggest_non_zero_new_unwrap(err, expr, expected, expr_ty) || self.suggest_calling_boxed_future_when_appropriate(err, expr, expected, expr_ty) diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs index 955ce5a6b58b5..323f0fb040d6b 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs @@ -250,6 +250,74 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } + /// Suggests calling `.collect()` on an `Iterator` it can be collected in the return type + /// ```compile_fail + /// let x: String = "foo".chars().map(|c| c); // with a .collect() here the code compiles + /// ``` + pub(crate) fn suggest_collect( + &self, + err: &mut Diag<'_>, + expr: &hir::Expr<'_>, + expected_type: Ty<'tcx>, + found_type: Ty<'tcx>, + ) -> bool { + let tcx = self.tcx; + let expected = self.resolve_vars_if_possible(expected_type); + let found = self.resolve_vars_if_possible(found_type); + + if expected.references_error() || found.references_error() || expected.is_unit() { + return false; + } + + let Some(iterator_trait_id) = tcx.get_diagnostic_item(sym::Iterator) else { + return false; + }; + + if !self + .infcx + .type_implements_trait(iterator_trait_id, [found], self.param_env) + .must_apply_modulo_regions() + { + return false; + } + + let Some(from_iterator_trait_id) = tcx.get_diagnostic_item(sym::FromIterator) else { + return false; + }; + + let Some(iterator_item_id) = tcx + .associated_items(iterator_trait_id) + .in_definition_order() + .find(|item| item.name() == sym::Item) + .map(|item| item.def_id) + else { + return false; + }; + + let item_type = Ty::new_projection(tcx, iterator_item_id, [found]); + let item_type = + self.normalize(expr.span, rustc_middle::ty::Unnormalized::new_wip(item_type)); + + let can_collect = self + .infcx + .type_implements_trait(from_iterator_trait_id, [expected, item_type], self.param_env) + .may_apply(); + + if can_collect { + err.span_suggestion_verbose( + expr.span.shrink_to_hi(), + format!( + "consider using `.collect()` to convert the `Iterator` into a `{expected}`" + ), + ".collect()", + rustc_errors::Applicability::MaybeIncorrect, + ); + return true; + } + + false + } + pub(crate) fn suggest_remove_last_method_call( &self, err: &mut Diag<'_>, diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs index 6d9f486f627f6..091b7ac228b54 100644 --- a/compiler/rustc_lint/src/lints.rs +++ b/compiler/rustc_lint/src/lints.rs @@ -2669,6 +2669,12 @@ pub(crate) struct RefOfMutStatic<'a> { "mutable references to mutable statics are dangerous; it's undefined behavior if any other pointer to the static is used or if any other reference is created for the static while the mutable reference lives" )] pub mut_note: bool, + #[help( + "use a type that relies on \"interior mutability\" instead; to read more on this, visit " + )] + pub interior_mutability_help: bool, + #[subdiagnostic] + pub interior_mutability_sugg: Option, } #[derive(Subdiagnostic)] @@ -2693,6 +2699,18 @@ pub(crate) enum MutRefSugg { }, } +#[derive(Subdiagnostic)] +#[suggestion( + "this type already provides \"interior mutability\", so its binding doesn't need to be declared as mutable", + style = "verbose", + applicability = "maybe-incorrect", + code = "" +)] +pub(crate) struct StaticMutRefsInteriorMutabilitySugg { + #[primary_span] + pub span: Span, +} + #[derive(Diagnostic)] #[diag("`use` of a local item without leading `self::`, `super::`, or `crate::`")] pub(crate) struct UnqualifiedLocalImportsDiag; diff --git a/compiler/rustc_lint/src/static_mut_refs.rs b/compiler/rustc_lint/src/static_mut_refs.rs index 1decb4b78e61a..67e83d0652c3d 100644 --- a/compiler/rustc_lint/src/static_mut_refs.rs +++ b/compiler/rustc_lint/src/static_mut_refs.rs @@ -1,11 +1,12 @@ use rustc_hir as hir; +use rustc_hir::def_id::DefId; use rustc_hir::{Expr, Stmt}; use rustc_middle::ty::{Mutability, TyKind}; use rustc_session::lint::fcw; use rustc_session::{declare_lint, declare_lint_pass}; use rustc_span::{BytePos, Span}; -use crate::lints::{MutRefSugg, RefOfMutStatic}; +use crate::lints::{MutRefSugg, RefOfMutStatic, StaticMutRefsInteriorMutabilitySugg}; use crate::{LateContext, LateLintPass, LintContext}; declare_lint! { @@ -67,7 +68,7 @@ impl<'tcx> LateLintPass<'tcx> for StaticMutRefs { match expr.kind { hir::ExprKind::AddrOf(borrow_kind, m, ex) if matches!(borrow_kind, hir::BorrowKind::Ref) - && let Some(err_span) = path_is_static_mut(ex, err_span) => + && let Some(static_mut) = path_is_static_mut(ex, err_span) => { let source_map = cx.sess().source_map(); let snippet = source_map.span_to_snippet(err_span); @@ -86,10 +87,17 @@ impl<'tcx> LateLintPass<'tcx> for StaticMutRefs { err_span.with_hi(ex.span.lo()) }; - emit_static_mut_refs(cx, err_span, sugg_span, m, !expr.span.from_expansion()); + emit_static_mut_refs( + cx, + static_mut.err_span, + sugg_span, + m, + !expr.span.from_expansion(), + static_mut.def_id, + ); } hir::ExprKind::MethodCall(_, e, _, _) - if let Some(err_span) = path_is_static_mut(e, expr.span) + if let Some(static_mut) = path_is_static_mut(e, expr.span) && let typeck = cx.typeck_results() && let Some(method_def_id) = typeck.type_dependent_def_id(expr.hir_id) && let inputs = @@ -97,7 +105,14 @@ impl<'tcx> LateLintPass<'tcx> for StaticMutRefs { && let Some(receiver) = inputs.get(0) && let TyKind::Ref(_, _, m) = receiver.kind() => { - emit_static_mut_refs(cx, err_span, err_span.shrink_to_lo(), *m, false); + emit_static_mut_refs( + cx, + static_mut.err_span, + static_mut.err_span.shrink_to_lo(), + *m, + false, + static_mut.def_id, + ); } _ => {} } @@ -108,14 +123,26 @@ impl<'tcx> LateLintPass<'tcx> for StaticMutRefs { && let hir::PatKind::Binding(ba, _, _, _) = loc.pat.kind && let hir::ByRef::Yes(_, m) = ba.0 && let Some(init) = loc.init - && let Some(err_span) = path_is_static_mut(init, init.span) + && let Some(static_mut) = path_is_static_mut(init, init.span) { - emit_static_mut_refs(cx, err_span, err_span.shrink_to_lo(), m, false); + emit_static_mut_refs( + cx, + static_mut.err_span, + static_mut.err_span.shrink_to_lo(), + m, + false, + static_mut.def_id, + ); } } } -fn path_is_static_mut(mut expr: &hir::Expr<'_>, mut err_span: Span) -> Option { +struct StaticMutInfo { + err_span: Span, + def_id: DefId, +} + +fn path_is_static_mut(mut expr: &hir::Expr<'_>, mut err_span: Span) -> Option { if err_span.from_expansion() { err_span = expr.span; } @@ -126,11 +153,11 @@ fn path_is_static_mut(mut expr: &hir::Expr<'_>, mut err_span: Span) -> Option { @@ -155,9 +183,106 @@ fn emit_static_mut_refs( } }; + let (interior_mutability_help, interior_mutability_sugg) = + interior_mutability_suggestion(cx, def_id); + cx.emit_span_lint( STATIC_MUT_REFS, span, - RefOfMutStatic { span, sugg, shared_label, shared_note, mut_note }, + RefOfMutStatic { + span, + sugg, + shared_label, + shared_note, + mut_note, + interior_mutability_help, + interior_mutability_sugg, + }, ); } + +// FIXME: This builds suggestion spans by handcrafting from source text. +// Replace this with HIR-based handling once we can identify the `mut` token +// in the static declaration that way. +// Context: https://github.com/rust-lang/rust/pull/151362/changes#r3210767018 +fn interior_mutability_suggestion( + cx: &LateContext<'_>, + def_id: DefId, +) -> (bool, Option) { + let static_ty = cx.tcx.type_of(def_id).skip_binder(); + let has_interior_mutability = !static_ty.is_freeze(cx.tcx, cx.typing_env()); + + if !has_interior_mutability { + return (false, None); + } + + let sugg = + static_mutability_span(cx, def_id).map(|span| StaticMutRefsInteriorMutabilitySugg { span }); + (sugg.is_none(), sugg) +} + +fn static_mutability_span(cx: &LateContext<'_>, def_id: DefId) -> Option { + let hir_id = cx.tcx.hir_get_if_local(def_id)?; + let hir::Node::Item(item) = hir_id else { return None }; + let (mutability, ident) = match item.kind { + hir::ItemKind::Static(mutability, ident, _, _) => (mutability, ident), + _ => return None, + }; + if mutability != hir::Mutability::Mut { + return None; + } + + let vis_span = item.vis_span.find_ancestor_inside(item.span)?; + if !item.span.can_be_used_for_suggestions() || !vis_span.can_be_used_for_suggestions() { + return None; + } + + let header_span = vis_span.between(ident.span); + if !header_span.can_be_used_for_suggestions() { + return None; + } + + let source_map = cx.sess().source_map(); + let snippet = source_map.span_to_snippet(header_span).ok()?; + + let (_static_start, static_end) = find_word(&snippet, "static", 0)?; + let (mut_start, mut_end) = find_word(&snippet, "mut", static_end)?; + let mut_end = extend_trailing_space(&snippet, mut_end); + + Some( + header_span + .with_lo(header_span.lo() + BytePos(mut_start as u32)) + .with_hi(header_span.lo() + BytePos(mut_end as u32)), + ) +} + +fn find_word(snippet: &str, word: &str, start: usize) -> Option<(usize, usize)> { + let bytes = snippet.as_bytes(); + let word_bytes = word.as_bytes(); + let mut search = start; + while search <= snippet.len() { + let found = snippet[search..].find(word)?; + let idx = search + found; + let end = idx + word_bytes.len(); + let before_ok = idx == 0 || !is_ident_char(bytes[idx - 1]); + let after_ok = end >= bytes.len() || !is_ident_char(bytes[end]); + if before_ok && after_ok { + return Some((idx, end)); + } + search = end; + } + None +} + +fn is_ident_char(byte: u8) -> bool { + byte.is_ascii_alphanumeric() || byte == b'_' +} + +fn extend_trailing_space(snippet: &str, mut end: usize) -> usize { + if let Some(ch) = snippet[end..].chars().next() + && (ch == ' ' || ch == '\t') + { + end += ch.len_utf8(); + } + end +} diff --git a/compiler/rustc_mir_transform/src/inline.rs b/compiler/rustc_mir_transform/src/inline.rs index fbe3a827d6394..31871c62fa7a2 100644 --- a/compiler/rustc_mir_transform/src/inline.rs +++ b/compiler/rustc_mir_transform/src/inline.rs @@ -1072,8 +1072,7 @@ fn make_call_args<'tcx, I: Inliner<'tcx>>( // // and the vector is `[closure_ref, tmp0, tmp1, tmp2]`. if callsite.fn_sig.abi() == ExternAbi::RustCall && callee_body.spread_arg.is_none() { - // FIXME(edition_2024): switch back to a normal method call. - let mut args = <_>::into_iter(args); + let mut args = args.into_iter(); let self_ = create_temp_if_necessary( inliner, args.next().unwrap().node, diff --git a/compiler/rustc_mir_transform/src/pass_manager.rs b/compiler/rustc_mir_transform/src/pass_manager.rs index ef4cf82cf1b5d..fbf16f91610c5 100644 --- a/compiler/rustc_mir_transform/src/pass_manager.rs +++ b/compiler/rustc_mir_transform/src/pass_manager.rs @@ -296,15 +296,14 @@ fn run_passes_inner<'tcx>( if is_optimization_stage(body, phase_change, optimizations) && let Some(limit) = &tcx.sess.opts.unstable_opts.mir_opt_bisect_limit - { - if limited_by_opt_bisect( + && limited_by_opt_bisect( tcx, tcx.def_path_debug_str(body.source.def_id()), *limit, *pass, - ) { - continue; - } + ) + { + continue; } let dumper = if pass.is_mir_dump_enabled() diff --git a/compiler/rustc_parse/src/lexer/unescape_error_reporting.rs b/compiler/rustc_parse/src/lexer/unescape_error_reporting.rs index 895374ab2cc4b..099bd44e9a065 100644 --- a/compiler/rustc_parse/src/lexer/unescape_error_reporting.rs +++ b/compiler/rustc_parse/src/lexer/unescape_error_reporting.rs @@ -3,7 +3,7 @@ use std::iter::once; use std::ops::Range; -use rustc_errors::{Applicability, DiagCtxtHandle, ErrorGuaranteed}; +use rustc_errors::{Applicability, Diag, DiagCtxtHandle, ErrorGuaranteed}; use rustc_literal_escaper::{EscapeError, Mode}; use rustc_span::{BytePos, Span}; use tracing::debug; @@ -172,6 +172,8 @@ pub(crate) fn emit_unescape_error( "for more information, visit \ ", ); + + foreign_escape_suggestion(&mut diag, (&ec, span), err_span); } diag.emit() } @@ -302,6 +304,44 @@ pub(crate) fn emit_unescape_error( }) } +/// Add additional suggestions for escapes that are supported by C. +fn foreign_escape_suggestion( + diag: &mut Diag<'_>, + (escaped_char, escape_span): (&str, Span), + err_span: Span, +) { + if escaped_char == "?" { + diag.span_suggestion( + err_span, + "if you meant to write a literal question mark, don't escape the character", + "?", + Applicability::MaybeIncorrect, + ); + return; + } + + if u8::from_str_radix(escaped_char, 8).is_ok() { + diag.help(r"if you meant to write an ASCII control code, use a `\xNN` hex escape"); + return; + } + + let (name, hex) = match escaped_char { + "a" => ("an audible bell", "07"), + "b" => ("a backspace", "08"), + "f" => ("a form feed", "0C"), + "v" => ("a vertical tab", "0B"), + "e" => ("an ANSI escape sequence", "1B"), + _ => return, + }; + + diag.span_suggestion( + escape_span, + format!("if you meant to write {name}, use a hex escape"), + format!("x{hex}"), + Applicability::MaybeIncorrect, + ); +} + /// Pushes a character to a message string for error reporting pub(crate) fn escaped_char(c: char) -> String { match c { diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs index f935f43d336c8..1360dc23a78f2 100644 --- a/compiler/rustc_parse/src/parser/diagnostics.rs +++ b/compiler/rustc_parse/src/parser/diagnostics.rs @@ -1891,9 +1891,8 @@ impl<'a> Parser<'a> { true } - /// Creates a `Diag` for an unexpected token `t` and tries to recover if it is a - /// closing delimiter. - pub(super) fn unexpected_try_recover(&mut self, t: &TokenKind) -> PResult<'a, Recovered> { + /// Creates a `Diag` for an unexpected token `t` + pub(super) fn unexpected_err(&mut self, t: &TokenKind) -> Diag<'a> { let token_str = pprust::token_kind_to_string(t); let this_token_str = super::token_descr(&self.token); let (prev_sp, sp) = match (&self.token.kind, self.subparser_name) { @@ -1928,7 +1927,7 @@ impl<'a> Parser<'a> { err.span_label(prev_sp, label_exp); err.span_label(sp, "unexpected token"); } - Err(err) + err } pub(super) fn expect_semi(&mut self) -> PResult<'a, ()> { diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs index 9303be8ff0ccd..850d64c8ecf44 100644 --- a/compiler/rustc_parse/src/parser/mod.rs +++ b/compiler/rustc_parse/src/parser/mod.rs @@ -409,7 +409,7 @@ impl<'a> Parser<'a> { self.bump(); Ok(Recovered::No) } else { - self.unexpected_try_recover(&exp.tok) + Err(self.unexpected_err(&exp.tok)) } } else { self.expect_one_of(slice::from_ref(&exp), &[]) diff --git a/compiler/rustc_resolve/src/check_unused.rs b/compiler/rustc_resolve/src/check_unused.rs index d39dcb1fa280b..84221cb8c2d5e 100644 --- a/compiler/rustc_resolve/src/check_unused.rs +++ b/compiler/rustc_resolve/src/check_unused.rs @@ -487,6 +487,9 @@ impl Resolver<'_, '_> { let remove_whole_use = remove_spans.len() == 1 && remove_spans[0] == unused.item_span; let num_to_remove = ms.primary_spans().len(); + // Only offer rustfix suggestions for spans that point at directly editable code. + let can_suggest_removal = + remove_spans.iter().all(|span| span.can_be_used_for_suggestions()); // If we are in the `--test` mode, suppress a help that adds the `#[cfg(test)]` // attribute; however, if not, suggest adding the attribute. There is no way to @@ -517,11 +520,13 @@ impl Resolver<'_, '_> { unused.use_tree_id, ms, move |dcx, level, sess| { - let sugg = if remove_whole_use { - errors::UnusedImportsSugg::RemoveWholeUse { span: remove_spans[0] } - } else { - errors::UnusedImportsSugg::RemoveImports { remove_spans, num_to_remove } - }; + let sugg = can_suggest_removal.then(|| { + if remove_whole_use { + errors::UnusedImportsSugg::RemoveWholeUse { span: remove_spans[0] } + } else { + errors::UnusedImportsSugg::RemoveImports { remove_spans, num_to_remove } + } + }); let test_module_span = test_module_span.map(|span| { sess.downcast_ref::() .expect("expected a `Session`") diff --git a/compiler/rustc_resolve/src/errors.rs b/compiler/rustc_resolve/src/errors.rs index 342484a8c0d51..4bcc7a5eb02e8 100644 --- a/compiler/rustc_resolve/src/errors.rs +++ b/compiler/rustc_resolve/src/errors.rs @@ -1742,7 +1742,7 @@ pub(crate) struct ElidedLifetimesInPaths { )] pub(crate) struct UnusedImports { #[subdiagnostic] - pub sugg: UnusedImportsSugg, + pub sugg: Option, #[help("if this is a test module, consider adding a `#[cfg(test)]` to the containing module")] pub test_module_span: Option, diff --git a/tests/rustdoc-ui/lints/unescaped_backticks.stderr b/tests/rustdoc-ui/lints/unescaped_backticks.deny_cli.stderr similarity index 91% rename from tests/rustdoc-ui/lints/unescaped_backticks.stderr rename to tests/rustdoc-ui/lints/unescaped_backticks.deny_cli.stderr index 1bcb88e108f20..6a2396ea1f9d6 100644 --- a/tests/rustdoc-ui/lints/unescaped_backticks.stderr +++ b/tests/rustdoc-ui/lints/unescaped_backticks.deny_cli.stderr @@ -1,14 +1,10 @@ error: unescaped backtick - --> $DIR/unescaped_backticks.rs:187:70 + --> $DIR/unescaped_backticks.rs:192:70 | LL | /// if you want your MIR to be modified by the full MIR pipeline, or `#![custom_mir(dialect = | ^ | -note: the lint level is defined here - --> $DIR/unescaped_backticks.rs:1:9 - | -LL | #![deny(rustdoc::unescaped_backticks)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: requested on the command line with `-D rustdoc::unescaped-backticks` help: the closing backtick of an inline code may be missing | LL | /// "runtime", phase = "optimized")]` if you don't. @@ -19,7 +15,7 @@ LL | /// if you want your MIR to be modified by the full MIR pipeline, or \`#![c | + error: unescaped backtick - --> $DIR/unescaped_backticks.rs:232:13 + --> $DIR/unescaped_backticks.rs:237:13 | LL | //! `#![rustc_expected_cgu_reuse(module="spike", cfg="rpass2", kind="post-lto")] | ^ @@ -34,7 +30,7 @@ LL | //! \`#![rustc_expected_cgu_reuse(module="spike", cfg="rpass2", kin | + error: unescaped backtick - --> $DIR/unescaped_backticks.rs:237:13 + --> $DIR/unescaped_backticks.rs:242:13 | LL | /// `cfg=... | ^ @@ -49,7 +45,7 @@ LL | /// \`cfg=... | + error: unescaped backtick - --> $DIR/unescaped_backticks.rs:241:42 + --> $DIR/unescaped_backticks.rs:246:42 | LL | /// `cfg=... and not `#[cfg_attr]` | ^ @@ -64,7 +60,7 @@ LL | /// `cfg=... and not `#[cfg_attr]\` | + error: unescaped backtick - --> $DIR/unescaped_backticks.rs:193:93 + --> $DIR/unescaped_backticks.rs:198:93 | LL | /// Constructs a `TyKind::Error` type and registers a `span_delayed_bug` with the given `msg to | ^ @@ -79,7 +75,7 @@ LL | /// Constructs a `TyKind::Error` type and registers a `span_delayed_bug | + error: unescaped backtick - --> $DIR/unescaped_backticks.rs:202:34 + --> $DIR/unescaped_backticks.rs:207:34 | LL | /// in `nt_to_tokenstream` | ^ @@ -94,7 +90,7 @@ LL | /// in `nt_to_tokenstream\` | + error: unescaped backtick - --> $DIR/unescaped_backticks.rs:208:62 + --> $DIR/unescaped_backticks.rs:213:62 | LL | /// that `Option` only takes up 4 bytes, because `newtype_index! reserves | ^ @@ -109,7 +105,7 @@ LL | /// that `Option` only takes up 4 bytes, because \`newtype_inde | + error: unescaped backtick - --> $DIR/unescaped_backticks.rs:216:52 + --> $DIR/unescaped_backticks.rs:221:52 | LL | /// also avoids the need to import `OpenOptions`. | ^ @@ -124,7 +120,7 @@ LL | /// also avoids the need to import `OpenOptions\`. | + error: unescaped backtick - --> $DIR/unescaped_backticks.rs:221:47 + --> $DIR/unescaped_backticks.rs:226:47 | LL | /// `ChunkedBitSet`. Has no effect if `row` does not exist. | ^ @@ -139,7 +135,7 @@ LL | /// `ChunkedBitSet`. Has no effect if `row\` does not exist. | + error: unescaped backtick - --> $DIR/unescaped_backticks.rs:247:12 + --> $DIR/unescaped_backticks.rs:252:12 | LL | /// RWU`s can get very large, so it uses a more compact representation. | ^ @@ -154,7 +150,7 @@ LL | /// RWU\`s can get very large, so it uses a more compact representation | + error: unescaped backtick - --> $DIR/unescaped_backticks.rs:254:15 + --> $DIR/unescaped_backticks.rs:259:15 | LL | /// in `U2`. | ^ @@ -169,7 +165,7 @@ LL | /// in `U2\`. | + error: unescaped backtick - --> $DIR/unescaped_backticks.rs:271:42 + --> $DIR/unescaped_backticks.rs:276:42 | LL | /// because it contains `[type error]`. Yuck! (See issue #29857 for | ^ @@ -184,7 +180,7 @@ LL | /// because it contains `[type error]\`. Yuck! (See issue #29857 for | + error: unescaped backtick - --> $DIR/unescaped_backticks.rs:281:53 + --> $DIR/unescaped_backticks.rs:286:53 | LL | /// well as the second instance of `A: AutoTrait`) to suppress | ^ @@ -199,7 +195,7 @@ LL | /// well as the second instance of `A: AutoTrait\`) to suppress | + error: unescaped backtick - --> $DIR/unescaped_backticks.rs:291:40 + --> $DIR/unescaped_backticks.rs:296:40 | LL | /// `'a` with `'b` and not `'static`. But it will have to do for | ^ @@ -211,7 +207,7 @@ LL | /// `'a` with `'b` and not `'static\`. But it will have to do for | + error: unescaped backtick - --> $DIR/unescaped_backticks.rs:300:54 + --> $DIR/unescaped_backticks.rs:305:54 | LL | /// `None`. Otherwise, it will return `Some(Dispatch)`. | ^ @@ -226,7 +222,7 @@ LL | /// `None`. Otherwise, it will return `Some(Dispatch)\`. | + error: unescaped backtick - --> $DIR/unescaped_backticks.rs:304:13 + --> $DIR/unescaped_backticks.rs:309:13 | LL | /// or `None` if it isn't. | ^ @@ -238,7 +234,7 @@ LL | /// or `None\` if it isn't. | + error: unescaped backtick - --> $DIR/unescaped_backticks.rs:308:14 + --> $DIR/unescaped_backticks.rs:313:14 | LL | /// `on_event` should be called. | ^ @@ -253,7 +249,7 @@ LL | /// `on_event\` should be called. | + error: unescaped backtick - --> $DIR/unescaped_backticks.rs:313:29 + --> $DIR/unescaped_backticks.rs:318:29 | LL | /// [`rebuild_interest_cache`][rebuild] is called after the value of the max | ^ @@ -268,7 +264,7 @@ LL | /// [`rebuild_interest_cache\`][rebuild] is called after the value of the m | + error: unescaped backtick - --> $DIR/unescaped_backticks.rs:323:5 + --> $DIR/unescaped_backticks.rs:328:5 | LL | / /// The Subscriber` may be accessed by calling [`WeakDispatch::upgrade`], ... | @@ -284,7 +280,7 @@ LL | | /// level changes. to this: `None`. Otherwise, it will return `Some(Dispatch)\`. error: unescaped backtick - --> $DIR/unescaped_backticks.rs:323:5 + --> $DIR/unescaped_backticks.rs:328:5 | LL | / /// The Subscriber` may be accessed by calling [`WeakDispatch::upgrade`], ... | @@ -298,7 +294,7 @@ LL | | /// level changes. to this: or `None\` if it isn't. error: unescaped backtick - --> $DIR/unescaped_backticks.rs:323:5 + --> $DIR/unescaped_backticks.rs:328:5 | LL | / /// The Subscriber` may be accessed by calling [`WeakDispatch::upgrade`], ... | @@ -314,7 +310,7 @@ LL | | /// level changes. to this: `on_event\` should be called. error: unescaped backtick - --> $DIR/unescaped_backticks.rs:323:5 + --> $DIR/unescaped_backticks.rs:328:5 | LL | / /// The Subscriber` may be accessed by calling [`WeakDispatch::upgrade`], ... | @@ -330,7 +326,7 @@ LL | | /// level changes. to this: [`rebuild_interest_cache\`][rebuild] is called after the value of the max error: unescaped backtick - --> $DIR/unescaped_backticks.rs:349:56 + --> $DIR/unescaped_backticks.rs:354:56 | LL | /// instead and use [`CloneCounterObserver::counter`] to increment. | ^ @@ -342,7 +338,7 @@ LL | /// instead and use [`CloneCounterObserver::counter\`] to increment. | + error: unescaped backtick - --> $DIR/unescaped_backticks.rs:12:5 + --> $DIR/unescaped_backticks.rs:17:5 | LL | /// ` | ^ @@ -354,7 +350,7 @@ LL | /// \` | + error: unescaped backtick - --> $DIR/unescaped_backticks.rs:19:7 + --> $DIR/unescaped_backticks.rs:24:7 | LL | /// \` | ^ @@ -369,7 +365,7 @@ LL | /// \\` | + error: unescaped backtick - --> $DIR/unescaped_backticks.rs:26:6 + --> $DIR/unescaped_backticks.rs:31:6 | LL | /// [`link1] | ^ @@ -384,7 +380,7 @@ LL | /// [\`link1] | + error: unescaped backtick - --> $DIR/unescaped_backticks.rs:30:11 + --> $DIR/unescaped_backticks.rs:35:11 | LL | /// [link2`] | ^ @@ -399,7 +395,7 @@ LL | /// [link2\`] | + error: unescaped backtick - --> $DIR/unescaped_backticks.rs:34:6 + --> $DIR/unescaped_backticks.rs:39:6 | LL | /// [`link_long](link_long) | ^ @@ -414,7 +410,7 @@ LL | /// [\`link_long](link_long) | + error: unescaped backtick - --> $DIR/unescaped_backticks.rs:38:6 + --> $DIR/unescaped_backticks.rs:43:6 | LL | /// [`broken-link] | ^ @@ -429,7 +425,7 @@ LL | /// [\`broken-link] | + error: unescaped backtick - --> $DIR/unescaped_backticks.rs:45:8 + --> $DIR/unescaped_backticks.rs:50:8 | LL | /// | ^ @@ -444,7 +440,7 @@ LL | /// | + error: unescaped backtick - --> $DIR/unescaped_backticks.rs:55:6 + --> $DIR/unescaped_backticks.rs:60:6 | LL | /// 🦀`🦀 | ^ @@ -463,7 +459,7 @@ LL | /// 🦀\`🦀 | + error: unescaped backtick - --> $DIR/unescaped_backticks.rs:59:5 + --> $DIR/unescaped_backticks.rs:64:5 | LL | /// `foo( | ^ @@ -478,7 +474,7 @@ LL | /// \`foo( | + error: unescaped backtick - --> $DIR/unescaped_backticks.rs:65:14 + --> $DIR/unescaped_backticks.rs:70:14 | LL | /// `foo `bar` | ^ @@ -493,7 +489,7 @@ LL | /// `foo `bar\` | + error: unescaped backtick - --> $DIR/unescaped_backticks.rs:71:5 + --> $DIR/unescaped_backticks.rs:76:5 | LL | /// `foo( | ^ @@ -508,7 +504,7 @@ LL | /// \`foo( | + error: unescaped backtick - --> $DIR/unescaped_backticks.rs:76:83 + --> $DIR/unescaped_backticks.rs:81:83 | LL | /// Addition is commutative, which means that add(a, b)` is the same as `add(b, a)`. | ^ @@ -523,7 +519,7 @@ LL | /// Addition is commutative, which means that add(a, b)` is the same as `ad | + error: unescaped backtick - --> $DIR/unescaped_backticks.rs:80:51 + --> $DIR/unescaped_backticks.rs:85:51 | LL | /// or even to add a number `n` to 42 (`add(42, b)`)! | ^ @@ -538,7 +534,7 @@ LL | /// or even to add a number `n` to 42 (`add(42, b)\`)! | + error: unescaped backtick - --> $DIR/unescaped_backticks.rs:84:83 + --> $DIR/unescaped_backticks.rs:89:83 | LL | /// Addition is commutative, which means that `add(a, b) is the same as `add(b, a)`. | ^ @@ -553,7 +549,7 @@ LL | /// Addition is commutative, which means that `add(a, b) is the same as `ad | + error: unescaped backtick - --> $DIR/unescaped_backticks.rs:88:51 + --> $DIR/unescaped_backticks.rs:93:51 | LL | /// or even to add a number `n` to 42 (`add(42, n)`)! | ^ @@ -568,7 +564,7 @@ LL | /// or even to add a number `n` to 42 (`add(42, n)\`)! | + error: unescaped backtick - --> $DIR/unescaped_backticks.rs:92:83 + --> $DIR/unescaped_backticks.rs:97:83 | LL | /// Addition is commutative, which means that `add(a, b)` is the same as add(b, a)`. | ^ @@ -583,7 +579,7 @@ LL | /// Addition is commutative, which means that `add(a, b)` is the same as ad | + error: unescaped backtick - --> $DIR/unescaped_backticks.rs:96:50 + --> $DIR/unescaped_backticks.rs:101:50 | LL | /// or even to add a number `n` to 42 (add(42, n)`)! | ^ @@ -598,7 +594,7 @@ LL | /// or even to add a number `n` to 42 (add(42, n)\`)! | + error: unescaped backtick - --> $DIR/unescaped_backticks.rs:100:74 + --> $DIR/unescaped_backticks.rs:105:74 | LL | /// Addition is commutative, which means that `add(a, b)` is the same as `add(b, a). | ^ @@ -613,7 +609,7 @@ LL | /// Addition is commutative, which means that `add(a, b)` is the same as \` | + error: unescaped backtick - --> $DIR/unescaped_backticks.rs:104:51 + --> $DIR/unescaped_backticks.rs:109:51 | LL | /// or even to add a number `n` to 42 (`add(42, n)`)! | ^ @@ -628,7 +624,7 @@ LL | /// or even to add a number `n` to 42 (`add(42, n)\`)! | + error: unescaped backtick - --> $DIR/unescaped_backticks.rs:108:10 + --> $DIR/unescaped_backticks.rs:113:10 | LL | #[doc = "`"] | ^ @@ -639,7 +635,7 @@ LL | #[doc = "`"] to this: \` error: unescaped backtick - --> $DIR/unescaped_backticks.rs:115:26 + --> $DIR/unescaped_backticks.rs:120:26 | LL | #[doc = concat!("\\", "`")] | ^ @@ -652,7 +648,7 @@ LL | #[doc = concat!("\\", "`")] to this: \\` error: unescaped backtick - --> $DIR/unescaped_backticks.rs:119:9 + --> $DIR/unescaped_backticks.rs:124:9 | LL | #[doc = "Addition is commutative, which means that add(a, b)` is the same as `add(b, a)`."] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -665,7 +661,7 @@ LL | #[doc = "Addition is commutative, which means that add(a, b)` is the same a to this: Addition is commutative, which means that add(a, b)` is the same as `add(b, a)\`. error: unescaped backtick - --> $DIR/unescaped_backticks.rs:123:9 + --> $DIR/unescaped_backticks.rs:128:9 | LL | #[doc = "Addition is commutative, which means that `add(a, b) is the same as `add(b, a)`."] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -678,7 +674,7 @@ LL | #[doc = "Addition is commutative, which means that `add(a, b) is the same a to this: Addition is commutative, which means that `add(a, b) is the same as `add(b, a)\`. error: unescaped backtick - --> $DIR/unescaped_backticks.rs:127:9 + --> $DIR/unescaped_backticks.rs:132:9 | LL | #[doc = "Addition is commutative, which means that `add(a, b)` is the same as add(b, a)`."] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -691,7 +687,7 @@ LL | #[doc = "Addition is commutative, which means that `add(a, b)` is the same to this: Addition is commutative, which means that `add(a, b)` is the same as add(b, a)\`. error: unescaped backtick - --> $DIR/unescaped_backticks.rs:131:9 + --> $DIR/unescaped_backticks.rs:136:9 | LL | #[doc = "Addition is commutative, which means that `add(a, b)` is the same as `add(b, a)."] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -704,7 +700,7 @@ LL | #[doc = "Addition is commutative, which means that `add(a, b)` is the same to this: Addition is commutative, which means that `add(a, b)` is the same as \`add(b, a). error: unescaped backtick - --> $DIR/unescaped_backticks.rs:136:5 + --> $DIR/unescaped_backticks.rs:141:5 | LL | /// `foo | ^ @@ -719,7 +715,7 @@ LL | /// \`foo | + error: unescaped backtick - --> $DIR/unescaped_backticks.rs:140:7 + --> $DIR/unescaped_backticks.rs:145:7 | LL | /// # `(heading | ^ @@ -734,7 +730,7 @@ LL | /// # \`(heading | + error: unescaped backtick - --> $DIR/unescaped_backticks.rs:142:17 + --> $DIR/unescaped_backticks.rs:147:17 | LL | /// ## heading2)` | ^ @@ -749,7 +745,7 @@ LL | /// ## heading2)\` | + error: unescaped backtick - --> $DIR/unescaped_backticks.rs:145:11 + --> $DIR/unescaped_backticks.rs:150:11 | LL | /// multi `( | ^ @@ -764,7 +760,7 @@ LL | /// multi \`( | + error: unescaped backtick - --> $DIR/unescaped_backticks.rs:151:10 + --> $DIR/unescaped_backticks.rs:156:10 | LL | /// para)`(graph | ^ @@ -783,7 +779,7 @@ LL | /// para)\`(graph | + error: unescaped backtick - --> $DIR/unescaped_backticks.rs:154:10 + --> $DIR/unescaped_backticks.rs:159:10 | LL | /// para)`(graph2 | ^ @@ -802,7 +798,7 @@ LL | /// para)\`(graph2 | + error: unescaped backtick - --> $DIR/unescaped_backticks.rs:157:12 + --> $DIR/unescaped_backticks.rs:162:12 | LL | /// 1. foo)` | ^ @@ -817,7 +813,7 @@ LL | /// 1. foo)\` | + error: unescaped backtick - --> $DIR/unescaped_backticks.rs:159:8 + --> $DIR/unescaped_backticks.rs:164:8 | LL | /// 2. `(bar | ^ @@ -832,7 +828,7 @@ LL | /// 2. \`(bar | + error: unescaped backtick - --> $DIR/unescaped_backticks.rs:161:11 + --> $DIR/unescaped_backticks.rs:166:11 | LL | /// * baz)` | ^ @@ -847,7 +843,7 @@ LL | /// * baz)\` | + error: unescaped backtick - --> $DIR/unescaped_backticks.rs:163:7 + --> $DIR/unescaped_backticks.rs:168:7 | LL | /// * `(quux | ^ @@ -862,7 +858,7 @@ LL | /// * \`(quux | + error: unescaped backtick - --> $DIR/unescaped_backticks.rs:166:5 + --> $DIR/unescaped_backticks.rs:171:5 | LL | /// `#![this_is_actually_an_image(and(not), an = "attribute")] | ^ @@ -877,7 +873,7 @@ LL | /// \`#![this_is_actually_an_image(and(not), an = "attribute")] | + error: unescaped backtick - --> $DIR/unescaped_backticks.rs:169:62 + --> $DIR/unescaped_backticks.rs:174:62 | LL | /// #![this_is_actually_an_image(and(not), an = "attribute")]` | ^ @@ -892,7 +888,7 @@ LL | /// #![this_is_actually_an_image(and(not), an = "attribute")]\` | + error: unescaped backtick - --> $DIR/unescaped_backticks.rs:174:7 + --> $DIR/unescaped_backticks.rs:179:7 | LL | /// | `table( | )head` | | ^ @@ -907,7 +903,7 @@ LL | /// | \`table( | )head` | | + error: unescaped backtick - --> $DIR/unescaped_backticks.rs:174:22 + --> $DIR/unescaped_backticks.rs:179:22 | LL | /// | `table( | )head` | | ^ @@ -922,7 +918,7 @@ LL | /// | `table( | )head\` | | + error: unescaped backtick - --> $DIR/unescaped_backticks.rs:178:12 + --> $DIR/unescaped_backticks.rs:183:12 | LL | /// | table`( | )`body | | ^ @@ -937,7 +933,7 @@ LL | /// | table\`( | )`body | | + error: unescaped backtick - --> $DIR/unescaped_backticks.rs:178:18 + --> $DIR/unescaped_backticks.rs:183:18 | LL | /// | table`( | )`body | | ^ diff --git a/tests/rustdoc-ui/lints/unescaped_backticks.rs b/tests/rustdoc-ui/lints/unescaped_backticks.rs index 8d6239296bf78..55ea1ac699d00 100644 --- a/tests/rustdoc-ui/lints/unescaped_backticks.rs +++ b/tests/rustdoc-ui/lints/unescaped_backticks.rs @@ -1,4 +1,9 @@ -#![deny(rustdoc::unescaped_backticks)] +//@revisions: deny_cli allow_cli capped +//@[capped] compile-flags: --cap-lints=allow +//@[capped] check-pass +//@[deny_cli] compile-flags: -Drustdoc::unescaped_backticks +//@[allow_cli] compile-flags: -Arustdoc::unescaped_backticks +//@[allow_cli] check-pass #![allow(rustdoc::broken_intra_doc_links)] #![allow(rustdoc::invalid_html_tags)] #![allow(rustdoc::redundant_explicit_links)] @@ -10,40 +15,40 @@ pub fn empty() {} pub fn empty2() {} /// ` -//~^ ERROR unescaped backtick +//[deny_cli]~^ ERROR unescaped backtick pub fn single() {} /// \` pub fn escaped() {} /// \\` -//~^ ERROR unescaped backtick +//[deny_cli]~^ ERROR unescaped backtick pub fn not_escaped() {} /// \\\` pub fn not_not_escaped() {} /// [`link1] -//~^ ERROR unescaped backtick +//[deny_cli]~^ ERROR unescaped backtick pub fn link1() {} /// [link2`] -//~^ ERROR unescaped backtick +//[deny_cli]~^ ERROR unescaped backtick pub fn link2() {} /// [`link_long](link_long) -//~^ ERROR unescaped backtick +//[deny_cli]~^ ERROR unescaped backtick pub fn link_long() {} /// [`broken-link] -//~^ ERROR unescaped backtick +//[deny_cli]~^ ERROR unescaped backtick pub fn broken_link() {} /// pub fn url() {} /// -//~^ ERROR unescaped backtick +//[deny_cli]~^ ERROR unescaped backtick pub fn not_url() {} ///

`

@@ -53,131 +58,131 @@ pub fn html_tag() {} pub fn html_escape() {} /// 🦀`🦀 -//~^ ERROR unescaped backtick +//[deny_cli]~^ ERROR unescaped backtick pub fn unicode() {} /// `foo( -//~^ ERROR unescaped backtick +//[deny_cli]~^ ERROR unescaped backtick /// /// paragraph pub fn paragraph() {} /// `foo `bar` -//~^ ERROR unescaped backtick +//[deny_cli]~^ ERROR unescaped backtick /// /// paragraph pub fn paragraph2() {} /// `foo( -//~^ ERROR unescaped backtick +//[deny_cli]~^ ERROR unescaped backtick /// not paragraph pub fn not_paragraph() {} /// Addition is commutative, which means that add(a, b)` is the same as `add(b, a)`. -//~^ ERROR unescaped backtick +//[deny_cli]~^ ERROR unescaped backtick /// /// You could use this function to add 42 to a number `n` (add(n, 42)`), /// or even to add a number `n` to 42 (`add(42, b)`)! -//~^ ERROR unescaped backtick +//[deny_cli]~^ ERROR unescaped backtick pub fn add1(a: i32, b: i32) -> i32 { a + b } /// Addition is commutative, which means that `add(a, b) is the same as `add(b, a)`. -//~^ ERROR unescaped backtick +//[deny_cli]~^ ERROR unescaped backtick /// /// You could use this function to add 42 to a number `n` (`add(n, 42)), /// or even to add a number `n` to 42 (`add(42, n)`)! -//~^ ERROR unescaped backtick +//[deny_cli]~^ ERROR unescaped backtick pub fn add2(a: i32, b: i32) -> i32 { a + b } /// Addition is commutative, which means that `add(a, b)` is the same as add(b, a)`. -//~^ ERROR unescaped backtick +//[deny_cli]~^ ERROR unescaped backtick /// /// You could use this function to add 42 to a number `n` (`add(n, 42)`), /// or even to add a number `n` to 42 (add(42, n)`)! -//~^ ERROR unescaped backtick +//[deny_cli]~^ ERROR unescaped backtick pub fn add3(a: i32, b: i32) -> i32 { a + b } /// Addition is commutative, which means that `add(a, b)` is the same as `add(b, a). -//~^ ERROR unescaped backtick +//[deny_cli]~^ ERROR unescaped backtick /// /// You could use this function to add 42 to a number `n` (`add(n, 42)), /// or even to add a number `n` to 42 (`add(42, n)`)! -//~^ ERROR unescaped backtick +//[deny_cli]~^ ERROR unescaped backtick pub fn add4(a: i32, b: i32) -> i32 { a + b } #[doc = "`"] -//~^ ERROR unescaped backtick +//[deny_cli]~^ ERROR unescaped backtick pub fn attr() {} #[doc = concat!("\\", "`")] pub fn attr_escaped() {} #[doc = concat!("\\\\", "`")] -//~^ ERROR unescaped backtick +//[deny_cli]~^ ERROR unescaped backtick pub fn attr_not_escaped() {} #[doc = "Addition is commutative, which means that add(a, b)` is the same as `add(b, a)`."] -//~^ ERROR unescaped backtick +//[deny_cli]~^ ERROR unescaped backtick pub fn attr_add1(a: i32, b: i32) -> i32 { a + b } #[doc = "Addition is commutative, which means that `add(a, b) is the same as `add(b, a)`."] -//~^ ERROR unescaped backtick +//[deny_cli]~^ ERROR unescaped backtick pub fn attr_add2(a: i32, b: i32) -> i32 { a + b } #[doc = "Addition is commutative, which means that `add(a, b)` is the same as add(b, a)`."] -//~^ ERROR unescaped backtick +//[deny_cli]~^ ERROR unescaped backtick pub fn attr_add3(a: i32, b: i32) -> i32 { a + b } #[doc = "Addition is commutative, which means that `add(a, b)` is the same as `add(b, a)."] -//~^ ERROR unescaped backtick +//[deny_cli]~^ ERROR unescaped backtick pub fn attr_add4(a: i32, b: i32) -> i32 { a + b } /// ``double backticks`` /// `foo -//~^ ERROR unescaped backtick +//[deny_cli]~^ ERROR unescaped backtick pub fn double_backticks() {} /// # `(heading -//~^ ERROR unescaped backtick +//[deny_cli]~^ ERROR unescaped backtick /// ## heading2)` -//~^ ERROR unescaped backtick +//[deny_cli]~^ ERROR unescaped backtick /// /// multi `( -//~^ ERROR unescaped backtick +//[deny_cli]~^ ERROR unescaped backtick /// line /// ) heading /// = /// /// para)`(graph -//~^ ERROR unescaped backtick +//[deny_cli]~^ ERROR unescaped backtick /// /// para)`(graph2 -//~^ ERROR unescaped backtick +//[deny_cli]~^ ERROR unescaped backtick /// /// 1. foo)` -//~^ ERROR unescaped backtick +//[deny_cli]~^ ERROR unescaped backtick /// 2. `(bar -//~^ ERROR unescaped backtick +//[deny_cli]~^ ERROR unescaped backtick /// * baz)` -//~^ ERROR unescaped backtick +//[deny_cli]~^ ERROR unescaped backtick /// * `(quux -//~^ ERROR unescaped backtick +//[deny_cli]~^ ERROR unescaped backtick /// /// `#![this_is_actually_an_image(and(not), an = "attribute")] -//~^ ERROR unescaped backtick +//[deny_cli]~^ ERROR unescaped backtick /// /// #![this_is_actually_an_image(and(not), an = "attribute")]` -//~^ ERROR unescaped backtick +//[deny_cli]~^ ERROR unescaped backtick /// /// [this_is_actually_an_image(and(not), an = "attribute")]: `.png /// /// | `table( | )head` | -//~^ ERROR unescaped backtick -//~| ERROR unescaped backtick +//[deny_cli]~^ ERROR unescaped backtick +//[deny_cli]~| ERROR unescaped backtick /// |---------|--------| /// | table`( | )`body | -//~^ ERROR unescaped backtick -//~| ERROR unescaped backtick +//[deny_cli]~^ ERROR unescaped backtick +//[deny_cli]~| ERROR unescaped backtick pub fn complicated_markdown() {} /// The `custom_mir` attribute tells the compiler to treat the function as being custom MIR. This @@ -185,13 +190,13 @@ pub fn complicated_markdown() {} /// another function. The `dialect` and `phase` parameters indicate which [version of MIR][dialect /// docs] you are inserting here. Generally you'll want to use `#![custom_mir(dialect = "built")]` /// if you want your MIR to be modified by the full MIR pipeline, or `#![custom_mir(dialect = -//~^ ERROR unescaped backtick +//[deny_cli]~^ ERROR unescaped backtick /// "runtime", phase = "optimized")] if you don't. pub mod mir {} pub mod rustc { /// Constructs a `TyKind::Error` type and registers a `span_delayed_bug` with the given `msg to - //~^ ERROR unescaped backtick + //[deny_cli]~^ ERROR unescaped backtick /// ensure it gets used. pub fn ty_error_with_message() {} @@ -200,13 +205,13 @@ pub mod rustc { /// if we parsed no predicates (e.g. `struct Foo where {} /// This allows us to accurately pretty-print /// in `nt_to_tokenstream` - //~^ ERROR unescaped backtick + //[deny_cli]~^ ERROR unescaped backtick pub has_where_token: bool, } /// A symbol is an interned or gensymed string. The use of `newtype_index!` means /// that `Option` only takes up 4 bytes, because `newtype_index! reserves - //~^ ERROR unescaped backtick + //[deny_cli]~^ ERROR unescaped backtick /// the last 256 values for tagging purposes. pub struct Symbol(); @@ -214,12 +219,12 @@ pub mod rustc { /// readable code. Instead of `OpenOptions::new().read(true).open("foo.txt")` /// you can write `File::with_options().read(true).open("foo.txt"). This /// also avoids the need to import `OpenOptions`. - //~^ ERROR unescaped backtick + //[deny_cli]~^ ERROR unescaped backtick pub fn with_options() {} /// Subtracts `set from `row`. `set` can be either `BitSet` or /// `ChunkedBitSet`. Has no effect if `row` does not exist. - //~^ ERROR unescaped backtick + //[deny_cli]~^ ERROR unescaped backtick /// /// Returns true if the row was changed. pub fn subtract_row() {} @@ -230,29 +235,29 @@ pub mod rustc { //! perturb the reuse results. //! //! `#![rustc_expected_cgu_reuse(module="spike", cfg="rpass2", kind="post-lto")] - //~^ ERROR unescaped backtick + //[deny_cli]~^ ERROR unescaped backtick //! allows for doing a more fine-grained check to see if pre- or post-lto data //! was re-used. /// `cfg=... - //~^ ERROR unescaped backtick + //[deny_cli]~^ ERROR unescaped backtick pub fn foo() {} /// `cfg=... and not `#[cfg_attr]` - //~^ ERROR unescaped backtick + //[deny_cli]~^ ERROR unescaped backtick pub fn bar() {} } /// Conceptually, this is like a `Vec>`. But the number of /// RWU`s can get very large, so it uses a more compact representation. - //~^ ERROR unescaped backtick + //[deny_cli]~^ ERROR unescaped backtick pub struct RWUTable {} /// Like [Self::canonicalize_query], but preserves distinct universes. For /// example, canonicalizing `&'?0: Trait<'?1>`, where `'?0` is in `U1` and /// `'?1` is in `U3` would be canonicalized to have ?0` in `U1` and `'?1` /// in `U2`. - //~^ ERROR unescaped backtick + //[deny_cli]~^ ERROR unescaped backtick /// /// This is used for Chalk integration. pub fn canonicalize_query_preserving_universes() {} @@ -269,7 +274,7 @@ pub mod rustc { /// ` as Trait>::Foo`. We are supposed to report /// an error for this obligation, but we legitimately should not, /// because it contains `[type error]`. Yuck! (See issue #29857 for - //~^ ERROR unescaped backtick + //[deny_cli]~^ ERROR unescaped backtick /// one case where this arose.) pub fn normalize_to_error() {} @@ -279,7 +284,7 @@ pub mod rustc { /// encountered a problem (later on) with `A: AutoTrait. So we /// currently set a flag on the stack node for `B: AutoTrait` (as /// well as the second instance of `A: AutoTrait`) to suppress - //~^ ERROR unescaped backtick + //[deny_cli]~^ ERROR unescaped backtick /// caching. pub struct TraitObligationStack; @@ -289,7 +294,7 @@ pub mod rustc { /// actually stricter than necessary: ideally, we'd support bounds /// like `for<'a: 'b`>` that might then allow us to approximate /// `'a` with `'b` and not `'static`. But it will have to do for - //~^ ERROR unescaped backtick + //[deny_cli]~^ ERROR unescaped backtick /// now. pub fn add_incompatible_universe(){} } @@ -298,20 +303,20 @@ pub mod rustc { /// which returns an `Option`. If all [`Dispatch`] clones that point /// at the `Subscriber` have been dropped, [`WeakDispatch::upgrade`] will return /// `None`. Otherwise, it will return `Some(Dispatch)`. -//~^ ERROR unescaped backtick +//[deny_cli]~^ ERROR unescaped backtick /// /// Returns some reference to this `[`Subscriber`] value if it is of type `T`, /// or `None` if it isn't. -//~^ ERROR unescaped backtick +//[deny_cli]~^ ERROR unescaped backtick /// /// Called before the filtered [`Layer]'s [`on_event`], to determine if /// `on_event` should be called. -//~^ ERROR unescaped backtick +//[deny_cli]~^ ERROR unescaped backtick /// /// Therefore, if the `Filter will change the value returned by this /// method, it is responsible for ensuring that /// [`rebuild_interest_cache`][rebuild] is called after the value of the max -//~^ ERROR unescaped backtick +//[deny_cli]~^ ERROR unescaped backtick /// level changes. pub mod tracing {} @@ -321,10 +326,10 @@ macro_rules! id { id! { /// The Subscriber` may be accessed by calling [`WeakDispatch::upgrade`], - //~^ ERROR unescaped backtick - //~| ERROR unescaped backtick - //~| ERROR unescaped backtick - //~| ERROR unescaped backtick + //[deny_cli]~^ ERROR unescaped backtick + //[deny_cli]~| ERROR unescaped backtick + //[deny_cli]~| ERROR unescaped backtick + //[deny_cli]~| ERROR unescaped backtick /// which returns an `Option`. If all [`Dispatch`] clones that point /// at the `Subscriber` have been dropped, [`WeakDispatch::upgrade`] will return /// `None`. Otherwise, it will return `Some(Dispatch)`. @@ -347,7 +352,7 @@ pub mod trillium_server_common { /// One-indexed, because the first CloneCounter is included. If you don't /// want the original to count, construct a [``CloneCounterObserver`] /// instead and use [`CloneCounterObserver::counter`] to increment. - //~^ ERROR unescaped backtick + //[deny_cli]~^ ERROR unescaped backtick pub struct CloneCounter; /// This is used by the above. diff --git a/tests/ui/eii/default/auxiliary/decl_with_default.rs b/tests/ui/eii/default/auxiliary/decl_with_default.rs index 8d962c19c94d9..ba855cb854afd 100644 --- a/tests/ui/eii/default/auxiliary/decl_with_default.rs +++ b/tests/ui/eii/default/auxiliary/decl_with_default.rs @@ -1,4 +1,3 @@ -//@ no-prefer-dynamic #![crate_type = "rlib"] #![feature(extern_item_impls)] diff --git a/tests/ui/eii/default/auxiliary/decl_with_default_panics.rs b/tests/ui/eii/default/auxiliary/decl_with_default_panics.rs index 14778a40cde4a..3867bfb85c9fe 100644 --- a/tests/ui/eii/default/auxiliary/decl_with_default_panics.rs +++ b/tests/ui/eii/default/auxiliary/decl_with_default_panics.rs @@ -1,4 +1,3 @@ -//@ no-prefer-dynamic //@ needs-unwind //@ exec-env:RUST_BACKTRACE=1 #![crate_type = "rlib"] diff --git a/tests/ui/eii/default/auxiliary/impl1.rs b/tests/ui/eii/default/auxiliary/impl1.rs index 3510ea1eb3f27..84edf24e12816 100644 --- a/tests/ui/eii/default/auxiliary/impl1.rs +++ b/tests/ui/eii/default/auxiliary/impl1.rs @@ -1,4 +1,3 @@ -//@ no-prefer-dynamic //@ aux-build: decl_with_default.rs #![crate_type = "rlib"] #![feature(extern_item_impls)] diff --git a/tests/ui/eii/default/call_default.rs b/tests/ui/eii/default/call_default.rs index 8806c7fa7d8ce..07b2a650d3c42 100644 --- a/tests/ui/eii/default/call_default.rs +++ b/tests/ui/eii/default/call_default.rs @@ -1,4 +1,3 @@ -//@ no-prefer-dynamic //@ aux-build: decl_with_default.rs //@ run-pass //@ check-run-results diff --git a/tests/ui/eii/default/call_default_panics.rs b/tests/ui/eii/default/call_default_panics.rs index db664e0cbcb0d..379ba8ea070b6 100644 --- a/tests/ui/eii/default/call_default_panics.rs +++ b/tests/ui/eii/default/call_default_panics.rs @@ -1,4 +1,3 @@ -//@ no-prefer-dynamic //@ aux-build: decl_with_default_panics.rs //@ edition: 2021 //@ run-pass diff --git a/tests/ui/eii/default/call_impl.rs b/tests/ui/eii/default/call_impl.rs index 1a972774beaeb..4553427b8c799 100644 --- a/tests/ui/eii/default/call_impl.rs +++ b/tests/ui/eii/default/call_impl.rs @@ -1,4 +1,3 @@ -//@ no-prefer-dynamic //@ aux-build: decl_with_default.rs //@ aux-build: impl1.rs //@ run-pass diff --git a/tests/ui/eii/duplicate/auxiliary/impl1.rs b/tests/ui/eii/duplicate/auxiliary/impl1.rs index e99932c69b90b..ffa2cd79818cc 100644 --- a/tests/ui/eii/duplicate/auxiliary/impl1.rs +++ b/tests/ui/eii/duplicate/auxiliary/impl1.rs @@ -1,4 +1,3 @@ -//@ no-prefer-dynamic //@ aux-build: decl.rs #![crate_type = "rlib"] #![feature(extern_item_impls)] diff --git a/tests/ui/eii/duplicate/auxiliary/impl2.rs b/tests/ui/eii/duplicate/auxiliary/impl2.rs index 3a09c824b8292..592234f53fd40 100644 --- a/tests/ui/eii/duplicate/auxiliary/impl2.rs +++ b/tests/ui/eii/duplicate/auxiliary/impl2.rs @@ -1,4 +1,3 @@ -//@ no-prefer-dynamic //@ aux-build: decl.rs #![crate_type = "rlib"] #![feature(extern_item_impls)] diff --git a/tests/ui/eii/duplicate/auxiliary/impl3.rs b/tests/ui/eii/duplicate/auxiliary/impl3.rs index 09bdd8509da29..5e9fdaba0bb6b 100644 --- a/tests/ui/eii/duplicate/auxiliary/impl3.rs +++ b/tests/ui/eii/duplicate/auxiliary/impl3.rs @@ -1,4 +1,3 @@ -//@ no-prefer-dynamic //@ aux-build: decl.rs #![crate_type = "rlib"] #![feature(extern_item_impls)] diff --git a/tests/ui/eii/duplicate/auxiliary/impl4.rs b/tests/ui/eii/duplicate/auxiliary/impl4.rs index fd68a83de1252..068cc18d78e6a 100644 --- a/tests/ui/eii/duplicate/auxiliary/impl4.rs +++ b/tests/ui/eii/duplicate/auxiliary/impl4.rs @@ -1,4 +1,3 @@ -//@ no-prefer-dynamic //@ aux-build: decl.rs #![crate_type = "rlib"] #![feature(extern_item_impls)] diff --git a/tests/ui/eii/duplicate/duplicate1.rs b/tests/ui/eii/duplicate/duplicate1.rs index 2128cac70eb30..3d770232af50f 100644 --- a/tests/ui/eii/duplicate/duplicate1.rs +++ b/tests/ui/eii/duplicate/duplicate1.rs @@ -1,4 +1,3 @@ -//@ no-prefer-dynamic //@ aux-build: impl1.rs //@ aux-build: impl2.rs //@ ignore-backends: gcc diff --git a/tests/ui/eii/duplicate/duplicate1.stderr b/tests/ui/eii/duplicate/duplicate1.stderr index 54cc141f88694..f691043e6a597 100644 --- a/tests/ui/eii/duplicate/duplicate1.stderr +++ b/tests/ui/eii/duplicate/duplicate1.stderr @@ -1,10 +1,10 @@ error: multiple implementations of `#[eii1]` - --> $DIR/auxiliary/impl1.rs:10:1 + --> $DIR/auxiliary/impl1.rs:9:1 | LL | fn other(x: u64) { | ^^^^^^^^^^^^^^^^ first implemented here in crate `impl1` | - ::: $DIR/auxiliary/impl2.rs:10:1 + ::: $DIR/auxiliary/impl2.rs:9:1 | LL | fn other(x: u64) { | ---------------- also implemented here in crate `impl2` diff --git a/tests/ui/eii/duplicate/duplicate2.rs b/tests/ui/eii/duplicate/duplicate2.rs index b0f1b1266e4ca..4311969ed8894 100644 --- a/tests/ui/eii/duplicate/duplicate2.rs +++ b/tests/ui/eii/duplicate/duplicate2.rs @@ -1,4 +1,3 @@ -//@ no-prefer-dynamic //@ aux-build: impl1.rs //@ aux-build: impl2.rs //@ aux-build: impl3.rs diff --git a/tests/ui/eii/duplicate/duplicate2.stderr b/tests/ui/eii/duplicate/duplicate2.stderr index 033e43c8b2fbd..492d2b3e6004b 100644 --- a/tests/ui/eii/duplicate/duplicate2.stderr +++ b/tests/ui/eii/duplicate/duplicate2.stderr @@ -1,10 +1,10 @@ error: multiple implementations of `#[eii1]` - --> $DIR/auxiliary/impl1.rs:10:1 + --> $DIR/auxiliary/impl1.rs:9:1 | LL | fn other(x: u64) { | ^^^^^^^^^^^^^^^^ first implemented here in crate `impl1` | - ::: $DIR/auxiliary/impl2.rs:10:1 + ::: $DIR/auxiliary/impl2.rs:9:1 | LL | fn other(x: u64) { | ---------------- also implemented here in crate `impl2` diff --git a/tests/ui/eii/duplicate/duplicate3.rs b/tests/ui/eii/duplicate/duplicate3.rs index 4b2b0fc111b58..4504ba30c246e 100644 --- a/tests/ui/eii/duplicate/duplicate3.rs +++ b/tests/ui/eii/duplicate/duplicate3.rs @@ -1,4 +1,3 @@ -//@ no-prefer-dynamic //@ aux-build: impl1.rs //@ aux-build: impl2.rs //@ aux-build: impl3.rs diff --git a/tests/ui/eii/duplicate/duplicate3.stderr b/tests/ui/eii/duplicate/duplicate3.stderr index 801d40e69c552..f3ca087a27325 100644 --- a/tests/ui/eii/duplicate/duplicate3.stderr +++ b/tests/ui/eii/duplicate/duplicate3.stderr @@ -1,10 +1,10 @@ error: multiple implementations of `#[eii1]` - --> $DIR/auxiliary/impl1.rs:10:1 + --> $DIR/auxiliary/impl1.rs:9:1 | LL | fn other(x: u64) { | ^^^^^^^^^^^^^^^^ first implemented here in crate `impl1` | - ::: $DIR/auxiliary/impl2.rs:10:1 + ::: $DIR/auxiliary/impl2.rs:9:1 | LL | fn other(x: u64) { | ---------------- also implemented here in crate `impl2` diff --git a/tests/ui/eii/static/auxiliary/cross_crate_def.rs b/tests/ui/eii/static/auxiliary/cross_crate_def.rs index 70933440a62be..56d3f6fcdc557 100644 --- a/tests/ui/eii/static/auxiliary/cross_crate_def.rs +++ b/tests/ui/eii/static/auxiliary/cross_crate_def.rs @@ -1,4 +1,3 @@ -//@ no-prefer-dynamic #![crate_type = "rlib"] #![feature(extern_item_impls)] diff --git a/tests/ui/imports/unused-import-in-macro-expansion-rustfix.fixed b/tests/ui/imports/unused-import-in-macro-expansion-rustfix.fixed new file mode 100644 index 0000000000000..3b7c8051122fc --- /dev/null +++ b/tests/ui/imports/unused-import-in-macro-expansion-rustfix.fixed @@ -0,0 +1,23 @@ +// Regression test for +//@ edition:2021 +//@ run-rustfix +//@ rustfix-only-machine-applicable +//@ check-pass + +mod m { + macro_rules! define_new_macro { + ($name:ident) => { + macro_rules! $name { + () => {}; + } + pub(crate) use $name; + }; + } + + define_new_macro!(item_used); + define_new_macro!(item_unused); +} + +fn main() { + m::item_used!(); +} diff --git a/tests/ui/imports/unused-import-in-macro-expansion-rustfix.rs b/tests/ui/imports/unused-import-in-macro-expansion-rustfix.rs new file mode 100644 index 0000000000000..3b7c8051122fc --- /dev/null +++ b/tests/ui/imports/unused-import-in-macro-expansion-rustfix.rs @@ -0,0 +1,23 @@ +// Regression test for +//@ edition:2021 +//@ run-rustfix +//@ rustfix-only-machine-applicable +//@ check-pass + +mod m { + macro_rules! define_new_macro { + ($name:ident) => { + macro_rules! $name { + () => {}; + } + pub(crate) use $name; + }; + } + + define_new_macro!(item_used); + define_new_macro!(item_unused); +} + +fn main() { + m::item_used!(); +} diff --git a/tests/ui/inference/ambiguous-cast-suggestion-issue-41261.rs b/tests/ui/inference/ambiguous-cast-suggestion-issue-41261.rs new file mode 100644 index 0000000000000..b1c4dfb9f1003 --- /dev/null +++ b/tests/ui/inference/ambiguous-cast-suggestion-issue-41261.rs @@ -0,0 +1,19 @@ +//@ edition: 2021 + +// Regression test for issue #41261. +// The diagnostic should point at the ambiguous cast, not at the later method call. + +struct S { + v: Vec<(u32, Vec)>, +} + +impl S { + pub fn remove(&mut self, i: u32) -> Option> { + self.v.get_mut(i as _).map(|&mut (_, ref mut v2)| { + //~^ ERROR type annotations needed + v2.drain(..) + }) + } +} + +fn main() {} diff --git a/tests/ui/inference/ambiguous-cast-suggestion-issue-41261.stderr b/tests/ui/inference/ambiguous-cast-suggestion-issue-41261.stderr new file mode 100644 index 0000000000000..da66f6237203e --- /dev/null +++ b/tests/ui/inference/ambiguous-cast-suggestion-issue-41261.stderr @@ -0,0 +1,17 @@ +error[E0282]: type annotations needed for `&mut (_, _)` + --> $DIR/ambiguous-cast-suggestion-issue-41261.rs:12:37 + | +LL | self.v.get_mut(i as _).map(|&mut (_, ref mut v2)| { + | ^^^^^^^^^^^^^^^^^^^^ +LL | +LL | v2.drain(..) + | -- type must be known at this point + | +help: consider giving this closure parameter an explicit type, where the placeholders `_` are specified + | +LL | self.v.get_mut(i as _).map(|&mut (_, ref mut v2): &mut (_, _)| { + | +++++++++++++ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0282`. diff --git a/tests/ui/lint/static-mut-refs-interior-mutability-no-sugg.rs b/tests/ui/lint/static-mut-refs-interior-mutability-no-sugg.rs new file mode 100644 index 0000000000000..82c6b55a7623a --- /dev/null +++ b/tests/ui/lint/static-mut-refs-interior-mutability-no-sugg.rs @@ -0,0 +1,18 @@ +//@ edition:2024 +// Ensure that we don't make structured suggestions for interior mutability note +// when span is not available. + +use std::sync::Mutex; + +macro_rules! declare_mutex { + () => { + static mut MACRO_MUTEX: Mutex = Mutex::new(false); + }; +} + +declare_mutex!(); + +fn main() { + let _lock = unsafe { MACRO_MUTEX.lock().unwrap() }; + //~^ ERROR creating a shared reference to mutable static [static_mut_refs] +} diff --git a/tests/ui/lint/static-mut-refs-interior-mutability-no-sugg.stderr b/tests/ui/lint/static-mut-refs-interior-mutability-no-sugg.stderr new file mode 100644 index 0000000000000..5ce69e1a14d83 --- /dev/null +++ b/tests/ui/lint/static-mut-refs-interior-mutability-no-sugg.stderr @@ -0,0 +1,13 @@ +error: creating a shared reference to mutable static + --> $DIR/static-mut-refs-interior-mutability-no-sugg.rs:16:26 + | +LL | let _lock = unsafe { MACRO_MUTEX.lock().unwrap() }; + | ^^^^^^^^^^^^^^^^^^ shared reference to mutable static + | + = note: shared references to mutable statics are dangerous; it's undefined behavior if the static is mutated or if a mutable reference is created for it while the shared reference lives + = help: use a type that relies on "interior mutability" instead; to read more on this, visit + = note: for more information, see + = note: `#[deny(static_mut_refs)]` (part of `#[deny(rust_2024_compatibility)]`) on by default + +error: aborting due to 1 previous error + diff --git a/tests/ui/lint/static-mut-refs-interior-mutability.fixed b/tests/ui/lint/static-mut-refs-interior-mutability.fixed new file mode 100644 index 0000000000000..d5b096119cce1 --- /dev/null +++ b/tests/ui/lint/static-mut-refs-interior-mutability.fixed @@ -0,0 +1,13 @@ +//@ edition:2024 +//@ run-rustfix + +#![allow(unused_unsafe)] + +use std::sync::Mutex; + +static STDINOUT_MUTEX: Mutex = Mutex::new(false); + +fn main() { + let _lock = unsafe { STDINOUT_MUTEX.lock().unwrap() }; + //~^ ERROR creating a shared reference to mutable static [static_mut_refs] +} diff --git a/tests/ui/lint/static-mut-refs-interior-mutability.rs b/tests/ui/lint/static-mut-refs-interior-mutability.rs new file mode 100644 index 0000000000000..f5d0fca5b45d7 --- /dev/null +++ b/tests/ui/lint/static-mut-refs-interior-mutability.rs @@ -0,0 +1,13 @@ +//@ edition:2024 +//@ run-rustfix + +#![allow(unused_unsafe)] + +use std::sync::Mutex; + +static mut STDINOUT_MUTEX: Mutex = Mutex::new(false); + +fn main() { + let _lock = unsafe { STDINOUT_MUTEX.lock().unwrap() }; + //~^ ERROR creating a shared reference to mutable static [static_mut_refs] +} diff --git a/tests/ui/lint/static-mut-refs-interior-mutability.stderr b/tests/ui/lint/static-mut-refs-interior-mutability.stderr new file mode 100644 index 0000000000000..29ab5a5c404de --- /dev/null +++ b/tests/ui/lint/static-mut-refs-interior-mutability.stderr @@ -0,0 +1,17 @@ +error: creating a shared reference to mutable static + --> $DIR/static-mut-refs-interior-mutability.rs:11:26 + | +LL | let _lock = unsafe { STDINOUT_MUTEX.lock().unwrap() }; + | ^^^^^^^^^^^^^^^^^^^^^ shared reference to mutable static + | + = note: shared references to mutable statics are dangerous; it's undefined behavior if the static is mutated or if a mutable reference is created for it while the shared reference lives + = note: for more information, see + = note: `#[deny(static_mut_refs)]` (part of `#[deny(rust_2024_compatibility)]`) on by default +help: this type already provides "interior mutability", so its binding doesn't need to be declared as mutable + | +LL - static mut STDINOUT_MUTEX: Mutex = Mutex::new(false); +LL + static STDINOUT_MUTEX: Mutex = Mutex::new(false); + | + +error: aborting due to 1 previous error + diff --git a/tests/ui/parser/byte-literals.stderr b/tests/ui/parser/byte-literals.stderr index 1c89e8e2864b6..4df5f764cfe85 100644 --- a/tests/ui/parser/byte-literals.stderr +++ b/tests/ui/parser/byte-literals.stderr @@ -5,6 +5,11 @@ LL | static FOO: u8 = b'\f'; | ^ unknown byte escape | = help: for more information, visit +help: if you meant to write a form feed, use a hex escape + | +LL - static FOO: u8 = b'\f'; +LL + static FOO: u8 = b'\x0C'; + | error: unknown byte escape: `f` --> $DIR/byte-literals.rs:6:8 @@ -13,6 +18,11 @@ LL | b'\f'; | ^ unknown byte escape | = help: for more information, visit +help: if you meant to write a form feed, use a hex escape + | +LL - b'\f'; +LL + b'\x0C'; + | error: invalid character in numeric character escape: `Z` --> $DIR/byte-literals.rs:7:10 diff --git a/tests/ui/parser/byte-string-literals.stderr b/tests/ui/parser/byte-string-literals.stderr index 3e589258d4132..d036fae68ea1f 100644 --- a/tests/ui/parser/byte-string-literals.stderr +++ b/tests/ui/parser/byte-string-literals.stderr @@ -5,6 +5,11 @@ LL | static FOO: &'static [u8] = b"\f"; | ^ unknown byte escape | = help: for more information, visit +help: if you meant to write a form feed, use a hex escape + | +LL - static FOO: &'static [u8] = b"\f"; +LL + static FOO: &'static [u8] = b"\x0C"; + | error: unknown byte escape: `f` --> $DIR/byte-string-literals.rs:4:8 @@ -13,6 +18,11 @@ LL | b"\f"; | ^ unknown byte escape | = help: for more information, visit +help: if you meant to write a form feed, use a hex escape + | +LL - b"\f"; +LL + b"\x0C"; + | error: invalid character in numeric character escape: `Z` --> $DIR/byte-string-literals.rs:5:10 diff --git a/tests/ui/parser/foreign-escapes.rs b/tests/ui/parser/foreign-escapes.rs new file mode 100644 index 0000000000000..d802f858f8e31 --- /dev/null +++ b/tests/ui/parser/foreign-escapes.rs @@ -0,0 +1,25 @@ +// Specified by both C and Rust +pub const SINGLE_QUOTE: char = '\''; +pub const DOUBLE_QUOTE: char = '\"'; +pub const BACKSLASH: char = '\\'; +pub const NEWLINE: char = '\n'; +pub const CARRIAGE_RETURN: char = '\r'; +pub const HORIZONTAL_TAB: char = '\t'; +pub const NULL: char = '\0'; + +// Specified by C, but not Rust +pub const QUESTION_MARK: char = '\?'; //~ ERROR unknown character escape +pub const AUDIBLE_BELL: char = '\a'; //~ ERROR unknown character escape +pub const BACKSPACE: char = '\b'; //~ ERROR unknown character escape +pub const FORM_FEED: char = '\f'; //~ ERROR unknown character escape +pub const VERTICAL_TAB: char = '\v'; //~ ERROR unknown character escape +pub const OCTAL: char = '\1'; //~ ERROR unknown character escape +pub const OCTAL_TWO_DIGIT: char = '\12'; //~ ERROR unknown character escape +pub const OCTAL_THREE_DIGIT: char = '\12'; //~ ERROR unknown character escape +pub const OCTAL_OUT_OF_RANGE: char = '\9'; //~ ERROR unknown character escape + +// Not specified by C, but recognized by GCC as an extension. +// Used for ANSI escape sequences in terminal emulators. +pub const ESCAPE: char = '\e'; //~ ERROR unknown character escape + +fn main() {} diff --git a/tests/ui/parser/foreign-escapes.stderr b/tests/ui/parser/foreign-escapes.stderr new file mode 100644 index 0000000000000..619d7d1e6e8b7 --- /dev/null +++ b/tests/ui/parser/foreign-escapes.stderr @@ -0,0 +1,165 @@ +error: unknown character escape: `?` + --> $DIR/foreign-escapes.rs:11:35 + | +LL | pub const QUESTION_MARK: char = '\?'; + | ^ unknown character escape + | + = help: for more information, visit +help: if you meant to write a literal backslash (perhaps escaping in a regular expression), consider a raw string literal + | +LL - pub const QUESTION_MARK: char = '\?'; +LL + pub const QUESTION_MARK: char = r"\?"; + | +help: if you meant to write a literal question mark, don't escape the character + | +LL - pub const QUESTION_MARK: char = '\?'; +LL + pub const QUESTION_MARK: char = '?'; + | + +error: unknown character escape: `a` + --> $DIR/foreign-escapes.rs:12:34 + | +LL | pub const AUDIBLE_BELL: char = '\a'; + | ^ unknown character escape + | + = help: for more information, visit +help: if you meant to write a literal backslash (perhaps escaping in a regular expression), consider a raw string literal + | +LL - pub const AUDIBLE_BELL: char = '\a'; +LL + pub const AUDIBLE_BELL: char = r"\a"; + | +help: if you meant to write an audible bell, use a hex escape + | +LL - pub const AUDIBLE_BELL: char = '\a'; +LL + pub const AUDIBLE_BELL: char = '\x07'; + | + +error: unknown character escape: `b` + --> $DIR/foreign-escapes.rs:13:31 + | +LL | pub const BACKSPACE: char = '\b'; + | ^ unknown character escape + | + = help: for more information, visit +help: if you meant to write a literal backslash (perhaps escaping in a regular expression), consider a raw string literal + | +LL - pub const BACKSPACE: char = '\b'; +LL + pub const BACKSPACE: char = r"\b"; + | +help: if you meant to write a backspace, use a hex escape + | +LL - pub const BACKSPACE: char = '\b'; +LL + pub const BACKSPACE: char = '\x08'; + | + +error: unknown character escape: `f` + --> $DIR/foreign-escapes.rs:14:31 + | +LL | pub const FORM_FEED: char = '\f'; + | ^ unknown character escape + | + = help: for more information, visit +help: if you meant to write a literal backslash (perhaps escaping in a regular expression), consider a raw string literal + | +LL - pub const FORM_FEED: char = '\f'; +LL + pub const FORM_FEED: char = r"\f"; + | +help: if you meant to write a form feed, use a hex escape + | +LL - pub const FORM_FEED: char = '\f'; +LL + pub const FORM_FEED: char = '\x0C'; + | + +error: unknown character escape: `v` + --> $DIR/foreign-escapes.rs:15:34 + | +LL | pub const VERTICAL_TAB: char = '\v'; + | ^ unknown character escape + | + = help: for more information, visit +help: if you meant to write a literal backslash (perhaps escaping in a regular expression), consider a raw string literal + | +LL - pub const VERTICAL_TAB: char = '\v'; +LL + pub const VERTICAL_TAB: char = r"\v"; + | +help: if you meant to write a vertical tab, use a hex escape + | +LL - pub const VERTICAL_TAB: char = '\v'; +LL + pub const VERTICAL_TAB: char = '\x0B'; + | + +error: unknown character escape: `1` + --> $DIR/foreign-escapes.rs:16:27 + | +LL | pub const OCTAL: char = '\1'; + | ^ unknown character escape + | + = help: for more information, visit + = help: if you meant to write an ASCII control code, use a `\xNN` hex escape +help: if you meant to write a literal backslash (perhaps escaping in a regular expression), consider a raw string literal + | +LL - pub const OCTAL: char = '\1'; +LL + pub const OCTAL: char = r"\1"; + | + +error: unknown character escape: `1` + --> $DIR/foreign-escapes.rs:17:37 + | +LL | pub const OCTAL_TWO_DIGIT: char = '\12'; + | ^ unknown character escape + | + = help: for more information, visit + = help: if you meant to write an ASCII control code, use a `\xNN` hex escape +help: if you meant to write a literal backslash (perhaps escaping in a regular expression), consider a raw string literal + | +LL - pub const OCTAL_TWO_DIGIT: char = '\12'; +LL + pub const OCTAL_TWO_DIGIT: char = r"\12"; + | + +error: unknown character escape: `1` + --> $DIR/foreign-escapes.rs:18:39 + | +LL | pub const OCTAL_THREE_DIGIT: char = '\12'; + | ^ unknown character escape + | + = help: for more information, visit + = help: if you meant to write an ASCII control code, use a `\xNN` hex escape +help: if you meant to write a literal backslash (perhaps escaping in a regular expression), consider a raw string literal + | +LL - pub const OCTAL_THREE_DIGIT: char = '\12'; +LL + pub const OCTAL_THREE_DIGIT: char = r"\12"; + | + +error: unknown character escape: `9` + --> $DIR/foreign-escapes.rs:19:40 + | +LL | pub const OCTAL_OUT_OF_RANGE: char = '\9'; + | ^ unknown character escape + | + = help: for more information, visit +help: if you meant to write a literal backslash (perhaps escaping in a regular expression), consider a raw string literal + | +LL - pub const OCTAL_OUT_OF_RANGE: char = '\9'; +LL + pub const OCTAL_OUT_OF_RANGE: char = r"\9"; + | + +error: unknown character escape: `e` + --> $DIR/foreign-escapes.rs:23:28 + | +LL | pub const ESCAPE: char = '\e'; + | ^ unknown character escape + | + = help: for more information, visit +help: if you meant to write a literal backslash (perhaps escaping in a regular expression), consider a raw string literal + | +LL - pub const ESCAPE: char = '\e'; +LL + pub const ESCAPE: char = r"\e"; + | +help: if you meant to write an ANSI escape sequence, use a hex escape + | +LL - pub const ESCAPE: char = '\e'; +LL + pub const ESCAPE: char = '\x1B'; + | + +error: aborting due to 10 previous errors + diff --git a/tests/ui/statics/static-lazy-init-with-arena-set.stderr b/tests/ui/statics/static-lazy-init-with-arena-set.stderr index 134129f814aa7..43b244607885d 100644 --- a/tests/ui/statics/static-lazy-init-with-arena-set.stderr +++ b/tests/ui/statics/static-lazy-init-with-arena-set.stderr @@ -12,6 +12,11 @@ LL | | }); = note: shared references to mutable statics are dangerous; it's undefined behavior if the static is mutated or if a mutable reference is created for it while the shared reference lives = note: for more information, see = note: `#[warn(static_mut_refs)]` (part of `#[warn(rust_2024_compatibility)]`) on by default +help: this type already provides "interior mutability", so its binding doesn't need to be declared as mutable + | +LL - static mut ONCE: Once = Once::new(); +LL + static ONCE: Once = Once::new(); + | warning: 1 warning emitted diff --git a/tests/ui/suggestions/suggest-collect.rs b/tests/ui/suggestions/suggest-collect.rs new file mode 100644 index 0000000000000..44e8909fca20f --- /dev/null +++ b/tests/ui/suggestions/suggest-collect.rs @@ -0,0 +1,16 @@ +fn main() { + let _x: String = "hello".chars().map(|c| c); + //~^ ERROR mismatched types + //~| HELP consider using `.collect()` to convert the `Iterator` into a `String` + + let _y: Vec = vec![1, 2, 3].into_iter().map(|x| x); + //~^ ERROR mismatched types + //~| HELP consider using `.collect()` to convert the `Iterator` into a `Vec` + + let res: Result, _> = ["1", "2"].into_iter().map(|s| s.parse::()); + //~^ ERROR mismatched types + //~| HELP consider using `.collect()` to convert the `Iterator` into a `Result, _>` + let (a, b): (Vec, Vec) = vec![1, 2].into_iter().map(|x| (x, x)); + //~^ ERROR mismatched types + //~| HELP consider using `.collect()` to convert the `Iterator` into a `(Vec, Vec)` +} diff --git a/tests/ui/suggestions/suggest-collect.stderr b/tests/ui/suggestions/suggest-collect.stderr new file mode 100644 index 0000000000000..a7bca2bbcaa7b --- /dev/null +++ b/tests/ui/suggestions/suggest-collect.stderr @@ -0,0 +1,63 @@ +error[E0308]: mismatched types + --> $DIR/suggest-collect.rs:2:22 + | +LL | let _x: String = "hello".chars().map(|c| c); + | ------ ^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `String`, found `Map, {closure@...}>` + | | + | expected due to this + | + = note: expected struct `String` + found struct `Map, {closure@$DIR/suggest-collect.rs:2:42: 2:45}>` +help: consider using `.collect()` to convert the `Iterator` into a `String` + | +LL | let _x: String = "hello".chars().map(|c| c).collect(); + | ++++++++++ + +error[E0308]: mismatched types + --> $DIR/suggest-collect.rs:6:24 + | +LL | let _y: Vec = vec![1, 2, 3].into_iter().map(|x| x); + | -------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `Vec`, found `Map, {closure@...}>` + | | + | expected due to this + | + = note: expected struct `Vec` + found struct `Map, {closure@$DIR/suggest-collect.rs:6:54: 6:57}>` +help: consider using `.collect()` to convert the `Iterator` into a `Vec` + | +LL | let _y: Vec = vec![1, 2, 3].into_iter().map(|x| x).collect(); + | ++++++++++ + +error[E0308]: mismatched types + --> $DIR/suggest-collect.rs:10:36 + | +LL | let res: Result, _> = ["1", "2"].into_iter().map(|s| s.parse::()); + | ------------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `Result, _>`, found `Map, {closure@...}>` + | | + | expected due to this + | + = note: expected enum `Result, _>` + found struct `Map, {closure@$DIR/suggest-collect.rs:10:63: 10:66}>` +help: consider using `.collect()` to convert the `Iterator` into a `Result, _>` + | +LL | let res: Result, _> = ["1", "2"].into_iter().map(|s| s.parse::()).collect(); + | ++++++++++ + +error[E0308]: mismatched types + --> $DIR/suggest-collect.rs:13:40 + | +LL | let (a, b): (Vec, Vec) = vec![1, 2].into_iter().map(|x| (x, x)); + | -------------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `(Vec, Vec)`, found `Map, {closure@...}>` + | | + | expected due to this + | + = note: expected tuple `(Vec, Vec)` + found struct `Map, {closure@$DIR/suggest-collect.rs:13:67: 13:70}>` +help: consider using `.collect()` to convert the `Iterator` into a `(Vec, Vec)` + | +LL | let (a, b): (Vec, Vec) = vec![1, 2].into_iter().map(|x| (x, x)).collect(); + | ++++++++++ + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0308`.