Auto merge of #110852 - matthiaskrgr:rollup-jz3eosr, r=matthiaskrgr

Rollup of 10 pull requests

Successful merges:

 - #108760 (Add lint to deny diagnostics composed of static strings)
 - #109444 (Change tidy error message for TODOs)
 - #110419 (Spelling library)
 - #110550 (Suggest deref on comparison binop RHS even if type is not Copy)
 - #110641 (Add new rustdoc book chapter to describe in-doc settings)
 - #110798 (pass `unused_extern_crates` in `librustdoc::doctest::make_test`)
 - #110819 (simplify TrustedLen impls)
 - #110825 (diagnostics: add test case for already-solved issue)
 - #110835 (Make some region folders a little stricter.)
 - #110847 (rustdoc-json: Time serialization.)

Failed merges:

r? `@ghost`
`@rustbot` modify labels: rollup
This commit is contained in:
bors 2023-04-26 18:32:57 +00:00
commit 1c42cb4ef0
85 changed files with 833 additions and 329 deletions

View File

@ -149,6 +149,25 @@ builtin_macros_format_pos_mismatch = {$n} positional {$n ->
[one] argument
*[more] arguments
} in format string, but {$desc}
builtin_macros_offset_of_expected_field = expected field
builtin_macros_offset_of_expected_two_args = expected 2 arguments
builtin_macros_test_case_non_item = `#[test_case]` attribute is only allowed on items
builtin_macros_test_bad_fn = {$kind} functions cannot be used for tests
.label = `{$kind}` because of this
builtin_macros_asm_explicit_register_name = explicit register arguments cannot have names
builtin_macros_asm_mutually_exclusive = the `{$opt1}` and `{$opt2}` options are mutually exclusive
builtin_macros_asm_pure_combine = the `pure` option must be combined with either `nomem` or `readonly`
builtin_macros_asm_pure_no_output = asm with the `pure` option must have at least one output
builtin_macros_asm_modifier_invalid = asm template modifier must be a single character
builtin_macros_test_runner_invalid = `test_runner` argument must be a path
builtin_macros_test_runner_nargs = `#![test_runner(..)]` accepts exactly 1 argument

View File

@ -15,6 +15,8 @@ use rustc_span::{InnerSpan, Span};
use rustc_target::asm::InlineAsmArch;
use smallvec::smallvec;
use crate::errors;
pub struct AsmArgs {
pub templates: Vec<P<ast::Expr>>,
pub operands: Vec<(ast::InlineAsmOperand, Span)>,
@ -205,7 +207,7 @@ pub fn parse_asm_args<'a>(
// of the argument available.
if explicit_reg {
if name.is_some() {
diag.struct_span_err(span, "explicit register arguments cannot have names").emit();
diag.emit_err(errors::AsmExplicitRegisterName { span });
}
args.reg_args.insert(slot);
} else if let Some(name) = name {
@ -240,25 +242,19 @@ pub fn parse_asm_args<'a>(
&& args.options.contains(ast::InlineAsmOptions::READONLY)
{
let spans = args.options_spans.clone();
diag.struct_span_err(spans, "the `nomem` and `readonly` options are mutually exclusive")
.emit();
diag.emit_err(errors::AsmMutuallyExclusive { spans, opt1: "nomem", opt2: "readonly" });
}
if args.options.contains(ast::InlineAsmOptions::PURE)
&& args.options.contains(ast::InlineAsmOptions::NORETURN)
{
let spans = args.options_spans.clone();
diag.struct_span_err(spans, "the `pure` and `noreturn` options are mutually exclusive")
.emit();
diag.emit_err(errors::AsmMutuallyExclusive { spans, opt1: "pure", opt2: "noreturn" });
}
if args.options.contains(ast::InlineAsmOptions::PURE)
&& !args.options.intersects(ast::InlineAsmOptions::NOMEM | ast::InlineAsmOptions::READONLY)
{
let spans = args.options_spans.clone();
diag.struct_span_err(
spans,
"the `pure` option must be combined with either `nomem` or `readonly`",
)
.emit();
diag.emit_err(errors::AsmPureCombine { spans });
}
let mut have_real_output = false;
@ -285,11 +281,7 @@ pub fn parse_asm_args<'a>(
}
}
if args.options.contains(ast::InlineAsmOptions::PURE) && !have_real_output {
diag.struct_span_err(
args.options_spans.clone(),
"asm with the `pure` option must have at least one output",
)
.emit();
diag.emit_err(errors::AsmPureNoOutput { spans: args.options_spans.clone() });
}
if args.options.contains(ast::InlineAsmOptions::NORETURN) && !outputs_sp.is_empty() {
let err = diag
@ -705,11 +697,7 @@ fn expand_preparsed_asm(ecx: &mut ExtCtxt<'_>, args: AsmArgs) -> Option<ast::Inl
.ty_span
.map(|sp| template_sp.from_inner(InnerSpan::new(sp.start, sp.end)))
.unwrap_or(template_sp);
ecx.struct_span_err(
span,
"asm template modifier must be a single character",
)
.emit();
ecx.emit_err(errors::AsmModifierInvalid { span });
modifier = None;
}

View File

@ -551,3 +551,71 @@ pub(crate) struct FormatPositionalMismatch {
#[subdiagnostic]
pub(crate) highlight: SingleLabelManySpans,
}
#[derive(Diagnostic)]
#[diag(builtin_macros_test_case_non_item)]
pub(crate) struct TestCaseNonItem {
#[primary_span]
pub(crate) span: Span,
}
#[derive(Diagnostic)]
#[diag(builtin_macros_test_bad_fn)]
pub(crate) struct TestBadFn {
#[primary_span]
pub(crate) span: Span,
#[label]
pub(crate) cause: Span,
pub(crate) kind: &'static str,
}
#[derive(Diagnostic)]
#[diag(builtin_macros_asm_explicit_register_name)]
pub(crate) struct AsmExplicitRegisterName {
#[primary_span]
pub(crate) span: Span,
}
#[derive(Diagnostic)]
#[diag(builtin_macros_asm_mutually_exclusive)]
pub(crate) struct AsmMutuallyExclusive {
#[primary_span]
pub(crate) spans: Vec<Span>,
pub(crate) opt1: &'static str,
pub(crate) opt2: &'static str,
}
#[derive(Diagnostic)]
#[diag(builtin_macros_asm_pure_combine)]
pub(crate) struct AsmPureCombine {
#[primary_span]
pub(crate) spans: Vec<Span>,
}
#[derive(Diagnostic)]
#[diag(builtin_macros_asm_pure_no_output)]
pub(crate) struct AsmPureNoOutput {
#[primary_span]
pub(crate) spans: Vec<Span>,
}
#[derive(Diagnostic)]
#[diag(builtin_macros_asm_modifier_invalid)]
pub(crate) struct AsmModifierInvalid {
#[primary_span]
pub(crate) span: Span,
}
#[derive(Diagnostic)]
#[diag(builtin_macros_test_runner_invalid)]
pub(crate) struct TestRunnerInvalid {
#[primary_span]
pub(crate) span: Span,
}
#[derive(Diagnostic)]
#[diag(builtin_macros_test_runner_nargs)]
pub(crate) struct TestRunnerNargs {
#[primary_span]
pub(crate) span: Span,
}

View File

@ -1,3 +1,4 @@
use crate::errors;
/// The expansion from a test function to the appropriate test struct for libtest
/// Ideally, this code would be in libtest but for efficiency and error messages it lives here.
use crate::util::{check_builtin_macro_attribute, warn_on_duplicate_attribute};
@ -40,12 +41,7 @@ pub fn expand_test_case(
unreachable!()
},
_ => {
ecx.struct_span_err(
anno_item.span(),
"`#[test_case]` attribute is only allowed on items",
)
.emit();
ecx.emit_err(errors::TestCaseNonItem { span: anno_item.span() });
return vec![];
}
};
@ -533,15 +529,11 @@ fn has_test_signature(cx: &ExtCtxt<'_>, i: &ast::Item) -> bool {
match &i.kind {
ast::ItemKind::Fn(box ast::Fn { sig, generics, .. }) => {
if let ast::Unsafe::Yes(span) = sig.header.unsafety {
sd.struct_span_err(i.span, "unsafe functions cannot be used for tests")
.span_label(span, "`unsafe` because of this")
.emit();
sd.emit_err(errors::TestBadFn { span: i.span, cause: span, kind: "unsafe" });
return false;
}
if let ast::Async::Yes { span, .. } = sig.header.asyncness {
sd.struct_span_err(i.span, "async functions cannot be used for tests")
.span_label(span, "`async` because of this")
.emit();
sd.emit_err(errors::TestBadFn { span: i.span, cause: span, kind: "async" });
return false;
}

View File

@ -19,6 +19,8 @@ use tracing::debug;
use std::{iter, mem};
use crate::errors;
#[derive(Clone)]
struct Test {
span: Span,
@ -385,11 +387,11 @@ fn get_test_runner(sd: &rustc_errors::Handler, krate: &ast::Crate) -> Option<ast
[single] => match single.meta_item() {
Some(meta_item) if meta_item.is_word() => return Some(meta_item.path.clone()),
_ => {
sd.struct_span_err(span, "`test_runner` argument must be a path").emit();
sd.emit_err(errors::TestRunnerInvalid { span });
}
},
_ => {
sd.struct_span_err(span, "`#![test_runner(..)]` accepts exactly 1 argument").emit();
sd.emit_err(errors::TestRunnerNargs { span });
}
}
None

View File

@ -291,3 +291,16 @@ codegen_ssa_invalid_monomorphization_unsupported_cast = invalid monomorphization
codegen_ssa_invalid_monomorphization_unsupported_operation = invalid monomorphization of `{$name}` intrinsic: unsupported operation on `{$in_ty}` with element `{$in_elem}`
codegen_ssa_invalid_monomorphization_expected_vector_element_type = invalid monomorphization of `{$name}` intrinsic: expected element type `{$expected_element}` of vector type `{$vector_type}` to be a signed or unsigned integer type
codegen_ssa_invalid_no_sanitize = invalid argument for `no_sanitize`
.note = expected one of: `address`, `cfi`, `hwaddress`, `kcfi`, `memory`, `memtag`, `shadow-call-stack`, or `thread`
codegen_ssa_invalid_link_ordinal_nargs = incorrect number of arguments to `#[link_ordinal]`
.note = the attribute requires exactly one argument
codegen_ssa_illegal_link_ordinal_format = illegal ordinal format in `link_ordinal`
.note = an unsuffixed integer value, e.g., `1`, is expected
codegen_ssa_target_feature_safe_trait = `#[target_feature(..)]` cannot be applied to safe trait method
.label = cannot be applied to safe trait method
.label_def = not an `unsafe` function

View File

@ -14,6 +14,7 @@ use rustc_span::symbol::Ident;
use rustc_span::{sym, Span};
use rustc_target::spec::{abi, SanitizerSet};
use crate::errors;
use crate::target_features::from_target_feature;
use crate::{errors::ExpectedUsedSymbol, target_features::check_target_feature_trait_unsafe};
@ -334,10 +335,7 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
codegen_fn_attrs.no_sanitize |= SanitizerSet::HWADDRESS
}
_ => {
tcx.sess
.struct_span_err(item.span(), "invalid argument for `no_sanitize`")
.note("expected one of: `address`, `cfi`, `hwaddress`, `kcfi`, `memory`, `memtag`, `shadow-call-stack`, or `thread`")
.emit();
tcx.sess.emit_err(errors::InvalidNoSanitize { span: item.span() });
}
}
}
@ -608,10 +606,7 @@ fn check_link_ordinal(tcx: TyCtxt<'_>, attr: &ast::Attribute) -> Option<u16> {
let sole_meta_list = match meta_item_list {
Some([item]) => item.lit(),
Some(_) => {
tcx.sess
.struct_span_err(attr.span, "incorrect number of arguments to `#[link_ordinal]`")
.note("the attribute requires exactly one argument")
.emit();
tcx.sess.emit_err(errors::InvalidLinkOrdinalNargs { span: attr.span });
return None;
}
_ => None,
@ -642,10 +637,7 @@ fn check_link_ordinal(tcx: TyCtxt<'_>, attr: &ast::Attribute) -> Option<u16> {
None
}
} else {
tcx.sess
.struct_span_err(attr.span, "illegal ordinal format in `link_ordinal`")
.note("an unsuffixed integer value, e.g., `1`, is expected")
.emit();
tcx.sess.emit_err(errors::InvalidLinkOrdinalFormat { span: attr.span });
None
}
}

