Auto merge of #103344 - Dylan-DPC:rollup-d1rpfvx, r=Dylan-DPC

Rollup of 6 pull requests

Successful merges:

 - #102287 (Elaborate supertrait bounds when triggering `unused_must_use` on `impl Trait`)
 - #102922 (Filtering spans when emitting json)
 - #103051 (translation: doc comments with derives, subdiagnostic-less enum variants, more derive use)
 - #103111 (Account for hygiene in typo suggestions, and use them to point to shadowed names)
 - #103260 (Fixup a few tests needing asm support)
 - #103321 (rustdoc: improve appearance of source page navigation bar)

Failed merges:

 - #103209 (Diagnostic derives: allow specifying multiple alternative suggestions)

r? `@ghost`
`@rustbot` modify labels: rollup
This commit is contained in:
bors 2022-10-21 12:41:09 +00:00
commit 657f246812
55 changed files with 617 additions and 490 deletions

View File

@ -1,7 +1,4 @@
use rustc_errors::{
fluent, AddToDiagnostic, Applicability, Diagnostic, DiagnosticArgFromDisplay,
SubdiagnosticMessage,
};
use rustc_errors::DiagnosticArgFromDisplay;
use rustc_macros::{Diagnostic, Subdiagnostic};
use rustc_span::{symbol::Ident, Span, Symbol};
@ -15,25 +12,15 @@ pub struct GenericTypeWithParentheses {
pub sub: Option<UseAngleBrackets>,
}
#[derive(Clone, Copy)]
#[derive(Clone, Copy, Subdiagnostic)]
#[multipart_suggestion(ast_lowering::use_angle_brackets, applicability = "maybe-incorrect")]
pub struct UseAngleBrackets {
#[suggestion_part(code = "<")]
pub open_param: Span,
#[suggestion_part(code = ">")]
pub close_param: Span,
}
impl AddToDiagnostic for UseAngleBrackets {
fn add_to_diagnostic_with<F>(self, diag: &mut Diagnostic, _: F)
where
F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage,
{
diag.multipart_suggestion(
fluent::ast_lowering::use_angle_brackets,
vec![(self.open_param, String::from("<")), (self.close_param, String::from(">"))],
Applicability::MaybeIncorrect,
);
}
}
#[derive(Diagnostic)]
#[diag(ast_lowering::invalid_abi, code = "E0703")]
#[note]
@ -68,30 +55,20 @@ pub struct AssocTyParentheses {
pub sub: AssocTyParenthesesSub,
}
#[derive(Clone, Copy)]
#[derive(Clone, Copy, Subdiagnostic)]
pub enum AssocTyParenthesesSub {
Empty { parentheses_span: Span },
NotEmpty { open_param: Span, close_param: Span },
}
impl AddToDiagnostic for AssocTyParenthesesSub {
fn add_to_diagnostic_with<F>(self, diag: &mut Diagnostic, _: F)
where
F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage,
{
match self {
Self::Empty { parentheses_span } => diag.multipart_suggestion(
fluent::ast_lowering::remove_parentheses,
vec![(parentheses_span, String::new())],
Applicability::MaybeIncorrect,
),
Self::NotEmpty { open_param, close_param } => diag.multipart_suggestion(
fluent::ast_lowering::use_angle_brackets,
vec![(open_param, String::from("<")), (close_param, String::from(">"))],
Applicability::MaybeIncorrect,
),
};
}
#[multipart_suggestion(ast_lowering::remove_parentheses)]
Empty {
#[suggestion_part(code = "")]
parentheses_span: Span,
},
#[multipart_suggestion(ast_lowering::use_angle_brackets)]
NotEmpty {
#[suggestion_part(code = "<")]
open_param: Span,
#[suggestion_part(code = ">")]
close_param: Span,
},
}
#[derive(Diagnostic)]

View File

