diff --git a/compiler/rustc_builtin_macros/messages.ftl b/compiler/rustc_builtin_macros/messages.ftl index fca6012a408c1..74049406426ed 100644 --- a/compiler/rustc_builtin_macros/messages.ftl +++ b/compiler/rustc_builtin_macros/messages.ftl @@ -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 diff --git a/compiler/rustc_builtin_macros/src/asm.rs b/compiler/rustc_builtin_macros/src/asm.rs index 8c1579baacb08..bcdd58a090162 100644 --- a/compiler/rustc_builtin_macros/src/asm.rs +++ b/compiler/rustc_builtin_macros/src/asm.rs @@ -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>, 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, + 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, +} + +#[derive(Diagnostic)] +#[diag(builtin_macros_asm_pure_no_output)] +pub(crate) struct AsmPureNoOutput { + #[primary_span] + pub(crate) spans: Vec, +} + +#[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, +} diff --git a/compiler/rustc_builtin_macros/src/test.rs b/compiler/rustc_builtin_macros/src/test.rs index 79d8be2484b59..49ee276af4e6f 100644 --- a/compiler/rustc_builtin_macros/src/test.rs +++ b/compiler/rustc_builtin_macros/src/test.rs @@ -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; } diff --git a/compiler/rustc_builtin_macros/src/test_harness.rs b/compiler/rustc_builtin_macros/src/test_harness.rs index 80f497333a632..be4ba66c082aa 100644 --- a/compiler/rustc_builtin_macros/src/test_harness.rs +++ b/compiler/rustc_builtin_macros/src/test_harness.rs @@ -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 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 diff --git a/compiler/rustc_codegen_ssa/messages.ftl b/compiler/rustc_codegen_ssa/messages.ftl index 85a96e3e89c05..375fdec10075a 100644 --- a/compiler/rustc_codegen_ssa/messages.ftl +++ b/compiler/rustc_codegen_ssa/messages.ftl @@ -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 diff --git a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs index 9bfe426c00766..5bd42622f2c33 100644 --- a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs +++ b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs @@ -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 { 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 { 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 } } diff --git a/compiler/rustc_codegen_ssa/src/errors.rs b/compiler/rustc_codegen_ssa/src/errors.rs index 4493176667867..cf4893b822651 100644 --- a/compiler/rustc_codegen_ssa/src/errors.rs +++ b/compiler/rustc_codegen_ssa/src/errors.rs @@ -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, +} diff --git a/compiler/rustc_codegen_ssa/src/target_features.rs b/compiler/rustc_codegen_ssa/src/target_features.rs index 611dd3d1cd18a..a936b62dd4eba 100644 --- a/compiler/rustc_codegen_ssa/src/target_features.rs +++ b/compiler/rustc_codegen_ssa/src/target_features.rs @@ -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), + }); } } } diff --git a/compiler/rustc_expand/messages.ftl b/compiler/rustc_expand/messages.ftl index 5d999d0db5dbd..70d2718b70639 100644 --- a/compiler/rustc_expand/messages.ftl +++ b/compiler/rustc_expand/messages.ftl @@ -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 diff --git a/compiler/rustc_expand/src/errors.rs b/compiler/rustc_expand/src/errors.rs index e5102a952e741..e3a0ae3570eb0 100644 --- a/compiler/rustc_expand/src/errors.rs +++ b/compiler/rustc_expand/src/errors.rs @@ -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, +} diff --git a/compiler/rustc_expand/src/mbe/macro_check.rs b/compiler/rustc_expand/src/mbe/macro_check.rs index 5be134f4e664c..75b6396f0be38 100644 --- a/compiler/rustc_expand/src/mbe/macro_check.rs +++ b/compiler/rustc_expand/src/mbe/macro_check.rs @@ -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() }); diff --git a/compiler/rustc_hir_analysis/messages.ftl b/compiler/rustc_hir_analysis/messages.ftl index f32ae509e335a..5d45d09797b0b 100644 --- a/compiler/rustc_hir_analysis/messages.ftl +++ b/compiler/rustc_hir_analysis/messages.ftl @@ -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 diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs index 65c2f5955cdd0..68e957f9d8e3a 100644 --- a/compiler/rustc_hir_analysis/src/check/check.rs +++ b/compiler/rustc_hir_analysis/src/check/check.rs @@ -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. diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs index 0eafab017c7f3..aab005dacf3e2 100644 --- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs +++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs @@ -1576,17 +1576,10 @@ impl<'tcx> TypeVisitor> 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 diff --git a/compiler/rustc_hir_analysis/src/coherence/mod.rs b/compiler/rustc_hir_analysis/src/coherence/mod.rs index ac393ee15a684..cd2ec2bef20f9 100644 --- a/compiler/rustc_hir_analysis/src/coherence/mod.rs +++ b/compiler/rustc_hir_analysis/src/coherence/mod.rs @@ -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; } } diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs index 9fe0c07814ed8..41547dd2a754d 100644 --- a/compiler/rustc_hir_analysis/src/collect.rs +++ b/compiler/rustc_hir_analysis/src/collect.rs @@ -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") } diff --git a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs index 3cb217335bda0..1c496f867a063 100644 --- a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs +++ b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs @@ -455,13 +455,9 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> { .collect::>(); 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 }); } } diff --git a/compiler/rustc_hir_analysis/src/errors.rs b/compiler/rustc_hir_analysis/src/errors.rs index cfce2463b1872..f82169dee988e 100644 --- a/compiler/rustc_hir_analysis/src/errors.rs +++ b/compiler/rustc_hir_analysis/src/errors.rs @@ -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, + #[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, +} diff --git a/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs b/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs index eb2fc395223ed..56f456e55577e 100644 --- a/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs +++ b/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs @@ -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 }); } _ => {} } diff --git a/compiler/rustc_hir_typeck/messages.ftl b/compiler/rustc_hir_typeck/messages.ftl index 6d40df7d0ccfa..603ea1440e9ca 100644 --- a/compiler/rustc_hir_typeck/messages.ftl +++ b/compiler/rustc_hir_typeck/messages.ftl @@ -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 diff --git a/compiler/rustc_hir_typeck/src/demand.rs b/compiler/rustc_hir_typeck/src/demand.rs index 525acfdaa8124..b8222820cf7a4 100644 --- a/compiler/rustc_hir_typeck/src/demand.rs +++ b/compiler/rustc_hir_typeck/src/demand.rs @@ -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" diff --git a/compiler/rustc_hir_typeck/src/errors.rs b/compiler/rustc_hir_typeck/src/errors.rs index 5be78416e6128..48c40d216034e 100644 --- a/compiler/rustc_hir_typeck/src/errors.rs +++ b/compiler/rustc_hir_typeck/src/errors.rs @@ -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, +} diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs index 955463c14348c..f42c825d9e8b1 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs @@ -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; } diff --git a/compiler/rustc_hir_typeck/src/pat.rs b/compiler/rustc_hir_typeck/src/pat.rs index 7160d1c67b251..d69a16d45ae54 100644 --- a/compiler/rustc_hir_typeck/src/pat.rs +++ b/compiler/rustc_hir_typeck/src/pat.rs @@ -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 diff --git a/compiler/rustc_lint/messages.ftl b/compiler/rustc_lint/messages.ftl index 3d1b8f8ed95ac..3c6dbb466db7a 100644 --- a/compiler/rustc_lint/messages.ftl +++ b/compiler/rustc_lint/messages.ftl @@ -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` diff --git a/compiler/rustc_lint/src/internal.rs b/compiler/rustc_lint/src/internal.rs index 4ac589c2e10f0..595b50c4063ca 100644 --- a/compiler/rustc_lint/src/internal.rs +++ b/compiler/rustc_lint/src/internal.rs @@ -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. diff --git a/compiler/rustc_lint/src/lib.rs b/compiler/rustc_lint/src/lib.rs index 76f0725790777..319eb2ea445ed 100644 --- a/compiler/rustc_lint/src/lib.rs +++ b/compiler/rustc_lint/src/lib.rs @@ -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)); diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs index 1d5e02369f528..848f6a9ecb532 100644 --- a/compiler/rustc_lint/src/lints.rs +++ b/compiler/rustc_lint/src/lints.rs @@ -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> { diff --git a/compiler/rustc_middle/src/ty/subst.rs b/compiler/rustc_middle/src/ty/subst.rs index 63b2acdbe4e5d..d05d3e2d3dcf5 100644 --- a/compiler/rustc_middle/src/ty/subst.rs +++ b/compiler/rustc_middle/src/ty/subst.rs @@ -829,7 +829,13 @@ impl<'a, 'tcx> TypeFolder> 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:?}"), } } diff --git a/compiler/rustc_parse/messages.ftl b/compiler/rustc_parse/messages.ftl index f11d0ed0f0109..d45fa90a11b08 100644 --- a/compiler/rustc_parse/messages.ftl +++ b/compiler/rustc_parse/messages.ftl @@ -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 diff --git a/compiler/rustc_parse/src/errors.rs b/compiler/rustc_parse/src/errors.rs index 069217165fabe..b0e1189851a1b 100644 --- a/compiler/rustc_parse/src/errors.rs +++ b/compiler/rustc_parse/src/errors.rs @@ -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, +} + +#[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, + 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, +} diff --git a/compiler/rustc_parse/src/lexer/mod.rs b/compiler/rustc_parse/src/lexer/mod.rs index ad9b20f9c767a..a4a75fcb96995 100644 --- a/compiler/rustc_parse/src/lexer/mod.rs +++ b/compiler/rustc_parse/src/lexer/mod.rs @@ -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)) diff --git a/compiler/rustc_parse/src/parser/generics.rs b/compiler/rustc_parse/src/parser/generics.rs index f8ef1307c988e..61a7ae93bfa8b 100644 --- a/compiler/rustc_parse/src/parser/generics.rs +++ b/compiler/rustc_parse/src/parser/generics.rs @@ -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 { diff --git a/compiler/rustc_parse/src/parser/path.rs b/compiler/rustc_parse/src/parser/path.rs index c25c23d849f04..6cceb47ff8384 100644 --- a/compiler/rustc_parse/src/parser/path.rs +++ b/compiler/rustc_parse/src/parser/path.rs @@ -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::>(), - "unexpected generic arguments in path", - ) - .emit(); + let span = path + .segments + .iter() + .filter_map(|segment| segment.args.as_ref()) + .map(|arg| arg.span()) + .collect::>(); + 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 => { diff --git a/compiler/rustc_parse/src/parser/ty.rs b/compiler/rustc_parse/src/parser/ty.rs index 400c8dbe9bc6b..f5f6788362ba9 100644 --- a/compiler/rustc_parse/src/parser/ty.rs +++ b/compiler/rustc_parse/src/parser/ty.rs @@ -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 { diff --git a/compiler/rustc_resolve/messages.ftl b/compiler/rustc_resolve/messages.ftl index 192badcbc37ea..32409499047cd 100644 --- a/compiler/rustc_resolve/messages.ftl +++ b/compiler/rustc_resolve/messages.ftl @@ -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 diff --git a/compiler/rustc_resolve/src/build_reduced_graph.rs b/compiler/rustc_resolve/src/build_reduced_graph.rs index 967c9e22fb26c..3799679cb1eac 100644 --- a/compiler/rustc_resolve/src/build_reduced_graph.rs +++ b/compiler/rustc_resolve/src/build_reduced_graph.rs @@ -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| { diff --git a/compiler/rustc_resolve/src/errors.rs b/compiler/rustc_resolve/src/errors.rs index 6197af105a965..4f9f1c7e85648 100644 --- a/compiler/rustc_resolve/src/errors.rs +++ b/compiler/rustc_resolve/src/errors.rs @@ -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, +} diff --git a/compiler/rustc_resolve/src/macros.rs b/compiler/rustc_resolve/src/macros.rs index 2211fb56ccda1..b30c1cd226cb6 100644 --- a/compiler/rustc_resolve/src/macros.rs +++ b/compiler/rustc_resolve/src/macros.rs @@ -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. diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 70b9088de5064..abf19c30e3deb 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -651,6 +651,7 @@ symbols! { edition_panic, eh_catch_typeinfo, eh_personality, + emit, emit_enum, emit_enum_variant, emit_enum_variant_arg, diff --git a/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs b/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs index 1a566e87dc8e3..996dc329dcb9b 100644 --- a/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs +++ b/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs @@ -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))), diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index 081e4d7cfa47d..af61ca0c29f44 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -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:?}"), }) } diff --git a/library/alloc/src/collections/vec_deque/spec_from_iter.rs b/library/alloc/src/collections/vec_deque/spec_from_iter.rs index 7650492ebdad1..2708c7fe10259 100644 --- a/library/alloc/src/collections/vec_deque/spec_from_iter.rs +++ b/library/alloc/src/collections/vec_deque/spec_from_iter.rs @@ -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() } diff --git a/library/alloc/src/str.rs b/library/alloc/src/str.rs index b87ef59f64a3b..8497740990443 100644 --- a/library/alloc/src/str.rs +++ b/library/alloc/src/str.rs @@ -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>(iter: I) -> bool { + fn case_ignorable_then_cased>(iter: I) -> bool { use core::unicode::{Case_Ignorable, Cased}; match iter.skip_while(|&c| Case_Ignorable(c)).next() { Some(c) => Cased(c), diff --git a/library/alloc/src/vec/in_place_collect.rs b/library/alloc/src/vec/in_place_collect.rs index 87d61deb1eb2f..2f1ee8b03533d 100644 --- a/library/alloc/src/vec/in_place_collect.rs +++ b/library/alloc/src/vec/in_place_collect.rs @@ -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); diff --git a/library/alloc/tests/slice.rs b/library/alloc/tests/slice.rs index 0693beb48c402..9aa5575ca938b 100644 --- a/library/alloc/tests/slice.rs +++ b/library/alloc/tests/slice.rs @@ -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(); diff --git a/library/alloc/tests/vec.rs b/library/alloc/tests/vec.rs index 3ee16f04e92f5..cc4c1f1272865 100644 --- a/library/alloc/tests/vec.rs +++ b/library/alloc/tests/vec.rs @@ -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, diff --git a/library/core/src/fmt/builders.rs b/library/core/src/fmt/builders.rs index 7da49b04aaae9..d1c6b67b27881 100644 --- a/library/core/src/fmt/builders.rs +++ b/library/core/src/fmt/builders.rs @@ -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")] diff --git a/library/core/src/intrinsics.rs b/library/core/src/intrinsics.rs index 39edfd8265b41..741f20cf4c715 100644 --- a/library/core/src/intrinsics.rs +++ b/library/core/src/intrinsics.rs @@ -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(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) ); diff --git a/library/core/src/iter/adapters/flatten.rs b/library/core/src/iter/adapters/flatten.rs index e0308e3360f45..7217e8f2a8ef6 100644 --- a/library/core/src/iter/adapters/flatten.rs +++ b/library/core/src/iter/adapters/flatten.rs @@ -136,26 +136,12 @@ where } #[unstable(feature = "trusted_len", issue = "37572")] -unsafe impl TrustedLen for FlatMap +unsafe impl TrustedLen for FlatMap 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 -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 -where - I: TrustedLen, - F: FnMut(I::Item) -> &'a mut [T; N], + I: Iterator, + U: IntoIterator, + F: FnMut(I::Item) -> U, + FlattenCompat, ::IntoIter>: TrustedLen, { } @@ -298,8 +284,8 @@ where #[unstable(feature = "trusted_len", issue = "37572")] unsafe impl TrustedLen for Flatten where - I: TrustedLen, - ::Item: TrustedConstSize, + I: Iterator, + FlattenCompat::IntoIter>: TrustedLen, { } @@ -660,6 +646,27 @@ where } } +unsafe impl TrustedLen + for FlattenCompat::IntoIter> +where + I: TrustedLen, +{ +} + +unsafe impl<'a, const N: usize, I, T> TrustedLen + for FlattenCompat::IntoIter> +where + I: TrustedLen, +{ +} + +unsafe impl<'a, const N: usize, I, T> TrustedLen + for FlattenCompat::IntoIter> +where + I: TrustedLen, +{ +} + trait ConstSizeIntoIterator: IntoIterator { // FIXME(#31844): convert to an associated const once specialization supports that fn size() -> Option; @@ -696,19 +703,6 @@ impl 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 TrustedConstSize for [T; N] {} -#[unstable(feature = "std_internals", issue = "none")] -unsafe impl TrustedConstSize for &'_ [T; N] {} -#[unstable(feature = "std_internals", issue = "none")] -unsafe impl TrustedConstSize for &'_ mut [T; N] {} - #[inline] fn and_then_or_clear(opt: &mut Option, f: impl FnOnce(&mut T) -> Option) -> Option { let x = f(opt.as_mut()?); diff --git a/library/core/src/macros/panic.md b/library/core/src/macros/panic.md index 98fb7e9e41d7a..8b549e187ba81 100644 --- a/library/core/src/macros/panic.md +++ b/library/core/src/macros/panic.md @@ -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. diff --git a/library/core/src/ptr/const_ptr.rs b/library/core/src/ptr/const_ptr.rs index 603bd88733393..6b18f5f5a40d1 100644 --- a/library/core/src/ptr/const_ptr.rs +++ b/library/core/src/ptr/const_ptr.rs @@ -264,7 +264,7 @@ impl *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) } diff --git a/library/core/src/ptr/mod.rs b/library/core/src/ptr/mod.rs index 555d58fad8440..675bc8245d8d8 100644 --- a/library/core/src/ptr/mod.rs +++ b/library/core/src/ptr/mod.rs @@ -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")] diff --git a/library/core/src/ptr/mut_ptr.rs b/library/core/src/ptr/mut_ptr.rs index 24b66c549a6e4..7b0fd02eb9f8b 100644 --- a/library/core/src/ptr/mut_ptr.rs +++ b/library/core/src/ptr/mut_ptr.rs @@ -270,7 +270,7 @@ impl *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) } diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs index d12809357a890..33a468a6bca57 100644 --- a/library/core/src/slice/mod.rs +++ b/library/core/src/slice/mod.rs @@ -4451,7 +4451,7 @@ impl 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(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() { diff --git a/library/core/tests/asserting.rs b/library/core/tests/asserting.rs index 4b626ba6f2d5d..1d9670886eb3d 100644 --- a/library/core/tests/asserting.rs +++ b/library/core/tests/asserting.rs @@ -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"); diff --git a/library/core/tests/lazy.rs b/library/core/tests/lazy.rs index e2f526d155e87..7f7f1f0058801 100644 --- a/library/core/tests/lazy.rs +++ b/library/core/tests/lazy.rs @@ -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)); } diff --git a/library/core/tests/num/mod.rs b/library/core/tests/num/mod.rs index c79e909e41db8..3e1f848ccfec2 100644 --- a/library/core/tests/num/mod.rs +++ b/library/core/tests/num/mod.rs @@ -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)); diff --git a/library/std/src/io/buffered/tests.rs b/library/std/src/io/buffered/tests.rs index 4c1b7d57684dd..35a5291a34769 100644 --- a/library/std/src/io/buffered/tests.rs +++ b/library/std/src/io/buffered/tests.rs @@ -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(); diff --git a/library/std/src/io/readbuf/tests.rs b/library/std/src/io/readbuf/tests.rs index cc1b423f2dd0d..89a2f6b2271bd 100644 --- a/library/std/src/io/readbuf/tests.rs +++ b/library/std/src/io/readbuf/tests.rs @@ -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(); diff --git a/library/std/src/keyword_docs.rs b/library/std/src/keyword_docs.rs index 43842bee992a7..be6dc7768af94 100644 --- a/library/std/src/keyword_docs.rs +++ b/library/std/src/keyword_docs.rs @@ -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 diff --git a/library/std/src/os/windows/io/handle.rs b/library/std/src/os/windows/io/handle.rs index f6622874625fc..11948cecad853 100644 --- a/library/std/src/os/windows/io/handle.rs +++ b/library/std/src/os/windows/io/handle.rs @@ -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()) } } diff --git a/library/std/src/os/windows/io/socket.rs b/library/std/src/os/windows/io/socket.rs index 5c1634084a055..b6bd0f9e12bd4 100644 --- a/library/std/src/os/windows/io/socket.rs +++ b/library/std/src/os/windows/io/socket.rs @@ -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()) } } diff --git a/library/std/src/sync/once_lock/tests.rs b/library/std/src/sync/once_lock/tests.rs index 46695225b9f5a..d5d32e73d8880 100644 --- a/library/std/src/sync/once_lock/tests.rs +++ b/library/std/src/sync/once_lock/tests.rs @@ -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)); } diff --git a/library/std/src/sync/remutex.rs b/library/std/src/sync/remutex.rs index 519ec2c32bd5d..0ced48d10b7c6 100644 --- a/library/std/src/sync/remutex.rs +++ b/library/std/src/sync/remutex.rs @@ -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 diff --git a/library/std/src/sys/sgx/abi/entry.S b/library/std/src/sys/sgx/abi/entry.S index f61bcf06f0815..ca79d1d796e9a 100644 --- a/library/std/src/sys/sgx/abi/entry.S +++ b/library/std/src/sys/sgx/abi/entry.S @@ -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 diff --git a/library/std/src/sys/unix/process/process_unix.rs b/library/std/src/sys/unix/process/process_unix.rs index ceaff59668460..612d43fe20414 100644 --- a/library/std/src/sys/unix/process/process_unix.rs +++ b/library/std/src/sys/unix/process/process_unix.rs @@ -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(()), diff --git a/library/std/src/sys/unix/process/process_vxworks.rs b/library/std/src/sys/unix/process/process_vxworks.rs index 569a4b149125d..c40e7ada03cbd 100644 --- a/library/std/src/sys/unix/process/process_vxworks.rs +++ b/library/std/src/sys/unix/process/process_vxworks.rs @@ -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(()), diff --git a/library/std/src/thread/mod.rs b/library/std/src/thread/mod.rs index 13b845b25c92d..40e8e5a629e19 100644 --- a/library/std/src/thread/mod.rs +++ b/library/std/src/thread/mod.rs @@ -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 Drop for MaybeDangling { fn drop(&mut self) { - // SAFETY: we are always initiailized. + // SAFETY: we are always initialized. unsafe { self.0.assume_init_drop() }; } } diff --git a/src/doc/rustdoc/src/SUMMARY.md b/src/doc/rustdoc/src/SUMMARY.md index 747cc629ba44b..b512135d92770 100644 --- a/src/doc/rustdoc/src/SUMMARY.md +++ b/src/doc/rustdoc/src/SUMMARY.md @@ -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) diff --git a/src/doc/rustdoc/src/how-to-read-rustdoc.md b/src/doc/rustdoc/src/how-to-read-rustdoc.md index 393192af01e98..ccd77fb17e938 100644 --- a/src/doc/rustdoc/src/how-to-read-rustdoc.md +++ b/src/doc/rustdoc/src/how-to-read-rustdoc.md @@ -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` or `Result>`. -### 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 diff --git a/src/doc/rustdoc/src/images/collapsed-long-item.png b/src/doc/rustdoc/src/images/collapsed-long-item.png new file mode 100644 index 0000000000000..c382870c64a65 Binary files /dev/null and b/src/doc/rustdoc/src/images/collapsed-long-item.png differ diff --git a/src/doc/rustdoc/src/images/collapsed-trait-impls.png b/src/doc/rustdoc/src/images/collapsed-trait-impls.png new file mode 100644 index 0000000000000..f685656e09a9c Binary files /dev/null and b/src/doc/rustdoc/src/images/collapsed-trait-impls.png differ diff --git a/src/doc/rustdoc/src/read-documentation/in-doc-settings.md b/src/doc/rustdoc/src/read-documentation/in-doc-settings.md new file mode 100644 index 0000000000000..12928a4f36926 --- /dev/null +++ b/src/doc/rustdoc/src/read-documentation/in-doc-settings.md @@ -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 +() 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). diff --git a/src/librustdoc/clean/auto_trait.rs b/src/librustdoc/clean/auto_trait.rs index eeee12a431065..1b622905e1adb 100644 --- a/src/librustdoc/clean/auto_trait.rs +++ b/src/librustdoc/clean/auto_trait.rs @@ -741,8 +741,10 @@ impl<'a, 'tcx> TypeFolder> 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:?}"), } } } diff --git a/src/librustdoc/doctest.rs b/src/librustdoc/doctest.rs index daf10e5b88a83..d71098ad89da0 100644 --- a/src/librustdoc/doctest.rs +++ b/src/librustdoc/doctest.rs @@ -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; } diff --git a/src/librustdoc/doctest/tests.rs b/src/librustdoc/doctest/tests.rs index 360d2259ea3d2..a30fe28f94f99 100644 --- a/src/librustdoc/doctest/tests.rs +++ b/src/librustdoc/doctest/tests.rs @@ -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); diff --git a/src/librustdoc/json/mod.rs b/src/librustdoc/json/mod.rs index d6da6e0993894..9392dd4d08825 100644 --- a/src/librustdoc/json/mod.rs +++ b/src/librustdoc/json/mod.rs @@ -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(()) diff --git a/src/tools/tidy/src/style.rs b/src/tools/tidy/src/style.rs index a2012db903a18..5f388ee47bbdb 100644 --- a/src/tools/tidy/src/style.rs +++ b/src/tools/tidy/src/style.rs @@ -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() { diff --git a/tests/rustdoc/playground-arg.rs b/tests/rustdoc/playground-arg.rs index f3811fe0b0ad1..2542ed657c1a7 100644 --- a/tests/rustdoc/playground-arg.rs +++ b/tests/rustdoc/playground-arg.rs @@ -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" diff --git a/tests/ui/inference/deref-suggestion.rs b/tests/ui/inference/deref-suggestion.rs index 0d8e7289dc8a2..dc39cc9dbffb0 100644 --- a/tests/ui/inference/deref-suggestion.rs +++ b/tests/ui/inference/deref-suggestion.rs @@ -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 + } } diff --git a/tests/ui/inference/deref-suggestion.stderr b/tests/ui/inference/deref-suggestion.stderr index 1626032ae997d..6f5aacacfc1f1 100644 --- a/tests/ui/inference/deref-suggestion.stderr +++ b/tests/ui/inference/deref-suggestion.stderr @@ -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`. diff --git a/tests/ui/inference/issue-70082.rs b/tests/ui/inference/issue-70082.rs new file mode 100644 index 0000000000000..d54d0a1a48a2d --- /dev/null +++ b/tests/ui/inference/issue-70082.rs @@ -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 +} diff --git a/tests/ui/inference/issue-70082.stderr b/tests/ui/inference/issue-70082.stderr new file mode 100644 index 0000000000000..47229a5fee14d --- /dev/null +++ b/tests/ui/inference/issue-70082.stderr @@ -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 `>::Output == f64` +help: try using a fully qualified path to specify the expected types + | +LL | let y: f64 = 0.01f64 * >::into(1i16); + | +++++++++++++++++++++++ ~ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0284`.