View File

@ -981,3 +981,37 @@ impl IntoDiagnosticArg for ExpectedPointerMutability {
}
}
}
#[derive(Diagnostic)]
#[diag(codegen_ssa_invalid_no_sanitize)]
#[note]
pub struct InvalidNoSanitize {
#[primary_span]
pub span: Span,
}
#[derive(Diagnostic)]
#[diag(codegen_ssa_invalid_link_ordinal_nargs)]
#[note]
pub struct InvalidLinkOrdinalNargs {
#[primary_span]
pub span: Span,
}
#[derive(Diagnostic)]
#[diag(codegen_ssa_illegal_link_ordinal_format)]
#[note]
pub struct InvalidLinkOrdinalFormat {
#[primary_span]
pub span: Span,
}
#[derive(Diagnostic)]
#[diag(codegen_ssa_target_feature_safe_trait)]
pub struct TargetFeatureSafeTrait {
#[primary_span]
#[label]
pub span: Span,
#[label(codegen_ssa_label_def)]
pub def: Span,
}

View File

@ -1,3 +1,4 @@
use crate::errors;
use rustc_ast::ast;
use rustc_attr::InstructionSetAttr;
use rustc_data_structures::fx::FxHashMap;
@ -443,14 +444,10 @@ pub fn check_target_feature_trait_unsafe(tcx: TyCtxt<'_>, id: LocalDefId, attr_s
if let DefKind::AssocFn = tcx.def_kind(id) {
let parent_id = tcx.local_parent(id);
if let DefKind::Trait | DefKind::Impl { of_trait: true } = tcx.def_kind(parent_id) {
tcx.sess
.struct_span_err(
attr_span,
"`#[target_feature(..)]` cannot be applied to safe trait method",
)
.span_label(attr_span, "cannot be applied to safe trait method")
.span_label(tcx.def_span(id), "not an `unsafe` function")
.emit();
tcx.sess.emit_err(errors::TargetFeatureSafeTrait {
span: attr_span,
def: tcx.def_span(id),
});
}
}
}

View File

@ -136,3 +136,7 @@ expand_proc_macro_panicked =
expand_proc_macro_derive_tokens =
proc-macro derive produced unparsable tokens
expand_duplicate_matcher_binding = duplicate matcher binding
.label = duplicate binding
.label2 = previous binding

View File

@ -397,3 +397,13 @@ pub struct ProcMacroDeriveTokens {
#[primary_span]
pub span: Span,
}
#[derive(Diagnostic)]
#[diag(expand_duplicate_matcher_binding)]
pub struct DuplicateMatcherBinding {
#[primary_span]
#[label]
pub span: Span,
#[label(expand_label2)]
pub prev: Span,
}

View File

