diff --git a/Cargo.lock b/Cargo.lock
index 146070cf1671..1dec7d0c11e2 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -986,14 +986,14 @@ dependencies = [
]
[[package]]
-name = "derivative"
-version = "2.2.0"
+name = "derive-where"
+version = "1.2.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b"
+checksum = "62d671cc41a825ebabc75757b62d3d168c577f9149b2d49ece1dad1f72119d25"
dependencies = [
"proc-macro2",
"quote",
- "syn 1.0.109",
+ "syn 2.0.67",
]
[[package]]
@@ -3882,7 +3882,6 @@ dependencies = [
"termcolor",
"termize",
"tracing",
- "unicode-width",
"windows",
]
@@ -4249,7 +4248,7 @@ name = "rustc_middle"
version = "0.0.0"
dependencies = [
"bitflags 2.5.0",
- "derivative",
+ "derive-where",
"either",
"field-offset",
"gsgdt",
@@ -4379,7 +4378,7 @@ name = "rustc_next_trait_solver"
version = "0.0.0"
dependencies = [
"bitflags 2.5.0",
- "derivative",
+ "derive-where",
"rustc_ast_ir",
"rustc_data_structures",
"rustc_index",
@@ -4629,7 +4628,7 @@ dependencies = [
name = "rustc_span"
version = "0.0.0"
dependencies = [
- "derivative",
+ "derive-where",
"indexmap",
"itoa",
"md-5",
@@ -4769,7 +4768,7 @@ name = "rustc_type_ir"
version = "0.0.0"
dependencies = [
"bitflags 2.5.0",
- "derivative",
+ "derive-where",
"indexmap",
"rustc_ast_ir",
"rustc_data_structures",
@@ -5206,6 +5205,7 @@ name = "stable_mir"
version = "0.1.0-preview"
dependencies = [
"scoped-tls",
+ "serde",
]
[[package]]
diff --git a/RELEASES.md b/RELEASES.md
index 0ecd472efb6e..2c91ddf78267 100644
--- a/RELEASES.md
+++ b/RELEASES.md
@@ -1,4 +1,4 @@
-Version 1.80 (2024-07-25)
+Version 1.80.0 (2024-07-25)
==========================
diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs
index 75c656973f96..564213ee7ee8 100644
--- a/compiler/rustc_ast/src/ast.rs
+++ b/compiler/rustc_ast/src/ast.rs
@@ -36,6 +36,7 @@ use rustc_macros::{Decodable, Encodable, HashStable_Generic};
use rustc_span::source_map::{respan, Spanned};
use rustc_span::symbol::{kw, sym, Ident, Symbol};
use rustc_span::{ErrorGuaranteed, Span, DUMMY_SP};
+use std::borrow::Cow;
use std::cmp;
use std::fmt;
use std::mem;
@@ -2264,6 +2265,42 @@ bitflags::bitflags! {
}
}
+impl InlineAsmOptions {
+ pub fn human_readable_names(&self) -> Vec<&'static str> {
+ let mut options = vec![];
+
+ if self.contains(InlineAsmOptions::PURE) {
+ options.push("pure");
+ }
+ if self.contains(InlineAsmOptions::NOMEM) {
+ options.push("nomem");
+ }
+ if self.contains(InlineAsmOptions::READONLY) {
+ options.push("readonly");
+ }
+ if self.contains(InlineAsmOptions::PRESERVES_FLAGS) {
+ options.push("preserves_flags");
+ }
+ if self.contains(InlineAsmOptions::NORETURN) {
+ options.push("noreturn");
+ }
+ if self.contains(InlineAsmOptions::NOSTACK) {
+ options.push("nostack");
+ }
+ if self.contains(InlineAsmOptions::ATT_SYNTAX) {
+ options.push("att_syntax");
+ }
+ if self.contains(InlineAsmOptions::RAW) {
+ options.push("raw");
+ }
+ if self.contains(InlineAsmOptions::MAY_UNWIND) {
+ options.push("may_unwind");
+ }
+
+ options
+ }
+}
+
impl std::fmt::Debug for InlineAsmOptions {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
bitflags::parser::to_writer(self, f)
@@ -2272,7 +2309,7 @@ impl std::fmt::Debug for InlineAsmOptions {
#[derive(Clone, PartialEq, Encodable, Decodable, Debug, Hash, HashStable_Generic)]
pub enum InlineAsmTemplatePiece {
- String(String),
+ String(Cow<'static, str>),
Placeholder { operand_idx: usize, modifier: Option, span: Span },
}
diff --git a/compiler/rustc_ast_passes/messages.ftl b/compiler/rustc_ast_passes/messages.ftl
index ca0b7f2ac3a6..df5c639382f0 100644
--- a/compiler/rustc_ast_passes/messages.ftl
+++ b/compiler/rustc_ast_passes/messages.ftl
@@ -155,8 +155,6 @@ ast_passes_impl_trait_path = `impl Trait` is not allowed in path parameters
ast_passes_incompatible_features = `{$f1}` and `{$f2}` are incompatible, using them at the same time is not allowed
.help = remove one of these features
-ast_passes_incompatible_trait_bound_modifiers = `{$left}` and `{$right}` are mutually exclusive
-
ast_passes_inherent_cannot_be = inherent impls cannot be {$annotation}
.because = {$annotation} because of this
.type = inherent impl for this type
diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs
index 34aac6e44730..1088db74cc96 100644
--- a/compiler/rustc_ast_passes/src/ast_validation.rs
+++ b/compiler/rustc_ast_passes/src/ast_validation.rs
@@ -1366,17 +1366,6 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
{
self.dcx().emit_err(errors::TildeConstDisallowed { span, reason });
}
- (
- _,
- BoundConstness::Always(_) | BoundConstness::Maybe(_),
- BoundPolarity::Negative(_) | BoundPolarity::Maybe(_),
- ) => {
- self.dcx().emit_err(errors::IncompatibleTraitBoundModifiers {
- span: bound.span(),
- left: modifiers.constness.as_str(),
- right: modifiers.polarity.as_str(),
- });
- }
_ => {}
}
diff --git a/compiler/rustc_ast_passes/src/errors.rs b/compiler/rustc_ast_passes/src/errors.rs
index 215ccd2ab4d9..9151c4a7c7c5 100644
--- a/compiler/rustc_ast_passes/src/errors.rs
+++ b/compiler/rustc_ast_passes/src/errors.rs
@@ -656,15 +656,6 @@ pub enum TildeConstReason {
Item,
}
-#[derive(Diagnostic)]
-#[diag(ast_passes_incompatible_trait_bound_modifiers)]
-pub struct IncompatibleTraitBoundModifiers {
- #[primary_span]
- pub span: Span,
- pub left: &'static str,
- pub right: &'static str,
-}
-
#[derive(Diagnostic)]
#[diag(ast_passes_const_and_async)]
pub struct ConstAndAsync {
diff --git a/compiler/rustc_ast_pretty/src/pprust/state.rs b/compiler/rustc_ast_pretty/src/pprust/state.rs
index 0568d368d8c4..b463d1f36ce5 100644
--- a/compiler/rustc_ast_pretty/src/pprust/state.rs
+++ b/compiler/rustc_ast_pretty/src/pprust/state.rs
@@ -1505,35 +1505,7 @@ impl<'a> State<'a> {
AsmArg::Options(opts) => {
s.word("options");
s.popen();
- let mut options = vec![];
- if opts.contains(InlineAsmOptions::PURE) {
- options.push("pure");
- }
- if opts.contains(InlineAsmOptions::NOMEM) {
- options.push("nomem");
- }
- if opts.contains(InlineAsmOptions::READONLY) {
- options.push("readonly");
- }
- if opts.contains(InlineAsmOptions::PRESERVES_FLAGS) {
- options.push("preserves_flags");
- }
- if opts.contains(InlineAsmOptions::NORETURN) {
- options.push("noreturn");
- }
- if opts.contains(InlineAsmOptions::NOSTACK) {
- options.push("nostack");
- }
- if opts.contains(InlineAsmOptions::ATT_SYNTAX) {
- options.push("att_syntax");
- }
- if opts.contains(InlineAsmOptions::RAW) {
- options.push("raw");
- }
- if opts.contains(InlineAsmOptions::MAY_UNWIND) {
- options.push("may_unwind");
- }
- s.commasep(Inconsistent, &options, |s, &opt| {
+ s.commasep(Inconsistent, &opts.human_readable_names(), |s, &opt| {
s.word(opt);
});
s.pclose();
diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
index b147567001db..2d9bc45ebc82 100644
--- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
@@ -4304,17 +4304,35 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, '_, 'infcx, 'tcx> {
// search for relevant arguments.
let mut arguments = Vec::new();
for (index, argument) in sig.inputs().skip_binder().iter().enumerate() {
- if let ty::Ref(argument_region, _, _) = argument.kind() {
- if argument_region == return_region {
- // Need to use the `rustc_middle::ty` types to compare against the
- // `return_region`. Then use the `rustc_hir` type to get only
- // the lifetime span.
- if let hir::TyKind::Ref(lifetime, _) = &fn_decl.inputs[index].kind {
+ if let ty::Ref(argument_region, _, _) = argument.kind()
+ && argument_region == return_region
+ {
+ // Need to use the `rustc_middle::ty` types to compare against the
+ // `return_region`. Then use the `rustc_hir` type to get only
+ // the lifetime span.
+ match &fn_decl.inputs[index].kind {
+ hir::TyKind::Ref(lifetime, _) => {
// With access to the lifetime, we can get
// the span of it.
arguments.push((*argument, lifetime.ident.span));
- } else {
- bug!("ty type is a ref but hir type is not");
+ }
+ // Resolve `self` whose self type is `&T`.
+ hir::TyKind::Path(hir::QPath::Resolved(None, path)) => {
+ if let Res::SelfTyAlias { alias_to, .. } = path.res
+ && let Some(alias_to) = alias_to.as_local()
+ && let hir::Impl { self_ty, .. } = self
+ .infcx
+ .tcx
+ .hir_node_by_def_id(alias_to)
+ .expect_item()
+ .expect_impl()
+ && let hir::TyKind::Ref(lifetime, _) = self_ty.kind
+ {
+ arguments.push((*argument, lifetime.ident.span));
+ }
+ }
+ _ => {
+ // Don't ICE though. It might be a type alias.
}
}
}
diff --git a/compiler/rustc_builtin_macros/src/asm.rs b/compiler/rustc_builtin_macros/src/asm.rs
index dd0f9aaf2210..b8fe6338493d 100644
--- a/compiler/rustc_builtin_macros/src/asm.rs
+++ b/compiler/rustc_builtin_macros/src/asm.rs
@@ -459,7 +459,7 @@ fn expand_preparsed_asm(
for (i, template_expr) in args.templates.into_iter().enumerate() {
if i != 0 {
- template.push(ast::InlineAsmTemplatePiece::String("\n".to_string()));
+ template.push(ast::InlineAsmTemplatePiece::String("\n".into()));
}
let msg = "asm template must be a string literal";
@@ -527,7 +527,7 @@ fn expand_preparsed_asm(
// Don't treat raw asm as a format string.
if args.options.contains(ast::InlineAsmOptions::RAW) {
- template.push(ast::InlineAsmTemplatePiece::String(template_str.to_string()));
+ template.push(ast::InlineAsmTemplatePiece::String(template_str.to_string().into()));
let template_num_lines = 1 + template_str.matches('\n').count();
line_spans.extend(std::iter::repeat(template_sp).take(template_num_lines));
continue;
@@ -577,7 +577,7 @@ fn expand_preparsed_asm(
for piece in unverified_pieces {
match piece {
parse::Piece::String(s) => {
- template.push(ast::InlineAsmTemplatePiece::String(s.to_string()))
+ template.push(ast::InlineAsmTemplatePiece::String(s.to_string().into()))
}
parse::Piece::NextArgument(arg) => {
let span = arg_spans.next().unwrap_or(template_sp);
diff --git a/compiler/rustc_codegen_cranelift/src/inline_asm.rs b/compiler/rustc_codegen_cranelift/src/inline_asm.rs
index c88230c93605..16edec47e102 100644
--- a/compiler/rustc_codegen_cranelift/src/inline_asm.rs
+++ b/compiler/rustc_codegen_cranelift/src/inline_asm.rs
@@ -46,9 +46,7 @@ pub(crate) fn codegen_inline_asm_terminator<'tcx>(
// Used by panic_abort on Windows, but uses a syntax which only happens to work with
// asm!() by accident and breaks with the GNU assembler as well as global_asm!() for
// the LLVM backend.
- if template.len() == 1
- && template[0] == InlineAsmTemplatePiece::String("int $$0x29".to_string())
- {
+ if template.len() == 1 && template[0] == InlineAsmTemplatePiece::String("int $$0x29".into()) {
fx.bcx.ins().trap(TrapCode::User(1));
return;
}
diff --git a/compiler/rustc_codegen_cranelift/src/intrinsics/llvm_x86.rs b/compiler/rustc_codegen_cranelift/src/intrinsics/llvm_x86.rs
index e1896138e487..a20faa2cad3a 100644
--- a/compiler/rustc_codegen_cranelift/src/intrinsics/llvm_x86.rs
+++ b/compiler/rustc_codegen_cranelift/src/intrinsics/llvm_x86.rs
@@ -40,7 +40,7 @@ pub(crate) fn codegen_x86_llvm_intrinsic_call<'tcx>(
shl rdx, 32
or rax, rdx
"
- .to_string(),
+ .into(),
)],
&[
CInlineAsmOperand::In {
@@ -471,7 +471,7 @@ pub(crate) fn codegen_x86_llvm_intrinsic_call<'tcx>(
// into 0x80000000 for which Cranelift doesn't have a native instruction.
codegen_inline_asm_inner(
fx,
- &[InlineAsmTemplatePiece::String(format!("cvtps2dq xmm0, xmm0"))],
+ &[InlineAsmTemplatePiece::String("cvtps2dq xmm0, xmm0".into())],
&[CInlineAsmOperand::InOut {
reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::X86(X86InlineAsmReg::xmm0)),
_late: true,
@@ -875,7 +875,7 @@ pub(crate) fn codegen_x86_llvm_intrinsic_call<'tcx>(
codegen_inline_asm_inner(
fx,
- &[InlineAsmTemplatePiece::String(asm.to_string())],
+ &[InlineAsmTemplatePiece::String(asm.into())],
&[
CInlineAsmOperand::InOut {
reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::X86(X86InlineAsmReg::ax)),
@@ -914,7 +914,7 @@ pub(crate) fn codegen_x86_llvm_intrinsic_call<'tcx>(
codegen_inline_asm_inner(
fx,
- &[InlineAsmTemplatePiece::String(format!("pcmpestri xmm0, xmm1, {imm8}"))],
+ &[InlineAsmTemplatePiece::String(format!("pcmpestri xmm0, xmm1, {imm8}").into())],
&[
CInlineAsmOperand::In {
reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::X86(X86InlineAsmReg::xmm0)),
@@ -967,7 +967,7 @@ pub(crate) fn codegen_x86_llvm_intrinsic_call<'tcx>(
codegen_inline_asm_inner(
fx,
- &[InlineAsmTemplatePiece::String(format!("pcmpestrm xmm0, xmm1, {imm8}"))],
+ &[InlineAsmTemplatePiece::String(format!("pcmpestrm xmm0, xmm1, {imm8}").into())],
&[
CInlineAsmOperand::InOut {
reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::X86(X86InlineAsmReg::xmm0)),
@@ -1015,7 +1015,7 @@ pub(crate) fn codegen_x86_llvm_intrinsic_call<'tcx>(
codegen_inline_asm_inner(
fx,
- &[InlineAsmTemplatePiece::String(format!("pclmulqdq xmm0, xmm1, {imm8}"))],
+ &[InlineAsmTemplatePiece::String(format!("pclmulqdq xmm0, xmm1, {imm8}").into())],
&[
CInlineAsmOperand::InOut {
reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::X86(X86InlineAsmReg::xmm0)),
@@ -1052,7 +1052,9 @@ pub(crate) fn codegen_x86_llvm_intrinsic_call<'tcx>(
codegen_inline_asm_inner(
fx,
- &[InlineAsmTemplatePiece::String(format!("aeskeygenassist xmm0, xmm0, {imm8}"))],
+ &[InlineAsmTemplatePiece::String(
+ format!("aeskeygenassist xmm0, xmm0, {imm8}").into(),
+ )],
&[CInlineAsmOperand::InOut {
reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::X86(X86InlineAsmReg::xmm0)),
_late: true,
@@ -1071,7 +1073,7 @@ pub(crate) fn codegen_x86_llvm_intrinsic_call<'tcx>(
codegen_inline_asm_inner(
fx,
- &[InlineAsmTemplatePiece::String("aesimc xmm0, xmm0".to_string())],
+ &[InlineAsmTemplatePiece::String("aesimc xmm0, xmm0".into())],
&[CInlineAsmOperand::InOut {
reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::X86(X86InlineAsmReg::xmm0)),
_late: true,
@@ -1091,7 +1093,7 @@ pub(crate) fn codegen_x86_llvm_intrinsic_call<'tcx>(
codegen_inline_asm_inner(
fx,
- &[InlineAsmTemplatePiece::String("aesenc xmm0, xmm1".to_string())],
+ &[InlineAsmTemplatePiece::String("aesenc xmm0, xmm1".into())],
&[
CInlineAsmOperand::InOut {
reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::X86(X86InlineAsmReg::xmm0)),
@@ -1117,7 +1119,7 @@ pub(crate) fn codegen_x86_llvm_intrinsic_call<'tcx>(
codegen_inline_asm_inner(
fx,
- &[InlineAsmTemplatePiece::String("aesenclast xmm0, xmm1".to_string())],
+ &[InlineAsmTemplatePiece::String("aesenclast xmm0, xmm1".into())],
&[
CInlineAsmOperand::InOut {
reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::X86(X86InlineAsmReg::xmm0)),
@@ -1143,7 +1145,7 @@ pub(crate) fn codegen_x86_llvm_intrinsic_call<'tcx>(
codegen_inline_asm_inner(
fx,
- &[InlineAsmTemplatePiece::String("aesdec xmm0, xmm1".to_string())],
+ &[InlineAsmTemplatePiece::String("aesdec xmm0, xmm1".into())],
&[
CInlineAsmOperand::InOut {
reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::X86(X86InlineAsmReg::xmm0)),
@@ -1169,7 +1171,7 @@ pub(crate) fn codegen_x86_llvm_intrinsic_call<'tcx>(
codegen_inline_asm_inner(
fx,
- &[InlineAsmTemplatePiece::String("aesdeclast xmm0, xmm1".to_string())],
+ &[InlineAsmTemplatePiece::String("aesdeclast xmm0, xmm1".into())],
&[
CInlineAsmOperand::InOut {
reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::X86(X86InlineAsmReg::xmm0)),
@@ -1207,7 +1209,7 @@ pub(crate) fn codegen_x86_llvm_intrinsic_call<'tcx>(
codegen_inline_asm_inner(
fx,
- &[InlineAsmTemplatePiece::String(format!("sha1rnds4 xmm1, xmm2, {func}"))],
+ &[InlineAsmTemplatePiece::String(format!("sha1rnds4 xmm1, xmm2, {func}").into())],
&[
CInlineAsmOperand::InOut {
reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::X86(X86InlineAsmReg::xmm1)),
@@ -1233,7 +1235,7 @@ pub(crate) fn codegen_x86_llvm_intrinsic_call<'tcx>(
codegen_inline_asm_inner(
fx,
- &[InlineAsmTemplatePiece::String("sha1msg1 xmm1, xmm2".to_string())],
+ &[InlineAsmTemplatePiece::String("sha1msg1 xmm1, xmm2".into())],
&[
CInlineAsmOperand::InOut {
reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::X86(X86InlineAsmReg::xmm1)),
@@ -1259,7 +1261,7 @@ pub(crate) fn codegen_x86_llvm_intrinsic_call<'tcx>(
codegen_inline_asm_inner(
fx,
- &[InlineAsmTemplatePiece::String("sha1msg2 xmm1, xmm2".to_string())],
+ &[InlineAsmTemplatePiece::String("sha1msg2 xmm1, xmm2".into())],
&[
CInlineAsmOperand::InOut {
reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::X86(X86InlineAsmReg::xmm1)),
@@ -1285,7 +1287,7 @@ pub(crate) fn codegen_x86_llvm_intrinsic_call<'tcx>(
codegen_inline_asm_inner(
fx,
- &[InlineAsmTemplatePiece::String("sha1nexte xmm1, xmm2".to_string())],
+ &[InlineAsmTemplatePiece::String("sha1nexte xmm1, xmm2".into())],
&[
CInlineAsmOperand::InOut {
reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::X86(X86InlineAsmReg::xmm1)),
@@ -1312,7 +1314,7 @@ pub(crate) fn codegen_x86_llvm_intrinsic_call<'tcx>(
codegen_inline_asm_inner(
fx,
- &[InlineAsmTemplatePiece::String("sha256rnds2 xmm1, xmm2".to_string())],
+ &[InlineAsmTemplatePiece::String("sha256rnds2 xmm1, xmm2".into())],
&[
CInlineAsmOperand::InOut {
reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::X86(X86InlineAsmReg::xmm1)),
@@ -1343,7 +1345,7 @@ pub(crate) fn codegen_x86_llvm_intrinsic_call<'tcx>(
codegen_inline_asm_inner(
fx,
- &[InlineAsmTemplatePiece::String("sha256msg1 xmm1, xmm2".to_string())],
+ &[InlineAsmTemplatePiece::String("sha256msg1 xmm1, xmm2".into())],
&[
CInlineAsmOperand::InOut {
reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::X86(X86InlineAsmReg::xmm1)),
@@ -1369,7 +1371,7 @@ pub(crate) fn codegen_x86_llvm_intrinsic_call<'tcx>(
codegen_inline_asm_inner(
fx,
- &[InlineAsmTemplatePiece::String("sha256msg2 xmm1, xmm2".to_string())],
+ &[InlineAsmTemplatePiece::String("sha256msg2 xmm1, xmm2".into())],
&[
CInlineAsmOperand::InOut {
reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::X86(X86InlineAsmReg::xmm1)),
@@ -1435,7 +1437,7 @@ pub(crate) fn codegen_x86_llvm_intrinsic_call<'tcx>(
let edx_place = res_place.place_field(fx, FieldIdx::new(1));
codegen_inline_asm_inner(
fx,
- &[InlineAsmTemplatePiece::String("rdtsc".to_string())],
+ &[InlineAsmTemplatePiece::String("rdtsc".into())],
&[
CInlineAsmOperand::Out {
reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::X86(X86InlineAsmReg::ax)),
diff --git a/compiler/rustc_codegen_llvm/src/consts.rs b/compiler/rustc_codegen_llvm/src/consts.rs
index 164d1681a367..80aa2018c81b 100644
--- a/compiler/rustc_codegen_llvm/src/consts.rs
+++ b/compiler/rustc_codegen_llvm/src/consts.rs
@@ -330,7 +330,7 @@ impl<'ll> CodegenCx<'ll, '_> {
// If this assertion triggers, there's something wrong with commandline
// argument validation.
- debug_assert!(
+ assert!(
!(self.tcx.sess.opts.cg.linker_plugin_lto.enabled()
&& self.tcx.sess.target.is_like_windows
&& self.tcx.sess.opts.cg.prefer_dynamic)
diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs
index 851a4c42e99b..364c35f31070 100644
--- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs
+++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs
@@ -170,7 +170,7 @@ fn build_pointer_or_reference_di_node<'ll, 'tcx>(
) -> DINodeCreationResult<'ll> {
// The debuginfo generated by this function is only valid if `ptr_type` is really just
// a (fat) pointer. Make sure it is not called for e.g. `Box`.
- debug_assert_eq!(
+ assert_eq!(
cx.size_and_align_of(ptr_type),
cx.size_and_align_of(Ty::new_mut_ptr(cx.tcx, pointee_type))
);
@@ -185,7 +185,7 @@ fn build_pointer_or_reference_di_node<'ll, 'tcx>(
match fat_pointer_kind(cx, pointee_type) {
None => {
// This is a thin pointer. Create a regular pointer type and give it the correct name.
- debug_assert_eq!(
+ assert_eq!(
(data_layout.pointer_size, data_layout.pointer_align.abi),
cx.size_and_align_of(ptr_type),
"ptr_type={ptr_type}, pointee_type={pointee_type}",
@@ -240,8 +240,8 @@ fn build_pointer_or_reference_di_node<'ll, 'tcx>(
FatPtrKind::Slice => ("data_ptr", "length"),
};
- debug_assert_eq!(abi::FAT_PTR_ADDR, 0);
- debug_assert_eq!(abi::FAT_PTR_EXTRA, 1);
+ assert_eq!(abi::FAT_PTR_ADDR, 0);
+ assert_eq!(abi::FAT_PTR_EXTRA, 1);
// The data pointer type is a regular, thin pointer, regardless of whether this
// is a slice or a trait object.
@@ -498,7 +498,7 @@ pub fn type_di_node<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>, t: Ty<'tcx>) -> &'ll D
}
};
- debug_assert_eq!(di_node_for_uid as *const _, di_node as *const _);
+ assert_eq!(di_node_for_uid as *const _, di_node as *const _);
} else {
debug_context(cx).type_map.insert(unique_type_id, di_node);
}
@@ -1060,7 +1060,7 @@ fn build_struct_type_di_node<'ll, 'tcx>(
let ty::Adt(adt_def, _) = struct_type.kind() else {
bug!("build_struct_type_di_node() called with non-struct-type: {:?}", struct_type);
};
- debug_assert!(adt_def.is_struct());
+ assert!(adt_def.is_struct());
let containing_scope = get_namespace_for_item(cx, adt_def.did());
let struct_type_and_layout = cx.layout_of(struct_type);
let variant_def = adt_def.non_enum_variant();
@@ -1130,7 +1130,7 @@ fn build_upvar_field_di_nodes<'ll, 'tcx>(
}
};
- debug_assert!(
+ assert!(
up_var_tys.iter().all(|t| t == cx.tcx.normalize_erasing_regions(ParamEnv::reveal_all(), t))
);
diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/cpp_like.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/cpp_like.rs
index 12f98eef97d4..cf7dddce84ff 100644
--- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/cpp_like.rs
+++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/cpp_like.rs
@@ -204,7 +204,7 @@ pub(super) fn build_enum_type_di_node<'ll, 'tcx>(
let enum_type_and_layout = cx.layout_of(enum_type);
let enum_type_name = compute_debuginfo_type_name(cx.tcx, enum_type, false);
- debug_assert!(!wants_c_like_enum_debuginfo(enum_type_and_layout));
+ assert!(!wants_c_like_enum_debuginfo(enum_type_and_layout));
type_map::build_type_with_children(
cx,
@@ -279,7 +279,7 @@ pub(super) fn build_coroutine_di_node<'ll, 'tcx>(
let coroutine_type_and_layout = cx.layout_of(coroutine_type);
let coroutine_type_name = compute_debuginfo_type_name(cx.tcx, coroutine_type, false);
- debug_assert!(!wants_c_like_enum_debuginfo(coroutine_type_and_layout));
+ assert!(!wants_c_like_enum_debuginfo(coroutine_type_and_layout));
type_map::build_type_with_children(
cx,
@@ -517,7 +517,7 @@ fn build_variant_struct_wrapper_type_di_node<'ll, 'tcx>(
if is_128_bits {
DiscrKind::Exact128(discr_val)
} else {
- debug_assert_eq!(discr_val, discr_val as u64 as u128);
+ assert_eq!(discr_val, discr_val as u64 as u128);
DiscrKind::Exact(discr_val as u64)
}
}
@@ -526,8 +526,8 @@ fn build_variant_struct_wrapper_type_di_node<'ll, 'tcx>(
if is_128_bits {
DiscrKind::Range128(min, max)
} else {
- debug_assert_eq!(min, min as u64 as u128);
- debug_assert_eq!(max, max as u64 as u128);
+ assert_eq!(min, min as u64 as u128);
+ assert_eq!(max, max as u64 as u128);
DiscrKind::Range(min as u64, max as u64)
}
}
@@ -815,7 +815,7 @@ fn build_union_fields_for_direct_tag_enum_or_coroutine<'ll, 'tcx>(
}
}));
- debug_assert_eq!(
+ assert_eq!(
cx.size_and_align_of(enum_type_and_layout.field(cx, tag_field).ty),
cx.size_and_align_of(super::tag_base_type(cx, enum_type_and_layout))
);
diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/mod.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/mod.rs
index 2b00bb14593e..96be1900ab2b 100644
--- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/mod.rs
+++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/mod.rs
@@ -106,7 +106,7 @@ fn tag_base_type<'ll, 'tcx>(
cx: &CodegenCx<'ll, 'tcx>,
enum_type_and_layout: TyAndLayout<'tcx>,
) -> Ty<'tcx> {
- debug_assert!(match enum_type_and_layout.ty.kind() {
+ assert!(match enum_type_and_layout.ty.kind() {
ty::Coroutine(..) => true,
ty::Adt(adt_def, _) => adt_def.is_enum(),
_ => false,
@@ -251,7 +251,7 @@ fn build_enum_variant_struct_type_di_node<'ll, 'tcx>(
variant_layout: TyAndLayout<'tcx>,
di_flags: DIFlags,
) -> &'ll DIType {
- debug_assert_eq!(variant_layout.ty, enum_type_and_layout.ty);
+ assert_eq!(variant_layout.ty, enum_type_and_layout.ty);
type_map::build_type_with_children(
cx,
diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/native.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/native.rs
index 115d5187eafa..63a9ce2fdf9c 100644
--- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/native.rs
+++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/native.rs
@@ -65,7 +65,7 @@ pub(super) fn build_enum_type_di_node<'ll, 'tcx>(
let visibility_flags = visibility_di_flags(cx, enum_adt_def.did(), enum_adt_def.did());
- debug_assert!(!wants_c_like_enum_debuginfo(enum_type_and_layout));
+ assert!(!wants_c_like_enum_debuginfo(enum_type_and_layout));
type_map::build_type_with_children(
cx,
@@ -142,7 +142,7 @@ pub(super) fn build_coroutine_di_node<'ll, 'tcx>(
let containing_scope = get_namespace_for_item(cx, coroutine_def_id);
let coroutine_type_and_layout = cx.layout_of(coroutine_type);
- debug_assert!(!wants_c_like_enum_debuginfo(coroutine_type_and_layout));
+ assert!(!wants_c_like_enum_debuginfo(coroutine_type_and_layout));
let coroutine_type_name = compute_debuginfo_type_name(cx.tcx, coroutine_type, false);
diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/type_map.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/type_map.rs
index e521d5e259ca..17931911f872 100644
--- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/type_map.rs
+++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/type_map.rs
@@ -36,7 +36,7 @@ mod private {
/// A unique identifier for anything that we create a debuginfo node for.
/// The types it contains are expected to already be normalized (which
-/// is debug_asserted in the constructors).
+/// is asserted in the constructors).
///
/// Note that there are some things that only show up in debuginfo, like
/// the separate type descriptions for each enum variant. These get an ID
@@ -58,12 +58,12 @@ pub(super) enum UniqueTypeId<'tcx> {
impl<'tcx> UniqueTypeId<'tcx> {
pub fn for_ty(tcx: TyCtxt<'tcx>, t: Ty<'tcx>) -> Self {
- debug_assert_eq!(t, tcx.normalize_erasing_regions(ParamEnv::reveal_all(), t));
+ assert_eq!(t, tcx.normalize_erasing_regions(ParamEnv::reveal_all(), t));
UniqueTypeId::Ty(t, private::HiddenZst)
}
pub fn for_enum_variant_part(tcx: TyCtxt<'tcx>, enum_ty: Ty<'tcx>) -> Self {
- debug_assert_eq!(enum_ty, tcx.normalize_erasing_regions(ParamEnv::reveal_all(), enum_ty));
+ assert_eq!(enum_ty, tcx.normalize_erasing_regions(ParamEnv::reveal_all(), enum_ty));
UniqueTypeId::VariantPart(enum_ty, private::HiddenZst)
}
@@ -72,7 +72,7 @@ impl<'tcx> UniqueTypeId<'tcx> {
enum_ty: Ty<'tcx>,
variant_idx: VariantIdx,
) -> Self {
- debug_assert_eq!(enum_ty, tcx.normalize_erasing_regions(ParamEnv::reveal_all(), enum_ty));
+ assert_eq!(enum_ty, tcx.normalize_erasing_regions(ParamEnv::reveal_all(), enum_ty));
UniqueTypeId::VariantStructType(enum_ty, variant_idx, private::HiddenZst)
}
@@ -81,7 +81,7 @@ impl<'tcx> UniqueTypeId<'tcx> {
enum_ty: Ty<'tcx>,
variant_idx: VariantIdx,
) -> Self {
- debug_assert_eq!(enum_ty, tcx.normalize_erasing_regions(ParamEnv::reveal_all(), enum_ty));
+ assert_eq!(enum_ty, tcx.normalize_erasing_regions(ParamEnv::reveal_all(), enum_ty));
UniqueTypeId::VariantStructTypeCppLikeWrapper(enum_ty, variant_idx, private::HiddenZst)
}
@@ -90,11 +90,8 @@ impl<'tcx> UniqueTypeId<'tcx> {
self_type: Ty<'tcx>,
implemented_trait: Option>,
) -> Self {
- debug_assert_eq!(
- self_type,
- tcx.normalize_erasing_regions(ParamEnv::reveal_all(), self_type)
- );
- debug_assert_eq!(
+ assert_eq!(self_type, tcx.normalize_erasing_regions(ParamEnv::reveal_all(), self_type));
+ assert_eq!(
implemented_trait,
tcx.normalize_erasing_regions(ParamEnv::reveal_all(), implemented_trait)
);
@@ -252,10 +249,7 @@ pub(super) fn build_type_with_children<'ll, 'tcx>(
members: impl FnOnce(&CodegenCx<'ll, 'tcx>, &'ll DIType) -> SmallVec<&'ll DIType>,
generics: impl FnOnce(&CodegenCx<'ll, 'tcx>) -> SmallVec<&'ll DIType>,
) -> DINodeCreationResult<'ll> {
- debug_assert_eq!(
- debug_context(cx).type_map.di_node_for_unique_id(stub_info.unique_type_id),
- None
- );
+ assert_eq!(debug_context(cx).type_map.di_node_for_unique_id(stub_info.unique_type_id), None);
debug_context(cx).type_map.insert(stub_info.unique_type_id, stub_info.metadata);
diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/utils.rs b/compiler/rustc_codegen_llvm/src/debuginfo/utils.rs
index 155e7a89fd8b..9bd2ccceadf3 100644
--- a/compiler/rustc_codegen_llvm/src/debuginfo/utils.rs
+++ b/compiler/rustc_codegen_llvm/src/debuginfo/utils.rs
@@ -81,7 +81,7 @@ pub(crate) fn fat_pointer_kind<'ll, 'tcx>(
ty::Dynamic(..) => Some(FatPtrKind::Dyn),
ty::Foreign(_) => {
// Assert that pointers to foreign types really are thin:
- debug_assert_eq!(
+ assert_eq!(
cx.size_of(Ty::new_imm_ptr(cx.tcx, pointee_tail_ty)),
cx.size_of(Ty::new_imm_ptr(cx.tcx, cx.tcx.types.u8))
);
diff --git a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs
index ae46200d3f55..3beda28ac1fd 100644
--- a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs
+++ b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs
@@ -305,7 +305,6 @@ pub enum TypeKind {
Pointer = 12,
Vector = 13,
Metadata = 14,
- X86_MMX = 15,
Token = 16,
ScalableVector = 17,
BFloat = 18,
@@ -330,7 +329,6 @@ impl TypeKind {
TypeKind::Pointer => rustc_codegen_ssa::common::TypeKind::Pointer,
TypeKind::Vector => rustc_codegen_ssa::common::TypeKind::Vector,
TypeKind::Metadata => rustc_codegen_ssa::common::TypeKind::Metadata,
- TypeKind::X86_MMX => rustc_codegen_ssa::common::TypeKind::X86_MMX,
TypeKind::Token => rustc_codegen_ssa::common::TypeKind::Token,
TypeKind::ScalableVector => rustc_codegen_ssa::common::TypeKind::ScalableVector,
TypeKind::BFloat => rustc_codegen_ssa::common::TypeKind::BFloat,
diff --git a/compiler/rustc_codegen_ssa/src/back/symbol_export.rs b/compiler/rustc_codegen_ssa/src/back/symbol_export.rs
index 6abe4fa1c380..b7ad09b055a9 100644
--- a/compiler/rustc_codegen_ssa/src/back/symbol_export.rs
+++ b/compiler/rustc_codegen_ssa/src/back/symbol_export.rs
@@ -352,7 +352,7 @@ fn exported_symbols_provider_local(
}
MonoItem::Fn(Instance { def: InstanceKind::DropGlue(def_id, Some(ty)), args }) => {
// A little sanity-check
- debug_assert_eq!(
+ assert_eq!(
args.non_erasable_generics(tcx, def_id).next(),
Some(GenericArgKind::Type(ty))
);
@@ -370,7 +370,7 @@ fn exported_symbols_provider_local(
args,
}) => {
// A little sanity-check
- debug_assert_eq!(
+ assert_eq!(
args.non_erasable_generics(tcx, def_id).next(),
Some(GenericArgKind::Type(ty))
);
@@ -462,7 +462,7 @@ fn upstream_monomorphizations_for_provider(
tcx: TyCtxt<'_>,
def_id: DefId,
) -> Option<&UnordMap, CrateNum>> {
- debug_assert!(!def_id.is_local());
+ assert!(!def_id.is_local());
tcx.upstream_monomorphizations(()).get(&def_id)
}
diff --git a/compiler/rustc_codegen_ssa/src/back/write.rs b/compiler/rustc_codegen_ssa/src/back/write.rs
index 0e48eee3dd57..56e94529bc11 100644
--- a/compiler/rustc_codegen_ssa/src/back/write.rs
+++ b/compiler/rustc_codegen_ssa/src/back/write.rs
@@ -1512,7 +1512,7 @@ fn start_executing_work(
// We reduce the `running` counter by one. The
// `tokens.truncate()` below will take care of
// giving the Token back.
- debug_assert!(running_with_own_token > 0);
+ assert!(running_with_own_token > 0);
running_with_own_token -= 1;
main_thread_state = MainThreadState::Lending;
}
diff --git a/compiler/rustc_codegen_ssa/src/common.rs b/compiler/rustc_codegen_ssa/src/common.rs
index 27b0f127e926..ea2fd482e1fc 100644
--- a/compiler/rustc_codegen_ssa/src/common.rs
+++ b/compiler/rustc_codegen_ssa/src/common.rs
@@ -91,7 +91,6 @@ pub enum TypeKind {
Pointer,
Vector,
Metadata,
- X86_MMX,
Token,
ScalableVector,
BFloat,
diff --git a/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs b/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs
index c4e5c8582404..6a6d47fcbba3 100644
--- a/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs
+++ b/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs
@@ -459,7 +459,7 @@ fn push_debuginfo_type_name<'tcx>(
output: &mut String,
visited: &mut FxHashSet>,
) {
- debug_assert!(!wants_c_like_enum_debuginfo(ty_and_layout));
+ assert!(!wants_c_like_enum_debuginfo(ty_and_layout));
output.push_str("enum2$<");
push_inner(output, visited);
push_close_angle_bracket(true, output);
@@ -660,7 +660,7 @@ fn push_generic_params_internal<'tcx>(
output: &mut String,
visited: &mut FxHashSet>,
) -> bool {
- debug_assert_eq!(args, tcx.normalize_erasing_regions(ty::ParamEnv::reveal_all(), args));
+ assert_eq!(args, tcx.normalize_erasing_regions(ty::ParamEnv::reveal_all(), args));
let mut args = args.non_erasable_generics(tcx, def_id).peekable();
if args.peek().is_none() {
return false;
diff --git a/compiler/rustc_codegen_ssa/src/mir/block.rs b/compiler/rustc_codegen_ssa/src/mir/block.rs
index c9c8f02c491b..9cb8b719b12b 100644
--- a/compiler/rustc_codegen_ssa/src/mir/block.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/block.rs
@@ -84,7 +84,7 @@ impl<'a, 'tcx> TerminatorCodegenHelper<'tcx> {
}
if is_cleanupret {
// Cross-funclet jump - need a trampoline
- debug_assert!(base::wants_new_eh_instructions(fx.cx.tcx().sess));
+ assert!(base::wants_new_eh_instructions(fx.cx.tcx().sess));
debug!("llbb_with_cleanup: creating cleanup trampoline for {:?}", target);
let name = &format!("{:?}_cleanup_trampoline_{:?}", self.bb, target);
let trampoline_llbb = Bx::append_block(fx.cx, fx.llfn, name);
diff --git a/compiler/rustc_codegen_ssa/src/mir/debuginfo.rs b/compiler/rustc_codegen_ssa/src/mir/debuginfo.rs
index 6b89636b6540..82ed5610d9ea 100644
--- a/compiler/rustc_codegen_ssa/src/mir/debuginfo.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/debuginfo.rs
@@ -194,7 +194,7 @@ fn calculate_debuginfo_offset<
}
_ => {
// Sanity check for `can_use_in_debuginfo`.
- debug_assert!(!elem.can_use_in_debuginfo());
+ assert!(!elem.can_use_in_debuginfo());
bug!("unsupported var debuginfo projection `{:?}`", projection)
}
}
@@ -502,7 +502,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
let DebugInfoOffset { direct_offset, indirect_offsets, result: fragment_layout } =
calculate_debuginfo_offset(bx, &fragment.projection, var_layout);
- debug_assert!(indirect_offsets.is_empty());
+ assert!(indirect_offsets.is_empty());
if fragment_layout.size == Size::ZERO {
// Fragment is a ZST, so does not represent anything. Avoid generating anything
diff --git a/compiler/rustc_codegen_ssa/src/mir/operand.rs b/compiler/rustc_codegen_ssa/src/mir/operand.rs
index cc0e91396506..e08d7a3e8265 100644
--- a/compiler/rustc_codegen_ssa/src/mir/operand.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/operand.rs
@@ -565,7 +565,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
for elem in place_ref.projection.iter() {
match elem {
mir::ProjectionElem::Field(ref f, _) => {
- debug_assert!(
+ assert!(
!o.layout.ty.is_any_ptr(),
"Bad PlaceRef: destructing pointers should use cast/PtrMetadata, \
but tried to access field {f:?} of pointer {o:?}",
diff --git a/compiler/rustc_codegen_ssa/src/mir/place.rs b/compiler/rustc_codegen_ssa/src/mir/place.rs
index 97d5bb831289..4394ffb7a1cf 100644
--- a/compiler/rustc_codegen_ssa/src/mir/place.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/place.rs
@@ -55,7 +55,7 @@ impl PlaceValue {
/// Creates a `PlaceRef` to this location with the given type.
pub fn with_type<'tcx>(self, layout: TyAndLayout<'tcx>) -> PlaceRef<'tcx, V> {
- debug_assert!(
+ assert!(
layout.is_unsized() || layout.abi.is_uninhabited() || self.llextra.is_none(),
"Had pointer metadata {:?} for sized type {layout:?}",
self.llextra,
@@ -488,7 +488,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
cg_base = match *elem {
mir::ProjectionElem::Deref => bx.load_operand(cg_base).deref(bx.cx()),
mir::ProjectionElem::Field(ref field, _) => {
- debug_assert!(
+ assert!(
!cg_base.layout.ty.is_any_ptr(),
"Bad PlaceRef: destructing pointers should use cast/PtrMetadata, \
but tried to access field {field:?} of pointer {cg_base:?}",
diff --git a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs
index f9e928a84a78..0cd3e60b0ccb 100644
--- a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs
@@ -168,8 +168,8 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
dst: PlaceRef<'tcx, Bx::Value>,
) {
// The MIR validator enforces no unsized transmutes.
- debug_assert!(src.layout.is_sized());
- debug_assert!(dst.layout.is_sized());
+ assert!(src.layout.is_sized());
+ assert!(dst.layout.is_sized());
if let Some(val) = self.codegen_transmute_operand(bx, src, dst.layout) {
val.store(bx, dst);
@@ -223,8 +223,8 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
match operand.val {
OperandValue::Ref(source_place_val) => {
- debug_assert_eq!(source_place_val.llextra, None);
- debug_assert!(matches!(operand_kind, OperandValueKind::Ref));
+ assert_eq!(source_place_val.llextra, None);
+ assert!(matches!(operand_kind, OperandValueKind::Ref));
Some(bx.load_operand(source_place_val.with_type(cast)).val)
}
OperandValue::ZeroSized => {
@@ -295,7 +295,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
to_scalar: abi::Scalar,
to_backend_ty: Bx::Type,
) -> Bx::Value {
- debug_assert_eq!(from_scalar.size(self.cx), to_scalar.size(self.cx));
+ assert_eq!(from_scalar.size(self.cx), to_scalar.size(self.cx));
use abi::Primitive::*;
imm = bx.from_immediate(imm);
@@ -639,9 +639,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
(OperandValue::Immediate(llval), operand.layout)
}
mir::UnOp::PtrMetadata => {
- debug_assert!(
- operand.layout.ty.is_unsafe_ptr() || operand.layout.ty.is_ref(),
- );
+ assert!(operand.layout.ty.is_unsafe_ptr() || operand.layout.ty.is_ref(),);
let (_, meta) = operand.val.pointer_parts();
assert_eq!(operand.layout.fields.count() > 1, meta.is_some());
if let Some(meta) = meta {
@@ -651,7 +649,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
}
}
};
- debug_assert!(
+ assert!(
val.is_expected_variant_for_type(self.cx, layout),
"Made wrong variant {val:?} for type {layout:?}",
);
@@ -742,7 +740,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
bug!("Field {field_idx:?} is {p:?} making {layout:?}");
});
let scalars = self.value_kind(op.layout).scalars().unwrap();
- debug_assert_eq!(values.len(), scalars.len());
+ assert_eq!(values.len(), scalars.len());
inputs.extend(values);
input_scalars.extend(scalars);
}
@@ -760,7 +758,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
);
let val = OperandValue::from_immediates(inputs);
- debug_assert!(
+ assert!(
val.is_expected_variant_for_type(self.cx, layout),
"Made wrong variant {val:?} for type {layout:?}",
);
@@ -805,7 +803,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
let val = cg_place.val.address();
let ty = cg_place.layout.ty;
- debug_assert!(
+ assert!(
if bx.cx().type_has_metadata(ty) {
matches!(val, OperandValue::Pair(..))
} else {
@@ -927,7 +925,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
}
mir::BinOp::Cmp => {
use std::cmp::Ordering;
- debug_assert!(!is_float);
+ assert!(!is_float);
let pred = |op| base::bin_op_to_icmp_predicate(op, is_signed);
if bx.cx().tcx().sess.opts.optimize == OptLevel::No {
// FIXME: This actually generates tighter assembly, and is a classic trick
@@ -1111,7 +1109,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
if layout.is_zst() {
OperandValueKind::ZeroSized
} else if self.cx.is_backend_immediate(layout) {
- debug_assert!(!self.cx.is_backend_scalar_pair(layout));
+ assert!(!self.cx.is_backend_scalar_pair(layout));
OperandValueKind::Immediate(match layout.abi {
abi::Abi::Scalar(s) => s,
abi::Abi::Vector { element, .. } => element,
diff --git a/compiler/rustc_codegen_ssa/src/traits/builder.rs b/compiler/rustc_codegen_ssa/src/traits/builder.rs
index 2f0daefa46a6..42980d9ebd24 100644
--- a/compiler/rustc_codegen_ssa/src/traits/builder.rs
+++ b/compiler/rustc_codegen_ssa/src/traits/builder.rs
@@ -165,7 +165,7 @@ pub trait BuilderMethods<'a, 'tcx>:
size: Size,
) -> Self::Value;
fn load_from_place(&mut self, ty: Self::Type, place: PlaceValue) -> Self::Value {
- debug_assert_eq!(place.llextra, None);
+ assert_eq!(place.llextra, None);
self.load(ty, place.llval, place.align)
}
fn load_operand(&mut self, place: PlaceRef<'tcx, Self::Value>)
@@ -184,7 +184,7 @@ pub trait BuilderMethods<'a, 'tcx>:
fn store(&mut self, val: Self::Value, ptr: Self::Value, align: Align) -> Self::Value;
fn store_to_place(&mut self, val: Self::Value, place: PlaceValue) -> Self::Value {
- debug_assert_eq!(place.llextra, None);
+ assert_eq!(place.llextra, None);
self.store(val, place.llval, place.align)
}
fn store_with_flags(
@@ -200,7 +200,7 @@ pub trait BuilderMethods<'a, 'tcx>:
place: PlaceValue,
flags: MemFlags,
) -> Self::Value {
- debug_assert_eq!(place.llextra, None);
+ assert_eq!(place.llextra, None);
self.store_with_flags(val, place.llval, place.align, flags)
}
fn atomic_store(
@@ -320,9 +320,9 @@ pub trait BuilderMethods<'a, 'tcx>:
layout: TyAndLayout<'tcx>,
flags: MemFlags,
) {
- debug_assert!(layout.is_sized(), "cannot typed-copy an unsigned type");
- debug_assert!(src.llextra.is_none(), "cannot directly copy from unsized values");
- debug_assert!(dst.llextra.is_none(), "cannot directly copy into unsized values");
+ assert!(layout.is_sized(), "cannot typed-copy an unsigned type");
+ assert!(src.llextra.is_none(), "cannot directly copy from unsized values");
+ assert!(dst.llextra.is_none(), "cannot directly copy into unsized values");
if flags.contains(MemFlags::NONTEMPORAL) {
// HACK(nox): This is inefficient but there is no nontemporal memcpy.
let ty = self.backend_type(layout);
diff --git a/compiler/rustc_const_eval/src/interpret/validity.rs b/compiler/rustc_const_eval/src/interpret/validity.rs
index 4da7e233889f..3dc3e6c88332 100644
--- a/compiler/rustc_const_eval/src/interpret/validity.rs
+++ b/compiler/rustc_const_eval/src/interpret/validity.rs
@@ -34,6 +34,8 @@ use super::{
Pointer, Projectable, Scalar, ValueVisitor,
};
+// for the validation errors
+#[rustfmt::skip]
use super::InterpError::UndefinedBehavior as Ub;
use super::InterpError::Unsupported as Unsup;
use super::UndefinedBehaviorInfo::*;
diff --git a/compiler/rustc_errors/Cargo.toml b/compiler/rustc_errors/Cargo.toml
index cc114fdcd8c3..2fff9f2de50f 100644
--- a/compiler/rustc_errors/Cargo.toml
+++ b/compiler/rustc_errors/Cargo.toml
@@ -26,7 +26,6 @@ serde_json = "1.0.59"
termcolor = "1.2.0"
termize = "0.1.1"
tracing = "0.1"
-unicode-width = "0.1.4"
# tidy-alphabetical-end
[target.'cfg(windows)'.dependencies.windows]
diff --git a/compiler/rustc_errors/src/emitter.rs b/compiler/rustc_errors/src/emitter.rs
index aa47ca166764..58220c654900 100644
--- a/compiler/rustc_errors/src/emitter.rs
+++ b/compiler/rustc_errors/src/emitter.rs
@@ -8,7 +8,7 @@
//! The output types are defined in `rustc_session::config::ErrorOutputType`.
use rustc_span::source_map::SourceMap;
-use rustc_span::{FileLines, FileName, SourceFile, Span};
+use rustc_span::{char_width, FileLines, FileName, SourceFile, Span};
use crate::snippet::{
Annotation, AnnotationColumn, AnnotationType, Line, MultilineAnnotation, Style, StyledString,
@@ -677,10 +677,7 @@ impl HumanEmitter {
.skip(left)
.take_while(|ch| {
// Make sure that the trimming on the right will fall within the terminal width.
- // FIXME: `unicode_width` sometimes disagrees with terminals on how wide a `char`
- // is. For now, just accept that sometimes the code line will be longer than
- // desired.
- let next = unicode_width::UnicodeWidthChar::width(*ch).unwrap_or(1);
+ let next = char_width(*ch);
if taken + next > right - left {
return false;
}
@@ -742,11 +739,7 @@ impl HumanEmitter {
let left = margin.left(source_string.len());
// Account for unicode characters of width !=0 that were removed.
- let left = source_string
- .chars()
- .take(left)
- .map(|ch| unicode_width::UnicodeWidthChar::width(ch).unwrap_or(1))
- .sum();
+ let left = source_string.chars().take(left).map(|ch| char_width(ch)).sum();
self.draw_line(
buffer,
@@ -2039,7 +2032,7 @@ impl HumanEmitter {
let sub_len: usize =
if is_whitespace_addition { &part.snippet } else { part.snippet.trim() }
.chars()
- .map(|ch| unicode_width::UnicodeWidthChar::width(ch).unwrap_or(1))
+ .map(|ch| char_width(ch))
.sum();
let offset: isize = offsets
@@ -2076,11 +2069,8 @@ impl HumanEmitter {
}
// length of the code after substitution
- let full_sub_len = part
- .snippet
- .chars()
- .map(|ch| unicode_width::UnicodeWidthChar::width(ch).unwrap_or(1))
- .sum::() as isize;
+ let full_sub_len =
+ part.snippet.chars().map(|ch| char_width(ch)).sum::() as isize;
// length of the code to be substituted
let snippet_len = span_end_pos as isize - span_start_pos as isize;
@@ -2568,18 +2558,53 @@ fn num_decimal_digits(num: usize) -> usize {
}
// We replace some characters so the CLI output is always consistent and underlines aligned.
+// Keep the following list in sync with `rustc_span::char_width`.
const OUTPUT_REPLACEMENTS: &[(char, &str)] = &[
- ('\t', " "), // We do our own tab replacement
+ ('\t', " "), // We do our own tab replacement
('\u{200D}', ""), // Replace ZWJ with nothing for consistent terminal output of grapheme clusters.
- ('\u{202A}', ""), // The following unicode text flow control characters are inconsistently
- ('\u{202B}', ""), // supported across CLIs and can cause confusion due to the bytes on disk
- ('\u{202D}', ""), // not corresponding to the visible source code, so we replace them always.
- ('\u{202E}', ""),
- ('\u{2066}', ""),
- ('\u{2067}', ""),
- ('\u{2068}', ""),
- ('\u{202C}', ""),
- ('\u{2069}', ""),
+ ('\u{202A}', "�"), // The following unicode text flow control characters are inconsistently
+ ('\u{202B}', "�"), // supported across CLIs and can cause confusion due to the bytes on disk
+ ('\u{202D}', "�"), // not corresponding to the visible source code, so we replace them always.
+ ('\u{202E}', "�"),
+ ('\u{2066}', "�"),
+ ('\u{2067}', "�"),
+ ('\u{2068}', "�"),
+ ('\u{202C}', "�"),
+ ('\u{2069}', "�"),
+ // In terminals without Unicode support the following will be garbled, but in *all* terminals
+ // the underlying codepoint will be as well. We could gate this replacement behind a "unicode
+ // support" gate.
+ ('\u{0000}', "␀"),
+ ('\u{0001}', "␁"),
+ ('\u{0002}', "␂"),
+ ('\u{0003}', "␃"),
+ ('\u{0004}', "␄"),
+ ('\u{0005}', "␅"),
+ ('\u{0006}', "␆"),
+ ('\u{0007}', "␇"),
+ ('\u{0008}', "␈"),
+ ('\u{000B}', "␋"),
+ ('\u{000C}', "␌"),
+ ('\u{000D}', "␍"),
+ ('\u{000E}', "␎"),
+ ('\u{000F}', "␏"),
+ ('\u{0010}', "␐"),
+ ('\u{0011}', "␑"),
+ ('\u{0012}', "␒"),
+ ('\u{0013}', "␓"),
+ ('\u{0014}', "␔"),
+ ('\u{0015}', "␕"),
+ ('\u{0016}', "␖"),
+ ('\u{0017}', "␗"),
+ ('\u{0018}', "␘"),
+ ('\u{0019}', "␙"),
+ ('\u{001A}', "␚"),
+ ('\u{001B}', "␛"),
+ ('\u{001C}', "␜"),
+ ('\u{001D}', "␝"),
+ ('\u{001E}', "␞"),
+ ('\u{001F}', "␟"),
+ ('\u{007F}', "␡"),
];
fn normalize_whitespace(str: &str) -> String {
diff --git a/compiler/rustc_hir_analysis/src/check/dropck.rs b/compiler/rustc_hir_analysis/src/check/dropck.rs
index 193714480255..06ec01484a41 100644
--- a/compiler/rustc_hir_analysis/src/check/dropck.rs
+++ b/compiler/rustc_hir_analysis/src/check/dropck.rs
@@ -6,10 +6,10 @@ use rustc_data_structures::fx::FxHashSet;
use rustc_errors::{codes::*, struct_span_code_err, ErrorGuaranteed};
use rustc_infer::infer::outlives::env::OutlivesEnvironment;
use rustc_infer::infer::{RegionResolutionError, TyCtxtInferExt};
-use rustc_infer::traits::ObligationCauseCode;
+use rustc_infer::traits::{ObligationCause, ObligationCauseCode};
use rustc_middle::ty::util::CheckRegions;
-use rustc_middle::ty::GenericArgsRef;
use rustc_middle::ty::{self, TyCtxt};
+use rustc_middle::ty::{GenericArgsRef, Ty};
use rustc_trait_selection::regions::InferCtxtRegionExt;
use rustc_trait_selection::traits::{self, ObligationCtxt};
@@ -115,8 +115,9 @@ fn ensure_drop_params_and_item_params_correspond<'tcx>(
Err(err.emit())
}
-/// Confirms that every predicate imposed by dtor_predicates is
-/// implied by assuming the predicates attached to self_type_did.
+/// Confirms that all predicates defined on the `Drop` impl (`drop_impl_def_id`) are able to be
+/// proven from within `adt_def_id`'s environment. I.e. all the predicates on the impl are
+/// implied by the ADT being well formed.
fn ensure_drop_predicates_are_implied_by_item_defn<'tcx>(
tcx: TyCtxt<'tcx>,
drop_impl_def_id: LocalDefId,
@@ -126,6 +127,8 @@ fn ensure_drop_predicates_are_implied_by_item_defn<'tcx>(
let infcx = tcx.infer_ctxt().build();
let ocx = ObligationCtxt::new_with_diagnostics(&infcx);
+ let impl_span = tcx.def_span(drop_impl_def_id.to_def_id());
+
// Take the param-env of the adt and instantiate the args that show up in
// the implementation's self type. This gives us the assumptions that the
// self ty of the implementation is allowed to know just from it being a
@@ -135,14 +138,27 @@ fn ensure_drop_predicates_are_implied_by_item_defn<'tcx>(
// We don't need to normalize this param-env or anything, since we're only
// instantiating it with free params, so no additional param-env normalization
// can occur on top of what has been done in the param_env query itself.
- let param_env =
+ //
+ // Note: Ideally instead of instantiating the `ParamEnv` with the arguments from the impl ty we
+ // could instead use identity args for the adt. Unfortunately this would cause any errors to
+ // reference the params from the ADT instead of from the impl which is bad UX. To resolve
+ // this we "rename" the ADT's params to be the impl's params which should not affect behaviour.
+ let impl_adt_ty = Ty::new_adt(tcx, tcx.adt_def(adt_def_id), adt_to_impl_args);
+ let adt_env =
ty::EarlyBinder::bind(tcx.param_env(adt_def_id)).instantiate(tcx, adt_to_impl_args);
- for (pred, span) in tcx.predicates_of(drop_impl_def_id).instantiate_identity(tcx) {
+ let fresh_impl_args = infcx.fresh_args_for_item(impl_span, drop_impl_def_id.to_def_id());
+ let fresh_adt_ty =
+ tcx.impl_trait_ref(drop_impl_def_id).unwrap().instantiate(tcx, fresh_impl_args).self_ty();
+
+ ocx.eq(&ObligationCause::dummy_with_span(impl_span), adt_env, fresh_adt_ty, impl_adt_ty)
+ .unwrap();
+
+ for (clause, span) in tcx.predicates_of(drop_impl_def_id).instantiate(tcx, fresh_impl_args) {
let normalize_cause = traits::ObligationCause::misc(span, adt_def_id);
- let pred = ocx.normalize(&normalize_cause, param_env, pred);
+ let pred = ocx.normalize(&normalize_cause, adt_env, clause);
let cause = traits::ObligationCause::new(span, adt_def_id, ObligationCauseCode::DropImpl);
- ocx.register_obligation(traits::Obligation::new(tcx, cause, param_env, pred));
+ ocx.register_obligation(traits::Obligation::new(tcx, cause, adt_env, pred));
}
// All of the custom error reporting logic is to preserve parity with the old
@@ -176,7 +192,7 @@ fn ensure_drop_predicates_are_implied_by_item_defn<'tcx>(
return Err(guar.unwrap());
}
- let errors = ocx.infcx.resolve_regions(&OutlivesEnvironment::new(param_env));
+ let errors = ocx.infcx.resolve_regions(&OutlivesEnvironment::new(adt_env));
if !errors.is_empty() {
let mut guar = None;
for error in errors {
diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs
index db5eba0d9eba..a982b84e755b 100644
--- a/compiler/rustc_hir_pretty/src/lib.rs
+++ b/compiler/rustc_hir_pretty/src/lib.rs
@@ -1298,35 +1298,7 @@ impl<'a> State<'a> {
AsmArg::Options(opts) => {
s.word("options");
s.popen();
- let mut options = vec![];
- if opts.contains(ast::InlineAsmOptions::PURE) {
- options.push("pure");
- }
- if opts.contains(ast::InlineAsmOptions::NOMEM) {
- options.push("nomem");
- }
- if opts.contains(ast::InlineAsmOptions::READONLY) {
- options.push("readonly");
- }
- if opts.contains(ast::InlineAsmOptions::PRESERVES_FLAGS) {
- options.push("preserves_flags");
- }
- if opts.contains(ast::InlineAsmOptions::NORETURN) {
- options.push("noreturn");
- }
- if opts.contains(ast::InlineAsmOptions::NOSTACK) {
- options.push("nostack");
- }
- if opts.contains(ast::InlineAsmOptions::ATT_SYNTAX) {
- options.push("att_syntax");
- }
- if opts.contains(ast::InlineAsmOptions::RAW) {
- options.push("raw");
- }
- if opts.contains(ast::InlineAsmOptions::MAY_UNWIND) {
- options.push("may_unwind");
- }
- s.commasep(Inconsistent, &options, |s, &opt| {
+ s.commasep(Inconsistent, &opts.human_readable_names(), |s, &opt| {
s.word(opt);
});
s.pclose();
diff --git a/compiler/rustc_lint/messages.ftl b/compiler/rustc_lint/messages.ftl
index 7d7b97e2eb1a..a87b3c2c1359 100644
--- a/compiler/rustc_lint/messages.ftl
+++ b/compiler/rustc_lint/messages.ftl
@@ -5,6 +5,11 @@ lint_ambiguous_glob_reexport = ambiguous glob re-exports
.label_first_reexport = the name `{$name}` in the {$namespace} namespace is first re-exported here
.label_duplicate_reexport = but the name `{$name}` in the {$namespace} namespace is also re-exported here
+lint_ambiguous_negative_literals = `-` has lower precedence than method calls, which might be unexpected
+ .example = e.g. `-4.abs()` equals `-4`; while `(-4).abs()` equals `4`
+ .negative_literal = add parentheses around the `-` and the literal to call the method on a negative literal
+ .current_behavior = add parentheses around the literal and the method call to keep the current behavior
+
lint_ambiguous_wide_pointer_comparisons = ambiguous wide pointer comparison, the comparison includes metadata which may not be expected
.addr_metadata_suggestion = use explicit `std::ptr::eq` method to compare metadata and addresses
.addr_suggestion = use `std::ptr::addr_eq` or untyped pointers to only compare their addresses
diff --git a/compiler/rustc_lint/src/lib.rs b/compiler/rustc_lint/src/lib.rs
index fc073233d972..7c44d16169e8 100644
--- a/compiler/rustc_lint/src/lib.rs
+++ b/compiler/rustc_lint/src/lib.rs
@@ -73,6 +73,7 @@ mod noop_method_call;
mod opaque_hidden_inferred_bound;
mod pass_by_value;
mod passes;
+mod precedence;
mod ptr_nulls;
mod redundant_semicolon;
mod reference_casting;
@@ -111,6 +112,7 @@ use nonstandard_style::*;
use noop_method_call::*;
use opaque_hidden_inferred_bound::*;
use pass_by_value::*;
+use precedence::*;
use ptr_nulls::*;
use redundant_semicolon::*;
use reference_casting::*;
@@ -120,6 +122,7 @@ use types::*;
use unit_bindings::*;
use unused::*;
+#[rustfmt::skip]
pub use builtin::{MissingDoc, SoftLints};
pub use context::{CheckLintNameResult, FindLintError, LintStore};
pub use context::{EarlyContext, LateContext, LintContext};
@@ -174,6 +177,7 @@ early_lint_methods!(
RedundantSemicolons: RedundantSemicolons,
UnusedDocComment: UnusedDocComment,
Expr2024: Expr2024,
+ Precedence: Precedence,
]
]
);
diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs
index 6c5f366727f9..1f0954c6e9f0 100644
--- a/compiler/rustc_lint/src/lints.rs
+++ b/compiler/rustc_lint/src/lints.rs
@@ -1499,6 +1499,35 @@ pub struct NonLocalDefinitionsCargoUpdateNote {
pub crate_name: Symbol,
}
+// precedence.rs
+#[derive(LintDiagnostic)]
+#[diag(lint_ambiguous_negative_literals)]
+#[note(lint_example)]
+pub struct AmbiguousNegativeLiteralsDiag {
+ #[subdiagnostic]
+ pub negative_literal: AmbiguousNegativeLiteralsNegativeLiteralSuggestion,
+ #[subdiagnostic]
+ pub current_behavior: AmbiguousNegativeLiteralsCurrentBehaviorSuggestion,
+}
+
+#[derive(Subdiagnostic)]
+#[multipart_suggestion(lint_negative_literal, applicability = "maybe-incorrect")]
+pub struct AmbiguousNegativeLiteralsNegativeLiteralSuggestion {
+ #[suggestion_part(code = "(")]
+ pub start_span: Span,
+ #[suggestion_part(code = ")")]
+ pub end_span: Span,
+}
+
+#[derive(Subdiagnostic)]
+#[multipart_suggestion(lint_current_behavior, applicability = "maybe-incorrect")]
+pub struct AmbiguousNegativeLiteralsCurrentBehaviorSuggestion {
+ #[suggestion_part(code = "(")]
+ pub start_span: Span,
+ #[suggestion_part(code = ")")]
+ pub end_span: Span,
+}
+
// pass_by_value.rs
#[derive(LintDiagnostic)]
#[diag(lint_pass_by_value)]
diff --git a/compiler/rustc_lint/src/precedence.rs b/compiler/rustc_lint/src/precedence.rs
new file mode 100644
index 000000000000..eb2ba3972779
--- /dev/null
+++ b/compiler/rustc_lint/src/precedence.rs
@@ -0,0 +1,70 @@
+use rustc_ast::token::LitKind;
+use rustc_ast::{Expr, ExprKind, MethodCall, UnOp};
+use rustc_session::{declare_lint, declare_lint_pass};
+
+use crate::lints::{
+ AmbiguousNegativeLiteralsCurrentBehaviorSuggestion, AmbiguousNegativeLiteralsDiag,
+ AmbiguousNegativeLiteralsNegativeLiteralSuggestion,
+};
+use crate::{EarlyContext, EarlyLintPass, LintContext};
+
+declare_lint! {
+ /// The `ambiguous_negative_literals` lint checks for cases that are
+ /// confusing between a negative literal and a negation that's not part
+ /// of the literal.
+ ///
+ /// ### Example
+ ///
+ /// ```rust,compile_fail
+ /// # #![allow(unused)]
+ /// -1i32.abs(); // equals -1, while `(-1i32).abs()` equals 1
+ /// ```
+ ///
+ /// {{produces}}
+ ///
+ /// ### Explanation
+ ///
+ /// Method calls take precedence over unary precedence. Setting the
+ /// precedence explicitly makes the code clearer and avoid potential bugs.
+ pub AMBIGUOUS_NEGATIVE_LITERALS,
+ Deny,
+ "ambiguous negative literals operations",
+ report_in_external_macro
+}
+
+declare_lint_pass!(Precedence => [AMBIGUOUS_NEGATIVE_LITERALS]);
+
+impl EarlyLintPass for Precedence {
+ fn check_expr(&mut self, cx: &EarlyContext<'_>, expr: &Expr) {
+ let ExprKind::Unary(UnOp::Neg, operand) = &expr.kind else {
+ return;
+ };
+
+ let mut arg = operand;
+ let mut at_least_one = false;
+ while let ExprKind::MethodCall(box MethodCall { receiver, .. }) = &arg.kind {
+ at_least_one = true;
+ arg = receiver;
+ }
+
+ if at_least_one
+ && let ExprKind::Lit(lit) = &arg.kind
+ && let LitKind::Integer | LitKind::Float = &lit.kind
+ {
+ cx.emit_span_lint(
+ AMBIGUOUS_NEGATIVE_LITERALS,
+ expr.span,
+ AmbiguousNegativeLiteralsDiag {
+ negative_literal: AmbiguousNegativeLiteralsNegativeLiteralSuggestion {
+ start_span: expr.span.shrink_to_lo(),
+ end_span: arg.span.shrink_to_hi(),
+ },
+ current_behavior: AmbiguousNegativeLiteralsCurrentBehaviorSuggestion {
+ start_span: operand.span.shrink_to_lo(),
+ end_span: operand.span.shrink_to_hi(),
+ },
+ },
+ );
+ }
+ }
+}
diff --git a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp
index 14757b27a375..4cdd8af1008c 100644
--- a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp
+++ b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp
@@ -1419,8 +1419,6 @@ extern "C" LLVMTypeKind LLVMRustGetTypeKind(LLVMTypeRef Ty) {
return LLVMPointerTypeKind;
case Type::FixedVectorTyID:
return LLVMVectorTypeKind;
- case Type::X86_MMXTyID:
- return LLVMX86_MMXTypeKind;
case Type::TokenTyID:
return LLVMTokenTypeKind;
case Type::ScalableVectorTyID:
diff --git a/compiler/rustc_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs
index e5e430bc90dc..9874624ae259 100644
--- a/compiler/rustc_metadata/src/rmeta/decoder.rs
+++ b/compiler/rustc_metadata/src/rmeta/decoder.rs
@@ -1728,7 +1728,6 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
source_len,
lines,
multibyte_chars,
- non_narrow_chars,
normalized_pos,
stable_id,
..
@@ -1780,7 +1779,6 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
self.cnum,
lines,
multibyte_chars,
- non_narrow_chars,
normalized_pos,
source_file_index,
);
diff --git a/compiler/rustc_middle/Cargo.toml b/compiler/rustc_middle/Cargo.toml
index 290ebde87128..69e3b703ccee 100644
--- a/compiler/rustc_middle/Cargo.toml
+++ b/compiler/rustc_middle/Cargo.toml
@@ -6,7 +6,7 @@ edition = "2021"
[dependencies]
# tidy-alphabetical-start
bitflags = "2.4.1"
-derivative = "2.2.0"
+derive-where = "1.2.7"
either = "1.5.0"
field-offset = "0.3.5"
gsgdt = "0.1.2"
diff --git a/compiler/rustc_middle/src/mir/query.rs b/compiler/rustc_middle/src/mir/query.rs
index cd8e28522ecf..acf4414c4d6f 100644
--- a/compiler/rustc_middle/src/mir/query.rs
+++ b/compiler/rustc_middle/src/mir/query.rs
@@ -2,6 +2,7 @@
use crate::mir;
use crate::ty::{self, CoroutineArgsExt, OpaqueHiddenType, Ty, TyCtxt};
+use derive_where::derive_where;
use rustc_data_structures::fx::FxIndexMap;
use rustc_errors::ErrorGuaranteed;
use rustc_hir::def_id::LocalDefId;
@@ -224,13 +225,7 @@ rustc_data_structures::static_assert_size!(ConstraintCategory<'_>, 16);
/// See also `rustc_const_eval::borrow_check::constraints`.
#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
#[derive(TyEncodable, TyDecodable, HashStable, TypeVisitable, TypeFoldable)]
-#[derive(derivative::Derivative)]
-#[derivative(
- PartialOrd,
- Ord,
- PartialOrd = "feature_allow_slow_enum",
- Ord = "feature_allow_slow_enum"
-)]
+#[derive_where(PartialOrd, Ord)]
pub enum ConstraintCategory<'tcx> {
Return(ReturnConstraint),
Yield,
@@ -240,7 +235,7 @@ pub enum ConstraintCategory<'tcx> {
Cast {
/// Whether this is an unsizing cast and if yes, this contains the target type.
/// Region variables are erased to ReErased.
- #[derivative(PartialOrd = "ignore", Ord = "ignore")]
+ #[derive_where(skip)]
unsize_to: Option>,
},
@@ -250,7 +245,7 @@ pub enum ConstraintCategory<'tcx> {
ClosureBounds,
/// Contains the function type if available.
- CallArgument(#[derivative(PartialOrd = "ignore", Ord = "ignore")] Option>),
+ CallArgument(#[derive_where(skip)] Option>),
CopyBound,
SizedBound,
Assignment,
diff --git a/compiler/rustc_mir_build/src/thir/cx/expr.rs b/compiler/rustc_mir_build/src/thir/cx/expr.rs
index 99afb500e0b6..5f13b329de40 100644
--- a/compiler/rustc_mir_build/src/thir/cx/expr.rs
+++ b/compiler/rustc_mir_build/src/thir/cx/expr.rs
@@ -3,7 +3,6 @@ use crate::thir::cx::region::Scope;
use crate::thir::cx::Cx;
use crate::thir::util::UserAnnotatedTyHelpers;
use itertools::Itertools;
-use rustc_ast::LitKind;
use rustc_data_structures::stack::ensure_sufficient_stack;
use rustc_hir as hir;
use rustc_hir::def::{CtorKind, CtorOf, DefKind, Res};
@@ -22,8 +21,7 @@ use rustc_middle::ty::{
self, AdtKind, InlineConstArgs, InlineConstArgsParts, ScalarInt, Ty, UpvarArgs, UserType,
};
use rustc_middle::{bug, span_bug};
-use rustc_span::source_map::Spanned;
-use rustc_span::{sym, Span, DUMMY_SP};
+use rustc_span::{sym, Span};
use rustc_target::abi::{FieldIdx, FIRST_VARIANT};
use tracing::{debug, info, instrument, trace};
@@ -899,14 +897,10 @@ impl<'tcx> Cx<'tcx> {
let hir_id = self.tcx.local_def_id_to_hir_id(def_id.expect_local());
let generics = self.tcx.generics_of(hir_id.owner);
let Some(&index) = generics.param_def_id_to_index.get(&def_id) else {
- let guar = self.tcx.dcx().has_errors().unwrap();
- // We already errored about a late bound const
-
- let lit = self
- .tcx
- .hir_arena
- .alloc(Spanned { span: DUMMY_SP, node: LitKind::Err(guar) });
- return ExprKind::Literal { lit, neg: false };
+ span_bug!(
+ expr.span,
+ "Should have already errored about late bound consts: {def_id:?}"
+ );
};
let name = self.tcx.hir().name(hir_id);
let param = ty::ParamConst::new(index, name);
diff --git a/compiler/rustc_next_trait_solver/Cargo.toml b/compiler/rustc_next_trait_solver/Cargo.toml
index 79d2107b2a0a..fdf44e123781 100644
--- a/compiler/rustc_next_trait_solver/Cargo.toml
+++ b/compiler/rustc_next_trait_solver/Cargo.toml
@@ -6,7 +6,7 @@ edition = "2021"
[dependencies]
# tidy-alphabetical-start
bitflags = "2.4.1"
-derivative = "2.2.0"
+derive-where = "1.2.7"
rustc_ast_ir = { path = "../rustc_ast_ir", default-features = false }
rustc_data_structures = { path = "../rustc_data_structures", optional = true }
rustc_index = { path = "../rustc_index", default-features = false }
diff --git a/compiler/rustc_next_trait_solver/src/coherence.rs b/compiler/rustc_next_trait_solver/src/coherence.rs
index 55f602d907bb..f22ea41c5122 100644
--- a/compiler/rustc_next_trait_solver/src/coherence.rs
+++ b/compiler/rustc_next_trait_solver/src/coherence.rs
@@ -1,6 +1,7 @@
use std::fmt::Debug;
use std::ops::ControlFlow;
+use derive_where::derive_where;
use rustc_type_ir::inherent::*;
use rustc_type_ir::visit::{TypeVisitable, TypeVisitableExt, TypeVisitor};
use rustc_type_ir::{self as ty, InferCtxtLike, Interner};
@@ -108,15 +109,13 @@ impl From for IsFirstInputType {
}
}
-#[derive(derivative::Derivative)]
-#[derivative(Debug(bound = "T: Debug"))]
+#[derive_where(Debug; I: Interner, T: Debug)]
pub enum OrphanCheckErr {
NonLocalInputType(Vec<(I::Ty, IsFirstInputType)>),
UncoveredTyParams(UncoveredTyParams),
}
-#[derive(derivative::Derivative)]
-#[derivative(Debug(bound = "T: Debug"))]
+#[derive_where(Debug; I: Interner, T: Debug)]
pub struct UncoveredTyParams {
pub uncovered: T,
pub local_ty: Option,
diff --git a/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs b/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs
index 01dde9ca587c..f74597fcb391 100644
--- a/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs
+++ b/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs
@@ -2,6 +2,7 @@
pub(super) mod structural_traits;
+use derive_where::derive_where;
use rustc_type_ir::elaborate;
use rustc_type_ir::fold::TypeFoldable;
use rustc_type_ir::inherent::*;
@@ -21,8 +22,7 @@ use crate::solve::{
///
/// It consists of both the `source`, which describes how that goal would be proven,
/// and the `result` when using the given `source`.
-#[derive(derivative::Derivative)]
-#[derivative(Debug(bound = ""), Clone(bound = ""))]
+#[derive_where(Clone, Debug; I: Interner)]
pub(super) struct Candidate {
pub(super) source: CandidateSource,
pub(super) result: CanonicalResponse,
diff --git a/compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs b/compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs
index 7df14e81ab5d..770ac9a929ea 100644
--- a/compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs
+++ b/compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs
@@ -1,6 +1,7 @@
//! Code which is used by built-in goals that match "structurally", such a auto
//! traits, `Copy`/`Clone`.
+use derive_where::derive_where;
use rustc_ast_ir::{Movability, Mutability};
use rustc_type_ir::data_structures::HashMap;
use rustc_type_ir::fold::{TypeFoldable, TypeFolder, TypeSuperFoldable};
@@ -384,8 +385,7 @@ pub(in crate::solve) fn extract_tupled_inputs_and_output_from_callable {
pub tupled_inputs_ty: I::Ty,
diff --git a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs
index c23bc8f09ad1..e328284c0010 100644
--- a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs
+++ b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs
@@ -1,5 +1,6 @@
use std::ops::ControlFlow;
+use derive_where::derive_where;
#[cfg(feature = "nightly")]
use rustc_macros::{HashStable_NoContext, TyDecodable, TyEncodable};
use rustc_type_ir::data_structures::ensure_sufficient_stack;
@@ -87,8 +88,7 @@ where
pub(super) inspect: ProofTreeBuilder,
}
-#[derive(derivative::Derivative)]
-#[derivative(Clone(bound = ""), Debug(bound = ""), Default(bound = ""))]
+#[derive_where(Clone, Debug, Default; I: Interner)]
#[derive(TypeVisitable_Generic, TypeFoldable_Generic, Lift_Generic)]
#[cfg_attr(feature = "nightly", derive(TyDecodable, TyEncodable, HashStable_NoContext))]
// FIXME: This can be made crate-private once `EvalCtxt` also lives in this crate.
diff --git a/compiler/rustc_next_trait_solver/src/solve/inspect/build.rs b/compiler/rustc_next_trait_solver/src/solve/inspect/build.rs
index 3e266ddac71f..36e13cc97d64 100644
--- a/compiler/rustc_next_trait_solver/src/solve/inspect/build.rs
+++ b/compiler/rustc_next_trait_solver/src/solve/inspect/build.rs
@@ -7,6 +7,7 @@
use std::marker::PhantomData;
use std::mem;
+use derive_where::derive_where;
use rustc_type_ir::inherent::*;
use rustc_type_ir::{self as ty, search_graph, Interner};
@@ -51,8 +52,7 @@ where
/// in the code, only one or two variants are actually possible.
///
/// We simply ICE in case that assumption is broken.
-#[derive(derivative::Derivative)]
-#[derivative(Debug(bound = ""))]
+#[derive_where(Debug; I: Interner)]
enum DebugSolver {
Root,
GoalEvaluation(WipGoalEvaluation),
@@ -78,8 +78,7 @@ impl From> for DebugSolver {
}
}
-#[derive(derivative::Derivative)]
-#[derivative(PartialEq(bound = ""), Eq(bound = ""), Debug(bound = ""))]
+#[derive_where(PartialEq, Eq, Debug; I: Interner)]
struct WipGoalEvaluation {
pub uncanonicalized_goal: Goal,
pub orig_values: Vec,
@@ -96,8 +95,7 @@ impl WipGoalEvaluation {
}
}
-#[derive(derivative::Derivative)]
-#[derivative(PartialEq(bound = ""), Eq(bound = ""))]
+#[derive_where(PartialEq, Eq; I: Interner)]
pub(in crate::solve) enum WipCanonicalGoalEvaluationKind {
Overflow,
CycleInStack,
@@ -118,8 +116,7 @@ impl std::fmt::Debug for WipCanonicalGoalEvaluationKind {
}
}
-#[derive(derivative::Derivative)]
-#[derivative(PartialEq(bound = ""), Eq(bound = ""), Debug(bound = ""))]
+#[derive_where(PartialEq, Eq, Debug; I: Interner)]
struct WipCanonicalGoalEvaluation {
goal: CanonicalInput,
kind: Option>,
@@ -153,8 +150,7 @@ impl WipCanonicalGoalEvaluation {
}
}
-#[derive(derivative::Derivative)]
-#[derivative(PartialEq(bound = ""), Eq(bound = ""), Debug(bound = ""))]
+#[derive_where(PartialEq, Eq, Debug; I: Interner)]
struct WipCanonicalGoalEvaluationStep {
/// Unlike `EvalCtxt::var_values`, we append a new
/// generic arg here whenever we create a new inference
@@ -193,8 +189,7 @@ impl WipCanonicalGoalEvaluationStep {
}
}
-#[derive(derivative::Derivative)]
-#[derivative(PartialEq(bound = ""), Eq(bound = ""), Debug(bound = ""))]
+#[derive_where(PartialEq, Eq, Debug; I: Interner)]
struct WipProbe {
initial_num_var_values: usize,
steps: Vec>,
@@ -212,8 +207,7 @@ impl WipProbe {
}
}
-#[derive(derivative::Derivative)]
-#[derivative(PartialEq(bound = ""), Eq(bound = ""), Debug(bound = ""))]
+#[derive_where(PartialEq, Eq, Debug; I: Interner)]
enum WipProbeStep {
AddGoal(GoalSource, inspect::CanonicalState>),
NestedProbe(WipProbe),
diff --git a/compiler/rustc_parse/messages.ftl b/compiler/rustc_parse/messages.ftl
index c79dad3953ba..391a57917768 100644
--- a/compiler/rustc_parse/messages.ftl
+++ b/compiler/rustc_parse/messages.ftl
@@ -53,6 +53,12 @@ parse_bare_cr = {$double_quotes ->
parse_bare_cr_in_raw_string = bare CR not allowed in raw string
+parse_binder_and_polarity = `for<...>` binder not allowed with `{$polarity}` trait polarity modifier
+ .label = there is not a well-defined meaning for a higher-ranked `{$polarity}` trait
+
+parse_binder_before_modifiers = `for<...>` binder should be placed before trait bound modifiers
+ .label = place the `for<...>` binder before any modifiers
+
parse_bounds_not_allowed_on_trait_aliases = bounds are not allowed on trait aliases
parse_box_not_pat = expected pattern, found {$descr}
@@ -577,6 +583,9 @@ parse_missing_trait_in_trait_impl = missing trait in a trait impl
parse_modifier_lifetime = `{$modifier}` may only modify trait bounds, not lifetime bounds
.suggestion = remove the `{$modifier}`
+parse_modifiers_and_polarity = `{$modifiers_concatenated}` trait not allowed with `{$polarity}` trait polarity modifier
+ .label = there is not a well-defined meaning for a `{$modifiers_concatenated} {$polarity}` trait
+
parse_more_than_one_char = character literal may only contain one codepoint
.followed_by = this `{$chr}` is followed by the combining {$len ->
[one] mark
diff --git a/compiler/rustc_parse/src/errors.rs b/compiler/rustc_parse/src/errors.rs
index 109d36fe6899..2e81d2a876ba 100644
--- a/compiler/rustc_parse/src/errors.rs
+++ b/compiler/rustc_parse/src/errors.rs
@@ -3212,3 +3212,33 @@ pub struct UnsafeAttrOutsideUnsafeSuggestion {
#[suggestion_part(code = ")")]
pub right: Span,
}
+
+#[derive(Diagnostic)]
+#[diag(parse_binder_before_modifiers)]
+pub struct BinderBeforeModifiers {
+ #[primary_span]
+ pub binder_span: Span,
+ #[label]
+ pub modifiers_span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(parse_binder_and_polarity)]
+pub struct BinderAndPolarity {
+ #[primary_span]
+ pub polarity_span: Span,
+ #[label]
+ pub binder_span: Span,
+ pub polarity: &'static str,
+}
+
+#[derive(Diagnostic)]
+#[diag(parse_modifiers_and_polarity)]
+pub struct PolarityAndModifiers {
+ #[primary_span]
+ pub polarity_span: Span,
+ #[label]
+ pub modifiers_span: Span,
+ pub polarity: &'static str,
+ pub modifiers_concatenated: String,
+}
diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs
index fbc5b9146003..9aaf4b99243f 100644
--- a/compiler/rustc_parse/src/parser/item.rs
+++ b/compiler/rustc_parse/src/parser/item.rs
@@ -2773,7 +2773,14 @@ impl<'a> Parser<'a> {
let snapshot = p.create_snapshot_for_diagnostic();
let param = p.parse_param_general(req_name, first_param).or_else(|e| {
let guar = e.emit();
- let lo = p.prev_token.span;
+ // When parsing a param failed, we should check to make the span of the param
+ // not contain '(' before it.
+ // For example when parsing `*mut Self` in function `fn oof(*mut Self)`.
+ let lo = if let TokenKind::OpenDelim(Delimiter::Parenthesis) = p.prev_token.kind {
+ p.prev_token.span.shrink_to_hi()
+ } else {
+ p.prev_token.span
+ };
p.restore_snapshot(snapshot);
// Skip every token until next possible arg or end.
p.eat_to_tokens(&[&token::Comma, &token::CloseDelim(Delimiter::Parenthesis)]);
diff --git a/compiler/rustc_parse/src/parser/ty.rs b/compiler/rustc_parse/src/parser/ty.rs
index a8134110010d..f95ecd254ceb 100644
--- a/compiler/rustc_parse/src/parser/ty.rs
+++ b/compiler/rustc_parse/src/parser/ty.rs
@@ -935,9 +935,14 @@ impl<'a> Parser<'a> {
/// If no modifiers are present, this does not consume any tokens.
///
/// ```ebnf
- /// TRAIT_BOUND_MODIFIERS = [["~"] "const"] ["async"] ["?" | "!"]
+ /// CONSTNESS = [["~"] "const"]
+ /// ASYNCNESS = ["async"]
+ /// POLARITY = ["?" | "!"]
/// ```
+ ///
+ /// See `parse_generic_ty_bound` for the complete grammar of trait bound modifiers.
fn parse_trait_bound_modifiers(&mut self) -> PResult<'a, TraitBoundModifiers> {
+ let modifier_lo = self.token.span;
let constness = if self.eat(&token::Tilde) {
let tilde = self.prev_token.span;
self.expect_keyword(kw::Const)?;
@@ -970,6 +975,7 @@ impl<'a> Parser<'a> {
} else {
BoundAsyncness::Normal
};
+ let modifier_hi = self.prev_token.span;
let polarity = if self.eat(&token::Question) {
BoundPolarity::Maybe(self.prev_token.span)
@@ -980,13 +986,40 @@ impl<'a> Parser<'a> {
BoundPolarity::Positive
};
+ // Enforce the mutual-exclusivity of `const`/`async` and `?`/`!`.
+ match polarity {
+ BoundPolarity::Positive => {
+ // All trait bound modifiers allowed to combine with positive polarity
+ }
+ BoundPolarity::Maybe(polarity_span) | BoundPolarity::Negative(polarity_span) => {
+ match (asyncness, constness) {
+ (BoundAsyncness::Normal, BoundConstness::Never) => {
+ // Ok, no modifiers.
+ }
+ (_, _) => {
+ let constness = constness.as_str();
+ let asyncness = asyncness.as_str();
+ let glue =
+ if !constness.is_empty() && !asyncness.is_empty() { " " } else { "" };
+ let modifiers_concatenated = format!("{constness}{glue}{asyncness}");
+ self.dcx().emit_err(errors::PolarityAndModifiers {
+ polarity_span,
+ polarity: polarity.as_str(),
+ modifiers_span: modifier_lo.to(modifier_hi),
+ modifiers_concatenated,
+ });
+ }
+ }
+ }
+ }
+
Ok(TraitBoundModifiers { constness, asyncness, polarity })
}
/// Parses a type bound according to:
/// ```ebnf
/// TY_BOUND = TY_BOUND_NOPAREN | (TY_BOUND_NOPAREN)
- /// TY_BOUND_NOPAREN = [TRAIT_BOUND_MODIFIERS] [for] SIMPLE_PATH
+ /// TY_BOUND_NOPAREN = [for CONSTNESS ASYNCNESS | POLARITY] SIMPLE_PATH
/// ```
///
/// For example, this grammar accepts `for<'a: 'b> ~const ?m::Trait<'a>`.
@@ -996,9 +1029,25 @@ impl<'a> Parser<'a> {
has_parens: bool,
leading_token: &Token,
) -> PResult<'a, GenericBound> {
- let modifiers = self.parse_trait_bound_modifiers()?;
let (mut lifetime_defs, binder_span) = self.parse_late_bound_lifetime_defs()?;
+ let modifiers_lo = self.token.span;
+ let modifiers = self.parse_trait_bound_modifiers()?;
+ let modifiers_span = modifiers_lo.to(self.prev_token.span);
+
+ if let Some(binder_span) = binder_span {
+ match modifiers.polarity {
+ BoundPolarity::Negative(polarity_span) | BoundPolarity::Maybe(polarity_span) => {
+ self.dcx().emit_err(errors::BinderAndPolarity {
+ binder_span,
+ polarity_span,
+ polarity: modifiers.polarity.as_str(),
+ });
+ }
+ BoundPolarity::Positive => {}
+ }
+ }
+
// Recover erroneous lifetime bound with modifiers or binder.
// e.g. `T: for<'a> 'a` or `T: ~const 'a`.
if self.token.is_lifetime() {
@@ -1006,6 +1055,11 @@ impl<'a> Parser<'a> {
return self.parse_generic_lt_bound(lo, has_parens);
}
+ if let (more_lifetime_defs, Some(binder_span)) = self.parse_late_bound_lifetime_defs()? {
+ lifetime_defs.extend(more_lifetime_defs);
+ self.dcx().emit_err(errors::BinderBeforeModifiers { binder_span, modifiers_span });
+ }
+
let mut path = if self.token.is_keyword(kw::Fn)
&& self.look_ahead(1, |tok| tok.kind == TokenKind::OpenDelim(Delimiter::Parenthesis))
&& let Some(path) = self.recover_path_from_fn()
diff --git a/compiler/rustc_passes/src/naked_functions.rs b/compiler/rustc_passes/src/naked_functions.rs
index d45ee32a624d..dbbf802c920d 100644
--- a/compiler/rustc_passes/src/naked_functions.rs
+++ b/compiler/rustc_passes/src/naked_functions.rs
@@ -244,22 +244,19 @@ impl<'tcx> CheckInlineAssembly<'tcx> {
self.tcx.dcx().emit_err(NakedFunctionsOperands { unsupported_operands });
}
- let unsupported_options: Vec<&'static str> = [
- (InlineAsmOptions::MAY_UNWIND, "`may_unwind`"),
- (InlineAsmOptions::NOMEM, "`nomem`"),
- (InlineAsmOptions::NOSTACK, "`nostack`"),
- (InlineAsmOptions::PRESERVES_FLAGS, "`preserves_flags`"),
- (InlineAsmOptions::PURE, "`pure`"),
- (InlineAsmOptions::READONLY, "`readonly`"),
- ]
- .iter()
- .filter_map(|&(option, name)| if asm.options.contains(option) { Some(name) } else { None })
- .collect();
+ let supported_options =
+ InlineAsmOptions::RAW | InlineAsmOptions::NORETURN | InlineAsmOptions::ATT_SYNTAX;
+ let unsupported_options = asm.options.difference(supported_options);
if !unsupported_options.is_empty() {
self.tcx.dcx().emit_err(NakedFunctionsAsmOptions {
span,
- unsupported_options: unsupported_options.join(", "),
+ unsupported_options: unsupported_options
+ .human_readable_names()
+ .into_iter()
+ .map(|name| format!("`{name}`"))
+ .collect::>()
+ .join(", "),
});
}
diff --git a/compiler/rustc_query_system/src/ich/impls_syntax.rs b/compiler/rustc_query_system/src/ich/impls_syntax.rs
index 5bd4fe04848f..39da5e395c42 100644
--- a/compiler/rustc_query_system/src/ich/impls_syntax.rs
+++ b/compiler/rustc_query_system/src/ich/impls_syntax.rs
@@ -73,7 +73,6 @@ impl<'a> HashStable> for SourceFile {
source_len: _,
lines: _,
ref multibyte_chars,
- ref non_narrow_chars,
ref normalized_pos,
} = *self;
@@ -98,11 +97,6 @@ impl<'a> HashStable> for SourceFile {
char_pos.hash_stable(hcx, hasher);
}
- non_narrow_chars.len().hash_stable(hcx, hasher);
- for &char_pos in non_narrow_chars.iter() {
- char_pos.hash_stable(hcx, hasher);
- }
-
normalized_pos.len().hash_stable(hcx, hasher);
for &char_pos in normalized_pos.iter() {
char_pos.hash_stable(hcx, hasher);
diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs
index bf7972e392c9..046ae5fc5933 100644
--- a/compiler/rustc_resolve/src/diagnostics.rs
+++ b/compiler/rustc_resolve/src/diagnostics.rs
@@ -2012,7 +2012,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
)
} else if ident.name == sym::core {
(
- format!("maybe a missing crate `{ident}`?"),
+ format!("you might be missing crate `{ident}`"),
Some((
vec![(ident.span, "std".to_string())],
"try using `std` instead of `core`".to_string(),
@@ -2021,7 +2021,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
)
} else if self.tcx.sess.is_rust_2015() {
(
- format!("maybe a missing crate `{ident}`?"),
+ format!("you might be missing crate `{ident}`"),
Some((
vec![],
format!(
diff --git a/compiler/rustc_span/Cargo.toml b/compiler/rustc_span/Cargo.toml
index 83a554fe31de..3fdfe77ead97 100644
--- a/compiler/rustc_span/Cargo.toml
+++ b/compiler/rustc_span/Cargo.toml
@@ -5,7 +5,7 @@ edition = "2021"
[dependencies]
# tidy-alphabetical-start
-derivative = "2.2.0"
+derive-where = "1.2.7"
indexmap = { version = "2.0.0" }
itoa = "1.0"
md5 = { package = "md-5", version = "0.10.0" }
diff --git a/compiler/rustc_span/src/analyze_source_file.rs b/compiler/rustc_span/src/analyze_source_file.rs
index d9e1ebaf0bce..ba7e0cec5bd8 100644
--- a/compiler/rustc_span/src/analyze_source_file.rs
+++ b/compiler/rustc_span/src/analyze_source_file.rs
@@ -1,5 +1,4 @@
use super::*;
-use unicode_width::UnicodeWidthChar;
#[cfg(test)]
mod tests;
@@ -9,15 +8,12 @@ mod tests;
///
/// This function will use an SSE2 enhanced implementation if hardware support
/// is detected at runtime.
-pub fn analyze_source_file(
- src: &str,
-) -> (Vec, Vec, Vec) {
+pub fn analyze_source_file(src: &str) -> (Vec, Vec) {
let mut lines = vec![RelativeBytePos::from_u32(0)];
let mut multi_byte_chars = vec![];
- let mut non_narrow_chars = vec![];
// Calls the right implementation, depending on hardware support available.
- analyze_source_file_dispatch(src, &mut lines, &mut multi_byte_chars, &mut non_narrow_chars);
+ analyze_source_file_dispatch(src, &mut lines, &mut multi_byte_chars);
// The code above optimistically registers a new line *after* each \n
// it encounters. If that point is already outside the source_file, remove
@@ -30,7 +26,7 @@ pub fn analyze_source_file(
}
}
- (lines, multi_byte_chars, non_narrow_chars)
+ (lines, multi_byte_chars)
}
cfg_match! {
@@ -39,11 +35,10 @@ cfg_match! {
src: &str,
lines: &mut Vec,
multi_byte_chars: &mut Vec,
- non_narrow_chars: &mut Vec,
) {
if is_x86_feature_detected!("sse2") {
unsafe {
- analyze_source_file_sse2(src, lines, multi_byte_chars, non_narrow_chars);
+ analyze_source_file_sse2(src, lines, multi_byte_chars);
}
} else {
analyze_source_file_generic(
@@ -52,7 +47,6 @@ cfg_match! {
RelativeBytePos::from_u32(0),
lines,
multi_byte_chars,
- non_narrow_chars,
);
}
}
@@ -66,7 +60,6 @@ cfg_match! {
src: &str,
lines: &mut Vec,
multi_byte_chars: &mut Vec,
- non_narrow_chars: &mut Vec,
) {
#[cfg(target_arch = "x86")]
use std::arch::x86::*;
@@ -159,7 +152,6 @@ cfg_match! {
RelativeBytePos::from_usize(scan_start),
lines,
multi_byte_chars,
- non_narrow_chars,
);
}
@@ -172,7 +164,6 @@ cfg_match! {
RelativeBytePos::from_usize(tail_start),
lines,
multi_byte_chars,
- non_narrow_chars,
);
}
}
@@ -183,7 +174,6 @@ cfg_match! {
src: &str,
lines: &mut Vec,
multi_byte_chars: &mut Vec,
- non_narrow_chars: &mut Vec,
) {
analyze_source_file_generic(
src,
@@ -191,7 +181,6 @@ cfg_match! {
RelativeBytePos::from_u32(0),
lines,
multi_byte_chars,
- non_narrow_chars,
);
}
}
@@ -205,7 +194,6 @@ fn analyze_source_file_generic(
output_offset: RelativeBytePos,
lines: &mut Vec,
multi_byte_chars: &mut Vec,
- non_narrow_chars: &mut Vec,
) -> usize {
assert!(src.len() >= scan_len);
let mut i = 0;
@@ -227,16 +215,8 @@ fn analyze_source_file_generic(
let pos = RelativeBytePos::from_usize(i) + output_offset;
- match byte {
- b'\n' => {
- lines.push(pos + RelativeBytePos(1));
- }
- b'\t' => {
- non_narrow_chars.push(NonNarrowChar::Tab(pos));
- }
- _ => {
- non_narrow_chars.push(NonNarrowChar::ZeroWidth(pos));
- }
+ if let b'\n' = byte {
+ lines.push(pos + RelativeBytePos(1));
}
} else if byte >= 127 {
// The slow path:
@@ -252,14 +232,6 @@ fn analyze_source_file_generic(
let mbc = MultiByteChar { pos, bytes: char_len as u8 };
multi_byte_chars.push(mbc);
}
-
- // Assume control characters are zero width.
- // FIXME: How can we decide between `width` and `width_cjk`?
- let char_width = UnicodeWidthChar::width(c).unwrap_or(0);
-
- if char_width != 1 {
- non_narrow_chars.push(NonNarrowChar::new(pos, char_width));
- }
}
i += char_len;
diff --git a/compiler/rustc_span/src/analyze_source_file/tests.rs b/compiler/rustc_span/src/analyze_source_file/tests.rs
index 0c77d080c17a..e4a24239d8ea 100644
--- a/compiler/rustc_span/src/analyze_source_file/tests.rs
+++ b/compiler/rustc_span/src/analyze_source_file/tests.rs
@@ -4,11 +4,10 @@ macro_rules! test {
(case: $test_name:ident,
text: $text:expr,
lines: $lines:expr,
- multi_byte_chars: $multi_byte_chars:expr,
- non_narrow_chars: $non_narrow_chars:expr,) => {
+ multi_byte_chars: $multi_byte_chars:expr,) => {
#[test]
fn $test_name() {
- let (lines, multi_byte_chars, non_narrow_chars) = analyze_source_file($text);
+ let (lines, multi_byte_chars) = analyze_source_file($text);
let expected_lines: Vec =
$lines.into_iter().map(RelativeBytePos).collect();
@@ -21,13 +20,6 @@ macro_rules! test {
.collect();
assert_eq!(multi_byte_chars, expected_mbcs);
-
- let expected_nncs: Vec = $non_narrow_chars
- .into_iter()
- .map(|(pos, width)| NonNarrowChar::new(RelativeBytePos(pos), width))
- .collect();
-
- assert_eq!(non_narrow_chars, expected_nncs);
}
};
}
@@ -37,7 +29,6 @@ test!(
text: "",
lines: vec![],
multi_byte_chars: vec![],
- non_narrow_chars: vec![],
);
test!(
@@ -45,7 +36,6 @@ test!(
text: "a\nc",
lines: vec![0, 2],
multi_byte_chars: vec![],
- non_narrow_chars: vec![],
);
test!(
@@ -53,7 +43,6 @@ test!(
text: "012345678\nabcdef012345678\na",
lines: vec![0, 10, 26],
multi_byte_chars: vec![],
- non_narrow_chars: vec![],
);
test!(
@@ -61,7 +50,6 @@ test!(
text: "01234β789\nbcdef0123456789abcdef",
lines: vec![0, 11],
multi_byte_chars: vec![(5, 2)],
- non_narrow_chars: vec![],
);
test!(
@@ -69,7 +57,6 @@ test!(
text: "01234\u{07}6789\nbcdef0123456789abcdef",
lines: vec![0, 11],
multi_byte_chars: vec![],
- non_narrow_chars: vec![(5, 0)],
);
test!(
@@ -77,7 +64,6 @@ test!(
text: "aβc",
lines: vec![0],
multi_byte_chars: vec![(1, 2)],
- non_narrow_chars: vec![],
);
test!(
@@ -85,7 +71,6 @@ test!(
text: "0123456789abcΔf012345β",
lines: vec![0],
multi_byte_chars: vec![(13, 2), (22, 2)],
- non_narrow_chars: vec![],
);
test!(
@@ -93,7 +78,6 @@ test!(
text: "0123456789abcdeΔ123456789abcdef01234",
lines: vec![0],
multi_byte_chars: vec![(15, 2)],
- non_narrow_chars: vec![],
);
test!(
@@ -101,7 +85,6 @@ test!(
text: "0123456789abcdeΔ....",
lines: vec![0],
multi_byte_chars: vec![(15, 2)],
- non_narrow_chars: vec![],
);
test!(
@@ -109,7 +92,6 @@ test!(
text: "0\t2",
lines: vec![0],
multi_byte_chars: vec![],
- non_narrow_chars: vec![(1, 4)],
);
test!(
@@ -117,7 +99,6 @@ test!(
text: "01\t3456789abcdef01234567\u{07}9",
lines: vec![0],
multi_byte_chars: vec![],
- non_narrow_chars: vec![(2, 4), (24, 0)],
);
test!(
@@ -125,5 +106,4 @@ test!(
text: "01\t345\n789abcΔf01234567\u{07}9\nbcΔf",
lines: vec![0, 7, 27],
multi_byte_chars: vec![(13, 2), (29, 2)],
- non_narrow_chars: vec![(2, 4), (24, 0)],
);
diff --git a/compiler/rustc_span/src/lib.rs b/compiler/rustc_span/src/lib.rs
index 266956d63d71..b94f910d4bc1 100644
--- a/compiler/rustc_span/src/lib.rs
+++ b/compiler/rustc_span/src/lib.rs
@@ -38,6 +38,7 @@
// this crate without this line making `rustc_span` available.
extern crate self as rustc_span;
+use derive_where::derive_where;
use rustc_data_structures::{outline, AtomicRef};
use rustc_macros::{Decodable, Encodable, HashStable_Generic};
use rustc_serialize::opaque::{FileEncoder, MemDecoder};
@@ -467,18 +468,18 @@ impl FileName {
/// `SpanData` is public because `Span` uses a thread-local interner and can't be
/// sent to other threads, but some pieces of performance infra run in a separate thread.
/// Using `Span` is generally preferred.
-#[derive(Clone, Copy, Hash, PartialEq, Eq, derivative::Derivative)]
-#[derivative(PartialOrd, Ord)]
+#[derive(Clone, Copy, Hash, PartialEq, Eq)]
+#[derive_where(PartialOrd, Ord)]
pub struct SpanData {
pub lo: BytePos,
pub hi: BytePos,
/// Information about where the macro came from, if this piece of
/// code was created by a macro expansion.
- #[derivative(PartialOrd = "ignore", Ord = "ignore")]
+ #[derive_where(skip)]
// `SyntaxContext` does not implement `Ord`.
// The other fields are enough to determine in-file order.
pub ctxt: SyntaxContext,
- #[derivative(PartialOrd = "ignore", Ord = "ignore")]
+ #[derive_where(skip)]
// `LocalDefId` does not implement `Ord`.
// The other fields are enough to determine in-file order.
pub parent: Option,
@@ -1345,68 +1346,6 @@ pub struct MultiByteChar {
pub bytes: u8,
}
-/// Identifies an offset of a non-narrow character in a `SourceFile`.
-#[derive(Copy, Clone, Encodable, Decodable, Eq, PartialEq, Debug, HashStable_Generic)]
-pub enum NonNarrowChar {
- /// Represents a zero-width character.
- ZeroWidth(RelativeBytePos),
- /// Represents a wide (full-width) character.
- Wide(RelativeBytePos),
- /// Represents a tab character, represented visually with a width of 4 characters.
- Tab(RelativeBytePos),
-}
-
-impl NonNarrowChar {
- fn new(pos: RelativeBytePos, width: usize) -> Self {
- match width {
- 0 => NonNarrowChar::ZeroWidth(pos),
- 2 => NonNarrowChar::Wide(pos),
- 4 => NonNarrowChar::Tab(pos),
- _ => panic!("width {width} given for non-narrow character"),
- }
- }
-
- /// Returns the relative offset of the character in the `SourceFile`.
- pub fn pos(&self) -> RelativeBytePos {
- match *self {
- NonNarrowChar::ZeroWidth(p) | NonNarrowChar::Wide(p) | NonNarrowChar::Tab(p) => p,
- }
- }
-
- /// Returns the width of the character, 0 (zero-width) or 2 (wide).
- pub fn width(&self) -> usize {
- match *self {
- NonNarrowChar::ZeroWidth(_) => 0,
- NonNarrowChar::Wide(_) => 2,
- NonNarrowChar::Tab(_) => 4,
- }
- }
-}
-
-impl Add for NonNarrowChar {
- type Output = Self;
-
- fn add(self, rhs: RelativeBytePos) -> Self {
- match self {
- NonNarrowChar::ZeroWidth(pos) => NonNarrowChar::ZeroWidth(pos + rhs),
- NonNarrowChar::Wide(pos) => NonNarrowChar::Wide(pos + rhs),
- NonNarrowChar::Tab(pos) => NonNarrowChar::Tab(pos + rhs),
- }
- }
-}
-
-impl Sub for NonNarrowChar {
- type Output = Self;
-
- fn sub(self, rhs: RelativeBytePos) -> Self {
- match self {
- NonNarrowChar::ZeroWidth(pos) => NonNarrowChar::ZeroWidth(pos - rhs),
- NonNarrowChar::Wide(pos) => NonNarrowChar::Wide(pos - rhs),
- NonNarrowChar::Tab(pos) => NonNarrowChar::Tab(pos - rhs),
- }
- }
-}
-
/// Identifies an offset of a character that was normalized away from `SourceFile`.
#[derive(Copy, Clone, Encodable, Decodable, Eq, PartialEq, Debug, HashStable_Generic)]
pub struct NormalizedPos {
@@ -1581,8 +1520,6 @@ pub struct SourceFile {
pub lines: FreezeLock,
/// Locations of multi-byte characters in the source code.
pub multibyte_chars: Vec,
- /// Width of characters that are not narrow in the source code.
- pub non_narrow_chars: Vec,
/// Locations of characters removed during normalization.
pub normalized_pos: Vec,
/// A hash of the filename & crate-id, used for uniquely identifying source
@@ -1604,7 +1541,6 @@ impl Clone for SourceFile {
source_len: self.source_len,
lines: self.lines.clone(),
multibyte_chars: self.multibyte_chars.clone(),
- non_narrow_chars: self.non_narrow_chars.clone(),
normalized_pos: self.normalized_pos.clone(),
stable_id: self.stable_id,
cnum: self.cnum,
@@ -1679,7 +1615,6 @@ impl Encodable for SourceFile {
}
self.multibyte_chars.encode(s);
- self.non_narrow_chars.encode(s);
self.stable_id.encode(s);
self.normalized_pos.encode(s);
self.cnum.encode(s);
@@ -1706,7 +1641,6 @@ impl Decodable for SourceFile {
}
};
let multibyte_chars: Vec = Decodable::decode(d);
- let non_narrow_chars: Vec = Decodable::decode(d);
let stable_id = Decodable::decode(d);
let normalized_pos: Vec = Decodable::decode(d);
let cnum: CrateNum = Decodable::decode(d);
@@ -1721,7 +1655,6 @@ impl Decodable for SourceFile {
external_src: FreezeLock::frozen(ExternalSource::Unneeded),
lines: FreezeLock::new(lines),
multibyte_chars,
- non_narrow_chars,
normalized_pos,
stable_id,
cnum,
@@ -1809,8 +1742,7 @@ impl SourceFile {
let source_len = src.len();
let source_len = u32::try_from(source_len).map_err(|_| OffsetOverflowError)?;
- let (lines, multibyte_chars, non_narrow_chars) =
- analyze_source_file::analyze_source_file(&src);
+ let (lines, multibyte_chars) = analyze_source_file::analyze_source_file(&src);
Ok(SourceFile {
name,
@@ -1821,7 +1753,6 @@ impl SourceFile {
source_len: RelativeBytePos::from_u32(source_len),
lines: FreezeLock::frozen(SourceFileLines::Lines(lines)),
multibyte_chars,
- non_narrow_chars,
normalized_pos,
stable_id,
cnum: LOCAL_CRATE,
@@ -2130,41 +2061,45 @@ impl SourceFile {
let pos = self.relative_position(pos);
let (line, col_or_chpos) = self.lookup_file_pos(pos);
if line > 0 {
- let col = col_or_chpos;
- let linebpos = self.lines()[line - 1];
- let col_display = {
- let start_width_idx = self
- .non_narrow_chars
- .binary_search_by_key(&linebpos, |x| x.pos())
- .unwrap_or_else(|x| x);
- let end_width_idx = self
- .non_narrow_chars
- .binary_search_by_key(&pos, |x| x.pos())
- .unwrap_or_else(|x| x);
- let special_chars = end_width_idx - start_width_idx;
- let non_narrow: usize = self.non_narrow_chars[start_width_idx..end_width_idx]
- .iter()
- .map(|x| x.width())
- .sum();
- col.0 - special_chars + non_narrow
+ let Some(code) = self.get_line(line - 1) else {
+ // If we don't have the code available, it is ok as a fallback to return the bytepos
+ // instead of the "display" column, which is only used to properly show underlines
+ // in the terminal.
+ // FIXME: we'll want better handling of this in the future for the sake of tools
+ // that want to use the display col instead of byte offsets to modify Rust code, but
+ // that is a problem for another day, the previous code was already incorrect for
+ // both displaying *and* third party tools using the json output naïvely.
+ tracing::info!("couldn't find line {line} {:?}", self.name);
+ return (line, col_or_chpos, col_or_chpos.0);
};
- (line, col, col_display)
+ let display_col = code.chars().take(col_or_chpos.0).map(|ch| char_width(ch)).sum();
+ (line, col_or_chpos, display_col)
} else {
- let chpos = col_or_chpos;
- let col_display = {
- let end_width_idx = self
- .non_narrow_chars
- .binary_search_by_key(&pos, |x| x.pos())
- .unwrap_or_else(|x| x);
- let non_narrow: usize =
- self.non_narrow_chars[0..end_width_idx].iter().map(|x| x.width()).sum();
- chpos.0 - end_width_idx + non_narrow
- };
- (0, chpos, col_display)
+ // This is never meant to happen?
+ (0, col_or_chpos, col_or_chpos.0)
}
}
}
+pub fn char_width(ch: char) -> usize {
+ // FIXME: `unicode_width` sometimes disagrees with terminals on how wide a `char` is. For now,
+ // just accept that sometimes the code line will be longer than desired.
+ match ch {
+ '\t' => 4,
+ // Keep the following list in sync with `rustc_errors::emitter::OUTPUT_REPLACEMENTS`. These
+ // are control points that we replace before printing with a visible codepoint for the sake
+ // of being able to point at them with underlines.
+ '\u{0000}' | '\u{0001}' | '\u{0002}' | '\u{0003}' | '\u{0004}' | '\u{0005}'
+ | '\u{0006}' | '\u{0007}' | '\u{0008}' | '\u{000B}' | '\u{000C}' | '\u{000D}'
+ | '\u{000E}' | '\u{000F}' | '\u{0010}' | '\u{0011}' | '\u{0012}' | '\u{0013}'
+ | '\u{0014}' | '\u{0015}' | '\u{0016}' | '\u{0017}' | '\u{0018}' | '\u{0019}'
+ | '\u{001A}' | '\u{001B}' | '\u{001C}' | '\u{001D}' | '\u{001E}' | '\u{001F}'
+ | '\u{007F}' | '\u{202A}' | '\u{202B}' | '\u{202D}' | '\u{202E}' | '\u{2066}'
+ | '\u{2067}' | '\u{2068}' | '\u{202C}' | '\u{2069}' => 1,
+ _ => unicode_width::UnicodeWidthChar::width(ch).unwrap_or(1),
+ }
+}
+
/// Normalizes the source code and records the normalizations.
fn normalize_src(src: &mut String) -> Vec {
let mut normalized_pos = vec![];
diff --git a/compiler/rustc_span/src/source_map.rs b/compiler/rustc_span/src/source_map.rs
index fb212d67997a..14c157a0111c 100644
--- a/compiler/rustc_span/src/source_map.rs
+++ b/compiler/rustc_span/src/source_map.rs
@@ -330,7 +330,6 @@ impl SourceMap {
cnum: CrateNum,
file_local_lines: FreezeLock,
multibyte_chars: Vec,
- non_narrow_chars: Vec,
normalized_pos: Vec,
metadata_index: u32,
) -> Lrc {
@@ -348,7 +347,6 @@ impl SourceMap {
source_len,
lines: file_local_lines,
multibyte_chars,
- non_narrow_chars,
normalized_pos,
stable_id,
cnum,
diff --git a/compiler/rustc_span/src/source_map/tests.rs b/compiler/rustc_span/src/source_map/tests.rs
index dcb02da37192..0c818b94b85a 100644
--- a/compiler/rustc_span/src/source_map/tests.rs
+++ b/compiler/rustc_span/src/source_map/tests.rs
@@ -232,7 +232,6 @@ fn t10() {
source_len,
lines,
multibyte_chars,
- non_narrow_chars,
normalized_pos,
stable_id,
..
@@ -246,7 +245,6 @@ fn t10() {
CrateNum::ZERO,
FreezeLock::new(lines.read().clone()),
multibyte_chars,
- non_narrow_chars,
normalized_pos,
0,
);
diff --git a/compiler/rustc_trait_selection/src/traits/object_safety.rs b/compiler/rustc_trait_selection/src/traits/object_safety.rs
index 1c6993bdd372..ec19cf276681 100644
--- a/compiler/rustc_trait_selection/src/traits/object_safety.rs
+++ b/compiler/rustc_trait_selection/src/traits/object_safety.rs
@@ -12,17 +12,16 @@ use super::elaborate;
use crate::infer::TyCtxtInferExt;
use crate::traits::query::evaluate_obligation::InferCtxtExt;
-use crate::traits::{self, Obligation, ObligationCause};
+use crate::traits::{util, Obligation, ObligationCause};
use rustc_errors::FatalError;
use rustc_hir as hir;
use rustc_hir::def_id::DefId;
use rustc_middle::query::Providers;
use rustc_middle::ty::{
- self, EarlyBinder, ExistentialPredicateStableCmpExt as _, Ty, TyCtxt, TypeSuperVisitable,
- TypeVisitable, TypeVisitor,
+ self, EarlyBinder, ExistentialPredicateStableCmpExt as _, GenericArgs, Ty, TyCtxt,
+ TypeFoldable, TypeFolder, TypeSuperFoldable, TypeSuperVisitable, TypeVisitable,
+ TypeVisitableExt, TypeVisitor, Upcast,
};
-use rustc_middle::ty::{GenericArg, GenericArgs};
-use rustc_middle::ty::{TypeVisitableExt, Upcast};
use rustc_span::symbol::Symbol;
use rustc_span::Span;
use rustc_target::abi::Abi;
@@ -195,7 +194,13 @@ fn predicates_reference_self(
.predicates
.iter()
.map(|&(predicate, sp)| (predicate.instantiate_supertrait(tcx, trait_ref), sp))
- .filter_map(|predicate| predicate_references_self(tcx, predicate))
+ .filter_map(|(clause, sp)| {
+ // Super predicates cannot allow self projections, since they're
+ // impossible to make into existential bounds without eager resolution
+ // or something.
+ // e.g. `trait A: B- `.
+ predicate_references_self(tcx, trait_def_id, clause, sp, AllowSelfProjections::No)
+ })
.collect()
}
@@ -204,20 +209,25 @@ fn bounds_reference_self(tcx: TyCtxt<'_>, trait_def_id: DefId) -> SmallVec<[Span
.in_definition_order()
.filter(|item| item.kind == ty::AssocKind::Type)
.flat_map(|item| tcx.explicit_item_bounds(item.def_id).iter_identity_copied())
- .filter_map(|c| predicate_references_self(tcx, c))
+ .filter_map(|(clause, sp)| {
+ // Item bounds *can* have self projections, since they never get
+ // their self type erased.
+ predicate_references_self(tcx, trait_def_id, clause, sp, AllowSelfProjections::Yes)
+ })
.collect()
}
fn predicate_references_self<'tcx>(
tcx: TyCtxt<'tcx>,
- (predicate, sp): (ty::Clause<'tcx>, Span),
+ trait_def_id: DefId,
+ predicate: ty::Clause<'tcx>,
+ sp: Span,
+ allow_self_projections: AllowSelfProjections,
) -> Option {
- let self_ty = tcx.types.self_param;
- let has_self_ty = |arg: &GenericArg<'tcx>| arg.walk().any(|arg| arg == self_ty.into());
match predicate.kind().skip_binder() {
ty::ClauseKind::Trait(ref data) => {
// In the case of a trait predicate, we can skip the "self" type.
- data.trait_ref.args[1..].iter().any(has_self_ty).then_some(sp)
+ data.trait_ref.args[1..].iter().any(|&arg| contains_illegal_self_type_reference(tcx, trait_def_id, arg, allow_self_projections)).then_some(sp)
}
ty::ClauseKind::Projection(ref data) => {
// And similarly for projections. This should be redundant with
@@ -235,9 +245,9 @@ fn predicate_references_self<'tcx>(
//
// This is ALT2 in issue #56288, see that for discussion of the
// possible alternatives.
- data.projection_term.args[1..].iter().any(has_self_ty).then_some(sp)
+ data.projection_term.args[1..].iter().any(|&arg| contains_illegal_self_type_reference(tcx, trait_def_id, arg, allow_self_projections)).then_some(sp)
}
- ty::ClauseKind::ConstArgHasType(_ct, ty) => has_self_ty(&ty.into()).then_some(sp),
+ ty::ClauseKind::ConstArgHasType(_ct, ty) => contains_illegal_self_type_reference(tcx, trait_def_id, ty, allow_self_projections).then_some(sp),
ty::ClauseKind::WellFormed(..)
| ty::ClauseKind::TypeOutlives(..)
@@ -383,7 +393,12 @@ fn virtual_call_violations_for_method<'tcx>(
let mut errors = Vec::new();
for (i, &input_ty) in sig.skip_binder().inputs().iter().enumerate().skip(1) {
- if contains_illegal_self_type_reference(tcx, trait_def_id, sig.rebind(input_ty)) {
+ if contains_illegal_self_type_reference(
+ tcx,
+ trait_def_id,
+ sig.rebind(input_ty),
+ AllowSelfProjections::Yes,
+ ) {
let span = if let Some(hir::Node::TraitItem(hir::TraitItem {
kind: hir::TraitItemKind::Fn(sig, _),
..
@@ -396,7 +411,12 @@ fn virtual_call_violations_for_method<'tcx>(
errors.push(MethodViolationCode::ReferencesSelfInput(span));
}
}
- if contains_illegal_self_type_reference(tcx, trait_def_id, sig.output()) {
+ if contains_illegal_self_type_reference(
+ tcx,
+ trait_def_id,
+ sig.output(),
+ AllowSelfProjections::Yes,
+ ) {
errors.push(MethodViolationCode::ReferencesSelfOutput);
}
if let Some(code) = contains_illegal_impl_trait_in_trait(tcx, method.def_id, sig.output()) {
@@ -482,7 +502,7 @@ fn virtual_call_violations_for_method<'tcx>(
return false;
}
- contains_illegal_self_type_reference(tcx, trait_def_id, pred)
+ contains_illegal_self_type_reference(tcx, trait_def_id, pred, AllowSelfProjections::Yes)
}) {
errors.push(MethodViolationCode::WhereClauseReferencesSelf);
}
@@ -711,121 +731,181 @@ fn receiver_is_dispatchable<'tcx>(
infcx.predicate_must_hold_modulo_regions(&obligation)
}
+#[derive(Copy, Clone)]
+enum AllowSelfProjections {
+ Yes,
+ No,
+}
+
+/// This is somewhat subtle. In general, we want to forbid
+/// references to `Self` in the argument and return types,
+/// since the value of `Self` is erased. However, there is one
+/// exception: it is ok to reference `Self` in order to access
+/// an associated type of the current trait, since we retain
+/// the value of those associated types in the object type
+/// itself.
+///
+/// ```rust,ignore (example)
+/// trait SuperTrait {
+/// type X;
+/// }
+///
+/// trait Trait : SuperTrait {
+/// type Y;
+/// fn foo(&self, x: Self) // bad
+/// fn foo(&self) -> Self // bad
+/// fn foo(&self) -> Option // bad
+/// fn foo(&self) -> Self::Y // OK, desugars to next example
+/// fn foo(&self) -> ::Y // OK
+/// fn foo(&self) -> Self::X // OK, desugars to next example
+/// fn foo(&self) -> ::X // OK
+/// }
+/// ```
+///
+/// However, it is not as simple as allowing `Self` in a projected
+/// type, because there are illegal ways to use `Self` as well:
+///
+/// ```rust,ignore (example)
+/// trait Trait : SuperTrait {
+/// ...
+/// fn foo(&self) -> ::X;
+/// }
+/// ```
+///
+/// Here we will not have the type of `X` recorded in the
+/// object type, and we cannot resolve `Self as SomeOtherTrait`
+/// without knowing what `Self` is.
fn contains_illegal_self_type_reference<'tcx, T: TypeVisitable>>(
tcx: TyCtxt<'tcx>,
trait_def_id: DefId,
value: T,
+ allow_self_projections: AllowSelfProjections,
) -> bool {
- // This is somewhat subtle. In general, we want to forbid
- // references to `Self` in the argument and return types,
- // since the value of `Self` is erased. However, there is one
- // exception: it is ok to reference `Self` in order to access
- // an associated type of the current trait, since we retain
- // the value of those associated types in the object type
- // itself.
- //
- // ```rust
- // trait SuperTrait {
- // type X;
- // }
- //
- // trait Trait : SuperTrait {
- // type Y;
- // fn foo(&self, x: Self) // bad
- // fn foo(&self) -> Self // bad
- // fn foo(&self) -> Option // bad
- // fn foo(&self) -> Self::Y // OK, desugars to next example
- // fn foo(&self) -> ::Y // OK
- // fn foo(&self) -> Self::X // OK, desugars to next example
- // fn foo(&self) -> ::X // OK
- // }
- // ```
- //
- // However, it is not as simple as allowing `Self` in a projected
- // type, because there are illegal ways to use `Self` as well:
- //
- // ```rust
- // trait Trait : SuperTrait {
- // ...
- // fn foo(&self) -> ::X;
- // }
- // ```
- //
- // Here we will not have the type of `X` recorded in the
- // object type, and we cannot resolve `Self as SomeOtherTrait`
- // without knowing what `Self` is.
+ value
+ .visit_with(&mut IllegalSelfTypeVisitor {
+ tcx,
+ trait_def_id,
+ supertraits: None,
+ allow_self_projections,
+ })
+ .is_break()
+}
- struct IllegalSelfTypeVisitor<'tcx> {
- tcx: TyCtxt<'tcx>,
- trait_def_id: DefId,
- supertraits: Option>,
- }
+struct IllegalSelfTypeVisitor<'tcx> {
+ tcx: TyCtxt<'tcx>,
+ trait_def_id: DefId,
+ supertraits: Option>>,
+ allow_self_projections: AllowSelfProjections,
+}
- impl<'tcx> TypeVisitor> for IllegalSelfTypeVisitor<'tcx> {
- type Result = ControlFlow<()>;
+impl<'tcx> TypeVisitor> for IllegalSelfTypeVisitor<'tcx> {
+ type Result = ControlFlow<()>;
- fn visit_ty(&mut self, t: Ty<'tcx>) -> Self::Result {
- match t.kind() {
- ty::Param(_) => {
- if t == self.tcx.types.self_param {
- ControlFlow::Break(())
- } else {
- ControlFlow::Continue(())
- }
- }
- ty::Alias(ty::Projection, ref data)
- if self.tcx.is_impl_trait_in_trait(data.def_id) =>
- {
- // We'll deny these later in their own pass
+ fn visit_ty(&mut self, t: Ty<'tcx>) -> Self::Result {
+ match t.kind() {
+ ty::Param(_) => {
+ if t == self.tcx.types.self_param {
+ ControlFlow::Break(())
+ } else {
ControlFlow::Continue(())
}
- ty::Alias(ty::Projection, ref data) => {
- // This is a projected type `::X`.
-
- // Compute supertraits of current trait lazily.
- if self.supertraits.is_none() {
- let trait_ref =
- ty::Binder::dummy(ty::TraitRef::identity(self.tcx, self.trait_def_id));
- self.supertraits = Some(
- traits::supertraits(self.tcx, trait_ref).map(|t| t.def_id()).collect(),
- );
- }
-
- // Determine whether the trait reference `Foo as
- // SomeTrait` is in fact a supertrait of the
- // current trait. In that case, this type is
- // legal, because the type `X` will be specified
- // in the object type. Note that we can just use
- // direct equality here because all of these types
- // are part of the formal parameter listing, and
- // hence there should be no inference variables.
- let is_supertrait_of_current_trait = self
- .supertraits
- .as_ref()
- .unwrap()
- .contains(&data.trait_ref(self.tcx).def_id);
-
- // only walk contained types if it's not a super trait
- if is_supertrait_of_current_trait {
- ControlFlow::Continue(())
- } else {
- t.super_visit_with(self) // POSSIBLY reporting an error
- }
- }
- _ => t.super_visit_with(self), // walk contained types, if any
}
- }
+ ty::Alias(ty::Projection, ref data) if self.tcx.is_impl_trait_in_trait(data.def_id) => {
+ // We'll deny these later in their own pass
+ ControlFlow::Continue(())
+ }
+ ty::Alias(ty::Projection, ref data) => {
+ match self.allow_self_projections {
+ AllowSelfProjections::Yes => {
+ // This is a projected type `::X`.
- fn visit_const(&mut self, ct: ty::Const<'tcx>) -> Self::Result {
- // Constants can only influence object safety if they are generic and reference `Self`.
- // This is only possible for unevaluated constants, so we walk these here.
- self.tcx.expand_abstract_consts(ct).super_visit_with(self)
+ // Compute supertraits of current trait lazily.
+ if self.supertraits.is_none() {
+ self.supertraits = Some(
+ util::supertraits(
+ self.tcx,
+ ty::Binder::dummy(ty::TraitRef::identity(
+ self.tcx,
+ self.trait_def_id,
+ )),
+ )
+ .map(|trait_ref| {
+ self.tcx.erase_regions(
+ self.tcx.instantiate_bound_regions_with_erased(trait_ref),
+ )
+ })
+ .collect(),
+ );
+ }
+
+ // Determine whether the trait reference `Foo as
+ // SomeTrait` is in fact a supertrait of the
+ // current trait. In that case, this type is
+ // legal, because the type `X` will be specified
+ // in the object type. Note that we can just use
+ // direct equality here because all of these types
+ // are part of the formal parameter listing, and
+ // hence there should be no inference variables.
+ let is_supertrait_of_current_trait =
+ self.supertraits.as_ref().unwrap().contains(
+ &data.trait_ref(self.tcx).fold_with(
+ &mut EraseEscapingBoundRegions {
+ tcx: self.tcx,
+ binder: ty::INNERMOST,
+ },
+ ),
+ );
+
+ // only walk contained types if it's not a super trait
+ if is_supertrait_of_current_trait {
+ ControlFlow::Continue(())
+ } else {
+ t.super_visit_with(self) // POSSIBLY reporting an error
+ }
+ }
+ AllowSelfProjections::No => t.super_visit_with(self),
+ }
+ }
+ _ => t.super_visit_with(self),
}
}
- value
- .visit_with(&mut IllegalSelfTypeVisitor { tcx, trait_def_id, supertraits: None })
- .is_break()
+ fn visit_const(&mut self, ct: ty::Const<'tcx>) -> Self::Result {
+ // Constants can only influence object safety if they are generic and reference `Self`.
+ // This is only possible for unevaluated constants, so we walk these here.
+ self.tcx.expand_abstract_consts(ct).super_visit_with(self)
+ }
+}
+
+struct EraseEscapingBoundRegions<'tcx> {
+ tcx: TyCtxt<'tcx>,
+ binder: ty::DebruijnIndex,
+}
+
+impl<'tcx> TypeFolder> for EraseEscapingBoundRegions<'tcx> {
+ fn cx(&self) -> TyCtxt<'tcx> {
+ self.tcx
+ }
+
+ fn fold_binder(&mut self, t: ty::Binder<'tcx, T>) -> ty::Binder<'tcx, T>
+ where
+ T: TypeFoldable>,
+ {
+ self.binder.shift_in(1);
+ let result = t.super_fold_with(self);
+ self.binder.shift_out(1);
+ result
+ }
+
+ fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
+ if let ty::ReBound(debruijn, _) = *r
+ && debruijn < self.binder
+ {
+ r
+ } else {
+ self.tcx.lifetimes.re_erased
+ }
+ }
}
pub fn contains_illegal_impl_trait_in_trait<'tcx>(
diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs
index 1d7a05150444..b96e0c8a9775 100644
--- a/compiler/rustc_trait_selection/src/traits/project.rs
+++ b/compiler/rustc_trait_selection/src/traits/project.rs
@@ -1202,6 +1202,12 @@ fn assemble_candidates_from_impls<'cx, 'tcx>(
false
}
}
+ } else if tcx.trait_is_auto(trait_ref.def_id) {
+ tcx.dcx().span_delayed_bug(
+ tcx.def_span(obligation.predicate.def_id),
+ "associated types not allowed on auto traits",
+ );
+ false
} else {
bug!("unexpected builtin trait with associated type: {trait_ref:?}")
}
diff --git a/compiler/rustc_ty_utils/src/instance.rs b/compiler/rustc_ty_utils/src/instance.rs
index 7b6d86d22a57..a2bed61a7ae1 100644
--- a/compiler/rustc_ty_utils/src/instance.rs
+++ b/compiler/rustc_ty_utils/src/instance.rs
@@ -191,11 +191,22 @@ fn resolve_associated_item<'tcx>(
// Any final impl is required to define all associated items.
if !leaf_def.item.defaultness(tcx).has_value() {
- let guard = tcx.dcx().span_delayed_bug(
+ let guar = tcx.dcx().span_delayed_bug(
tcx.def_span(leaf_def.item.def_id),
"missing value for assoc item in impl",
);
- return Err(guard);
+ return Err(guar);
+ }
+
+ // Make sure that we're projecting to an item that has compatible args.
+ // This may happen if we are resolving an instance before codegen, such
+ // as during inlining. This check is also done in projection.
+ if !tcx.check_args_compatible(leaf_def.item.def_id, args) {
+ let guar = tcx.dcx().span_delayed_bug(
+ tcx.def_span(leaf_def.item.def_id),
+ "missing value for assoc item in impl",
+ );
+ return Err(guar);
}
let args = tcx.erase_regions(args);
diff --git a/compiler/rustc_type_ir/Cargo.toml b/compiler/rustc_type_ir/Cargo.toml
index 769e350b835c..2750838bbe99 100644
--- a/compiler/rustc_type_ir/Cargo.toml
+++ b/compiler/rustc_type_ir/Cargo.toml
@@ -6,7 +6,7 @@ edition = "2021"
[dependencies]
# tidy-alphabetical-start
bitflags = "2.4.1"
-derivative = "2.2.0"
+derive-where = "1.2.7"
indexmap = "2.0.0"
rustc_ast_ir = { path = "../rustc_ast_ir", default-features = false }
rustc_data_structures = { path = "../rustc_data_structures", optional = true }
diff --git a/compiler/rustc_type_ir/src/binder.rs b/compiler/rustc_type_ir/src/binder.rs
index 17b35a2807a2..c1f6fb36324e 100644
--- a/compiler/rustc_type_ir/src/binder.rs
+++ b/compiler/rustc_type_ir/src/binder.rs
@@ -3,6 +3,7 @@ use std::hash::Hash;
use std::marker::PhantomData;
use std::ops::{ControlFlow, Deref};
+use derive_where::derive_where;
#[cfg(feature = "nightly")]
use rustc_macros::{HashStable_NoContext, TyDecodable, TyEncodable};
#[cfg(feature = "nightly")]
@@ -25,15 +26,12 @@ use crate::{self as ty, Interner};
/// e.g., `liberate_late_bound_regions`).
///
/// `Decodable` and `Encodable` are implemented for `Binder` using the `impl_binder_encode_decode!` macro.
-#[derive(derivative::Derivative)]
-#[derivative(
- Clone(bound = "T: Clone"),
- Copy(bound = "T: Copy"),
- Hash(bound = "T: Hash"),
- PartialEq(bound = "T: PartialEq"),
- Eq(bound = "T: Eq"),
- Debug(bound = "T: Debug")
-)]
+#[derive_where(Clone; I: Interner, T: Clone)]
+#[derive_where(Copy; I: Interner, T: Copy)]
+#[derive_where(Hash; I: Interner, T: Hash)]
+#[derive_where(PartialEq; I: Interner, T: PartialEq)]
+#[derive_where(Eq; I: Interner, T: Eq)]
+#[derive_where(Debug; I: Interner, T: Debug)]
#[cfg_attr(feature = "nightly", derive(HashStable_NoContext))]
pub struct Binder {
value: T,
@@ -351,21 +349,18 @@ impl TypeVisitor for ValidateBoundVars {
///
/// If you don't have anything to `instantiate`, you may be looking for
/// [`instantiate_identity`](EarlyBinder::instantiate_identity) or [`skip_binder`](EarlyBinder::skip_binder).
-#[derive(derivative::Derivative)]
-#[derivative(
- Clone(bound = "T: Clone"),
- Copy(bound = "T: Copy"),
- PartialEq(bound = "T: PartialEq"),
- Eq(bound = "T: Eq"),
- Ord(bound = "T: Ord"),
- PartialOrd(bound = "T: Ord"),
- Hash(bound = "T: Hash"),
- Debug(bound = "T: Debug")
-)]
+#[derive_where(Clone; I: Interner, T: Clone)]
+#[derive_where(Copy; I: Interner, T: Copy)]
+#[derive_where(PartialEq; I: Interner, T: PartialEq)]
+#[derive_where(Eq; I: Interner, T: Eq)]
+#[derive_where(Ord; I: Interner, T: Ord)]
+#[derive_where(PartialOrd; I: Interner, T: Ord)]
+#[derive_where(Hash; I: Interner, T: Hash)]
+#[derive_where(Debug; I: Interner, T: Debug)]
#[cfg_attr(feature = "nightly", derive(TyEncodable, TyDecodable, HashStable_NoContext))]
pub struct EarlyBinder {
value: T,
- #[derivative(Debug = "ignore")]
+ #[derive_where(skip(Debug))]
_tcx: PhantomData,
}
diff --git a/compiler/rustc_type_ir/src/canonical.rs b/compiler/rustc_type_ir/src/canonical.rs
index a9252711b2b6..7e93dc248cc1 100644
--- a/compiler/rustc_type_ir/src/canonical.rs
+++ b/compiler/rustc_type_ir/src/canonical.rs
@@ -1,3 +1,6 @@
+#![allow(clippy::derived_hash_with_manual_eq)]
+
+use derive_where::derive_where;
#[cfg(feature = "nightly")]
use rustc_macros::{HashStable_NoContext, TyDecodable, TyEncodable};
use rustc_type_ir_macros::{Lift_Generic, TypeFoldable_Generic, TypeVisitable_Generic};
@@ -11,15 +14,12 @@ use crate::{self as ty, Interner, UniverseIndex};
/// A "canonicalized" type `V` is one where all free inference
/// variables have been rewritten to "canonical vars". These are
/// numbered starting from 0 in order of first appearance.
-#[derive(derivative::Derivative)]
-#[derivative(
- Clone(bound = "V: Clone"),
- Hash(bound = "V: Hash"),
- PartialEq(bound = "V: PartialEq"),
- Eq(bound = "V: Eq"),
- Debug(bound = "V: fmt::Debug"),
- Copy(bound = "V: Copy")
-)]
+#[derive_where(Clone; I: Interner, V: Clone)]
+#[derive_where(Hash; I: Interner, V: Hash)]
+#[derive_where(PartialEq; I: Interner, V: PartialEq)]
+#[derive_where(Eq; I: Interner, V: Eq)]
+#[derive_where(Debug; I: Interner, V: fmt::Debug)]
+#[derive_where(Copy; I: Interner, V: Copy)]
#[derive(TypeVisitable_Generic, TypeFoldable_Generic)]
#[cfg_attr(feature = "nightly", derive(TyEncodable, TyDecodable, HashStable_NoContext))]
pub struct Canonical {
@@ -84,15 +84,7 @@ impl fmt::Display for Canonical {
/// canonical value. This is sufficient information for code to create
/// a copy of the canonical value in some other inference context,
/// with fresh inference variables replacing the canonical values.
-#[derive(derivative::Derivative)]
-#[derivative(
- Clone(bound = ""),
- Copy(bound = ""),
- Hash(bound = ""),
- Debug(bound = ""),
- Eq(bound = ""),
- PartialEq(bound = "")
-)]
+#[derive_where(Clone, Copy, Hash, PartialEq, Eq, Debug; I: Interner)]
#[derive(TypeVisitable_Generic, TypeFoldable_Generic)]
#[cfg_attr(feature = "nightly", derive(TyDecodable, TyEncodable, HashStable_NoContext))]
pub struct CanonicalVarInfo {
@@ -149,8 +141,7 @@ impl CanonicalVarInfo {
/// Describes the "kind" of the canonical variable. This is a "kind"
/// in the type-theory sense of the term -- i.e., a "meta" type system
/// that analyzes type-like values.
-#[derive(derivative::Derivative)]
-#[derivative(Clone(bound = ""), Copy(bound = ""), Hash(bound = ""), Debug(bound = ""))]
+#[derive_where(Clone, Copy, Hash, Eq, Debug; I: Interner)]
#[derive(TypeVisitable_Generic, TypeFoldable_Generic)]
#[cfg_attr(feature = "nightly", derive(TyDecodable, TyEncodable, HashStable_NoContext))]
pub enum CanonicalVarKind {
@@ -178,6 +169,7 @@ pub enum CanonicalVarKind {
PlaceholderConst(I::PlaceholderConst),
}
+// FIXME(GrigorenkoPV): consider not implementing PartialEq manually
impl PartialEq for CanonicalVarKind {
fn eq(&self, other: &Self) -> bool {
match (self, other) {
@@ -266,15 +258,7 @@ pub enum CanonicalTyVarKind {
/// vectors with the original values that were replaced by canonical
/// variables. You will need to supply it later to instantiate the
/// canonicalized query response.
-#[derive(derivative::Derivative)]
-#[derivative(
- Clone(bound = ""),
- Copy(bound = ""),
- PartialEq(bound = ""),
- Eq(bound = ""),
- Hash(bound = ""),
- Debug(bound = "")
-)]
+#[derive_where(Clone, Copy, Hash, PartialEq, Eq, Debug; I: Interner)]
#[cfg_attr(feature = "nightly", derive(TyEncodable, TyDecodable, HashStable_NoContext))]
#[derive(TypeVisitable_Generic, TypeFoldable_Generic, Lift_Generic)]
pub struct CanonicalVarValues {
diff --git a/compiler/rustc_type_ir/src/const_kind.rs b/compiler/rustc_type_ir/src/const_kind.rs
index 1a51c95ecdff..458ffdabe94e 100644
--- a/compiler/rustc_type_ir/src/const_kind.rs
+++ b/compiler/rustc_type_ir/src/const_kind.rs
@@ -1,3 +1,6 @@
+#![allow(clippy::derived_hash_with_manual_eq)]
+
+use derive_where::derive_where;
#[cfg(feature = "nightly")]
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
#[cfg(feature = "nightly")]
@@ -10,8 +13,7 @@ use crate::{self as ty, DebruijnIndex, Interner};
use self::ConstKind::*;
/// Represents a constant in Rust.
-#[derive(derivative::Derivative)]
-#[derivative(Clone(bound = ""), Copy(bound = ""), Hash(bound = ""), Eq(bound = ""))]
+#[derive_where(Clone, Copy, Hash, Eq; I: Interner)]
#[cfg_attr(feature = "nightly", derive(TyEncodable, TyDecodable, HashStable_NoContext))]
pub enum ConstKind {
/// A const generic parameter.
@@ -43,6 +45,7 @@ pub enum ConstKind {
Expr(I::ExprConst),
}
+// FIXME(GrigorenkoPV): consider not implementing PartialEq manually
impl PartialEq for ConstKind {
fn eq(&self, other: &Self) -> bool {
match (self, other) {
@@ -77,14 +80,7 @@ impl fmt::Debug for ConstKind {
}
/// An unevaluated (potentially generic) constant used in the type-system.
-#[derive(derivative::Derivative)]
-#[derivative(
- Clone(bound = ""),
- Copy(bound = ""),
- Hash(bound = ""),
- PartialEq(bound = ""),
- Eq(bound = "")
-)]
+#[derive_where(Clone, Copy, Hash, PartialEq, Eq; I: Interner)]
#[derive(TypeVisitable_Generic, TypeFoldable_Generic, Lift_Generic)]
#[cfg_attr(feature = "nightly", derive(TyDecodable, TyEncodable, HashStable_NoContext))]
pub struct UnevaluatedConst {
diff --git a/compiler/rustc_type_ir/src/error.rs b/compiler/rustc_type_ir/src/error.rs
index 8b59e9a6f481..8a6d37b7d23f 100644
--- a/compiler/rustc_type_ir/src/error.rs
+++ b/compiler/rustc_type_ir/src/error.rs
@@ -1,3 +1,4 @@
+use derive_where::derive_where;
use rustc_type_ir_macros::{TypeFoldable_Generic, TypeVisitable_Generic};
use crate::solve::NoSolution;
@@ -21,14 +22,7 @@ impl ExpectedFound {
}
// Data structures used in type unification
-#[derive(derivative::Derivative)]
-#[derivative(
- Clone(bound = ""),
- Copy(bound = ""),
- PartialEq(bound = ""),
- Eq(bound = ""),
- Debug(bound = "")
-)]
+#[derive_where(Clone, Copy, PartialEq, Eq, Debug; I: Interner)]
#[derive(TypeVisitable_Generic)]
#[cfg_attr(feature = "nightly", rustc_pass_by_value)]
pub enum TypeError {
diff --git a/compiler/rustc_type_ir/src/generic_arg.rs b/compiler/rustc_type_ir/src/generic_arg.rs
index b158f0f5eee9..008268c3bffa 100644
--- a/compiler/rustc_type_ir/src/generic_arg.rs
+++ b/compiler/rustc_type_ir/src/generic_arg.rs
@@ -1,16 +1,10 @@
+use derive_where::derive_where;
#[cfg(feature = "nightly")]
use rustc_macros::{HashStable_NoContext, TyDecodable, TyEncodable};
use crate::Interner;
-#[derive(derivative::Derivative)]
-#[derivative(
- Clone(bound = ""),
- Copy(bound = ""),
- Debug(bound = ""),
- Eq(bound = ""),
- PartialEq(bound = "")
-)]
+#[derive_where(Clone, Copy, PartialEq, Eq, Debug; I: Interner)]
#[cfg_attr(feature = "nightly", derive(TyDecodable, TyEncodable, HashStable_NoContext))]
pub enum GenericArgKind {
Lifetime(I::Region),
@@ -18,14 +12,7 @@ pub enum GenericArgKind {
Const(I::Const),
}
-#[derive(derivative::Derivative)]
-#[derivative(
- Clone(bound = ""),
- Copy(bound = ""),
- Debug(bound = ""),
- Eq(bound = ""),
- PartialEq(bound = "")
-)]
+#[derive_where(Clone, Copy, PartialEq, Eq, Debug; I: Interner)]
#[cfg_attr(feature = "nightly", derive(TyDecodable, TyEncodable, HashStable_NoContext))]
pub enum TermKind {
Ty(I::Ty),
diff --git a/compiler/rustc_type_ir/src/opaque_ty.rs b/compiler/rustc_type_ir/src/opaque_ty.rs
index e5d18fcb3d1e..6d61a52723ae 100644
--- a/compiler/rustc_type_ir/src/opaque_ty.rs
+++ b/compiler/rustc_type_ir/src/opaque_ty.rs
@@ -1,3 +1,4 @@
+use derive_where::derive_where;
#[cfg(feature = "nightly")]
use rustc_macros::{HashStable_NoContext, TyDecodable, TyEncodable};
use rustc_type_ir_macros::{TypeFoldable_Generic, TypeVisitable_Generic};
@@ -5,15 +6,7 @@ use rustc_type_ir_macros::{TypeFoldable_Generic, TypeVisitable_Generic};
use crate::inherent::*;
use crate::{self as ty, Interner};
-#[derive(derivative::Derivative)]
-#[derivative(
- Clone(bound = ""),
- Hash(bound = ""),
- PartialEq(bound = ""),
- Eq(bound = ""),
- Debug(bound = ""),
- Copy(bound = "")
-)]
+#[derive_where(Clone, Copy, Hash, PartialEq, Eq, Debug; I: Interner)]
#[derive(TypeVisitable_Generic, TypeFoldable_Generic)]
#[cfg_attr(feature = "nightly", derive(TyEncodable, TyDecodable, HashStable_NoContext))]
pub struct OpaqueTypeKey {
diff --git a/compiler/rustc_type_ir/src/outlives.rs b/compiler/rustc_type_ir/src/outlives.rs
index eb84f3dd5873..2f26a4391838 100644
--- a/compiler/rustc_type_ir/src/outlives.rs
+++ b/compiler/rustc_type_ir/src/outlives.rs
@@ -2,6 +2,7 @@
//! refers to rules defined in RFC 1214 (`OutlivesFooBar`), so see that
//! RFC for reference.
+use derive_where::derive_where;
use smallvec::{smallvec, SmallVec};
use crate::data_structures::SsoHashSet;
@@ -9,8 +10,7 @@ use crate::inherent::*;
use crate::visit::{TypeSuperVisitable, TypeVisitable, TypeVisitableExt as _, TypeVisitor};
use crate::{self as ty, Interner};
-#[derive(derivative::Derivative)]
-#[derivative(Debug(bound = ""))]
+#[derive_where(Debug; I: Interner)]
pub enum Component {
Region(I::Region),
Param(I::ParamTy),
diff --git a/compiler/rustc_type_ir/src/predicate.rs b/compiler/rustc_type_ir/src/predicate.rs
index e03f521c5b10..b30346ffc53d 100644
--- a/compiler/rustc_type_ir/src/predicate.rs
+++ b/compiler/rustc_type_ir/src/predicate.rs
@@ -1,6 +1,7 @@
use std::fmt;
use std::hash::Hash;
+use derive_where::derive_where;
#[cfg(feature = "nightly")]
use rustc_macros::{Decodable, Encodable, HashStable_NoContext, TyDecodable, TyEncodable};
use rustc_type_ir_macros::{Lift_Generic, TypeFoldable_Generic, TypeVisitable_Generic};
@@ -12,15 +13,12 @@ use crate::visit::TypeVisitableExt as _;
use crate::{self as ty, Interner};
/// `A: 'region`
-#[derive(derivative::Derivative)]
-#[derivative(
- Clone(bound = "A: Clone"),
- Copy(bound = "A: Copy"),
- Hash(bound = "A: Hash"),
- PartialEq(bound = "A: PartialEq"),
- Eq(bound = "A: Eq"),
- Debug(bound = "A: fmt::Debug")
-)]
+#[derive_where(Clone; I: Interner, A: Clone)]
+#[derive_where(Copy; I: Interner, A: Copy)]
+#[derive_where(Hash; I: Interner, A: Hash)]
+#[derive_where(PartialEq; I: Interner, A: PartialEq)]
+#[derive_where(Eq; I: Interner, A: Eq)]
+#[derive_where(Debug; I: Interner, A: fmt::Debug)]
#[derive(TypeVisitable_Generic, TypeFoldable_Generic)]
#[cfg_attr(feature = "nightly", derive(TyDecodable, TyEncodable, HashStable_NoContext))]
pub struct OutlivesPredicate(pub A, pub I::Region);
@@ -50,14 +48,7 @@ where
///
/// Trait references also appear in object types like `Foo`, but in
/// that case the `Self` parameter is absent from the generic parameters.
-#[derive(derivative::Derivative)]
-#[derivative(
- Clone(bound = ""),
- Copy(bound = ""),
- Hash(bound = ""),
- PartialEq(bound = ""),
- Eq(bound = "")
-)]
+#[derive_where(Clone, Copy, Hash, PartialEq, Eq; I: Interner)]
#[derive(TypeVisitable_Generic, TypeFoldable_Generic, Lift_Generic)]
#[cfg_attr(feature = "nightly", derive(TyDecodable, TyEncodable, HashStable_NoContext))]
pub struct TraitRef {
@@ -122,14 +113,7 @@ impl ty::Binder> {
}
}
-#[derive(derivative::Derivative)]
-#[derivative(
- Clone(bound = ""),
- Copy(bound = ""),
- Hash(bound = ""),
- PartialEq(bound = ""),
- Eq(bound = "")
-)]
+#[derive_where(Clone, Copy, Hash, PartialEq, Eq; I: Interner)]
#[derive(TypeVisitable_Generic, TypeFoldable_Generic, Lift_Generic)]
#[cfg_attr(feature = "nightly", derive(TyDecodable, TyEncodable, HashStable_NoContext))]
pub struct TraitPredicate {
@@ -243,15 +227,7 @@ impl fmt::Display for PredicatePolarity {
}
}
-#[derive(derivative::Derivative)]
-#[derivative(
- Clone(bound = ""),
- Copy(bound = ""),
- Hash(bound = ""),
- PartialEq(bound = ""),
- Eq(bound = ""),
- Debug(bound = "")
-)]
+#[derive_where(Clone, Copy, Hash, PartialEq, Eq, Debug; I: Interner)]
#[derive(TypeVisitable_Generic, TypeFoldable_Generic, Lift_Generic)]
#[cfg_attr(feature = "nightly", derive(TyDecodable, TyEncodable, HashStable_NoContext))]
pub enum ExistentialPredicate {
@@ -296,14 +272,7 @@ impl ty::Binder> {
/// ```
/// The generic parameters don't include the erased `Self`, only trait
/// type and lifetime parameters (`[X, Y]` and `['a, 'b]` above).
-#[derive(derivative::Derivative)]
-#[derivative(
- Clone(bound = ""),
- Copy(bound = ""),
- Hash(bound = ""),
- PartialEq(bound = ""),
- Eq(bound = "")
-)]
+#[derive_where(Clone, Copy, Hash, PartialEq, Eq; I: Interner)]
#[derive(TypeVisitable_Generic, TypeFoldable_Generic, Lift_Generic)]
#[cfg_attr(feature = "nightly", derive(TyDecodable, TyEncodable, HashStable_NoContext))]
pub struct ExistentialTraitRef {
@@ -349,14 +318,7 @@ impl ty::Binder> {
}
/// A `ProjectionPredicate` for an `ExistentialTraitRef`.
-#[derive(derivative::Derivative)]
-#[derivative(
- Clone(bound = ""),
- Copy(bound = ""),
- Hash(bound = ""),
- PartialEq(bound = ""),
- Eq(bound = "")
-)]
+#[derive_where(Clone, Copy, Hash, PartialEq, Eq; I: Interner)]
#[derive(TypeVisitable_Generic, TypeFoldable_Generic, Lift_Generic)]
#[cfg_attr(feature = "nightly", derive(TyDecodable, TyEncodable, HashStable_NoContext))]
pub struct ExistentialProjection {
@@ -452,15 +414,7 @@ impl AliasTermKind {
/// * For a projection, this would be `>::N<...>`.
/// * For an inherent projection, this would be `Ty::N<...>`.
/// * For an opaque type, there is no explicit syntax.
-#[derive(derivative::Derivative)]
-#[derivative(
- Clone(bound = ""),
- Copy(bound = ""),
- Hash(bound = ""),
- PartialEq(bound = ""),
- Eq(bound = ""),
- Debug(bound = "")
-)]
+#[derive_where(Clone, Copy, Hash, PartialEq, Eq, Debug; I: Interner)]
#[derive(TypeVisitable_Generic, TypeFoldable_Generic, Lift_Generic)]
#[cfg_attr(feature = "nightly", derive(TyDecodable, TyEncodable, HashStable_NoContext))]
pub struct AliasTerm {
@@ -489,7 +443,7 @@ pub struct AliasTerm {
pub def_id: I::DefId,
/// This field exists to prevent the creation of `AliasTerm` without using [`AliasTerm::new_from_args`].
- #[derivative(Debug = "ignore")]
+ #[derive_where(skip(Debug))]
_use_alias_term_new_instead: (),
}
@@ -631,14 +585,7 @@ impl From> for AliasTerm {
/// equality between arbitrary types. Processing an instance of
/// Form #2 eventually yields one of these `ProjectionPredicate`
/// instances to normalize the LHS.
-#[derive(derivative::Derivative)]
-#[derivative(
- Clone(bound = ""),
- Copy(bound = ""),
- Hash(bound = ""),
- PartialEq(bound = ""),
- Eq(bound = "")
-)]
+#[derive_where(Clone, Copy, Hash, PartialEq, Eq; I: Interner)]
#[derive(TypeVisitable_Generic, TypeFoldable_Generic, Lift_Generic)]
#[cfg_attr(feature = "nightly", derive(TyDecodable, TyEncodable, HashStable_NoContext))]
pub struct ProjectionPredicate {
@@ -706,14 +653,7 @@ impl fmt::Debug for ProjectionPredicate {
/// Used by the new solver. Unlike a `ProjectionPredicate` this can only be
/// proven by actually normalizing `alias`.
-#[derive(derivative::Derivative)]
-#[derivative(
- Clone(bound = ""),
- Copy(bound = ""),
- Hash(bound = ""),
- PartialEq(bound = ""),
- Eq(bound = "")
-)]
+#[derive_where(Clone, Copy, Hash, PartialEq, Eq; I: Interner)]
#[derive(TypeVisitable_Generic, TypeFoldable_Generic, Lift_Generic)]
#[cfg_attr(feature = "nightly", derive(TyDecodable, TyEncodable, HashStable_NoContext))]
pub struct NormalizesTo {
@@ -748,15 +688,7 @@ impl fmt::Debug for NormalizesTo {
/// Encodes that `a` must be a subtype of `b`. The `a_is_expected` flag indicates
/// whether the `a` type is the type that we should label as "expected" when
/// presenting user diagnostics.
-#[derive(derivative::Derivative)]
-#[derivative(
- Clone(bound = ""),
- Copy(bound = ""),
- Hash(bound = ""),
- PartialEq(bound = ""),
- Eq(bound = ""),
- Debug(bound = "")
-)]
+#[derive_where(Clone, Copy, Hash, PartialEq, Eq, Debug; I: Interner)]
#[derive(TypeVisitable_Generic, TypeFoldable_Generic, Lift_Generic)]
#[cfg_attr(feature = "nightly", derive(TyDecodable, TyEncodable, HashStable_NoContext))]
pub struct SubtypePredicate {
@@ -766,15 +698,7 @@ pub struct SubtypePredicate {
}
/// Encodes that we have to coerce *from* the `a` type to the `b` type.
-#[derive(derivative::Derivative)]
-#[derivative(
- Clone(bound = ""),
- Copy(bound = ""),
- Hash(bound = ""),
- PartialEq(bound = ""),
- Eq(bound = ""),
- Debug(bound = "")
-)]
+#[derive_where(Clone, Copy, Hash, PartialEq, Eq, Debug; I: Interner)]
#[derive(TypeVisitable_Generic, TypeFoldable_Generic, Lift_Generic)]
#[cfg_attr(feature = "nightly", derive(TyDecodable, TyEncodable, HashStable_NoContext))]
pub struct CoercePredicate {
diff --git a/compiler/rustc_type_ir/src/predicate_kind.rs b/compiler/rustc_type_ir/src/predicate_kind.rs
index b1d0f8d19b39..70b7c29bdfcc 100644
--- a/compiler/rustc_type_ir/src/predicate_kind.rs
+++ b/compiler/rustc_type_ir/src/predicate_kind.rs
@@ -1,3 +1,6 @@
+#![allow(clippy::derived_hash_with_manual_eq)]
+
+use derive_where::derive_where;
#[cfg(feature = "nightly")]
use rustc_macros::{Decodable, Encodable, HashStable_NoContext, TyDecodable, TyEncodable};
use rustc_type_ir_macros::{TypeFoldable_Generic, TypeVisitable_Generic};
@@ -7,8 +10,7 @@ use crate::{self as ty, Interner};
/// A clause is something that can appear in where bounds or be inferred
/// by implied bounds.
-#[derive(derivative::Derivative)]
-#[derivative(Clone(bound = ""), Copy(bound = ""), Hash(bound = ""), Eq(bound = ""))]
+#[derive_where(Clone, Copy, Hash, Eq; I: Interner)]
#[derive(TypeVisitable_Generic, TypeFoldable_Generic)]
#[cfg_attr(feature = "nightly", derive(TyEncodable, TyDecodable, HashStable_NoContext))]
pub enum ClauseKind {
@@ -38,6 +40,7 @@ pub enum ClauseKind {
ConstEvaluatable(I::Const),
}
+// FIXME(GrigorenkoPV): consider not implementing PartialEq manually
impl PartialEq for ClauseKind {
fn eq(&self, other: &Self) -> bool {
match (self, other) {
@@ -53,14 +56,7 @@ impl PartialEq for ClauseKind {
}
}
-#[derive(derivative::Derivative)]
-#[derivative(
- Clone(bound = ""),
- Copy(bound = ""),
- Hash(bound = ""),
- PartialEq(bound = ""),
- Eq(bound = "")
-)]
+#[derive_where(Clone, Copy, Hash, PartialEq, Eq; I: Interner)]
#[derive(TypeVisitable_Generic, TypeFoldable_Generic)]
#[cfg_attr(feature = "nightly", derive(TyEncodable, TyDecodable, HashStable_NoContext))]
pub enum PredicateKind {
diff --git a/compiler/rustc_type_ir/src/region_kind.rs b/compiler/rustc_type_ir/src/region_kind.rs
index 140c89af147d..ef18ef152355 100644
--- a/compiler/rustc_type_ir/src/region_kind.rs
+++ b/compiler/rustc_type_ir/src/region_kind.rs
@@ -1,3 +1,6 @@
+#![allow(clippy::derived_hash_with_manual_eq)]
+
+use derive_where::derive_where;
#[cfg(feature = "nightly")]
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
#[cfg(feature = "nightly")]
@@ -124,8 +127,7 @@ rustc_index::newtype_index! {
/// [1]: https://smallcultfollowing.com/babysteps/blog/2013/10/29/intermingled-parameter-lists/
/// [2]: https://smallcultfollowing.com/babysteps/blog/2013/11/04/intermingled-parameter-lists/
/// [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/traits/hrtb.html
-#[derive(derivative::Derivative)]
-#[derivative(Clone(bound = ""), Copy(bound = ""), Hash(bound = ""), Eq(bound = ""))]
+#[derive_where(Clone, Copy, Hash, Eq; I: Interner)]
#[cfg_attr(feature = "nightly", derive(TyEncodable, TyDecodable))]
pub enum RegionKind {
/// A region parameter; for example `'a` in `impl<'a> Trait for &'a ()`.
@@ -193,6 +195,7 @@ const fn regionkind_discriminant(value: &RegionKind) -> usize {
}
}
+// FIXME(GrigorenkoPV): consider not implementing PartialEq manually
// This is manually implemented because a derive would require `I: PartialEq`
impl PartialEq for RegionKind {
#[inline]
diff --git a/compiler/rustc_type_ir/src/relate.rs b/compiler/rustc_type_ir/src/relate.rs
index ae840ec02103..9fd3534d1fa6 100644
--- a/compiler/rustc_type_ir/src/relate.rs
+++ b/compiler/rustc_type_ir/src/relate.rs
@@ -1,5 +1,6 @@
use std::iter;
+use derive_where::derive_where;
use rustc_ast_ir::Mutability;
use tracing::{instrument, trace};
@@ -17,19 +18,11 @@ pub type RelateResult = Result>;
/// a miscompilation or unsoundness.
///
/// When in doubt, use `VarianceDiagInfo::default()`
-#[derive(derivative::Derivative)]
-#[derivative(
- Copy(bound = ""),
- Clone(bound = ""),
- Debug(bound = ""),
- Default(bound = ""),
- PartialEq(bound = ""),
- Eq(bound = "")
-)]
+#[derive_where(Clone, Copy, PartialEq, Eq, Debug, Default; I: Interner)]
pub enum VarianceDiagInfo {
/// No additional information - this is the default.
/// We will not add any additional information to error messages.
- #[derivative(Default)]
+ #[derive_where(default)]
None,
/// We switched our variance because a generic argument occurs inside
/// the invariant generic argument of another type.
diff --git a/compiler/rustc_type_ir/src/search_graph/global_cache.rs b/compiler/rustc_type_ir/src/search_graph/global_cache.rs
index 5ccda931f9c5..be4f1069cd16 100644
--- a/compiler/rustc_type_ir/src/search_graph/global_cache.rs
+++ b/compiler/rustc_type_ir/src/search_graph/global_cache.rs
@@ -1,10 +1,10 @@
+use derive_where::derive_where;
use rustc_index::IndexVec;
use super::{AvailableDepth, Cx, StackDepth, StackEntry};
use crate::data_structures::{HashMap, HashSet};
-#[derive(derivative::Derivative)]
-#[derivative(Debug(bound = ""), Clone(bound = ""), Copy(bound = ""))]
+#[derive_where(Debug, Clone, Copy; X: Cx)]
struct QueryData {
result: X::Result,
proof_tree: X::ProofTree,
@@ -20,8 +20,7 @@ struct Success {
/// This contains results whose computation never hit the
/// recursion limit in `success`, and all results which hit
/// the recursion limit in `with_overflow`.
-#[derive(derivative::Derivative)]
-#[derivative(Default(bound = ""))]
+#[derive_where(Default; X: Cx)]
struct CacheEntry {
success: Option>,
/// We have to be careful when caching roots of cycles.
@@ -32,8 +31,7 @@ struct CacheEntry {
with_overflow: HashMap>>,
}
-#[derive(derivative::Derivative)]
-#[derivative(Debug(bound = ""))]
+#[derive_where(Debug; X: Cx)]
pub(super) struct CacheData<'a, X: Cx> {
pub(super) result: X::Result,
pub(super) proof_tree: X::ProofTree,
@@ -41,11 +39,10 @@ pub(super) struct CacheData<'a, X: Cx> {
pub(super) encountered_overflow: bool,
// FIXME: This is currently unused, but impacts the design
// by requiring a closure for `Cx::with_global_cache`.
+ #[allow(dead_code)]
pub(super) nested_goals: &'a HashSet,
}
-
-#[derive(derivative::Derivative)]
-#[derivative(Default(bound = ""))]
+#[derive_where(Default; X: Cx)]
pub struct GlobalCache {
map: HashMap>,
}
diff --git a/compiler/rustc_type_ir/src/search_graph/mod.rs b/compiler/rustc_type_ir/src/search_graph/mod.rs
index c2204becdfd7..4abf99b1ded8 100644
--- a/compiler/rustc_type_ir/src/search_graph/mod.rs
+++ b/compiler/rustc_type_ir/src/search_graph/mod.rs
@@ -3,6 +3,7 @@ use std::hash::Hash;
use std::marker::PhantomData;
use std::mem;
+use derive_where::derive_where;
use rustc_index::{Idx, IndexVec};
use tracing::debug;
@@ -153,8 +154,7 @@ rustc_index::newtype_index! {
pub struct StackDepth {}
}
-#[derive(derivative::Derivative)]
-#[derivative(Debug(bound = ""))]
+#[derive_where(Debug; X: Cx)]
struct StackEntry {
input: X::Input,
@@ -226,8 +226,7 @@ struct DetachedEntry {
///
/// The provisional cache can theoretically result in changes to the observable behavior,
/// see tests/ui/traits/next-solver/cycles/provisional-cache-impacts-behavior.rs.
-#[derive(derivative::Derivative)]
-#[derivative(Default(bound = ""))]
+#[derive_where(Default; X: Cx)]
struct ProvisionalCacheEntry {
stack_depth: Option,
with_inductive_stack: Option>,
diff --git a/compiler/rustc_type_ir/src/solve/inspect.rs b/compiler/rustc_type_ir/src/solve/inspect.rs
index 0733c730064b..e25df7a0f604 100644
--- a/compiler/rustc_type_ir/src/solve/inspect.rs
+++ b/compiler/rustc_type_ir/src/solve/inspect.rs
@@ -21,6 +21,7 @@ use crate::solve::{
CandidateSource, CanonicalInput, Certainty, Goal, GoalSource, QueryInput, QueryResult,
};
use crate::{Canonical, CanonicalVarValues, Interner};
+use derive_where::derive_where;
use rustc_type_ir_macros::{TypeFoldable_Generic, TypeVisitable_Generic};
use std::fmt::Debug;
use std::hash::Hash;
@@ -31,15 +32,12 @@ use std::hash::Hash;
/// This is only ever used as [CanonicalState]. Any type information in proof
/// trees used mechanically has to be canonicalized as we otherwise leak
/// inference variables from a nested `InferCtxt`.
-#[derive(derivative::Derivative)]
-#[derivative(
- Clone(bound = "T: Clone"),
- Copy(bound = "T: Copy"),
- PartialEq(bound = "T: PartialEq"),
- Eq(bound = "T: Eq"),
- Hash(bound = "T: Hash"),
- Debug(bound = "T: Debug")
-)]
+#[derive_where(Clone; I: Interner, T: Clone)]
+#[derive_where(Copy; I: Interner, T: Copy)]
+#[derive_where(PartialEq; I: Interner, T: PartialEq)]
+#[derive_where(Eq; I: Interner, T: Eq)]
+#[derive_where(Hash; I: Interner, T: Hash)]
+#[derive_where(Debug; I: Interner, T: Debug)]
#[derive(TypeVisitable_Generic, TypeFoldable_Generic)]
pub struct State {
pub var_values: CanonicalVarValues,
@@ -52,24 +50,21 @@ pub type CanonicalState = Canonical>;
/// for the `CanonicalVarValues` of the canonicalized goal.
/// We use this to map any [CanonicalState] from the local `InferCtxt`
/// of the solver query to the `InferCtxt` of the caller.
-#[derive(derivative::Derivative)]
-#[derivative(PartialEq(bound = ""), Eq(bound = ""), Hash(bound = ""))]
+#[derive_where(PartialEq, Eq, Hash; I: Interner)]
pub struct GoalEvaluation {
pub uncanonicalized_goal: Goal,
pub orig_values: Vec,
pub evaluation: CanonicalGoalEvaluation,
}
-#[derive(derivative::Derivative)]
-#[derivative(PartialEq(bound = ""), Eq(bound = ""), Hash(bound = ""), Debug(bound = ""))]
+#[derive_where(PartialEq, Eq, Hash, Debug; I: Interner)]
pub struct CanonicalGoalEvaluation {
pub goal: CanonicalInput,
pub kind: CanonicalGoalEvaluationKind,
pub result: QueryResult,
}
-#[derive(derivative::Derivative)]
-#[derivative(PartialEq(bound = ""), Eq(bound = ""), Hash(bound = ""), Debug(bound = ""))]
+#[derive_where(PartialEq, Eq, Hash, Debug; I: Interner)]
pub enum CanonicalGoalEvaluationKind {
Overflow,
CycleInStack,
@@ -77,8 +72,7 @@ pub enum CanonicalGoalEvaluationKind {
Evaluation { final_revision: I::CanonicalGoalEvaluationStepRef },
}
-#[derive(derivative::Derivative)]
-#[derivative(PartialEq(bound = ""), Eq(bound = ""), Hash(bound = ""), Debug(bound = ""))]
+#[derive_where(PartialEq, Eq, Hash, Debug; I: Interner)]
pub struct CanonicalGoalEvaluationStep {
pub instantiated_goal: QueryInput,
@@ -89,8 +83,7 @@ pub struct CanonicalGoalEvaluationStep {
/// A self-contained computation during trait solving. This either
/// corresponds to a `EvalCtxt::probe(_X)` call or the root evaluation
/// of a goal.
-#[derive(derivative::Derivative)]
-#[derivative(Debug(bound = ""), PartialEq(bound = ""), Eq(bound = ""), Hash(bound = ""))]
+#[derive_where(PartialEq, Eq, Hash, Debug; I: Interner)]
pub struct Probe {
/// What happened inside of this probe in chronological order.
pub steps: Vec>,
@@ -98,8 +91,7 @@ pub struct Probe {
pub final_state: CanonicalState,
}
-#[derive(derivative::Derivative)]
-#[derivative(PartialEq(bound = ""), Eq(bound = ""), Hash(bound = ""), Debug(bound = ""))]
+#[derive_where(PartialEq, Eq, Hash, Debug; I: Interner)]
pub enum ProbeStep {
/// We added a goal to the `EvalCtxt` which will get proven
/// the next time `EvalCtxt::try_evaluate_added_goals` is called.
@@ -121,15 +113,7 @@ pub enum ProbeStep {
/// What kind of probe we're in. In case the probe represents a candidate, or
/// the final result of the current goal - via [ProbeKind::Root] - we also
/// store the [QueryResult].
-#[derive(derivative::Derivative)]
-#[derivative(
- Clone(bound = ""),
- Copy(bound = ""),
- PartialEq(bound = ""),
- Eq(bound = ""),
- Hash(bound = ""),
- Debug(bound = "")
-)]
+#[derive_where(Clone, Copy, PartialEq, Eq, Hash, Debug; I: Interner)]
#[derive(TypeVisitable_Generic, TypeFoldable_Generic)]
pub enum ProbeKind {
/// The root inference context while proving a goal.
diff --git a/compiler/rustc_type_ir/src/solve/mod.rs b/compiler/rustc_type_ir/src/solve/mod.rs
index 2449ac47db6f..444fd01f0128 100644
--- a/compiler/rustc_type_ir/src/solve/mod.rs
+++ b/compiler/rustc_type_ir/src/solve/mod.rs
@@ -3,6 +3,7 @@ pub mod inspect;
use std::fmt;
use std::hash::Hash;
+use derive_where::derive_where;
#[cfg(feature = "nightly")]
use rustc_macros::{HashStable_NoContext, TyDecodable, TyEncodable};
use rustc_type_ir_macros::{Lift_Generic, TypeFoldable_Generic, TypeVisitable_Generic};
@@ -89,15 +90,12 @@ pub struct NoSolution;
///
/// Most of the time the `param_env` contains the `where`-bounds of the function
/// we're currently typechecking while the `predicate` is some trait bound.
-#[derive(derivative::Derivative)]
-#[derivative(
- Clone(bound = "P: Clone"),
- Copy(bound = "P: Copy"),
- Hash(bound = "P: Hash"),
- PartialEq(bound = "P: PartialEq"),
- Eq(bound = "P: Eq"),
- Debug(bound = "P: fmt::Debug")
-)]
+#[derive_where(Clone; I: Interner, P: Clone)]
+#[derive_where(Copy; I: Interner, P: Copy)]
+#[derive_where(Hash; I: Interner, P: Hash)]
+#[derive_where(PartialEq; I: Interner, P: PartialEq)]
+#[derive_where(Eq; I: Interner, P: Eq)]
+#[derive_where(Debug; I: Interner, P: fmt::Debug)]
#[derive(TypeVisitable_Generic, TypeFoldable_Generic, Lift_Generic)]
#[cfg_attr(feature = "nightly", derive(TyDecodable, TyEncodable, HashStable_NoContext))]
pub struct Goal {
@@ -140,15 +138,12 @@ pub enum GoalSource {
InstantiateHigherRanked,
}
-#[derive(derivative::Derivative)]
-#[derivative(
- Clone(bound = "Goal: Clone"),
- Copy(bound = "Goal: Copy"),
- Hash(bound = "Goal: Hash"),
- PartialEq(bound = "Goal: PartialEq"),
- Eq(bound = "Goal: Eq"),
- Debug(bound = "Goal: fmt::Debug")
-)]
+#[derive_where(Clone; I: Interner, Goal: Clone)]
+#[derive_where(Copy; I: Interner, Goal: Copy)]
+#[derive_where(Hash; I: Interner, Goal: Hash)]
+#[derive_where(PartialEq; I: Interner, Goal: PartialEq)]
+#[derive_where(Eq; I: Interner, Goal: Eq)]
+#[derive_where(Debug; I: Interner, Goal: fmt::Debug)]
#[derive(TypeVisitable_Generic, TypeFoldable_Generic)]
#[cfg_attr(feature = "nightly", derive(TyDecodable, TyEncodable, HashStable_NoContext))]
pub struct QueryInput {
@@ -157,15 +152,7 @@ pub struct QueryInput {
}
/// Opaques that are defined in the inference context before a query is called.
-#[derive(derivative::Derivative)]
-#[derivative(
- Clone(bound = ""),
- Hash(bound = ""),
- PartialEq(bound = ""),
- Eq(bound = ""),
- Debug(bound = ""),
- Default(bound = "")
-)]
+#[derive_where(Clone, Hash, PartialEq, Eq, Debug, Default; I: Interner)]
#[derive(TypeVisitable_Generic, TypeFoldable_Generic)]
#[cfg_attr(feature = "nightly", derive(TyDecodable, TyEncodable, HashStable_NoContext))]
pub struct PredefinedOpaquesData {
@@ -173,15 +160,7 @@ pub struct PredefinedOpaquesData {
}
/// Possible ways the given goal can be proven.
-#[derive(derivative::Derivative)]
-#[derivative(
- Clone(bound = ""),
- Copy(bound = ""),
- Hash(bound = ""),
- PartialEq(bound = ""),
- Eq(bound = ""),
- Debug(bound = "")
-)]
+#[derive_where(Clone, Copy, Hash, PartialEq, Eq, Debug; I: Interner)]
pub enum CandidateSource {
/// A user written impl.
///
@@ -265,15 +244,7 @@ pub enum BuiltinImplSource {
TupleUnsizing,
}
-#[derive(derivative::Derivative)]
-#[derivative(
- Clone(bound = ""),
- Copy(bound = ""),
- Hash(bound = ""),
- PartialEq(bound = ""),
- Eq(bound = ""),
- Debug(bound = "")
-)]
+#[derive_where(Clone, Copy, Hash, PartialEq, Eq, Debug; I: Interner)]
#[derive(TypeVisitable_Generic, TypeFoldable_Generic)]
#[cfg_attr(feature = "nightly", derive(HashStable_NoContext))]
pub struct Response {
@@ -284,15 +255,7 @@ pub struct Response