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