@ -14,6 +14,7 @@
use rustc_ast_pretty::pprust::{self, State};
use rustc_data_structures::fx::FxHashMap;
use rustc_errors::{error_code, fluent, pluralize, struct_span_err, Applicability};
use rustc_macros::Subdiagnostic;
use rustc_parse::validate_attr;
use rustc_session::lint::builtin::{
DEPRECATED_WHERE_CLAUSE_LOCATION, MISSING_ABI, PATTERNS_IN_FNS_WITHOUT_BODY,
@ -1805,15 +1806,17 @@ pub fn check_crate(session: &Session, krate: &Crate, lints: &mut LintBuffer) ->
}
/// Used to forbid `let` expressions in certain syntactic locations.
#[derive(Clone, Copy)]
#[derive(Clone, Copy, Subdiagnostic)]
pub(crate) enum ForbiddenLetReason {
/// `let` is not valid and the source environment is not important
GenericForbidden,
/// A let chain with the `||` operator
NotSupportedOr(Span),
#[note(ast_passes::not_supported_or)]
NotSupportedOr(#[primary_span] Span),
/// A let chain with invalid parentheses
///
/// For example, `let 1 = 1 && (expr && expr)` is allowed
/// but `(let 1 = 1 && (let 1 = 1 && (let 1 = 1))) && let a = 1` is not
NotSupportedParentheses(Span),
#[note(ast_passes::not_supported_parentheses)]
NotSupportedParentheses(#[primary_span] Span),
}

View File

@ -16,23 +16,6 @@ pub struct ForbiddenLet {
pub(crate) reason: ForbiddenLetReason,
}
impl AddToDiagnostic for ForbiddenLetReason {
fn add_to_diagnostic_with<F>(self, diag: &mut Diagnostic, _: F)
where
F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage,
{
match self {
Self::GenericForbidden => {}
Self::NotSupportedOr(span) => {
diag.span_note(span, fluent::ast_passes::not_supported_or);
}
Self::NotSupportedParentheses(span) => {
diag.span_note(span, fluent::ast_passes::not_supported_parentheses);
}
}
}
}
#[derive(Diagnostic)]
#[diag(ast_passes::forbidden_let_stable)]
#[note]

View File

@ -164,7 +164,9 @@ infer_region_explanation = {$pref_kind ->
}
infer_mismatched_static_lifetime = incompatible lifetime on type
infer_msl_impl_note = ...does not necessarily outlive the static lifetime introduced by the compatible `impl`
infer_does_not_outlive_static_from_impl = ...does not necessarily outlive the static lifetime introduced by the compatible `impl`
infer_implicit_static_lifetime_note = this has an implicit `'static` lifetime requirement
infer_implicit_static_lifetime_suggestion = consider relaxing the implicit `'static` requirement
infer_msl_introduces_static = introduces a `'static` lifetime requirement
infer_msl_unmet_req = because this has an unmet lifetime requirement
infer_msl_trait_note = this has an implicit `'static` lifetime requirement

View File

@ -54,3 +54,7 @@ session_crate_name_empty = crate name must not be empty
session_invalid_character_in_create_name = invalid character `{$character}` in crate name: `{$crate_name}`
session_expr_parentheses_needed = parentheses are required to parse this as an expression
session_skipping_const_checks = skipping const checks
session_unleashed_feature_help_named = skipping check for `{$gate}` feature
session_unleashed_feature_help_unnamed = skipping check that does not even have a feature gate

View File

@ -567,6 +567,11 @@ pub fn multipart_suggestion_with_style(
style: SuggestionStyle,
) -> &mut Self {
assert!(!suggestion.is_empty());
debug_assert!(
!(suggestion.iter().any(|(sp, text)| sp.is_empty() && text.is_empty())),
"Span must not be empty and have no suggestion"
);
self.push_suggestion(CodeSuggestion {
substitutions: vec![Substitution {
parts: suggestion
@ -644,6 +649,10 @@ pub fn span_suggestion_with_style(
applicability: Applicability,
style: SuggestionStyle,
) -> &mut Self {
debug_assert!(
!(sp.is_empty() && suggestion.to_string().is_empty()),
"Span must not be empty and have no suggestion"
);
self.push_suggestion(CodeSuggestion {
substitutions: vec![Substitution {
parts: vec![SubstitutionPart { snippet: suggestion.to_string(), span: sp }],
@ -684,6 +693,12 @@ pub fn span_suggestions(
) -> &mut Self {
let mut suggestions: Vec<_> = suggestions.collect();
suggestions.sort();
debug_assert!(
!(sp.is_empty() && suggestions.iter().any(|suggestion| suggestion.is_empty())),
"Span must not be empty and have no suggestion"
);
let substitutions = suggestions
.into_iter()
.map(|snippet| Substitution { parts: vec![SubstitutionPart { snippet, span: sp }] })
@ -705,8 +720,18 @@ pub fn multipart_suggestions(
suggestions: impl Iterator<Item = Vec<(Span, String)>>,
applicability: Applicability,
) -> &mut Self {
let suggestions: Vec<_> = suggestions.collect();
debug_assert!(
!(suggestions
.iter()
.flat_map(|suggs| suggs)
.any(|(sp, suggestion)| sp.is_empty() && suggestion.is_empty())),
"Span must not be empty and have no suggestion"
);
self.push_suggestion(CodeSuggestion {
substitutions: suggestions
.into_iter()
.map(|sugg| Substitution {
parts: sugg
.into_iter()

View File

@ -1,14 +1,14 @@
use crate::{
fluent, DiagnosticArgValue, DiagnosticBuilder, Handler, IntoDiagnostic, IntoDiagnosticArg,
};
use rustc_target::abi::TargetDataLayoutErrors;
use rustc_target::spec::{PanicStrategy, SplitDebuginfo, StackProtector, TargetTriple};
use rustc_ast as ast;
use rustc_ast_pretty::pprust;
use rustc_hir as hir;
use rustc_lint_defs::Level;
use rustc_span::edition::Edition;
use rustc_span::symbol::{Ident, MacroRulesNormalizedIdent, Symbol};
use rustc_target::abi::TargetDataLayoutErrors;
use rustc_target::spec::{PanicStrategy, SplitDebuginfo, StackProtector, TargetTriple};
use std::borrow::Cow;
use std::fmt;
use std::num::ParseIntError;
@ -155,6 +155,21 @@ fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> {
}
}
impl IntoDiagnosticArg for Level {
fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> {
DiagnosticArgValue::Str(Cow::Borrowed(match self {
Level::Allow => "-A",
Level::Warn => "-W",
Level::ForceWarn(_) => "--force-warn",
Level::Deny => "-D",
Level::Forbid => "-F",
Level::Expect(_) => {
unreachable!("lints with the level of `expect` should not run this code");
}
}))
}
}
impl IntoDiagnostic<'_, !> for TargetDataLayoutErrors<'_> {
fn into_diagnostic(self, handler: &Handler) -> DiagnosticBuilder<'_, !> {
let mut diag;

View File

@ -22,7 +22,7 @@
use rustc_span::hygiene::{AstPass, ExpnData, ExpnKind, LocalExpnId};
use rustc_span::source_map::SourceMap;
use rustc_span::symbol::{kw, sym, Ident, Symbol};
use rustc_span::{FileName, Span, DUMMY_SP};
use rustc_span::{BytePos, FileName, Span, DUMMY_SP};
use smallvec::{smallvec, SmallVec};
use std::default::Default;
@ -1228,8 +1228,9 @@ pub fn expr_to_spanned_string<'a>(
ast::LitKind::Str(s, style) => return Ok((s, style, expr.span)),
ast::LitKind::ByteStr(_) => {
let mut err = cx.struct_span_err(l.span, err_msg);
let span = expr.span.shrink_to_lo();
err.span_suggestion(
expr.span.shrink_to_lo(),
span.with_hi(span.lo() + BytePos(1)),
"consider removing the leading `b`",
"",
Applicability::MaybeIncorrect,

View File

@ -3051,24 +3051,27 @@ fn maybe_lint_bare_trait(&self, self_ty: &hir::Ty<'_>, in_path: bool) {
.map_or(false, |s| s.trim_end().ends_with('<'));
let is_global = poly_trait_ref.trait_ref.path.is_global();
let sugg = Vec::from_iter([
(
self_ty.span.shrink_to_lo(),
format!(
"{}dyn {}",
if needs_bracket { "<" } else { "" },
if is_global { "(" } else { "" },
),
let mut sugg = Vec::from_iter([(
self_ty.span.shrink_to_lo(),
format!(
"{}dyn {}",
if needs_bracket { "<" } else { "" },
if is_global { "(" } else { "" },
),
(
)]);
if is_global || needs_bracket {
sugg.push((
self_ty.span.shrink_to_hi(),
format!(
"{}{}",
if is_global { ")" } else { "" },
if needs_bracket { ">" } else { "" },
),
),
]);
));
}
if self_ty.span.edition() >= Edition::Edition2021 {
let msg = "trait objects must include the `dyn` keyword";
let label = "add `dyn` keyword before this trait";

View File

@ -459,47 +459,34 @@ fn add_to_diagnostic_with<F>(mut self, diag: &mut Diagnostic, _: F)
}
}
pub struct ImplNote {
pub impl_span: Option<Span>,
// FIXME(#100717): replace with a `Option<Span>` when subdiagnostic supports that
#[derive(Subdiagnostic)]
pub enum DoesNotOutliveStaticFromImpl {
#[note(infer::does_not_outlive_static_from_impl)]
Spanned {
#[primary_span]
span: Span,
},
#[note(infer::does_not_outlive_static_from_impl)]
Unspanned,
}
impl AddToDiagnostic for ImplNote {
fn add_to_diagnostic_with<F>(self, diag: &mut Diagnostic, _: F)
where
F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage,
{
match self.impl_span {
Some(span) => diag.span_note(span, fluent::infer::msl_impl_note),
None => diag.note(fluent::infer::msl_impl_note),
};
}
}
pub enum TraitSubdiag {
Note { span: Span },
Sugg { span: Span },
}
// FIXME(#100717) used in `Vec<TraitSubdiag>` so requires eager translation/list support
impl AddToDiagnostic for TraitSubdiag {
fn add_to_diagnostic_with<F>(self, diag: &mut Diagnostic, _: F)
where
F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage,
{
match self {
TraitSubdiag::Note { span } => {
diag.span_note(span, "this has an implicit `'static` lifetime requirement");
}
TraitSubdiag::Sugg { span } => {
diag.span_suggestion_verbose(
span,
"consider relaxing the implicit `'static` requirement",
" + '_".to_owned(),
rustc_errors::Applicability::MaybeIncorrect,
);
}
}
}
#[derive(Subdiagnostic)]
pub enum ImplicitStaticLifetimeSubdiag {
#[note(infer::implicit_static_lifetime_note)]
Note {
#[primary_span]
span: Span,
},
#[suggestion_verbose(
infer::implicit_static_lifetime_suggestion,
code = " + '_",
applicability = "maybe-incorrect"
)]
Sugg {
#[primary_span]
span: Span,
},
}
#[derive(Diagnostic)]
@ -512,7 +499,7 @@ pub struct MismatchedStaticLifetime<'a> {
#[subdiagnostic]
pub expl: Option<note_and_explain::RegionExplanation<'a>>,
#[subdiagnostic]
pub impl_note: ImplNote,
#[subdiagnostic]
pub trait_subdiags: Vec<TraitSubdiag>,
pub does_not_outlive_static_from_impl: DoesNotOutliveStaticFromImpl,
#[subdiagnostic(eager)]
pub implicit_static_lifetimes: Vec<ImplicitStaticLifetimeSubdiag>,
}

View File

@ -2,7 +2,9 @@
//! to hold.
use crate::errors::{note_and_explain, IntroducesStaticBecauseUnmetLifetimeReq};
use crate::errors::{ImplNote, MismatchedStaticLifetime, TraitSubdiag};
use crate::errors::{
DoesNotOutliveStaticFromImpl, ImplicitStaticLifetimeSubdiag, MismatchedStaticLifetime,
};
use crate::infer::error_reporting::nice_region_error::NiceRegionError;
use crate::infer::lexical_region_resolve::RegionResolutionError;
use crate::infer::{SubregionOrigin, TypeTrace};
@ -56,7 +58,7 @@ pub(super) fn try_report_mismatched_static_lifetime(&self) -> Option<ErrorGuaran
note_and_explain::SuffixKind::Continues,
);
let mut impl_span = None;
let mut trait_subdiags = Vec::new();
let mut implicit_static_lifetimes = Vec::new();
if let Some(impl_node) = self.tcx().hir().get_if_local(*impl_def_id) {
// If an impl is local, then maybe this isn't what they want. Try to
// be as helpful as possible with implicit lifetimes.
@ -90,10 +92,12 @@ pub(super) fn try_report_mismatched_static_lifetime(&self) -> Option<ErrorGuaran
// Otherwise, point at all implicit static lifetimes
for span in &traits {
trait_subdiags.push(TraitSubdiag::Note { span: *span });
implicit_static_lifetimes
.push(ImplicitStaticLifetimeSubdiag::Note { span: *span });
// It would be nice to put this immediately under the above note, but they get
// pushed to the end.
trait_subdiags.push(TraitSubdiag::Sugg { span: span.shrink_to_hi() });
implicit_static_lifetimes
.push(ImplicitStaticLifetimeSubdiag::Sugg { span: span.shrink_to_hi() });
}
}
} else {
@ -105,8 +109,10 @@ pub(super) fn try_report_mismatched_static_lifetime(&self) -> Option<ErrorGuaran
cause_span: cause.span,
unmet_lifetime_reqs: multispan_subdiag,
expl,
impl_note: ImplNote { impl_span },
trait_subdiags,
does_not_outlive_static_from_impl: impl_span
.map(|span| DoesNotOutliveStaticFromImpl::Spanned { span })
.unwrap_or(DoesNotOutliveStaticFromImpl::Unspanned),
implicit_static_lifetimes,
};
let reported = self.tcx().sess.emit_err(err);
Some(reported)

View File

@ -3176,6 +3176,7 @@ fn is_zero(expr: &hir::Expr<'_>) -> bool {
/// ### Example
///
/// ```rust,compile_fail
/// # #![feature(asm_experimental_arch)]
/// use std::arch::asm;
///
/// fn main() {

View File

@ -88,34 +88,13 @@ pub struct BuiltinEllpisisInclusiveRangePatterns {
pub replace: String,
}
#[derive(Subdiagnostic)]
#[note(lint::requested_level)]
pub struct RequestedLevel {
pub level: Level,
pub lint_name: String,
}
impl AddToDiagnostic for RequestedLevel {
fn add_to_diagnostic_with<F>(self, diag: &mut Diagnostic, _: F)
where
F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage,
{
diag.note(fluent::lint::requested_level);
diag.set_arg(
"level",
match self.level {
Level::Allow => "-A",
Level::Warn => "-W",
Level::ForceWarn(_) => "--force-warn",
Level::Deny => "-D",
Level::Forbid => "-F",
Level::Expect(_) => {
unreachable!("lints with the level of `expect` should not run this code");
}
},
);
diag.set_arg("lint_name", self.lint_name);
}
}
#[derive(Diagnostic)]
#[diag(lint::unsupported_group, code = "E0602")]
pub struct UnsupportedGroup {

View File

@ -7,6 +7,7 @@
use rustc_hir as hir;
use rustc_hir::def::{DefKind, Res};
use rustc_hir::def_id::DefId;
use rustc_infer::traits::util::elaborate_predicates_with_span;
use rustc_middle::ty::adjustment;
use rustc_middle::ty::{self, Ty};
use rustc_span::symbol::Symbol;
@ -204,10 +205,13 @@ fn check_must_use_ty<'tcx>(
ty::Adt(def, _) => check_must_use_def(cx, def.did(), span, descr_pre, descr_post),
ty::Opaque(def, _) => {
let mut has_emitted = false;
for &(predicate, _) in cx.tcx.explicit_item_bounds(def) {
for obligation in elaborate_predicates_with_span(
cx.tcx,
cx.tcx.explicit_item_bounds(def).iter().cloned(),
) {
// We only look at the `DefId`, so it is safe to skip the binder here.
if let ty::PredicateKind::Trait(ref poly_trait_predicate) =
predicate.kind().skip_binder()
obligation.predicate.kind().skip_binder()
{
let def_id = poly_trait_predicate.trait_ref.def_id;
let descr_pre =

View File

@ -2878,7 +2878,7 @@
/// ### Example
///
/// ```rust
/// #![feature(naked_functions)]
/// #![feature(asm_experimental_arch, naked_functions)]
///
/// use std::arch::asm;
///

View File

@ -5,7 +5,7 @@
DiagnosticDeriveError,
};
use crate::diagnostics::utils::{
build_field_mapping, report_error_if_not_applied_to_span, report_type_error,
build_field_mapping, is_doc_comment, report_error_if_not_applied_to_span, report_type_error,
should_generate_set_arg, type_is_unit, type_matches_path, FieldInfo, FieldInnerTy, FieldMap,
HasFieldMap, SetOnce, SpannedOption, SubdiagnosticKind,
};
@ -152,8 +152,12 @@ pub fn body<'s>(&mut self, variant: &VariantInfo<'s>) -> TokenStream {
fn parse_subdiag_attribute(
&self,
attr: &Attribute,
) -> Result<(SubdiagnosticKind, Path), DiagnosticDeriveError> {
let (subdiag, slug) = SubdiagnosticKind::from_attr(attr, self)?;
) -> Result<Option<(SubdiagnosticKind, Path)>, DiagnosticDeriveError> {
let Some((subdiag, slug)) = SubdiagnosticKind::from_attr(attr, self)? else {
// Some attributes aren't errors - like documentation comments - but also aren't
// subdiagnostics.
return Ok(None);
};
if let SubdiagnosticKind::MultipartSuggestion { .. } = subdiag {
let meta = attr.parse_meta()?;
@ -170,7 +174,7 @@ fn parse_subdiag_attribute(
SubdiagnosticKind::MultipartSuggestion { .. } => unreachable!(),
});
Ok((subdiag, slug))
Ok(Some((subdiag, slug)))
}
/// Establishes state in the `DiagnosticDeriveBuilder` resulting from the struct
@ -182,6 +186,11 @@ fn generate_structure_code_for_attr(
) -> Result<TokenStream, DiagnosticDeriveError> {
let diag = &self.parent.diag;
// Always allow documentation comments.
if is_doc_comment(attr) {
return Ok(quote! {});
}
let name = attr.path.segments.last().unwrap().ident.to_string();
let name = name.as_str();
let meta = attr.parse_meta()?;
@ -250,7 +259,11 @@ fn generate_structure_code_for_attr(
return Ok(tokens);
}
let (subdiag, slug) = self.parse_subdiag_attribute(attr)?;
let Some((subdiag, slug)) = self.parse_subdiag_attribute(attr)? else {
// Some attributes aren't errors - like documentation comments - but also aren't
// subdiagnostics.
return Ok(quote! {});
};
let fn_ident = format_ident!("{}", subdiag);
match subdiag {
SubdiagnosticKind::Note | SubdiagnosticKind::Help | SubdiagnosticKind::Warn => {
@ -291,6 +304,11 @@ fn generate_field_attrs_code(&mut self, binding_info: &BindingInfo<'_>) -> Token
.attrs
.iter()
.map(move |attr| {
// Always allow documentation comments.
if is_doc_comment(attr) {
return quote! {};
}
let name = attr.path.segments.last().unwrap().ident.to_string();
let needs_clone =
name == "primary_span" && matches!(inner_ty, FieldInnerTy::Vec(_));
@ -397,8 +415,11 @@ fn generate_inner_field_code(
_ => (),
}
let (subdiag, slug) = self.parse_subdiag_attribute(attr)?;
let Some((subdiag, slug)) = self.parse_subdiag_attribute(attr)? else {
// Some attributes aren't errors - like documentation comments - but also aren't
// subdiagnostics.
return Ok(quote! {});
};
let fn_ident = format_ident!("{}", subdiag);
match subdiag {
SubdiagnosticKind::Label => {

View File

@ -5,9 +5,9 @@
DiagnosticDeriveError,
};
use crate::diagnostics::utils::{
build_field_mapping, new_code_ident, report_error_if_not_applied_to_applicability,
report_error_if_not_applied_to_span, FieldInfo, FieldInnerTy, FieldMap, HasFieldMap, SetOnce,
SpannedOption, SubdiagnosticKind,
build_field_mapping, is_doc_comment, new_code_ident,
report_error_if_not_applied_to_applicability, report_error_if_not_applied_to_span, FieldInfo,
FieldInnerTy, FieldMap, HasFieldMap, SetOnce, SpannedOption, SubdiagnosticKind,
};
use proc_macro2::TokenStream;
use quote::{format_ident, quote};
@ -41,8 +41,14 @@ pub(crate) fn into_tokens<'a>(self, mut structure: Structure<'a>) -> TokenStream
}
}
if matches!(ast.data, syn::Data::Enum(..)) {
let is_enum = matches!(ast.data, syn::Data::Enum(..));
if is_enum {
for attr in &ast.attrs {
// Always allow documentation comments.
if is_doc_comment(attr) {
continue;
}
span_err(
attr.span().unwrap(),
"unsupported type attribute for subdiagnostic enum",
@ -62,6 +68,7 @@ pub(crate) fn into_tokens<'a>(self, mut structure: Structure<'a>) -> TokenStream
span_field: None,
applicability: None,
has_suggestion_parts: false,
is_enum,
};
builder.into_tokens().unwrap_or_else(|v| v.to_compile_error())
});
@ -79,7 +86,7 @@ pub(crate) fn into_tokens<'a>(self, mut structure: Structure<'a>) -> TokenStream
gen impl rustc_errors::AddToDiagnostic for @Self {
fn add_to_diagnostic_with<__F>(self, #diag: &mut rustc_errors::Diagnostic, #f: __F)
where
__F: Fn(
__F: core::ops::Fn(
&mut rustc_errors::Diagnostic,
rustc_errors::SubdiagnosticMessage
) -> rustc_errors::SubdiagnosticMessage,
@ -122,6 +129,9 @@ struct SubdiagnosticDeriveVariantBuilder<'parent, 'a> {
/// Set to true when a `#[suggestion_part]` field is encountered, used to generate an error
/// during finalization if still `false`.
has_suggestion_parts: bool,
/// Set to true when this variant is an enum variant rather than just the body of a struct.
is_enum: bool,
}
impl<'parent, 'a> HasFieldMap for SubdiagnosticDeriveVariantBuilder<'parent, 'a> {
@ -173,7 +183,11 @@ fn identify_kind(&mut self) -> Result<Vec<(SubdiagnosticKind, Path)>, Diagnostic
let mut kind_slugs = vec![];
for attr in self.variant.ast().attrs {
let (kind, slug) = SubdiagnosticKind::from_attr(attr, self)?;
let Some((kind, slug)) = SubdiagnosticKind::from_attr(attr, self)? else {
// Some attributes aren't errors - like documentation comments - but also aren't
// subdiagnostics.
continue;
};
let Some(slug) = slug else {
let name = attr.path.segments.last().unwrap().ident.to_string();
@ -227,6 +241,11 @@ fn generate_field_attr_code(
ast.attrs
.iter()
.map(|attr| {
// Always allow documentation comments.
if is_doc_comment(attr) {
return quote! {};
}
let info = FieldInfo {
binding,
ty: inner_ty.inner_type().unwrap_or(&ast.ty),
@ -290,6 +309,8 @@ fn generate_field_code_inner_path(
report_error_if_not_applied_to_span(attr, &info)?;
let binding = info.binding.binding.clone();
// FIXME(#100717): support `Option<Span>` on `primary_span` like in the
// diagnostic derive
self.span_field.set_once(binding, span);
}
@ -443,10 +464,16 @@ fn generate_field_code_inner_list(
pub fn into_tokens(&mut self) -> Result<TokenStream, DiagnosticDeriveError> {
let kind_slugs = self.identify_kind()?;
if kind_slugs.is_empty() {
throw_span_err!(
self.variant.ast().ident.span().unwrap(),
"subdiagnostic kind not specified"
);
if self.is_enum {
// It's okay for a variant to not be a subdiagnostic at all..
return Ok(quote! {});
} else {
// ..but structs should always be _something_.
throw_span_err!(
self.variant.ast().ident.span().unwrap(),
"subdiagnostic kind not specified"
);
}
};
let kind_stats: KindsStatistics = kind_slugs.iter().map(|(kind, _slug)| kind).collect();

View File

@ -477,7 +477,12 @@ impl SubdiagnosticKind {
pub(super) fn from_attr(
attr: &Attribute,
fields: &impl HasFieldMap,
) -> Result<(SubdiagnosticKind, Option<Path>), DiagnosticDeriveError> {
) -> Result<Option<(SubdiagnosticKind, Option<Path>)>, DiagnosticDeriveError> {
// Always allow documentation comments.
if is_doc_comment(attr) {
return Ok(None);
}
let span = attr.span().unwrap();
let name = attr.path.segments.last().unwrap().ident.to_string();
@ -526,7 +531,9 @@ pub(super) fn from_attr(
| SubdiagnosticKind::Note
| SubdiagnosticKind::Help
| SubdiagnosticKind::Warn
| SubdiagnosticKind::MultipartSuggestion { .. } => return Ok((kind, None)),
| SubdiagnosticKind::MultipartSuggestion { .. } => {
return Ok(Some((kind, None)));
}
SubdiagnosticKind::Suggestion { .. } => {
throw_span_err!(span, "suggestion without `code = \"...\"`")
}
@ -626,7 +633,7 @@ pub(super) fn from_attr(
| SubdiagnosticKind::MultipartSuggestion { .. } => {}
}
Ok((kind, slug))
Ok(Some((kind, slug)))
}
}
@ -654,3 +661,7 @@ fn span(&self) -> Option<proc_macro2::Span> {
pub(super) fn should_generate_set_arg(field: &Field) -> bool {
field.attrs.is_empty()
}
pub(super) fn is_doc_comment(attr: &Attribute) -> bool {
attr.path.segments.last().unwrap().ident.to_string() == "doc"
}

View File

@ -1374,9 +1374,17 @@ fn inc_dec_standalone_suggest(
kind: IncDecRecovery,
(pre_span, post_span): (Span, Span),
) -> MultiSugg {
let mut patches = Vec::new();
if !pre_span.is_empty() {
patches.push((pre_span, String::new()));
}
patches.push((post_span, format!(" {}= 1", kind.op.chr())));
MultiSugg {
msg: format!("use `{}= 1` instead", kind.op.chr()),
patches: vec![(pre_span, String::new()), (post_span, format!(" {}= 1", kind.op.chr()))],
patches,
applicability: Applicability::MachineApplicable,
}
}

View File

@ -24,7 +24,7 @@
use rustc_span::lev_distance::find_best_match_for_name;
use rustc_span::source_map::SourceMap;
use rustc_span::symbol::{kw, sym, Ident, Symbol};
use rustc_span::{BytePos, Span};
use rustc_span::{BytePos, Span, SyntaxContext};
use crate::imports::{Import, ImportKind, ImportResolver};
use crate::late::{PatternSource, Rib};
@ -47,6 +47,7 @@
/// similarly named label and whether or not it is reachable.
pub(crate) type LabelSuggestion = (Ident, bool);
#[derive(Debug)]
pub(crate) enum SuggestionTarget {
/// The target has a similar name as the name used by the programmer (probably a typo)
SimilarlyNamed,
@ -54,6 +55,7 @@ pub(crate) enum SuggestionTarget {
SingleItem,
}
#[derive(Debug)]
pub(crate) struct TypoSuggestion {
pub candidate: Symbol,
pub res: Res,
@ -482,11 +484,12 @@ pub(crate) fn add_module_candidates(
module: Module<'a>,
names: &mut Vec<TypoSuggestion>,
filter_fn: &impl Fn(Res) -> bool,
ctxt: Option<SyntaxContext>,
) {
for (key, resolution) in self.resolutions(module).borrow().iter() {
if let Some(binding) = resolution.borrow().binding {
let res = binding.res();
if filter_fn(res) {
if filter_fn(res) && ctxt.map_or(true, |ctxt| ctxt == key.ident.span.ctxt()) {
names.push(TypoSuggestion::typo_from_res(key.ident.name, res));
}
}
@ -1181,10 +1184,10 @@ fn early_lookup_typo_candidate(
Scope::CrateRoot => {
let root_ident = Ident::new(kw::PathRoot, ident.span);
let root_module = this.resolve_crate_root(root_ident);
this.add_module_candidates(root_module, &mut suggestions, filter_fn);
this.add_module_candidates(root_module, &mut suggestions, filter_fn, None);
}
Scope::Module(module, _) => {
this.add_module_candidates(module, &mut suggestions, filter_fn);
this.add_module_candidates(module, &mut suggestions, filter_fn, None);
}
Scope::MacroUsePrelude => {
suggestions.extend(this.macro_use_prelude.iter().filter_map(
@ -1221,7 +1224,7 @@ fn early_lookup_typo_candidate(
Scope::StdLibPrelude => {
if let Some(prelude) = this.prelude {
let mut tmp_suggestions = Vec::new();
this.add_module_candidates(prelude, &mut tmp_suggestions, filter_fn);
this.add_module_candidates(prelude, &mut tmp_suggestions, filter_fn, None);
suggestions.extend(
tmp_suggestions
.into_iter()

View File

@ -131,6 +131,7 @@ pub(super) enum LifetimeElisionCandidate {
}
/// Only used for diagnostics.
#[derive(Debug)]
struct BaseError {
msg: String,
fallback_label: String,
@ -140,6 +141,22 @@ struct BaseError {
suggestion: Option<(Span, &'static str, String)>,
}
#[derive(Debug)]
enum TypoCandidate {
Typo(TypoSuggestion),
Shadowed(Res),
None,
}
impl TypoCandidate {
fn to_opt_suggestion(self) -> Option<TypoSuggestion> {
match self {
TypoCandidate::Typo(sugg) => Some(sugg),
TypoCandidate::Shadowed(_) | TypoCandidate::None => None,
}
}
}
impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
fn def_span(&self, def_id: DefId) -> Option<Span> {
match def_id.krate {
@ -496,7 +513,8 @@ fn try_lookup_name_relaxed(
}
// Try Levenshtein algorithm.
let typo_sugg = self.lookup_typo_candidate(path, source.namespace(), is_expected);
let typo_sugg =
self.lookup_typo_candidate(path, source.namespace(), is_expected).to_opt_suggestion();
if path.len() == 1 && self.self_type_is_available() {
if let Some(candidate) = self.lookup_assoc_candidate(ident, ns, is_expected) {
let self_is_available = self.self_value_is_available(path[0].ident.span);
@ -660,7 +678,18 @@ fn suggest_typo(
let is_expected = &|res| source.is_expected(res);
let ident_span = path.last().map_or(span, |ident| ident.ident.span);
let typo_sugg = self.lookup_typo_candidate(path, source.namespace(), is_expected);
if let TypoCandidate::Shadowed(res) = typo_sugg
&& let Some(id) = res.opt_def_id()
&& let Some(sugg_span) = self.r.opt_span(id)
{
err.span_label(
sugg_span,
format!("you might have meant to refer to this {}", res.descr()),
);
return true;
}
let mut fallback = false;
let typo_sugg = typo_sugg.to_opt_suggestion();
if !self.r.add_typo_suggestion(err, typo_sugg, ident_span) {
fallback = true;
match self.diagnostic_metadata.current_let_binding {
@ -1581,22 +1610,38 @@ fn lookup_typo_candidate(
path: &[Segment],
ns: Namespace,
filter_fn: &impl Fn(Res) -> bool,
) -> Option<TypoSuggestion> {
) -> TypoCandidate {
let mut names = Vec::new();
if path.len() == 1 {
let mut ctxt = path.last().unwrap().ident.span.ctxt();
// Search in lexical scope.
// Walk backwards up the ribs in scope and collect candidates.
for rib in self.ribs[ns].iter().rev() {
let rib_ctxt = if rib.kind.contains_params() {
ctxt.normalize_to_macros_2_0()
} else {
ctxt.normalize_to_macro_rules()
};
// Locals and type parameters
for (ident, &res) in &rib.bindings {
if filter_fn(res) {
if filter_fn(res) && ident.span.ctxt() == rib_ctxt {
names.push(TypoSuggestion::typo_from_res(ident.name, res));
}
}
if let RibKind::MacroDefinition(def) = rib.kind && def == self.r.macro_def(ctxt) {
// If an invocation of this macro created `ident`, give up on `ident`
// and switch to `ident`'s source from the macro definition.
ctxt.remove_mark();
continue;
}
// Items in scope
if let RibKind::ModuleRibKind(module) = rib.kind {
// Items from this module
self.r.add_module_candidates(module, &mut names, &filter_fn);
self.r.add_module_candidates(module, &mut names, &filter_fn, Some(ctxt));
if let ModuleKind::Block = module.kind {
// We can see through blocks
@ -1622,7 +1667,7 @@ fn lookup_typo_candidate(
}));
if let Some(prelude) = self.r.prelude {
self.r.add_module_candidates(prelude, &mut names, &filter_fn);
self.r.add_module_candidates(prelude, &mut names, &filter_fn, None);
}
}
break;
@ -1641,7 +1686,7 @@ fn lookup_typo_candidate(
if let PathResult::Module(ModuleOrUniformRoot::Module(module)) =
self.resolve_path(mod_path, Some(TypeNS), None)
{
self.r.add_module_candidates(module, &mut names, &filter_fn);
self.r.add_module_candidates(module, &mut names, &filter_fn, None);
}
}
@ -1654,10 +1699,17 @@ fn lookup_typo_candidate(
name,
None,
) {
Some(found) if found != name => {
names.into_iter().find(|suggestion| suggestion.candidate == found)
Some(found) => {
let Some(sugg) = names.into_iter().find(|suggestion| suggestion.candidate == found) else {
return TypoCandidate::None;
};
if found == name {
TypoCandidate::Shadowed(sugg.res)
} else {
TypoCandidate::Typo(sugg)
}
}
_ => None,
_ => TypoCandidate::None,
}
}

View File

@ -1,9 +1,7 @@
use std::num::NonZeroU32;
use crate::cgu_reuse_tracker::CguReuse;
use rustc_errors::{
fluent, DiagnosticBuilder, ErrorGuaranteed, Handler, IntoDiagnostic, MultiSpan,
};
use rustc_errors::MultiSpan;
use rustc_macros::Diagnostic;
use rustc_span::{Span, Symbol};
use rustc_target::spec::{SplitDebuginfo, StackProtector, TargetTriple};
@ -148,24 +146,15 @@ pub struct CrateNameEmpty {
pub span: Option<Span>,
}
#[derive(Diagnostic)]
#[diag(session::invalid_character_in_create_name)]
pub struct InvalidCharacterInCrateName<'a> {
#[primary_span]
pub span: Option<Span>,
pub character: char,
pub crate_name: &'a str,
}
impl IntoDiagnostic<'_> for InvalidCharacterInCrateName<'_> {
fn into_diagnostic(self, sess: &Handler) -> DiagnosticBuilder<'_, ErrorGuaranteed> {
let mut diag = sess.struct_err(fluent::session::invalid_character_in_create_name);
if let Some(sp) = self.span {
diag.set_span(sp);
}
diag.set_arg("character", self.character);
diag.set_arg("crate_name", self.crate_name);
diag
}
}
#[derive(Subdiagnostic)]
#[multipart_suggestion(session::expr_parentheses_needed, applicability = "machine-applicable")]
pub struct ExprParenthesesNeeded {
@ -180,3 +169,25 @@ pub fn surrounding(s: Span) -> Self {
ExprParenthesesNeeded { left: s.shrink_to_lo(), right: s.shrink_to_hi() }
}
}
#[derive(Diagnostic)]
#[diag(session::skipping_const_checks)]
pub struct SkippingConstChecks {
#[subdiagnostic(eager)]
pub unleashed_features: Vec<UnleashedFeatureHelp>,
}
#[derive(Subdiagnostic)]
pub enum UnleashedFeatureHelp {
#[help(session::unleashed_feature_help_named)]
Named {
#[primary_span]
span: Span,
gate: Symbol,
},
#[help(session::unleashed_feature_help_unnamed)]
Unnamed {
#[primary_span]
span: Span,
},
}

View File

@ -5,9 +5,10 @@
use crate::errors::{
CannotEnableCrtStaticLinux, CannotMixAndMatchSanitizers, LinkerPluginToWindowsNotSupported,
NotCircumventFeature, ProfileSampleUseFileDoesNotExist, ProfileUseFileDoesNotExist,
SanitizerCfiEnabled, SanitizerNotSupported, SanitizersNotSupported,
SanitizerCfiEnabled, SanitizerNotSupported, SanitizersNotSupported, SkippingConstChecks,
SplitDebugInfoUnstablePlatform, StackProtectorNotSupportedForTarget,
TargetRequiresUnwindTables, UnstableVirtualFunctionElimination, UnsupportedDwarfVersion,
TargetRequiresUnwindTables, UnleashedFeatureHelp, UnstableVirtualFunctionElimination,
UnsupportedDwarfVersion,
};
use crate::parse::{add_feature_diagnostics, ParseSess};
use crate::search_paths::{PathKind, SearchPath};
@ -232,21 +233,19 @@ fn check_miri_unleashed_features(&self) {
if !unleashed_features.is_empty() {
let mut must_err = false;
// Create a diagnostic pointing at where things got unleashed.
// FIXME(#100717): needs eager translation/lists
#[allow(rustc::untranslatable_diagnostic)]
#[allow(rustc::diagnostic_outside_of_impl)]
let mut diag = self.struct_warn("skipping const checks");
for &(span, feature_gate) in unleashed_features.iter() {
// FIXME: `span_label` doesn't do anything, so we use "help" as a hack.
if let Some(gate) = feature_gate {
diag.span_help(span, &format!("skipping check for `{gate}` feature"));
// The unleash flag must *not* be used to just "hack around" feature gates.
must_err = true;
} else {
diag.span_help(span, "skipping check that does not even have a feature gate");
}
}
diag.emit();
self.emit_warning(SkippingConstChecks {
unleashed_features: unleashed_features
.iter()
.map(|(span, gate)| {
gate.map(|gate| {
must_err = true;
UnleashedFeatureHelp::Named { span: *span, gate }
})
.unwrap_or(UnleashedFeatureHelp::Unnamed { span: *span })
})
.collect(),
});
// If we should err, make sure we did.
if must_err && self.has_errors().is_none() {
// We have skipped a feature gate, and not run into other errors... reject.

View File

@ -14,7 +14,7 @@ rules.
display: none;
}
.sub {
nav.sub {
/* The search bar and related controls don't work without JS */
display: none;
}

View File

@ -365,15 +365,8 @@ img {
overflow: visible;
}
.sub-container {
display: flex;
flex-direction: row;
flex-wrap: nowrap;
}
.sub-logo-container {
display: block;
margin-right: 20px;
line-height: 0;
}
.sub-logo-container > img {
@ -696,14 +689,21 @@ pre, .rustdoc.source .example-wrap {
}
nav.sub {
position: relative;
flex-grow: 1;
margin-bottom: 25px;
flex-flow: row nowrap;
margin: 4px 0 25px 0;
display: flex;
align-items: center;
}
nav.sub form {
flex-grow: 1;
}
.source nav.sub {
margin: 0 0 15px 0;
}
.source nav.sub form {
margin-left: 32px;
}
nav.sub form { display: inline; }
a {
text-decoration: none;
@ -796,7 +796,6 @@ table,
position: relative;
display: flex;
height: 34px;
margin-top: 4px;
}
.search-results-title {
margin-top: 0;
@ -1822,10 +1821,6 @@ in storage.js
margin-left: 0px;
}
.source .content {
margin-top: 10px;
}
.anchor {
display: none !important;
}
@ -1934,6 +1929,11 @@ in storage.js
.impl-items > .item-info {
margin-left: 34px;
}
.source nav.sub {
margin: 0;
padding: 8px;
}
}
@media print {
@ -1962,12 +1962,12 @@ in storage.js
overflow-wrap: anywhere;
}
.sub-container {
nav.sub {
flex-direction: column;
}
.sub-logo-container {
align-self: center;
nav.sub form {
align-self: stretch;
}
.sub-logo-container > img {

View File

@ -102,7 +102,7 @@
</nav> {#- -#}
<main> {#- -#}
<div class="width-limiter"> {#- -#}
<div class="sub-container"> {#- -#}
<nav class="sub"> {#- -#}
{%- if page.css_class == "source" -%}
<a class="sub-logo-container" href="{{page.root_path|safe}}{{krate_with_trailing_slash|safe}}index.html"> {#- -#}
{%- if !layout.logo.is_empty() %}
@ -112,30 +112,28 @@
{%- endif -%}
</a> {#- -#}
{%- endif -%}
<nav class="sub"> {#- -#}
<form class="search-form"> {#- -#}
<div class="search-container"> {#- -#}
<span></span> {#- This empty span is a hacky fix for Safari - See #93184 -#}
<input {# -#}
class="search-input" {# -#}
name="search" {# -#}
autocomplete="off" {# -#}
spellcheck="false" {# -#}
placeholder="Click or press S to search, ? for more options…" {# -#}
type="search"> {#- -#}
<div id="help-button" title="help" tabindex="-1"> {#- -#}
<a href="{{page.root_path|safe}}help.html">?</a> {#- -#}
</div> {#- -#}
<div id="settings-menu" tabindex="-1"> {#- -#}
<a href="{{page.root_path|safe}}settings.html" title="settings"> {#- -#}
<img width="22" height="22" alt="Change settings" {# -#}
src="{{static_root_path|safe}}wheel{{page.resource_suffix}}.svg"> {#- -#}
</a> {#- -#}
</div> {#- -#}
<form class="search-form"> {#- -#}
<div class="search-container"> {#- -#}
<span></span> {#- This empty span is a hacky fix for Safari - See #93184 -#}
<input {# -#}
class="search-input" {# -#}
name="search" {# -#}
autocomplete="off" {# -#}
spellcheck="false" {# -#}
placeholder="Click or press S to search, ? for more options…" {# -#}
type="search"> {#- -#}
<div id="help-button" title="help" tabindex="-1"> {#- -#}
<a href="{{page.root_path|safe}}help.html">?</a> {#- -#}
</div> {#- -#}
</form> {#- -#}
</nav> {#- -#}
</div> {#- -#}
<div id="settings-menu" tabindex="-1"> {#- -#}
<a href="{{page.root_path|safe}}settings.html" title="settings"> {#- -#}
<img width="22" height="22" alt="Change settings" {# -#}
src="{{static_root_path|safe}}wheel{{page.resource_suffix}}.svg"> {#- -#}
</a> {#- -#}
</div> {#- -#}
</div> {#- -#}
</form> {#- -#}
</nav> {#- -#}
<section id="main-content" class="content">{{- content|safe -}}</section> {#- -#}
</div> {#- -#}
</main> {#- -#}

View File

@ -1,3 +1,4 @@
// needs-asm-support
// pp-exact
#[cfg(foo = r#"just parse this"#)]

View File

@ -1,5 +1,6 @@
include ../tools.mk
# needs-asm-support
# ignore-windows-msvc
#
# Because of Windows exception handling, the code is not necessarily any shorter.

View File

@ -5,12 +5,12 @@ wait-for: "#help"
assert-css: ("#help", {"display": "block"})
click: "#help-button > a"
assert-css: ("#help", {"display": "block"})
compare-elements-property: (".sub-container", "#help", ["offsetWidth"])
compare-elements-position: (".sub-container", "#help", ("x"))
compare-elements-property: (".sub", "#help", ["offsetWidth"])
compare-elements-position: (".sub", "#help", ("x"))
size: (500, 1000) // Try mobile next.
assert-css: ("#help", {"display": "block"})
compare-elements-property: (".sub-container", "#help", ["offsetWidth"])
compare-elements-position: (".sub-container", "#help", ("x"))
compare-elements-property: (".sub", "#help", ["offsetWidth"])
compare-elements-position: (".sub", "#help", ("x"))
// This test ensures that opening the help popover without switching pages works.
goto: "file://" + |DOC_PATH| + "/test_docs/index.html"
@ -20,5 +20,5 @@ click: "#help-button > a"
assert-css: ("#help", {"display": "block"})
click: "#help-button > a"
assert-css: ("#help", {"display": "none"})
compare-elements-property-false: (".sub-container", "#help", ["offsetWidth"])
compare-elements-position-false: (".sub-container", "#help", ("x"))
compare-elements-property-false: (".sub", "#help", ["offsetWidth"])
compare-elements-position-false: (".sub", "#help", ("x"))

View File

@ -147,7 +147,7 @@ assert-css: (
)
assert-attribute-false: ("#settings", {"class": "popover"}, CONTAINS)
compare-elements-position: (".sub-container", "#settings", ("x"))
compare-elements-position: (".sub form", "#settings", ("x"))
// We now check the display with JS disabled.
assert-false: "noscript section"

View File

@ -23,7 +23,7 @@ assert-css: (".src-line-numbers", {"text-align": "right"})
show-text: true
goto: "file://" + |DOC_PATH| + "/src/test_docs/lib.rs.html"
// We use this assert-position to know where we will click.
assert-position: ("//*[@id='1']", {"x": 104, "y": 103})
assert-position: ("//*[@id='1']", {"x": 104, "y": 112})
// We click on the left of the "1" span but still in the "src-line-number" `<pre>`.
click: (103, 103)
assert-document-property: ({"URL": "/lib.rs.html"}, ENDS_WITH)
@ -47,3 +47,25 @@ assert-property: ("#source-sidebar details:first-of-type", {"open": "false"})
// Check the spacing.
assert-css: ("#source-sidebar > details.dir-entry", {"padding-left": "4px"})
// Check the search form
assert-css: ("nav.sub", {"flex-direction": "row"})
// The goal of this test is to ensure the search input is perfectly centered
// between the top of the page and the top of the gray code block.
// To check this, we maintain the invariant:
//
// offsetTop[nav.sub form] = offsetTop[#main-content] - offsetHeight[nav.sub form] - offsetTop[nav.sub form]
assert-property: ("nav.sub form", {"offsetTop": 28, "offsetHeight": 34})
assert-property: ("#main-content", {"offsetTop": 90})
// 28 = 90 - 34 - 28
// Now do the same check on moderately-sized mobile.
size: (700, 700)
assert-css: ("nav.sub", {"flex-direction": "row"})
assert-property: ("nav.sub form", {"offsetTop": 21, "offsetHeight": 34})
assert-property: ("#main-content", {"offsetTop": 76})
// 21 = 76 - 34 - 21
// Tiny mobile gets a different display where the logo is stacked on top.
size: (450, 700)
assert-css: ("nav.sub", {"flex-direction": "column"})

View File

@ -749,3 +749,12 @@ struct SubdiagnosticEagerSuggestion {
#[subdiagnostic(eager)]
sub: SubdiagnosticWithSuggestion,
}
/// with a doc comment on the type..
#[derive(Diagnostic)]
#[diag(compiletest::example, code = "E0123")]
struct WithDocComment {
/// ..and the field
#[primary_span]
span: Span,
}

View File

@ -237,7 +237,6 @@ enum V {
var: String,
},
B {
//~^ ERROR subdiagnostic kind not specified
#[primary_span]
span: Span,
var: String,
@ -641,3 +640,24 @@ struct BJ {
span: Span,
r#type: String,
}
/// with a doc comment on the type..
#[derive(Subdiagnostic)]
#[label(parser::add_paren)]
struct BK {
/// ..and the field
#[primary_span]
span: Span,
}
/// with a doc comment on the type..
#[derive(Subdiagnostic)]
enum BL {
/// ..and the variant..
#[label(parser::add_paren)]
Foo {
/// ..and the field
#[primary_span]
span: Span,
}
}

View File

@ -134,20 +134,14 @@ error: diagnostic slug must be first argument of a `#[label(...)]` attribute
LL | #[label(code = "...")]
| ^^^^^^^^^^^^^^^^^^^^^^
error: subdiagnostic kind not specified
--> $DIR/subdiagnostic-derive.rs:239:5
|
LL | B {
| ^
error: the `#[primary_span]` attribute can only be applied to fields of type `Span` or `MultiSpan`
--> $DIR/subdiagnostic-derive.rs:251:5
--> $DIR/subdiagnostic-derive.rs:250:5
|
LL | #[primary_span]
| ^^^^^^^^^^^^^^^
error: label without `#[primary_span]` field
--> $DIR/subdiagnostic-derive.rs:248:1
--> $DIR/subdiagnostic-derive.rs:247:1
|
LL | / #[label(parser::add_paren)]
LL | |
@ -159,13 +153,13 @@ LL | | }
| |_^
error: `#[applicability]` is only valid on suggestions
--> $DIR/subdiagnostic-derive.rs:261:5
--> $DIR/subdiagnostic-derive.rs:260:5
|
LL | #[applicability]
| ^^^^^^^^^^^^^^^^
error: `#[bar]` is not a valid attribute
--> $DIR/subdiagnostic-derive.rs:271:5
--> $DIR/subdiagnostic-derive.rs:270:5
|
LL | #[bar]
| ^^^^^^
@ -173,13 +167,13 @@ LL | #[bar]
= help: only `primary_span`, `applicability` and `skip_arg` are valid field attributes
error: `#[bar = ...]` is not a valid attribute
--> $DIR/subdiagnostic-derive.rs:282:5
--> $DIR/subdiagnostic-derive.rs:281:5
|
LL | #[bar = "..."]
| ^^^^^^^^^^^^^^
error: `#[bar(...)]` is not a valid attribute
--> $DIR/subdiagnostic-derive.rs:293:5
--> $DIR/subdiagnostic-derive.rs:292:5
|
LL | #[bar("...")]
| ^^^^^^^^^^^^^
@ -187,7 +181,7 @@ LL | #[bar("...")]
= help: only `primary_span`, `applicability` and `skip_arg` are valid field attributes
error: unexpected unsupported untagged union
--> $DIR/subdiagnostic-derive.rs:309:1
--> $DIR/subdiagnostic-derive.rs:308:1
|
LL | / union AC {
LL | |
@ -197,7 +191,7 @@ LL | | }
| |_^
error: `#[label(parser::add_paren)]` is not a valid attribute
--> $DIR/subdiagnostic-derive.rs:324:28
--> $DIR/subdiagnostic-derive.rs:323:28
|
LL | #[label(parser::add_paren, parser::add_paren)]
| ^^^^^^^^^^^^^^^^^
@ -205,67 +199,67 @@ LL | #[label(parser::add_paren, parser::add_paren)]
= help: a diagnostic slug must be the first argument to the attribute
error: specified multiple times
--> $DIR/subdiagnostic-derive.rs:337:5
--> $DIR/subdiagnostic-derive.rs:336:5
|
LL | #[primary_span]
| ^^^^^^^^^^^^^^^
|
note: previously specified here
--> $DIR/subdiagnostic-derive.rs:334:5
--> $DIR/subdiagnostic-derive.rs:333:5
|
LL | #[primary_span]
| ^^^^^^^^^^^^^^^
error: subdiagnostic kind not specified
--> $DIR/subdiagnostic-derive.rs:343:8
--> $DIR/subdiagnostic-derive.rs:342:8
|
LL | struct AG {
| ^^
error: specified multiple times
--> $DIR/subdiagnostic-derive.rs:380:47
--> $DIR/subdiagnostic-derive.rs:379:47
|
LL | #[suggestion(parser::add_paren, code = "...", code = "...")]
| ^^^^^^^^^^^^
|
note: previously specified here
--> $DIR/subdiagnostic-derive.rs:380:33
--> $DIR/subdiagnostic-derive.rs:379:33
|
LL | #[suggestion(parser::add_paren, code = "...", code = "...")]
| ^^^^^^^^^^^^
error: specified multiple times
--> $DIR/subdiagnostic-derive.rs:398:5
--> $DIR/subdiagnostic-derive.rs:397:5
|
LL | #[applicability]
| ^^^^^^^^^^^^^^^^
|
note: previously specified here
--> $DIR/subdiagnostic-derive.rs:395:5
--> $DIR/subdiagnostic-derive.rs:394:5
|
LL | #[applicability]
| ^^^^^^^^^^^^^^^^
error: the `#[applicability]` attribute can only be applied to fields of type `Applicability`
--> $DIR/subdiagnostic-derive.rs:408:5
--> $DIR/subdiagnostic-derive.rs:407:5
|
LL | #[applicability]
| ^^^^^^^^^^^^^^^^
error: suggestion without `code = "..."`
--> $DIR/subdiagnostic-derive.rs:421:1
--> $DIR/subdiagnostic-derive.rs:420:1
|
LL | #[suggestion(parser::add_paren)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: invalid applicability
--> $DIR/subdiagnostic-derive.rs:431:46
--> $DIR/subdiagnostic-derive.rs:430:46
|
LL | #[suggestion(parser::add_paren, code ="...", applicability = "foo")]
| ^^^^^^^^^^^^^^^^^^^^^
error: suggestion without `#[primary_span]` field
--> $DIR/subdiagnostic-derive.rs:449:1
--> $DIR/subdiagnostic-derive.rs:448:1
|
LL | / #[suggestion(parser::add_paren, code = "...")]
LL | |
@ -275,25 +269,25 @@ LL | | }
| |_^
error: unsupported type attribute for subdiagnostic enum
--> $DIR/subdiagnostic-derive.rs:463:1
--> $DIR/subdiagnostic-derive.rs:462:1
|
LL | #[label]
| ^^^^^^^^
error: `var` doesn't refer to a field on this type
--> $DIR/subdiagnostic-derive.rs:483:39
--> $DIR/subdiagnostic-derive.rs:482:39
|
LL | #[suggestion(parser::add_paren, code ="{var}", applicability = "machine-applicable")]
| ^^^^^^^
error: `var` doesn't refer to a field on this type
--> $DIR/subdiagnostic-derive.rs:502:43
--> $DIR/subdiagnostic-derive.rs:501:43
|
LL | #[suggestion(parser::add_paren, code ="{var}", applicability = "machine-applicable")]
| ^^^^^^^
error: `#[suggestion_part]` is not a valid attribute
--> $DIR/subdiagnostic-derive.rs:525:5
--> $DIR/subdiagnostic-derive.rs:524:5
|
LL | #[suggestion_part]
| ^^^^^^^^^^^^^^^^^^
@ -301,7 +295,7 @@ LL | #[suggestion_part]
= help: `#[suggestion_part(...)]` is only valid in multipart suggestions, use `#[primary_span]` instead
error: `#[suggestion_part(...)]` is not a valid attribute
--> $DIR/subdiagnostic-derive.rs:528:5
--> $DIR/subdiagnostic-derive.rs:527:5
|
LL | #[suggestion_part(code = "...")]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@ -309,7 +303,7 @@ LL | #[suggestion_part(code = "...")]
= help: `#[suggestion_part(...)]` is only valid in multipart suggestions
error: suggestion without `#[primary_span]` field
--> $DIR/subdiagnostic-derive.rs:522:1
--> $DIR/subdiagnostic-derive.rs:521:1
|
LL | / #[suggestion(parser::add_paren, code = "...")]
LL | |
@ -321,7 +315,7 @@ LL | | }
| |_^
error: `#[multipart_suggestion(code = ...)]` is not a valid attribute
--> $DIR/subdiagnostic-derive.rs:537:43
--> $DIR/subdiagnostic-derive.rs:536:43
|
LL | #[multipart_suggestion(parser::add_paren, code = "...", applicability = "machine-applicable")]
| ^^^^^^^^^^^^
@ -329,7 +323,7 @@ LL | #[multipart_suggestion(parser::add_paren, code = "...", applicability = "ma
= help: only `applicability` is a valid nested attributes
error: multipart suggestion without any `#[suggestion_part(...)]` fields
--> $DIR/subdiagnostic-derive.rs:537:1
--> $DIR/subdiagnostic-derive.rs:536:1
|
LL | / #[multipart_suggestion(parser::add_paren, code = "...", applicability = "machine-applicable")]
LL | |
@ -340,19 +334,19 @@ LL | | }
| |_^
error: `#[suggestion_part(...)]` attribute without `code = "..."`
--> $DIR/subdiagnostic-derive.rs:547:5
--> $DIR/subdiagnostic-derive.rs:546:5
|
LL | #[suggestion_part]
| ^^^^^^^^^^^^^^^^^^
error: `#[suggestion_part(...)]` attribute without `code = "..."`
--> $DIR/subdiagnostic-derive.rs:555:5
--> $DIR/subdiagnostic-derive.rs:554:5
|
LL | #[suggestion_part()]
| ^^^^^^^^^^^^^^^^^^^^
error: `#[primary_span]` is not a valid attribute
--> $DIR/subdiagnostic-derive.rs:564:5
--> $DIR/subdiagnostic-derive.rs:563:5
|
LL | #[primary_span]
| ^^^^^^^^^^^^^^^
@ -360,7 +354,7 @@ LL | #[primary_span]
= help: multipart suggestions use one or more `#[suggestion_part]`s rather than one `#[primary_span]`
error: multipart suggestion without any `#[suggestion_part(...)]` fields
--> $DIR/subdiagnostic-derive.rs:561:1
--> $DIR/subdiagnostic-derive.rs:560:1
|
LL | / #[multipart_suggestion(parser::add_paren)]
LL | |
@ -372,19 +366,19 @@ LL | | }
| |_^
error: `#[suggestion_part(...)]` attribute without `code = "..."`
--> $DIR/subdiagnostic-derive.rs:572:5
--> $DIR/subdiagnostic-derive.rs:571:5
|
LL | #[suggestion_part]
| ^^^^^^^^^^^^^^^^^^
error: `#[suggestion_part(...)]` attribute without `code = "..."`
--> $DIR/subdiagnostic-derive.rs:575:5
--> $DIR/subdiagnostic-derive.rs:574:5
|
LL | #[suggestion_part()]
| ^^^^^^^^^^^^^^^^^^^^
error: `#[suggestion_part(foo = ...)]` is not a valid attribute
--> $DIR/subdiagnostic-derive.rs:578:23
--> $DIR/subdiagnostic-derive.rs:577:23
|
LL | #[suggestion_part(foo = "bar")]
| ^^^^^^^^^^^
@ -392,31 +386,31 @@ LL | #[suggestion_part(foo = "bar")]
= help: `code` is the only valid nested attribute
error: the `#[suggestion_part(...)]` attribute can only be applied to fields of type `Span` or `MultiSpan`
--> $DIR/subdiagnostic-derive.rs:581:5
--> $DIR/subdiagnostic-derive.rs:580:5
|
LL | #[suggestion_part(code = "...")]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: the `#[suggestion_part(...)]` attribute can only be applied to fields of type `Span` or `MultiSpan`
--> $DIR/subdiagnostic-derive.rs:584:5
--> $DIR/subdiagnostic-derive.rs:583:5
|
LL | #[suggestion_part()]
| ^^^^^^^^^^^^^^^^^^^^
error: specified multiple times
--> $DIR/subdiagnostic-derive.rs:592:37
--> $DIR/subdiagnostic-derive.rs:591:37
|
LL | #[suggestion_part(code = "...", code = ",,,")]
| ^^^^^^^^^^^^
|
note: previously specified here
--> $DIR/subdiagnostic-derive.rs:592:23
--> $DIR/subdiagnostic-derive.rs:591:23
|
LL | #[suggestion_part(code = "...", code = ",,,")]
| ^^^^^^^^^^^^
error: `#[applicability]` has no effect if all `#[suggestion]`/`#[multipart_suggestion]` attributes have a static `applicability = "..."`
--> $DIR/subdiagnostic-derive.rs:621:5
--> $DIR/subdiagnostic-derive.rs:620:5
|
LL | #[applicability]
| ^^^^^^^^^^^^^^^^
@ -458,19 +452,19 @@ LL | #[bar("...")]
| ^^^
error: cannot find attribute `bar` in this scope
--> $DIR/subdiagnostic-derive.rs:271:7
--> $DIR/subdiagnostic-derive.rs:270:7
|
LL | #[bar]
| ^^^
error: cannot find attribute `bar` in this scope
--> $DIR/subdiagnostic-derive.rs:282:7
--> $DIR/subdiagnostic-derive.rs:281:7
|
LL | #[bar = "..."]
| ^^^
error: cannot find attribute `bar` in this scope
--> $DIR/subdiagnostic-derive.rs:293:7
--> $DIR/subdiagnostic-derive.rs:292:7
|
LL | #[bar("...")]
| ^^^
@ -481,6 +475,6 @@ error[E0425]: cannot find value `slug` in module `rustc_errors::fluent`
LL | #[label(slug)]
| ^^^^ not found in `rustc_errors::fluent`
error: aborting due to 68 previous errors
error: aborting due to 67 previous errors
For more information about this error, try `rustc --explain E0425`.

View File

@ -1,3 +1,4 @@
// needs-asm-support
// check-pass
// compile-flags: -Zunpretty=expanded
core::arch::global_asm!("x: .byte 42");

View File

@ -4,6 +4,7 @@
use ::std::prelude::rust_2015::*;
#[macro_use]
extern crate std;
// needs-asm-support
// check-pass
// compile-flags: -Zunpretty=expanded
global_asm! ("x: .byte 42");

View File

@ -1,21 +1,8 @@
// needs-asm-support
// run-pass
#[allow(unused_imports)]
use std::arch::global_asm;
#[cfg(target_arch = "x86")]
global_asm!("");
#[cfg(target_arch = "x86_64")]
global_asm!("");
#[cfg(target_arch = "arm")]
global_asm!("");
#[cfg(target_arch = "aarch64")]
global_asm!("");
#[cfg(target_arch = "mips")]
global_asm!("");
fn main() {}

View File

@ -1,9 +1,16 @@
error[E0425]: cannot find function `f` in this scope
--> $DIR/globs.rs:22:9
|
LL | pub fn g() {}
| ---------- similarly named function `g` defined here
...
LL | f();
| ^ not found in this scope
| ^
|
help: a function with a similar name exists
|
LL | g();
| ~
help: consider importing this function
|
LL | use foo::f;
@ -12,8 +19,11 @@ LL | use foo::f;
error[E0425]: cannot find function `g` in this scope
--> $DIR/globs.rs:15:5
|
LL | pub fn f() {}
| ---------- similarly named function `f` defined here
...
LL | g();
| ^ not found in this scope
| ^
...
LL | / m! {
LL | | use bar::*;
@ -23,6 +33,10 @@ LL | | }
| |_____- in this macro invocation
|
= note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info)
help: a function with a similar name exists
|
LL | f();
| ~
help: consider importing this function
|
LL | use bar::g;

View File

@ -19,14 +19,8 @@ LL | semitransparent;
error[E0423]: expected value, found macro `opaque`
--> $DIR/rustc-macro-transparency.rs:30:5
|
LL | struct Opaque;
| -------------- similarly named unit struct `Opaque` defined here
...
LL | opaque;
| ^^^^^^
| |
| not a value
| help: a unit struct with a similar name exists (notice the capitalization): `Opaque`
| ^^^^^^ not a value
error: aborting due to 3 previous errors

View File

@ -1,6 +1,8 @@
error[E0574]: expected struct, variant or union type, found type parameter `T`
--> $DIR/lexical-scopes.rs:3:13
|
LL | struct T { i: i32 }
| ------------------- you might have meant to refer to this struct
LL | fn f<T>() {
| - found this type parameter
LL | let t = T { i: 0 };

View File

@ -0,0 +1,11 @@
#![deny(unused_must_use)]
fn it() -> impl ExactSizeIterator<Item = ()> {
let x: Box<dyn ExactSizeIterator<Item = ()>> = todo!();
x
}
fn main() {
it();
//~^ ERROR unused implementer of `Iterator` that must be used
}

View File

@ -0,0 +1,15 @@
error: unused implementer of `Iterator` that must be used
--> $DIR/unused-supertrait.rs:9:5
|
LL | it();
| ^^^^^
|
= note: iterators are lazy and do nothing unless consumed
note: the lint level is defined here
--> $DIR/unused-supertrait.rs:1:9
|
LL | #![deny(unused_must_use)]
| ^^^^^^^^^^^^^^^
error: aborting due to previous error

View File

@ -57,7 +57,7 @@ error[E0425]: cannot find value `i` in this scope
--> $DIR/macro-context.rs:3:13
|
LL | () => ( i ; typeof );
| ^ help: a local variable with a similar name exists: `a`
| ^ not found in this scope
...
LL | let i = m!();
| ---- in this macro invocation

View File

@ -13,7 +13,7 @@ error[E0425]: cannot find value `local_use` in this scope
--> $DIR/gen-macro-rules-hygiene.rs:12:1
|
LL | gen_macro_rules!();
| ^^^^^^^^^^^^^^^^^^ not found in this scope
| ^^^^^^^^^^^^^^^^^^ help: a local variable with a similar name exists: `local_def`
...
LL | generated!();
| ------------ in this macro invocation
@ -24,7 +24,7 @@ error[E0425]: cannot find value `local_def` in this scope
--> $DIR/gen-macro-rules-hygiene.rs:21:9
|
LL | local_def;
| ^^^^^^^^^ not found in this scope
| ^^^^^^^^^ help: a local variable with a similar name exists: `local_use`
error: aborting due to 3 previous errors

View File

@ -10,7 +10,7 @@ error[E0425]: cannot find value `local_use` in this scope
--> $DIR/mixed-site-span.rs:13:9
|
LL | proc_macro_rules!();
| ^^^^^^^^^^^^^^^^^^^ not found in this scope
| ^^^^^^^^^^^^^^^^^^^ help: a local variable with a similar name exists: `local_def`
|
= note: this error originates in the macro `proc_macro_rules` (in Nightly builds, run with -Z macro-backtrace for more info)
@ -18,7 +18,7 @@ error[E0425]: cannot find value `local_def` in this scope
--> $DIR/mixed-site-span.rs:17:9
|
LL | local_def;
| ^^^^^^^^^ not found in this scope
| ^^^^^^^^^ help: a local variable with a similar name exists: `local_use`
error[E0412]: cannot find type `ItemUse` in crate `$crate`
--> $DIR/mixed-site-span.rs:24:1

View File

@ -1,11 +1,16 @@
error[E0574]: expected struct, variant or union type, found type parameter `Baz`
--> $DIR/point-at-type-parameter-shadowing-another-type.rs:16:13
|
LL | impl<Baz> Foo<Baz> for Bar {
| --- found this type parameter
LL | / struct Baz {
LL | | num: usize,
LL | | }
| |_- you might have meant to refer to this struct
LL |
LL | impl<Baz> Foo<Baz> for Bar {
| --- found this type parameter
...
LL | Baz { num } => num,
| ^^^ not a struct, variant or union type
LL | Baz { num } => num,
| ^^^ not a struct, variant or union type
error: aborting due to previous error

View File

@ -69,11 +69,13 @@ fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &Expr<'tcx>) {
"only a `panic!` in `if`-then statement",
|diag| {
// comments can be noisy, do not show them to the user
diag.tool_only_span_suggestion(
expr.span.shrink_to_lo(),
"add comments back",
comments,
applicability);
if !comments.is_empty() {
diag.tool_only_span_suggestion(
expr.span.shrink_to_lo(),
"add comments back",
comments,
applicability);
}
diag.span_suggestion(
expr.span,
"try instead",

View File

@ -180,10 +180,13 @@ fn assignment_suggestions<'tcx>(
let suggestions = assignments
.iter()
.flat_map(|assignment| {
[
assignment.span.until(assignment.rhs_span),
assignment.rhs_span.shrink_to_hi().with_hi(assignment.span.hi()),
]
let mut spans = vec![assignment.span.until(assignment.rhs_span)];
if assignment.rhs_span.hi() != assignment.span.hi() {
spans.push(assignment.rhs_span.shrink_to_hi().with_hi(assignment.span.hi()));
}
spans
})
.map(|span| (span, String::new()))
.collect::<Vec<(Span, String)>>();

View File

@ -1,3 +1,4 @@
// needs-asm-support
// run-rustfix
#![allow(unused, clippy::needless_pass_by_value, clippy::collapsible_if)]

View File

@ -1,3 +1,4 @@
// needs-asm-support
// run-rustfix
#![allow(unused, clippy::needless_pass_by_value, clippy::collapsible_if)]

View File

@ -1,5 +1,5 @@
error: usage of `contains_key` followed by `insert` on a `HashMap`
--> $DIR/entry.rs:24:5
--> $DIR/entry.rs:25:5
|
LL | / if !m.contains_key(&k) {
LL | | m.insert(k, v);
@ -9,7 +9,7 @@ LL | | }
= note: `-D clippy::map-entry` implied by `-D warnings`
error: usage of `contains_key` followed by `insert` on a `HashMap`
--> $DIR/entry.rs:29:5
--> $DIR/entry.rs:30:5
|
LL | / if !m.contains_key(&k) {
LL | | if true {
@ -32,7 +32,7 @@ LL + });
|
error: usage of `contains_key` followed by `insert` on a `HashMap`
--> $DIR/entry.rs:38:5
--> $DIR/entry.rs:39:5
|
LL | / if !m.contains_key(&k) {
LL | | if true {
@ -55,7 +55,7 @@ LL + });
|
error: usage of `contains_key` followed by `insert` on a `HashMap`
--> $DIR/entry.rs:47:5
--> $DIR/entry.rs:48:5
|
LL | / if !m.contains_key(&k) {
LL | | if true {
@ -79,7 +79,7 @@ LL + }
|
error: usage of `contains_key` followed by `insert` on a `HashMap`
--> $DIR/entry.rs:57:5
--> $DIR/entry.rs:58:5
|
LL | / if !m.contains_key(&k) {
LL | | foo();
@ -96,7 +96,7 @@ LL + });
|
error: usage of `contains_key` followed by `insert` on a `HashMap`
--> $DIR/entry.rs:63:5
--> $DIR/entry.rs:64:5
|
LL | / if !m.contains_key(&k) {
LL | | match 0 {
@ -122,7 +122,7 @@ LL + });
|
error: usage of `contains_key` followed by `insert` on a `HashMap`
--> $DIR/entry.rs:75:5
--> $DIR/entry.rs:76:5
|
LL | / if !m.contains_key(&k) {
LL | | match 0 {
@ -146,7 +146,7 @@ LL + }
|
error: usage of `contains_key` followed by `insert` on a `HashMap`
--> $DIR/entry.rs:85:5
--> $DIR/entry.rs:86:5
|
LL | / if !m.contains_key(&k) {
LL | | foo();
@ -187,7 +187,7 @@ LL + });
|
error: usage of `contains_key` followed by `insert` on a `HashMap`
--> $DIR/entry.rs:119:5
--> $DIR/entry.rs:120:5
|
LL | / if !m.contains_key(&m!(k)) {
LL | | m.insert(m!(k), m!(v));
@ -195,7 +195,7 @@ LL | | }
| |_____^ help: try this: `m.entry(m!(k)).or_insert_with(|| m!(v));`
error: usage of `contains_key` followed by `insert` on a `HashMap`
--> $DIR/entry.rs:151:5
--> $DIR/entry.rs:152:5
|
LL | / if !m.contains_key(&k) {
LL | | let x = (String::new(), String::new());

View File

@ -4,13 +4,9 @@ error: only a `panic!` in `if`-then statement
LL | / if !a.is_empty() {
LL | | panic!("qaqaq{:?}", a);
LL | | }
| |_____^
| |_____^ help: try instead: `assert!(a.is_empty(), "qaqaq{:?}", a);`
|
= note: `-D clippy::manual-assert` implied by `-D warnings`
help: try instead
|
LL | assert!(a.is_empty(), "qaqaq{:?}", a);
|
error: only a `panic!` in `if`-then statement
--> $DIR/manual_assert.rs:34:5
@ -18,12 +14,7 @@ error: only a `panic!` in `if`-then statement
LL | / if !a.is_empty() {
LL | | panic!("qwqwq");
LL | | }
| |_____^
|
help: try instead
|
LL | assert!(a.is_empty(), "qwqwq");
|
| |_____^ help: try instead: `assert!(a.is_empty(), "qwqwq");`
error: only a `panic!` in `if`-then statement
--> $DIR/manual_assert.rs:51:5
@ -31,12 +22,7 @@ error: only a `panic!` in `if`-then statement
LL | / if b.is_empty() {
LL | | panic!("panic1");
LL | | }
| |_____^
|
help: try instead
|
LL | assert!(!b.is_empty(), "panic1");
|
| |_____^ help: try instead: `assert!(!b.is_empty(), "panic1");`
error: only a `panic!` in `if`-then statement
--> $DIR/manual_assert.rs:54:5
@ -44,12 +30,7 @@ error: only a `panic!` in `if`-then statement
LL | / if b.is_empty() && a.is_empty() {
LL | | panic!("panic2");
LL | | }
| |_____^
|
help: try instead
|
LL | assert!(!(b.is_empty() && a.is_empty()), "panic2");
|
| |_____^ help: try instead: `assert!(!(b.is_empty() && a.is_empty()), "panic2");`
error: only a `panic!` in `if`-then statement
--> $DIR/manual_assert.rs:57:5
@ -57,12 +38,7 @@ error: only a `panic!` in `if`-then statement
LL | / if a.is_empty() && !b.is_empty() {
LL | | panic!("panic3");
LL | | }
| |_____^
|
help: try instead
|
LL | assert!(!(a.is_empty() && !b.is_empty()), "panic3");
|
| |_____^ help: try instead: `assert!(!(a.is_empty() && !b.is_empty()), "panic3");`
error: only a `panic!` in `if`-then statement
--> $DIR/manual_assert.rs:60:5
@ -70,12 +46,7 @@ error: only a `panic!` in `if`-then statement
LL | / if b.is_empty() || a.is_empty() {
LL | | panic!("panic4");
LL | | }
| |_____^
|
help: try instead
|
LL | assert!(!(b.is_empty() || a.is_empty()), "panic4");
|
| |_____^ help: try instead: `assert!(!(b.is_empty() || a.is_empty()), "panic4");`
error: only a `panic!` in `if`-then statement
--> $DIR/manual_assert.rs:63:5
@ -83,12 +54,7 @@ error: only a `panic!` in `if`-then statement
LL | / if a.is_empty() || !b.is_empty() {
LL | | panic!("panic5");
LL | | }
| |_____^
|
help: try instead
|
LL | assert!(!(a.is_empty() || !b.is_empty()), "panic5");
|
| |_____^ help: try instead: `assert!(!(a.is_empty() || !b.is_empty()), "panic5");`
error: only a `panic!` in `if`-then statement
--> $DIR/manual_assert.rs:66:5
@ -96,12 +62,7 @@ error: only a `panic!` in `if`-then statement
LL | / if a.is_empty() {
LL | | panic!("with expansion {}", one!())
LL | | }
| |_____^
|
help: try instead
|
LL | assert!(!a.is_empty(), "with expansion {}", one!());
|
| |_____^ help: try instead: `assert!(!a.is_empty(), "with expansion {}", one!());`
error: only a `panic!` in `if`-then statement
--> $DIR/manual_assert.rs:73:5

View File

@ -4,13 +4,9 @@ error: only a `panic!` in `if`-then statement
LL | / if !a.is_empty() {
LL | | panic!("qaqaq{:?}", a);
LL | | }
| |_____^
| |_____^ help: try instead: `assert!(a.is_empty(), "qaqaq{:?}", a);`
|
= note: `-D clippy::manual-assert` implied by `-D warnings`
help: try instead
|
LL | assert!(a.is_empty(), "qaqaq{:?}", a);
|
error: only a `panic!` in `if`-then statement
--> $DIR/manual_assert.rs:34:5
@ -18,12 +14,7 @@ error: only a `panic!` in `if`-then statement
LL | / if !a.is_empty() {
LL | | panic!("qwqwq");
LL | | }
| |_____^
|
help: try instead
|
LL | assert!(a.is_empty(), "qwqwq");
|
| |_____^ help: try instead: `assert!(a.is_empty(), "qwqwq");`
error: only a `panic!` in `if`-then statement
--> $DIR/manual_assert.rs:51:5
@ -31,12 +22,7 @@ error: only a `panic!` in `if`-then statement
LL | / if b.is_empty() {
LL | | panic!("panic1");
LL | | }
| |_____^
|
help: try instead
|
LL | assert!(!b.is_empty(), "panic1");
|
| |_____^ help: try instead: `assert!(!b.is_empty(), "panic1");`
error: only a `panic!` in `if`-then statement
--> $DIR/manual_assert.rs:54:5
@ -44,12 +30,7 @@ error: only a `panic!` in `if`-then statement
LL | / if b.is_empty() && a.is_empty() {
LL | | panic!("panic2");
LL | | }
| |_____^
|
help: try instead
|
LL | assert!(!(b.is_empty() && a.is_empty()), "panic2");
|
| |_____^ help: try instead: `assert!(!(b.is_empty() && a.is_empty()), "panic2");`
error: only a `panic!` in `if`-then statement
--> $DIR/manual_assert.rs:57:5
@ -57,12 +38,7 @@ error: only a `panic!` in `if`-then statement
LL | / if a.is_empty() && !b.is_empty() {
LL | | panic!("panic3");
LL | | }
| |_____^
|
help: try instead
|
LL | assert!(!(a.is_empty() && !b.is_empty()), "panic3");
|
| |_____^ help: try instead: `assert!(!(a.is_empty() && !b.is_empty()), "panic3");`
error: only a `panic!` in `if`-then statement
--> $DIR/manual_assert.rs:60:5
@ -70,12 +46,7 @@ error: only a `panic!` in `if`-then statement
LL | / if b.is_empty() || a.is_empty() {
LL | | panic!("panic4");
LL | | }
| |_____^
|
help: try instead
|
LL | assert!(!(b.is_empty() || a.is_empty()), "panic4");
|
| |_____^ help: try instead: `assert!(!(b.is_empty() || a.is_empty()), "panic4");`
error: only a `panic!` in `if`-then statement
--> $DIR/manual_assert.rs:63:5
@ -83,12 +54,7 @@ error: only a `panic!` in `if`-then statement
LL | / if a.is_empty() || !b.is_empty() {
LL | | panic!("panic5");
LL | | }
| |_____^
|
help: try instead
|
LL | assert!(!(a.is_empty() || !b.is_empty()), "panic5");
|
| |_____^ help: try instead: `assert!(!(a.is_empty() || !b.is_empty()), "panic5");`
error: only a `panic!` in `if`-then statement
--> $DIR/manual_assert.rs:66:5
@ -96,12 +62,7 @@ error: only a `panic!` in `if`-then statement
LL | / if a.is_empty() {
LL | | panic!("with expansion {}", one!())
LL | | }
| |_____^
|
help: try instead
|
LL | assert!(!a.is_empty(), "with expansion {}", one!());
|
| |_____^ help: try instead: `assert!(!a.is_empty(), "with expansion {}", one!());`
error: only a `panic!` in `if`-then statement
--> $DIR/manual_assert.rs:73:5

View File

@ -1,3 +1,4 @@
// needs-asm-support
// aux-build: proc_macro_with_span.rs
#![warn(clippy::missing_docs_in_private_items)]

View File

@ -1,5 +1,5 @@
error: missing documentation for a type alias
--> $DIR/missing_doc.rs:15:1
--> $DIR/missing_doc.rs:16:1
|
LL | type Typedef = String;
| ^^^^^^^^^^^^^^^^^^^^^^
@ -7,37 +7,37 @@ LL | type Typedef = String;
= note: `-D clippy::missing-docs-in-private-items` implied by `-D warnings`
error: missing documentation for a type alias
--> $DIR/missing_doc.rs:16:1
--> $DIR/missing_doc.rs:17:1
|
LL | pub type PubTypedef = String;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: missing documentation for a module
--> $DIR/missing_doc.rs:18:1
--> $DIR/missing_doc.rs:19:1
|
LL | mod module_no_dox {}
| ^^^^^^^^^^^^^^^^^^^^
error: missing documentation for a module
--> $DIR/missing_doc.rs:19:1
--> $DIR/missing_doc.rs:20:1
|
LL | pub mod pub_module_no_dox {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: missing documentation for a function
--> $DIR/missing_doc.rs:23:1
--> $DIR/missing_doc.rs:24:1
|
LL | pub fn foo2() {}
| ^^^^^^^^^^^^^^^^
error: missing documentation for a function
--> $DIR/missing_doc.rs:24:1
--> $DIR/missing_doc.rs:25:1
|
LL | fn foo3() {}
| ^^^^^^^^^^^^
error: missing documentation for an enum
--> $DIR/missing_doc.rs:38:1
--> $DIR/missing_doc.rs:39:1
|
LL | / enum Baz {
LL | | BazA { a: isize, b: isize },
@ -46,31 +46,31 @@ LL | | }
| |_^
error: missing documentation for a variant
--> $DIR/missing_doc.rs:39:5
--> $DIR/missing_doc.rs:40:5
|
LL | BazA { a: isize, b: isize },
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: missing documentation for a struct field
--> $DIR/missing_doc.rs:39:12
--> $DIR/missing_doc.rs:40:12
|
LL | BazA { a: isize, b: isize },
| ^^^^^^^^
error: missing documentation for a struct field
--> $DIR/missing_doc.rs:39:22
--> $DIR/missing_doc.rs:40:22
|
LL | BazA { a: isize, b: isize },
| ^^^^^^^^
error: missing documentation for a variant
--> $DIR/missing_doc.rs:40:5
--> $DIR/missing_doc.rs:41:5
|
LL | BarB,
| ^^^^
error: missing documentation for an enum
--> $DIR/missing_doc.rs:43:1
--> $DIR/missing_doc.rs:44:1
|
LL | / pub enum PubBaz {
LL | | PubBazA { a: isize },
@ -78,43 +78,43 @@ LL | | }
| |_^
error: missing documentation for a variant
--> $DIR/missing_doc.rs:44:5
--> $DIR/missing_doc.rs:45:5
|
LL | PubBazA { a: isize },
| ^^^^^^^^^^^^^^^^^^^^
error: missing documentation for a struct field
--> $DIR/missing_doc.rs:44:15
--> $DIR/missing_doc.rs:45:15
|
LL | PubBazA { a: isize },
| ^^^^^^^^
error: missing documentation for a constant
--> $DIR/missing_doc.rs:64:1
--> $DIR/missing_doc.rs:65:1
|
LL | const FOO: u32 = 0;
| ^^^^^^^^^^^^^^^^^^^
error: missing documentation for a constant
--> $DIR/missing_doc.rs:71:1
--> $DIR/missing_doc.rs:72:1
|
LL | pub const FOO4: u32 = 0;
| ^^^^^^^^^^^^^^^^^^^^^^^^
error: missing documentation for a static
--> $DIR/missing_doc.rs:73:1
--> $DIR/missing_doc.rs:74:1
|
LL | static BAR: u32 = 0;
| ^^^^^^^^^^^^^^^^^^^^
error: missing documentation for a static
--> $DIR/missing_doc.rs:80:1
--> $DIR/missing_doc.rs:81:1
|
LL | pub static BAR4: u32 = 0;
| ^^^^^^^^^^^^^^^^^^^^^^^^^
error: missing documentation for a module
--> $DIR/missing_doc.rs:82:1
--> $DIR/missing_doc.rs:83:1
|
LL | / mod internal_impl {
LL | | /// dox
@ -126,31 +126,31 @@ LL | | }
| |_^
error: missing documentation for a function
--> $DIR/missing_doc.rs:85:5
--> $DIR/missing_doc.rs:86:5
|
LL | pub fn undocumented1() {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^
error: missing documentation for a function
--> $DIR/missing_doc.rs:86:5
--> $DIR/missing_doc.rs:87:5
|
LL | pub fn undocumented2() {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^
error: missing documentation for a function
--> $DIR/missing_doc.rs:87:5
--> $DIR/missing_doc.rs:88:5
|
LL | fn undocumented3() {}
| ^^^^^^^^^^^^^^^^^^^^^
error: missing documentation for a function
--> $DIR/missing_doc.rs:92:9
--> $DIR/missing_doc.rs:93:9
|
LL | pub fn also_undocumented1() {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: missing documentation for a function
--> $DIR/missing_doc.rs:93:9
--> $DIR/missing_doc.rs:94:9
|
LL | fn also_undocumented2() {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^