@ -104,6 +104,7 @@
//! Kleene operators under which a meta-variable is repeating is the concatenation of the stacks
//! stored when entering a macro definition starting from the state in which the meta-variable is
//! bound.
use crate::errors;
use crate::mbe::{KleeneToken, TokenTree};
use rustc_ast::token::{Delimiter, Token, TokenKind};
@ -281,10 +282,7 @@ fn check_binders(
// Duplicate binders at the top-level macro definition are errors. The lint is only
// for nested macro definitions.
sess.span_diagnostic
.struct_span_err(span, "duplicate matcher binding")
.span_label(span, "duplicate binding")
.span_label(prev_info.span, "previous binding")
.emit();
.emit_err(errors::DuplicateMatcherBinding { span, prev: prev_info.span });
*valid = false;
} else {
binders.insert(name, BinderInfo { span, ops: ops.into() });

View File

@ -262,3 +262,17 @@ hir_analysis_transparent_non_zero_sized_enum = the variant of a transparent {$de
hir_analysis_transparent_non_zero_sized = transparent {$desc} needs at most one non-zero-sized field, but has {$field_count}
.label = needs at most one non-zero-sized field, but has {$field_count}
.labels = this field is non-zero-sized
hir_analysis_too_large_static = extern static is too large for the current architecture
hir_analysis_specialization_trait = implementing `rustc_specialization_trait` traits is unstable
.help = add `#![feature(min_specialization)]` to the crate attributes to enable
hir_analysis_closure_implicit_hrtb = implicit types in closure signatures are forbidden when `for<...>` is present
.label = `for<...>` is here
hir_analysis_const_specialize = cannot specialize on const impl with non-const impl
hir_analysis_static_specialize = cannot specialize on `'static` lifetime
hir_analysis_missing_tilde_const = missing `~const` qualifier for specialization

View File

@ -170,9 +170,7 @@ fn check_static_inhabited(tcx: TyCtxt<'_>, def_id: LocalDefId) {
if matches!(tcx.def_kind(def_id), DefKind::Static(_)
if tcx.def_kind(tcx.local_parent(def_id)) == DefKind::ForeignMod) =>
{
tcx.sess
.struct_span_err(span, "extern static is too large for the current architecture")
.emit();
tcx.sess.emit_err(errors::TooLargeStatic { span });
return;
}
// Generic statics are rejected, but we still reach this case.

View File

@ -1576,17 +1576,10 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for ImplTraitInTraitFinder<'_, 'tcx> {
&& let hir::OpaqueTyOrigin::FnReturn(source) | hir::OpaqueTyOrigin::AsyncFn(source) = opaque.origin
&& source == self.fn_def_id
{
let opaque_ty = tcx.fold_regions(unshifted_opaque_ty, |re, depth| {
if let ty::ReLateBound(index, bv) = re.kind() {
if depth != ty::INNERMOST {
return tcx.mk_re_error_with_message(
DUMMY_SP,
"we shouldn't walk non-predicate binders with `impl Trait`...",
);
}
tcx.mk_re_late_bound(index.shifted_out_to_binder(self.depth), bv)
} else {
re
let opaque_ty = tcx.fold_regions(unshifted_opaque_ty, |re, _depth| {
match re.kind() {
ty::ReEarlyBound(_) | ty::ReFree(_) | ty::ReError(_) => re,
r => bug!("unexpected region: {r:?}"),
}
});
for (bound, bound_span) in tcx

View File

@ -5,6 +5,7 @@
// done by the orphan and overlap modules. Then we build up various
// mappings. That mapping code resides here.
use crate::errors;
use rustc_errors::{error_code, struct_span_err};
use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_middle::ty::query::Providers;
@ -67,13 +68,7 @@ fn enforce_trait_manually_implementable(
tcx.trait_def(trait_def_id).specialization_kind
{
if !tcx.features().specialization && !tcx.features().min_specialization {
tcx.sess
.struct_span_err(
impl_header_span,
"implementing `rustc_specialization_trait` traits is unstable",
)
.help("add `#![feature(min_specialization)]` to the crate attributes to enable")
.emit();
tcx.sess.emit_err(errors::SpecializationTrait { span: impl_header_span });
return;
}
}

View File

@ -386,8 +386,10 @@ impl<'tcx> AstConv<'tcx> for ItemCtxt<'tcx> {
fn ct_infer(&self, ty: Ty<'tcx>, _: Option<&ty::GenericParamDef>, span: Span) -> Const<'tcx> {
let ty = self.tcx.fold_regions(ty, |r, _| match *r {
ty::ReErased => self.tcx.lifetimes.re_static,
_ => r,
// This is never reached in practice. If it ever is reached,
// `ReErased` should be changed to `ReStatic`, and any other region
// left alone.
r => bug!("unexpected region: {r:?}"),
});
self.tcx().const_error_with_message(ty, span, "bad placeholder constant")
}

View File

@ -455,13 +455,9 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> {
.collect::<Vec<_>>();
if !infer_spans.is_empty() {
self.tcx.sess
.struct_span_err(
infer_spans,
"implicit types in closure signatures are forbidden when `for<...>` is present",
)
.span_label(for_sp, "`for<...>` is here")
.emit();
self.tcx
.sess
.emit_err(errors::ClosureImplicitHrtb { spans: infer_spans, for_sp });
}
}

View File

@ -633,6 +633,7 @@ pub(crate) struct SIMDFFIHighlyExperimental {
}
#[derive(Diagnostic)]
pub enum ImplNotMarkedDefault {
#[diag(hir_analysis_impl_not_marked_default, code = "E0520")]
#[note]
@ -769,3 +770,48 @@ pub(crate) struct TransparentNonZeroSized<'a> {
pub field_count: usize,
pub desc: &'a str,
}
#[derive(Diagnostic)]
#[diag(hir_analysis_too_large_static)]
pub(crate) struct TooLargeStatic {
#[primary_span]
pub span: Span,
}
#[derive(Diagnostic)]
#[diag(hir_analysis_specialization_trait)]
#[help]
pub(crate) struct SpecializationTrait {
#[primary_span]
pub span: Span,
}
#[derive(Diagnostic)]
#[diag(hir_analysis_closure_implicit_hrtb)]
pub(crate) struct ClosureImplicitHrtb {
#[primary_span]
pub spans: Vec<Span>,
#[label]
pub for_sp: Span,
}
#[derive(Diagnostic)]
#[diag(hir_analysis_const_specialize)]
pub(crate) struct ConstSpecialize {
#[primary_span]
pub span: Span,
}
#[derive(Diagnostic)]
#[diag(hir_analysis_static_specialize)]
pub(crate) struct StaticSpecialize {
#[primary_span]
pub span: Span,
}
#[derive(Diagnostic)]
#[diag(hir_analysis_missing_tilde_const)]
pub(crate) struct MissingTildeConst {
#[primary_span]
pub span: Span,
}

View File

@ -65,8 +65,8 @@
//! cause use after frees with purely safe code in the same way as specializing
//! on traits with methods can.
use crate::constrained_generic_params as cgp;
use crate::errors::SubstsOnOverriddenImpl;
use crate::{constrained_generic_params as cgp, errors};
use rustc_data_structures::fx::FxHashSet;
use rustc_hir as hir;
@ -137,9 +137,7 @@ fn check_constness(tcx: TyCtxt<'_>, impl1_def_id: LocalDefId, impl2_node: Node,
if let hir::Constness::Const = impl2_constness {
if let hir::Constness::NotConst = impl1_constness {
tcx.sess
.struct_span_err(span, "cannot specialize on const impl with non-const impl")
.emit();
tcx.sess.emit_err(errors::ConstSpecialize { span });
}
}
}
@ -293,7 +291,7 @@ fn check_static_lifetimes<'tcx>(
span: Span,
) {
if tcx.any_free_region_meets(parent_substs, |r| r.is_static()) {
tcx.sess.struct_span_err(span, "cannot specialize on `'static` lifetime").emit();
tcx.sess.emit_err(errors::StaticSpecialize { span });
}
}
@ -438,7 +436,7 @@ fn trait_predicates_eq<'tcx>(
// the one on the base.
match (trait_pred2.constness, trait_pred1.constness) {
(ty::BoundConstness::ConstIfConst, ty::BoundConstness::NotConst) => {
tcx.sess.struct_span_err(span, "missing `~const` qualifier for specialization").emit();
tcx.sess.emit_err(errors::MissingTildeConst { span });
}
_ => {}
}

View File

@ -62,3 +62,16 @@ hir_typeck_fru_suggestion =
[NONE]{""}
*[other] {" "}from `{$expr}`
}, separate the last named field with a comma
hir_typeck_const_select_must_be_const = this argument must be a `const fn`
.help = consult the documentation on `const_eval_select` for more information
hir_typeck_const_select_must_be_fn = this argument must be a function item
.note = expected a function item, found {$ty}
.help = consult the documentation on `const_eval_select` for more information
hir_typeck_union_pat_multiple_fields = union patterns should have exactly one field
hir_typeck_union_pat_dotdot = `..` cannot be used in union patterns
hir_typeck_arg_mismatch_indeterminate = argument type mismatch was detected, but rustc had trouble determining where
.note = we would appreciate a bug report: https://github.com/rust-lang/rust/issues/new

View File

@ -1508,6 +1508,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// FIXME(compiler-errors): We can actually do this if the checked_ty is
// `steps` layers of boxes, not just one, but this is easier and most likely.
|| (checked_ty.is_box() && steps == 1)
// We can always deref a binop that takes its arguments by ref.
|| matches!(
self.tcx.hir().get_parent(expr.hir_id),
hir::Node::Expr(hir::Expr { kind: hir::ExprKind::Binary(op, ..), .. })
if !op.node.is_by_value()
)
{
let deref_kind = if checked_ty.is_box() {
"unboxing the value"

View File

@ -228,3 +228,42 @@ impl HelpUseLatestEdition {
}
}
}
#[derive(Diagnostic)]
#[diag(hir_typeck_const_select_must_be_const)]
#[help]
pub struct ConstSelectMustBeConst {
#[primary_span]
pub span: Span,
}
#[derive(Diagnostic)]
#[diag(hir_typeck_const_select_must_be_fn)]
#[note]
#[help]
pub struct ConstSelectMustBeFn<'a> {
#[primary_span]
pub span: Span,
pub ty: Ty<'a>,
}
#[derive(Diagnostic)]
#[diag(hir_typeck_union_pat_multiple_fields)]
pub struct UnionPatMultipleFields {
#[primary_span]
pub span: Span,
}
#[derive(Diagnostic)]
#[diag(hir_typeck_union_pat_dotdot)]
pub struct UnionPatDotDot {
#[primary_span]
pub span: Span,
}
#[derive(Diagnostic)]
#[diag(hir_typeck_arg_mismatch_indeterminate)]
pub struct ArgMismatchIndeterminate {
#[primary_span]
pub span: Span,
}

View File

@ -2,8 +2,8 @@ use crate::coercion::CoerceMany;
use crate::fn_ctxt::arg_matrix::{ArgMatrix, Compatibility, Error, ExpectedIdx, ProvidedIdx};
use crate::gather_locals::Declaration;
use crate::method::MethodCallee;
use crate::Expectation::*;
use crate::TupleArgumentsFlag::*;
use crate::{errors, Expectation::*};
use crate::{
struct_span_err, BreakableCtxt, Diverges, Expectation, FnCtxt, LocalTy, Needs, RawTy,
TupleArgumentsFlag,
@ -283,19 +283,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
if idx == 1 && !self.tcx.is_const_fn_raw(*def_id) {
self.tcx
.sess
.struct_span_err(provided_arg.span, "this argument must be a `const fn`")
.help("consult the documentation on `const_eval_select` for more information")
.emit();
.emit_err(errors::ConstSelectMustBeConst { span: provided_arg.span });
}
} else {
self.tcx
.sess
.struct_span_err(provided_arg.span, "this argument must be a function item")
.note(format!("expected a function item, found {checked_ty}"))
.help(
"consult the documentation on `const_eval_select` for more information",
)
.emit();
self.tcx.sess.emit_err(errors::ConstSelectMustBeFn {
span: provided_arg.span,
ty: checked_ty,
});
}
}
@ -744,17 +738,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
if cfg!(debug_assertions) {
span_bug!(error_span, "expected errors from argument matrix");
} else {
tcx.sess
.struct_span_err(
error_span,
"argument type mismatch was detected, \
but rustc had trouble determining where",
)
.note(
"we would appreciate a bug report: \
https://github.com/rust-lang/rust/issues/new",
)
.emit();
tcx.sess.emit_err(errors::ArgMismatchIndeterminate { span: error_span });
}
return;
}

View File

@ -1,4 +1,4 @@
use crate::{FnCtxt, RawTy};
use crate::{errors, FnCtxt, RawTy};
use rustc_ast as ast;
use rustc_data_structures::fx::FxHashMap;
use rustc_errors::{
@ -1410,12 +1410,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// Report an error if an incorrect number of fields was specified.
if adt.is_union() {
if fields.len() != 1 {
tcx.sess
.struct_span_err(pat.span, "union patterns should have exactly one field")
.emit();
tcx.sess.emit_err(errors::UnionPatMultipleFields { span: pat.span });
}
if has_rest_pat {
tcx.sess.struct_span_err(pat.span, "`..` cannot be used in union patterns").emit();
tcx.sess.emit_err(errors::UnionPatDotDot { span: pat.span });
}
} else if !unmentioned_fields.is_empty() {
let accessible_unmentioned_fields: Vec<_> = unmentioned_fields

View File

@ -99,6 +99,8 @@ lint_diag_out_of_impl =
lint_untranslatable_diag = diagnostics should be created using translatable messages
lint_trivial_untranslatable_diag = diagnostic with static strings only
lint_bad_opt_access = {$msg}
lint_cstring_ptr = getting the inner pointer of a temporary `CString`

View File

@ -4,6 +4,7 @@
use crate::lints::{
BadOptAccessDiag, DefaultHashTypesDiag, DiagOutOfImpl, LintPassByHand, NonExistentDocKeyword,
QueryInstability, TyQualified, TykindDiag, TykindKind, UntranslatableDiag,
UntranslatableDiagnosticTrivial,
};
use crate::{EarlyContext, EarlyLintPass, LateContext, LateLintPass, LintContext};
use rustc_ast as ast;
@ -366,7 +367,15 @@ declare_tool_lint! {
report_in_external_macro: true
}
declare_lint_pass!(Diagnostics => [ UNTRANSLATABLE_DIAGNOSTIC, DIAGNOSTIC_OUTSIDE_OF_IMPL ]);
declare_tool_lint! {
/// The `untranslatable_diagnostic_trivial` lint detects diagnostics created using only static strings.
pub rustc::UNTRANSLATABLE_DIAGNOSTIC_TRIVIAL,
Deny,
"prevent creation of diagnostics which cannot be translated, which use only static strings",
report_in_external_macro: true
}
declare_lint_pass!(Diagnostics => [ UNTRANSLATABLE_DIAGNOSTIC, DIAGNOSTIC_OUTSIDE_OF_IMPL, UNTRANSLATABLE_DIAGNOSTIC_TRIVIAL ]);
impl LateLintPass<'_> for Diagnostics {
fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) {
@ -423,6 +432,75 @@ impl LateLintPass<'_> for Diagnostics {
}
}
impl EarlyLintPass for Diagnostics {
#[allow(unused_must_use)]
fn check_stmt(&mut self, cx: &EarlyContext<'_>, stmt: &ast::Stmt) {
// Looking for a straight chain of method calls from 'struct_span_err' to 'emit'.
let ast::StmtKind::Semi(expr) = &stmt.kind else {
return;
};
let ast::ExprKind::MethodCall(meth) = &expr.kind else {
return;
};
if meth.seg.ident.name != sym::emit || !meth.args.is_empty() {
return;
}
let mut segments = vec![];
let mut cur = &meth.receiver;
let fake = &[].into();
loop {
match &cur.kind {
ast::ExprKind::Call(func, args) => {
if let ast::ExprKind::Path(_, path) = &func.kind {
segments.push((path.segments.last().unwrap().ident.name, args))
}
break;
}
ast::ExprKind::MethodCall(method) => {
segments.push((method.seg.ident.name, &method.args));
cur = &method.receiver;
}
ast::ExprKind::MacCall(mac) => {
segments.push((mac.path.segments.last().unwrap().ident.name, fake));
break;
}
_ => {
break;
}
}
}
segments.reverse();
if segments.is_empty() {
return;
}
if segments[0].0.as_str() != "struct_span_err" {
return;
}
if !segments.iter().all(|(name, args)| {
let arg = match name.as_str() {
"struct_span_err" | "span_note" | "span_label" | "span_help" => &args[1],
"note" | "help" => &args[0],
_ => {
return false;
}
};
if let ast::ExprKind::Lit(lit) = arg.kind
&& let ast::token::LitKind::Str = lit.kind {
true
} else {
false
}
}) {
return;
}
cx.emit_spanned_lint(
UNTRANSLATABLE_DIAGNOSTIC_TRIVIAL,
stmt.span,
UntranslatableDiagnosticTrivial,
);
}
}
declare_tool_lint! {
/// The `bad_opt_access` lint detects accessing options by field instead of
/// the wrapper function.

View File

@ -518,6 +518,7 @@ fn register_internals(store: &mut LintStore) {
store.register_lints(&TyTyKind::get_lints());
store.register_late_pass(|_| Box::new(TyTyKind));
store.register_lints(&Diagnostics::get_lints());
store.register_early_pass(|| Box::new(Diagnostics));
store.register_late_pass(|_| Box::new(Diagnostics));
store.register_lints(&BadOptAccess::get_lints());
store.register_late_pass(|_| Box::new(BadOptAccess));

View File

@ -820,6 +820,10 @@ pub struct DiagOutOfImpl;
#[diag(lint_untranslatable_diag)]
pub struct UntranslatableDiag;
#[derive(LintDiagnostic)]
#[diag(lint_trivial_untranslatable_diag)]
pub struct UntranslatableDiagnosticTrivial;
#[derive(LintDiagnostic)]
#[diag(lint_bad_opt_access)]
pub struct BadOptAccessDiag<'a> {

View File

@ -829,7 +829,13 @@ impl<'a, 'tcx> TypeFolder<TyCtxt<'tcx>> for SubstFolder<'a, 'tcx> {
None => region_param_out_of_range(data, self.substs),
}
}
_ => r,
ty::ReLateBound(..)
| ty::ReFree(_)
| ty::ReStatic
| ty::RePlaceholder(_)
| ty::ReErased
| ty::ReError(_) => r,
ty::ReVar(_) => bug!("unexpected region: {r:?}"),
}
}

View File

@ -742,3 +742,33 @@ parse_bad_return_type_notation_output =
parse_bad_return_type_notation_dotdot =
return type notation uses `()` instead of `(..)` for elided arguments
.suggestion = remove the `..`
parse_bad_assoc_type_bounds = bounds on associated types do not belong here
.label = belongs in `where` clause
parse_attr_after_generic = trailing attribute after generic parameter
.label = attributes must go before parameters
parse_attr_without_generics = attribute without generic parameters
.label = attributes are only permitted when preceding parameters
parse_where_generics = generic parameters on `where` clauses are reserved for future use
.label = currently unsupported
parse_generics_in_path = unexpected generic arguments in path
parse_assoc_lifetime = associated lifetimes are not supported
.label = the lifetime is given here
.help = if you meant to specify a trait object, write `dyn Trait + 'lifetime`
parse_tilde_const_lifetime = `~const` may only modify trait bounds, not lifetime bounds
parse_maybe_lifetime = `?` may only modify trait bounds, not lifetime bounds
parse_parenthesized_lifetime = parenthesized lifetime bounds are not supported
.suggestion = remove the parentheses
parse_const_bounds_missing_tilde = const bounds must start with `~`
.suggestion = add `~`
parse_underscore_literal_suffix = underscore literal suffix is not allowed

View File

@ -2332,3 +2332,92 @@ pub(crate) struct BadReturnTypeNotationDotDot {
#[suggestion(code = "", applicability = "maybe-incorrect")]
pub span: Span,
}
#[derive(Diagnostic)]
#[diag(parse_bad_assoc_type_bounds)]
pub(crate) struct BadAssocTypeBounds {
#[primary_span]
#[label]
pub span: Span,
}
#[derive(Diagnostic)]
#[diag(parse_attr_after_generic)]
pub(crate) struct AttrAfterGeneric {
#[primary_span]
#[label]
pub span: Span,
}
#[derive(Diagnostic)]
#[diag(parse_attr_without_generics)]
pub(crate) struct AttrWithoutGenerics {
#[primary_span]
#[label]
pub span: Span,
}
#[derive(Diagnostic)]
#[diag(parse_where_generics)]
pub(crate) struct WhereOnGenerics {
#[primary_span]
#[label]
pub span: Span,
}
#[derive(Diagnostic)]
#[diag(parse_generics_in_path)]
pub(crate) struct GenericsInPath {
#[primary_span]
pub span: Vec<Span>,
}
#[derive(Diagnostic)]
#[diag(parse_assoc_lifetime)]
#[help]
pub(crate) struct AssocLifetime {
#[primary_span]
pub span: Span,
#[label]
pub lifetime: Span,
}
#[derive(Diagnostic)]
#[diag(parse_tilde_const_lifetime)]
pub(crate) struct TildeConstLifetime {
#[primary_span]
pub span: Span,
}
#[derive(Diagnostic)]
#[diag(parse_maybe_lifetime)]
pub(crate) struct MaybeLifetime {
#[primary_span]
pub span: Span,
}
#[derive(Diagnostic)]
#[diag(parse_parenthesized_lifetime)]
pub(crate) struct ParenthesizedLifetime {
#[primary_span]
pub span: Span,
#[suggestion(style = "short", applicability = "machine-applicable", code = "{snippet}")]
pub sugg: Option<Span>,
pub snippet: String,
}
#[derive(Diagnostic)]
#[diag(parse_const_bounds_missing_tilde)]
pub(crate) struct ConstMissingTilde {
#[primary_span]
pub span: Span,
#[suggestion(code = "~", applicability = "machine-applicable")]
pub start: Span,
}
#[derive(Diagnostic)]
#[diag(parse_underscore_literal_suffix)]
pub(crate) struct UnderscoreLiteralSuffix {
#[primary_span]
pub span: Span,
}

View File

@ -209,11 +209,7 @@ impl<'a> StringReader<'a> {
if string == "_" {
self.sess
.span_diagnostic
.struct_span_err(
self.mk_sp(suffix_start, self.pos),
"underscore literal suffix is not allowed",
)
.emit();
.emit_err(errors::UnderscoreLiteralSuffix { span: self.mk_sp(suffix_start, self.pos) });
None
} else {
Some(Symbol::intern(string))

View File

@ -1,5 +1,5 @@
use crate::errors::{
MultipleWhereClauses, UnexpectedDefaultValueForLifetimeInGenericParameters,
self, MultipleWhereClauses, UnexpectedDefaultValueForLifetimeInGenericParameters,
UnexpectedSelfInGenericParameters, WhereClauseBeforeTupleStructBody,
WhereClauseBeforeTupleStructBodySugg,
};
@ -181,12 +181,9 @@ impl<'a> Parser<'a> {
let snapshot = this.create_snapshot_for_diagnostic();
match this.parse_ty_where_predicate() {
Ok(where_predicate) => {
this.struct_span_err(
where_predicate.span(),
"bounds on associated types do not belong here",
)
.span_label(where_predicate.span(), "belongs in `where` clause")
.emit();
this.sess.emit_err(errors::BadAssocTypeBounds {
span: where_predicate.span(),
});
// FIXME - try to continue parsing other generics?
return Ok((None, TrailingToken::None));
}
@ -201,22 +198,11 @@ impl<'a> Parser<'a> {
// Check for trailing attributes and stop parsing.
if !attrs.is_empty() {
if !params.is_empty() {
this.struct_span_err(
attrs[0].span,
"trailing attribute after generic parameter",
)
.span_label(attrs[0].span, "attributes must go before parameters")
.emit();
this.sess
.emit_err(errors::AttrAfterGeneric { span: attrs[0].span });
} else {
this.struct_span_err(
attrs[0].span,
"attribute without generic parameters",
)
.span_label(
attrs[0].span,
"attributes are only permitted when preceding parameters",
)
.emit();
this.sess
.emit_err(errors::AttrWithoutGenerics { span: attrs[0].span });
}
}
return Ok((None, TrailingToken::None));
@ -304,12 +290,7 @@ impl<'a> Parser<'a> {
// change we parse those generics now, but report an error.
if self.choose_generics_over_qpath(0) {
let generics = self.parse_generics()?;
self.struct_span_err(
generics.span,
"generic parameters on `where` clauses are reserved for future use",
)
.span_label(generics.span, "currently unsupported")
.emit();
self.sess.emit_err(errors::WhereOnGenerics { span: generics.span });
}
loop {

View File

@ -150,16 +150,13 @@ impl<'a> Parser<'a> {
//
if style == PathStyle::Mod && path.segments.iter().any(|segment| segment.args.is_some())
{
parser
.struct_span_err(
path.segments
.iter()
.filter_map(|segment| segment.args.as_ref())
.map(|arg| arg.span())
.collect::<Vec<_>>(),
"unexpected generic arguments in path",
)
.emit();
let span = path
.segments
.iter()
.filter_map(|segment| segment.args.as_ref())
.map(|arg| arg.span())
.collect::<Vec<_>>();
parser.sess.emit_err(errors::GenericsInPath { span });
}
};
@ -620,10 +617,7 @@ impl<'a> Parser<'a> {
c.into()
}
Some(GenericArg::Lifetime(lt)) => {
self.struct_span_err(span, "associated lifetimes are not supported")
.span_label(lt.ident.span, "the lifetime is given here")
.help("if you meant to specify a trait object, write `dyn Trait + 'lifetime`")
.emit();
self.sess.emit_err(errors::AssocLifetime { span, lifetime: lt.ident.span });
self.mk_ty(span, ast::TyKind::Err).into()
}
None => {

View File

@ -1,7 +1,7 @@
use super::{Parser, PathStyle, TokenType};
use crate::errors::{
DynAfterMut, ExpectedFnPathFoundFnKeyword, ExpectedMutOrConstInRawPointerType,
self, DynAfterMut, ExpectedFnPathFoundFnKeyword, ExpectedMutOrConstInRawPointerType,
FnPointerCannotBeAsync, FnPointerCannotBeConst, FnPtrWithGenerics, FnPtrWithGenericsSugg,
InvalidDynKeyword, LifetimeAfterMut, NeedPlusAfterTraitObjectLifetime,
NegativeBoundsNotSupported, NegativeBoundsNotSupportedSugg, NestedCVariadicType,
@ -807,16 +807,11 @@ impl<'a> Parser<'a> {
/// Emits an error if any trait bound modifiers were present.
fn error_lt_bound_with_modifiers(&self, modifiers: BoundModifiers) {
if let Some(span) = modifiers.maybe_const {
self.struct_span_err(
span,
"`~const` may only modify trait bounds, not lifetime bounds",
)
.emit();
self.sess.emit_err(errors::TildeConstLifetime { span });
}
if let Some(span) = modifiers.maybe {
self.struct_span_err(span, "`?` may only modify trait bounds, not lifetime bounds")
.emit();
self.sess.emit_err(errors::MaybeLifetime { span });
}
}
@ -824,19 +819,14 @@ impl<'a> Parser<'a> {
fn recover_paren_lifetime(&mut self, lo: Span, inner_lo: Span) -> PResult<'a, ()> {
let inner_span = inner_lo.to(self.prev_token.span);
self.expect(&token::CloseDelim(Delimiter::Parenthesis))?;
let mut err = self.struct_span_err(
lo.to(self.prev_token.span),
"parenthesized lifetime bounds are not supported",
);
if let Ok(snippet) = self.span_to_snippet(inner_span) {
err.span_suggestion_short(
lo.to(self.prev_token.span),
"remove the parentheses",
snippet,
Applicability::MachineApplicable,
);
}
err.emit();
let span = lo.to(self.prev_token.span);
let (sugg, snippet) = if let Ok(snippet) = self.span_to_snippet(inner_span) {
(Some(span), snippet)
} else {
(None, String::new())
};
self.sess.emit_err(errors::ParenthesizedLifetime { span, sugg, snippet });
Ok(())
}
@ -857,15 +847,7 @@ impl<'a> Parser<'a> {
} else if self.eat_keyword(kw::Const) {
let span = self.prev_token.span;
self.sess.gated_spans.gate(sym::const_trait_impl, span);
self.struct_span_err(span, "const bounds must start with `~`")
.span_suggestion(
span.shrink_to_lo(),
"add `~`",
"~",
Applicability::MachineApplicable,
)
.emit();
self.sess.emit_err(errors::ConstMissingTilde { span, start: span.shrink_to_lo() });
Some(span)
} else {

View File

@ -226,3 +226,10 @@ resolve_add_as_non_derive =
resolve_proc_macro_same_crate = can't use a procedural macro from the same crate that defines it
.help = you can define integration tests in a directory named `tests`
resolve_imported_crate = `$crate` may not be imported
resolve_macro_use_extern_crate_self = `#[macro_use]` is not supported on `extern crate self`
resolve_accessible_unsure = not sure whether the path is accessible or not
.note = the type may have associated items, but we are currently not checking them

View File

@ -9,7 +9,9 @@ use crate::def_collector::collect_definitions;
use crate::imports::{Import, ImportKind};
use crate::macros::{MacroRulesBinding, MacroRulesScope, MacroRulesScopeRef};
use crate::Namespace::{self, MacroNS, TypeNS, ValueNS};
use crate::{Determinacy, ExternPreludeEntry, Finalize, Module, ModuleKind, ModuleOrUniformRoot};
use crate::{
errors, Determinacy, ExternPreludeEntry, Finalize, Module, ModuleKind, ModuleOrUniformRoot,
};
use crate::{
MacroData, NameBinding, NameBindingKind, ParentScope, PathResult, PerNS, ResolutionError,
};
@ -523,11 +525,7 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> {
ident.name = crate_name;
}
self.r
.tcx
.sess
.struct_span_err(item.span, "`$crate` may not be imported")
.emit();
self.r.tcx.sess.emit_err(errors::CrateImported { span: item.span });
}
}
@ -1028,11 +1026,7 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> {
self.r
.tcx
.sess
.struct_span_err(
attr.span,
"`#[macro_use]` is not supported on `extern crate self`",
)
.emit();
.emit_err(errors::MacroUseExternCrateSelf { span: attr.span });
}
}
let ill_formed = |span| {

View File

@ -517,3 +517,25 @@ pub(crate) struct ProcMacroSameCrate {
#[help]
pub(crate) is_test: bool,
}
#[derive(Diagnostic)]
#[diag(resolve_imported_crate)]
pub(crate) struct CrateImported {
#[primary_span]
pub(crate) span: Span,
}
#[derive(Diagnostic)]
#[diag(resolve_macro_use_extern_crate_self)]
pub(crate) struct MacroUseExternCrateSelf {
#[primary_span]
pub(crate) span: Span,
}
#[derive(Diagnostic)]
#[diag(resolve_accessible_unsure)]
#[note]
pub(crate) struct CfgAccessibleUnsure {
#[primary_span]
pub(crate) span: Span,
}

View File

@ -436,9 +436,7 @@ impl<'a, 'tcx> ResolverExpand for Resolver<'a, 'tcx> {
// HACK(Urgau): This shouldn't be necessary
PathResult::Failed { is_error_from_last_segment: false, .. } => {
self.tcx.sess
.struct_span_err(span, "not sure whether the path is accessible or not")
.note("the type may have associated items, but we are currently not checking them")
.emit();
.emit_err(errors::CfgAccessibleUnsure { span });
// If we get a partially resolved NonModule in one namespace, we should get the
// same result in any other namespaces, so we can return early.

View File

@ -651,6 +651,7 @@ symbols! {
edition_panic,
eh_catch_typeinfo,
eh_personality,
emit,
emit_enum,
emit_enum_variant,
emit_enum_variant_arg,

View File

@ -91,14 +91,15 @@ pub(in crate::solve) fn replace_erased_lifetimes_with_bound_vars<'tcx>(
) -> ty::Binder<'tcx, Ty<'tcx>> {
debug_assert!(!ty.has_late_bound_regions());
let mut counter = 0;
let ty = tcx.fold_regions(ty, |mut r, current_depth| {
if let ty::ReErased = r.kind() {
let ty = tcx.fold_regions(ty, |r, current_depth| match r.kind() {
ty::ReErased => {
let br =
ty::BoundRegion { var: ty::BoundVar::from_u32(counter), kind: ty::BrAnon(None) };
counter += 1;
r = tcx.mk_re_late_bound(current_depth, br);
tcx.mk_re_late_bound(current_depth, br)
}
r
// All free regions should be erased here.
r => bug!("unexpected region: {r:?}"),
});
let bound_vars = tcx.mk_bound_variable_kinds_from_iter(
(0..counter).map(|_| ty::BoundVariableKind::Region(ty::BrAnon(None))),

View File

@ -3006,16 +3006,16 @@ fn bind_generator_hidden_types_above<'tcx>(
// Only remap erased regions if we use them.
if considering_regions {
ty = tcx.fold_regions(ty, |mut r, current_depth| {
if let ty::ReErased = r.kind() {
ty = tcx.fold_regions(ty, |r, current_depth| match r.kind() {
ty::ReErased => {
let br = ty::BoundRegion {
var: ty::BoundVar::from_u32(counter),
kind: ty::BrAnon(None),
};
counter += 1;
r = tcx.mk_re_late_bound(current_depth, br);
tcx.mk_re_late_bound(current_depth, br)
}
r
r => bug!("unexpected region: {r:?}"),
})
}

View File

@ -12,7 +12,7 @@ where
default fn spec_from_iter(iterator: I) -> Self {
// Since converting is O(1) now, just re-use the `Vec` logic for
// anything where we can't do something extra-special for `VecDeque`,
// especially as that could save us some monomorphiziation work
// especially as that could save us some monomorphization work
// if one uses the same iterators (like slice ones) with both.
crate::vec::Vec::from_iter(iterator).into()
}

View File

@ -404,12 +404,12 @@ impl str {
// See https://www.unicode.org/versions/Unicode7.0.0/ch03.pdf#G33992
// for the definition of `Final_Sigma`.
debug_assert!('Σ'.len_utf8() == 2);
let is_word_final = case_ignoreable_then_cased(from[..i].chars().rev())
&& !case_ignoreable_then_cased(from[i + 2..].chars());
let is_word_final = case_ignorable_then_cased(from[..i].chars().rev())
&& !case_ignorable_then_cased(from[i + 2..].chars());
to.push_str(if is_word_final { "ς" } else { "σ" });
}
fn case_ignoreable_then_cased<I: Iterator<Item = char>>(iter: I) -> bool {
fn case_ignorable_then_cased<I: Iterator<Item = char>>(iter: I) -> bool {
use core::unicode::{Case_Ignorable, Cased};
match iter.skip_while(|&c| Case_Ignorable(c)).next() {
Some(c) => Cased(c),

View File

@ -201,7 +201,7 @@ where
//
// Note: This access to the source wouldn't be allowed by the TrustedRandomIteratorNoCoerce
// contract (used by SpecInPlaceCollect below). But see the "O(1) collect" section in the
// module documenttation why this is ok anyway.
// module documentation why this is ok anyway.
let dst_guard = InPlaceDstBufDrop { ptr: dst_buf, len, cap };
src.forget_allocation_drop_remaining();
mem::forget(dst_guard);

View File

@ -705,7 +705,7 @@ fn test_move_rev_iterator() {
}
#[test]
fn test_splitator() {
fn test_split_iterator() {
let xs = &[1, 2, 3, 4, 5];
let splits: &[&[_]] = &[&[1], &[3], &[5]];
@ -725,7 +725,7 @@ fn test_splitator() {
}
#[test]
fn test_splitator_inclusive() {
fn test_split_iterator_inclusive() {
let xs = &[1, 2, 3, 4, 5];
let splits: &[&[_]] = &[&[1, 2], &[3, 4], &[5]];
@ -745,7 +745,7 @@ fn test_splitator_inclusive() {
}
#[test]
fn test_splitator_inclusive_reverse() {
fn test_split_iterator_inclusive_reverse() {
let xs = &[1, 2, 3, 4, 5];
let splits: &[&[_]] = &[&[5], &[3, 4], &[1, 2]];
@ -765,7 +765,7 @@ fn test_splitator_inclusive_reverse() {
}
#[test]
fn test_splitator_mut_inclusive() {
fn test_split_iterator_mut_inclusive() {
let xs = &mut [1, 2, 3, 4, 5];
let splits: &[&[_]] = &[&[1, 2], &[3, 4], &[5]];
@ -785,7 +785,7 @@ fn test_splitator_mut_inclusive() {
}
#[test]
fn test_splitator_mut_inclusive_reverse() {
fn test_split_iterator_mut_inclusive_reverse() {
let xs = &mut [1, 2, 3, 4, 5];
let splits: &[&[_]] = &[&[5], &[3, 4], &[1, 2]];
@ -805,7 +805,7 @@ fn test_splitator_mut_inclusive_reverse() {
}
#[test]
fn test_splitnator() {
fn test_splitn_iterator() {
let xs = &[1, 2, 3, 4, 5];
let splits: &[&[_]] = &[&[1, 2, 3, 4, 5]];
@ -821,7 +821,7 @@ fn test_splitnator() {
}
#[test]
fn test_splitnator_mut() {
fn test_splitn_iterator_mut() {
let xs = &mut [1, 2, 3, 4, 5];
let splits: &[&mut [_]] = &[&mut [1, 2, 3, 4, 5]];
@ -837,7 +837,7 @@ fn test_splitnator_mut() {
}
#[test]
fn test_rsplitator() {
fn test_rsplit_iterator() {
let xs = &[1, 2, 3, 4, 5];
let splits: &[&[_]] = &[&[5], &[3], &[1]];
@ -855,7 +855,7 @@ fn test_rsplitator() {
}
#[test]
fn test_rsplitnator() {
fn test_rsplitn_iterator() {
let xs = &[1, 2, 3, 4, 5];
let splits: &[&[_]] = &[&[1, 2, 3, 4, 5]];
@ -932,7 +932,7 @@ fn test_split_iterators_size_hint() {
}
#[test]
fn test_windowsator() {
fn test_windows_iterator() {
let v = &[1, 2, 3, 4];
let wins: &[&[_]] = &[&[1, 2], &[2, 3], &[3, 4]];
@ -948,13 +948,13 @@ fn test_windowsator() {
#[test]
#[should_panic]
fn test_windowsator_0() {
fn test_windows_iterator_0() {
let v = &[1, 2, 3, 4];
let _it = v.windows(0);
}
#[test]
fn test_chunksator() {
fn test_chunks_iterator() {
let v = &[1, 2, 3, 4, 5];
assert_eq!(v.chunks(2).len(), 3);
@ -972,13 +972,13 @@ fn test_chunksator() {
#[test]
#[should_panic]
fn test_chunksator_0() {
fn test_chunks_iterator_0() {
let v = &[1, 2, 3, 4];
let _it = v.chunks(0);
}
#[test]
fn test_chunks_exactator() {
fn test_chunks_exact_iterator() {
let v = &[1, 2, 3, 4, 5];
assert_eq!(v.chunks_exact(2).len(), 2);
@ -996,13 +996,13 @@ fn test_chunks_exactator() {
#[test]
#[should_panic]
fn test_chunks_exactator_0() {
fn test_chunks_exact_iterator_0() {
let v = &[1, 2, 3, 4];
let _it = v.chunks_exact(0);
}
#[test]
fn test_rchunksator() {
fn test_rchunks_iterator() {
let v = &[1, 2, 3, 4, 5];
assert_eq!(v.rchunks(2).len(), 3);
@ -1020,13 +1020,13 @@ fn test_rchunksator() {
#[test]
#[should_panic]
fn test_rchunksator_0() {
fn test_rchunks_iterator_0() {
let v = &[1, 2, 3, 4];
let _it = v.rchunks(0);
}
#[test]
fn test_rchunks_exactator() {
fn test_rchunks_exact_iterator() {
let v = &[1, 2, 3, 4, 5];
assert_eq!(v.rchunks_exact(2).len(), 2);
@ -1044,7 +1044,7 @@ fn test_rchunks_exactator() {
#[test]
#[should_panic]
fn test_rchunks_exactator_0() {
fn test_rchunks_exact_iterator_0() {
let v = &[1, 2, 3, 4];
let _it = v.rchunks_exact(0);
}
@ -1219,7 +1219,7 @@ fn test_ends_with() {
}
#[test]
fn test_mut_splitator() {
fn test_mut_split_iterator() {
let mut xs = [0, 1, 0, 2, 3, 0, 0, 4, 5, 0];
assert_eq!(xs.split_mut(|x| *x == 0).count(), 6);
for slice in xs.split_mut(|x| *x == 0) {
@ -1235,7 +1235,7 @@ fn test_mut_splitator() {
}
#[test]
fn test_mut_splitator_rev() {
fn test_mut_split_iterator_rev() {
let mut xs = [1, 2, 0, 3, 4, 0, 0, 5, 6, 0];
for slice in xs.split_mut(|x| *x == 0).rev().take(4) {
slice.reverse();

View File

@ -2470,7 +2470,7 @@ fn test_vec_dedup_panicking() {
// Regression test for issue #82533
#[test]
fn test_extend_from_within_panicing_clone() {
fn test_extend_from_within_panicking_clone() {
struct Panic<'dc> {
drop_count: &'dc AtomicU32,
aaaaa: bool,

View File

@ -109,14 +109,14 @@ impl<'a, 'b: 'a> DebugStruct<'a, 'b> {
/// .field("bar", &self.bar) // We add `bar` field.
/// .field("another", &self.another) // We add `another` field.
/// // We even add a field which doesn't exist (because why not?).
/// .field("not_existing_field", &1)
/// .field("nonexistent_field", &1)
/// .finish() // We're good to go!
/// }
/// }
///
/// assert_eq!(
/// format!("{:?}", Bar { bar: 10, another: "Hello World".to_string() }),
/// "Bar { bar: 10, another: \"Hello World\", not_existing_field: 1 }",
/// "Bar { bar: 10, another: \"Hello World\", nonexistent_field: 1 }",
/// );
/// ```
#[stable(feature = "debug_builders", since = "1.2.0")]

View File

@ -2474,7 +2474,7 @@ extern "rust-intrinsic" {
/// This macro should be called as `assert_unsafe_precondition!([Generics](name: Type) => Expression)`
/// where the names specified will be moved into the macro as captured variables, and defines an item
/// to call `const_eval_select` on. The tokens inside the square brackets are used to denote generics
/// for the function declaractions and can be omitted if there is no generics.
/// for the function declarations and can be omitted if there is no generics.
///
/// # Safety
///
@ -2733,7 +2733,7 @@ pub const unsafe fn copy<T>(src: *const T, dst: *mut T, count: usize) {
// SAFETY: the safety contract for `copy` must be upheld by the caller.
unsafe {
assert_unsafe_precondition!(
"ptr::copy requires that both pointer arguments are aligned aligned and non-null",
"ptr::copy requires that both pointer arguments are aligned and non-null",
[T](src: *const T, dst: *mut T) =>
is_aligned_and_not_null(src) && is_aligned_and_not_null(dst)
);

View File

@ -136,26 +136,12 @@ where
}
#[unstable(feature = "trusted_len", issue = "37572")]
unsafe impl<T, I, F, const N: usize> TrustedLen for FlatMap<I, [T; N], F>
unsafe impl<I, U, F> TrustedLen for FlatMap<I, U, F>
where
I: TrustedLen,
F: FnMut(I::Item) -> [T; N],
{
}
#[unstable(feature = "trusted_len", issue = "37572")]
unsafe impl<'a, T, I, F, const N: usize> TrustedLen for FlatMap<I, &'a [T; N], F>
where
I: TrustedLen,
F: FnMut(I::Item) -> &'a [T; N],
{
}
#[unstable(feature = "trusted_len", issue = "37572")]
unsafe impl<'a, T, I, F, const N: usize> TrustedLen for FlatMap<I, &'a mut [T; N], F>
where
I: TrustedLen,
F: FnMut(I::Item) -> &'a mut [T; N],
I: Iterator,
U: IntoIterator,
F: FnMut(I::Item) -> U,
FlattenCompat<Map<I, F>, <U as IntoIterator>::IntoIter>: TrustedLen,
{
}
@ -298,8 +284,8 @@ where
#[unstable(feature = "trusted_len", issue = "37572")]
unsafe impl<I> TrustedLen for Flatten<I>
where
I: TrustedLen,
<I as Iterator>::Item: TrustedConstSize,
I: Iterator<Item: IntoIterator>,
FlattenCompat<I, <I::Item as IntoIterator>::IntoIter>: TrustedLen,
{
}
@ -660,6 +646,27 @@ where
}
}
unsafe impl<const N: usize, I, T> TrustedLen
for FlattenCompat<I, <[T; N] as IntoIterator>::IntoIter>
where
I: TrustedLen<Item = [T; N]>,
{
}
unsafe impl<'a, const N: usize, I, T> TrustedLen
for FlattenCompat<I, <&'a [T; N] as IntoIterator>::IntoIter>
where
I: TrustedLen<Item = &'a [T; N]>,
{
}
unsafe impl<'a, const N: usize, I, T> TrustedLen
for FlattenCompat<I, <&'a mut [T; N] as IntoIterator>::IntoIter>
where
I: TrustedLen<Item = &'a mut [T; N]>,
{
}
trait ConstSizeIntoIterator: IntoIterator {
// FIXME(#31844): convert to an associated const once specialization supports that
fn size() -> Option<usize>;
@ -696,19 +703,6 @@ impl<T, const N: usize> ConstSizeIntoIterator for &mut [T; N] {
}
}
#[doc(hidden)]
#[unstable(feature = "std_internals", issue = "none")]
// FIXME(#20400): Instead of this helper trait there should be multiple impl TrustedLen for Flatten<>
// blocks with different bounds on Iterator::Item but the compiler erroneously considers them overlapping
pub unsafe trait TrustedConstSize: IntoIterator {}
#[unstable(feature = "std_internals", issue = "none")]
unsafe impl<T, const N: usize> TrustedConstSize for [T; N] {}
#[unstable(feature = "std_internals", issue = "none")]
unsafe impl<T, const N: usize> TrustedConstSize for &'_ [T; N] {}
#[unstable(feature = "std_internals", issue = "none")]
unsafe impl<T, const N: usize> TrustedConstSize for &'_ mut [T; N] {}
#[inline]
fn and_then_or_clear<T, U>(opt: &mut Option<T>, f: impl FnOnce(&mut T) -> Option<U>) -> Option<U> {
let x = f(opt.as_mut()?);

View File

@ -42,7 +42,7 @@ the successful result of some computation, `Ok(T)`, or error types that
represent an anticipated runtime failure mode of that computation, `Err(E)`.
`Result` is used alongside user defined types which represent the various
anticipated runtime failure modes that the associated computation could
encounter. `Result` must be propagated manually, often with the the help of the
encounter. `Result` must be propagated manually, often with the help of the
`?` operator and `Try` trait, and they must be reported manually, often with
the help of the `Error` trait.

View File

@ -264,7 +264,7 @@ impl<T: ?Sized> *const T {
let dest_addr = addr as isize;
let offset = dest_addr.wrapping_sub(self_addr);
// This is the canonical desugarring of this operation
// This is the canonical desugaring of this operation
self.wrapping_byte_offset(offset)
}

View File

@ -2126,7 +2126,7 @@ mod new_fn_ptr_impl {
/// assert_eq!(unsafe { raw_f2.read_unaligned() }, 2);
/// ```
///
/// See [`addr_of_mut`] for how to create a pointer to unininitialized data.
/// See [`addr_of_mut`] for how to create a pointer to uninitialized data.
/// Doing that with `addr_of` would not make much sense since one could only
/// read the data, and that would be Undefined Behavior.
#[stable(feature = "raw_ref_macros", since = "1.51.0")]

View File

@ -270,7 +270,7 @@ impl<T: ?Sized> *mut T {
let dest_addr = addr as isize;
let offset = dest_addr.wrapping_sub(self_addr);
// This is the canonical desugarring of this operation
// This is the canonical desugaring of this operation
self.wrapping_byte_offset(offset)
}

View File

@ -4451,7 +4451,7 @@ impl<T, const N: usize> SlicePattern for [T; N] {
/// This will do `binomial(N + 1, 2) = N * (N + 1) / 2 = 0, 1, 3, 6, 10, ..`
/// comparison operations.
fn get_many_check_valid<const N: usize>(indices: &[usize; N], len: usize) -> bool {
// NB: The optimzer should inline the loops into a sequence
// NB: The optimizer should inline the loops into a sequence
// of instructions without additional branching.
let mut valid = true;
for (i, &idx) in indices.iter().enumerate() {

View File

@ -24,7 +24,7 @@ struct NoCopyNoDebug;
struct NoDebug;
test!(
capture_with_non_copyable_and_non_debugabble_elem_has_correct_params,
capture_with_non_copyable_and_non_debuggable_elem_has_correct_params,
NoCopyNoDebug,
None,
"N/A"
@ -32,6 +32,6 @@ test!(
test!(capture_with_non_copyable_elem_has_correct_params, NoCopy, None, "N/A");
test!(capture_with_non_debugabble_elem_has_correct_params, NoDebug, None, "N/A");
test!(capture_with_non_debuggable_elem_has_correct_params, NoDebug, None, "N/A");
test!(capture_with_copyable_and_debugabble_elem_has_correct_params, 1i32, Some(1i32), "1");
test!(capture_with_copyable_and_debuggable_elem_has_correct_params, 1i32, Some(1i32), "1");

View File

@ -10,7 +10,7 @@ fn once_cell() {
c.get_or_init(|| 92);
assert_eq!(c.get(), Some(&92));
c.get_or_init(|| panic!("Kabom!"));
c.get_or_init(|| panic!("Kaboom!"));
assert_eq!(c.get(), Some(&92));
}

View File

@ -170,7 +170,7 @@ fn test_can_not_overflow() {
for base in 2..=36 {
let num = (<$t>::MAX as u128) + 1;
// Calcutate the string length for the smallest overflowing number:
// Calculate the string length for the smallest overflowing number:
let max_len_string = format_radix(num, base as u128);
// Ensure that string length is deemed to potentially overflow:
assert!(can_overflow::<$t>(base, &max_len_string));

View File

@ -831,9 +831,9 @@ fn partial_line_buffered_after_line_write() {
assert_eq!(&writer.get_ref().buffer, b"Line 1\nLine 2\nLine 3");
}
/// Test that, given a partial line that exceeds the length of
/// LineBuffer's buffer (that is, without a trailing newline), that that
/// line is written to the inner writer
/// Test that for calls to LineBuffer::write where the passed bytes do not contain
/// a newline and on their own are greater in length than the internal buffer, the
/// passed bytes are immediately written to the inner writer.
#[test]
fn long_line_flushed() {
let writer = ProgrammableSink::default();
@ -844,9 +844,10 @@ fn long_line_flushed() {
}
/// Test that, given a very long partial line *after* successfully
/// flushing a complete line, that that line is buffered unconditionally,
/// and no additional writes take place. This assures the property that
/// `write` should make at-most-one attempt to write new data.
/// flushing a complete line, the very long partial line is buffered
/// unconditionally, and no additional writes take place. This assures
/// the property that `write` should make at-most-one attempt to write
/// new data.
#[test]
fn line_long_tail_not_flushed() {
let writer = ProgrammableSink::default();

View File

@ -36,7 +36,7 @@ fn initialize_unfilled() {
}
#[test]
fn addvance_filled() {
fn advance_filled() {
let buf: &mut [_] = &mut [0; 16];
let mut rbuf: BorrowedBuf<'_> = buf.into();

View File

@ -1925,7 +1925,7 @@ mod type_keyword {}
/// `unsafe_op_in_unsafe_fn` lint can be enabled to warn against that and require explicit unsafe
/// blocks even inside `unsafe fn`.
///
/// See the [Rustnomicon] and the [Reference] for more information.
/// See the [Rustonomicon] and the [Reference] for more information.
///
/// # Examples
///
@ -2129,7 +2129,7 @@ mod type_keyword {}
/// [`impl`]: keyword.impl.html
/// [raw pointers]: ../reference/types/pointer.html
/// [memory safety]: ../book/ch19-01-unsafe-rust.html
/// [Rustnomicon]: ../nomicon/index.html
/// [Rustonomicon]: ../nomicon/index.html
/// [nomicon-soundness]: ../nomicon/safe-unsafe-meaning.html
/// [soundness]: https://rust-lang.github.io/unsafe-code-guidelines/glossary.html#soundness-of-code--of-a-library
/// [Reference]: ../reference/unsafety.html

View File

@ -450,7 +450,7 @@ impl AsHandle for OwnedHandle {
#[inline]
fn as_handle(&self) -> BorrowedHandle<'_> {
// Safety: `OwnedHandle` and `BorrowedHandle` have the same validity
// invariants, and the `BorrowdHandle` is bounded by the lifetime
// invariants, and the `BorrowedHandle` is bounded by the lifetime
// of `&self`.
unsafe { BorrowedHandle::borrow_raw(self.as_raw_handle()) }
}

View File

@ -260,7 +260,7 @@ impl AsSocket for OwnedSocket {
#[inline]
fn as_socket(&self) -> BorrowedSocket<'_> {
// Safety: `OwnedSocket` and `BorrowedSocket` have the same validity
// invariants, and the `BorrowdSocket` is bounded by the lifetime
// invariants, and the `BorrowedSocket` is bounded by the lifetime
// of `&self`.
unsafe { BorrowedSocket::borrow_raw(self.as_raw_socket()) }
}

View File

@ -24,7 +24,7 @@ fn sync_once_cell() {
assert_eq!(ONCE_CELL.get(), Some(&92));
});
ONCE_CELL.get_or_init(|| panic!("Kabom!"));
ONCE_CELL.get_or_init(|| panic!("Kaboom!"));
assert_eq!(ONCE_CELL.get(), Some(&92));
}

View File

@ -7,7 +7,7 @@ use crate::panic::{RefUnwindSafe, UnwindSafe};
use crate::sync::atomic::{AtomicUsize, Ordering::Relaxed};
use crate::sys::locks as sys;
/// A re-entrant mutual exclusion
/// A reentrant mutual exclusion
///
/// This mutex will block *other* threads waiting for the lock to become
/// available. The thread which has already locked the mutex can lock it

View File

@ -58,7 +58,7 @@ IMAGE_BASE:
globvar DEBUG 1
/* The base address (relative to enclave start) of the enclave text section */
globvar TEXT_BASE 8
/* The size in bytes of enclacve text section */
/* The size in bytes of enclave text section */
globvar TEXT_SIZE 8
/* The base address (relative to enclave start) of the enclave .eh_frame_hdr section */
globvar EH_FRM_HDR_OFFSET 8
@ -66,7 +66,7 @@ IMAGE_BASE:
globvar EH_FRM_HDR_LEN 8
/* The base address (relative to enclave start) of the enclave .eh_frame section */
globvar EH_FRM_OFFSET 8
/* The size in bytes of enclacve .eh_frame section */
/* The size in bytes of enclave .eh_frame section */
globvar EH_FRM_LEN 8
.org .Lxsave_clear+512

View File

@ -735,7 +735,7 @@ impl ExitStatus {
// true on all actual versions of Unix, is widely assumed, and is specified in SuS
// https://pubs.opengroup.org/onlinepubs/9699919799/functions/wait.html. If it is not
// true for a platform pretending to be Unix, the tests (our doctests, and also
// procsss_unix/tests.rs) will spot it. `ExitStatusError::code` assumes this too.
// process_unix/tests.rs) will spot it. `ExitStatusError::code` assumes this too.
match NonZero_c_int::try_from(self.0) {
/* was nonzero */ Ok(failure) => Err(ExitStatusError(failure)),
/* was zero, couldn't convert */ Err(_) => Ok(()),

View File

@ -199,7 +199,7 @@ impl ExitStatus {
// true on all actual versions of Unix, is widely assumed, and is specified in SuS
// https://pubs.opengroup.org/onlinepubs/9699919799/functions/wait.html. If it is not
// true for a platform pretending to be Unix, the tests (our doctests, and also
// procsss_unix/tests.rs) will spot it. `ExitStatusError::code` assumes this too.
// process_unix/tests.rs) will spot it. `ExitStatusError::code` assumes this too.
match NonZero_c_int::try_from(self.0) {
Ok(failure) => Err(ExitStatusError(failure)),
Err(_) => Ok(()),

View File

@ -494,7 +494,7 @@ impl Builder {
MaybeDangling(mem::MaybeUninit::new(x))
}
fn into_inner(self) -> T {
// SAFETY: we are always initiailized.
// SAFETY: we are always initialized.
let ret = unsafe { self.0.assume_init_read() };
// Make sure we don't drop.
mem::forget(self);
@ -503,7 +503,7 @@ impl Builder {
}
impl<T> Drop for MaybeDangling<T> {
fn drop(&mut self) {
// SAFETY: we are always initiailized.
// SAFETY: we are always initialized.
unsafe { self.0.assume_init_drop() };
}
}

View File

@ -3,6 +3,7 @@
- [What is rustdoc?](what-is-rustdoc.md)
- [Command-line arguments](command-line-arguments.md)
- [How to read rustdoc output](how-to-read-rustdoc.md)
- [In-doc settings](read-documentation/in-doc-settings.md)
- [How to write documentation](how-to-write-documentation.md)
- [What to include (and exclude)](write-documentation/what-to-include.md)
- [The `#[doc]` attribute](write-documentation/the-doc-attribute.md)

View File

@ -68,7 +68,7 @@ Typing in the search bar instantly searches the available documentation for
the string entered with a fuzzy matching algorithm that is tolerant of minor
typos.
By default, the search results give are "In Names",
By default, the search results given are "In Names",
meaning that the fuzzy match is made against the names of items.
Matching names are shown on the left, and the first few words of their
descriptions are given on the right.
@ -105,11 +105,6 @@ will match these queries:
But it *does not* match `Result<Vec, u8>` or `Result<u8<Vec>>`.
### Changing displayed theme
You can change the displayed theme by opening the settings menu (the gear
icon in the upper right) and then pick a new one from there.
### Shortcuts
Pressing `S` while focused elsewhere on the page will move focus to the

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 43 KiB

View File

@ -0,0 +1,64 @@
# Rustdoc in-doc settings
Rustdoc's HTML output includes a settings menu, and this chapter describes what
each setting in this menu does.
It can be accessed by clicking on the gear button
(<i class="fa fa-cog" aria-hidden="true"></i>) in the upper right.
## Changing displayed theme
It is possible to change the theme. If you pick the "system preference", you
will be able to see two new sub-menus: "Preferred light theme" and "Preferred
dark theme". It means that if your system preference is set to "light", then
rustdoc will use the theme you selected in "Preferred light theme".
## Auto-hide item contents for large items
If the type definition contains more than 12 items, and this setting is enabled,
it'll collapse them by default. You can see them by clicking on the `[+]` button
to expand them.
A good example of this setting in use can be seen in the
[`Iterator`](https://doc.rust-lang.org/stable/std/iter/trait.Iterator.html) doc
page:
![Collapsed long item](../images/collapsed-long-item.png)
## Auto-hide item methods' documentation
If enabled, this setting will collapse all trait implementations blocks. It is
convenient if you just want an overview of all the methods available. You can
still see a method's documentation by expanding it.
## Auto-hide trait implementation documentation
If enabled, this setting will collapse all trait implementations blocks (you can
see them in the "Trait Implementations" section). It is convenient if you just
want an overview of all the trait implemented on a type. You can still see
a trait implementation's associated items by expanding it.
Example:
![Collapsed trait implementations](../images/collapsed-trait-impls.png)
## Directly go to item in search if there is only one result
If this setting is enabled, you will directly be taken to the result page if
your search only returned one element. Useful if you know exactly what you're
looking for and want to be taken there directly and not waste time selecting the
only search result.
## Show line numbers on code examples
If enabled, this setting will add line numbers to the code examples in the
documentation. It provides a visual aide for the code reading.
## Disable keyboard shortcuts
If this setting is enabled, the keyboard shortcuts will be disabled. It's useful
in case some of these shortcuts are already used by a web extension you're
using.
To see the full list of the rustdoc keyboard shortcuts, you can open the help
menu (the button with the question mark on the left of the setting menu button).

View File

@ -741,8 +741,10 @@ impl<'a, 'tcx> TypeFolder<TyCtxt<'tcx>> for RegionReplacer<'a, 'tcx> {
fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
match *r {
// These are the regions that can be seen in the AST.
ty::ReVar(vid) => self.vid_to_region.get(&vid).cloned().unwrap_or(r),
_ => r,
ty::ReEarlyBound(_) | ty::ReStatic | ty::ReLateBound(..) | ty::ReError(_) => r,
r => bug!("unexpected region: {r:?}"),
}
}
}

View File

@ -679,6 +679,10 @@ pub(crate) fn make_test(
// parse the source, but only has false positives, not false
// negatives.
if s.contains(crate_name) {
// rustdoc implicitly inserts an `extern crate` item for the own crate
// which may be unused, so we need to allow the lint.
prog.push_str(&format!("#[allow(unused_extern_crates)]\n"));
prog.push_str(&format!("extern crate r#{crate_name};\n"));
line_offset += 1;
}

View File

@ -38,6 +38,7 @@ fn make_test_crate_name() {
let input = "use asdf::qwop;
assert_eq!(2+2, 4);";
let expected = "#![allow(unused)]
#[allow(unused_extern_crates)]
extern crate r#asdf;
fn main() {
use asdf::qwop;
@ -128,6 +129,7 @@ fn make_test_opts_attrs() {
let input = "use asdf::qwop;
assert_eq!(2+2, 4);";
let expected = "#![feature(sick_rad)]
#[allow(unused_extern_crates)]
extern crate r#asdf;
fn main() {
use asdf::qwop;
@ -141,6 +143,7 @@ assert_eq!(2+2, 4);
opts.attrs.push("feature(hella_dope)".to_string());
let expected = "#![feature(sick_rad)]
#![feature(hella_dope)]
#[allow(unused_extern_crates)]
extern crate r#asdf;
fn main() {
use asdf::qwop;
@ -236,6 +239,7 @@ assert_eq!(asdf::foo, 4);";
let expected = "#![allow(unused)]
extern crate hella_qwop;
#[allow(unused_extern_crates)]
extern crate r#asdf;
fn main() {
assert_eq!(asdf::foo, 4);

View File

@ -279,7 +279,10 @@ impl<'tcx> FormatRenderer<'tcx> for JsonRenderer<'tcx> {
p.push(output.index.get(&output.root).unwrap().name.clone().unwrap());
p.set_extension("json");
let mut file = BufWriter::new(try_err!(File::create(&p), p));
serde_json::ser::to_writer(&mut file, &output).unwrap();
self.tcx
.sess
.time("rustdoc_json_serialization", || serde_json::ser::to_writer(&mut file, &output))
.unwrap();
try_err!(file.flush(), p);
Ok(())

View File

@ -385,10 +385,12 @@ pub fn check(path: &Path, bad: &mut bool) {
}
if filename != "style.rs" {
if trimmed.contains("TODO") {
err("TODO is deprecated; use FIXME")
err(
"TODO is used for tasks that should be done before merging a PR; If you want to leave a message in the codebase use FIXME",
)
}
if trimmed.contains("//") && trimmed.contains(" XXX") {
err("XXX is deprecated; use FIXME")
err("Instead of XXX use FIXME")
}
if any_problematic_line {
for s in problematic_consts_strings.iter() {

View File

@ -10,4 +10,4 @@
pub fn dummy() {}
// ensure that `extern crate foo;` was inserted into code snips automatically:
// @matches foo/index.html '//a[@class="test-arrow"][@href="https://example.com/?code=%23!%5Ballow(unused)%5D%0Aextern+crate+r%23foo;%0Afn+main()+%7B%0Ause+foo::dummy;%0Adummy();%0A%7D&edition=2015"]' "Run"
// @matches foo/index.html '//a[@class="test-arrow"][@href="https://example.com/?code=%23!%5Ballow(unused)%5D%0A%23%5Ballow(unused_extern_crates)%5D%0Aextern+crate+r%23foo;%0Afn+main()+%7B%0Ause+foo::dummy;%0Adummy();%0A%7D&edition=2015"]' "Run"

View File

@ -72,4 +72,13 @@ fn main() {
} else {
&0
};
#[derive(PartialEq, Eq)]
struct Foo;
let foo = Foo;
let bar = &Foo;
if foo == bar {
//~^ ERROR mismatched types
}
}

View File

@ -175,6 +175,19 @@ LL | || };
| |_____`if` and `else` have incompatible types
| expected `i32`, found `&{integer}`
error: aborting due to 13 previous errors
error[E0308]: mismatched types
--> $DIR/deref-suggestion.rs:81:15
|
LL | if foo == bar {
| --- ^^^ expected `Foo`, found `&Foo`
| |
| expected because this is `Foo`
|
help: consider dereferencing the borrow
|
LL | if foo == *bar {
| +
error: aborting due to 14 previous errors
For more information about this error, try `rustc --explain E0308`.

View File

@ -0,0 +1,10 @@
fn main() {
// this closure is fine, and should not get any error annotations
let em = |v: f64| -> f64 { v };
let x: f64 = em(1i16.into());
let y: f64 = 0.01f64 * 1i16.into();
//~^ ERROR type annotations needed
//~| HELP try using a fully qualified path
}

View File

@ -0,0 +1,17 @@
error[E0284]: type annotations needed
--> $DIR/issue-70082.rs:7:33
|
LL | let y: f64 = 0.01f64 * 1i16.into();
| - ^^^^
| |
| type must be known at this point
|
= note: cannot satisfy `<f64 as Mul<_>>::Output == f64`
help: try using a fully qualified path to specify the expected types
|
LL | let y: f64 = 0.01f64 * <i16 as Into<T>>::into(1i16);
| +++++++++++++++++++++++ ~
error: aborting due to previous error
For more information about this error, try `rustc --explain E0284`.