diff --git a/Cargo.lock b/Cargo.lock index 8c2c3f5e628b..72f0236fd08a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -641,9 +641,9 @@ dependencies = [ [[package]] name = "compiler_builtins" -version = "0.1.95" +version = "0.1.98" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6866e0f3638013234db3c89ead7a14d278354338e7237257407500009012b23f" +checksum = "dfbefa16407456e5cad1ad066c84dfcb980afe4437103a0007d1c2f136130210" dependencies = [ "cc", "rustc-std-workspace-core", diff --git a/compiler/rustc_abi/src/layout.rs b/compiler/rustc_abi/src/layout.rs index aea88641f82b..489a8403c3b1 100644 --- a/compiler/rustc_abi/src/layout.rs +++ b/compiler/rustc_abi/src/layout.rs @@ -763,7 +763,9 @@ pub trait LayoutCalculator { let mut size = Size::ZERO; let only_variant = &variants[FIRST_VARIANT]; for field in only_variant { - assert!(field.0.is_sized()); + if field.0.is_unsized() { + self.delay_bug("unsized field in union".to_string()); + } align = align.max(field.align()); max_repr_align = max_repr_align.max(field.max_repr_align()); diff --git a/compiler/rustc_abi/src/lib.rs b/compiler/rustc_abi/src/lib.rs index ef0c763ac203..835143407d2b 100644 --- a/compiler/rustc_abi/src/lib.rs +++ b/compiler/rustc_abi/src/lib.rs @@ -1189,7 +1189,7 @@ impl FieldsShape { } FieldsShape::Array { stride, count } => { let i = u64::try_from(i).unwrap(); - assert!(i < count); + assert!(i < count, "tried to access field {} of array with {} fields", i, count); stride * i } FieldsShape::Arbitrary { ref offsets, .. } => offsets[FieldIdx::from_usize(i)], @@ -1345,7 +1345,6 @@ impl Abi { /// Discard validity range information and allow undef. pub fn to_union(&self) -> Self { - assert!(self.is_sized()); match *self { Abi::Scalar(s) => Abi::Scalar(s.to_union()), Abi::ScalarPair(s1, s2) => Abi::ScalarPair(s1.to_union(), s2.to_union()), diff --git a/compiler/rustc_ast/src/util/comments.rs b/compiler/rustc_ast/src/util/comments.rs index eece99a3eef0..bdf5143b0f70 100644 --- a/compiler/rustc_ast/src/util/comments.rs +++ b/compiler/rustc_ast/src/util/comments.rs @@ -62,7 +62,7 @@ pub fn beautify_doc_string(data: Symbol, kind: CommentKind) -> Symbol { CommentKind::Block => { // Whatever happens, we skip the first line. let mut i = lines - .get(0) + .first() .map(|l| if l.trim_start().starts_with('*') { 0 } else { 1 }) .unwrap_or(0); let mut j = lines.len(); diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs index dcaaaafedbea..0954cf03da9a 100644 --- a/compiler/rustc_ast_lowering/src/expr.rs +++ b/compiler/rustc_ast_lowering/src/expr.rs @@ -286,7 +286,7 @@ impl<'hir> LoweringContext<'_, 'hir> { ExprKind::OffsetOf(container, fields) => hir::ExprKind::OffsetOf( self.lower_ty( container, - &mut ImplTraitContext::Disallowed(ImplTraitPosition::OffsetOf), + &ImplTraitContext::Disallowed(ImplTraitPosition::OffsetOf), ), self.arena.alloc_from_iter(fields.iter().map(|&ident| self.lower_ident(ident))), ), diff --git a/compiler/rustc_ast_pretty/src/pprust/state/expr.rs b/compiler/rustc_ast_pretty/src/pprust/state/expr.rs index 609920180a2f..8767bbcb2106 100644 --- a/compiler/rustc_ast_pretty/src/pprust/state/expr.rs +++ b/compiler/rustc_ast_pretty/src/pprust/state/expr.rs @@ -697,15 +697,15 @@ pub fn reconstruct_format_args_template_string(pieces: &[FormatArgsPiece]) -> St write!(template, "{n}").unwrap(); if p.format_options != Default::default() || p.format_trait != FormatTrait::Display { - template.push_str(":"); + template.push(':'); } if let Some(fill) = p.format_options.fill { template.push(fill); } match p.format_options.alignment { - Some(FormatAlignment::Left) => template.push_str("<"), - Some(FormatAlignment::Right) => template.push_str(">"), - Some(FormatAlignment::Center) => template.push_str("^"), + Some(FormatAlignment::Left) => template.push('<'), + Some(FormatAlignment::Right) => template.push('>'), + Some(FormatAlignment::Center) => template.push('^'), None => {} } match p.format_options.sign { diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs index ea32506fc898..2fd42e2f56a6 100644 --- a/compiler/rustc_borrowck/src/lib.rs +++ b/compiler/rustc_borrowck/src/lib.rs @@ -2306,11 +2306,10 @@ mod error { pub fn buffer_error(&mut self, t: DiagnosticBuilder<'_, ErrorGuaranteed>) { if let None = self.tainted_by_errors { - self.tainted_by_errors = Some( - self.tcx - .sess - .delay_span_bug(t.span.clone(), "diagnostic buffered but not emitted"), - ) + self.tainted_by_errors = Some(self.tcx.sess.delay_span_bug( + t.span.clone_ignoring_labels(), + "diagnostic buffered but not emitted", + )) } t.buffer(&mut self.buffered); } diff --git a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs index d8e81827a3be..17a4f2d76b60 100644 --- a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs +++ b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs @@ -339,8 +339,8 @@ fn check_opaque_type_well_formed<'tcx>( // version. let errors = ocx.select_all_or_error(); - // This is still required for many(half of the tests in ui/type-alias-impl-trait) - // tests to pass + // This is fishy, but we check it again in `check_opaque_meets_bounds`. + // Remove once we can prepopulate with known hidden types. let _ = infcx.take_opaque_types(); if errors.is_empty() { diff --git a/compiler/rustc_builtin_macros/messages.ftl b/compiler/rustc_builtin_macros/messages.ftl index 322222ae3303..79fae7f92f1e 100644 --- a/compiler/rustc_builtin_macros/messages.ftl +++ b/compiler/rustc_builtin_macros/messages.ftl @@ -109,8 +109,8 @@ builtin_macros_derive_path_args_value = traits in `#[derive(...)]` don't accept .suggestion = remove the value builtin_macros_env_not_defined = environment variable `{$var}` not defined at compile time - .cargo = Cargo sets build script variables at run time. Use `std::env::var("{$var}")` instead - .other = use `std::env::var("{$var}")` to read the variable at run time + .cargo = Cargo sets build script variables at run time. Use `std::env::var({$var_expr})` instead + .custom = use `std::env::var({$var_expr})` to read the variable at run time builtin_macros_env_takes_args = `env!()` takes 1 or 2 arguments diff --git a/compiler/rustc_builtin_macros/src/asm.rs b/compiler/rustc_builtin_macros/src/asm.rs index 19acefc38e31..21f459352184 100644 --- a/compiler/rustc_builtin_macros/src/asm.rs +++ b/compiler/rustc_builtin_macros/src/asm.rs @@ -401,7 +401,7 @@ fn parse_clobber_abi<'a>(p: &mut Parser<'a>, args: &mut AsmArgs) -> PResult<'a, // should have errored above during parsing [] => unreachable!(), [(abi, _span)] => args.clobber_abis.push((*abi, full_span)), - [abis @ ..] => { + abis => { for (abi, span) in abis { args.clobber_abis.push((*abi, *span)); } diff --git a/compiler/rustc_builtin_macros/src/env.rs b/compiler/rustc_builtin_macros/src/env.rs index bcff475f6267..92da0c069e51 100644 --- a/compiler/rustc_builtin_macros/src/env.rs +++ b/compiler/rustc_builtin_macros/src/env.rs @@ -4,7 +4,7 @@ // use rustc_ast::tokenstream::TokenStream; -use rustc_ast::{self as ast, GenericArg}; +use rustc_ast::{self as ast, AstDeref, GenericArg}; use rustc_expand::base::{self, *}; use rustc_span::symbol::{kw, sym, Ident, Symbol}; use rustc_span::Span; @@ -76,27 +76,36 @@ pub fn expand_env<'cx>( }, }; - let sp = cx.with_def_site_ctxt(sp); + let span = cx.with_def_site_ctxt(sp); let value = env::var(var.as_str()).ok().as_deref().map(Symbol::intern); cx.sess.parse_sess.env_depinfo.borrow_mut().insert((var, value)); let e = match value { None => { - // Use the string literal in the code in the diagnostic to avoid confusing diagnostics, - // e.g. when the literal contains escape sequences. let ast::ExprKind::Lit(ast::token::Lit { - kind: ast::token::LitKind::Str, - symbol: original_var, + kind: ast::token::LitKind::Str | ast::token::LitKind::StrRaw(..), + symbol, .. }) = &var_expr.kind else { unreachable!("`expr_to_string` ensures this is a string lit") }; - cx.emit_err(errors::EnvNotDefined { - span: sp, - msg: custom_msg, - var: *original_var, - help: custom_msg.is_none().then(|| help_for_missing_env_var(var.as_str())), - }); + + if let Some(msg_from_user) = custom_msg { + cx.emit_err(errors::EnvNotDefinedWithUserMessage { span, msg_from_user }); + } else if is_cargo_env_var(var.as_str()) { + cx.emit_err(errors::EnvNotDefined::CargoEnvVar { + span, + var: *symbol, + var_expr: var_expr.ast_deref(), + }); + } else { + cx.emit_err(errors::EnvNotDefined::CustomEnvVar { + span, + var: *symbol, + var_expr: var_expr.ast_deref(), + }); + } + return DummyResult::any(sp); } Some(value) => cx.expr_str(sp, value), @@ -104,13 +113,9 @@ pub fn expand_env<'cx>( MacEager::expr(e) } -fn help_for_missing_env_var(var: &str) -> errors::EnvNotDefinedHelp { - if var.starts_with("CARGO_") +/// Returns `true` if an environment variable from `env!` is one used by Cargo. +fn is_cargo_env_var(var: &str) -> bool { + var.starts_with("CARGO_") || var.starts_with("DEP_") || matches!(var, "OUT_DIR" | "OPT_LEVEL" | "PROFILE" | "HOST" | "TARGET") - { - errors::EnvNotDefinedHelp::CargoVar - } else { - errors::EnvNotDefinedHelp::Other - } } diff --git a/compiler/rustc_builtin_macros/src/errors.rs b/compiler/rustc_builtin_macros/src/errors.rs index 7b2a375a822b..fbf0395bb05a 100644 --- a/compiler/rustc_builtin_macros/src/errors.rs +++ b/compiler/rustc_builtin_macros/src/errors.rs @@ -440,43 +440,43 @@ pub(crate) struct EnvTakesArgs { pub(crate) span: Span, } -//#[derive(Diagnostic)] -//#[diag(builtin_macros_env_not_defined)] -pub(crate) struct EnvNotDefined { +pub(crate) struct EnvNotDefinedWithUserMessage { pub(crate) span: Span, - pub(crate) msg: Option, - pub(crate) var: Symbol, - pub(crate) help: Option, + pub(crate) msg_from_user: Symbol, } -// Hand-written implementation to support custom user messages -impl<'a, G: EmissionGuarantee> IntoDiagnostic<'a, G> for EnvNotDefined { +// Hand-written implementation to support custom user messages. +impl<'a, G: EmissionGuarantee> IntoDiagnostic<'a, G> for EnvNotDefinedWithUserMessage { #[track_caller] fn into_diagnostic(self, handler: &'a Handler) -> DiagnosticBuilder<'a, G> { - let mut diag = if let Some(msg) = self.msg { - #[expect( - rustc::untranslatable_diagnostic, - reason = "cannot translate user-provided messages" - )] - handler.struct_diagnostic(msg.to_string()) - } else { - handler.struct_diagnostic(crate::fluent_generated::builtin_macros_env_not_defined) - }; - diag.set_arg("var", self.var); + #[expect( + rustc::untranslatable_diagnostic, + reason = "cannot translate user-provided messages" + )] + let mut diag = handler.struct_diagnostic(self.msg_from_user.to_string()); diag.set_span(self.span); - if let Some(help) = self.help { - diag.subdiagnostic(help); - } diag } } -#[derive(Subdiagnostic)] -pub(crate) enum EnvNotDefinedHelp { +#[derive(Diagnostic)] +pub(crate) enum EnvNotDefined<'a> { + #[diag(builtin_macros_env_not_defined)] #[help(builtin_macros_cargo)] - CargoVar, - #[help(builtin_macros_other)] - Other, + CargoEnvVar { + #[primary_span] + span: Span, + var: Symbol, + var_expr: &'a rustc_ast::Expr, + }, + #[diag(builtin_macros_env_not_defined)] + #[help(builtin_macros_custom)] + CustomEnvVar { + #[primary_span] + span: Span, + var: Symbol, + var_expr: &'a rustc_ast::Expr, + }, } #[derive(Diagnostic)] diff --git a/compiler/rustc_codegen_gcc/messages.ftl b/compiler/rustc_codegen_gcc/messages.ftl index 97bc8ef9d1bb..2fd0daee3e73 100644 --- a/compiler/rustc_codegen_gcc/messages.ftl +++ b/compiler/rustc_codegen_gcc/messages.ftl @@ -1,63 +1,6 @@ codegen_gcc_invalid_minimum_alignment = invalid minimum global alignment: {$err} -codegen_gcc_invalid_monomorphization_basic_integer = - invalid monomorphization of `{$name}` intrinsic: expected basic integer type, found `{$ty}` - -codegen_gcc_invalid_monomorphization_expected_signed_unsigned = - invalid monomorphization of `{$name}` intrinsic: expected element type `{$elem_ty}` of vector type `{$vec_ty}` to be a signed or unsigned integer type - -codegen_gcc_invalid_monomorphization_expected_simd = - invalid monomorphization of `{$name}` intrinsic: expected SIMD {$expected_ty} type, found non-SIMD `{$found_ty}` - -codegen_gcc_invalid_monomorphization_inserted_type = - invalid monomorphization of `{$name}` intrinsic: expected inserted type `{$in_elem}` (element of input `{$in_ty}`), found `{$out_ty}` - -codegen_gcc_invalid_monomorphization_invalid_bitmask = - invalid monomorphization of `{$name}` intrinsic: invalid bitmask `{$ty}`, expected `u{$expected_int_bits}` or `[u8; {$expected_bytes}]` - -codegen_gcc_invalid_monomorphization_invalid_float_vector = - invalid monomorphization of `{$name}` intrinsic: unsupported element type `{$elem_ty}` of floating-point vector `{$vec_ty}` - -codegen_gcc_invalid_monomorphization_mask_type = - invalid monomorphization of `{$name}` intrinsic: mask element type is `{$ty}`, expected `i_` - -codegen_gcc_invalid_monomorphization_mismatched_lengths = - invalid monomorphization of `{$name}` intrinsic: mismatched lengths: mask length `{$m_len}` != other vector length `{$v_len}` - -codegen_gcc_invalid_monomorphization_not_float = - invalid monomorphization of `{$name}` intrinsic: `{$ty}` is not a floating-point type - -codegen_gcc_invalid_monomorphization_return_element = - invalid monomorphization of `{$name}` intrinsic: expected return element type `{$in_elem}` (element of input `{$in_ty}`), found `{$ret_ty}` with element type `{$out_ty}` - -codegen_gcc_invalid_monomorphization_return_integer_type = - invalid monomorphization of `{$name}` intrinsic: expected return type with integer elements, found `{$ret_ty}` with non-integer `{$out_ty}` - -codegen_gcc_invalid_monomorphization_return_length = - invalid monomorphization of `{$name}` intrinsic: expected return type of length {$in_len}, found `{$ret_ty}` with length {$out_len} - -codegen_gcc_invalid_monomorphization_return_length_input_type = - invalid monomorphization of `{$name}` intrinsic: expected return type with length {$in_len} (same as input type `{$in_ty}`), found `{$ret_ty}` with length {$out_len} - -codegen_gcc_invalid_monomorphization_return_type = - invalid monomorphization of `{$name}` intrinsic: expected return type `{$in_elem}` (element of input `{$in_ty}`), found `{$ret_ty}` - -codegen_gcc_invalid_monomorphization_simd_shuffle = - invalid monomorphization of `{$name}` intrinsic: simd_shuffle index must be an array of `u32`, got `{$ty}` - -codegen_gcc_invalid_monomorphization_unrecognized = - invalid monomorphization of `{$name}` intrinsic: unrecognized intrinsic `{$name}` - -codegen_gcc_invalid_monomorphization_unsupported_cast = - invalid monomorphization of `{$name}` intrinsic: unsupported cast from `{$in_ty}` with element `{$in_elem}` to `{$ret_ty}` with element `{$out_elem}` - -codegen_gcc_invalid_monomorphization_unsupported_element = - invalid monomorphization of `{$name}` intrinsic: unsupported {$name} from `{$in_ty}` with element `{$elem_ty}` to `{$ret_ty}` - -codegen_gcc_invalid_monomorphization_unsupported_operation = - invalid monomorphization of `{$name}` intrinsic: unsupported operation on `{$in_ty}` with element `{$in_elem}` - codegen_gcc_lto_not_supported = LTO is not supported. You may get a linker error. diff --git a/compiler/rustc_codegen_gcc/src/errors.rs b/compiler/rustc_codegen_gcc/src/errors.rs index 9305bd1e043d..693367192b1f 100644 --- a/compiler/rustc_codegen_gcc/src/errors.rs +++ b/compiler/rustc_codegen_gcc/src/errors.rs @@ -1,7 +1,6 @@ use rustc_errors::{DiagnosticArgValue, IntoDiagnosticArg}; use rustc_macros::Diagnostic; -use rustc_middle::ty::Ty; -use rustc_span::{Span, Symbol}; +use rustc_span::Span; use std::borrow::Cow; struct ExitCode(Option); @@ -16,201 +15,6 @@ impl IntoDiagnosticArg for ExitCode { } } -#[derive(Diagnostic)] -#[diag(codegen_gcc_invalid_monomorphization_basic_integer, code = "E0511")] -pub(crate) struct InvalidMonomorphizationBasicInteger<'a> { - #[primary_span] - pub span: Span, - pub name: Symbol, - pub ty: Ty<'a>, -} - -#[derive(Diagnostic)] -#[diag(codegen_gcc_invalid_monomorphization_invalid_float_vector, code = "E0511")] -pub(crate) struct InvalidMonomorphizationInvalidFloatVector<'a> { - #[primary_span] - pub span: Span, - pub name: Symbol, - pub elem_ty: &'a str, - pub vec_ty: Ty<'a>, -} - -#[derive(Diagnostic)] -#[diag(codegen_gcc_invalid_monomorphization_not_float, code = "E0511")] -pub(crate) struct InvalidMonomorphizationNotFloat<'a> { - #[primary_span] - pub span: Span, - pub name: Symbol, - pub ty: Ty<'a>, -} - -#[derive(Diagnostic)] -#[diag(codegen_gcc_invalid_monomorphization_unrecognized, code = "E0511")] -pub(crate) struct InvalidMonomorphizationUnrecognized { - #[primary_span] - pub span: Span, - pub name: Symbol, -} - -#[derive(Diagnostic)] -#[diag(codegen_gcc_invalid_monomorphization_expected_signed_unsigned, code = "E0511")] -pub(crate) struct InvalidMonomorphizationExpectedSignedUnsigned<'a> { - #[primary_span] - pub span: Span, - pub name: Symbol, - pub elem_ty: Ty<'a>, - pub vec_ty: Ty<'a>, -} - -#[derive(Diagnostic)] -#[diag(codegen_gcc_invalid_monomorphization_unsupported_element, code = "E0511")] -pub(crate) struct InvalidMonomorphizationUnsupportedElement<'a> { - #[primary_span] - pub span: Span, - pub name: Symbol, - pub in_ty: Ty<'a>, - pub elem_ty: Ty<'a>, - pub ret_ty: Ty<'a>, -} - -#[derive(Diagnostic)] -#[diag(codegen_gcc_invalid_monomorphization_invalid_bitmask, code = "E0511")] -pub(crate) struct InvalidMonomorphizationInvalidBitmask<'a> { - #[primary_span] - pub span: Span, - pub name: Symbol, - pub ty: Ty<'a>, - pub expected_int_bits: u64, - pub expected_bytes: u64, -} - -#[derive(Diagnostic)] -#[diag(codegen_gcc_invalid_monomorphization_simd_shuffle, code = "E0511")] -pub(crate) struct InvalidMonomorphizationSimdShuffle<'a> { - #[primary_span] - pub span: Span, - pub name: Symbol, - pub ty: Ty<'a>, -} - -#[derive(Diagnostic)] -#[diag(codegen_gcc_invalid_monomorphization_expected_simd, code = "E0511")] -pub(crate) struct InvalidMonomorphizationExpectedSimd<'a> { - #[primary_span] - pub span: Span, - pub name: Symbol, - pub position: &'a str, - pub found_ty: Ty<'a>, -} - -#[derive(Diagnostic)] -#[diag(codegen_gcc_invalid_monomorphization_mask_type, code = "E0511")] -pub(crate) struct InvalidMonomorphizationMaskType<'a> { - #[primary_span] - pub span: Span, - pub name: Symbol, - pub ty: Ty<'a>, -} - -#[derive(Diagnostic)] -#[diag(codegen_gcc_invalid_monomorphization_return_length, code = "E0511")] -pub(crate) struct InvalidMonomorphizationReturnLength<'a> { - #[primary_span] - pub span: Span, - pub name: Symbol, - pub in_len: u64, - pub ret_ty: Ty<'a>, - pub out_len: u64, -} - -#[derive(Diagnostic)] -#[diag(codegen_gcc_invalid_monomorphization_return_length_input_type, code = "E0511")] -pub(crate) struct InvalidMonomorphizationReturnLengthInputType<'a> { - #[primary_span] - pub span: Span, - pub name: Symbol, - pub in_len: u64, - pub in_ty: Ty<'a>, - pub ret_ty: Ty<'a>, - pub out_len: u64, -} - -#[derive(Diagnostic)] -#[diag(codegen_gcc_invalid_monomorphization_return_element, code = "E0511")] -pub(crate) struct InvalidMonomorphizationReturnElement<'a> { - #[primary_span] - pub span: Span, - pub name: Symbol, - pub in_elem: Ty<'a>, - pub in_ty: Ty<'a>, - pub ret_ty: Ty<'a>, - pub out_ty: Ty<'a>, -} - -#[derive(Diagnostic)] -#[diag(codegen_gcc_invalid_monomorphization_return_type, code = "E0511")] -pub(crate) struct InvalidMonomorphizationReturnType<'a> { - #[primary_span] - pub span: Span, - pub name: Symbol, - pub in_elem: Ty<'a>, - pub in_ty: Ty<'a>, - pub ret_ty: Ty<'a>, -} - -#[derive(Diagnostic)] -#[diag(codegen_gcc_invalid_monomorphization_inserted_type, code = "E0511")] -pub(crate) struct InvalidMonomorphizationInsertedType<'a> { - #[primary_span] - pub span: Span, - pub name: Symbol, - pub in_elem: Ty<'a>, - pub in_ty: Ty<'a>, - pub out_ty: Ty<'a>, -} - -#[derive(Diagnostic)] -#[diag(codegen_gcc_invalid_monomorphization_return_integer_type, code = "E0511")] -pub(crate) struct InvalidMonomorphizationReturnIntegerType<'a> { - #[primary_span] - pub span: Span, - pub name: Symbol, - pub ret_ty: Ty<'a>, - pub out_ty: Ty<'a>, -} - -#[derive(Diagnostic)] -#[diag(codegen_gcc_invalid_monomorphization_mismatched_lengths, code = "E0511")] -pub(crate) struct InvalidMonomorphizationMismatchedLengths { - #[primary_span] - pub span: Span, - pub name: Symbol, - pub m_len: u64, - pub v_len: u64, -} - -#[derive(Diagnostic)] -#[diag(codegen_gcc_invalid_monomorphization_unsupported_cast, code = "E0511")] -pub(crate) struct InvalidMonomorphizationUnsupportedCast<'a> { - #[primary_span] - pub span: Span, - pub name: Symbol, - pub in_ty: Ty<'a>, - pub in_elem: Ty<'a>, - pub ret_ty: Ty<'a>, - pub out_elem: Ty<'a>, -} - -#[derive(Diagnostic)] -#[diag(codegen_gcc_invalid_monomorphization_unsupported_operation, code = "E0511")] -pub(crate) struct InvalidMonomorphizationUnsupportedOperation<'a> { - #[primary_span] - pub span: Span, - pub name: Symbol, - pub in_ty: Ty<'a>, - pub in_elem: Ty<'a>, -} - #[derive(Diagnostic)] #[diag(codegen_gcc_lto_not_supported)] pub(crate) struct LTONotSupported; diff --git a/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs b/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs index fe604be33b67..b75546447e32 100644 --- a/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs +++ b/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs @@ -13,6 +13,7 @@ use rustc_codegen_ssa::mir::place::PlaceRef; use rustc_codegen_ssa::traits::{ArgAbiMethods, BaseTypeMethods, BuilderMethods, ConstMethods, IntrinsicCallMethods}; #[cfg(feature="master")] use rustc_codegen_ssa::traits::{DerivedTypeMethods, MiscMethods}; +use rustc_codegen_ssa::errors::InvalidMonomorphization; use rustc_middle::bug; use rustc_middle::ty::{self, Instance, Ty}; use rustc_middle::ty::layout::LayoutOf; @@ -31,7 +32,6 @@ use crate::abi::FnAbiGccExt; use crate::builder::Builder; use crate::common::{SignType, TypeReflection}; use crate::context::CodegenCx; -use crate::errors::InvalidMonomorphizationBasicInteger; use crate::type_of::LayoutGccExt; use crate::intrinsic::simd::generic_simd_intrinsic; @@ -256,7 +256,7 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallMethods<'tcx> for Builder<'a, 'gcc, 'tcx> { _ => bug!(), }, None => { - tcx.sess.emit_err(InvalidMonomorphizationBasicInteger { span, name, ty }); + tcx.sess.emit_err(InvalidMonomorphization::BasicIntegerType { span, name, ty }); return; } } diff --git a/compiler/rustc_codegen_gcc/src/intrinsic/simd.rs b/compiler/rustc_codegen_gcc/src/intrinsic/simd.rs index 9115cf971196..f27de867d367 100644 --- a/compiler/rustc_codegen_gcc/src/intrinsic/simd.rs +++ b/compiler/rustc_codegen_gcc/src/intrinsic/simd.rs @@ -21,19 +21,6 @@ use rustc_target::abi::Align; use crate::builder::Builder; #[cfg(feature="master")] use crate::context::CodegenCx; -#[cfg(feature="master")] -use crate::errors::{InvalidMonomorphizationExpectedSignedUnsigned, InvalidMonomorphizationInsertedType}; -use crate::errors::{ - InvalidMonomorphizationExpectedSimd, - InvalidMonomorphizationInvalidBitmask, - InvalidMonomorphizationInvalidFloatVector, InvalidMonomorphizationMaskType, - InvalidMonomorphizationMismatchedLengths, InvalidMonomorphizationNotFloat, - InvalidMonomorphizationReturnElement, InvalidMonomorphizationReturnIntegerType, - InvalidMonomorphizationReturnLength, InvalidMonomorphizationReturnLengthInputType, - InvalidMonomorphizationReturnType, InvalidMonomorphizationSimdShuffle, - InvalidMonomorphizationUnrecognized, InvalidMonomorphizationUnsupportedElement, - InvalidMonomorphizationUnsupportedOperation, -}; pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( bx: &mut Builder<'a, 'gcc, 'tcx>, @@ -59,16 +46,8 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( }; } macro_rules! require_simd { - ($ty: expr, $position: expr) => { - require!( - $ty.is_simd(), - InvalidMonomorphizationExpectedSimd { - span, - name, - position: $position, - found_ty: $ty - } - ) + ($ty: expr, $diag: expr) => { + require!($ty.is_simd(), $diag) }; } @@ -78,7 +57,7 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( let arg_tys = sig.inputs(); if name == sym::simd_select_bitmask { - require_simd!(arg_tys[1], "argument"); + require_simd!(arg_tys[1], InvalidMonomorphization::SimdArgument { span, name, ty: arg_tys[1] }); let (len, _) = arg_tys[1].simd_size_and_type(bx.tcx()); let expected_int_bits = (len.max(8) - 1).next_power_of_two(); @@ -99,10 +78,10 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( let ptr = bx.pointercast(place.llval, bx.cx.type_ptr_to(int_ty)); bx.load(int_ty, ptr, Align::ONE) } - _ => return_error!(InvalidMonomorphizationInvalidBitmask { + _ => return_error!(InvalidMonomorphization::InvalidBitmask { span, name, - ty: mask_ty, + mask_ty, expected_int_bits, expected_bytes }), @@ -131,7 +110,7 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( } // every intrinsic below takes a SIMD vector as its first argument - require_simd!(arg_tys[0], "input"); + require_simd!(arg_tys[0], InvalidMonomorphization::SimdInput { span, name, ty: arg_tys[0] }); let in_ty = arg_tys[0]; let comparison = match name { @@ -146,12 +125,12 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( let (in_len, in_elem) = arg_tys[0].simd_size_and_type(bx.tcx()); if let Some(cmp_op) = comparison { - require_simd!(ret_ty, "return"); + require_simd!(ret_ty, InvalidMonomorphization::SimdReturn { span, name, ty: ret_ty }); let (out_len, out_ty) = ret_ty.simd_size_and_type(bx.tcx()); require!( in_len == out_len, - InvalidMonomorphizationReturnLengthInputType { + InvalidMonomorphization::ReturnLengthInputType { span, name, in_len, @@ -162,7 +141,7 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( ); require!( bx.type_kind(bx.element_type(llret_ty)) == TypeKind::Integer, - InvalidMonomorphizationReturnIntegerType { span, name, ret_ty, out_ty } + InvalidMonomorphization::ReturnIntegerType { span, name, ret_ty, out_ty } ); let arg1 = args[0].immediate(); @@ -190,7 +169,7 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( || span_bug!(span, "could not evaluate shuffle index array length"), ) } - _ => return_error!(InvalidMonomorphizationSimdShuffle { + _ => return_error!(InvalidMonomorphization::SimdShuffle { span, name, ty: args[2].layout.ty @@ -202,16 +181,16 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( }) }; - require_simd!(ret_ty, "return"); + require_simd!(ret_ty, InvalidMonomorphization::SimdReturn { span, name, ty: ret_ty }); let (out_len, out_ty) = ret_ty.simd_size_and_type(bx.tcx()); require!( out_len == n, - InvalidMonomorphizationReturnLength { span, name, in_len: n, ret_ty, out_len } + InvalidMonomorphization::ReturnLength { span, name, in_len: n, ret_ty, out_len } ); require!( in_elem == out_ty, - InvalidMonomorphizationReturnElement { span, name, in_elem, in_ty, ret_ty, out_ty } + InvalidMonomorphization::ReturnElement { span, name, in_elem, in_ty, ret_ty, out_ty } ); let vector = args[2].immediate(); @@ -223,7 +202,7 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( if name == sym::simd_insert { require!( in_elem == arg_tys[2], - InvalidMonomorphizationInsertedType { span, name, in_elem, in_ty, out_ty: arg_tys[2] } + InvalidMonomorphization::InsertedType { span, name, in_elem, in_ty, out_ty: arg_tys[2] } ); let vector = args[0].immediate(); let index = args[1].immediate(); @@ -240,7 +219,7 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( if name == sym::simd_extract { require!( ret_ty == in_elem, - InvalidMonomorphizationReturnType { span, name, in_elem, in_ty, ret_ty } + InvalidMonomorphization::ReturnType { span, name, in_elem, in_ty, ret_ty } ); let vector = args[0].immediate(); return Ok(bx.context.new_vector_access(None, vector, args[1].immediate()).to_rvalue()); @@ -249,26 +228,26 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( if name == sym::simd_select { let m_elem_ty = in_elem; let m_len = in_len; - require_simd!(arg_tys[1], "argument"); + require_simd!(arg_tys[1], InvalidMonomorphization::SimdArgument { span, name, ty: arg_tys[1] }); let (v_len, _) = arg_tys[1].simd_size_and_type(bx.tcx()); require!( m_len == v_len, - InvalidMonomorphizationMismatchedLengths { span, name, m_len, v_len } + InvalidMonomorphization::MismatchedLengths { span, name, m_len, v_len } ); match m_elem_ty.kind() { ty::Int(_) => {} - _ => return_error!(InvalidMonomorphizationMaskType { span, name, ty: m_elem_ty }), + _ => return_error!(InvalidMonomorphization::MaskType { span, name, ty: m_elem_ty }), } return Ok(bx.vector_select(args[0].immediate(), args[1].immediate(), args[2].immediate())); } #[cfg(feature="master")] if name == sym::simd_cast || name == sym::simd_as { - require_simd!(ret_ty, "return"); + require_simd!(ret_ty, InvalidMonomorphization::SimdReturn { span, name, ty: ret_ty }); let (out_len, out_elem) = ret_ty.simd_size_and_type(bx.tcx()); require!( in_len == out_len, - InvalidMonomorphizationReturnLengthInputType { + InvalidMonomorphization::ReturnLengthInputType { span, name, in_len, @@ -329,7 +308,7 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( })* _ => {}, } - return_error!(InvalidMonomorphizationUnsupportedOperation { span, name, in_ty, in_elem }) + return_error!(InvalidMonomorphization::UnsupportedOperation { span, name, in_ty, in_elem }) })* } } @@ -422,12 +401,12 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( 32 => ("f", elem_ty), 64 => ("", elem_ty), _ => { - return_error!(InvalidMonomorphizationInvalidFloatVector { span, name, elem_ty: f.name_str(), vec_ty: in_ty }); + return_error!(InvalidMonomorphization::FloatingPointVector { span, name, f_ty: *f, in_ty }); } } } else { - return_error!(InvalidMonomorphizationNotFloat { span, name, ty: in_ty }); + return_error!(InvalidMonomorphization::FloatingPointType { span, name, in_ty }); }; let vec_ty = bx.cx.type_vector(elem_ty, in_len); @@ -450,7 +429,7 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( sym::simd_fsqrt => "sqrt", sym::simd_round => "round", sym::simd_trunc => "trunc", - _ => return_error!(InvalidMonomorphizationUnrecognized { span, name }) + _ => return_error!(InvalidMonomorphization::UnrecognizedIntrinsic { span, name }) }; let builtin_name = format!("{}{}", intr_name, elem_ty_str); let funcs = bx.cx.functions.borrow(); @@ -566,10 +545,10 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( // * M: any integer width is supported, will be truncated to i1 // All types must be simd vector types - require_simd!(in_ty, "first"); - require_simd!(arg_tys[1], "second"); - require_simd!(arg_tys[2], "third"); - require_simd!(ret_ty, "return"); + require_simd!(in_ty, InvalidMonomorphization::SimdFirst { span, name, ty: in_ty }); + require_simd!(arg_tys[1], InvalidMonomorphization::SimdSecond { span, name, ty: arg_tys[1] }); + require_simd!(arg_tys[2], InvalidMonomorphization::SimdThird { span, name, ty: arg_tys[2] }); + require_simd!(ret_ty, InvalidMonomorphization::SimdReturn { span, name, ty: ret_ty }); // Of the same length: let (out_len, _) = arg_tys[1].simd_size_and_type(bx.tcx()); @@ -674,9 +653,9 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( // * M: any integer width is supported, will be truncated to i1 // All types must be simd vector types - require_simd!(in_ty, "first"); - require_simd!(arg_tys[1], "second"); - require_simd!(arg_tys[2], "third"); + require_simd!(in_ty, InvalidMonomorphization::SimdFirst { span, name, ty: in_ty }); + require_simd!(arg_tys[1], InvalidMonomorphization::SimdSecond { span, name, ty: arg_tys[1] }); + require_simd!(arg_tys[2], InvalidMonomorphization::SimdThird { span, name, ty: arg_tys[2] }); // Of the same length: let (element_len1, _) = arg_tys[1].simd_size_and_type(bx.tcx()); @@ -815,7 +794,7 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( })* _ => {}, } - return_error!(InvalidMonomorphizationUnsupportedOperation { span, name, in_ty, in_elem }) + return_error!(InvalidMonomorphization::UnsupportedOperation { span, name, in_ty, in_elem }) })* } } @@ -835,11 +814,11 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( ty::Int(i) => (true, i.bit_width().unwrap_or(ptr_bits) / 8, bx.cx.type_int_from_ty(i)), ty::Uint(i) => (false, i.bit_width().unwrap_or(ptr_bits) / 8, bx.cx.type_uint_from_ty(i)), _ => { - return_error!(InvalidMonomorphizationExpectedSignedUnsigned { + return_error!(InvalidMonomorphization::ExpectedVectorElementType { span, name, - elem_ty: arg_tys[0].simd_size_and_type(bx.tcx()).1, - vec_ty: arg_tys[0], + expected_element: arg_tys[0].simd_size_and_type(bx.tcx()).1, + vector_type: arg_tys[0], }); } }; @@ -925,7 +904,7 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( if name == sym::$name { require!( ret_ty == in_elem, - InvalidMonomorphizationReturnType { span, name, in_elem, in_ty, ret_ty } + InvalidMonomorphization::ReturnType { span, name, in_elem, in_ty, ret_ty } ); return match in_elem.kind() { ty::Int(_) | ty::Uint(_) => { @@ -947,11 +926,12 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( Ok(bx.vector_reduce_op(args[0].immediate(), $vec_op)) } } - _ => return_error!(InvalidMonomorphizationUnsupportedElement { + _ => return_error!(InvalidMonomorphization::UnsupportedSymbol { span, name, + symbol: sym::$name, in_ty, - elem_ty: in_elem, + in_elem, ret_ty }), }; @@ -994,12 +974,19 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( if name == sym::$name { require!( ret_ty == in_elem, - InvalidMonomorphizationReturnType { span, name, in_elem, in_ty, ret_ty } + InvalidMonomorphization::ReturnType { span, name, in_elem, in_ty, ret_ty } ); return match in_elem.kind() { ty::Int(_) | ty::Uint(_) => Ok(bx.$int_red(args[0].immediate())), ty::Float(_) => Ok(bx.$float_red(args[0].immediate())), - _ => return_error!(InvalidMonomorphizationUnsupportedElement { span, name, in_ty, elem_ty: in_elem, ret_ty }), + _ => return_error!(InvalidMonomorphization::UnsupportedSymbol { + span, + name, + symbol: sym::$name, + in_ty, + in_elem, + ret_ty + }), }; } }; @@ -1017,17 +1004,18 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( let input = if !$boolean { require!( ret_ty == in_elem, - InvalidMonomorphizationReturnType { span, name, in_elem, in_ty, ret_ty } + InvalidMonomorphization::ReturnType { span, name, in_elem, in_ty, ret_ty } ); args[0].immediate() } else { match in_elem.kind() { ty::Int(_) | ty::Uint(_) => {} - _ => return_error!(InvalidMonomorphizationUnsupportedElement { + _ => return_error!(InvalidMonomorphization::UnsupportedSymbol { span, name, + symbol: sym::$name, in_ty, - elem_ty: in_elem, + in_elem, ret_ty }), } @@ -1039,11 +1027,12 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( let r = bx.vector_reduce_op(input, $op); Ok(if !$boolean { r } else { bx.icmp(IntPredicate::IntNE, r, bx.context.new_rvalue_zero(r.get_type())) }) } - _ => return_error!(InvalidMonomorphizationUnsupportedElement { + _ => return_error!(InvalidMonomorphization::UnsupportedSymbol { span, name, + symbol: sym::$name, in_ty, - elem_ty: in_elem, + in_elem, ret_ty }), }; diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs index 6e815ab3ff51..9149b06886b3 100644 --- a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs +++ b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs @@ -100,9 +100,11 @@ pub fn finalize(cx: &CodegenCx<'_, '_>) { // Generate the LLVM IR representation of the coverage map and store it in a well-known global let cov_data_val = mapgen.generate_coverage_map(cx, version, filenames_size, filenames_val); + let covfun_section_name = coverageinfo::covfun_section_name(cx); for (mangled_function_name, source_hash, is_used, coverage_mapping_buffer) in function_data { save_function_record( cx, + &covfun_section_name, mangled_function_name, source_hash, filenames_ref, @@ -228,6 +230,7 @@ impl CoverageMapGenerator { /// specific, well-known section and name. fn save_function_record( cx: &CodegenCx<'_, '_>, + covfun_section_name: &str, mangled_function_name: &str, source_hash: u64, filenames_ref: u64, @@ -254,7 +257,13 @@ fn save_function_record( /*packed=*/ true, ); - coverageinfo::save_func_record_to_mod(cx, func_name_hash, func_record_val, is_used); + coverageinfo::save_func_record_to_mod( + cx, + covfun_section_name, + func_name_hash, + func_record_val, + is_used, + ); } /// When finalizing the coverage map, `FunctionCoverage` only has the `CodeRegion`s and counters for diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs index 1f8f40339313..60cbb3d3d9d6 100644 --- a/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs +++ b/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs @@ -408,6 +408,7 @@ pub(crate) fn save_cov_data_to_mod<'ll, 'tcx>( pub(crate) fn save_func_record_to_mod<'ll, 'tcx>( cx: &CodegenCx<'ll, 'tcx>, + covfun_section_name: &str, func_name_hash: u64, func_record_val: &'ll llvm::Value, is_used: bool, @@ -423,20 +424,33 @@ pub(crate) fn save_func_record_to_mod<'ll, 'tcx>( let func_record_var_name = format!("__covrec_{:X}{}", func_name_hash, if is_used { "u" } else { "" }); debug!("function record var name: {:?}", func_record_var_name); - - let func_record_section_name = llvm::build_string(|s| unsafe { - llvm::LLVMRustCoverageWriteFuncSectionNameToString(cx.llmod, s); - }) - .expect("Rust Coverage function record section name failed UTF-8 conversion"); - debug!("function record section name: {:?}", func_record_section_name); + debug!("function record section name: {:?}", covfun_section_name); let llglobal = llvm::add_global(cx.llmod, cx.val_ty(func_record_val), &func_record_var_name); llvm::set_initializer(llglobal, func_record_val); llvm::set_global_constant(llglobal, true); llvm::set_linkage(llglobal, llvm::Linkage::LinkOnceODRLinkage); llvm::set_visibility(llglobal, llvm::Visibility::Hidden); - llvm::set_section(llglobal, &func_record_section_name); + llvm::set_section(llglobal, covfun_section_name); llvm::set_alignment(llglobal, VAR_ALIGN_BYTES); llvm::set_comdat(cx.llmod, llglobal, &func_record_var_name); cx.add_used_global(llglobal); } + +/// Returns the section name string to pass through to the linker when embedding +/// per-function coverage information in the object file, according to the target +/// platform's object file format. +/// +/// LLVM's coverage tools read coverage mapping details from this section when +/// producing coverage reports. +/// +/// Typical values are: +/// - `__llvm_covfun` on Linux +/// - `__LLVM_COV,__llvm_covfun` on macOS (includes `__LLVM_COV,` segment prefix) +/// - `.lcovfun$M` on Windows (includes `$M` sorting suffix) +pub(crate) fn covfun_section_name(cx: &CodegenCx<'_, '_>) -> String { + llvm::build_string(|s| unsafe { + llvm::LLVMRustCoverageWriteFuncSectionNameToString(cx.llmod, s); + }) + .expect("Rust Coverage function record section name failed UTF-8 conversion") +} diff --git a/compiler/rustc_codegen_ssa/src/errors.rs b/compiler/rustc_codegen_ssa/src/errors.rs index c72d37be7481..dbe1d6e8ba89 100644 --- a/compiler/rustc_codegen_ssa/src/errors.rs +++ b/compiler/rustc_codegen_ssa/src/errors.rs @@ -353,7 +353,7 @@ impl IntoDiagnostic<'_> for LinkingFailed<'_> { let contains_undefined_ref = self.escaped_output.contains("undefined reference to"); - diag.note(format!("{:?}", self.command)).note(self.escaped_output.to_string()); + diag.note(format!("{:?}", self.command)).note(self.escaped_output); // Trying to match an error from OS linkers // which by now we have no way to translate. diff --git a/compiler/rustc_const_eval/messages.ftl b/compiler/rustc_const_eval/messages.ftl index d8eade5bd2a0..671c2be1de9d 100644 --- a/compiler/rustc_const_eval/messages.ftl +++ b/compiler/rustc_const_eval/messages.ftl @@ -408,8 +408,11 @@ const_eval_undefined_behavior = const_eval_undefined_behavior_note = The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. +const_eval_uninhabited_enum_tag = {$front_matter}: encountered an uninhabited enum variant +const_eval_uninhabited_enum_variant_read = + read discriminant of an uninhabited enum variant const_eval_uninhabited_enum_variant_written = - writing discriminant of an uninhabited enum + writing discriminant of an uninhabited enum variant const_eval_uninhabited_val = {$front_matter}: encountered a value of uninhabited type `{$ty}` const_eval_uninit = {$front_matter}: encountered uninitialized bytes const_eval_uninit_bool = {$front_matter}: encountered uninitialized memory, but expected a boolean @@ -423,8 +426,6 @@ const_eval_uninit_int = {$front_matter}: encountered uninitialized memory, but e const_eval_uninit_raw_ptr = {$front_matter}: encountered uninitialized memory, but expected a raw pointer const_eval_uninit_ref = {$front_matter}: encountered uninitialized memory, but expected a reference const_eval_uninit_str = {$front_matter}: encountered uninitialized data in `str` -const_eval_uninit_unsized_local = - unsized local is used while uninitialized const_eval_unreachable = entering unreachable code const_eval_unreachable_unwind = unwinding past a stack frame that does not allow unwinding diff --git a/compiler/rustc_const_eval/src/const_eval/mod.rs b/compiler/rustc_const_eval/src/const_eval/mod.rs index 0a3c3914ff97..ef31155215a1 100644 --- a/compiler/rustc_const_eval/src/const_eval/mod.rs +++ b/compiler/rustc_const_eval/src/const_eval/mod.rs @@ -101,8 +101,8 @@ pub(crate) fn try_destructure_mir_constant_for_diagnostics<'tcx>( return None; } ty::Adt(def, _) => { - let variant = ecx.read_discriminant(&op).ok()?.1; - let down = ecx.operand_downcast(&op, variant).ok()?; + let variant = ecx.read_discriminant(&op).ok()?; + let down = ecx.project_downcast(&op, variant).ok()?; (def.variants()[variant].fields.len(), Some(variant), down) } ty::Tuple(args) => (args.len(), None, op), @@ -111,7 +111,7 @@ pub(crate) fn try_destructure_mir_constant_for_diagnostics<'tcx>( let fields_iter = (0..field_count) .map(|i| { - let field_op = ecx.operand_field(&down, i).ok()?; + let field_op = ecx.project_field(&down, i).ok()?; let val = op_to_const(&ecx, &field_op); Some((val, field_op.layout.ty)) }) diff --git a/compiler/rustc_const_eval/src/const_eval/valtrees.rs b/compiler/rustc_const_eval/src/const_eval/valtrees.rs index 9531d973eb32..b519bcdf4a33 100644 --- a/compiler/rustc_const_eval/src/const_eval/valtrees.rs +++ b/compiler/rustc_const_eval/src/const_eval/valtrees.rs @@ -2,11 +2,11 @@ use super::eval_queries::{mk_eval_cx, op_to_const}; use super::machine::CompileTimeEvalContext; use super::{ValTreeCreationError, ValTreeCreationResult, VALTREE_MAX_NODES}; use crate::const_eval::CanAccessStatics; +use crate::interpret::MPlaceTy; use crate::interpret::{ intern_const_alloc_recursive, ConstValue, ImmTy, Immediate, InternKind, MemPlaceMeta, - MemoryKind, PlaceTy, Scalar, + MemoryKind, PlaceTy, Projectable, Scalar, }; -use crate::interpret::{MPlaceTy, Value}; use rustc_middle::ty::{self, ScalarInt, Ty, TyCtxt}; use rustc_span::source_map::DUMMY_SP; use rustc_target::abi::{Align, FieldIdx, VariantIdx, FIRST_VARIANT}; @@ -20,7 +20,7 @@ fn branches<'tcx>( num_nodes: &mut usize, ) -> ValTreeCreationResult<'tcx> { let place = match variant { - Some(variant) => ecx.mplace_downcast(&place, variant).unwrap(), + Some(variant) => ecx.project_downcast(place, variant).unwrap(), None => *place, }; let variant = variant.map(|variant| Some(ty::ValTree::Leaf(ScalarInt::from(variant.as_u32())))); @@ -28,7 +28,7 @@ fn branches<'tcx>( let mut fields = Vec::with_capacity(n); for i in 0..n { - let field = ecx.mplace_field(&place, i).unwrap(); + let field = ecx.project_field(&place, i).unwrap(); let valtree = const_to_valtree_inner(ecx, &field, num_nodes)?; fields.push(Some(valtree)); } @@ -55,13 +55,11 @@ fn slice_branches<'tcx>( place: &MPlaceTy<'tcx>, num_nodes: &mut usize, ) -> ValTreeCreationResult<'tcx> { - let n = place - .len(&ecx.tcx.tcx) - .unwrap_or_else(|_| panic!("expected to use len of place {:?}", place)); + let n = place.len(ecx).unwrap_or_else(|_| panic!("expected to use len of place {:?}", place)); let mut elems = Vec::with_capacity(n as usize); for i in 0..n { - let place_elem = ecx.mplace_index(place, i).unwrap(); + let place_elem = ecx.project_index(place, i).unwrap(); let valtree = const_to_valtree_inner(ecx, &place_elem, num_nodes)?; elems.push(valtree); } @@ -132,7 +130,7 @@ pub(crate) fn const_to_valtree_inner<'tcx>( bug!("uninhabited types should have errored and never gotten converted to valtree") } - let Ok((_, variant)) = ecx.read_discriminant(&place.into()) else { + let Ok(variant) = ecx.read_discriminant(&place.into()) else { return Err(ValTreeCreationError::Other); }; branches(ecx, place, def.variant(variant).fields.len(), def.is_enum().then_some(variant), num_nodes) @@ -386,7 +384,7 @@ fn valtree_into_mplace<'tcx>( debug!(?variant); ( - place.project_downcast(ecx, variant_idx).unwrap(), + ecx.project_downcast(place, variant_idx).unwrap(), &branches[1..], Some(variant_idx), ) @@ -401,7 +399,7 @@ fn valtree_into_mplace<'tcx>( debug!(?i, ?inner_valtree); let mut place_inner = match ty.kind() { - ty::Str | ty::Slice(_) => ecx.mplace_index(&place, i as u64).unwrap(), + ty::Str | ty::Slice(_) => ecx.project_index(place, i as u64).unwrap(), _ if !ty.is_sized(*ecx.tcx, ty::ParamEnv::empty()) && i == branches.len() - 1 => { @@ -441,7 +439,7 @@ fn valtree_into_mplace<'tcx>( ) .unwrap() } - _ => ecx.mplace_field(&place_adjusted, i).unwrap(), + _ => ecx.project_field(&place_adjusted, i).unwrap(), }; debug!(?place_inner); diff --git a/compiler/rustc_const_eval/src/errors.rs b/compiler/rustc_const_eval/src/errors.rs index ca38cce710e6..e1109e584b7b 100644 --- a/compiler/rustc_const_eval/src/errors.rs +++ b/compiler/rustc_const_eval/src/errors.rs @@ -511,7 +511,8 @@ impl<'a> ReportErrorExt for UndefinedBehaviorInfo<'a> { InvalidUninitBytes(Some(_)) => const_eval_invalid_uninit_bytes, DeadLocal => const_eval_dead_local, ScalarSizeMismatch(_) => const_eval_scalar_size_mismatch, - UninhabitedEnumVariantWritten => const_eval_uninhabited_enum_variant_written, + UninhabitedEnumVariantWritten(_) => const_eval_uninhabited_enum_variant_written, + UninhabitedEnumVariantRead(_) => const_eval_uninhabited_enum_variant_read, Validation(e) => e.diagnostic_message(), Custom(x) => (x.msg)(), } @@ -535,7 +536,8 @@ impl<'a> ReportErrorExt for UndefinedBehaviorInfo<'a> { | InvalidMeta(InvalidMetaKind::TooBig) | InvalidUninitBytes(None) | DeadLocal - | UninhabitedEnumVariantWritten => {} + | UninhabitedEnumVariantWritten(_) + | UninhabitedEnumVariantRead(_) => {} BoundsCheckFailed { len, index } => { builder.set_arg("len", len); builder.set_arg("index", index); @@ -623,6 +625,7 @@ impl<'tcx> ReportErrorExt for ValidationErrorInfo<'tcx> { UnsafeCell => const_eval_unsafe_cell, UninhabitedVal { .. } => const_eval_uninhabited_val, InvalidEnumTag { .. } => const_eval_invalid_enum_tag, + UninhabitedEnumTag => const_eval_uninhabited_enum_tag, UninitEnumTag => const_eval_uninit_enum_tag, UninitStr => const_eval_uninit_str, Uninit { expected: ExpectedKind::Bool } => const_eval_uninit_bool, @@ -760,7 +763,8 @@ impl<'tcx> ReportErrorExt for ValidationErrorInfo<'tcx> { | InvalidMetaSliceTooLarge { .. } | InvalidMetaTooLarge { .. } | DanglingPtrUseAfterFree { .. } - | DanglingPtrOutOfBounds { .. } => {} + | DanglingPtrOutOfBounds { .. } + | UninhabitedEnumTag => {} } } } @@ -835,7 +839,9 @@ impl<'tcx> ReportErrorExt for InvalidProgramInfo<'tcx> { rustc_middle::error::middle_adjust_for_foreign_abi_error } InvalidProgramInfo::SizeOfUnsizedType(_) => const_eval_size_of_unsized, - InvalidProgramInfo::UninitUnsizedLocal => const_eval_uninit_unsized_local, + InvalidProgramInfo::ConstPropNonsense => { + panic!("We had const-prop nonsense, this should never be printed") + } } } fn add_args( @@ -846,7 +852,7 @@ impl<'tcx> ReportErrorExt for InvalidProgramInfo<'tcx> { match self { InvalidProgramInfo::TooGeneric | InvalidProgramInfo::AlreadyReported(_) - | InvalidProgramInfo::UninitUnsizedLocal => {} + | InvalidProgramInfo::ConstPropNonsense => {} InvalidProgramInfo::Layout(e) => { let diag: DiagnosticBuilder<'_, ()> = e.into_diagnostic().into_diagnostic(handler); for (name, val) in diag.args() { diff --git a/compiler/rustc_const_eval/src/interpret/cast.rs b/compiler/rustc_const_eval/src/interpret/cast.rs index dd7a1fcc1659..977e49b63431 100644 --- a/compiler/rustc_const_eval/src/interpret/cast.rs +++ b/compiler/rustc_const_eval/src/interpret/cast.rs @@ -420,8 +420,8 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { if cast_ty_field.is_zst() { continue; } - let src_field = self.operand_field(src, i)?; - let dst_field = self.place_field(dest, i)?; + let src_field = self.project_field(src, i)?; + let dst_field = self.project_field(dest, i)?; if src_field.layout.ty == cast_ty_field.ty { self.copy_op(&src_field, &dst_field, /*allow_transmute*/ false)?; } else { diff --git a/compiler/rustc_const_eval/src/interpret/discriminant.rs b/compiler/rustc_const_eval/src/interpret/discriminant.rs index f23a455c2ca3..aff86d5f4866 100644 --- a/compiler/rustc_const_eval/src/interpret/discriminant.rs +++ b/compiler/rustc_const_eval/src/interpret/discriminant.rs @@ -1,6 +1,6 @@ //! Functions for reading and writing discriminants of multi-variant layouts (enums and generators). -use rustc_middle::ty::layout::{LayoutOf, PrimitiveExt}; +use rustc_middle::ty::layout::{LayoutOf, PrimitiveExt, TyAndLayout}; use rustc_middle::{mir, ty}; use rustc_target::abi::{self, TagEncoding}; use rustc_target::abi::{VariantIdx, Variants}; @@ -22,7 +22,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { // When evaluating we will always error before even getting here, but ConstProp 'executes' // dead code, so we cannot ICE here. if dest.layout.for_variant(self, variant_index).abi.is_uninhabited() { - throw_ub!(UninhabitedEnumVariantWritten) + throw_ub!(UninhabitedEnumVariantWritten(variant_index)) } match dest.layout.variants { @@ -47,7 +47,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { let size = tag_layout.size(self); let tag_val = size.truncate(discr_val); - let tag_dest = self.place_field(dest, tag_field)?; + let tag_dest = self.project_field(dest, tag_field)?; self.write_scalar(Scalar::from_uint(tag_val, size), &tag_dest)?; } abi::Variants::Multiple { @@ -78,7 +78,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { &niche_start_val, )?; // Write result. - let niche_dest = self.place_field(dest, tag_field)?; + let niche_dest = self.project_field(dest, tag_field)?; self.write_immediate(*tag_val, &niche_dest)?; } } @@ -93,7 +93,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { pub fn read_discriminant( &self, op: &OpTy<'tcx, M::Provenance>, - ) -> InterpResult<'tcx, (Scalar, VariantIdx)> { + ) -> InterpResult<'tcx, VariantIdx> { trace!("read_discriminant_value {:#?}", op.layout); // Get type and layout of the discriminant. let discr_layout = self.layout_of(op.layout.ty.discriminant_ty(*self.tcx))?; @@ -106,19 +106,22 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { // straight-forward (`TagEncoding::Direct`) or with a niche (`TagEncoding::Niche`). let (tag_scalar_layout, tag_encoding, tag_field) = match op.layout.variants { Variants::Single { index } => { - let discr = match op.layout.ty.discriminant_for_variant(*self.tcx, index) { - Some(discr) => { - // This type actually has discriminants. - assert_eq!(discr.ty, discr_layout.ty); - Scalar::from_uint(discr.val, discr_layout.size) + // Do some extra checks on enums. + if op.layout.ty.is_enum() { + // Hilariously, `Single` is used even for 0-variant enums. + // (See https://github.com/rust-lang/rust/issues/89765). + if matches!(op.layout.ty.kind(), ty::Adt(def, ..) if def.variants().is_empty()) + { + throw_ub!(UninhabitedEnumVariantRead(index)) } - None => { - // On a type without actual discriminants, variant is 0. - assert_eq!(index.as_u32(), 0); - Scalar::from_uint(index.as_u32(), discr_layout.size) + // For consisteny with `write_discriminant`, and to make sure that + // `project_downcast` cannot fail due to strange layouts, we declare immediate UB + // for uninhabited variants. + if op.layout.for_variant(self, index).abi.is_uninhabited() { + throw_ub!(UninhabitedEnumVariantRead(index)) } - }; - return Ok((discr, index)); + } + return Ok(index); } Variants::Multiple { tag, ref tag_encoding, tag_field, .. } => { (tag, tag_encoding, tag_field) @@ -138,13 +141,13 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { let tag_layout = self.layout_of(tag_scalar_layout.primitive().to_int_ty(*self.tcx))?; // Read tag and sanity-check `tag_layout`. - let tag_val = self.read_immediate(&self.operand_field(op, tag_field)?)?; + let tag_val = self.read_immediate(&self.project_field(op, tag_field)?)?; assert_eq!(tag_layout.size, tag_val.layout.size); assert_eq!(tag_layout.abi.is_signed(), tag_val.layout.abi.is_signed()); trace!("tag value: {}", tag_val); // Figure out which discriminant and variant this corresponds to. - Ok(match *tag_encoding { + let index = match *tag_encoding { TagEncoding::Direct => { let scalar = tag_val.to_scalar(); // Generate a specific error if `tag_val` is not an integer. @@ -172,7 +175,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { } .ok_or_else(|| err_ub!(InvalidTag(Scalar::from_uint(tag_bits, tag_layout.size))))?; // Return the cast value, and the index. - (discr_val, index.0) + index.0 } TagEncoding::Niche { untagged_variant, ref niche_variants, niche_start } => { let tag_val = tag_val.to_scalar(); @@ -230,7 +233,32 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { // Compute the size of the scalar we need to return. // No need to cast, because the variant index directly serves as discriminant and is // encoded in the tag. - (Scalar::from_uint(variant.as_u32(), discr_layout.size), variant) + variant + } + }; + // For consisteny with `write_discriminant`, and to make sure that `project_downcast` cannot fail due to strange layouts, we declare immediate UB for uninhabited variants. + if op.layout.for_variant(self, index).abi.is_uninhabited() { + throw_ub!(UninhabitedEnumVariantRead(index)) + } + Ok(index) + } + + pub fn discriminant_for_variant( + &self, + layout: TyAndLayout<'tcx>, + variant: VariantIdx, + ) -> InterpResult<'tcx, Scalar> { + let discr_layout = self.layout_of(layout.ty.discriminant_ty(*self.tcx))?; + Ok(match layout.ty.discriminant_for_variant(*self.tcx, variant) { + Some(discr) => { + // This type actually has discriminants. + assert_eq!(discr.ty, discr_layout.ty); + Scalar::from_uint(discr.val, discr_layout.size) + } + None => { + // On a type without actual discriminants, variant is 0. + assert_eq!(variant.as_u32(), 0); + Scalar::from_uint(variant.as_u32(), discr_layout.size) } }) } diff --git a/compiler/rustc_const_eval/src/interpret/eval_context.rs b/compiler/rustc_const_eval/src/interpret/eval_context.rs index 04e046fbda35..0e6125388a60 100644 --- a/compiler/rustc_const_eval/src/interpret/eval_context.rs +++ b/compiler/rustc_const_eval/src/interpret/eval_context.rs @@ -1014,9 +1014,12 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> std::fmt::Debug { fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self.place { - Place::Local { frame, local } => { + Place::Local { frame, local, offset } => { let mut allocs = Vec::new(); write!(fmt, "{:?}", local)?; + if let Some(offset) = offset { + write!(fmt, "+{:#x}", offset.bytes())?; + } if frame != self.ecx.frame_idx() { write!(fmt, " ({} frames up)", self.ecx.frame_idx() - frame)?; } diff --git a/compiler/rustc_const_eval/src/interpret/intern.rs b/compiler/rustc_const_eval/src/interpret/intern.rs index 107e5bec6141..3a7fe8bd4781 100644 --- a/compiler/rustc_const_eval/src/interpret/intern.rs +++ b/compiler/rustc_const_eval/src/interpret/intern.rs @@ -164,75 +164,6 @@ impl<'rt, 'mir, 'tcx: 'mir, M: CompileTimeMachine<'mir, 'tcx, const_eval::Memory &self.ecx } - fn visit_aggregate( - &mut self, - mplace: &MPlaceTy<'tcx>, - fields: impl Iterator>, - ) -> InterpResult<'tcx> { - // We want to walk the aggregate to look for references to intern. While doing that we - // also need to take special care of interior mutability. - // - // As an optimization, however, if the allocation does not contain any references: we don't - // need to do the walk. It can be costly for big arrays for example (e.g. issue #93215). - let is_walk_needed = |mplace: &MPlaceTy<'tcx>| -> InterpResult<'tcx, bool> { - // ZSTs cannot contain pointers, we can avoid the interning walk. - if mplace.layout.is_zst() { - return Ok(false); - } - - // Now, check whether this allocation could contain references. - // - // Note, this check may sometimes not be cheap, so we only do it when the walk we'd like - // to avoid could be expensive: on the potentially larger types, arrays and slices, - // rather than on all aggregates unconditionally. - if matches!(mplace.layout.ty.kind(), ty::Array(..) | ty::Slice(..)) { - let Some((size, align)) = self.ecx.size_and_align_of_mplace(&mplace)? else { - // We do the walk if we can't determine the size of the mplace: we may be - // dealing with extern types here in the future. - return Ok(true); - }; - - // If there is no provenance in this allocation, it does not contain references - // that point to another allocation, and we can avoid the interning walk. - if let Some(alloc) = self.ecx.get_ptr_alloc(mplace.ptr, size, align)? { - if !alloc.has_provenance() { - return Ok(false); - } - } else { - // We're encountering a ZST here, and can avoid the walk as well. - return Ok(false); - } - } - - // In the general case, we do the walk. - Ok(true) - }; - - // If this allocation contains no references to intern, we avoid the potentially costly - // walk. - // - // We can do this before the checks for interior mutability below, because only references - // are relevant in that situation, and we're checking if there are any here. - if !is_walk_needed(mplace)? { - return Ok(()); - } - - if let Some(def) = mplace.layout.ty.ty_adt_def() { - if def.is_unsafe_cell() { - // We are crossing over an `UnsafeCell`, we can mutate again. This means that - // References we encounter inside here are interned as pointing to mutable - // allocations. - // Remember the `old` value to handle nested `UnsafeCell`. - let old = std::mem::replace(&mut self.inside_unsafe_cell, true); - let walked = self.walk_aggregate(mplace, fields); - self.inside_unsafe_cell = old; - return walked; - } - } - - self.walk_aggregate(mplace, fields) - } - fn visit_value(&mut self, mplace: &MPlaceTy<'tcx>) -> InterpResult<'tcx> { // Handle Reference types, as these are the only types with provenance supported by const eval. // Raw pointers (and boxes) are handled by the `leftover_allocations` logic. @@ -315,7 +246,63 @@ impl<'rt, 'mir, 'tcx: 'mir, M: CompileTimeMachine<'mir, 'tcx, const_eval::Memory } Ok(()) } else { - // Not a reference -- proceed recursively. + // Not a reference. Check if we want to recurse. + let is_walk_needed = |mplace: &MPlaceTy<'tcx>| -> InterpResult<'tcx, bool> { + // ZSTs cannot contain pointers, we can avoid the interning walk. + if mplace.layout.is_zst() { + return Ok(false); + } + + // Now, check whether this allocation could contain references. + // + // Note, this check may sometimes not be cheap, so we only do it when the walk we'd like + // to avoid could be expensive: on the potentially larger types, arrays and slices, + // rather than on all aggregates unconditionally. + if matches!(mplace.layout.ty.kind(), ty::Array(..) | ty::Slice(..)) { + let Some((size, align)) = self.ecx.size_and_align_of_mplace(&mplace)? else { + // We do the walk if we can't determine the size of the mplace: we may be + // dealing with extern types here in the future. + return Ok(true); + }; + + // If there is no provenance in this allocation, it does not contain references + // that point to another allocation, and we can avoid the interning walk. + if let Some(alloc) = self.ecx.get_ptr_alloc(mplace.ptr, size, align)? { + if !alloc.has_provenance() { + return Ok(false); + } + } else { + // We're encountering a ZST here, and can avoid the walk as well. + return Ok(false); + } + } + + // In the general case, we do the walk. + Ok(true) + }; + + // If this allocation contains no references to intern, we avoid the potentially costly + // walk. + // + // We can do this before the checks for interior mutability below, because only references + // are relevant in that situation, and we're checking if there are any here. + if !is_walk_needed(mplace)? { + return Ok(()); + } + + if let Some(def) = mplace.layout.ty.ty_adt_def() { + if def.is_unsafe_cell() { + // We are crossing over an `UnsafeCell`, we can mutate again. This means that + // References we encounter inside here are interned as pointing to mutable + // allocations. + // Remember the `old` value to handle nested `UnsafeCell`. + let old = std::mem::replace(&mut self.inside_unsafe_cell, true); + let walked = self.walk_value(mplace); + self.inside_unsafe_cell = old; + return walked; + } + } + self.walk_value(mplace) } } diff --git a/compiler/rustc_const_eval/src/interpret/intrinsics.rs b/compiler/rustc_const_eval/src/interpret/intrinsics.rs index 04cae23f852a..3f6971682805 100644 --- a/compiler/rustc_const_eval/src/interpret/intrinsics.rs +++ b/compiler/rustc_const_eval/src/interpret/intrinsics.rs @@ -226,8 +226,9 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { } sym::discriminant_value => { let place = self.deref_operand(&args[0])?; - let discr_val = self.read_discriminant(&place.into())?.0; - self.write_scalar(discr_val, dest)?; + let variant = self.read_discriminant(&place.into())?; + let discr = self.discriminant_for_variant(place.layout, variant)?; + self.write_scalar(discr, dest)?; } sym::exact_div => { let l = self.read_immediate(&args[0])?; @@ -425,11 +426,11 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { ); for i in 0..dest_len { - let place = self.mplace_index(&dest, i)?; + let place = self.project_index(&dest, i)?; let value = if i == index { elem.clone() } else { - self.mplace_index(&input, i)?.into() + self.project_index(&input, i)?.into() }; self.copy_op(&value, &place.into(), /*allow_transmute*/ false)?; } @@ -444,7 +445,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { input_len ); self.copy_op( - &self.mplace_index(&input, index)?.into(), + &self.project_index(&input, index)?.into(), dest, /*allow_transmute*/ false, )?; diff --git a/compiler/rustc_const_eval/src/interpret/intrinsics/caller_location.rs b/compiler/rustc_const_eval/src/interpret/intrinsics/caller_location.rs index c4fe293bfacc..44a12751743d 100644 --- a/compiler/rustc_const_eval/src/interpret/intrinsics/caller_location.rs +++ b/compiler/rustc_const_eval/src/interpret/intrinsics/caller_location.rs @@ -101,11 +101,11 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { let location = self.allocate(loc_layout, MemoryKind::CallerLocation).unwrap(); // Initialize fields. - self.write_immediate(file.to_ref(self), &self.mplace_field(&location, 0).unwrap().into()) + self.write_immediate(file.to_ref(self), &self.project_field(&location, 0).unwrap().into()) .expect("writing to memory we just allocated cannot fail"); - self.write_scalar(line, &self.mplace_field(&location, 1).unwrap().into()) + self.write_scalar(line, &self.project_field(&location, 1).unwrap().into()) .expect("writing to memory we just allocated cannot fail"); - self.write_scalar(col, &self.mplace_field(&location, 2).unwrap().into()) + self.write_scalar(col, &self.project_field(&location, 2).unwrap().into()) .expect("writing to memory we just allocated cannot fail"); location diff --git a/compiler/rustc_const_eval/src/interpret/mod.rs b/compiler/rustc_const_eval/src/interpret/mod.rs index f657f954f9c6..7974920bc14d 100644 --- a/compiler/rustc_const_eval/src/interpret/mod.rs +++ b/compiler/rustc_const_eval/src/interpret/mod.rs @@ -26,9 +26,10 @@ pub use self::machine::{compile_time_machine, AllocMap, Machine, MayLeak, StackP pub use self::memory::{AllocKind, AllocRef, AllocRefMut, FnVal, Memory, MemoryKind}; pub use self::operand::{ImmTy, Immediate, OpTy, Operand}; pub use self::place::{MPlaceTy, MemPlace, MemPlaceMeta, Place, PlaceTy}; +pub use self::projection::Projectable; pub use self::terminator::FnArg; pub use self::validity::{CtfeValidationMode, RefTracking}; -pub use self::visitor::{MutValueVisitor, Value, ValueVisitor}; +pub use self::visitor::ValueVisitor; pub(crate) use self::intrinsics::eval_nullary_intrinsic; use eval_context::{from_known_layout, mir_assign_valid_types}; diff --git a/compiler/rustc_const_eval/src/interpret/operand.rs b/compiler/rustc_const_eval/src/interpret/operand.rs index 47383c0eabc3..be39e63ab4f5 100644 --- a/compiler/rustc_const_eval/src/interpret/operand.rs +++ b/compiler/rustc_const_eval/src/interpret/operand.rs @@ -1,6 +1,8 @@ //! Functions concerning immediate values and operands, and reading from operands. //! All high-level functions to read from memory work on operands as sources. +use std::assert_matches::assert_matches; + use either::{Either, Left, Right}; use rustc_hir::def::Namespace; @@ -13,8 +15,8 @@ use rustc_target::abi::{self, Abi, Align, HasDataLayout, Size}; use super::{ alloc_range, from_known_layout, mir_assign_valid_types, AllocId, ConstValue, Frame, GlobalId, - InterpCx, InterpResult, MPlaceTy, Machine, MemPlace, MemPlaceMeta, Place, PlaceTy, Pointer, - Provenance, Scalar, + InterpCx, InterpResult, MPlaceTy, Machine, MemPlace, MemPlaceMeta, PlaceTy, Pointer, + Projectable, Provenance, Scalar, }; /// An `Immediate` represents a single immediate self-contained Rust value. @@ -199,6 +201,20 @@ impl<'tcx, Prov: Provenance> From> for OpTy<'tcx, Prov> { } } +impl<'tcx, Prov: Provenance> From<&'_ ImmTy<'tcx, Prov>> for OpTy<'tcx, Prov> { + #[inline(always)] + fn from(val: &ImmTy<'tcx, Prov>) -> Self { + OpTy { op: Operand::Immediate(val.imm), layout: val.layout, align: None } + } +} + +impl<'tcx, Prov: Provenance> From<&'_ mut ImmTy<'tcx, Prov>> for OpTy<'tcx, Prov> { + #[inline(always)] + fn from(val: &mut ImmTy<'tcx, Prov>) -> Self { + OpTy { op: Operand::Immediate(val.imm), layout: val.layout, align: None } + } +} + impl<'tcx, Prov: Provenance> ImmTy<'tcx, Prov> { #[inline] pub fn from_scalar(val: Scalar, layout: TyAndLayout<'tcx>) -> Self { @@ -240,43 +256,128 @@ impl<'tcx, Prov: Provenance> ImmTy<'tcx, Prov> { let int = self.to_scalar().assert_int(); ConstInt::new(int, self.layout.ty.is_signed(), self.layout.ty.is_ptr_sized_integral()) } + + /// Compute the "sub-immediate" that is located within the `base` at the given offset with the + /// given layout. + // Not called `offset` to avoid confusion with the trait method. + fn offset_(&self, offset: Size, layout: TyAndLayout<'tcx>, cx: &impl HasDataLayout) -> Self { + // This makes several assumptions about what layouts we will encounter; we match what + // codegen does as good as we can (see `extract_field` in `rustc_codegen_ssa/src/mir/operand.rs`). + let inner_val: Immediate<_> = match (**self, self.layout.abi) { + // if the entire value is uninit, then so is the field (can happen in ConstProp) + (Immediate::Uninit, _) => Immediate::Uninit, + // the field contains no information, can be left uninit + _ if layout.is_zst() => Immediate::Uninit, + // some fieldless enum variants can have non-zero size but still `Aggregate` ABI... try + // to detect those here and also give them no data + _ if matches!(layout.abi, Abi::Aggregate { .. }) + && matches!(&layout.fields, abi::FieldsShape::Arbitrary { offsets, .. } if offsets.len() == 0) => + { + Immediate::Uninit + } + // the field covers the entire type + _ if layout.size == self.layout.size => { + assert_eq!(offset.bytes(), 0); + assert!( + match (self.layout.abi, layout.abi) { + (Abi::Scalar(..), Abi::Scalar(..)) => true, + (Abi::ScalarPair(..), Abi::ScalarPair(..)) => true, + _ => false, + }, + "cannot project into {} immediate with equally-sized field {}\nouter ABI: {:#?}\nfield ABI: {:#?}", + self.layout.ty, + layout.ty, + self.layout.abi, + layout.abi, + ); + **self + } + // extract fields from types with `ScalarPair` ABI + (Immediate::ScalarPair(a_val, b_val), Abi::ScalarPair(a, b)) => { + assert!(matches!(layout.abi, Abi::Scalar(..))); + Immediate::from(if offset.bytes() == 0 { + debug_assert_eq!(layout.size, a.size(cx)); + a_val + } else { + debug_assert_eq!(offset, a.size(cx).align_to(b.align(cx).abi)); + debug_assert_eq!(layout.size, b.size(cx)); + b_val + }) + } + // everything else is a bug + _ => bug!("invalid field access on immediate {}, layout {:#?}", self, self.layout), + }; + + ImmTy::from_immediate(inner_val, layout) + } +} + +impl<'mir, 'tcx: 'mir, Prov: Provenance> Projectable<'mir, 'tcx, Prov> for ImmTy<'tcx, Prov> { + #[inline(always)] + fn layout(&self) -> TyAndLayout<'tcx> { + self.layout + } + + fn meta>( + &self, + _ecx: &InterpCx<'mir, 'tcx, M>, + ) -> InterpResult<'tcx, MemPlaceMeta> { + assert!(self.layout.is_sized()); // unsized ImmTy can only exist temporarily and should never reach this here + Ok(MemPlaceMeta::None) + } + + fn offset_with_meta( + &self, + offset: Size, + meta: MemPlaceMeta, + layout: TyAndLayout<'tcx>, + cx: &impl HasDataLayout, + ) -> InterpResult<'tcx, Self> { + assert_matches!(meta, MemPlaceMeta::None); // we can't store this anywhere anyway + Ok(self.offset_(offset, layout, cx)) + } + + fn to_op>( + &self, + _ecx: &InterpCx<'mir, 'tcx, M>, + ) -> InterpResult<'tcx, OpTy<'tcx, M::Provenance>> { + Ok(self.into()) + } } impl<'tcx, Prov: Provenance> OpTy<'tcx, Prov> { - pub fn len(&self, cx: &impl HasDataLayout) -> InterpResult<'tcx, u64> { - if self.layout.is_unsized() { - if matches!(self.op, Operand::Immediate(Immediate::Uninit)) { - // Uninit unsized places shouldn't occur. In the interpreter we have them - // temporarily for unsized arguments before their value is put in; in ConstProp they - // remain uninit and this code can actually be reached. - throw_inval!(UninitUnsizedLocal); + // Provided as inherent method since it doesn't need the `ecx` of `Projectable::meta`. + pub fn meta(&self) -> InterpResult<'tcx, MemPlaceMeta> { + Ok(if self.layout.is_unsized() { + if matches!(self.op, Operand::Immediate(_)) { + // Unsized immediate OpTy cannot occur. We create a MemPlace for all unsized locals during argument passing. + // However, ConstProp doesn't do that, so we can run into this nonsense situation. + throw_inval!(ConstPropNonsense); } // There are no unsized immediates. - self.assert_mem_place().len(cx) + self.assert_mem_place().meta } else { - match self.layout.fields { - abi::FieldsShape::Array { count, .. } => Ok(count), - _ => bug!("len not supported on sized type {:?}", self.layout.ty), - } - } + MemPlaceMeta::None + }) + } +} + +impl<'mir, 'tcx: 'mir, Prov: Provenance + 'static> Projectable<'mir, 'tcx, Prov> + for OpTy<'tcx, Prov> +{ + #[inline(always)] + fn layout(&self) -> TyAndLayout<'tcx> { + self.layout } - /// Replace the layout of this operand. There's basically no sanity check that this makes sense, - /// you better know what you are doing! If this is an immediate, applying the wrong layout can - /// not just lead to invalid data, it can actually *shift the data around* since the offsets of - /// a ScalarPair are entirely determined by the layout, not the data. - pub fn transmute(&self, layout: TyAndLayout<'tcx>) -> Self { - assert_eq!( - self.layout.size, layout.size, - "transmuting with a size change, that doesn't seem right" - ); - OpTy { layout, ..*self } + fn meta>( + &self, + _ecx: &InterpCx<'mir, 'tcx, M>, + ) -> InterpResult<'tcx, MemPlaceMeta> { + self.meta() } - /// Offset the operand in memory (if possible) and change its metadata. - /// - /// This can go wrong very easily if you give the wrong layout for the new place! - pub(super) fn offset_with_meta( + fn offset_with_meta( &self, offset: Size, meta: MemPlaceMeta, @@ -286,28 +387,18 @@ impl<'tcx, Prov: Provenance> OpTy<'tcx, Prov> { match self.as_mplace_or_imm() { Left(mplace) => Ok(mplace.offset_with_meta(offset, meta, layout, cx)?.into()), Right(imm) => { - assert!( - matches!(*imm, Immediate::Uninit), - "Scalar/ScalarPair cannot be offset into" - ); assert!(!meta.has_meta()); // no place to store metadata here // Every part of an uninit is uninit. - Ok(ImmTy::uninit(layout).into()) + Ok(imm.offset(offset, layout, cx)?.into()) } } } - /// Offset the operand in memory (if possible). - /// - /// This can go wrong very easily if you give the wrong layout for the new place! - pub fn offset( + fn to_op>( &self, - offset: Size, - layout: TyAndLayout<'tcx>, - cx: &impl HasDataLayout, - ) -> InterpResult<'tcx, Self> { - assert!(layout.is_sized()); - self.offset_with_meta(offset, MemPlaceMeta::None, layout, cx) + _ecx: &InterpCx<'mir, 'tcx, M>, + ) -> InterpResult<'tcx, OpTy<'tcx, M::Provenance>> { + Ok(self.clone()) } } @@ -497,18 +588,28 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { /// Every place can be read from, so we can turn them into an operand. /// This will definitely return `Indirect` if the place is a `Ptr`, i.e., this /// will never actually read from memory. - #[inline(always)] pub fn place_to_op( &self, place: &PlaceTy<'tcx, M::Provenance>, ) -> InterpResult<'tcx, OpTy<'tcx, M::Provenance>> { - let op = match **place { - Place::Ptr(mplace) => Operand::Indirect(mplace), - Place::Local { frame, local } => { - *self.local_to_op(&self.stack()[frame], local, None)? + match place.as_mplace_or_local() { + Left(mplace) => Ok(mplace.into()), + Right((frame, local, offset)) => { + let base = self.local_to_op(&self.stack()[frame], local, None)?; + let mut field = if let Some(offset) = offset { + // This got offset. We can be sure that the field is sized. + base.offset(offset, place.layout, self)? + } else { + assert_eq!(place.layout, base.layout); + // Unsized cases are possible here since an unsized local will be a + // `Place::Local` until the first projection calls `place_to_op` to extract the + // underlying mplace. + base + }; + field.align = Some(place.align); + Ok(field) } - }; - Ok(OpTy { op, layout: place.layout, align: Some(place.align) }) + } } /// Evaluate a place with the goal of reading from it. This lets us sometimes @@ -525,7 +626,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { let mut op = self.local_to_op(self.frame(), mir_place.local, layout)?; // Using `try_fold` turned out to be bad for performance, hence the loop. for elem in mir_place.projection.iter() { - op = self.operand_projection(&op, elem)? + op = self.project(&op, elem)? } trace!("eval_place_to_op: got {:?}", *op); diff --git a/compiler/rustc_const_eval/src/interpret/operator.rs b/compiler/rustc_const_eval/src/interpret/operator.rs index e04764636cc1..49c3b152e1d7 100644 --- a/compiler/rustc_const_eval/src/interpret/operator.rs +++ b/compiler/rustc_const_eval/src/interpret/operator.rs @@ -38,9 +38,9 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { // With randomized layout, `(int, bool)` might cease to be a `ScalarPair`, so we have to // do a component-wise write here. This code path is slower than the above because // `place_field` will have to `force_allocate` locals here. - let val_field = self.place_field(&dest, 0)?; + let val_field = self.project_field(dest, 0)?; self.write_scalar(val, &val_field)?; - let overflowed_field = self.place_field(&dest, 1)?; + let overflowed_field = self.project_field(dest, 1)?; self.write_scalar(Scalar::from_bool(overflowed), &overflowed_field)?; } Ok(()) diff --git a/compiler/rustc_const_eval/src/interpret/place.rs b/compiler/rustc_const_eval/src/interpret/place.rs index a9b2b43f1e6f..db1239c7136a 100644 --- a/compiler/rustc_const_eval/src/interpret/place.rs +++ b/compiler/rustc_const_eval/src/interpret/place.rs @@ -2,11 +2,14 @@ //! into a place. //! All high-level functions to write to memory work on places as destinations. +use std::assert_matches::assert_matches; + use either::{Either, Left, Right}; use rustc_ast::Mutability; use rustc_index::IndexSlice; use rustc_middle::mir; +use rustc_middle::mir::interpret::PointerArithmetic; use rustc_middle::ty; use rustc_middle::ty::layout::{LayoutOf, TyAndLayout}; use rustc_middle::ty::Ty; @@ -15,7 +18,7 @@ use rustc_target::abi::{self, Abi, Align, FieldIdx, HasDataLayout, Size, FIRST_V use super::{ alloc_range, mir_assign_valid_types, AllocId, AllocRef, AllocRefMut, CheckInAllocMsg, ConstAlloc, ImmTy, Immediate, InterpCx, InterpResult, Machine, MemoryKind, OpTy, Operand, - Pointer, Provenance, Scalar, + Pointer, Projectable, Provenance, Scalar, }; #[derive(Copy, Clone, Hash, PartialEq, Eq, Debug)] @@ -44,6 +47,27 @@ impl MemPlaceMeta { Self::None => false, } } + + pub(crate) fn len<'tcx>( + &self, + layout: TyAndLayout<'tcx>, + cx: &impl HasDataLayout, + ) -> InterpResult<'tcx, u64> { + if layout.is_unsized() { + // We need to consult `meta` metadata + match layout.ty.kind() { + ty::Slice(..) | ty::Str => self.unwrap_meta().to_target_usize(cx), + _ => bug!("len not supported on unsized type {:?}", layout.ty), + } + } else { + // Go through the layout. There are lots of types that support a length, + // e.g., SIMD types. (But not all repr(simd) types even have FieldsShape::Array!) + match layout.fields { + abi::FieldsShape::Array { count, .. } => Ok(count), + _ => bug!("len not supported on sized type {:?}", layout.ty), + } + } + } } #[derive(Copy, Clone, Hash, PartialEq, Eq, Debug)] @@ -73,9 +97,13 @@ pub enum Place { /// A place referring to a value allocated in the `Memory` system. Ptr(MemPlace), - /// To support alloc-free locals, we are able to write directly to a local. + /// To support alloc-free locals, we are able to write directly to a local. The offset indicates + /// where in the local this place is located; if it is `None`, no projection has been applied. + /// Such projections are meaningful even if the offset is 0, since they can change layouts. /// (Without that optimization, we'd just always be a `MemPlace`.) - Local { frame: usize, local: mir::Local }, + /// Note that this only stores the frame index, not the thread this frame belongs to -- that is + /// implicit. This means a `Place` must never be moved across interpreter thread boundaries! + Local { frame: usize, local: mir::Local, offset: Option }, } #[derive(Clone, Debug)] @@ -132,6 +160,11 @@ impl MemPlace { MemPlace { ptr, meta: MemPlaceMeta::None } } + #[inline(always)] + pub fn from_ptr_with_meta(ptr: Pointer>, meta: MemPlaceMeta) -> Self { + MemPlace { ptr, meta } + } + /// Adjust the provenance of the main pointer (metadata is unaffected). pub fn map_provenance(self, f: impl FnOnce(Option) -> Option) -> Self { MemPlace { ptr: self.ptr.map_provenance(f), ..self } @@ -150,7 +183,8 @@ impl MemPlace { } #[inline] - pub(super) fn offset_with_meta<'tcx>( + // Not called `offset_with_meta` to avoid confusion with the trait method. + fn offset_with_meta_<'tcx>( self, offset: Size, meta: MemPlaceMeta, @@ -164,19 +198,6 @@ impl MemPlace { } } -impl Place { - /// Asserts that this points to some local variable. - /// Returns the frame idx and the variable idx. - #[inline] - #[cfg_attr(debug_assertions, track_caller)] // only in debug builds due to perf (see #98980) - pub fn assert_local(&self) -> (usize, mir::Local) { - match self { - Place::Local { frame, local } => (*frame, *local), - _ => bug!("assert_local: expected Place::Local, got {:?}", self), - } - } -} - impl<'tcx, Prov: Provenance> MPlaceTy<'tcx, Prov> { /// Produces a MemPlace that works for ZST but nothing else. /// Conceptually this is a new allocation, but it doesn't actually create an allocation so you @@ -189,37 +210,6 @@ impl<'tcx, Prov: Provenance> MPlaceTy<'tcx, Prov> { MPlaceTy { mplace: MemPlace { ptr, meta: MemPlaceMeta::None }, layout, align } } - /// Offset the place in memory and change its metadata. - /// - /// This can go wrong very easily if you give the wrong layout for the new place! - #[inline] - pub(crate) fn offset_with_meta( - &self, - offset: Size, - meta: MemPlaceMeta, - layout: TyAndLayout<'tcx>, - cx: &impl HasDataLayout, - ) -> InterpResult<'tcx, Self> { - Ok(MPlaceTy { - mplace: self.mplace.offset_with_meta(offset, meta, cx)?, - align: self.align.restrict_for_offset(offset), - layout, - }) - } - - /// Offset the place in memory. - /// - /// This can go wrong very easily if you give the wrong layout for the new place! - pub fn offset( - &self, - offset: Size, - layout: TyAndLayout<'tcx>, - cx: &impl HasDataLayout, - ) -> InterpResult<'tcx, Self> { - assert!(layout.is_sized()); - self.offset_with_meta(offset, MemPlaceMeta::None, layout, cx) - } - #[inline] pub fn from_aligned_ptr(ptr: Pointer>, layout: TyAndLayout<'tcx>) -> Self { MPlaceTy { mplace: MemPlace::from_ptr(ptr), layout, align: layout.align.abi } @@ -231,28 +221,48 @@ impl<'tcx, Prov: Provenance> MPlaceTy<'tcx, Prov> { layout: TyAndLayout<'tcx>, meta: MemPlaceMeta, ) -> Self { - let mut mplace = MemPlace::from_ptr(ptr); - mplace.meta = meta; + MPlaceTy { + mplace: MemPlace::from_ptr_with_meta(ptr, meta), + layout, + align: layout.align.abi, + } + } +} - MPlaceTy { mplace, layout, align: layout.align.abi } +impl<'mir, 'tcx: 'mir, Prov: Provenance + 'static> Projectable<'mir, 'tcx, Prov> + for MPlaceTy<'tcx, Prov> +{ + #[inline(always)] + fn layout(&self) -> TyAndLayout<'tcx> { + self.layout } - #[inline] - pub(crate) fn len(&self, cx: &impl HasDataLayout) -> InterpResult<'tcx, u64> { - if self.layout.is_unsized() { - // We need to consult `meta` metadata - match self.layout.ty.kind() { - ty::Slice(..) | ty::Str => self.mplace.meta.unwrap_meta().to_target_usize(cx), - _ => bug!("len not supported on unsized type {:?}", self.layout.ty), - } - } else { - // Go through the layout. There are lots of types that support a length, - // e.g., SIMD types. (But not all repr(simd) types even have FieldsShape::Array!) - match self.layout.fields { - abi::FieldsShape::Array { count, .. } => Ok(count), - _ => bug!("len not supported on sized type {:?}", self.layout.ty), - } - } + fn meta>( + &self, + _ecx: &InterpCx<'mir, 'tcx, M>, + ) -> InterpResult<'tcx, MemPlaceMeta> { + Ok(self.meta) + } + + fn offset_with_meta( + &self, + offset: Size, + meta: MemPlaceMeta, + layout: TyAndLayout<'tcx>, + cx: &impl HasDataLayout, + ) -> InterpResult<'tcx, Self> { + Ok(MPlaceTy { + mplace: self.mplace.offset_with_meta_(offset, meta, cx)?, + align: self.align.restrict_for_offset(offset), + layout, + }) + } + + fn to_op>( + &self, + _ecx: &InterpCx<'mir, 'tcx, M>, + ) -> InterpResult<'tcx, OpTy<'tcx, M::Provenance>> { + Ok(self.into()) } } @@ -280,13 +290,15 @@ impl<'tcx, Prov: Provenance> OpTy<'tcx, Prov> { } } -impl<'tcx, Prov: Provenance> PlaceTy<'tcx, Prov> { +impl<'tcx, Prov: Provenance + 'static> PlaceTy<'tcx, Prov> { /// A place is either an mplace or some local. #[inline] - pub fn as_mplace_or_local(&self) -> Either, (usize, mir::Local)> { + pub fn as_mplace_or_local( + &self, + ) -> Either, (usize, mir::Local, Option)> { match **self { Place::Ptr(mplace) => Left(MPlaceTy { mplace, layout: self.layout, align: self.align }), - Place::Local { frame, local } => Right((frame, local)), + Place::Local { frame, local, offset } => Right((frame, local, offset)), } } @@ -302,12 +314,76 @@ impl<'tcx, Prov: Provenance> PlaceTy<'tcx, Prov> { } } +impl<'mir, 'tcx: 'mir, Prov: Provenance + 'static> Projectable<'mir, 'tcx, Prov> + for PlaceTy<'tcx, Prov> +{ + #[inline(always)] + fn layout(&self) -> TyAndLayout<'tcx> { + self.layout + } + + fn meta>( + &self, + ecx: &InterpCx<'mir, 'tcx, M>, + ) -> InterpResult<'tcx, MemPlaceMeta> { + ecx.place_meta(self) + } + + fn offset_with_meta( + &self, + offset: Size, + meta: MemPlaceMeta, + layout: TyAndLayout<'tcx>, + cx: &impl HasDataLayout, + ) -> InterpResult<'tcx, Self> { + Ok(match self.as_mplace_or_local() { + Left(mplace) => mplace.offset_with_meta(offset, meta, layout, cx)?.into(), + Right((frame, local, old_offset)) => { + assert_matches!(meta, MemPlaceMeta::None); // we couldn't store it anyway... + let new_offset = cx + .data_layout() + .offset(old_offset.unwrap_or(Size::ZERO).bytes(), offset.bytes())?; + PlaceTy { + place: Place::Local { + frame, + local, + offset: Some(Size::from_bytes(new_offset)), + }, + align: self.align.restrict_for_offset(offset), + layout, + } + } + }) + } + + fn to_op>( + &self, + ecx: &InterpCx<'mir, 'tcx, M>, + ) -> InterpResult<'tcx, OpTy<'tcx, M::Provenance>> { + ecx.place_to_op(self) + } +} + // FIXME: Working around https://github.com/rust-lang/rust/issues/54385 impl<'mir, 'tcx: 'mir, Prov, M> InterpCx<'mir, 'tcx, M> where Prov: Provenance + 'static, M: Machine<'mir, 'tcx, Provenance = Prov>, { + /// Get the metadata of the given place. + pub(super) fn place_meta( + &self, + place: &PlaceTy<'tcx, M::Provenance>, + ) -> InterpResult<'tcx, MemPlaceMeta> { + if place.layout.is_unsized() { + // For `Place::Local`, the metadata is stored with the local, not the place. So we have + // to look that up first. + self.place_to_op(place)?.meta() + } else { + Ok(MemPlaceMeta::None) + } + } + /// Take a value, which represents a (thin or wide) reference, and make it a place. /// Alignment is just based on the type. This is the inverse of `MemPlace::to_ref()`. /// @@ -327,11 +403,9 @@ where Immediate::Uninit => throw_ub!(InvalidUninitBytes(None)), }; - let mplace = MemPlace { ptr: ptr.to_pointer(self)?, meta }; // `ref_to_mplace` is called on raw pointers even if they don't actually get dereferenced; // we hence can't call `size_and_align_of` since that asserts more validity than we want. - let align = layout.align.abi; - Ok(MPlaceTy { mplace, layout, align }) + Ok(MPlaceTy::from_aligned_ptr_with_meta(ptr.to_pointer(self)?, layout, meta)) } /// Take an operand, representing a pointer, and dereference it to a place. @@ -422,7 +496,7 @@ where local: mir::Local, ) -> InterpResult<'tcx, PlaceTy<'tcx, M::Provenance>> { let layout = self.layout_of_local(&self.stack()[frame], local, None)?; - let place = Place::Local { frame, local }; + let place = Place::Local { frame, local, offset: None }; Ok(PlaceTy { place, layout, align: layout.align.abi }) } @@ -430,13 +504,13 @@ where /// place; for reading, a more efficient alternative is `eval_place_to_op`. #[instrument(skip(self), level = "debug")] pub fn eval_place( - &mut self, + &self, mir_place: mir::Place<'tcx>, ) -> InterpResult<'tcx, PlaceTy<'tcx, M::Provenance>> { let mut place = self.local_to_place(self.frame_idx(), mir_place.local)?; // Using `try_fold` turned out to be bad for performance, hence the loop. for elem in mir_place.projection.iter() { - place = self.place_projection(&place, elem)? + place = self.project(&place, elem)? } trace!("{:?}", self.dump_place(place.place)); @@ -503,22 +577,54 @@ where src: Immediate, dest: &PlaceTy<'tcx, M::Provenance>, ) -> InterpResult<'tcx> { - assert!(dest.layout.is_sized(), "Cannot write unsized data"); + assert!(dest.layout.is_sized(), "Cannot write unsized immediate data"); trace!("write_immediate: {:?} <- {:?}: {}", *dest, src, dest.layout.ty); // See if we can avoid an allocation. This is the counterpart to `read_immediate_raw`, // but not factored as a separate function. let mplace = match dest.place { - Place::Local { frame, local } => { - match M::access_local_mut(self, frame, local)? { - Operand::Immediate(local) => { - // Local can be updated in-place. - *local = src; - return Ok(()); - } - Operand::Indirect(mplace) => { - // The local is in memory, go on below. - *mplace + Place::Local { frame, local, offset } => { + if offset.is_some() { + // This has been projected to a part of this local. We could have complicated + // logic to still keep this local as an `Operand`... but it's much easier to + // just fall back to the indirect path. + *self.force_allocation(dest)? + } else { + match M::access_local_mut(self, frame, local)? { + Operand::Immediate(local_val) => { + // Local can be updated in-place. + *local_val = src; + // Double-check that the value we are storing and the local fit to each other. + // (*After* doing the update for borrow checker reasons.) + if cfg!(debug_assertions) { + let local_layout = + self.layout_of_local(&self.stack()[frame], local, None)?; + match (src, local_layout.abi) { + (Immediate::Scalar(scalar), Abi::Scalar(s)) => { + assert_eq!(scalar.size(), s.size(self)) + } + ( + Immediate::ScalarPair(a_val, b_val), + Abi::ScalarPair(a, b), + ) => { + assert_eq!(a_val.size(), a.size(self)); + assert_eq!(b_val.size(), b.size(self)); + } + (Immediate::Uninit, _) => {} + (src, abi) => { + bug!( + "value {src:?} cannot be written into local with type {} (ABI {abi:?})", + local_layout.ty + ) + } + }; + } + return Ok(()); + } + Operand::Indirect(mplace) => { + // The local is in memory, go on below. + *mplace + } } } } @@ -593,15 +699,23 @@ where pub fn write_uninit(&mut self, dest: &PlaceTy<'tcx, M::Provenance>) -> InterpResult<'tcx> { let mplace = match dest.as_mplace_or_local() { Left(mplace) => mplace, - Right((frame, local)) => { - match M::access_local_mut(self, frame, local)? { - Operand::Immediate(local) => { - *local = Immediate::Uninit; - return Ok(()); - } - Operand::Indirect(mplace) => { - // The local is in memory, go on below. - MPlaceTy { mplace: *mplace, layout: dest.layout, align: dest.align } + Right((frame, local, offset)) => { + if offset.is_some() { + // This has been projected to a part of this local. We could have complicated + // logic to still keep this local as an `Operand`... but it's much easier to + // just fall back to the indirect path. + // FIXME: share the logic with `write_immediate_no_validate`. + self.force_allocation(dest)? + } else { + match M::access_local_mut(self, frame, local)? { + Operand::Immediate(local) => { + *local = Immediate::Uninit; + return Ok(()); + } + Operand::Indirect(mplace) => { + // The local is in memory, go on below. + MPlaceTy { mplace: *mplace, layout: dest.layout, align: dest.align } + } } } } @@ -728,8 +842,8 @@ where place: &PlaceTy<'tcx, M::Provenance>, ) -> InterpResult<'tcx, MPlaceTy<'tcx, M::Provenance>> { let mplace = match place.place { - Place::Local { frame, local } => { - match M::access_local_mut(self, frame, local)? { + Place::Local { frame, local, offset } => { + let whole_local = match M::access_local_mut(self, frame, local)? { &mut Operand::Immediate(local_val) => { // We need to make an allocation. @@ -742,10 +856,11 @@ where throw_unsup_format!("unsized locals are not supported"); } let mplace = *self.allocate(local_layout, MemoryKind::Stack)?; + // Preserve old value. (As an optimization, we can skip this if it was uninit.) if !matches!(local_val, Immediate::Uninit) { - // Preserve old value. (As an optimization, we can skip this if it was uninit.) - // We don't have to validate as we can assume the local - // was already valid for its type. + // We don't have to validate as we can assume the local was already + // valid for its type. We must not use any part of `place` here, that + // could be a projection to a part of the local! self.write_immediate_to_mplace_no_validate( local_val, local_layout, @@ -753,18 +868,25 @@ where mplace, )?; } - // Now we can call `access_mut` again, asserting it goes well, - // and actually overwrite things. + // Now we can call `access_mut` again, asserting it goes well, and actually + // overwrite things. This points to the entire allocation, not just the part + // the place refers to, i.e. we do this before we apply `offset`. *M::access_local_mut(self, frame, local).unwrap() = Operand::Indirect(mplace); mplace } &mut Operand::Indirect(mplace) => mplace, // this already was an indirect local + }; + if let Some(offset) = offset { + whole_local.offset_with_meta_(offset, MemPlaceMeta::None, self)? + } else { + // Preserve wide place metadata, do not call `offset`. + whole_local } } Place::Ptr(mplace) => mplace, }; - // Return with the original layout, so that the caller can go on + // Return with the original layout and align, so that the caller can go on Ok(MPlaceTy { mplace, layout: place.layout, align: place.align }) } @@ -809,7 +931,7 @@ where self.write_uninit(&dest)?; let (variant_index, variant_dest, active_field_index) = match *kind { mir::AggregateKind::Adt(_, variant_index, _, _, active_field_index) => { - let variant_dest = self.place_downcast(&dest, variant_index)?; + let variant_dest = self.project_downcast(dest, variant_index)?; (variant_index, variant_dest, active_field_index) } _ => (FIRST_VARIANT, dest.clone(), None), @@ -819,7 +941,7 @@ where } for (field_index, operand) in operands.iter_enumerated() { let field_index = active_field_index.unwrap_or(field_index); - let field_dest = self.place_field(&variant_dest, field_index.as_usize())?; + let field_dest = self.project_field(&variant_dest, field_index.as_usize())?; let op = self.eval_operand(operand, Some(field_dest.layout))?; self.copy_op(&op, &field_dest, /*allow_transmute*/ false)?; } @@ -859,22 +981,24 @@ where Ok((mplace, vtable)) } - /// Turn an operand with a `dyn* Trait` type into an operand with the actual dynamic type. - /// Aso returns the vtable. - pub(super) fn unpack_dyn_star( + /// Turn a `dyn* Trait` type into an value with the actual dynamic type. + /// Also returns the vtable. + pub(super) fn unpack_dyn_star>( &self, - op: &OpTy<'tcx, M::Provenance>, - ) -> InterpResult<'tcx, (OpTy<'tcx, M::Provenance>, Pointer>)> { + val: &P, + ) -> InterpResult<'tcx, (P, Pointer>)> { assert!( - matches!(op.layout.ty.kind(), ty::Dynamic(_, _, ty::DynStar)), + matches!(val.layout().ty.kind(), ty::Dynamic(_, _, ty::DynStar)), "`unpack_dyn_star` only makes sense on `dyn*` types" ); - let data = self.operand_field(&op, 0)?; - let vtable = self.operand_field(&op, 1)?; - let vtable = self.read_pointer(&vtable)?; + let data = self.project_field(val, 0)?; + let vtable = self.project_field(val, 1)?; + let vtable = self.read_pointer(&vtable.to_op(self)?)?; let (ty, _) = self.get_ptr_vtable(vtable)?; let layout = self.layout_of(ty)?; - let data = data.transmute(layout); + // `data` is already the right thing but has the wrong type. So we transmute it, by + // projecting with offset 0. + let data = data.transmute(layout, self)?; Ok((data, vtable)) } } diff --git a/compiler/rustc_const_eval/src/interpret/projection.rs b/compiler/rustc_const_eval/src/interpret/projection.rs index d7d31fe18875..ddcbc8350aae 100644 --- a/compiler/rustc_const_eval/src/interpret/projection.rs +++ b/compiler/rustc_const_eval/src/interpret/projection.rs @@ -7,18 +7,71 @@ //! but we still need to do bounds checking and adjust the layout. To not duplicate that with MPlaceTy, we actually //! implement the logic on OpTy, and MPlaceTy calls that. -use either::{Left, Right}; - use rustc_middle::mir; use rustc_middle::ty; -use rustc_middle::ty::layout::LayoutOf; +use rustc_middle::ty::layout::{LayoutOf, TyAndLayout}; use rustc_middle::ty::Ty; -use rustc_target::abi::{self, Abi, VariantIdx}; +use rustc_middle::ty::TyCtxt; +use rustc_target::abi::HasDataLayout; +use rustc_target::abi::Size; +use rustc_target::abi::{self, VariantIdx}; -use super::{ - ImmTy, Immediate, InterpCx, InterpResult, MPlaceTy, Machine, MemPlaceMeta, OpTy, PlaceTy, - Provenance, Scalar, -}; +use super::MPlaceTy; +use super::{InterpCx, InterpResult, Machine, MemPlaceMeta, OpTy, Provenance, Scalar}; + +/// A thing that we can project into, and that has a layout. +pub trait Projectable<'mir, 'tcx: 'mir, Prov: Provenance>: Sized { + /// Get the layout. + fn layout(&self) -> TyAndLayout<'tcx>; + + /// Get the metadata of a wide value. + fn meta>( + &self, + ecx: &InterpCx<'mir, 'tcx, M>, + ) -> InterpResult<'tcx, MemPlaceMeta>; + + fn len>( + &self, + ecx: &InterpCx<'mir, 'tcx, M>, + ) -> InterpResult<'tcx, u64> { + self.meta(ecx)?.len(self.layout(), ecx) + } + + /// Offset the value by the given amount, replacing the layout and metadata. + fn offset_with_meta( + &self, + offset: Size, + meta: MemPlaceMeta, + layout: TyAndLayout<'tcx>, + cx: &impl HasDataLayout, + ) -> InterpResult<'tcx, Self>; + + fn offset( + &self, + offset: Size, + layout: TyAndLayout<'tcx>, + cx: &impl HasDataLayout, + ) -> InterpResult<'tcx, Self> { + assert!(layout.is_sized()); + self.offset_with_meta(offset, MemPlaceMeta::None, layout, cx) + } + + fn transmute( + &self, + layout: TyAndLayout<'tcx>, + cx: &impl HasDataLayout, + ) -> InterpResult<'tcx, Self> { + assert_eq!(self.layout().size, layout.size); + self.offset_with_meta(Size::ZERO, MemPlaceMeta::None, layout, cx) + } + + /// Convert this to an `OpTy`. This might be an irreversible transformation, but is useful for + /// reading from this thing. + fn to_op>( + &self, + ecx: &InterpCx<'mir, 'tcx, M>, + ) -> InterpResult<'tcx, OpTy<'tcx, M::Provenance>>; +} // FIXME: Working around https://github.com/rust-lang/rust/issues/54385 impl<'mir, 'tcx: 'mir, Prov, M> InterpCx<'mir, 'tcx, M> @@ -26,167 +79,83 @@ where Prov: Provenance + 'static, M: Machine<'mir, 'tcx, Provenance = Prov>, { - //# Field access - /// Offset a pointer to project to a field of a struct/union. Unlike `place_field`, this is /// always possible without allocating, so it can take `&self`. Also return the field's layout. - /// This supports both struct and array fields. + /// This supports both struct and array fields, but not slices! /// /// This also works for arrays, but then the `usize` index type is restricting. /// For indexing into arrays, use `mplace_index`. - pub fn mplace_field( + pub fn project_field>( &self, - base: &MPlaceTy<'tcx, M::Provenance>, + base: &P, field: usize, - ) -> InterpResult<'tcx, MPlaceTy<'tcx, M::Provenance>> { - let offset = base.layout.fields.offset(field); - let field_layout = base.layout.field(self, field); + ) -> InterpResult<'tcx, P> { + // Slices nominally have length 0, so they will panic somewhere in `fields.offset`. + debug_assert!( + !matches!(base.layout().ty.kind(), ty::Slice(..)), + "`field` projection called on a slice -- call `index` projection instead" + ); + let offset = base.layout().fields.offset(field); + let field_layout = base.layout().field(self, field); // Offset may need adjustment for unsized fields. let (meta, offset) = if field_layout.is_unsized() { + if base.layout().is_sized() { + // An unsized field of a sized type? Sure... + // But const-prop actually feeds us such nonsense MIR! + throw_inval!(ConstPropNonsense); + } + let base_meta = base.meta(self)?; // Re-use parent metadata to determine dynamic field layout. // With custom DSTS, this *will* execute user-defined code, but the same // happens at run-time so that's okay. - match self.size_and_align_of(&base.meta, &field_layout)? { - Some((_, align)) => (base.meta, offset.align_to(align)), + match self.size_and_align_of(&base_meta, &field_layout)? { + Some((_, align)) => (base_meta, offset.align_to(align)), None => { // For unsized types with an extern type tail we perform no adjustments. // NOTE: keep this in sync with `PlaceRef::project_field` in the codegen backend. - assert!(matches!(base.meta, MemPlaceMeta::None)); - (base.meta, offset) + assert!(matches!(base_meta, MemPlaceMeta::None)); + (base_meta, offset) } } } else { - // base.meta could be present; we might be accessing a sized field of an unsized + // base_meta could be present; we might be accessing a sized field of an unsized // struct. (MemPlaceMeta::None, offset) }; - // We do not look at `base.layout.align` nor `field_layout.align`, unlike - // codegen -- mostly to see if we can get away with that base.offset_with_meta(offset, meta, field_layout, self) } - /// Gets the place of a field inside the place, and also the field's type. - /// Just a convenience function, but used quite a bit. - /// This is the only projection that might have a side-effect: We cannot project - /// into the field of a local `ScalarPair`, we have to first allocate it. - pub fn place_field( - &mut self, - base: &PlaceTy<'tcx, M::Provenance>, - field: usize, - ) -> InterpResult<'tcx, PlaceTy<'tcx, M::Provenance>> { - // FIXME: We could try to be smarter and avoid allocation for fields that span the - // entire place. - let base = self.force_allocation(base)?; - Ok(self.mplace_field(&base, field)?.into()) - } - - pub fn operand_field( + /// Downcasting to an enum variant. + pub fn project_downcast>( &self, - base: &OpTy<'tcx, M::Provenance>, - field: usize, - ) -> InterpResult<'tcx, OpTy<'tcx, M::Provenance>> { - let base = match base.as_mplace_or_imm() { - Left(ref mplace) => { - // We can reuse the mplace field computation logic for indirect operands. - let field = self.mplace_field(mplace, field)?; - return Ok(field.into()); - } - Right(value) => value, - }; - - let field_layout = base.layout.field(self, field); - let offset = base.layout.fields.offset(field); - // This makes several assumptions about what layouts we will encounter; we match what - // codegen does as good as we can (see `extract_field` in `rustc_codegen_ssa/src/mir/operand.rs`). - let field_val: Immediate<_> = match (*base, base.layout.abi) { - // if the entire value is uninit, then so is the field (can happen in ConstProp) - (Immediate::Uninit, _) => Immediate::Uninit, - // the field contains no information, can be left uninit - _ if field_layout.is_zst() => Immediate::Uninit, - // the field covers the entire type - _ if field_layout.size == base.layout.size => { - assert!(match (base.layout.abi, field_layout.abi) { - (Abi::Scalar(..), Abi::Scalar(..)) => true, - (Abi::ScalarPair(..), Abi::ScalarPair(..)) => true, - _ => false, - }); - assert!(offset.bytes() == 0); - *base - } - // extract fields from types with `ScalarPair` ABI - (Immediate::ScalarPair(a_val, b_val), Abi::ScalarPair(a, b)) => { - assert!(matches!(field_layout.abi, Abi::Scalar(..))); - Immediate::from(if offset.bytes() == 0 { - debug_assert_eq!(field_layout.size, a.size(self)); - a_val - } else { - debug_assert_eq!(offset, a.size(self).align_to(b.align(self).abi)); - debug_assert_eq!(field_layout.size, b.size(self)); - b_val - }) - } - // everything else is a bug - _ => span_bug!( - self.cur_span(), - "invalid field access on immediate {}, layout {:#?}", - base, - base.layout - ), - }; - - Ok(ImmTy::from_immediate(field_val, field_layout).into()) - } - - //# Downcasting - - pub fn mplace_downcast( - &self, - base: &MPlaceTy<'tcx, M::Provenance>, + base: &P, variant: VariantIdx, - ) -> InterpResult<'tcx, MPlaceTy<'tcx, M::Provenance>> { + ) -> InterpResult<'tcx, P> { + assert!(!base.meta(self)?.has_meta()); // Downcasts only change the layout. // (In particular, no check about whether this is even the active variant -- that's by design, // see https://github.com/rust-lang/rust/issues/93688#issuecomment-1032929496.) - assert!(!base.meta.has_meta()); - let mut base = *base; - base.layout = base.layout.for_variant(self, variant); - Ok(base) + // So we just "offset" by 0. + let layout = base.layout().for_variant(self, variant); + if layout.abi.is_uninhabited() { + // `read_discriminant` should have excluded uninhabited variants... but ConstProp calls + // us on dead code. + throw_inval!(ConstPropNonsense) + } + // This cannot be `transmute` as variants *can* have a smaller size than the entire enum. + base.offset(Size::ZERO, layout, self) } - pub fn place_downcast( + /// Compute the offset and field layout for accessing the given index. + pub fn project_index>( &self, - base: &PlaceTy<'tcx, M::Provenance>, - variant: VariantIdx, - ) -> InterpResult<'tcx, PlaceTy<'tcx, M::Provenance>> { - // Downcast just changes the layout - let mut base = base.clone(); - base.layout = base.layout.for_variant(self, variant); - Ok(base) - } - - pub fn operand_downcast( - &self, - base: &OpTy<'tcx, M::Provenance>, - variant: VariantIdx, - ) -> InterpResult<'tcx, OpTy<'tcx, M::Provenance>> { - // Downcast just changes the layout - let mut base = base.clone(); - base.layout = base.layout.for_variant(self, variant); - Ok(base) - } - - //# Slice indexing - - #[inline(always)] - pub fn operand_index( - &self, - base: &OpTy<'tcx, M::Provenance>, + base: &P, index: u64, - ) -> InterpResult<'tcx, OpTy<'tcx, M::Provenance>> { + ) -> InterpResult<'tcx, P> { // Not using the layout method because we want to compute on u64 - match base.layout.fields { + let (offset, field_layout) = match base.layout().fields { abi::FieldsShape::Array { stride, count: _ } => { // `count` is nonsense for slices, use the dynamic length instead. let len = base.len(self)?; @@ -196,63 +165,26 @@ where } let offset = stride * index; // `Size` multiplication // All fields have the same layout. - let field_layout = base.layout.field(self, 0); - base.offset(offset, field_layout, self) + let field_layout = base.layout().field(self, 0); + (offset, field_layout) } _ => span_bug!( self.cur_span(), "`mplace_index` called on non-array type {:?}", - base.layout.ty + base.layout().ty ), - } - } - - /// Iterates over all fields of an array. Much more efficient than doing the - /// same by repeatedly calling `operand_index`. - pub fn operand_array_fields<'a>( - &self, - base: &'a OpTy<'tcx, Prov>, - ) -> InterpResult<'tcx, impl Iterator>> + 'a> { - let len = base.len(self)?; // also asserts that we have a type where this makes sense - let abi::FieldsShape::Array { stride, .. } = base.layout.fields else { - span_bug!(self.cur_span(), "operand_array_fields: expected an array layout"); }; - let field_layout = base.layout.field(self, 0); - let dl = &self.tcx.data_layout; - // `Size` multiplication - Ok((0..len).map(move |i| base.offset(stride * i, field_layout, dl))) + + base.offset(offset, field_layout, self) } - /// Index into an array. - pub fn mplace_index( + fn project_constant_index>( &self, - base: &MPlaceTy<'tcx, M::Provenance>, - index: u64, - ) -> InterpResult<'tcx, MPlaceTy<'tcx, M::Provenance>> { - Ok(self.operand_index(&base.into(), index)?.assert_mem_place()) - } - - pub fn place_index( - &mut self, - base: &PlaceTy<'tcx, M::Provenance>, - index: u64, - ) -> InterpResult<'tcx, PlaceTy<'tcx, M::Provenance>> { - // There's not a lot we can do here, since we cannot have a place to a part of a local. If - // we are accessing the only element of a 1-element array, it's still the entire local... - // that doesn't seem worth it. - let base = self.force_allocation(base)?; - Ok(self.mplace_index(&base, index)?.into()) - } - - //# ConstantIndex support - - fn operand_constant_index( - &self, - base: &OpTy<'tcx, M::Provenance>, + base: &P, offset: u64, min_length: u64, from_end: bool, - ) -> InterpResult<'tcx, OpTy<'tcx, M::Provenance>> { + ) -> InterpResult<'tcx, P> { let n = base.len(self)?; if n < min_length { // This can only be reached in ConstProp and non-rustc-MIR. @@ -267,32 +199,38 @@ where offset }; - self.operand_index(base, index) + self.project_index(base, index) } - fn place_constant_index( - &mut self, - base: &PlaceTy<'tcx, M::Provenance>, - offset: u64, - min_length: u64, - from_end: bool, - ) -> InterpResult<'tcx, PlaceTy<'tcx, M::Provenance>> { - let base = self.force_allocation(base)?; - Ok(self - .operand_constant_index(&base.into(), offset, min_length, from_end)? - .assert_mem_place() - .into()) - } - - //# Subslicing - - fn operand_subslice( + /// Iterates over all fields of an array. Much more efficient than doing the + /// same by repeatedly calling `operand_index`. + pub fn project_array_fields<'a, P: Projectable<'mir, 'tcx, M::Provenance>>( &self, - base: &OpTy<'tcx, M::Provenance>, + base: &'a P, + ) -> InterpResult<'tcx, impl Iterator> + 'a> + where + 'tcx: 'a, + { + let abi::FieldsShape::Array { stride, .. } = base.layout().fields else { + span_bug!(self.cur_span(), "operand_array_fields: expected an array layout"); + }; + let len = base.len(self)?; + let field_layout = base.layout().field(self, 0); + let tcx: TyCtxt<'tcx> = *self.tcx; + // `Size` multiplication + Ok((0..len).map(move |i| { + base.offset_with_meta(stride * i, MemPlaceMeta::None, field_layout, &tcx) + })) + } + + /// Subslicing + fn project_subslice>( + &self, + base: &P, from: u64, to: u64, from_end: bool, - ) -> InterpResult<'tcx, OpTy<'tcx, M::Provenance>> { + ) -> InterpResult<'tcx, P> { let len = base.len(self)?; // also asserts that we have a type where this makes sense let actual_to = if from_end { if from.checked_add(to).map_or(true, |to| to > len) { @@ -306,16 +244,20 @@ where // Not using layout method because that works with usize, and does not work with slices // (that have count 0 in their layout). - let from_offset = match base.layout.fields { + let from_offset = match base.layout().fields { abi::FieldsShape::Array { stride, .. } => stride * from, // `Size` multiplication is checked _ => { - span_bug!(self.cur_span(), "unexpected layout of index access: {:#?}", base.layout) + span_bug!( + self.cur_span(), + "unexpected layout of index access: {:#?}", + base.layout() + ) } }; // Compute meta and new layout let inner_len = actual_to.checked_sub(from).unwrap(); - let (meta, ty) = match base.layout.ty.kind() { + let (meta, ty) = match base.layout().ty.kind() { // It is not nice to match on the type, but that seems to be the only way to // implement this. ty::Array(inner, _) => { @@ -323,85 +265,45 @@ where } ty::Slice(..) => { let len = Scalar::from_target_usize(inner_len, self); - (MemPlaceMeta::Meta(len), base.layout.ty) + (MemPlaceMeta::Meta(len), base.layout().ty) } _ => { - span_bug!(self.cur_span(), "cannot subslice non-array type: `{:?}`", base.layout.ty) + span_bug!( + self.cur_span(), + "cannot subslice non-array type: `{:?}`", + base.layout().ty + ) } }; let layout = self.layout_of(ty)?; + base.offset_with_meta(from_offset, meta, layout, self) } - pub fn place_subslice( - &mut self, - base: &PlaceTy<'tcx, M::Provenance>, - from: u64, - to: u64, - from_end: bool, - ) -> InterpResult<'tcx, PlaceTy<'tcx, M::Provenance>> { - let base = self.force_allocation(base)?; - Ok(self.operand_subslice(&base.into(), from, to, from_end)?.assert_mem_place().into()) - } - - //# Applying a general projection - - /// Projects into a place. + /// Applying a general projection #[instrument(skip(self), level = "trace")] - pub fn place_projection( - &mut self, - base: &PlaceTy<'tcx, M::Provenance>, - proj_elem: mir::PlaceElem<'tcx>, - ) -> InterpResult<'tcx, PlaceTy<'tcx, M::Provenance>> { + pub fn project

(&self, base: &P, proj_elem: mir::PlaceElem<'tcx>) -> InterpResult<'tcx, P> + where + P: Projectable<'mir, 'tcx, M::Provenance> + + From> + + std::fmt::Debug, + { use rustc_middle::mir::ProjectionElem::*; Ok(match proj_elem { - OpaqueCast(ty) => { - let mut place = base.clone(); - place.layout = self.layout_of(ty)?; - place - } - Field(field, _) => self.place_field(base, field.index())?, - Downcast(_, variant) => self.place_downcast(base, variant)?, - Deref => self.deref_operand(&self.place_to_op(base)?)?.into(), + OpaqueCast(ty) => base.transmute(self.layout_of(ty)?, self)?, + Field(field, _) => self.project_field(base, field.index())?, + Downcast(_, variant) => self.project_downcast(base, variant)?, + Deref => self.deref_operand(&base.to_op(self)?)?.into(), Index(local) => { let layout = self.layout_of(self.tcx.types.usize)?; let n = self.local_to_op(self.frame(), local, Some(layout))?; let n = self.read_target_usize(&n)?; - self.place_index(base, n)? + self.project_index(base, n)? } ConstantIndex { offset, min_length, from_end } => { - self.place_constant_index(base, offset, min_length, from_end)? + self.project_constant_index(base, offset, min_length, from_end)? } - Subslice { from, to, from_end } => self.place_subslice(base, from, to, from_end)?, - }) - } - - #[instrument(skip(self), level = "trace")] - pub fn operand_projection( - &self, - base: &OpTy<'tcx, M::Provenance>, - proj_elem: mir::PlaceElem<'tcx>, - ) -> InterpResult<'tcx, OpTy<'tcx, M::Provenance>> { - use rustc_middle::mir::ProjectionElem::*; - Ok(match proj_elem { - OpaqueCast(ty) => { - let mut op = base.clone(); - op.layout = self.layout_of(ty)?; - op - } - Field(field, _) => self.operand_field(base, field.index())?, - Downcast(_, variant) => self.operand_downcast(base, variant)?, - Deref => self.deref_operand(base)?.into(), - Index(local) => { - let layout = self.layout_of(self.tcx.types.usize)?; - let n = self.local_to_op(self.frame(), local, Some(layout))?; - let n = self.read_target_usize(&n)?; - self.operand_index(base, n)? - } - ConstantIndex { offset, min_length, from_end } => { - self.operand_constant_index(base, offset, min_length, from_end)? - } - Subslice { from, to, from_end } => self.operand_subslice(base, from, to, from_end)?, + Subslice { from, to, from_end } => self.project_subslice(base, from, to, from_end)?, }) } } diff --git a/compiler/rustc_const_eval/src/interpret/step.rs b/compiler/rustc_const_eval/src/interpret/step.rs index 619da8abb7d2..9182d23128fe 100644 --- a/compiler/rustc_const_eval/src/interpret/step.rs +++ b/compiler/rustc_const_eval/src/interpret/step.rs @@ -8,7 +8,7 @@ use rustc_middle::mir; use rustc_middle::mir::interpret::{InterpResult, Scalar}; use rustc_middle::ty::layout::LayoutOf; -use super::{ImmTy, InterpCx, Machine}; +use super::{ImmTy, InterpCx, Machine, Projectable}; use crate::util; impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { @@ -197,7 +197,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { self.get_place_alloc_mut(&dest)?; } else { // Write the src to the first element. - let first = self.mplace_field(&dest, 0)?; + let first = self.project_index(&dest, 0)?; self.copy_op(&src, &first.into(), /*allow_transmute*/ false)?; // This is performance-sensitive code for big static/const arrays! So we @@ -302,8 +302,9 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { Discriminant(place) => { let op = self.eval_place_to_op(place, None)?; - let discr_val = self.read_discriminant(&op)?.0; - self.write_scalar(discr_val, &dest)?; + let variant = self.read_discriminant(&op)?; + let discr = self.discriminant_for_variant(op.layout, variant)?; + self.write_scalar(discr, &dest)?; } } diff --git a/compiler/rustc_const_eval/src/interpret/terminator.rs b/compiler/rustc_const_eval/src/interpret/terminator.rs index 7964c6be008c..f934cca2517b 100644 --- a/compiler/rustc_const_eval/src/interpret/terminator.rs +++ b/compiler/rustc_const_eval/src/interpret/terminator.rs @@ -60,13 +60,13 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { } pub fn fn_arg_field( - &mut self, + &self, arg: &FnArg<'tcx, M::Provenance>, field: usize, ) -> InterpResult<'tcx, FnArg<'tcx, M::Provenance>> { Ok(match arg { - FnArg::Copy(op) => FnArg::Copy(self.operand_field(op, field)?), - FnArg::InPlace(place) => FnArg::InPlace(self.place_field(place, field)?), + FnArg::Copy(op) => FnArg::Copy(self.project_field(op, field)?), + FnArg::InPlace(place) => FnArg::InPlace(self.project_field(place, field)?), }) } @@ -239,7 +239,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { /// Evaluate the arguments of a function call pub(super) fn eval_fn_call_arguments( - &mut self, + &self, ops: &[mir::Operand<'tcx>], ) -> InterpResult<'tcx, Vec>> { ops.iter() @@ -382,12 +382,16 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { // This all has to be in memory, there are no immediate unsized values. let src = caller_arg_copy.assert_mem_place(); // The destination cannot be one of these "spread args". - let (dest_frame, dest_local) = callee_arg.assert_local(); + let (dest_frame, dest_local, dest_offset) = callee_arg + .as_mplace_or_local() + .right() + .expect("callee fn arguments must be locals"); // We are just initializing things, so there can't be anything here yet. assert!(matches!( *self.local_to_op(&self.stack()[dest_frame], dest_local, None)?, Operand::Immediate(Immediate::Uninit) )); + assert_eq!(dest_offset, None); // Allocate enough memory to hold `src`. let Some((size, align)) = self.size_and_align_of_mplace(&src)? else { span_bug!( @@ -595,7 +599,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { if Some(local) == body.spread_arg { // Must be a tuple for i in 0..dest.layout.fields.count() { - let dest = self.place_field(&dest, i)?; + let dest = self.project_field(&dest, i)?; let callee_abi = callee_args_abis.next().unwrap(); self.pass_argument(&mut caller_args, callee_abi, &dest)?; } @@ -677,7 +681,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { // Not there yet, search for the only non-ZST field. let mut non_zst_field = None; for i in 0..receiver.layout.fields.count() { - let field = self.operand_field(&receiver, i)?; + let field = self.project_field(&receiver, i)?; let zst = field.layout.is_zst() && field.layout.align.abi.bytes() == 1; if !zst { @@ -703,12 +707,11 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { let (vptr, dyn_ty, adjusted_receiver) = if let ty::Dynamic(data, _, ty::DynStar) = receiver_place.layout.ty.kind() { - let (recv, vptr) = self.unpack_dyn_star(&receiver_place.into())?; + let (recv, vptr) = self.unpack_dyn_star(&receiver_place)?; let (dyn_ty, dyn_trait) = self.get_ptr_vtable(vptr)?; if dyn_trait != data.principal() { throw_ub_custom!(fluent::const_eval_dyn_star_call_vtable_mismatch); } - let recv = recv.assert_mem_place(); // we passed an MPlaceTy to `unpack_dyn_star` so we definitely still have one (vptr, dyn_ty, recv.ptr) } else { @@ -836,7 +839,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { } ty::Dynamic(_, _, ty::DynStar) => { // Dropping a `dyn*`. Need to find actual drop fn. - self.unpack_dyn_star(&place.into())?.0.assert_mem_place() + self.unpack_dyn_star(&place)?.0 } _ => { debug_assert_eq!( diff --git a/compiler/rustc_const_eval/src/interpret/validity.rs b/compiler/rustc_const_eval/src/interpret/validity.rs index 21c655988a0e..a82c98e72057 100644 --- a/compiler/rustc_const_eval/src/interpret/validity.rs +++ b/compiler/rustc_const_eval/src/interpret/validity.rs @@ -29,7 +29,7 @@ use std::hash::Hash; use super::UndefinedBehaviorInfo::*; use super::{ AllocId, CheckInAllocMsg, GlobalAlloc, ImmTy, Immediate, InterpCx, InterpResult, MPlaceTy, - Machine, MemPlaceMeta, OpTy, Pointer, Scalar, ValueVisitor, + Machine, MemPlaceMeta, OpTy, Pointer, Projectable, Scalar, ValueVisitor, }; macro_rules! throw_validation_failure { @@ -462,6 +462,8 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, ' /// Check if this is a value of primitive type, and if yes check the validity of the value /// at that type. Return `true` if the type is indeed primitive. + /// + /// Note that not all of these have `FieldsShape::Primitive`, e.g. wide references. fn try_visit_primitive( &mut self, value: &OpTy<'tcx, M::Provenance>, @@ -660,10 +662,9 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValueVisitor<'mir, 'tcx, M> InvalidTag(val) => InvalidEnumTag { value: format!("{val:x}"), }, - + UninhabitedEnumVariantRead(_) => UninhabitedEnumTag, InvalidUninitBytes(None) => UninitEnumTag, - ) - .1) + )) }) } @@ -733,60 +734,7 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValueVisitor<'mir, 'tcx, M> } } - // Recursively walk the value at its type. - self.walk_value(op)?; - - // *After* all of this, check the ABI. We need to check the ABI to handle - // types like `NonNull` where the `Scalar` info is more restrictive than what - // the fields say (`rustc_layout_scalar_valid_range_start`). - // But in most cases, this will just propagate what the fields say, - // and then we want the error to point at the field -- so, first recurse, - // then check ABI. - // - // FIXME: We could avoid some redundant checks here. For newtypes wrapping - // scalars, we do the same check on every "level" (e.g., first we check - // MyNewtype and then the scalar in there). - match op.layout.abi { - Abi::Uninhabited => { - let ty = op.layout.ty; - throw_validation_failure!(self.path, UninhabitedVal { ty }); - } - Abi::Scalar(scalar_layout) => { - if !scalar_layout.is_uninit_valid() { - // There is something to check here. - let scalar = self.read_scalar(op, ExpectedKind::InitScalar)?; - self.visit_scalar(scalar, scalar_layout)?; - } - } - Abi::ScalarPair(a_layout, b_layout) => { - // We can only proceed if *both* scalars need to be initialized. - // FIXME: find a way to also check ScalarPair when one side can be uninit but - // the other must be init. - if !a_layout.is_uninit_valid() && !b_layout.is_uninit_valid() { - let (a, b) = - self.read_immediate(op, ExpectedKind::InitScalar)?.to_scalar_pair(); - self.visit_scalar(a, a_layout)?; - self.visit_scalar(b, b_layout)?; - } - } - Abi::Vector { .. } => { - // No checks here, we assume layout computation gets this right. - // (This is harder to check since Miri does not represent these as `Immediate`. We - // also cannot use field projections since this might be a newtype around a vector.) - } - Abi::Aggregate { .. } => { - // Nothing to do. - } - } - - Ok(()) - } - - fn visit_aggregate( - &mut self, - op: &OpTy<'tcx, M::Provenance>, - fields: impl Iterator>, - ) -> InterpResult<'tcx> { + // Recursively walk the value at its type. Apply optimizations for some large types. match op.layout.ty.kind() { ty::Str => { let mplace = op.assert_mem_place(); // strings are unsized and hence never immediate @@ -874,12 +822,58 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValueVisitor<'mir, 'tcx, M> // ZST type, so either validation fails for all elements or none. ty::Array(tys, ..) | ty::Slice(tys) if self.ecx.layout_of(*tys)?.is_zst() => { // Validate just the first element (if any). - self.walk_aggregate(op, fields.take(1))? + if op.len(self.ecx)? > 0 { + self.visit_field(op, 0, &self.ecx.project_index(op, 0)?)?; + } } _ => { - self.walk_aggregate(op, fields)? // default handler + self.walk_value(op)?; // default handler } } + + // *After* all of this, check the ABI. We need to check the ABI to handle + // types like `NonNull` where the `Scalar` info is more restrictive than what + // the fields say (`rustc_layout_scalar_valid_range_start`). + // But in most cases, this will just propagate what the fields say, + // and then we want the error to point at the field -- so, first recurse, + // then check ABI. + // + // FIXME: We could avoid some redundant checks here. For newtypes wrapping + // scalars, we do the same check on every "level" (e.g., first we check + // MyNewtype and then the scalar in there). + match op.layout.abi { + Abi::Uninhabited => { + let ty = op.layout.ty; + throw_validation_failure!(self.path, UninhabitedVal { ty }); + } + Abi::Scalar(scalar_layout) => { + if !scalar_layout.is_uninit_valid() { + // There is something to check here. + let scalar = self.read_scalar(op, ExpectedKind::InitScalar)?; + self.visit_scalar(scalar, scalar_layout)?; + } + } + Abi::ScalarPair(a_layout, b_layout) => { + // We can only proceed if *both* scalars need to be initialized. + // FIXME: find a way to also check ScalarPair when one side can be uninit but + // the other must be init. + if !a_layout.is_uninit_valid() && !b_layout.is_uninit_valid() { + let (a, b) = + self.read_immediate(op, ExpectedKind::InitScalar)?.to_scalar_pair(); + self.visit_scalar(a, a_layout)?; + self.visit_scalar(b, b_layout)?; + } + } + Abi::Vector { .. } => { + // No checks here, we assume layout computation gets this right. + // (This is harder to check since Miri does not represent these as `Immediate`. We + // also cannot use field projections since this might be a newtype around a vector.) + } + Abi::Aggregate { .. } => { + // Nothing to do. + } + } + Ok(()) } } diff --git a/compiler/rustc_const_eval/src/interpret/visitor.rs b/compiler/rustc_const_eval/src/interpret/visitor.rs index 879ae198f7e5..4ec19d9e655b 100644 --- a/compiler/rustc_const_eval/src/interpret/visitor.rs +++ b/compiler/rustc_const_eval/src/interpret/visitor.rs @@ -1,544 +1,204 @@ //! Visitor for a run-time value with a given layout: Traverse enums, structs and other compound //! types until we arrive at the leaves, with custom handling for primitive types. +use rustc_index::IndexVec; use rustc_middle::mir::interpret::InterpResult; use rustc_middle::ty; -use rustc_middle::ty::layout::TyAndLayout; +use rustc_target::abi::FieldIdx; use rustc_target::abi::{FieldsShape, VariantIdx, Variants}; use std::num::NonZeroUsize; -use super::{InterpCx, MPlaceTy, Machine, OpTy, PlaceTy}; +use super::{InterpCx, MPlaceTy, Machine, Projectable}; -/// A thing that we can project into, and that has a layout. -/// This wouldn't have to depend on `Machine` but with the current type inference, -/// that's just more convenient to work with (avoids repeating all the `Machine` bounds). -pub trait Value<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>>: Sized { - /// Gets this value's layout. - fn layout(&self) -> TyAndLayout<'tcx>; +/// How to traverse a value and what to do when we are at the leaves. +pub trait ValueVisitor<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>>: Sized { + type V: Projectable<'mir, 'tcx, M::Provenance> + + From> + + std::fmt::Debug; - /// Makes this into an `OpTy`, in a cheap way that is good for reading. - fn to_op_for_read( - &self, - ecx: &InterpCx<'mir, 'tcx, M>, - ) -> InterpResult<'tcx, OpTy<'tcx, M::Provenance>>; + /// The visitor must have an `InterpCx` in it. + fn ecx(&self) -> &InterpCx<'mir, 'tcx, M>; - /// Makes this into an `OpTy`, in a potentially more expensive way that is good for projections. - fn to_op_for_proj( - &self, - ecx: &InterpCx<'mir, 'tcx, M>, - ) -> InterpResult<'tcx, OpTy<'tcx, M::Provenance>> { - self.to_op_for_read(ecx) + /// `read_discriminant` can be hooked for better error messages. + #[inline(always)] + fn read_discriminant(&mut self, v: &Self::V) -> InterpResult<'tcx, VariantIdx> { + Ok(self.ecx().read_discriminant(&v.to_op(self.ecx())?)?) } - /// Creates this from an `OpTy`. + /// This function provides the chance to reorder the order in which fields are visited for + /// `FieldsShape::Aggregate`: The order of fields will be + /// `(0..num_fields).map(aggregate_field_order)`. /// - /// If `to_op_for_proj` only ever produces `Indirect` operands, then this one is definitely `Indirect`. - fn from_op(op: &OpTy<'tcx, M::Provenance>) -> Self; - - /// Projects to the given enum variant. - fn project_downcast( - &self, - ecx: &InterpCx<'mir, 'tcx, M>, - variant: VariantIdx, - ) -> InterpResult<'tcx, Self>; - - /// Projects to the n-th field. - fn project_field( - &self, - ecx: &InterpCx<'mir, 'tcx, M>, - field: usize, - ) -> InterpResult<'tcx, Self>; -} - -/// A thing that we can project into given *mutable* access to `ecx`, and that has a layout. -/// This wouldn't have to depend on `Machine` but with the current type inference, -/// that's just more convenient to work with (avoids repeating all the `Machine` bounds). -pub trait ValueMut<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>>: Sized { - /// Gets this value's layout. - fn layout(&self) -> TyAndLayout<'tcx>; - - /// Makes this into an `OpTy`, in a cheap way that is good for reading. - fn to_op_for_read( - &self, - ecx: &InterpCx<'mir, 'tcx, M>, - ) -> InterpResult<'tcx, OpTy<'tcx, M::Provenance>>; - - /// Makes this into an `OpTy`, in a potentially more expensive way that is good for projections. - fn to_op_for_proj( - &self, - ecx: &mut InterpCx<'mir, 'tcx, M>, - ) -> InterpResult<'tcx, OpTy<'tcx, M::Provenance>>; - - /// Creates this from an `OpTy`. - /// - /// If `to_op_for_proj` only ever produces `Indirect` operands, then this one is definitely `Indirect`. - fn from_op(op: &OpTy<'tcx, M::Provenance>) -> Self; - - /// Projects to the given enum variant. - fn project_downcast( - &self, - ecx: &mut InterpCx<'mir, 'tcx, M>, - variant: VariantIdx, - ) -> InterpResult<'tcx, Self>; - - /// Projects to the n-th field. - fn project_field( - &self, - ecx: &mut InterpCx<'mir, 'tcx, M>, - field: usize, - ) -> InterpResult<'tcx, Self>; -} - -// We cannot have a general impl which shows that Value implies ValueMut. (When we do, it says we -// cannot `impl ValueMut for PlaceTy` because some downstream crate could `impl Value for PlaceTy`.) -// So we have some copy-paste here. (We could have a macro but since we only have 2 types with this -// double-impl, that would barely make the code shorter, if at all.) - -impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> Value<'mir, 'tcx, M> for OpTy<'tcx, M::Provenance> { + /// The default means we iterate in source declaration order; alternative this can do an inverse + /// lookup in `memory_index` to use memory field order instead. #[inline(always)] - fn layout(&self) -> TyAndLayout<'tcx> { - self.layout + fn aggregate_field_order(_memory_index: &IndexVec, idx: usize) -> usize { + idx } + // Recursive actions, ready to be overloaded. + /// Visits the given value, dispatching as appropriate to more specialized visitors. #[inline(always)] - fn to_op_for_read( - &self, - _ecx: &InterpCx<'mir, 'tcx, M>, - ) -> InterpResult<'tcx, OpTy<'tcx, M::Provenance>> { - Ok(self.clone()) + fn visit_value(&mut self, v: &Self::V) -> InterpResult<'tcx> { + self.walk_value(v) + } + /// Visits the given value as a union. No automatic recursion can happen here. + #[inline(always)] + fn visit_union(&mut self, _v: &Self::V, _fields: NonZeroUsize) -> InterpResult<'tcx> { + Ok(()) + } + /// Visits the given value as the pointer of a `Box`. There is nothing to recurse into. + /// The type of `v` will be a raw pointer, but this is a field of `Box` and the + /// pointee type is the actual `T`. + #[inline(always)] + fn visit_box(&mut self, _v: &Self::V) -> InterpResult<'tcx> { + Ok(()) } + /// Called each time we recurse down to a field of a "product-like" aggregate + /// (structs, tuples, arrays and the like, but not enums), passing in old (outer) + /// and new (inner) value. + /// This gives the visitor the chance to track the stack of nested fields that + /// we are descending through. #[inline(always)] - fn from_op(op: &OpTy<'tcx, M::Provenance>) -> Self { - op.clone() + fn visit_field( + &mut self, + _old_val: &Self::V, + _field: usize, + new_val: &Self::V, + ) -> InterpResult<'tcx> { + self.visit_value(new_val) + } + /// Called when recursing into an enum variant. + /// This gives the visitor the chance to track the stack of nested fields that + /// we are descending through. + #[inline(always)] + fn visit_variant( + &mut self, + _old_val: &Self::V, + _variant: VariantIdx, + new_val: &Self::V, + ) -> InterpResult<'tcx> { + self.visit_value(new_val) } - #[inline(always)] - fn project_downcast( - &self, - ecx: &InterpCx<'mir, 'tcx, M>, - variant: VariantIdx, - ) -> InterpResult<'tcx, Self> { - ecx.operand_downcast(self, variant) - } + fn walk_value(&mut self, v: &Self::V) -> InterpResult<'tcx> { + let ty = v.layout().ty; + trace!("walk_value: type: {ty}"); - #[inline(always)] - fn project_field( - &self, - ecx: &InterpCx<'mir, 'tcx, M>, - field: usize, - ) -> InterpResult<'tcx, Self> { - ecx.operand_field(self, field) - } -} - -impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValueMut<'mir, 'tcx, M> - for OpTy<'tcx, M::Provenance> -{ - #[inline(always)] - fn layout(&self) -> TyAndLayout<'tcx> { - self.layout - } - - #[inline(always)] - fn to_op_for_read( - &self, - _ecx: &InterpCx<'mir, 'tcx, M>, - ) -> InterpResult<'tcx, OpTy<'tcx, M::Provenance>> { - Ok(self.clone()) - } - - #[inline(always)] - fn to_op_for_proj( - &self, - _ecx: &mut InterpCx<'mir, 'tcx, M>, - ) -> InterpResult<'tcx, OpTy<'tcx, M::Provenance>> { - Ok(self.clone()) - } - - #[inline(always)] - fn from_op(op: &OpTy<'tcx, M::Provenance>) -> Self { - op.clone() - } - - #[inline(always)] - fn project_downcast( - &self, - ecx: &mut InterpCx<'mir, 'tcx, M>, - variant: VariantIdx, - ) -> InterpResult<'tcx, Self> { - ecx.operand_downcast(self, variant) - } - - #[inline(always)] - fn project_field( - &self, - ecx: &mut InterpCx<'mir, 'tcx, M>, - field: usize, - ) -> InterpResult<'tcx, Self> { - ecx.operand_field(self, field) - } -} - -impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> Value<'mir, 'tcx, M> - for MPlaceTy<'tcx, M::Provenance> -{ - #[inline(always)] - fn layout(&self) -> TyAndLayout<'tcx> { - self.layout - } - - #[inline(always)] - fn to_op_for_read( - &self, - _ecx: &InterpCx<'mir, 'tcx, M>, - ) -> InterpResult<'tcx, OpTy<'tcx, M::Provenance>> { - Ok(self.into()) - } - - #[inline(always)] - fn from_op(op: &OpTy<'tcx, M::Provenance>) -> Self { - // assert is justified because our `to_op_for_read` only ever produces `Indirect` operands. - op.assert_mem_place() - } - - #[inline(always)] - fn project_downcast( - &self, - ecx: &InterpCx<'mir, 'tcx, M>, - variant: VariantIdx, - ) -> InterpResult<'tcx, Self> { - ecx.mplace_downcast(self, variant) - } - - #[inline(always)] - fn project_field( - &self, - ecx: &InterpCx<'mir, 'tcx, M>, - field: usize, - ) -> InterpResult<'tcx, Self> { - ecx.mplace_field(self, field) - } -} - -impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValueMut<'mir, 'tcx, M> - for MPlaceTy<'tcx, M::Provenance> -{ - #[inline(always)] - fn layout(&self) -> TyAndLayout<'tcx> { - self.layout - } - - #[inline(always)] - fn to_op_for_read( - &self, - _ecx: &InterpCx<'mir, 'tcx, M>, - ) -> InterpResult<'tcx, OpTy<'tcx, M::Provenance>> { - Ok(self.into()) - } - - #[inline(always)] - fn to_op_for_proj( - &self, - _ecx: &mut InterpCx<'mir, 'tcx, M>, - ) -> InterpResult<'tcx, OpTy<'tcx, M::Provenance>> { - Ok(self.into()) - } - - #[inline(always)] - fn from_op(op: &OpTy<'tcx, M::Provenance>) -> Self { - // assert is justified because our `to_op_for_proj` only ever produces `Indirect` operands. - op.assert_mem_place() - } - - #[inline(always)] - fn project_downcast( - &self, - ecx: &mut InterpCx<'mir, 'tcx, M>, - variant: VariantIdx, - ) -> InterpResult<'tcx, Self> { - ecx.mplace_downcast(self, variant) - } - - #[inline(always)] - fn project_field( - &self, - ecx: &mut InterpCx<'mir, 'tcx, M>, - field: usize, - ) -> InterpResult<'tcx, Self> { - ecx.mplace_field(self, field) - } -} - -impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValueMut<'mir, 'tcx, M> - for PlaceTy<'tcx, M::Provenance> -{ - #[inline(always)] - fn layout(&self) -> TyAndLayout<'tcx> { - self.layout - } - - #[inline(always)] - fn to_op_for_read( - &self, - ecx: &InterpCx<'mir, 'tcx, M>, - ) -> InterpResult<'tcx, OpTy<'tcx, M::Provenance>> { - // No need for `force_allocation` since we are just going to read from this. - ecx.place_to_op(self) - } - - #[inline(always)] - fn to_op_for_proj( - &self, - ecx: &mut InterpCx<'mir, 'tcx, M>, - ) -> InterpResult<'tcx, OpTy<'tcx, M::Provenance>> { - // We `force_allocation` here so that `from_op` below can work. - Ok(ecx.force_allocation(self)?.into()) - } - - #[inline(always)] - fn from_op(op: &OpTy<'tcx, M::Provenance>) -> Self { - // assert is justified because our `to_op` only ever produces `Indirect` operands. - op.assert_mem_place().into() - } - - #[inline(always)] - fn project_downcast( - &self, - ecx: &mut InterpCx<'mir, 'tcx, M>, - variant: VariantIdx, - ) -> InterpResult<'tcx, Self> { - ecx.place_downcast(self, variant) - } - - #[inline(always)] - fn project_field( - &self, - ecx: &mut InterpCx<'mir, 'tcx, M>, - field: usize, - ) -> InterpResult<'tcx, Self> { - ecx.place_field(self, field) - } -} - -macro_rules! make_value_visitor { - ($visitor_trait:ident, $value_trait:ident, $($mutability:ident)?) => { - /// How to traverse a value and what to do when we are at the leaves. - pub trait $visitor_trait<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>>: Sized { - type V: $value_trait<'mir, 'tcx, M>; - - /// The visitor must have an `InterpCx` in it. - fn ecx(&$($mutability)? self) - -> &$($mutability)? InterpCx<'mir, 'tcx, M>; - - /// `read_discriminant` can be hooked for better error messages. - #[inline(always)] - fn read_discriminant( - &mut self, - op: &OpTy<'tcx, M::Provenance>, - ) -> InterpResult<'tcx, VariantIdx> { - Ok(self.ecx().read_discriminant(op)?.1) + // Special treatment for special types, where the (static) layout is not sufficient. + match *ty.kind() { + // If it is a trait object, switch to the real type that was used to create it. + ty::Dynamic(_, _, ty::Dyn) => { + // Dyn types. This is unsized, and the actual dynamic type of the data is given by the + // vtable stored in the place metadata. + // unsized values are never immediate, so we can assert_mem_place + let op = v.to_op(self.ecx())?; + let dest = op.assert_mem_place(); + let inner_mplace = self.ecx().unpack_dyn_trait(&dest)?.0; + trace!("walk_value: dyn object layout: {:#?}", inner_mplace.layout); + // recurse with the inner type + return self.visit_field(&v, 0, &inner_mplace.into()); } + ty::Dynamic(_, _, ty::DynStar) => { + // DynStar types. Very different from a dyn type (but strangely part of the + // same variant in `TyKind`): These are pairs where the 2nd component is the + // vtable, and the first component is the data (which must be ptr-sized). + let data = self.ecx().unpack_dyn_star(v)?.0; + return self.visit_field(&v, 0, &data); + } + // Slices do not need special handling here: they have `Array` field + // placement with length 0, so we enter the `Array` case below which + // indirectly uses the metadata to determine the actual length. - // Recursive actions, ready to be overloaded. - /// Visits the given value, dispatching as appropriate to more specialized visitors. - #[inline(always)] - fn visit_value(&mut self, v: &Self::V) -> InterpResult<'tcx> - { - self.walk_value(v) - } - /// Visits the given value as a union. No automatic recursion can happen here. - #[inline(always)] - fn visit_union(&mut self, _v: &Self::V, _fields: NonZeroUsize) -> InterpResult<'tcx> - { - Ok(()) - } - /// Visits the given value as the pointer of a `Box`. There is nothing to recurse into. - /// The type of `v` will be a raw pointer, but this is a field of `Box` and the - /// pointee type is the actual `T`. - #[inline(always)] - fn visit_box(&mut self, _v: &Self::V) -> InterpResult<'tcx> - { - Ok(()) - } - /// Visits this value as an aggregate, you are getting an iterator yielding - /// all the fields (still in an `InterpResult`, you have to do error handling yourself). - /// Recurses into the fields. - #[inline(always)] - fn visit_aggregate( - &mut self, - v: &Self::V, - fields: impl Iterator>, - ) -> InterpResult<'tcx> { - self.walk_aggregate(v, fields) - } + // However, `Box`... let's talk about `Box`. + ty::Adt(def, ..) if def.is_box() => { + // `Box` is a hybrid primitive-library-defined type that one the one hand is + // a dereferenceable pointer, on the other hand has *basically arbitrary + // user-defined layout* since the user controls the 'allocator' field. So it + // cannot be treated like a normal pointer, since it does not fit into an + // `Immediate`. Yeah, it is quite terrible. But many visitors want to do + // something with "all boxed pointers", so we handle this mess for them. + // + // When we hit a `Box`, we do not do the usual field recursion; instead, + // we (a) call `visit_box` on the pointer value, and (b) recurse on the + // allocator field. We also assert tons of things to ensure we do not miss + // any other fields. - /// Called each time we recurse down to a field of a "product-like" aggregate - /// (structs, tuples, arrays and the like, but not enums), passing in old (outer) - /// and new (inner) value. - /// This gives the visitor the chance to track the stack of nested fields that - /// we are descending through. - #[inline(always)] - fn visit_field( - &mut self, - _old_val: &Self::V, - _field: usize, - new_val: &Self::V, - ) -> InterpResult<'tcx> { - self.visit_value(new_val) - } - /// Called when recursing into an enum variant. - /// This gives the visitor the chance to track the stack of nested fields that - /// we are descending through. - #[inline(always)] - fn visit_variant( - &mut self, - _old_val: &Self::V, - _variant: VariantIdx, - new_val: &Self::V, - ) -> InterpResult<'tcx> { - self.visit_value(new_val) - } + // `Box` has two fields: the pointer we care about, and the allocator. + assert_eq!(v.layout().fields.count(), 2, "`Box` must have exactly 2 fields"); + let (unique_ptr, alloc) = + (self.ecx().project_field(v, 0)?, self.ecx().project_field(v, 1)?); + // Unfortunately there is some type junk in the way here: `unique_ptr` is a `Unique`... + // (which means another 2 fields, the second of which is a `PhantomData`) + assert_eq!(unique_ptr.layout().fields.count(), 2); + let (nonnull_ptr, phantom) = ( + self.ecx().project_field(&unique_ptr, 0)?, + self.ecx().project_field(&unique_ptr, 1)?, + ); + assert!( + phantom.layout().ty.ty_adt_def().is_some_and(|adt| adt.is_phantom_data()), + "2nd field of `Unique` should be PhantomData but is {:?}", + phantom.layout().ty, + ); + // ... that contains a `NonNull`... (gladly, only a single field here) + assert_eq!(nonnull_ptr.layout().fields.count(), 1); + let raw_ptr = self.ecx().project_field(&nonnull_ptr, 0)?; // the actual raw ptr + // ... whose only field finally is a raw ptr we can dereference. + self.visit_box(&raw_ptr)?; - // Default recursors. Not meant to be overloaded. - fn walk_aggregate( - &mut self, - v: &Self::V, - fields: impl Iterator>, - ) -> InterpResult<'tcx> { - // Now iterate over it. - for (idx, field_val) in fields.enumerate() { - self.visit_field(v, idx, &field_val?)?; + // The second `Box` field is the allocator, which we recursively check for validity + // like in regular structs. + self.visit_field(v, 1, &alloc)?; + + // We visited all parts of this one. + return Ok(()); + } + _ => {} + }; + + // Visit the fields of this value. + match &v.layout().fields { + FieldsShape::Primitive => {} + &FieldsShape::Union(fields) => { + self.visit_union(v, fields)?; + } + FieldsShape::Arbitrary { offsets, memory_index } => { + for idx in 0..offsets.len() { + let idx = Self::aggregate_field_order(memory_index, idx); + let field = self.ecx().project_field(v, idx)?; + self.visit_field(v, idx, &field)?; } - Ok(()) } - fn walk_value(&mut self, v: &Self::V) -> InterpResult<'tcx> - { - let ty = v.layout().ty; - trace!("walk_value: type: {ty}"); - - // Special treatment for special types, where the (static) layout is not sufficient. - match *ty.kind() { - // If it is a trait object, switch to the real type that was used to create it. - ty::Dynamic(_, _, ty::Dyn) => { - // Dyn types. This is unsized, and the actual dynamic type of the data is given by the - // vtable stored in the place metadata. - // unsized values are never immediate, so we can assert_mem_place - let op = v.to_op_for_read(self.ecx())?; - let dest = op.assert_mem_place(); - let inner_mplace = self.ecx().unpack_dyn_trait(&dest)?.0; - trace!("walk_value: dyn object layout: {:#?}", inner_mplace.layout); - // recurse with the inner type - return self.visit_field(&v, 0, &$value_trait::from_op(&inner_mplace.into())); - }, - ty::Dynamic(_, _, ty::DynStar) => { - // DynStar types. Very different from a dyn type (but strangely part of the - // same variant in `TyKind`): These are pairs where the 2nd component is the - // vtable, and the first component is the data (which must be ptr-sized). - let op = v.to_op_for_proj(self.ecx())?; - let data = self.ecx().unpack_dyn_star(&op)?.0; - return self.visit_field(&v, 0, &$value_trait::from_op(&data)); - } - // Slices do not need special handling here: they have `Array` field - // placement with length 0, so we enter the `Array` case below which - // indirectly uses the metadata to determine the actual length. - - // However, `Box`... let's talk about `Box`. - ty::Adt(def, ..) if def.is_box() => { - // `Box` is a hybrid primitive-library-defined type that one the one hand is - // a dereferenceable pointer, on the other hand has *basically arbitrary - // user-defined layout* since the user controls the 'allocator' field. So it - // cannot be treated like a normal pointer, since it does not fit into an - // `Immediate`. Yeah, it is quite terrible. But many visitors want to do - // something with "all boxed pointers", so we handle this mess for them. - // - // When we hit a `Box`, we do not do the usual `visit_aggregate`; instead, - // we (a) call `visit_box` on the pointer value, and (b) recurse on the - // allocator field. We also assert tons of things to ensure we do not miss - // any other fields. - - // `Box` has two fields: the pointer we care about, and the allocator. - assert_eq!(v.layout().fields.count(), 2, "`Box` must have exactly 2 fields"); - let (unique_ptr, alloc) = - (v.project_field(self.ecx(), 0)?, v.project_field(self.ecx(), 1)?); - // Unfortunately there is some type junk in the way here: `unique_ptr` is a `Unique`... - // (which means another 2 fields, the second of which is a `PhantomData`) - assert_eq!(unique_ptr.layout().fields.count(), 2); - let (nonnull_ptr, phantom) = ( - unique_ptr.project_field(self.ecx(), 0)?, - unique_ptr.project_field(self.ecx(), 1)?, - ); - assert!( - phantom.layout().ty.ty_adt_def().is_some_and(|adt| adt.is_phantom_data()), - "2nd field of `Unique` should be PhantomData but is {:?}", - phantom.layout().ty, - ); - // ... that contains a `NonNull`... (gladly, only a single field here) - assert_eq!(nonnull_ptr.layout().fields.count(), 1); - let raw_ptr = nonnull_ptr.project_field(self.ecx(), 0)?; // the actual raw ptr - // ... whose only field finally is a raw ptr we can dereference. - self.visit_box(&raw_ptr)?; - - // The second `Box` field is the allocator, which we recursively check for validity - // like in regular structs. - self.visit_field(v, 1, &alloc)?; - - // We visited all parts of this one. - return Ok(()); - } - _ => {}, - }; - - // Visit the fields of this value. - match &v.layout().fields { - FieldsShape::Primitive => {} - &FieldsShape::Union(fields) => { - self.visit_union(v, fields)?; - } - FieldsShape::Arbitrary { offsets, .. } => { - // FIXME: We collect in a vec because otherwise there are lifetime - // errors: Projecting to a field needs access to `ecx`. - let fields: Vec> = - (0..offsets.len()).map(|i| { - v.project_field(self.ecx(), i) - }) - .collect(); - self.visit_aggregate(v, fields.into_iter())?; - } - FieldsShape::Array { .. } => { - // Let's get an mplace (or immediate) first. - // This might `force_allocate` if `v` is a `PlaceTy`, but `place_index` does that anyway. - let op = v.to_op_for_proj(self.ecx())?; - // Now we can go over all the fields. - // This uses the *run-time length*, i.e., if we are a slice, - // the dynamic info from the metadata is used. - let iter = self.ecx().operand_array_fields(&op)? - .map(|f| f.and_then(|f| { - Ok($value_trait::from_op(&f)) - })); - self.visit_aggregate(v, iter)?; - } - } - - match v.layout().variants { - // If this is a multi-variant layout, find the right variant and proceed - // with *its* fields. - Variants::Multiple { .. } => { - let op = v.to_op_for_read(self.ecx())?; - let idx = self.read_discriminant(&op)?; - let inner = v.project_downcast(self.ecx(), idx)?; - trace!("walk_value: variant layout: {:#?}", inner.layout()); - // recurse with the inner type - self.visit_variant(v, idx, &inner) - } - // For single-variant layouts, we already did anything there is to do. - Variants::Single { .. } => Ok(()) + FieldsShape::Array { .. } => { + for (idx, field) in self.ecx().project_array_fields(v)?.enumerate() { + self.visit_field(v, idx, &field?)?; } } } + + match v.layout().variants { + // If this is a multi-variant layout, find the right variant and proceed + // with *its* fields. + Variants::Multiple { .. } => { + let idx = self.read_discriminant(v)?; + // There are 3 cases where downcasts can turn a Scalar/ScalarPair into a different ABI which + // could be a problem for `ImmTy` (see layout_sanity_check): + // - variant.size == Size::ZERO: works fine because `ImmTy::offset` has a special case for + // zero-sized layouts. + // - variant.fields.count() == 0: works fine because `ImmTy::offset` has a special case for + // zero-field aggregates. + // - variant.abi.is_uninhabited(): triggers UB in `read_discriminant` so we never get here. + let inner = self.ecx().project_downcast(v, idx)?; + trace!("walk_value: variant layout: {:#?}", inner.layout()); + // recurse with the inner type + self.visit_variant(v, idx, &inner)?; + } + // For single-variant layouts, we already did anything there is to do. + Variants::Single { .. } => {} + } + + Ok(()) } } - -make_value_visitor!(ValueVisitor, Value,); -make_value_visitor!(MutValueVisitor, ValueMut, mut); diff --git a/compiler/rustc_const_eval/src/transform/check_consts/check.rs b/compiler/rustc_const_eval/src/transform/check_consts/check.rs index d8b8fa927c7e..15a7c0536cbb 100644 --- a/compiler/rustc_const_eval/src/transform/check_consts/check.rs +++ b/compiler/rustc_const_eval/src/transform/check_consts/check.rs @@ -8,6 +8,7 @@ use rustc_infer::infer::TyCtxtInferExt; use rustc_infer::traits::{ImplSource, Obligation, ObligationCause}; use rustc_middle::mir::visit::{MutatingUseContext, NonMutatingUseContext, PlaceContext, Visitor}; use rustc_middle::mir::*; +use rustc_middle::traits::BuiltinImplSource; use rustc_middle::ty::{self, adjustment::PointerCoercion, Instance, InstanceDef, Ty, TyCtxt}; use rustc_middle::ty::{GenericArgKind, GenericArgs}; use rustc_middle::ty::{TraitRef, TypeVisitableExt}; @@ -766,7 +767,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> { }; match implsrc { - Ok(Some(ImplSource::Param(_, ty::BoundConstness::ConstIfConst))) => { + Ok(Some(ImplSource::Param(ty::BoundConstness::ConstIfConst, _))) => { debug!( "const_trait_impl: provided {:?} via where-clause in {:?}", trait_ref, param_env @@ -774,7 +775,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> { return; } // Closure: Fn{Once|Mut} - Ok(Some(ImplSource::Builtin(_))) + Ok(Some(ImplSource::Builtin(BuiltinImplSource::Misc, _))) if trait_ref.self_ty().is_closure() && tcx.fn_trait_kind_from_def_id(trait_id).is_some() => { diff --git a/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs b/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs index 0ef7ace69653..b3730dd26487 100644 --- a/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs +++ b/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs @@ -7,6 +7,7 @@ use rustc_hir::LangItem; use rustc_infer::infer::TyCtxtInferExt; use rustc_middle::mir; use rustc_middle::mir::*; +use rustc_middle::traits::BuiltinImplSource; use rustc_middle::ty::{self, AdtDef, GenericArgsRef, Ty}; use rustc_trait_selection::traits::{ self, ImplSource, Obligation, ObligationCause, ObligationCtxt, SelectionContext, @@ -172,7 +173,8 @@ impl Qualif for NeedsNonConstDrop { if !matches!( impl_src, - ImplSource::Builtin(_) | ImplSource::Param(_, ty::BoundConstness::ConstIfConst) + ImplSource::Builtin(BuiltinImplSource::Misc, _) + | ImplSource::Param(ty::BoundConstness::ConstIfConst, _) ) { // If our const destruct candidate is not ConstDestruct or implied by the param env, // then it's bad diff --git a/compiler/rustc_const_eval/src/util/compare_types.rs b/compiler/rustc_const_eval/src/util/compare_types.rs index d6a2ffb75111..88d4f5e715c9 100644 --- a/compiler/rustc_const_eval/src/util/compare_types.rs +++ b/compiler/rustc_const_eval/src/util/compare_types.rs @@ -56,8 +56,13 @@ pub fn is_subtype<'tcx>( // With `Reveal::All`, opaque types get normalized away, with `Reveal::UserFacing` // we would get unification errors because we're unable to look into opaque types, // even if they're constrained in our current function. - // - // It seems very unlikely that this hides any bugs. - let _ = infcx.take_opaque_types(); + for (key, ty) in infcx.take_opaque_types() { + span_bug!( + ty.hidden_type.span, + "{}, {}", + tcx.type_of(key.def_id).instantiate(tcx, key.args), + ty.hidden_type.ty + ); + } errors.is_empty() } diff --git a/compiler/rustc_data_structures/src/sso/map.rs b/compiler/rustc_data_structures/src/sso/map.rs index 99581ed23759..04e359a54708 100644 --- a/compiler/rustc_data_structures/src/sso/map.rs +++ b/compiler/rustc_data_structures/src/sso/map.rs @@ -268,11 +268,7 @@ impl SsoHashMap { pub fn remove_entry(&mut self, key: &K) -> Option<(K, V)> { match self { SsoHashMap::Array(array) => { - if let Some(index) = array.iter().position(|(k, _v)| k == key) { - Some(array.swap_remove(index)) - } else { - None - } + array.iter().position(|(k, _v)| k == key).map(|index| array.swap_remove(index)) } SsoHashMap::Map(map) => map.remove_entry(key), } diff --git a/compiler/rustc_error_messages/src/lib.rs b/compiler/rustc_error_messages/src/lib.rs index 1879ece59e32..a49b842d9ffe 100644 --- a/compiler/rustc_error_messages/src/lib.rs +++ b/compiler/rustc_error_messages/src/lib.rs @@ -533,6 +533,14 @@ impl MultiSpan { pub fn has_span_labels(&self) -> bool { self.span_labels.iter().any(|(sp, _)| !sp.is_dummy()) } + + /// Clone this `MultiSpan` without keeping any of the span labels - sometimes a `MultiSpan` is + /// to be re-used in another diagnostic, but includes `span_labels` which have translated + /// messages. These translated messages would fail to translate without their diagnostic + /// arguments which are unlikely to be cloned alongside the `Span`. + pub fn clone_ignoring_labels(&self) -> Self { + Self { primary_spans: self.primary_spans.clone(), ..MultiSpan::new() } + } } impl From for MultiSpan { diff --git a/compiler/rustc_errors/src/diagnostic.rs b/compiler/rustc_errors/src/diagnostic.rs index ed0d06ed0ff7..a96e317df55d 100644 --- a/compiler/rustc_errors/src/diagnostic.rs +++ b/compiler/rustc_errors/src/diagnostic.rs @@ -420,13 +420,13 @@ impl Diagnostic { let expected_label = if expected_label.is_empty() { "expected".to_string() } else { - format!("expected {}", expected_label) + format!("expected {expected_label}") }; let found_label = found_label.to_string(); let found_label = if found_label.is_empty() { "found".to_string() } else { - format!("found {}", found_label) + format!("found {found_label}") }; let (found_padding, expected_padding) = if expected_label.len() > found_label.len() { (expected_label.len() - found_label.len(), 0) @@ -439,13 +439,13 @@ impl Diagnostic { StringPart::Normal(ref s) => (s.to_owned(), Style::NoStyle), StringPart::Highlighted(ref s) => (s.to_owned(), Style::Highlight), })); - msg.push((format!("`{}\n", expected_extra), Style::NoStyle)); + msg.push((format!("`{expected_extra}\n"), Style::NoStyle)); msg.push((format!("{}{} `", " ".repeat(found_padding), found_label), Style::NoStyle)); msg.extend(found.0.iter().map(|x| match *x { StringPart::Normal(ref s) => (s.to_owned(), Style::NoStyle), StringPart::Highlighted(ref s) => (s.to_owned(), Style::Highlight), })); - msg.push((format!("`{}", found_extra), Style::NoStyle)); + msg.push((format!("`{found_extra}"), Style::NoStyle)); // For now, just attach these as notes. self.highlighted_note(msg); @@ -454,7 +454,7 @@ impl Diagnostic { pub fn note_trait_signature(&mut self, name: Symbol, signature: String) -> &mut Self { self.highlighted_note(vec![ - (format!("`{}` from trait: `", name), Style::NoStyle), + (format!("`{name}` from trait: `"), Style::NoStyle), (signature, Style::Highlight), ("`".to_string(), Style::NoStyle), ]); diff --git a/compiler/rustc_errors/src/diagnostic_impls.rs b/compiler/rustc_errors/src/diagnostic_impls.rs index 10fe7fc74a87..132f2c015b8f 100644 --- a/compiler/rustc_errors/src/diagnostic_impls.rs +++ b/compiler/rustc_errors/src/diagnostic_impls.rs @@ -102,7 +102,7 @@ impl IntoDiagnosticArg for bool { impl IntoDiagnosticArg for char { fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> { - DiagnosticArgValue::Str(Cow::Owned(format!("{:?}", self))) + DiagnosticArgValue::Str(Cow::Owned(format!("{self:?}"))) } } @@ -164,6 +164,12 @@ impl IntoDiagnosticArg for hir::ConstContext { } } +impl IntoDiagnosticArg for ast::Expr { + fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> { + DiagnosticArgValue::Str(Cow::Owned(pprust::expr_to_string(&self))) + } +} + impl IntoDiagnosticArg for ast::Path { fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> { DiagnosticArgValue::Str(Cow::Owned(pprust::path_to_string(&self))) diff --git a/compiler/rustc_errors/src/emitter.rs b/compiler/rustc_errors/src/emitter.rs index a0fa4115c3e4..961feba3250c 100644 --- a/compiler/rustc_errors/src/emitter.rs +++ b/compiler/rustc_errors/src/emitter.rs @@ -279,12 +279,12 @@ pub trait Emitter: Translate { let msg = if substitution.is_empty() || sugg.style.hide_inline() { // This substitution is only removal OR we explicitly don't want to show the // code inline (`hide_inline`). Therefore, we don't show the substitution. - format!("help: {}", &msg) + format!("help: {msg}") } else { // Show the default suggestion text with the substitution format!( "help: {}{}: `{}`", - &msg, + msg, if self.source_map().is_some_and(|sm| is_case_difference( sm, substitution, diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index 1da02e1bb012..eae7a46e07a3 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -1485,7 +1485,7 @@ impl HandlerInner { let _ = self.fatal(errors); } (_, _) => { - let _ = self.fatal(format!("{}; {}", &errors, &warnings)); + let _ = self.fatal(format!("{errors}; {warnings}")); } } diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index 68f1559ea220..3663c450ba64 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -3013,8 +3013,7 @@ pub struct FieldDef<'hir> { impl FieldDef<'_> { // Still necessary in couple of places pub fn is_positional(&self) -> bool { - let first = self.ident.as_str().as_bytes()[0]; - (b'0'..=b'9').contains(&first) + self.ident.as_str().as_bytes()[0].is_ascii_digit() } } diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs index e0698a72335f..a876f169c3aa 100644 --- a/compiler/rustc_hir_analysis/src/check/check.rs +++ b/compiler/rustc_hir_analysis/src/check/check.rs @@ -19,11 +19,13 @@ use rustc_lint_defs::builtin::REPR_TRANSPARENT_EXTERNAL_PRIVATE_FIELDS; use rustc_middle::hir::nested_filter; use rustc_middle::middle::stability::EvalResult; use rustc_middle::traits::DefiningAnchor; +use rustc_middle::ty::fold::BottomUpFolder; use rustc_middle::ty::layout::{LayoutError, MAX_SIMD_LANES}; use rustc_middle::ty::util::{Discr, IntTypeExt}; use rustc_middle::ty::GenericArgKind; use rustc_middle::ty::{ - self, AdtDef, ParamEnv, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, + self, AdtDef, ParamEnv, RegionKind, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, + TypeVisitableExt, }; use rustc_session::lint::builtin::{UNINHABITED_STATIC, UNSUPPORTED_CALLING_CONVENTIONS}; use rustc_span::symbol::sym; @@ -34,6 +36,7 @@ use rustc_trait_selection::traits::error_reporting::on_unimplemented::OnUnimplem use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt as _; use rustc_trait_selection::traits::outlives_bounds::InferCtxtExt as _; use rustc_trait_selection::traits::{self, ObligationCtxt, TraitEngine, TraitEngineExt as _}; +use rustc_type_ir::fold::TypeFoldable; use std::ops::ControlFlow; @@ -437,7 +440,7 @@ fn check_opaque_meets_bounds<'tcx>( // hidden type is well formed even without those bounds. let predicate = ty::Binder::dummy(ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(hidden_ty.into()))); - ocx.register_obligation(Obligation::new(tcx, misc_cause, param_env, predicate)); + ocx.register_obligation(Obligation::new(tcx, misc_cause.clone(), param_env, predicate)); // Check that all obligations are satisfied by the implementation's // version. @@ -464,11 +467,179 @@ fn check_opaque_meets_bounds<'tcx>( ocx.resolve_regions_and_report_errors(defining_use_anchor, &outlives_env)?; } } - // Clean up after ourselves - let _ = infcx.take_opaque_types(); + // Check that any hidden types found during wf checking match the hidden types that `type_of` sees. + for (key, mut ty) in infcx.take_opaque_types() { + ty.hidden_type.ty = infcx.resolve_vars_if_possible(ty.hidden_type.ty); + sanity_check_found_hidden_type(tcx, key, ty.hidden_type, defining_use_anchor, origin)?; + } Ok(()) } +fn sanity_check_found_hidden_type<'tcx>( + tcx: TyCtxt<'tcx>, + key: ty::OpaqueTypeKey<'tcx>, + mut ty: ty::OpaqueHiddenType<'tcx>, + defining_use_anchor: LocalDefId, + origin: &hir::OpaqueTyOrigin, +) -> Result<(), ErrorGuaranteed> { + if ty.ty.is_ty_var() { + // Nothing was actually constrained. + return Ok(()); + } + if let ty::Alias(ty::Opaque, alias) = ty.ty.kind() { + if alias.def_id == key.def_id.to_def_id() && alias.args == key.args { + // Nothing was actually constrained, this is an opaque usage that was + // only discovered to be opaque after inference vars resolved. + return Ok(()); + } + } + // Closures frequently end up containing erased lifetimes in their final representation. + // These correspond to lifetime variables that never got resolved, so we patch this up here. + ty.ty = ty.ty.fold_with(&mut BottomUpFolder { + tcx, + ty_op: |t| t, + ct_op: |c| c, + lt_op: |l| match l.kind() { + RegionKind::ReVar(_) => tcx.lifetimes.re_erased, + _ => l, + }, + }); + // Get the hidden type. + let mut hidden_ty = tcx.type_of(key.def_id).instantiate(tcx, key.args); + if let hir::OpaqueTyOrigin::FnReturn(..) | hir::OpaqueTyOrigin::AsyncFn(..) = origin { + if hidden_ty != ty.ty { + hidden_ty = find_and_apply_rpit_args( + tcx, + hidden_ty, + defining_use_anchor.to_def_id(), + key.def_id.to_def_id(), + )?; + } + } + + // If the hidden types differ, emit a type mismatch diagnostic. + if hidden_ty == ty.ty { + Ok(()) + } else { + let span = tcx.def_span(key.def_id); + let other = ty::OpaqueHiddenType { ty: hidden_ty, span }; + Err(ty.report_mismatch(&other, key.def_id, tcx).emit()) + } +} + +/// In case it is in a nested opaque type, find that opaque type's +/// usage in the function signature and use the generic arguments from the usage site. +/// We need to do because RPITs ignore the lifetimes of the function, +/// as they have their own copies of all the lifetimes they capture. +/// So the only way to get the lifetimes represented in terms of the function, +/// is to look how they are used in the function signature (or do some other fancy +/// recording of this mapping at ast -> hir lowering time). +/// +/// As an example: +/// ```text +/// trait Id { +/// type Assoc; +/// } +/// impl<'a> Id for &'a () { +/// type Assoc = &'a (); +/// } +/// fn func<'a>(x: &'a ()) -> impl Id { x } +/// // desugared to +/// fn func<'a>(x: &'a () -> Outer<'a> where as Id>::Assoc = Inner<'a> { +/// // Note that in contrast to other nested items, RPIT type aliases can +/// // access their parents' generics. +/// +/// // hidden type is `&'aDupOuter ()` +/// // During wfcheck the hidden type of `Inner<'aDupOuter>` is `&'a ()`, but +/// // `typeof(Inner<'aDupOuter>) = &'aDupOuter ()`. +/// // So we walk the signature of `func` to find the use of `Inner<'a>` +/// // and then use that to replace the lifetimes in the hidden type, obtaining +/// // `&'a ()`. +/// type Outer<'aDupOuter> = impl Id>; +/// +/// // hidden type is `&'aDupInner ()` +/// type Inner<'aDupInner> = impl Sized + 'aDupInner; +/// +/// x +/// } +/// ``` +fn find_and_apply_rpit_args<'tcx>( + tcx: TyCtxt<'tcx>, + mut hidden_ty: Ty<'tcx>, + function: DefId, + opaque: DefId, +) -> Result, ErrorGuaranteed> { + // Find use of the RPIT in the function signature and thus find the right args to + // convert it into the parameter space of the function signature. This is needed, + // because that's what `type_of` returns, against which we compare later. + let ret = tcx.fn_sig(function).instantiate_identity().output(); + struct Visitor<'tcx> { + tcx: TyCtxt<'tcx>, + opaque: DefId, + function: DefId, + seen: FxHashSet, + } + impl<'tcx> ty::TypeVisitor> for Visitor<'tcx> { + type BreakTy = GenericArgsRef<'tcx>; + + #[instrument(level = "trace", skip(self), ret)] + fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow { + trace!("{:#?}", t.kind()); + match t.kind() { + ty::Alias(ty::Opaque, alias) => { + trace!(?alias.def_id); + if alias.def_id == self.opaque { + return ControlFlow::Break(alias.args); + } else if self.seen.insert(alias.def_id) { + for clause in self + .tcx + .explicit_item_bounds(alias.def_id) + .iter_instantiated_copied(self.tcx, alias.args) + { + trace!(?clause); + clause.visit_with(self)?; + } + } + } + ty::Alias(ty::Projection, alias) => { + if self.tcx.is_impl_trait_in_trait(alias.def_id) + && self.tcx.impl_trait_in_trait_parent_fn(alias.def_id) == self.function + { + // If we're lowering to associated item, install the opaque type which is just + // the `type_of` of the trait's associated item. If we're using the old lowering + // strategy, then just reinterpret the associated type like an opaque :^) + self.tcx + .type_of(alias.def_id) + .instantiate(self.tcx, alias.args) + .visit_with(self)?; + } + } + ty::Alias(ty::Weak, alias) => { + self.tcx + .type_of(alias.def_id) + .instantiate(self.tcx, alias.args) + .visit_with(self)?; + } + _ => (), + } + + t.super_visit_with(self) + } + } + if let ControlFlow::Break(args) = + ret.visit_with(&mut Visitor { tcx, function, opaque, seen: Default::default() }) + { + trace!(?args); + trace!("expected: {hidden_ty:#?}"); + hidden_ty = ty::EarlyBinder::bind(hidden_ty).instantiate(tcx, args); + trace!("expected: {hidden_ty:#?}"); + } else { + tcx.sess + .delay_span_bug(tcx.def_span(function), format!("{ret:?} does not contain {opaque:?}")); + } + Ok(hidden_ty) +} + fn is_enum_of_nonnullable_ptr<'tcx>( tcx: TyCtxt<'tcx>, adt_def: AdtDef<'tcx>, diff --git a/compiler/rustc_hir_analysis/src/coherence/orphan.rs b/compiler/rustc_hir_analysis/src/coherence/orphan.rs index 21ffbefcd081..8d9a6f4d4461 100644 --- a/compiler/rustc_hir_analysis/src/coherence/orphan.rs +++ b/compiler/rustc_hir_analysis/src/coherence/orphan.rs @@ -352,7 +352,7 @@ fn emit_orphan_check_error<'tcx>( let this = |name: &str| { if !trait_ref.def_id.is_local() && !is_target_ty { - msg("this", &format!(" because this is a foreign trait")) + msg("this", " because this is a foreign trait") } else { msg("this", &format!(" because {name} are always foreign")) } diff --git a/compiler/rustc_hir_typeck/src/callee.rs b/compiler/rustc_hir_typeck/src/callee.rs index a24d1ff077f3..a1fd09d4050f 100644 --- a/compiler/rustc_hir_typeck/src/callee.rs +++ b/compiler/rustc_hir_typeck/src/callee.rs @@ -581,6 +581,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { callee_ty: Ty<'tcx>, arg_exprs: &'tcx [hir::Expr<'tcx>], ) -> ErrorGuaranteed { + // Callee probe fails when APIT references errors, so suppress those + // errors here. + if let Some((_, _, args)) = self.extract_callable_info(callee_ty) + && let Err(err) = args.error_reported() + { + return err; + } + let mut unit_variant = None; if let hir::ExprKind::Path(qpath) = &callee_expr.kind && let Res::Def(def::DefKind::Ctor(kind, CtorKind::Const), _) diff --git a/compiler/rustc_hir_typeck/src/cast.rs b/compiler/rustc_hir_typeck/src/cast.rs index 7597ce88f934..af8afcc0f0b9 100644 --- a/compiler/rustc_hir_typeck/src/cast.rs +++ b/compiler/rustc_hir_typeck/src/cast.rs @@ -705,10 +705,10 @@ impl<'a, 'tcx> CastCheck<'tcx> { ) }), |lint| { - lint.help(format!( + lint.help( "cast can be replaced by coercion; this might \ - require a temporary variable" - )) + require a temporary variable", + ) }, ); } diff --git a/compiler/rustc_hir_typeck/src/coercion.rs b/compiler/rustc_hir_typeck/src/coercion.rs index 3b1d9c8905b4..56e485a4a3c1 100644 --- a/compiler/rustc_hir_typeck/src/coercion.rs +++ b/compiler/rustc_hir_typeck/src/coercion.rs @@ -46,6 +46,7 @@ use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKi use rustc_infer::infer::{Coercion, DefineOpaqueTypes, InferOk, InferResult}; use rustc_infer::traits::{Obligation, PredicateObligation}; use rustc_middle::lint::in_external_macro; +use rustc_middle::traits::BuiltinImplSource; use rustc_middle::ty::adjustment::{ Adjust, Adjustment, AllowTwoPhase, AutoBorrow, AutoBorrowMutability, PointerCoercion, }; @@ -636,22 +637,6 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { Some(ty::PredicateKind::Clause(ty::ClauseKind::Trait(trait_pred))) if traits.contains(&trait_pred.def_id()) => { - let trait_pred = self.resolve_vars_if_possible(trait_pred); - if unsize_did == trait_pred.def_id() { - let self_ty = trait_pred.self_ty(); - let unsize_ty = trait_pred.trait_ref.args[1].expect_ty(); - if let (ty::Dynamic(ref data_a, ..), ty::Dynamic(ref data_b, ..)) = - (self_ty.kind(), unsize_ty.kind()) - && data_a.principal_def_id() != data_b.principal_def_id() - { - debug!("coerce_unsized: found trait upcasting coercion"); - has_trait_upcasting_coercion = Some((self_ty, unsize_ty)); - } - if let ty::Tuple(..) = unsize_ty.kind() { - debug!("coerce_unsized: found unsized tuple coercion"); - has_unsized_tuple_coercion = true; - } - } trait_pred } _ => { @@ -659,6 +644,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { continue; } }; + let trait_pred = self.resolve_vars_if_possible(trait_pred); match selcx.select(&obligation.with(selcx.tcx(), trait_pred)) { // Uncertain or unimplemented. Ok(None) => { @@ -701,20 +687,28 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { // be silent, as it causes a type mismatch later. } - Ok(Some(impl_source)) => queue.extend(impl_source.nested_obligations()), + Ok(Some(impl_source)) => { + // Some builtin coercions are still unstable so we detect + // these here and emit a feature error if coercion doesn't fail + // due to another reason. + match impl_source { + traits::ImplSource::Builtin( + BuiltinImplSource::TraitUpcasting { .. }, + _, + ) => { + has_trait_upcasting_coercion = + Some((trait_pred.self_ty(), trait_pred.trait_ref.args.type_at(1))); + } + traits::ImplSource::Builtin(BuiltinImplSource::TupleUnsizing, _) => { + has_unsized_tuple_coercion = true; + } + _ => {} + } + queue.extend(impl_source.nested_obligations()) + } } } - if has_unsized_tuple_coercion && !self.tcx.features().unsized_tuple_coercion { - feature_err( - &self.tcx.sess.parse_sess, - sym::unsized_tuple_coercion, - self.cause.span, - "unsized tuple coercion is not stable enough for use and is subject to change", - ) - .emit(); - } - if let Some((sub, sup)) = has_trait_upcasting_coercion && !self.tcx().features().trait_upcasting { @@ -730,6 +724,16 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { err.emit(); } + if has_unsized_tuple_coercion && !self.tcx.features().unsized_tuple_coercion { + feature_err( + &self.tcx.sess.parse_sess, + sym::unsized_tuple_coercion, + self.cause.span, + "unsized tuple coercion is not stable enough for use and is subject to change", + ) + .emit(); + } + Ok(coercion) } diff --git a/compiler/rustc_hir_typeck/src/demand.rs b/compiler/rustc_hir_typeck/src/demand.rs index 429c3366fedf..26fa3d80d553 100644 --- a/compiler/rustc_hir_typeck/src/demand.rs +++ b/compiler/rustc_hir_typeck/src/demand.rs @@ -53,7 +53,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { || self.suggest_no_capture_closure(err, expected, expr_ty) || self.suggest_boxing_when_appropriate(err, expr.span, expr.hir_id, expected, expr_ty) || self.suggest_block_to_brackets_peeling_refs(err, expr, expr_ty, expected) - || self.suggest_copied_or_cloned(err, expr, expr_ty, expected) + || self.suggest_copied_cloned_or_as_ref(err, expr, expr_ty, expected, expected_ty_expr) || self.suggest_clone_for_ref(err, expr, expr_ty, expected) || self.suggest_into(err, expr, expr_ty, expected) || self.suggest_floating_point_literal(err, expr, expected) @@ -621,7 +621,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // is in a different line, so we point at both. err.span_label(secondary_span, "expected due to the type of this binding"); err.span_label(primary_span, format!("expected due to this{post_message}")); - } else if post_message == "" { + } else if post_message.is_empty() { // We are pointing at either the assignment lhs or the binding def pattern. err.span_label(primary_span, "expected due to the type of this binding"); } else { diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs index 94f64a1ffdb6..fa1056e724a1 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs @@ -1069,7 +1069,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } else if let ExprKind::MethodCall(..) = rcvr.kind { err.span_note( sp, - modifies_rcvr_note.clone() + ", it is not meant to be used in method chains.", + modifies_rcvr_note + ", it is not meant to be used in method chains.", ); } else { err.span_note(sp, modifies_rcvr_note); diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs index ec19d017c259..4a1cbaceaf7e 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs @@ -1085,12 +1085,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { false } - pub(crate) fn suggest_copied_or_cloned( + pub(crate) fn suggest_copied_cloned_or_as_ref( &self, diag: &mut Diagnostic, expr: &hir::Expr<'_>, expr_ty: Ty<'tcx>, expected_ty: Ty<'tcx>, + expected_ty_expr: Option<&'tcx hir::Expr<'tcx>>, ) -> bool { let ty::Adt(adt_def, args) = expr_ty.kind() else { return false; @@ -1102,7 +1103,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { return false; } - let mut suggest_copied_or_cloned = || { + let mut suggest_copied_cloned_or_as_ref = || { let expr_inner_ty = args.type_at(0); let expected_inner_ty = expected_args.type_at(0); if let &ty::Ref(_, ty, hir::Mutability::Not) = expr_inner_ty.kind() @@ -1119,6 +1120,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { Applicability::MachineApplicable, ); return true; + } else if let Some(expected_ty_expr) = expected_ty_expr { + diag.span_suggestion_verbose( + expected_ty_expr.span.shrink_to_hi(), + format!( + "use `{def_path}::as_ref()` to convert `{expected_ty}` to `{expr_ty}`" + ), + ".as_ref()", + Applicability::MachineApplicable, + ); + return true; } else if let Some(clone_did) = self.tcx.lang_items().clone_trait() && rustc_trait_selection::traits::type_known_to_meet_bound_modulo_regions( self, @@ -1146,11 +1157,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // Check that the error types are equal && self.can_eq(self.param_env, args.type_at(1), expected_args.type_at(1)) { - return suggest_copied_or_cloned(); + return suggest_copied_cloned_or_as_ref(); } else if let Some(option_did) = self.tcx.get_diagnostic_item(sym::Option) && adt_def.did() == option_did { - return suggest_copied_or_cloned(); + return suggest_copied_cloned_or_as_ref(); } false @@ -1512,9 +1523,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { found_ty: Ty<'tcx>, expr: &hir::Expr<'_>, ) { + // When `expr` is `x` in something like `let x = foo.clone(); x`, need to recurse up to get + // `foo` and `clone`. + let expr = self.note_type_is_not_clone_inner_expr(expr); + + // If we've recursed to an `expr` of `foo.clone()`, get `foo` and `clone`. let hir::ExprKind::MethodCall(segment, callee_expr, &[], _) = expr.kind else { return; }; + let Some(clone_trait_did) = self.tcx.lang_items().clone_trait() else { return; }; @@ -1567,6 +1584,84 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } + /// Given a type mismatch error caused by `&T` being cloned instead of `T`, and + /// the `expr` as the source of this type mismatch, try to find the method call + /// as the source of this error and return that instead. Otherwise, return the + /// original expression. + fn note_type_is_not_clone_inner_expr<'b>( + &'b self, + expr: &'b hir::Expr<'b>, + ) -> &'b hir::Expr<'b> { + match expr.peel_blocks().kind { + hir::ExprKind::Path(hir::QPath::Resolved( + None, + hir::Path { segments: [_], res: crate::Res::Local(binding), .. }, + )) => { + let Some(hir::Node::Pat(hir::Pat { hir_id, .. })) = self.tcx.hir().find(*binding) + else { + return expr; + }; + let Some(parent) = self.tcx.hir().find(self.tcx.hir().parent_id(*hir_id)) else { + return expr; + }; + + match parent { + // foo.clone() + hir::Node::Local(hir::Local { init: Some(init), .. }) => { + self.note_type_is_not_clone_inner_expr(init) + } + // When `expr` is more complex like a tuple + hir::Node::Pat(hir::Pat { + hir_id: pat_hir_id, + kind: hir::PatKind::Tuple(pats, ..), + .. + }) => { + let Some(hir::Node::Local(hir::Local { init: Some(init), .. })) = + self.tcx.hir().find(self.tcx.hir().parent_id(*pat_hir_id)) else { + return expr; + }; + + match init.peel_blocks().kind { + ExprKind::Tup(init_tup) => { + if let Some(init) = pats + .iter() + .enumerate() + .filter(|x| x.1.hir_id == *hir_id) + .map(|(i, _)| init_tup.get(i).unwrap()) + .next() + { + self.note_type_is_not_clone_inner_expr(init) + } else { + expr + } + } + _ => expr, + } + } + _ => expr, + } + } + // If we're calling into a closure that may not be typed recurse into that call. no need + // to worry if it's a call to a typed function or closure as this would ne handled + // previously. + hir::ExprKind::Call(Expr { kind: call_expr_kind, .. }, _) => { + if let hir::ExprKind::Path(hir::QPath::Resolved(None, call_expr_path)) = call_expr_kind + && let hir::Path { segments: [_], res: crate::Res::Local(binding), .. } = call_expr_path + && let Some(hir::Node::Pat(hir::Pat { hir_id, .. })) = self.tcx.hir().find(*binding) + && let Some(closure) = self.tcx.hir().find(self.tcx.hir().parent_id(*hir_id)) + && let hir::Node::Local(hir::Local { init: Some(init), .. }) = closure + && let Expr { kind: hir::ExprKind::Closure(hir::Closure { body: body_id, .. }), ..} = init + { + let hir::Body { value: body_expr, .. } = self.tcx.hir().body(*body_id); + self.note_type_is_not_clone_inner_expr(body_expr) + } else { + expr + } + } + _ => expr, + } + } + /// A common error is to add an extra semicolon: /// /// ```compile_fail,E0308 diff --git a/compiler/rustc_hir_typeck/src/upvar.rs b/compiler/rustc_hir_typeck/src/upvar.rs index fb81a8395d79..22fe823acb76 100644 --- a/compiler/rustc_hir_typeck/src/upvar.rs +++ b/compiler/rustc_hir_typeck/src/upvar.rs @@ -932,7 +932,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { var_hir_id: hir::HirId, closure_clause: hir::CaptureBy, ) -> Option>> { - let auto_traits_def_id = vec![ + let auto_traits_def_id = [ self.tcx.lang_items().clone_trait(), self.tcx.lang_items().sync_trait(), self.tcx.get_diagnostic_item(sym::Send), diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs index 8e3c76d6a4b4..d3978e242a85 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs @@ -264,11 +264,11 @@ fn msg_span_from_named_region<'tcx>( ty::RePlaceholder(ty::PlaceholderRegion { bound: ty::BoundRegion { kind: ty::BoundRegionKind::BrAnon(Some(span)), .. }, .. - }) => (format!("the anonymous lifetime defined here"), Some(span)), + }) => ("the anonymous lifetime defined here".to_owned(), Some(span)), ty::RePlaceholder(ty::PlaceholderRegion { bound: ty::BoundRegion { kind: ty::BoundRegionKind::BrAnon(None), .. }, .. - }) => (format!("an anonymous lifetime"), None), + }) => ("an anonymous lifetime".to_owned(), None), _ => bug!("{:?}", region), } } @@ -2354,7 +2354,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { if let Ok(snip) = self.tcx.sess.source_map().span_to_next_source(p.span) && snip.starts_with(' ') { - format!("{new_lt}") + new_lt.to_string() } else { format!("{new_lt} ") } diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs index cc92bfbfdfeb..40dc64976113 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs @@ -333,11 +333,7 @@ pub fn suggest_new_region_bound( } else { None }; - let name = if let Some(name) = &existing_lt_name { - format!("{}", name) - } else { - format!("'a") - }; + let name = if let Some(name) = &existing_lt_name { name } else { "'a" }; // if there are more than one elided lifetimes in inputs, the explicit `'_` lifetime cannot be used. // introducing a new lifetime `'a` or making use of one from existing named lifetimes if any if let Some(id) = scope_def_id @@ -350,7 +346,7 @@ pub fn suggest_new_region_bound( if p.span.hi() - p.span.lo() == rustc_span::BytePos(1) { // Ampersand (elided without '_) (p.span.shrink_to_hi(),format!("{name} ")) } else { // Underscore (elided with '_) - (p.span, format!("{name}")) + (p.span, name.to_string()) } ) .collect::>() diff --git a/compiler/rustc_infer/src/infer/region_constraints/leak_check.rs b/compiler/rustc_infer/src/infer/region_constraints/leak_check.rs index dd65f66ccd14..b6ff8f2f512d 100644 --- a/compiler/rustc_infer/src/infer/region_constraints/leak_check.rs +++ b/compiler/rustc_infer/src/infer/region_constraints/leak_check.rs @@ -425,9 +425,11 @@ impl<'tcx> MiniGraph<'tcx> { } } } else { - for (constraint, _origin) in ®ion_constraints.data().constraints { - each_constraint(constraint) - } + region_constraints + .data() + .constraints + .keys() + .for_each(|constraint| each_constraint(constraint)); } } diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs index 12124f14a821..e3d66d18388c 100644 --- a/compiler/rustc_interface/src/tests.rs +++ b/compiler/rustc_interface/src/tests.rs @@ -740,6 +740,7 @@ fn test_unstable_options_tracking_hash() { untracked!(unstable_options, true); untracked!(validate_mir, true); untracked!(verbose, true); + untracked!(write_long_types_to_disk, false); // tidy-alphabetical-end macro_rules! tracked { diff --git a/compiler/rustc_lexer/src/cursor.rs b/compiler/rustc_lexer/src/cursor.rs index eceef59802eb..aba7f95487e9 100644 --- a/compiler/rustc_lexer/src/cursor.rs +++ b/compiler/rustc_lexer/src/cursor.rs @@ -24,6 +24,10 @@ impl<'a> Cursor<'a> { } } + pub fn as_str(&self) -> &'a str { + self.chars.as_str() + } + /// Returns the last eaten symbol (or `'\0'` in release builds). /// (For debug assertions only.) pub(crate) fn prev(&self) -> char { diff --git a/compiler/rustc_lexer/src/lib.rs b/compiler/rustc_lexer/src/lib.rs index 29335a8c0f4c..d511d2b1280d 100644 --- a/compiler/rustc_lexer/src/lib.rs +++ b/compiler/rustc_lexer/src/lib.rs @@ -367,6 +367,13 @@ impl Cursor<'_> { Some(|terminated| Byte { terminated }), ), + // c-string literal, raw c-string literal or identifier. + 'c' => self.c_or_byte_string( + |terminated| CStr { terminated }, + |n_hashes| RawCStr { n_hashes }, + None, + ), + // Identifier (this should be checked after other variant that can // start as identifier). c if is_id_start(c) => self.ident_or_unknown_prefix(), diff --git a/compiler/rustc_lexer/src/unescape.rs b/compiler/rustc_lexer/src/unescape.rs index c9ad54d8d980..717b042fbdab 100644 --- a/compiler/rustc_lexer/src/unescape.rs +++ b/compiler/rustc_lexer/src/unescape.rs @@ -372,7 +372,7 @@ where callback(start..end, EscapeError::MultipleSkippedLinesWarning); } let tail = &tail[first_non_space..]; - if let Some(c) = tail.chars().nth(0) { + if let Some(c) = tail.chars().next() { if c.is_whitespace() { // For error reporting, we would like the span to contain the character that was not // skipped. The +1 is necessary to account for the leading \ that started the escape. diff --git a/compiler/rustc_lint/src/types.rs b/compiler/rustc_lint/src/types.rs index cc8a34080040..3379479b1742 100644 --- a/compiler/rustc_lint/src/types.rs +++ b/compiler/rustc_lint/src/types.rs @@ -966,12 +966,12 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { args: GenericArgsRef<'tcx>, ) -> FfiResult<'tcx> { let field_ty = field.ty(self.cx.tcx, args); - if field_ty.has_opaque_types() { - self.check_type_for_ffi(cache, field_ty) - } else { - let field_ty = self.cx.tcx.normalize_erasing_regions(self.cx.param_env, field_ty); - self.check_type_for_ffi(cache, field_ty) - } + let field_ty = self + .cx + .tcx + .try_normalize_erasing_regions(self.cx.param_env, field_ty) + .unwrap_or(field_ty); + self.check_type_for_ffi(cache, field_ty) } /// Checks if the given `VariantDef`'s field types are "ffi-safe". @@ -1320,7 +1320,8 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { if let Some(ty) = self .cx .tcx - .normalize_erasing_regions(self.cx.param_env, ty) + .try_normalize_erasing_regions(self.cx.param_env, ty) + .unwrap_or(ty) .visit_with(&mut ProhibitOpaqueTypes) .break_value() { @@ -1338,16 +1339,12 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { is_static: bool, is_return_type: bool, ) { - // We have to check for opaque types before `normalize_erasing_regions`, - // which will replace opaque types with their underlying concrete type. if self.check_for_opaque_ty(sp, ty) { // We've already emitted an error due to an opaque type. return; } - // it is only OK to use this function because extern fns cannot have - // any generic types right now: - let ty = self.cx.tcx.normalize_erasing_regions(self.cx.param_env, ty); + let ty = self.cx.tcx.try_normalize_erasing_regions(self.cx.param_env, ty).unwrap_or(ty); // C doesn't really support passing arrays by value - the only way to pass an array by value // is through a struct. So, first test that the top level isn't an array, and then diff --git a/compiler/rustc_metadata/src/fs.rs b/compiler/rustc_metadata/src/fs.rs index 238f963ed463..69a77e82f987 100644 --- a/compiler/rustc_metadata/src/fs.rs +++ b/compiler/rustc_metadata/src/fs.rs @@ -104,8 +104,8 @@ pub fn encode_and_write_metadata(tcx: TyCtxt<'_>) -> (EncodedMetadata, bool) { }; // Load metadata back to memory: codegen may need to include it in object files. - let metadata = EncodedMetadata::from_path(metadata_filename.clone(), metadata_tmpdir) - .unwrap_or_else(|err| { + let metadata = + EncodedMetadata::from_path(metadata_filename, metadata_tmpdir).unwrap_or_else(|err| { tcx.sess.emit_fatal(FailedCreateEncodedMetadata { err }); }); diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index ac86110f2bdb..8f065dd6b580 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -2244,13 +2244,12 @@ pub fn provide(providers: &mut Providers) { tcx.resolutions(()) .doc_link_resolutions .get(&def_id) - .expect("no resolutions for a doc link") + .unwrap_or_else(|| span_bug!(tcx.def_span(def_id), "no resolutions for a doc link")) }, doc_link_traits_in_scope: |tcx, def_id| { - tcx.resolutions(()) - .doc_link_traits_in_scope - .get(&def_id) - .expect("no traits in scope for a doc link") + tcx.resolutions(()).doc_link_traits_in_scope.get(&def_id).unwrap_or_else(|| { + span_bug!(tcx.def_span(def_id), "no traits in scope for a doc link") + }) }, traits: |tcx, LocalCrate| { let mut traits = Vec::new(); diff --git a/compiler/rustc_middle/src/macros.rs b/compiler/rustc_middle/src/macros.rs index cd1c6c330bc1..fca16d8e509f 100644 --- a/compiler/rustc_middle/src/macros.rs +++ b/compiler/rustc_middle/src/macros.rs @@ -43,7 +43,7 @@ macro_rules! span_bug { #[macro_export] macro_rules! CloneLiftImpls { - ($($ty:ty,)+) => { + ($($ty:ty),+ $(,)?) => { $( impl<'tcx> $crate::ty::Lift<'tcx> for $ty { type Lifted = Self; @@ -59,7 +59,7 @@ macro_rules! CloneLiftImpls { /// allocated data** (i.e., don't need to be folded). #[macro_export] macro_rules! TrivialTypeTraversalImpls { - ($($ty:ty,)+) => { + ($($ty:ty),+ $(,)?) => { $( impl<'tcx> $crate::ty::fold::TypeFoldable<$crate::ty::TyCtxt<'tcx>> for $ty { fn try_fold_with>>( diff --git a/compiler/rustc_middle/src/mir/basic_blocks.rs b/compiler/rustc_middle/src/mir/basic_blocks.rs index 7722e7b47cff..0ad17e819c74 100644 --- a/compiler/rustc_middle/src/mir/basic_blocks.rs +++ b/compiler/rustc_middle/src/mir/basic_blocks.rs @@ -178,9 +178,7 @@ impl<'tcx> graph::WithPredecessors for BasicBlocks<'tcx> { } } -TrivialTypeTraversalAndLiftImpls! { - Cache, -} +TrivialTypeTraversalAndLiftImpls! { Cache } impl Encodable for Cache { #[inline] diff --git a/compiler/rustc_middle/src/mir/interpret/allocation.rs b/compiler/rustc_middle/src/mir/interpret/allocation.rs index b8030d9db13c..c1cb2f2e497f 100644 --- a/compiler/rustc_middle/src/mir/interpret/allocation.rs +++ b/compiler/rustc_middle/src/mir/interpret/allocation.rs @@ -571,7 +571,7 @@ impl Allocation assert!(self.mutability == Mutability::Mut); // `to_bits_or_ptr_internal` is the right method because we just want to store this data - // as-is into memory. + // as-is into memory. This also double-checks that `val.size()` matches `range.size`. let (bytes, provenance) = match val.to_bits_or_ptr_internal(range.size)? { Right(ptr) => { let (provenance, offset) = ptr.into_parts(); diff --git a/compiler/rustc_middle/src/mir/interpret/error.rs b/compiler/rustc_middle/src/mir/interpret/error.rs index 372452ea29a8..6161b16fc466 100644 --- a/compiler/rustc_middle/src/mir/interpret/error.rs +++ b/compiler/rustc_middle/src/mir/interpret/error.rs @@ -12,7 +12,8 @@ use rustc_errors::{ use rustc_macros::HashStable; use rustc_session::CtfeBacktrace; use rustc_span::def_id::DefId; -use rustc_target::abi::{call, Align, Size, WrappingRange}; +use rustc_target::abi::{call, Align, Size, VariantIdx, WrappingRange}; + use std::borrow::Cow; use std::{any::Any, backtrace::Backtrace, fmt}; @@ -66,9 +67,7 @@ impl Into for ReportedErrorInfo { } } -TrivialTypeTraversalAndLiftImpls! { - ErrorHandled, -} +TrivialTypeTraversalAndLiftImpls! { ErrorHandled } pub type EvalToAllocationRawResult<'tcx> = Result, ErrorHandled>; pub type EvalToConstValueResult<'tcx> = Result, ErrorHandled>; @@ -191,9 +190,8 @@ pub enum InvalidProgramInfo<'tcx> { FnAbiAdjustForForeignAbi(call::AdjustForForeignAbiError), /// SizeOf of unsized type was requested. SizeOfUnsizedType(Ty<'tcx>), - /// An unsized local was accessed without having been initialized. - /// This is not meaningful as we can't even have backing memory for such locals. - UninitUnsizedLocal, + /// We are runnning into a nonsense situation due to ConstProp violating our invariants. + ConstPropNonsense, } /// Details of why a pointer had to be in-bounds. @@ -324,7 +322,9 @@ pub enum UndefinedBehaviorInfo<'a> { /// Data size is not equal to target size. ScalarSizeMismatch(ScalarSizeMismatch), /// A discriminant of an uninhabited enum variant is written. - UninhabitedEnumVariantWritten, + UninhabitedEnumVariantWritten(VariantIdx), + /// An uninhabited enum variant is projected. + UninhabitedEnumVariantRead(VariantIdx), /// Validation error. Validation(ValidationErrorInfo<'a>), // FIXME(fee1-dead) these should all be actual variants of the enum instead of dynamically @@ -394,6 +394,7 @@ pub enum ValidationErrorKind<'tcx> { UnsafeCell, UninhabitedVal { ty: Ty<'tcx> }, InvalidEnumTag { value: String }, + UninhabitedEnumTag, UninitEnumTag, UninitStr, Uninit { expected: ExpectedKind }, diff --git a/compiler/rustc_middle/src/mir/interpret/value.rs b/compiler/rustc_middle/src/mir/interpret/value.rs index 0416411dfe14..47421d0f0371 100644 --- a/compiler/rustc_middle/src/mir/interpret/value.rs +++ b/compiler/rustc_middle/src/mir/interpret/value.rs @@ -320,6 +320,14 @@ impl Scalar { } }) } + + #[inline] + pub fn size(self) -> Size { + match self { + Scalar::Int(int) => int.size(), + Scalar::Ptr(_ptr, sz) => Size::from_bytes(sz), + } + } } impl<'tcx, Prov: Provenance> Scalar { diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs index 97f53a59fd66..3a9585485155 100644 --- a/compiler/rustc_middle/src/mir/mod.rs +++ b/compiler/rustc_middle/src/mir/mod.rs @@ -706,9 +706,7 @@ pub enum BindingForm<'tcx> { RefForGuard, } -TrivialTypeTraversalAndLiftImpls! { - BindingForm<'tcx>, -} +TrivialTypeTraversalAndLiftImpls! { BindingForm<'tcx> } mod binding_form_impl { use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index b36f0df78f12..fb7965873529 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -2064,9 +2064,9 @@ rustc_queries! { } } - query is_impossible_method(key: (DefId, DefId)) -> bool { + query is_impossible_associated_item(key: (DefId, DefId)) -> bool { desc { |tcx| - "checking if `{}` is impossible to call within `{}`", + "checking if `{}` is impossible to reference within `{}`", tcx.def_path_str(key.1), tcx.def_path_str(key.0), } diff --git a/compiler/rustc_middle/src/traits/mod.rs b/compiler/rustc_middle/src/traits/mod.rs index b7ffed57a0be..a2b33bb2737a 100644 --- a/compiler/rustc_middle/src/traits/mod.rs +++ b/compiler/rustc_middle/src/traits/mod.rs @@ -649,43 +649,31 @@ pub enum ImplSource<'tcx, N> { /// for some type parameter. The `Vec` represents the /// obligations incurred from normalizing the where-clause (if /// any). - Param(Vec, ty::BoundConstness), + Param(ty::BoundConstness, Vec), - /// Virtual calls through an object. - Object(ImplSourceObjectData), - - /// Successful resolution for a builtin trait. - Builtin(Vec), - - /// ImplSource for trait upcasting coercion - TraitUpcasting(ImplSourceTraitUpcastingData), + /// Successful resolution for a builtin impl. + Builtin(BuiltinImplSource, Vec), } impl<'tcx, N> ImplSource<'tcx, N> { pub fn nested_obligations(self) -> Vec { match self { ImplSource::UserDefined(i) => i.nested, - ImplSource::Param(n, _) | ImplSource::Builtin(n) => n, - ImplSource::Object(d) => d.nested, - ImplSource::TraitUpcasting(d) => d.nested, + ImplSource::Param(_, n) | ImplSource::Builtin(_, n) => n, } } pub fn borrow_nested_obligations(&self) -> &[N] { match self { ImplSource::UserDefined(i) => &i.nested, - ImplSource::Param(n, _) | ImplSource::Builtin(n) => &n, - ImplSource::Object(d) => &d.nested, - ImplSource::TraitUpcasting(d) => &d.nested, + ImplSource::Param(_, n) | ImplSource::Builtin(_, n) => &n, } } pub fn borrow_nested_obligations_mut(&mut self) -> &mut [N] { match self { ImplSource::UserDefined(i) => &mut i.nested, - ImplSource::Param(n, _) | ImplSource::Builtin(n) => n, - ImplSource::Object(d) => &mut d.nested, - ImplSource::TraitUpcasting(d) => &mut d.nested, + ImplSource::Param(_, n) | ImplSource::Builtin(_, n) => n, } } @@ -699,17 +687,9 @@ impl<'tcx, N> ImplSource<'tcx, N> { args: i.args, nested: i.nested.into_iter().map(f).collect(), }), - ImplSource::Param(n, ct) => ImplSource::Param(n.into_iter().map(f).collect(), ct), - ImplSource::Builtin(n) => ImplSource::Builtin(n.into_iter().map(f).collect()), - ImplSource::Object(o) => ImplSource::Object(ImplSourceObjectData { - vtable_base: o.vtable_base, - nested: o.nested.into_iter().map(f).collect(), - }), - ImplSource::TraitUpcasting(d) => { - ImplSource::TraitUpcasting(ImplSourceTraitUpcastingData { - vtable_vptr_slot: d.vtable_vptr_slot, - nested: d.nested.into_iter().map(f).collect(), - }) + ImplSource::Param(ct, n) => ImplSource::Param(ct, n.into_iter().map(f).collect()), + ImplSource::Builtin(source, n) => { + ImplSource::Builtin(source, n.into_iter().map(f).collect()) } } } @@ -733,30 +713,32 @@ pub struct ImplSourceUserDefinedData<'tcx, N> { pub nested: Vec, } -#[derive(Clone, PartialEq, Eq, TyEncodable, TyDecodable, HashStable, Lift)] -#[derive(TypeFoldable, TypeVisitable)] -pub struct ImplSourceTraitUpcastingData { - /// The vtable is formed by concatenating together the method lists of - /// the base object trait and all supertraits, pointers to supertrait vtable will - /// be provided when necessary; this is the position of `upcast_trait_ref`'s vtable - /// within that vtable. - pub vtable_vptr_slot: Option, - - pub nested: Vec, -} - -#[derive(PartialEq, Eq, Clone, TyEncodable, TyDecodable, HashStable, Lift)] -#[derive(TypeFoldable, TypeVisitable)] -pub struct ImplSourceObjectData { +#[derive(Copy, Clone, PartialEq, Eq, TyEncodable, TyDecodable, HashStable, Debug)] +pub enum BuiltinImplSource { + /// Some builtin impl we don't need to differentiate. This should be used + /// unless more specific information is necessary. + Misc, + /// A builtin impl for trait objects. + /// /// The vtable is formed by concatenating together the method lists of /// the base object trait and all supertraits, pointers to supertrait vtable will /// be provided when necessary; this is the start of `upcast_trait_ref`'s methods /// in that vtable. - pub vtable_base: usize, - - pub nested: Vec, + Object { vtable_base: usize }, + /// The vtable is formed by concatenating together the method lists of + /// the base object trait and all supertraits, pointers to supertrait vtable will + /// be provided when necessary; this is the position of `upcast_trait_ref`'s vtable + /// within that vtable. + TraitUpcasting { vtable_vptr_slot: Option }, + /// Unsizing a tuple like `(A, B, ..., X)` to `(A, B, ..., Y)` if `X` unsizes to `Y`. + /// + /// This needs to be a separate variant as it is still unstable and we need to emit + /// a feature error when using it on stable. + TupleUnsizing, } +TrivialTypeTraversalAndLiftImpls! { BuiltinImplSource } + #[derive(Clone, Debug, PartialEq, Eq, Hash, HashStable, PartialOrd, Ord)] pub enum ObjectSafetyViolation { /// `Self: Sized` declared on the trait. diff --git a/compiler/rustc_middle/src/traits/select.rs b/compiler/rustc_middle/src/traits/select.rs index f2dda003b99c..a90d58f5fc17 100644 --- a/compiler/rustc_middle/src/traits/select.rs +++ b/compiler/rustc_middle/src/traits/select.rs @@ -304,9 +304,7 @@ impl From for OverflowError { } } -TrivialTypeTraversalAndLiftImpls! { - OverflowError, -} +TrivialTypeTraversalAndLiftImpls! { OverflowError } impl<'tcx> From for SelectionError<'tcx> { fn from(overflow_error: OverflowError) -> SelectionError<'tcx> { diff --git a/compiler/rustc_middle/src/traits/solve/inspect.rs b/compiler/rustc_middle/src/traits/solve/inspect.rs index 8698cf860226..e793f481995f 100644 --- a/compiler/rustc_middle/src/traits/solve/inspect.rs +++ b/compiler/rustc_middle/src/traits/solve/inspect.rs @@ -73,8 +73,12 @@ pub struct GoalCandidate<'tcx> { pub enum CandidateKind<'tcx> { /// Probe entered when normalizing the self ty during candidate assembly NormalizedSelfTyAssembly, + DynUpcastingAssembly, /// A normal candidate for proving a goal - Candidate { name: String, result: QueryResult<'tcx> }, + Candidate { + name: String, + result: QueryResult<'tcx>, + }, } impl Debug for GoalCandidate<'_> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { diff --git a/compiler/rustc_middle/src/traits/solve/inspect/format.rs b/compiler/rustc_middle/src/traits/solve/inspect/format.rs index f19f1189e444..39f84279259c 100644 --- a/compiler/rustc_middle/src/traits/solve/inspect/format.rs +++ b/compiler/rustc_middle/src/traits/solve/inspect/format.rs @@ -15,11 +15,11 @@ struct Indentor<'a, 'b> { impl Write for Indentor<'_, '_> { fn write_str(&mut self, s: &str) -> std::fmt::Result { - for line in s.split_inclusive("\n") { + for line in s.split_inclusive('\n') { if self.on_newline { self.f.write_str(" ")?; } - self.on_newline = line.ends_with("\n"); + self.on_newline = line.ends_with('\n'); self.f.write_str(line)?; } @@ -100,6 +100,9 @@ impl<'a, 'b> ProofTreeFormatter<'a, 'b> { CandidateKind::NormalizedSelfTyAssembly => { writeln!(self.f, "NORMALIZING SELF TY FOR ASSEMBLY:") } + CandidateKind::DynUpcastingAssembly => { + writeln!(self.f, "ASSEMBLING CANDIDATES FOR DYN UPCASTING:") + } CandidateKind::Candidate { name, result } => { writeln!(self.f, "CANDIDATE {}: {:?}", name, result) } diff --git a/compiler/rustc_middle/src/traits/structural_impls.rs b/compiler/rustc_middle/src/traits/structural_impls.rs index e2cd118500b6..530d1ec5d353 100644 --- a/compiler/rustc_middle/src/traits/structural_impls.rs +++ b/compiler/rustc_middle/src/traits/structural_impls.rs @@ -6,18 +6,16 @@ use std::fmt; impl<'tcx, N: fmt::Debug> fmt::Debug for traits::ImplSource<'tcx, N> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match *self { - super::ImplSource::UserDefined(ref v) => write!(f, "{:?}", v), + match self { + super::ImplSource::UserDefined(v) => write!(f, "{:?}", v), - super::ImplSource::Builtin(ref d) => write!(f, "{:?}", d), - - super::ImplSource::Object(ref d) => write!(f, "{:?}", d), - - super::ImplSource::Param(ref n, ct) => { - write!(f, "ImplSourceParamData({:?}, {:?})", n, ct) + super::ImplSource::Builtin(source, d) => { + write!(f, "Builtin({source:?}, {d:?})") } - super::ImplSource::TraitUpcasting(ref d) => write!(f, "{:?}", d), + super::ImplSource::Param(ct, n) => { + write!(f, "ImplSourceParamData({:?}, {:?})", n, ct) + } } } } @@ -31,23 +29,3 @@ impl<'tcx, N: fmt::Debug> fmt::Debug for traits::ImplSourceUserDefinedData<'tcx, ) } } - -impl fmt::Debug for traits::ImplSourceTraitUpcastingData { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!( - f, - "ImplSourceTraitUpcastingData(vtable_vptr_slot={:?}, nested={:?})", - self.vtable_vptr_slot, self.nested - ) - } -} - -impl fmt::Debug for traits::ImplSourceObjectData { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!( - f, - "ImplSourceObjectData(vtable_base={}, nested={:?})", - self.vtable_base, self.nested - ) - } -} diff --git a/compiler/rustc_middle/src/ty/abstract_const.rs b/compiler/rustc_middle/src/ty/abstract_const.rs index 0364a620810a..cdd8351499b4 100644 --- a/compiler/rustc_middle/src/ty/abstract_const.rs +++ b/compiler/rustc_middle/src/ty/abstract_const.rs @@ -27,9 +27,7 @@ impl From for NotConstEvaluatable { } } -TrivialTypeTraversalAndLiftImpls! { - NotConstEvaluatable, -} +TrivialTypeTraversalAndLiftImpls! { NotConstEvaluatable } pub type BoundAbstractConst<'tcx> = Result>>, ErrorGuaranteed>; diff --git a/compiler/rustc_middle/src/ty/binding.rs b/compiler/rustc_middle/src/ty/binding.rs index a5b05a4f9b52..2fec8ac90956 100644 --- a/compiler/rustc_middle/src/ty/binding.rs +++ b/compiler/rustc_middle/src/ty/binding.rs @@ -6,7 +6,7 @@ pub enum BindingMode { BindByValue(Mutability), } -TrivialTypeTraversalAndLiftImpls! { BindingMode, } +TrivialTypeTraversalAndLiftImpls! { BindingMode } impl BindingMode { pub fn convert(BindingAnnotation(by_ref, mutbl): BindingAnnotation) -> BindingMode { diff --git a/compiler/rustc_middle/src/ty/error.rs b/compiler/rustc_middle/src/ty/error.rs index c794c3faded1..3fdbaf5e9477 100644 --- a/compiler/rustc_middle/src/ty/error.rs +++ b/compiler/rustc_middle/src/ty/error.rs @@ -339,12 +339,17 @@ impl<'tcx> TyCtxt<'tcx> { } pub fn short_ty_string(self, ty: Ty<'tcx>) -> (String, Option) { - let width = self.sess.diagnostic_width(); - let length_limit = width.saturating_sub(30); let regular = FmtPrinter::new(self, hir::def::Namespace::TypeNS) .pretty_print_type(ty) .expect("could not write to `String`") .into_buffer(); + + if !self.sess.opts.unstable_opts.write_long_types_to_disk { + return (regular, None); + } + + let width = self.sess.diagnostic_width(); + let length_limit = width.saturating_sub(30); if regular.len() <= width { return (regular, None); } diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs index 62805d1e8b5c..81e7dc3728ab 100644 --- a/compiler/rustc_middle/src/ty/layout.rs +++ b/compiler/rustc_middle/src/ty/layout.rs @@ -741,9 +741,9 @@ where let fields = match this.ty.kind() { ty::Adt(def, _) if def.variants().is_empty() => - bug!("for_variant called on zero-variant enum"), + bug!("for_variant called on zero-variant enum {}", this.ty), ty::Adt(def, _) => def.variant(variant_index).fields.len(), - _ => bug!(), + _ => bug!("`ty_and_layout_for_variant` on unexpected type {}", this.ty), }; tcx.mk_layout(LayoutS { variants: Variants::Single { index: variant_index }, diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index f9c1ca9a8b16..3e023ccdead6 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -2670,11 +2670,6 @@ impl<'tcx> Ty<'tcx> { variant_index: VariantIdx, ) -> Option> { match self.kind() { - TyKind::Adt(adt, _) if adt.variants().is_empty() => { - // This can actually happen during CTFE, see - // https://github.com/rust-lang/rust/issues/89765. - None - } TyKind::Adt(adt, _) if adt.is_enum() => { Some(adt.discriminant_for_variant(tcx, variant_index)) } diff --git a/compiler/rustc_monomorphize/src/partitioning.rs b/compiler/rustc_monomorphize/src/partitioning.rs index 71aef53192f4..c34c2c248fe5 100644 --- a/compiler/rustc_monomorphize/src/partitioning.rs +++ b/compiler/rustc_monomorphize/src/partitioning.rs @@ -1041,10 +1041,7 @@ fn debug_dump<'a, 'tcx: 'a>(tcx: TyCtxt<'tcx>, label: &str, cgus: &[CodegenUnit< } elem(curr, curr_count); - let mut s = "[".to_string(); - s.push_str(&v.join(", ")); - s.push_str("]"); - s + format!("[{}]", v.join(", ")) } }; @@ -1229,12 +1226,13 @@ fn dump_mono_items_stats<'tcx>( // Gather instantiated mono items grouped by def_id let mut items_per_def_id: FxHashMap<_, Vec<_>> = Default::default(); for cgu in codegen_units { - for (&mono_item, _) in cgu.items() { + cgu.items() + .keys() // Avoid variable-sized compiler-generated shims - if mono_item.is_user_defined() { + .filter(|mono_item| mono_item.is_user_defined()) + .for_each(|mono_item| { items_per_def_id.entry(mono_item.def_id()).or_default().push(mono_item); - } - } + }); } #[derive(serde::Serialize)] @@ -1287,7 +1285,7 @@ fn codegened_and_inlined_items(tcx: TyCtxt<'_>, (): ()) -> &DefIdSet { let mut result = items.clone(); for cgu in cgus { - for (item, _) in cgu.items() { + for item in cgu.items().keys() { if let MonoItem::Fn(ref instance) = item { let did = instance.def_id(); if !visited.insert(did) { diff --git a/compiler/rustc_parse/src/lexer/mod.rs b/compiler/rustc_parse/src/lexer/mod.rs index c6e6b46e4551..1931ee5e528d 100644 --- a/compiler/rustc_parse/src/lexer/mod.rs +++ b/compiler/rustc_parse/src/lexer/mod.rs @@ -9,8 +9,8 @@ use rustc_ast::tokenstream::TokenStream; use rustc_ast::util::unicode::contains_text_flow_control_chars; use rustc_errors::{error_code, Applicability, Diagnostic, DiagnosticBuilder, StashKey}; use rustc_lexer::unescape::{self, EscapeError, Mode}; -use rustc_lexer::Cursor; use rustc_lexer::{Base, DocStyle, RawStrError}; +use rustc_lexer::{Cursor, LiteralKind}; use rustc_session::lint::builtin::{ RUST_2021_PREFIXES_INCOMPATIBLE_SYNTAX, TEXT_DIRECTION_CODEPOINT_IN_COMMENT, }; @@ -118,6 +118,7 @@ impl<'a> StringReader<'a> { let mut swallow_next_invalid = 0; // Skip trivial (whitespace & comments) tokens loop { + let str_before = self.cursor.as_str(); let token = self.cursor.advance_token(); let start = self.pos; self.pos = self.pos + BytePos(token.len); @@ -165,10 +166,7 @@ impl<'a> StringReader<'a> { continue; } rustc_lexer::TokenKind::Ident => { - let sym = nfc_normalize(self.str_from(start)); - let span = self.mk_sp(start, self.pos); - self.sess.symbol_gallery.insert(sym, span); - token::Ident(sym, false) + self.ident(start) } rustc_lexer::TokenKind::RawIdent => { let sym = nfc_normalize(self.str_from(start + BytePos(2))); @@ -182,10 +180,7 @@ impl<'a> StringReader<'a> { } rustc_lexer::TokenKind::UnknownPrefix => { self.report_unknown_prefix(start); - let sym = nfc_normalize(self.str_from(start)); - let span = self.mk_sp(start, self.pos); - self.sess.symbol_gallery.insert(sym, span); - token::Ident(sym, false) + self.ident(start) } rustc_lexer::TokenKind::InvalidIdent // Do not recover an identifier with emoji if the codepoint is a confusable @@ -203,6 +198,27 @@ impl<'a> StringReader<'a> { .push(span); token::Ident(sym, false) } + // split up (raw) c string literals to an ident and a string literal when edition < 2021. + rustc_lexer::TokenKind::Literal { + kind: kind @ (LiteralKind::CStr { .. } | LiteralKind::RawCStr { .. }), + suffix_start: _, + } if !self.mk_sp(start, self.pos).edition().at_least_rust_2021() => { + let prefix_len = match kind { + LiteralKind::CStr { .. } => 1, + LiteralKind::RawCStr { .. } => 2, + _ => unreachable!(), + }; + + // reset the state so that only the prefix ("c" or "cr") + // was consumed. + let lit_start = start + BytePos(prefix_len); + self.pos = lit_start; + self.cursor = Cursor::new(&str_before[prefix_len as usize..]); + + self.report_unknown_prefix(start); + let prefix_span = self.mk_sp(start, lit_start); + return (Token::new(self.ident(start), prefix_span), preceded_by_whitespace); + } rustc_lexer::TokenKind::Literal { kind, suffix_start } => { let suffix_start = start + BytePos(suffix_start); let (kind, symbol) = self.cook_lexer_literal(start, suffix_start, kind); @@ -317,6 +333,13 @@ impl<'a> StringReader<'a> { } } + fn ident(&self, start: BytePos) -> TokenKind { + let sym = nfc_normalize(self.str_from(start)); + let span = self.mk_sp(start, self.pos); + self.sess.symbol_gallery.insert(sym, span); + token::Ident(sym, false) + } + fn struct_fatal_span_char( &self, from_pos: BytePos, diff --git a/compiler/rustc_parse/src/lexer/unescape_error_reporting.rs b/compiler/rustc_parse/src/lexer/unescape_error_reporting.rs index 461a34b67db6..d1f852b1a405 100644 --- a/compiler/rustc_parse/src/lexer/unescape_error_reporting.rs +++ b/compiler/rustc_parse/src/lexer/unescape_error_reporting.rs @@ -27,7 +27,7 @@ pub(crate) fn emit_unescape_error( lit, span_with_quotes, mode, range, error ); let last_char = || { - let c = lit[range.clone()].chars().rev().next().unwrap(); + let c = lit[range.clone()].chars().next_back().unwrap(); let span = span.with_lo(span.hi() - BytePos(c.len_utf8() as u32)); (c, span) }; diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index 769415b614b0..b54cb8c5a0c1 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -238,7 +238,7 @@ impl<'a> Parser<'a> { _ => unreachable!(), } .into(); - let invalid = format!("{}=", &sugg); + let invalid = format!("{sugg}="); self.sess.emit_err(errors::InvalidComparisonOperator { span: sp, invalid: invalid.clone(), diff --git a/compiler/rustc_parse/src/parser/generics.rs b/compiler/rustc_parse/src/parser/generics.rs index 8ab38c4fb8be..242c9d332bb0 100644 --- a/compiler/rustc_parse/src/parser/generics.rs +++ b/compiler/rustc_parse/src/parser/generics.rs @@ -49,7 +49,7 @@ impl<'a> Parser<'a> { && self.check_ident() // `Const` followed by IDENT { - return Ok(self.recover_const_param_with_mistyped_const(preceding_attrs, ident)?); + return self.recover_const_param_with_mistyped_const(preceding_attrs, ident); } // Parse optional colon and param bounds. diff --git a/compiler/rustc_parse/src/validate_attr.rs b/compiler/rustc_parse/src/validate_attr.rs index 928fdce313d9..2011083019c8 100644 --- a/compiler/rustc_parse/src/validate_attr.rs +++ b/compiler/rustc_parse/src/validate_attr.rs @@ -157,15 +157,15 @@ fn emit_malformed_attribute( matches!(name, sym::doc | sym::ignore | sym::inline | sym::link | sym::test | sym::bench) }; - let error_msg = format!("malformed `{}` attribute input", name); + let error_msg = format!("malformed `{name}` attribute input"); let mut msg = "attribute must be of the form ".to_owned(); let mut suggestions = vec![]; let mut first = true; let inner = if style == ast::AttrStyle::Inner { "!" } else { "" }; if template.word { first = false; - let code = format!("#{}[{}]", inner, name); - msg.push_str(&format!("`{}`", &code)); + let code = format!("#{inner}[{name}]"); + msg.push_str(&format!("`{code}`")); suggestions.push(code); } if let Some(descr) = template.list { @@ -173,16 +173,16 @@ fn emit_malformed_attribute( msg.push_str(" or "); } first = false; - let code = format!("#{}[{}({})]", inner, name, descr); - msg.push_str(&format!("`{}`", &code)); + let code = format!("#{inner}[{name}({descr})]"); + msg.push_str(&format!("`{code}`")); suggestions.push(code); } if let Some(descr) = template.name_value_str { if !first { msg.push_str(" or "); } - let code = format!("#{}[{} = \"{}\"]", inner, name, descr); - msg.push_str(&format!("`{}`", &code)); + let code = format!("#{inner}[{name} = \"{descr}\"]"); + msg.push_str(&format!("`{code}`")); suggestions.push(code); } if should_warn(name) { diff --git a/compiler/rustc_passes/messages.ftl b/compiler/rustc_passes/messages.ftl index 0aa3d6265dce..5b3cc5d99cc7 100644 --- a/compiler/rustc_passes/messages.ftl +++ b/compiler/rustc_passes/messages.ftl @@ -211,6 +211,17 @@ passes_doc_keyword_not_mod = passes_doc_keyword_only_impl = `#[doc(keyword = "...")]` should be used on impl blocks +passes_doc_masked_not_extern_crate_self = + this attribute cannot be applied to an `extern crate self` item + .label = not applicable on `extern crate self` items + .extern_crate_self_label = `extern crate self` defined here + +passes_doc_masked_only_extern_crate = + this attribute can only be applied to an `extern crate` item + .label = only applicable on `extern crate` items + .not_an_extern_crate_label = not an `extern crate` item + .note = read for more information + passes_doc_test_literal = `#![doc(test(...)]` does not take a literal passes_doc_test_takes_list = diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index 4d7ebe3fefef..cbb030958c69 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -878,6 +878,44 @@ impl CheckAttrVisitor<'_> { } } + fn check_doc_masked( + &self, + attr: &Attribute, + meta: &NestedMetaItem, + hir_id: HirId, + target: Target, + ) -> bool { + if target != Target::ExternCrate { + self.tcx.emit_spanned_lint( + INVALID_DOC_ATTRIBUTES, + hir_id, + meta.span(), + errors::DocMaskedOnlyExternCrate { + attr_span: meta.span(), + item_span: (attr.style == AttrStyle::Outer) + .then(|| self.tcx.hir().span(hir_id)), + }, + ); + return false; + } + + if self.tcx.extern_mod_stmt_cnum(hir_id.owner).is_none() { + self.tcx.emit_spanned_lint( + INVALID_DOC_ATTRIBUTES, + hir_id, + meta.span(), + errors::DocMaskedNotExternCrateSelf { + attr_span: meta.span(), + item_span: (attr.style == AttrStyle::Outer) + .then(|| self.tcx.hir().span(hir_id)), + }, + ); + return false; + } + + true + } + /// Checks that an attribute is *not* used at the crate level. Returns `true` if valid. fn check_attr_not_crate_level( &self, @@ -1048,6 +1086,17 @@ impl CheckAttrVisitor<'_> { is_valid = false; } + sym::masked + if !self.check_doc_masked( + attr, + meta, + hir_id, + target, + ) => + { + is_valid = false; + } + // no_default_passes: deprecated // passes: deprecated // plugins: removed, but rustdoc warns about it itself diff --git a/compiler/rustc_passes/src/errors.rs b/compiler/rustc_passes/src/errors.rs index eae13f86049a..4f5514372d1e 100644 --- a/compiler/rustc_passes/src/errors.rs +++ b/compiler/rustc_passes/src/errors.rs @@ -267,6 +267,25 @@ pub struct DocInlineOnlyUse { pub item_span: Option, } +#[derive(LintDiagnostic)] +#[diag(passes_doc_masked_only_extern_crate)] +#[note] +pub struct DocMaskedOnlyExternCrate { + #[label] + pub attr_span: Span, + #[label(passes_not_an_extern_crate_label)] + pub item_span: Option, +} + +#[derive(LintDiagnostic)] +#[diag(passes_doc_masked_not_extern_crate_self)] +pub struct DocMaskedNotExternCrateSelf { + #[label] + pub attr_span: Span, + #[label(passes_extern_crate_self_label)] + pub item_span: Option, +} + #[derive(Diagnostic)] #[diag(passes_doc_attr_not_crate_level)] pub struct DocAttrNotCrateLevel<'a> { diff --git a/compiler/rustc_query_impl/src/plumbing.rs b/compiler/rustc_query_impl/src/plumbing.rs index 12a3f2ac802b..def6ac280b80 100644 --- a/compiler/rustc_query_impl/src/plumbing.rs +++ b/compiler/rustc_query_impl/src/plumbing.rs @@ -183,7 +183,7 @@ pub(super) fn encode_all_query_results<'tcx>( encoder: &mut CacheEncoder<'_, 'tcx>, query_result_index: &mut EncodedDepNodeIndex, ) { - for encode in super::ENCODE_QUERY_RESULTS.iter().copied().filter_map(|e| e) { + for encode in super::ENCODE_QUERY_RESULTS.iter().copied().flatten() { encode(tcx, encoder, query_result_index); } } diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs index 2cfde2f62d8c..73cd596c0769 100644 --- a/compiler/rustc_resolve/src/diagnostics.rs +++ b/compiler/rustc_resolve/src/diagnostics.rs @@ -1395,7 +1395,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { let head_span = source_map.guess_head_span(span); err.subdiagnostic(ConsiderAddingADerive { span: head_span.shrink_to_lo(), - suggestion: format!("#[derive(Default)]\n") + suggestion: "#[derive(Default)]\n".to_string(), }); } for ns in [Namespace::MacroNS, Namespace::TypeNS, Namespace::ValueNS] { @@ -1718,7 +1718,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { if next_binding.is_none() && let Some(span) = non_exhaustive { note_span.push_span_label( span, - format!("cannot be constructed because it is `#[non_exhaustive]`"), + "cannot be constructed because it is `#[non_exhaustive]`", ); } err.span_note(note_span, msg); diff --git a/compiler/rustc_resolve/src/imports.rs b/compiler/rustc_resolve/src/imports.rs index 526fc9c3aa51..f3cf61c5b932 100644 --- a/compiler/rustc_resolve/src/imports.rs +++ b/compiler/rustc_resolve/src/imports.rs @@ -989,14 +989,17 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { initial_binding.res() }); let res = binding.res(); + if res == Res::Err || !this.ambiguity_errors.is_empty() { + this.tcx + .sess + .delay_span_bug(import.span, "some error happened for an import"); + return; + } if let Ok(initial_res) = initial_res { - if res != initial_res && this.ambiguity_errors.is_empty() { + if res != initial_res { span_bug!(import.span, "inconsistent resolution for an import"); } - } else if res != Res::Err - && this.ambiguity_errors.is_empty() - && this.privacy_errors.is_empty() - { + } else if this.privacy_errors.is_empty() { this.tcx .sess .create_err(CannotDetermineImportResolution { span: import.span }) diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index be7ef92d1753..aab71494fd31 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -549,6 +549,7 @@ enum MaybeExported<'a> { Ok(NodeId), Impl(Option), ImplItem(Result), + NestedUse(&'a Visibility), } impl MaybeExported<'_> { @@ -559,7 +560,9 @@ impl MaybeExported<'_> { trait_def_id.as_local() } MaybeExported::Impl(None) => return true, - MaybeExported::ImplItem(Err(vis)) => return vis.kind.is_pub(), + MaybeExported::ImplItem(Err(vis)) | MaybeExported::NestedUse(vis) => { + return vis.kind.is_pub(); + } }; def_id.map_or(true, |def_id| r.effective_visibilities.is_exported(def_id)) } @@ -2284,7 +2287,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { fn resolve_item(&mut self, item: &'ast Item) { let mod_inner_docs = matches!(item.kind, ItemKind::Mod(..)) && rustdoc::inner_docs(&item.attrs); - if !mod_inner_docs && !matches!(item.kind, ItemKind::Impl(..)) { + if !mod_inner_docs && !matches!(item.kind, ItemKind::Impl(..) | ItemKind::Use(..)) { self.resolve_doc_links(&item.attrs, MaybeExported::Ok(item.id)); } @@ -2428,6 +2431,12 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { } ItemKind::Use(ref use_tree) => { + let maybe_exported = match use_tree.kind { + UseTreeKind::Simple(_) | UseTreeKind::Glob => MaybeExported::Ok(item.id), + UseTreeKind::Nested(_) => MaybeExported::NestedUse(&item.vis), + }; + self.resolve_doc_links(&item.attrs, maybe_exported); + self.future_proof_import(use_tree); } diff --git a/compiler/rustc_session/messages.ftl b/compiler/rustc_session/messages.ftl index ee24c6d902fa..d4042a2e61ad 100644 --- a/compiler/rustc_session/messages.ftl +++ b/compiler/rustc_session/messages.ftl @@ -45,6 +45,7 @@ session_int_literal_too_large = integer literal is too large .note = value exceeds limit of `{$limit}` session_invalid_character_in_create_name = invalid character `{$character}` in crate name: `{$crate_name}` +session_invalid_character_in_create_name_help = you can either pass `--crate-name` on the command line or add `#![crate_name="…"]` to set the crate name session_invalid_float_literal_suffix = invalid suffix `{$suffix}` for float literal .label = invalid suffix `{$suffix}` diff --git a/compiler/rustc_session/src/code_stats.rs b/compiler/rustc_session/src/code_stats.rs index cabe1c96bf79..df81e1f8305e 100644 --- a/compiler/rustc_session/src/code_stats.rs +++ b/compiler/rustc_session/src/code_stats.rs @@ -227,10 +227,8 @@ impl CodeStats { } pub fn print_vtable_sizes(&self, crate_name: &str) { - let mut infos = std::mem::take(&mut *self.vtable_sizes.lock()) - .into_iter() - .map(|(_did, stats)| stats) - .collect::>(); + let mut infos = + std::mem::take(&mut *self.vtable_sizes.lock()).into_values().collect::>(); // Primary sort: cost % in reverse order (from largest to smallest) // Secondary sort: trait_name diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs index a8147ede970c..36b5c385ab19 100644 --- a/compiler/rustc_session/src/config.rs +++ b/compiler/rustc_session/src/config.rs @@ -279,11 +279,11 @@ impl LinkSelfContained { // set of all values like `y` or `n` used to be. Therefore, if this flag had previously been // set in bulk with its historical values, then manually setting a component clears that // `explicitly_set` state. - if let Some(component_to_enable) = component.strip_prefix("+") { + if let Some(component_to_enable) = component.strip_prefix('+') { self.explicitly_set = None; self.components.insert(component_to_enable.parse()?); Ok(()) - } else if let Some(component_to_disable) = component.strip_prefix("-") { + } else if let Some(component_to_disable) = component.strip_prefix('-') { self.explicitly_set = None; self.components.remove(component_to_disable.parse()?); Ok(()) diff --git a/compiler/rustc_session/src/errors.rs b/compiler/rustc_session/src/errors.rs index dd15ad45145f..1ffee01b2f1c 100644 --- a/compiler/rustc_session/src/errors.rs +++ b/compiler/rustc_session/src/errors.rs @@ -199,6 +199,14 @@ pub struct InvalidCharacterInCrateName { pub span: Option, pub character: char, pub crate_name: Symbol, + #[subdiagnostic] + pub crate_name_help: Option, +} + +#[derive(Subdiagnostic)] +pub enum InvalidCrateNameHelp { + #[help(session_invalid_character_in_create_name_help)] + AddCrateName, } #[derive(Subdiagnostic)] diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index 39efe9abeecd..c19c2d1dc9e2 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -1145,7 +1145,7 @@ mod parse { } // 2. Parse a list of enabled and disabled components. - for comp in s.split(",") { + for comp in s.split(',') { if slot.handle_cli_component(comp).is_err() { return false; } @@ -1878,6 +1878,8 @@ written to standard error output)"), Requires `-Clto[=[fat,yes]]`"), wasi_exec_model: Option = (None, parse_wasi_exec_model, [TRACKED], "whether to build a wasi command or reactor"), + write_long_types_to_disk: bool = (true, parse_bool, [UNTRACKED], + "whether long type names should be written to files instead of being printed in errors"), // tidy-alphabetical-end // If you add a new option, please update: diff --git a/compiler/rustc_session/src/output.rs b/compiler/rustc_session/src/output.rs index 2088744bc5bf..c0884fb21cd1 100644 --- a/compiler/rustc_session/src/output.rs +++ b/compiler/rustc_session/src/output.rs @@ -2,7 +2,7 @@ use crate::config::{CrateType, Input, OutFileName, OutputFilenames, OutputType}; use crate::errors::{ CrateNameDoesNotMatch, CrateNameEmpty, CrateNameInvalid, FileIsNotWriteable, - InvalidCharacterInCrateName, + InvalidCharacterInCrateName, InvalidCrateNameHelp, }; use crate::Session; use rustc_ast::{self as ast, attr}; @@ -101,7 +101,16 @@ pub fn validate_crate_name(sess: &Session, s: Symbol, sp: Option) { continue; } err_count += 1; - sess.emit_err(InvalidCharacterInCrateName { span: sp, character: c, crate_name: s }); + sess.emit_err(InvalidCharacterInCrateName { + span: sp, + character: c, + crate_name: s, + crate_name_help: if sp.is_none() { + Some(InvalidCrateNameHelp::AddCrateName) + } else { + None + }, + }); } } diff --git a/compiler/rustc_session/src/utils.rs b/compiler/rustc_session/src/utils.rs index 1d15e2c28d83..71f2591fe665 100644 --- a/compiler/rustc_session/src/utils.rs +++ b/compiler/rustc_session/src/utils.rs @@ -7,6 +7,7 @@ impl Session { pub fn timer(&self, what: &'static str) -> VerboseTimingGuard<'_> { self.prof.verbose_generic_activity(what) } + /// Used by `-Z self-profile`. pub fn time(&self, what: &'static str, f: impl FnOnce() -> R) -> R { self.prof.verbose_generic_activity(what).run(f) } diff --git a/compiler/rustc_smir/src/rustc_internal/mod.rs b/compiler/rustc_smir/src/rustc_internal/mod.rs index e0cf698acd74..6a26a4a22ed4 100644 --- a/compiler/rustc_smir/src/rustc_internal/mod.rs +++ b/compiler/rustc_smir/src/rustc_internal/mod.rs @@ -59,6 +59,10 @@ pub fn br_named_def(did: DefId) -> stable_mir::ty::BrNamedDef { with_tables(|t| t.br_named_def(did)) } +pub fn trait_def(did: DefId) -> stable_mir::ty::TraitDef { + with_tables(|t| t.trait_def(did)) +} + impl<'tcx> Tables<'tcx> { pub fn item_def_id(&self, item: &stable_mir::CrateItem) -> DefId { self.def_ids[item.0] @@ -100,6 +104,10 @@ impl<'tcx> Tables<'tcx> { stable_mir::ty::BrNamedDef(self.create_def_id(did)) } + pub fn trait_def(&mut self, did: DefId) -> stable_mir::ty::TraitDef { + stable_mir::ty::TraitDef(self.create_def_id(did)) + } + fn create_def_id(&mut self, did: DefId) -> stable_mir::DefId { // FIXME: this becomes inefficient when we have too many ids for (i, &d) in self.def_ids.iter().enumerate() { diff --git a/compiler/rustc_smir/src/rustc_smir/mod.rs b/compiler/rustc_smir/src/rustc_smir/mod.rs index 97bde5c3c191..044e2f8f3256 100644 --- a/compiler/rustc_smir/src/rustc_smir/mod.rs +++ b/compiler/rustc_smir/src/rustc_smir/mod.rs @@ -258,6 +258,72 @@ impl<'tcx> Stable<'tcx> for ty::AliasTy<'tcx> { } } +impl<'tcx> Stable<'tcx> for ty::DynKind { + type T = stable_mir::ty::DynKind; + + fn stable(&self, _: &mut Tables<'tcx>) -> Self::T { + use ty::DynKind; + match self { + DynKind::Dyn => stable_mir::ty::DynKind::Dyn, + DynKind::DynStar => stable_mir::ty::DynKind::DynStar, + } + } +} + +impl<'tcx> Stable<'tcx> for ty::ExistentialPredicate<'tcx> { + type T = stable_mir::ty::ExistentialPredicate; + + fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T { + use stable_mir::ty::ExistentialPredicate::*; + match self { + ty::ExistentialPredicate::Trait(existential_trait_ref) => { + Trait(existential_trait_ref.stable(tables)) + } + ty::ExistentialPredicate::Projection(existential_projection) => { + Projection(existential_projection.stable(tables)) + } + ty::ExistentialPredicate::AutoTrait(def_id) => AutoTrait(tables.trait_def(*def_id)), + } + } +} + +impl<'tcx> Stable<'tcx> for ty::ExistentialTraitRef<'tcx> { + type T = stable_mir::ty::ExistentialTraitRef; + + fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T { + let ty::ExistentialTraitRef { def_id, args } = self; + stable_mir::ty::ExistentialTraitRef { + def_id: tables.trait_def(*def_id), + generic_args: args.stable(tables), + } + } +} + +impl<'tcx> Stable<'tcx> for ty::TermKind<'tcx> { + type T = stable_mir::ty::TermKind; + + fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T { + use stable_mir::ty::TermKind; + match self { + ty::TermKind::Ty(ty) => TermKind::Type(tables.intern_ty(*ty)), + ty::TermKind::Const(const_) => TermKind::Const(opaque(const_)), + } + } +} + +impl<'tcx> Stable<'tcx> for ty::ExistentialProjection<'tcx> { + type T = stable_mir::ty::ExistentialProjection; + + fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T { + let ty::ExistentialProjection { def_id, args, term } = self; + stable_mir::ty::ExistentialProjection { + def_id: tables.trait_def(*def_id), + generic_args: args.stable(tables), + term: term.unpack().stable(tables), + } + } +} + impl<'tcx> Stable<'tcx> for ty::adjustment::PointerCoercion { type T = stable_mir::mir::PointerCoercion; fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T { @@ -509,29 +575,36 @@ impl<'tcx> Stable<'tcx> for mir::Terminator<'tcx> { impl<'tcx> Stable<'tcx> for ty::GenericArgs<'tcx> { type T = stable_mir::ty::GenericArgs; fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T { - use stable_mir::ty::{GenericArgKind, GenericArgs}; + use stable_mir::ty::GenericArgs; - GenericArgs( - self.iter() - .map(|arg| match arg.unpack() { - ty::GenericArgKind::Lifetime(region) => { - GenericArgKind::Lifetime(opaque(®ion)) - } - ty::GenericArgKind::Type(ty) => GenericArgKind::Type(tables.intern_ty(ty)), - ty::GenericArgKind::Const(const_) => GenericArgKind::Const(opaque(&const_)), - }) - .collect(), - ) + GenericArgs(self.iter().map(|arg| arg.unpack().stable(tables)).collect()) } } -impl<'tcx> Stable<'tcx> for ty::PolyFnSig<'tcx> { - type T = stable_mir::ty::PolyFnSig; +impl<'tcx> Stable<'tcx> for ty::GenericArgKind<'tcx> { + type T = stable_mir::ty::GenericArgKind; + + fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T { + use stable_mir::ty::GenericArgKind; + match self { + ty::GenericArgKind::Lifetime(region) => GenericArgKind::Lifetime(opaque(region)), + ty::GenericArgKind::Type(ty) => GenericArgKind::Type(tables.intern_ty(*ty)), + ty::GenericArgKind::Const(const_) => GenericArgKind::Const(opaque(&const_)), + } + } +} + +impl<'tcx, S, V> Stable<'tcx> for ty::Binder<'tcx, S> +where + S: Stable<'tcx, T = V>, +{ + type T = stable_mir::ty::Binder; + fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T { use stable_mir::ty::Binder; Binder { - value: self.skip_binder().stable(tables), + value: self.as_ref().skip_binder().stable(tables), bound_vars: self .bound_vars() .iter() @@ -589,63 +662,118 @@ impl<'tcx> Stable<'tcx> for ty::FnSig<'tcx> { } } +impl<'tcx> Stable<'tcx> for ty::BoundTyKind { + type T = stable_mir::ty::BoundTyKind; + + fn stable(&self, _: &mut Tables<'tcx>) -> Self::T { + use stable_mir::ty::BoundTyKind; + + match self { + ty::BoundTyKind::Anon => BoundTyKind::Anon, + ty::BoundTyKind::Param(def_id, symbol) => { + BoundTyKind::Param(rustc_internal::param_def(*def_id), symbol.to_string()) + } + } + } +} + +impl<'tcx> Stable<'tcx> for ty::BoundRegionKind { + type T = stable_mir::ty::BoundRegionKind; + + fn stable(&self, _: &mut Tables<'tcx>) -> Self::T { + use stable_mir::ty::BoundRegionKind; + + match self { + ty::BoundRegionKind::BrAnon(option_span) => { + BoundRegionKind::BrAnon(option_span.map(|span| opaque(&span))) + } + ty::BoundRegionKind::BrNamed(def_id, symbol) => { + BoundRegionKind::BrNamed(rustc_internal::br_named_def(*def_id), symbol.to_string()) + } + ty::BoundRegionKind::BrEnv => BoundRegionKind::BrEnv, + } + } +} + impl<'tcx> Stable<'tcx> for ty::BoundVariableKind { type T = stable_mir::ty::BoundVariableKind; - fn stable(&self, _: &mut Tables<'tcx>) -> Self::T { - use stable_mir::ty::{BoundRegionKind, BoundTyKind, BoundVariableKind}; + + fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T { + use stable_mir::ty::BoundVariableKind; match self { ty::BoundVariableKind::Ty(bound_ty_kind) => { - BoundVariableKind::Ty(match bound_ty_kind { - ty::BoundTyKind::Anon => BoundTyKind::Anon, - ty::BoundTyKind::Param(def_id, symbol) => { - BoundTyKind::Param(rustc_internal::param_def(*def_id), symbol.to_string()) - } - }) + BoundVariableKind::Ty(bound_ty_kind.stable(tables)) } ty::BoundVariableKind::Region(bound_region_kind) => { - BoundVariableKind::Region(match bound_region_kind { - ty::BoundRegionKind::BrAnon(option_span) => { - BoundRegionKind::BrAnon(option_span.map(|span| opaque(&span))) - } - ty::BoundRegionKind::BrNamed(def_id, symbol) => BoundRegionKind::BrNamed( - rustc_internal::br_named_def(*def_id), - symbol.to_string(), - ), - ty::BoundRegionKind::BrEnv => BoundRegionKind::BrEnv, - }) + BoundVariableKind::Region(bound_region_kind.stable(tables)) } ty::BoundVariableKind::Const => BoundVariableKind::Const, } } } +impl<'tcx> Stable<'tcx> for ty::IntTy { + type T = IntTy; + + fn stable(&self, _: &mut Tables<'tcx>) -> Self::T { + match self { + ty::IntTy::Isize => IntTy::Isize, + ty::IntTy::I8 => IntTy::I8, + ty::IntTy::I16 => IntTy::I16, + ty::IntTy::I32 => IntTy::I32, + ty::IntTy::I64 => IntTy::I64, + ty::IntTy::I128 => IntTy::I128, + } + } +} + +impl<'tcx> Stable<'tcx> for ty::UintTy { + type T = UintTy; + + fn stable(&self, _: &mut Tables<'tcx>) -> Self::T { + match self { + ty::UintTy::Usize => UintTy::Usize, + ty::UintTy::U8 => UintTy::U8, + ty::UintTy::U16 => UintTy::U16, + ty::UintTy::U32 => UintTy::U32, + ty::UintTy::U64 => UintTy::U64, + ty::UintTy::U128 => UintTy::U128, + } + } +} + +impl<'tcx> Stable<'tcx> for ty::FloatTy { + type T = FloatTy; + + fn stable(&self, _: &mut Tables<'tcx>) -> Self::T { + match self { + ty::FloatTy::F32 => FloatTy::F32, + ty::FloatTy::F64 => FloatTy::F64, + } + } +} + +impl<'tcx> Stable<'tcx> for hir::Movability { + type T = Movability; + + fn stable(&self, _: &mut Tables<'tcx>) -> Self::T { + match self { + hir::Movability::Static => Movability::Static, + hir::Movability::Movable => Movability::Movable, + } + } +} + impl<'tcx> Stable<'tcx> for Ty<'tcx> { type T = stable_mir::ty::TyKind; fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T { match self.kind() { ty::Bool => TyKind::RigidTy(RigidTy::Bool), ty::Char => TyKind::RigidTy(RigidTy::Char), - ty::Int(int_ty) => match int_ty { - ty::IntTy::Isize => TyKind::RigidTy(RigidTy::Int(IntTy::Isize)), - ty::IntTy::I8 => TyKind::RigidTy(RigidTy::Int(IntTy::I8)), - ty::IntTy::I16 => TyKind::RigidTy(RigidTy::Int(IntTy::I16)), - ty::IntTy::I32 => TyKind::RigidTy(RigidTy::Int(IntTy::I32)), - ty::IntTy::I64 => TyKind::RigidTy(RigidTy::Int(IntTy::I64)), - ty::IntTy::I128 => TyKind::RigidTy(RigidTy::Int(IntTy::I128)), - }, - ty::Uint(uint_ty) => match uint_ty { - ty::UintTy::Usize => TyKind::RigidTy(RigidTy::Uint(UintTy::Usize)), - ty::UintTy::U8 => TyKind::RigidTy(RigidTy::Uint(UintTy::U8)), - ty::UintTy::U16 => TyKind::RigidTy(RigidTy::Uint(UintTy::U16)), - ty::UintTy::U32 => TyKind::RigidTy(RigidTy::Uint(UintTy::U32)), - ty::UintTy::U64 => TyKind::RigidTy(RigidTy::Uint(UintTy::U64)), - ty::UintTy::U128 => TyKind::RigidTy(RigidTy::Uint(UintTy::U128)), - }, - ty::Float(float_ty) => match float_ty { - ty::FloatTy::F32 => TyKind::RigidTy(RigidTy::Float(FloatTy::F32)), - ty::FloatTy::F64 => TyKind::RigidTy(RigidTy::Float(FloatTy::F64)), - }, + ty::Int(int_ty) => TyKind::RigidTy(RigidTy::Int(int_ty.stable(tables))), + ty::Uint(uint_ty) => TyKind::RigidTy(RigidTy::Uint(uint_ty.stable(tables))), + ty::Float(float_ty) => TyKind::RigidTy(RigidTy::Float(float_ty.stable(tables))), ty::Adt(adt_def, generic_args) => TyKind::RigidTy(RigidTy::Adt( rustc_internal::adt_def(adt_def.did()), generic_args.stable(tables), @@ -671,7 +799,16 @@ impl<'tcx> Stable<'tcx> for Ty<'tcx> { generic_args.stable(tables), )), ty::FnPtr(poly_fn_sig) => TyKind::RigidTy(RigidTy::FnPtr(poly_fn_sig.stable(tables))), - ty::Dynamic(_, _, _) => todo!(), + ty::Dynamic(existential_predicates, region, dyn_kind) => { + TyKind::RigidTy(RigidTy::Dynamic( + existential_predicates + .iter() + .map(|existential_predicate| existential_predicate.stable(tables)) + .collect(), + opaque(region), + dyn_kind.stable(tables), + )) + } ty::Closure(def_id, generic_args) => TyKind::RigidTy(RigidTy::Closure( rustc_internal::closure_def(*def_id), generic_args.stable(tables), @@ -679,10 +816,7 @@ impl<'tcx> Stable<'tcx> for Ty<'tcx> { ty::Generator(def_id, generic_args, movability) => TyKind::RigidTy(RigidTy::Generator( rustc_internal::generator_def(*def_id), generic_args.stable(tables), - match movability { - hir::Movability::Static => Movability::Static, - hir::Movability::Movable => Movability::Movable, - }, + movability.stable(tables), )), ty::Never => TyKind::RigidTy(RigidTy::Never), ty::Tuple(fields) => TyKind::RigidTy(RigidTy::Tuple( diff --git a/compiler/rustc_smir/src/stable_mir/ty.rs b/compiler/rustc_smir/src/stable_mir/ty.rs index 885beeda78c9..7b4747a7fe29 100644 --- a/compiler/rustc_smir/src/stable_mir/ty.rs +++ b/compiler/rustc_smir/src/stable_mir/ty.rs @@ -38,6 +38,7 @@ pub enum RigidTy { FnPtr(PolyFnSig), Closure(ClosureDef, GenericArgs), Generator(GeneratorDef, GenericArgs, Movability), + Dynamic(Vec>, Region, DynKind), Never, Tuple(Vec), } @@ -98,6 +99,9 @@ pub struct AdtDef(pub(crate) DefId); #[derive(Clone, PartialEq, Eq, Debug)] pub struct AliasDef(pub(crate) DefId); +#[derive(Clone, PartialEq, Eq, Debug)] +pub struct TraitDef(pub(crate) DefId); + #[derive(Clone, Debug)] pub struct GenericArgs(pub Vec); @@ -108,6 +112,12 @@ pub enum GenericArgKind { Const(Const), } +#[derive(Clone, Debug)] +pub enum TermKind { + Type(Ty), + Const(Const), +} + #[derive(Clone, Debug)] pub enum AliasKind { Projection, @@ -192,3 +202,29 @@ pub enum BoundRegionKind { BrNamed(BrNamedDef, String), BrEnv, } + +#[derive(Clone, Debug)] +pub enum DynKind { + Dyn, + DynStar, +} + +#[derive(Clone, Debug)] +pub enum ExistentialPredicate { + Trait(ExistentialTraitRef), + Projection(ExistentialProjection), + AutoTrait(TraitDef), +} + +#[derive(Clone, Debug)] +pub struct ExistentialTraitRef { + pub def_id: TraitDef, + pub generic_args: GenericArgs, +} + +#[derive(Clone, Debug)] +pub struct ExistentialProjection { + pub def_id: TraitDef, + pub generic_args: GenericArgs, + pub term: TermKind, +} diff --git a/compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs b/compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs index 4a938ff938a0..f683832e3df0 100644 --- a/compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs +++ b/compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs @@ -400,7 +400,7 @@ fn encode_ty_name(tcx: TyCtxt<'_>, def_id: DefId) -> String { let _ = write!(s, "{}", name.len()); // Prepend a '_' if name starts with a digit or '_' - if let Some(first) = name.as_bytes().get(0) { + if let Some(first) = name.as_bytes().first() { if first.is_ascii_digit() || *first == b'_' { s.push('_'); } diff --git a/compiler/rustc_target/src/spec/aarch64_unknown_hermit.rs b/compiler/rustc_target/src/spec/aarch64_unknown_hermit.rs index 87e8d6270269..2414867be552 100644 --- a/compiler/rustc_target/src/spec/aarch64_unknown_hermit.rs +++ b/compiler/rustc_target/src/spec/aarch64_unknown_hermit.rs @@ -1,15 +1,15 @@ -use crate::spec::Target; +use crate::spec::{Target, TargetOptions}; pub fn target() -> Target { - let mut base = super::hermit_base::opts(); - base.max_atomic_width = Some(128); - base.features = "+v8a,+strict-align,+neon,+fp-armv8".into(); - Target { llvm_target: "aarch64-unknown-hermit".into(), pointer_width: 64, - data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128".into(), arch: "aarch64".into(), - options: base, + data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128".into(), + options: TargetOptions { + features: "+v8a,+strict-align,+neon,+fp-armv8".into(), + max_atomic_width: Some(128), + ..super::hermit_base::opts() + }, } } diff --git a/compiler/rustc_target/src/spec/armebv7r_none_eabi.rs b/compiler/rustc_target/src/spec/armebv7r_none_eabi.rs index 5632bcfcefe2..446efa90d098 100644 --- a/compiler/rustc_target/src/spec/armebv7r_none_eabi.rs +++ b/compiler/rustc_target/src/spec/armebv7r_none_eabi.rs @@ -5,7 +5,7 @@ use crate::spec::{Cc, LinkerFlavor, Lld, PanicStrategy, RelocModel, Target, Targ pub fn target() -> Target { Target { - llvm_target: "armebv7r-unknown-none-eabi".into(), + llvm_target: "armebv7r-none-eabi".into(), pointer_width: 32, data_layout: "E-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(), arch: "arm".into(), @@ -18,7 +18,7 @@ pub fn target() -> Target { panic_strategy: PanicStrategy::Abort, max_atomic_width: Some(64), emit_debug_gdb_scripts: false, - // GCC and Clang default to 8 for arm-none here + // GCC defaults to 8 for arm-none here. c_enum_min_bits: Some(8), ..Default::default() }, diff --git a/compiler/rustc_target/src/spec/armebv7r_none_eabihf.rs b/compiler/rustc_target/src/spec/armebv7r_none_eabihf.rs index 2815de3589db..0c9e99ff84bf 100644 --- a/compiler/rustc_target/src/spec/armebv7r_none_eabihf.rs +++ b/compiler/rustc_target/src/spec/armebv7r_none_eabihf.rs @@ -5,7 +5,7 @@ use crate::spec::{Cc, LinkerFlavor, Lld, PanicStrategy, RelocModel, Target, Targ pub fn target() -> Target { Target { - llvm_target: "armebv7r-unknown-none-eabihf".into(), + llvm_target: "armebv7r-none-eabihf".into(), pointer_width: 32, data_layout: "E-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(), arch: "arm".into(), @@ -19,7 +19,7 @@ pub fn target() -> Target { features: "+vfp3,-d32,-fp16".into(), max_atomic_width: Some(64), emit_debug_gdb_scripts: false, - // GCC and Clang default to 8 for arm-none here + // GCC defaults to 8 for arm-none here. c_enum_min_bits: Some(8), ..Default::default() }, diff --git a/compiler/rustc_target/src/spec/armv4t_none_eabi.rs b/compiler/rustc_target/src/spec/armv4t_none_eabi.rs index d0f988b278ff..44fdd3178af4 100644 --- a/compiler/rustc_target/src/spec/armv4t_none_eabi.rs +++ b/compiler/rustc_target/src/spec/armv4t_none_eabi.rs @@ -39,9 +39,9 @@ pub fn target() -> Target { has_thumb_interworking: true, relocation_model: RelocModel::Static, panic_strategy: PanicStrategy::Abort, - // from thumb_base, rust-lang/rust#44993. + // From thumb_base, rust-lang/rust#44993. emit_debug_gdb_scripts: false, - // from thumb_base, apparently gcc/clang give enums a minimum of 8 bits on no-os targets + // From thumb_base, GCC gives enums a minimum of 8 bits on no-os targets. c_enum_min_bits: Some(8), ..Default::default() }, diff --git a/compiler/rustc_target/src/spec/armv7a_none_eabihf.rs b/compiler/rustc_target/src/spec/armv7a_none_eabihf.rs index 8cdf3c36ba2e..c134f3e09078 100644 --- a/compiler/rustc_target/src/spec/armv7a_none_eabihf.rs +++ b/compiler/rustc_target/src/spec/armv7a_none_eabihf.rs @@ -18,7 +18,7 @@ pub fn target() -> Target { max_atomic_width: Some(64), panic_strategy: PanicStrategy::Abort, emit_debug_gdb_scripts: false, - // GCC and Clang default to 8 for arm-none here + // GCC defaults to 8 for arm-none here. c_enum_min_bits: Some(8), ..Default::default() }; diff --git a/compiler/rustc_target/src/spec/armv7r_none_eabi.rs b/compiler/rustc_target/src/spec/armv7r_none_eabi.rs index 74905ed5a4e0..68b2527985a6 100644 --- a/compiler/rustc_target/src/spec/armv7r_none_eabi.rs +++ b/compiler/rustc_target/src/spec/armv7r_none_eabi.rs @@ -4,7 +4,7 @@ use crate::spec::{Cc, LinkerFlavor, Lld, PanicStrategy, RelocModel, Target, Targ pub fn target() -> Target { Target { - llvm_target: "armv7r-unknown-none-eabi".into(), + llvm_target: "armv7r-none-eabi".into(), pointer_width: 32, data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(), arch: "arm".into(), @@ -17,7 +17,7 @@ pub fn target() -> Target { panic_strategy: PanicStrategy::Abort, max_atomic_width: Some(64), emit_debug_gdb_scripts: false, - // GCC and Clang default to 8 for arm-none here + // GCC defaults to 8 for arm-none here. c_enum_min_bits: Some(8), ..Default::default() }, diff --git a/compiler/rustc_target/src/spec/armv7r_none_eabihf.rs b/compiler/rustc_target/src/spec/armv7r_none_eabihf.rs index 516b3f5c17ee..909765a310fe 100644 --- a/compiler/rustc_target/src/spec/armv7r_none_eabihf.rs +++ b/compiler/rustc_target/src/spec/armv7r_none_eabihf.rs @@ -4,7 +4,7 @@ use crate::spec::{Cc, LinkerFlavor, Lld, PanicStrategy, RelocModel, Target, Targ pub fn target() -> Target { Target { - llvm_target: "armv7r-unknown-none-eabihf".into(), + llvm_target: "armv7r-none-eabihf".into(), pointer_width: 32, data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(), arch: "arm".into(), @@ -18,7 +18,7 @@ pub fn target() -> Target { features: "+vfp3,-d32,-fp16".into(), max_atomic_width: Some(64), emit_debug_gdb_scripts: false, - // GCC and Clang default to 8 for arm-none here + // GCC defaults to 8 for arm-none here. c_enum_min_bits: Some(8), ..Default::default() }, diff --git a/compiler/rustc_target/src/spec/hermit_base.rs b/compiler/rustc_target/src/spec/hermit_base.rs index dd9991381e7b..c6e98fc1a115 100644 --- a/compiler/rustc_target/src/spec/hermit_base.rs +++ b/compiler/rustc_target/src/spec/hermit_base.rs @@ -1,21 +1,15 @@ use crate::spec::{Cc, LinkerFlavor, Lld, PanicStrategy, TargetOptions, TlsModel}; pub fn opts() -> TargetOptions { - let pre_link_args = TargetOptions::link_args( - LinkerFlavor::Gnu(Cc::No, Lld::No), - &["--build-id", "--hash-style=gnu", "--Bstatic"], - ); - TargetOptions { os: "hermit".into(), - linker_flavor: LinkerFlavor::Gnu(Cc::No, Lld::Yes), linker: Some("rust-lld".into()), - has_thread_local: true, - pre_link_args, - panic_strategy: PanicStrategy::Abort, + linker_flavor: LinkerFlavor::Gnu(Cc::No, Lld::Yes), + tls_model: TlsModel::InitialExec, position_independent_executables: true, static_position_independent_executables: true, - tls_model: TlsModel::InitialExec, + has_thread_local: true, + panic_strategy: PanicStrategy::Abort, ..Default::default() } } diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs index 6ae07f45f4a4..7114c243ea14 100644 --- a/compiler/rustc_target/src/spec/mod.rs +++ b/compiler/rustc_target/src/spec/mod.rs @@ -85,6 +85,7 @@ mod solaris_base; mod solid_base; mod thumb_base; mod uefi_msvc_base; +mod unikraft_linux_musl_base; mod vxworks_base; mod wasm_base; mod windows_gnu_base; @@ -1418,8 +1419,11 @@ supported_targets! { ("msp430-none-elf", msp430_none_elf), ("aarch64-unknown-hermit", aarch64_unknown_hermit), + ("riscv64gc-unknown-hermit", riscv64gc_unknown_hermit), ("x86_64-unknown-hermit", x86_64_unknown_hermit), + ("x86_64-unikraft-linux-musl", x86_64_unikraft_linux_musl), + ("riscv32i-unknown-none-elf", riscv32i_unknown_none_elf), ("riscv32im-unknown-none-elf", riscv32im_unknown_none_elf), ("riscv32imc-unknown-none-elf", riscv32imc_unknown_none_elf), diff --git a/compiler/rustc_target/src/spec/riscv64gc_unknown_hermit.rs b/compiler/rustc_target/src/spec/riscv64gc_unknown_hermit.rs new file mode 100644 index 000000000000..1f6a34c0cacc --- /dev/null +++ b/compiler/rustc_target/src/spec/riscv64gc_unknown_hermit.rs @@ -0,0 +1,20 @@ +use crate::spec::{CodeModel, RelocModel, Target, TargetOptions, TlsModel}; + +pub fn target() -> Target { + Target { + llvm_target: "riscv64-unknown-hermit".into(), + pointer_width: 64, + arch: "riscv64".into(), + data_layout: "e-m:e-p:64:64-i64:64-i128:128-n32:64-S128".into(), + options: TargetOptions { + cpu: "generic-rv64".into(), + features: "+m,+a,+f,+d,+c".into(), + relocation_model: RelocModel::Pic, + code_model: Some(CodeModel::Medium), + tls_model: TlsModel::LocalExec, + max_atomic_width: Some(64), + llvm_abiname: "lp64d".into(), + ..super::hermit_base::opts() + }, + } +} diff --git a/compiler/rustc_target/src/spec/thumb_base.rs b/compiler/rustc_target/src/spec/thumb_base.rs index 2220b9326c97..0decfecb4cd1 100644 --- a/compiler/rustc_target/src/spec/thumb_base.rs +++ b/compiler/rustc_target/src/spec/thumb_base.rs @@ -52,7 +52,7 @@ pub fn opts() -> TargetOptions { // breaks debugging. Preserve LR by default to prevent that from happening. frame_pointer: FramePointer::Always, // ARM supports multiple ABIs for enums, the linux one matches the default of 32 here - // but any arm-none or thumb-none target will be defaulted to 8 on GCC and clang + // but any arm-none or thumb-none target will be defaulted to 8 on GCC. c_enum_min_bits: Some(8), ..Default::default() } diff --git a/compiler/rustc_target/src/spec/thumbv4t_none_eabi.rs b/compiler/rustc_target/src/spec/thumbv4t_none_eabi.rs index 9c59bb9114ec..88a76f49acd6 100644 --- a/compiler/rustc_target/src/spec/thumbv4t_none_eabi.rs +++ b/compiler/rustc_target/src/spec/thumbv4t_none_eabi.rs @@ -45,8 +45,6 @@ pub fn target() -> Target { relocation_model: RelocModel::Static, // suggested from thumb_base, rust-lang/rust#44993. emit_debug_gdb_scripts: false, - // suggested from thumb_base, with no-os gcc/clang use 8-bit enums - c_enum_min_bits: Some(8), frame_pointer: FramePointer::MayOmit, main_needs_argc_argv: false, diff --git a/compiler/rustc_target/src/spec/unikraft_linux_musl_base.rs b/compiler/rustc_target/src/spec/unikraft_linux_musl_base.rs new file mode 100644 index 000000000000..9ccd0a1e7cae --- /dev/null +++ b/compiler/rustc_target/src/spec/unikraft_linux_musl_base.rs @@ -0,0 +1,15 @@ +use crate::spec::{cvs, PanicStrategy, RelocModel, TargetOptions}; + +pub fn opts() -> TargetOptions { + TargetOptions { + os: "linux".into(), + env: "musl".into(), + vendor: "unikraft".into(), + linker: Some("kraftld".into()), + relocation_model: RelocModel::Static, + families: cvs!["unix"], + has_thread_local: true, + panic_strategy: PanicStrategy::Abort, + ..Default::default() + } +} diff --git a/compiler/rustc_target/src/spec/x86_64_unikraft_linux_musl.rs b/compiler/rustc_target/src/spec/x86_64_unikraft_linux_musl.rs new file mode 100644 index 000000000000..2aa093b131f5 --- /dev/null +++ b/compiler/rustc_target/src/spec/x86_64_unikraft_linux_musl.rs @@ -0,0 +1,19 @@ +use crate::spec::{Cc, LinkerFlavor, Lld, StackProbeType, Target, TargetOptions}; + +pub fn target() -> Target { + Target { + llvm_target: "x86_64-unknown-linux-musl".into(), + pointer_width: 64, + arch: "x86_64".into(), + data_layout: "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" + .into(), + options: TargetOptions { + cpu: "x86-64".into(), + plt_by_default: false, + pre_link_args: TargetOptions::link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-m64"]), + max_atomic_width: Some(64), + stack_probes: StackProbeType::X86, + ..super::unikraft_linux_musl_base::opts() + }, + } +} diff --git a/compiler/rustc_target/src/spec/x86_64_unknown_hermit.rs b/compiler/rustc_target/src/spec/x86_64_unknown_hermit.rs index 74ef2527c36c..1eb069301117 100644 --- a/compiler/rustc_target/src/spec/x86_64_unknown_hermit.rs +++ b/compiler/rustc_target/src/spec/x86_64_unknown_hermit.rs @@ -1,19 +1,19 @@ -use crate::spec::{StackProbeType, Target}; +use crate::spec::{StackProbeType, Target, TargetOptions}; pub fn target() -> Target { - let mut base = super::hermit_base::opts(); - base.cpu = "x86-64".into(); - base.plt_by_default = false; - base.max_atomic_width = Some(64); - base.features = "+rdrnd,+rdseed".into(); - base.stack_probes = StackProbeType::X86; - Target { llvm_target: "x86_64-unknown-hermit".into(), pointer_width: 64, + arch: "x86_64".into(), data_layout: "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" .into(), - arch: "x86_64".into(), - options: base, + options: TargetOptions { + cpu: "x86-64".into(), + features: "+rdrnd,+rdseed".into(), + plt_by_default: false, + max_atomic_width: Some(64), + stack_probes: StackProbeType::X86, + ..super::hermit_base::opts() + }, } } diff --git a/compiler/rustc_trait_selection/src/solve/alias_relate.rs b/compiler/rustc_trait_selection/src/solve/alias_relate.rs index 3c7f91e6ca9b..1b4af95cb8a7 100644 --- a/compiler/rustc_trait_selection/src/solve/alias_relate.rs +++ b/compiler/rustc_trait_selection/src/solve/alias_relate.rs @@ -1,3 +1,16 @@ +//! Implements the `AliasRelate` goal, which is used when unifying aliases. +//! Doing this via a separate goal is called "deferred alias relation" and part +//! of our more general approach to "lazy normalization". +//! +//! This goal, e.g. `A alias-relate B`, may be satisfied by one of three branches: +//! * normalizes-to: If `A` is a projection, we can prove the equivalent +//! projection predicate with B as the right-hand side of the projection. +//! This goal is computed in both directions, if both are aliases. +//! * subst-relate: Equate `A` and `B` by their substs, if they're both +//! aliases with the same def-id. +//! * bidirectional-normalizes-to: If `A` and `B` are both projections, and both +//! may apply, then we can compute the "intersection" of both normalizes-to by +//! performing them together. This is used specifically to resolve ambiguities. use super::{EvalCtxt, SolverMode}; use rustc_infer::traits::query::NoSolution; use rustc_middle::traits::solve::{Certainty, Goal, QueryResult}; @@ -118,6 +131,8 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { }) } + // Computes the normalizes-to branch, with side-effects. This must be performed + // in a probe in order to not taint the evaluation context. fn normalizes_to_inner( &mut self, param_env: ty::ParamEnv<'tcx>, @@ -127,9 +142,13 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { invert: Invert, ) -> Result<(), NoSolution> { let other = match direction { - // This is purely an optimization. + // This is purely an optimization. No need to instantiate a new + // infer var and equate the RHS to it. ty::AliasRelationDirection::Equate => other, + // Instantiate an infer var and subtype our RHS to it, so that we + // properly represent a subtype relation between the LHS and RHS + // of the goal. ty::AliasRelationDirection::Subtype => { let fresh = self.next_term_infer_of_kind(other); let (sub, sup) = match invert { diff --git a/compiler/rustc_trait_selection/src/solve/assembly/mod.rs b/compiler/rustc_trait_selection/src/solve/assembly/mod.rs index 6920e790e71a..ab90db6ff586 100644 --- a/compiler/rustc_trait_selection/src/solve/assembly/mod.rs +++ b/compiler/rustc_trait_selection/src/solve/assembly/mod.rs @@ -3,17 +3,16 @@ use super::search_graph::OverflowHandler; use super::{EvalCtxt, SolverMode}; use crate::traits::coherence; -use rustc_data_structures::fx::FxIndexSet; use rustc_hir::def_id::DefId; use rustc_infer::traits::query::NoSolution; -use rustc_infer::traits::util::elaborate; use rustc_infer::traits::Reveal; use rustc_middle::traits::solve::inspect::CandidateKind; use rustc_middle::traits::solve::{CanonicalResponse, Certainty, Goal, MaybeCause, QueryResult}; +use rustc_middle::traits::BuiltinImplSource; use rustc_middle::ty::fast_reject::{SimplifiedType, TreatParams}; -use rustc_middle::ty::TypeVisitableExt; use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_middle::ty::{fast_reject, TypeFoldable}; +use rustc_middle::ty::{ToPredicate, TypeVisitableExt}; use rustc_span::ErrorGuaranteed; use std::fmt::Debug; @@ -89,16 +88,6 @@ pub(super) enum CandidateSource { AliasBound, } -/// Records additional information about what kind of built-in impl this is. -/// This should only be used by selection. -#[derive(Debug, Clone, Copy)] -pub(super) enum BuiltinImplSource { - TraitUpcasting, - Object, - Misc, - Ambiguity, -} - /// Methods used to assemble candidates for either trait or projection goals. pub(super) trait GoalKind<'tcx>: TypeFoldable> + Copy + Eq + std::fmt::Display @@ -281,21 +270,6 @@ pub(super) trait GoalKind<'tcx>: goal: Goal<'tcx, Self>, ) -> QueryResult<'tcx>; - /// The most common forms of unsizing are array to slice, and concrete (Sized) - /// type into a `dyn Trait`. ADTs and Tuples can also have their final field - /// unsized if it's generic. - fn consider_builtin_unsize_candidate( - ecx: &mut EvalCtxt<'_, 'tcx>, - goal: Goal<'tcx, Self>, - ) -> QueryResult<'tcx>; - - /// `dyn Trait1` can be unsized to `dyn Trait2` if they are the same trait, or - /// if `Trait2` is a (transitive) supertrait of `Trait2`. - fn consider_builtin_dyn_upcast_candidates( - ecx: &mut EvalCtxt<'_, 'tcx>, - goal: Goal<'tcx, Self>, - ) -> Vec>; - fn consider_builtin_discriminant_kind_candidate( ecx: &mut EvalCtxt<'_, 'tcx>, goal: Goal<'tcx, Self>, @@ -310,6 +284,25 @@ pub(super) trait GoalKind<'tcx>: ecx: &mut EvalCtxt<'_, 'tcx>, goal: Goal<'tcx, Self>, ) -> QueryResult<'tcx>; + + /// Consider (possibly several) candidates to upcast or unsize a type to another + /// type. + /// + /// The most common forms of unsizing are array to slice, and concrete (Sized) + /// type into a `dyn Trait`. ADTs and Tuples can also have their final field + /// unsized if it's generic. + /// + /// `dyn Trait1` can be unsized to `dyn Trait2` if they are the same trait, or + /// if `Trait2` is a (transitive) supertrait of `Trait2`. + /// + /// We return the `BuiltinImplSource` for each candidate as it is needed + /// for unsize coercion in hir typeck and because it is difficult to + /// otherwise recompute this for codegen. This is a bit of a mess but the + /// easiest way to maintain the existing behavior for now. + fn consider_builtin_unsize_and_upcast_candidates( + ecx: &mut EvalCtxt<'_, 'tcx>, + goal: Goal<'tcx, Self>, + ) -> Vec<(CanonicalResponse<'tcx>, BuiltinImplSource)>; } impl<'tcx> EvalCtxt<'_, 'tcx> { @@ -343,7 +336,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { ) -> Option>> { goal.predicate.self_ty().is_ty_var().then(|| { vec![Candidate { - source: CandidateSource::BuiltinImpl(BuiltinImplSource::Ambiguity), + source: CandidateSource::BuiltinImpl(BuiltinImplSource::Misc), result: self .evaluate_added_goals_and_make_canonical_response(Certainty::AMBIGUOUS) .unwrap(), @@ -412,7 +405,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { Certainty::Maybe(MaybeCause::Overflow), )?; Ok(vec![Candidate { - source: CandidateSource::BuiltinImpl(BuiltinImplSource::Ambiguity), + source: CandidateSource::BuiltinImpl(BuiltinImplSource::Misc), result, }]) }, @@ -610,8 +603,6 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { G::consider_builtin_future_candidate(self, goal) } else if lang_items.gen_trait() == Some(trait_def_id) { G::consider_builtin_generator_candidate(self, goal) - } else if lang_items.unsize_trait() == Some(trait_def_id) { - G::consider_builtin_unsize_candidate(self, goal) } else if lang_items.discriminant_kind_trait() == Some(trait_def_id) { G::consider_builtin_discriminant_kind_candidate(self, goal) } else if lang_items.destruct_trait() == Some(trait_def_id) { @@ -633,11 +624,8 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { // There may be multiple unsize candidates for a trait with several supertraits: // `trait Foo: Bar + Bar` and `dyn Foo: Unsize>` if lang_items.unsize_trait() == Some(trait_def_id) { - for result in G::consider_builtin_dyn_upcast_candidates(self, goal) { - candidates.push(Candidate { - source: CandidateSource::BuiltinImpl(BuiltinImplSource::TraitUpcasting), - result, - }); + for (result, source) in G::consider_builtin_unsize_and_upcast_candidates(self, goal) { + candidates.push(Candidate { source: CandidateSource::BuiltinImpl(source), result }); } } } @@ -853,29 +841,47 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { ty::Dynamic(bounds, ..) => bounds, }; - let own_bounds: FxIndexSet<_> = - bounds.iter().map(|bound| bound.with_self_ty(tcx, self_ty)).collect(); - for assumption in elaborate(tcx, own_bounds.iter().copied()) - // we only care about bounds that match the `Self` type - .filter_only_self() - { - // FIXME: Predicates are fully elaborated in the object type's existential bounds - // list. We want to only consider these pre-elaborated projections, and not other - // projection predicates that we reach by elaborating the principal trait ref, - // since that'll cause ambiguity. - // - // We can remove this when we have implemented lifetime intersections in responses. - if assumption.as_projection_clause().is_some() && !own_bounds.contains(&assumption) { - continue; + // Consider all of the auto-trait and projection bounds, which don't + // need to be recorded as a `BuiltinImplSource::Object` since they don't + // really have a vtable base... + for bound in bounds { + match bound.skip_binder() { + ty::ExistentialPredicate::Trait(_) => { + // Skip principal + } + ty::ExistentialPredicate::Projection(_) + | ty::ExistentialPredicate::AutoTrait(_) => { + match G::consider_object_bound_candidate( + self, + goal, + bound.with_self_ty(tcx, self_ty), + ) { + Ok(result) => candidates.push(Candidate { + source: CandidateSource::BuiltinImpl(BuiltinImplSource::Misc), + result, + }), + Err(NoSolution) => (), + } + } } + } - match G::consider_object_bound_candidate(self, goal, assumption) { - Ok(result) => candidates.push(Candidate { - source: CandidateSource::BuiltinImpl(BuiltinImplSource::Object), - result, - }), - Err(NoSolution) => (), - } + // FIXME: We only need to do *any* of this if we're considering a trait goal, + // since we don't need to look at any supertrait or anything if we are doing + // a projection goal. + if let Some(principal) = bounds.principal() { + let principal_trait_ref = principal.with_self_ty(tcx, self_ty); + self.walk_vtable(principal_trait_ref, |ecx, assumption, vtable_base, _| { + match G::consider_object_bound_candidate(ecx, goal, assumption.to_predicate(tcx)) { + Ok(result) => candidates.push(Candidate { + source: CandidateSource::BuiltinImpl(BuiltinImplSource::Object { + vtable_base, + }), + result, + }), + Err(NoSolution) => (), + } + }); } } @@ -895,7 +901,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { .evaluate_added_goals_and_make_canonical_response(Certainty::AMBIGUOUS) { Ok(result) => candidates.push(Candidate { - source: CandidateSource::BuiltinImpl(BuiltinImplSource::Ambiguity), + source: CandidateSource::BuiltinImpl(BuiltinImplSource::Misc), result, }), // FIXME: This will be reachable at some point if we're in diff --git a/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs b/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs index a8ba98bef6d9..a2db35e069eb 100644 --- a/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs +++ b/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs @@ -1,3 +1,5 @@ +//! Code which is used by built-in goals that match "structurally", such a auto +//! traits, `Copy`/`Clone`. use rustc_data_structures::fx::FxHashMap; use rustc_hir::{def_id::DefId, Movability, Mutability}; use rustc_infer::traits::query::NoSolution; diff --git a/compiler/rustc_trait_selection/src/solve/eval_ctxt.rs b/compiler/rustc_trait_selection/src/solve/eval_ctxt.rs index 6e0aa08c307b..f48a992d3275 100644 --- a/compiler/rustc_trait_selection/src/solve/eval_ctxt.rs +++ b/compiler/rustc_trait_selection/src/solve/eval_ctxt.rs @@ -25,6 +25,7 @@ use std::io::Write; use std::ops::ControlFlow; use crate::traits::specialization_graph; +use crate::traits::vtable::{count_own_vtable_entries, prepare_vtable_segments, VtblSegment}; use super::inspect::ProofTreeBuilder; use super::search_graph::{self, OverflowHandler}; @@ -271,6 +272,7 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> { // assertions against dropping an `InferCtxt` without taking opaques. // FIXME: Once we remove support for the old impl we can remove this. if input.anchor != DefiningAnchor::Error { + // This seems ok, but fragile. let _ = infcx.take_opaque_types(); } @@ -920,4 +922,39 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { Err(ErrorHandled::TooGeneric) => None, } } + + /// Walk through the vtable of a principal trait ref, executing a `supertrait_visitor` + /// for every trait ref encountered (including the principal). Passes both the vtable + /// base and the (optional) vptr slot. + pub(super) fn walk_vtable( + &mut self, + principal: ty::PolyTraitRef<'tcx>, + mut supertrait_visitor: impl FnMut(&mut Self, ty::PolyTraitRef<'tcx>, usize, Option), + ) { + let tcx = self.tcx(); + let mut offset = 0; + prepare_vtable_segments::<()>(tcx, principal, |segment| { + match segment { + VtblSegment::MetadataDSA => { + offset += TyCtxt::COMMON_VTABLE_ENTRIES.len(); + } + VtblSegment::TraitOwnEntries { trait_ref, emit_vptr } => { + let own_vtable_entries = count_own_vtable_entries(tcx, trait_ref); + + supertrait_visitor( + self, + trait_ref, + offset, + emit_vptr.then(|| offset + own_vtable_entries), + ); + + offset += own_vtable_entries; + if emit_vptr { + offset += 1; + } + } + } + ControlFlow::Continue(()) + }); + } } diff --git a/compiler/rustc_trait_selection/src/solve/eval_ctxt/canonical.rs b/compiler/rustc_trait_selection/src/solve/eval_ctxt/canonical.rs index 9f58e66d04e8..7323b98b8ce2 100644 --- a/compiler/rustc_trait_selection/src/solve/eval_ctxt/canonical.rs +++ b/compiler/rustc_trait_selection/src/solve/eval_ctxt/canonical.rs @@ -1,13 +1,13 @@ -/// Canonicalization is used to separate some goal from its context, -/// throwing away unnecessary information in the process. -/// -/// This is necessary to cache goals containing inference variables -/// and placeholders without restricting them to the current `InferCtxt`. -/// -/// Canonicalization is fairly involved, for more details see the relevant -/// section of the [rustc-dev-guide][c]. -/// -/// [c]: https://rustc-dev-guide.rust-lang.org/solve/canonicalization.html +//! Canonicalization is used to separate some goal from its context, +//! throwing away unnecessary information in the process. +//! +//! This is necessary to cache goals containing inference variables +//! and placeholders without restricting them to the current `InferCtxt`. +//! +//! Canonicalization is fairly involved, for more details see the relevant +//! section of the [rustc-dev-guide][c]. +//! +//! [c]: https://rustc-dev-guide.rust-lang.org/solve/canonicalization.html use super::{CanonicalInput, Certainty, EvalCtxt, Goal}; use crate::solve::canonicalize::{CanonicalizeMode, Canonicalizer}; use crate::solve::{CanonicalResponse, QueryResult, Response}; @@ -135,6 +135,13 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { ) } + /// Computes the region constraints and *new* opaque types registered when + /// proving a goal. + /// + /// If an opaque was already constrained before proving this goal, then the + /// external constraints do not need to record that opaque, since if it is + /// further constrained by inference, that will be passed back in the var + /// values. #[instrument(level = "debug", skip(self), ret)] fn compute_external_query_constraints(&self) -> Result, NoSolution> { // We only check for leaks from universes which were entered inside diff --git a/compiler/rustc_trait_selection/src/solve/eval_ctxt/select.rs b/compiler/rustc_trait_selection/src/solve/eval_ctxt/select.rs index a6d118d8cc29..6045001510e4 100644 --- a/compiler/rustc_trait_selection/src/solve/eval_ctxt/select.rs +++ b/compiler/rustc_trait_selection/src/solve/eval_ctxt/select.rs @@ -1,25 +1,20 @@ -use std::ops::ControlFlow; - use rustc_hir as hir; use rustc_hir::def_id::DefId; -use rustc_infer::infer::{DefineOpaqueTypes, InferCtxt, InferOk}; -use rustc_infer::traits::util::supertraits; +use rustc_infer::infer::{DefineOpaqueTypes, InferCtxt}; use rustc_infer::traits::{ Obligation, PolyTraitObligation, PredicateObligation, Selection, SelectionResult, TraitEngine, }; use rustc_middle::traits::solve::{CanonicalInput, Certainty, Goal}; use rustc_middle::traits::{ - ImplSource, ImplSourceObjectData, ImplSourceTraitUpcastingData, ImplSourceUserDefinedData, - ObligationCause, SelectionError, + BuiltinImplSource, ImplSource, ImplSourceUserDefinedData, ObligationCause, SelectionError, }; use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_span::DUMMY_SP; -use crate::solve::assembly::{BuiltinImplSource, Candidate, CandidateSource}; +use crate::solve::assembly::{Candidate, CandidateSource}; use crate::solve::eval_ctxt::{EvalCtxt, GenerateProofTree}; use crate::solve::inspect::ProofTreeBuilder; use crate::solve::search_graph::OverflowHandler; -use crate::traits::vtable::{count_own_vtable_entries, prepare_vtable_segments, VtblSegment}; use crate::traits::StructurallyNormalizeExt; use crate::traits::TraitEngineExt; @@ -105,38 +100,26 @@ impl<'tcx> InferCtxtSelectExt<'tcx> for InferCtxt<'tcx> { rematch_impl(self, goal, def_id, nested_obligations) } - // Rematching the dyn upcast or object goal will instantiate the same nested - // goals that would have caused the ambiguity, so we can still make progress here - // regardless. - // FIXME: This doesn't actually check the object bounds hold here. - ( - _, - CandidateSource::BuiltinImpl( - BuiltinImplSource::Object | BuiltinImplSource::TraitUpcasting, - ), - ) => rematch_object(self, goal, nested_obligations), - - (Certainty::Maybe(_), CandidateSource::BuiltinImpl(BuiltinImplSource::Misc)) + (Certainty::Maybe(_), CandidateSource::BuiltinImpl(src)) if self.tcx.lang_items().unsize_trait() == Some(goal.predicate.def_id()) => { - rematch_unsize(self, goal, nested_obligations) + rematch_unsize(self, goal, nested_obligations, src) } // Technically some builtin impls have nested obligations, but if // `Certainty::Yes`, then they should've all been verified and don't // need re-checking. - (Certainty::Yes, CandidateSource::BuiltinImpl(BuiltinImplSource::Misc)) => { - Ok(Some(ImplSource::Builtin(nested_obligations))) + (Certainty::Yes, CandidateSource::BuiltinImpl(src)) => { + Ok(Some(ImplSource::Builtin(src, nested_obligations))) } // It's fine not to do anything to rematch these, since there are no // nested obligations. (Certainty::Yes, CandidateSource::ParamEnv(_) | CandidateSource::AliasBound) => { - Ok(Some(ImplSource::Param(nested_obligations, ty::BoundConstness::NotConst))) + Ok(Some(ImplSource::Param(ty::BoundConstness::NotConst, nested_obligations))) } - (_, CandidateSource::BuiltinImpl(BuiltinImplSource::Ambiguity)) - | (Certainty::Maybe(_), _) => Ok(None), + (Certainty::Maybe(_), _) => Ok(None), } } } @@ -183,11 +166,12 @@ fn candidate_should_be_dropped_in_favor_of<'tcx>( } (_, CandidateSource::ParamEnv(_)) => true, + // FIXME: we could prefer earlier vtable bases perhaps... ( - CandidateSource::BuiltinImpl(BuiltinImplSource::Object), - CandidateSource::BuiltinImpl(BuiltinImplSource::Object), + CandidateSource::BuiltinImpl(BuiltinImplSource::Object { .. }), + CandidateSource::BuiltinImpl(BuiltinImplSource::Object { .. }), ) => false, - (_, CandidateSource::BuiltinImpl(BuiltinImplSource::Object)) => true, + (_, CandidateSource::BuiltinImpl(BuiltinImplSource::Object { .. })) => true, (CandidateSource::Impl(victim_def_id), CandidateSource::Impl(other_def_id)) => { tcx.specializes((other_def_id, victim_def_id)) @@ -225,102 +209,6 @@ fn rematch_impl<'tcx>( Ok(Some(ImplSource::UserDefined(ImplSourceUserDefinedData { impl_def_id, args, nested }))) } -fn rematch_object<'tcx>( - infcx: &InferCtxt<'tcx>, - goal: Goal<'tcx, ty::TraitPredicate<'tcx>>, - mut nested: Vec>, -) -> SelectionResult<'tcx, Selection<'tcx>> { - let a_ty = structurally_normalize(goal.predicate.self_ty(), infcx, goal.param_env, &mut nested); - let ty::Dynamic(data, _, source_kind) = *a_ty.kind() else { bug!() }; - let source_trait_ref = data.principal().unwrap().with_self_ty(infcx.tcx, a_ty); - - let (is_upcasting, target_trait_ref_unnormalized) = - if Some(goal.predicate.def_id()) == infcx.tcx.lang_items().unsize_trait() { - assert_eq!(source_kind, ty::Dyn, "cannot upcast dyn*"); - let b_ty = structurally_normalize( - goal.predicate.trait_ref.args.type_at(1), - infcx, - goal.param_env, - &mut nested, - ); - if let ty::Dynamic(data, _, ty::Dyn) = *b_ty.kind() { - // FIXME: We also need to ensure that the source lifetime outlives the - // target lifetime. This doesn't matter for codegen, though, and only - // *really* matters if the goal's certainty is ambiguous. - (true, data.principal().unwrap().with_self_ty(infcx.tcx, a_ty)) - } else { - bug!() - } - } else { - (false, ty::Binder::dummy(goal.predicate.trait_ref)) - }; - - let mut target_trait_ref = None; - for candidate_trait_ref in supertraits(infcx.tcx, source_trait_ref) { - let result = infcx.commit_if_ok(|_| { - infcx.at(&ObligationCause::dummy(), goal.param_env).eq( - DefineOpaqueTypes::No, - target_trait_ref_unnormalized, - candidate_trait_ref, - ) - - // FIXME: We probably should at least shallowly verify these... - }); - - match result { - Ok(InferOk { value: (), obligations }) => { - target_trait_ref = Some(candidate_trait_ref); - nested.extend(obligations); - break; - } - Err(_) => continue, - } - } - - let target_trait_ref = target_trait_ref.unwrap(); - - let mut offset = 0; - let Some((vtable_base, vtable_vptr_slot)) = - prepare_vtable_segments(infcx.tcx, source_trait_ref, |segment| { - match segment { - VtblSegment::MetadataDSA => { - offset += TyCtxt::COMMON_VTABLE_ENTRIES.len(); - } - VtblSegment::TraitOwnEntries { trait_ref, emit_vptr } => { - let own_vtable_entries = count_own_vtable_entries(infcx.tcx, trait_ref); - - if trait_ref == target_trait_ref { - if emit_vptr { - return ControlFlow::Break(( - offset, - Some(offset + count_own_vtable_entries(infcx.tcx, trait_ref)), - )); - } else { - return ControlFlow::Break((offset, None)); - } - } - - offset += own_vtable_entries; - if emit_vptr { - offset += 1; - } - } - } - ControlFlow::Continue(()) - }) - else { - bug!(); - }; - - // If we're upcasting, get the offset of the vtable pointer, otherwise get - // the base of the vtable. - Ok(Some(if is_upcasting { - ImplSource::TraitUpcasting(ImplSourceTraitUpcastingData { vtable_vptr_slot, nested }) - } else { - ImplSource::Object(ImplSourceObjectData { vtable_base, nested }) - })) -} - /// The `Unsize` trait is particularly important to coercion, so we try rematch it. /// NOTE: This must stay in sync with `consider_builtin_unsize_candidate` in trait /// goal assembly in the solver, both for soundness and in order to avoid ICEs. @@ -328,11 +216,16 @@ fn rematch_unsize<'tcx>( infcx: &InferCtxt<'tcx>, goal: Goal<'tcx, ty::TraitPredicate<'tcx>>, mut nested: Vec>, + source: BuiltinImplSource, ) -> SelectionResult<'tcx, Selection<'tcx>> { let tcx = infcx.tcx; - let a_ty = goal.predicate.self_ty(); - let b_ty = goal.predicate.trait_ref.args.type_at(1); - + let a_ty = structurally_normalize(goal.predicate.self_ty(), infcx, goal.param_env, &mut nested); + let b_ty = structurally_normalize( + goal.predicate.trait_ref.args.type_at(1), + infcx, + goal.param_env, + &mut nested, + ); match (a_ty.kind(), b_ty.kind()) { (_, &ty::Dynamic(data, region, ty::Dyn)) => { // Check that the type implements all of the predicates of the def-id. @@ -360,6 +253,8 @@ fn rematch_unsize<'tcx>( goal.param_env, ty::Binder::dummy(ty::OutlivesPredicate(a_ty, region)), )); + + Ok(Some(ImplSource::Builtin(source, nested))) } // `[T; n]` -> `[T]` unsizing (&ty::Array(a_elem_ty, ..), &ty::Slice(b_elem_ty)) => { @@ -370,6 +265,8 @@ fn rematch_unsize<'tcx>( .expect("expected rematch to succeed") .into_obligations(), ); + + Ok(Some(ImplSource::Builtin(source, nested))) } // Struct unsizing `Struct` -> `Struct` where `T: Unsize` (&ty::Adt(a_def, a_args), &ty::Adt(b_def, b_args)) @@ -420,6 +317,8 @@ fn rematch_unsize<'tcx>( goal.param_env, ty::TraitRef::new(tcx, goal.predicate.def_id(), [a_tail_ty, b_tail_ty]), )); + + Ok(Some(ImplSource::Builtin(source, nested))) } // Tuple unsizing `(.., T)` -> `(.., U)` where `T: Unsize` (&ty::Tuple(a_tys), &ty::Tuple(b_tys)) @@ -446,14 +345,20 @@ fn rematch_unsize<'tcx>( goal.param_env, ty::TraitRef::new(tcx, goal.predicate.def_id(), [*a_last_ty, *b_last_ty]), )); + + // We need to be able to detect tuple unsizing to require its feature gate. + assert_eq!( + source, + BuiltinImplSource::TupleUnsizing, + "compiler-errors wants to know if this can ever be triggered..." + ); + Ok(Some(ImplSource::Builtin(source, nested))) } // FIXME: We *could* ICE here if either: // 1. the certainty is `Certainty::Yes`, // 2. we're in codegen (which should mean `Certainty::Yes`). - _ => return Ok(None), + _ => Ok(None), } - - Ok(Some(ImplSource::Builtin(nested))) } fn structurally_normalize<'tcx>( diff --git a/compiler/rustc_trait_selection/src/solve/inherent_projection.rs b/compiler/rustc_trait_selection/src/solve/inherent_projection.rs index d10a14ff742e..28fe59b7f6a7 100644 --- a/compiler/rustc_trait_selection/src/solve/inherent_projection.rs +++ b/compiler/rustc_trait_selection/src/solve/inherent_projection.rs @@ -1,3 +1,9 @@ +//! Computes a normalizes-to (projection) goal for inherent associated types, +//! `#![feature(inherent_associated_type)]`. Since astconv already determines +//! which impl the IAT is being projected from, we just: +//! 1. instantiate substs, +//! 2. equate the self type, and +//! 3. instantiate and register where clauses. use rustc_middle::traits::solve::{Certainty, Goal, QueryResult}; use rustc_middle::ty; diff --git a/compiler/rustc_trait_selection/src/solve/mod.rs b/compiler/rustc_trait_selection/src/solve/mod.rs index 7c15c3c0e8b5..63e48c94a867 100644 --- a/compiler/rustc_trait_selection/src/solve/mod.rs +++ b/compiler/rustc_trait_selection/src/solve/mod.rs @@ -1,14 +1,19 @@ -//! The new trait solver, currently still WIP. +//! The next-generation trait solver, currently still WIP. //! -//! As a user of the trait system, you can use `TyCtxt::evaluate_goal` to -//! interact with this solver. +//! As a user of rust, you can use `-Ztrait-solver=next` or `next-coherence` +//! to enable the new trait solver always, or just within coherence, respectively. +//! +//! As a developer of rustc, you shouldn't be using the new trait +//! solver without asking the trait-system-refactor-initiative, but it can +//! be enabled with `InferCtxtBuilder::with_next_trait_solver`. This will +//! ensure that trait solving using that inference context will be routed +//! to the new trait solver. //! //! For a high-level overview of how this solver works, check out the relevant //! section of the rustc-dev-guide. //! //! FIXME(@lcnr): Write that section. If you read this before then ask me //! about it on zulip. - use rustc_hir::def_id::DefId; use rustc_infer::infer::canonical::{Canonical, CanonicalVarValues}; use rustc_infer::traits::query::NoSolution; diff --git a/compiler/rustc_trait_selection/src/solve/normalize.rs b/compiler/rustc_trait_selection/src/solve/normalize.rs index f51f4edb9334..091b7f338348 100644 --- a/compiler/rustc_trait_selection/src/solve/normalize.rs +++ b/compiler/rustc_trait_selection/src/solve/normalize.rs @@ -28,7 +28,8 @@ pub(crate) fn deeply_normalize<'tcx, T: TypeFoldable>>( /// its input to be already fully resolved. /// /// Additionally takes a list of universes which represents the binders which have been -/// entered before passing `value` to the function. +/// entered before passing `value` to the function. This is currently needed for +/// `normalize_erasing_regions`, which skips binders as it walks through a type. pub(crate) fn deeply_normalize_with_skipped_universes<'tcx, T: TypeFoldable>>( at: At<'_, 'tcx>, value: T, @@ -194,7 +195,7 @@ impl<'tcx> FallibleTypeFolder> for NormalizationFolder<'_, 'tcx> { mapped_regions, mapped_types, mapped_consts, - &mut self.universes, + &self.universes, result, )) } else { @@ -224,7 +225,7 @@ impl<'tcx> FallibleTypeFolder> for NormalizationFolder<'_, 'tcx> { mapped_regions, mapped_types, mapped_consts, - &mut self.universes, + &self.universes, result, )) } else { diff --git a/compiler/rustc_trait_selection/src/solve/opaques.rs b/compiler/rustc_trait_selection/src/solve/opaques.rs index 2e537d1c358a..f08adc0208b5 100644 --- a/compiler/rustc_trait_selection/src/solve/opaques.rs +++ b/compiler/rustc_trait_selection/src/solve/opaques.rs @@ -1,3 +1,6 @@ +//! Computes a normalizes-to (projection) goal for opaque types. This goal +//! behaves differently depending on the param-env's reveal mode and whether +//! the opaque is in a defining scope. use rustc_middle::traits::query::NoSolution; use rustc_middle::traits::solve::{Certainty, Goal, QueryResult}; use rustc_middle::traits::Reveal; diff --git a/compiler/rustc_trait_selection/src/solve/project_goals.rs b/compiler/rustc_trait_selection/src/solve/project_goals.rs index 222ed9939ba2..03ade738bb63 100644 --- a/compiler/rustc_trait_selection/src/solve/project_goals.rs +++ b/compiler/rustc_trait_selection/src/solve/project_goals.rs @@ -10,6 +10,7 @@ use rustc_infer::traits::specialization_graph::LeafDef; use rustc_infer::traits::Reveal; use rustc_middle::traits::solve::inspect::CandidateKind; use rustc_middle::traits::solve::{CanonicalResponse, Certainty, Goal, QueryResult}; +use rustc_middle::traits::BuiltinImplSource; use rustc_middle::ty::fast_reject::{DeepRejectCtxt, TreatParams}; use rustc_middle::ty::ProjectionPredicate; use rustc_middle::ty::{self, Ty, TyCtxt}; @@ -502,17 +503,10 @@ impl<'tcx> assembly::GoalKind<'tcx> for ProjectionPredicate<'tcx> { ) } - fn consider_builtin_unsize_candidate( + fn consider_builtin_unsize_and_upcast_candidates( _ecx: &mut EvalCtxt<'_, 'tcx>, goal: Goal<'tcx, Self>, - ) -> QueryResult<'tcx> { - bug!("`Unsize` does not have an associated type: {:?}", goal); - } - - fn consider_builtin_dyn_upcast_candidates( - _ecx: &mut EvalCtxt<'_, 'tcx>, - goal: Goal<'tcx, Self>, - ) -> Vec> { + ) -> Vec<(CanonicalResponse<'tcx>, BuiltinImplSource)> { bug!("`Unsize` does not have an associated type: {:?}", goal); } diff --git a/compiler/rustc_trait_selection/src/solve/trait_goals.rs b/compiler/rustc_trait_selection/src/solve/trait_goals.rs index 930e62d63883..24ea9b5ea124 100644 --- a/compiler/rustc_trait_selection/src/solve/trait_goals.rs +++ b/compiler/rustc_trait_selection/src/solve/trait_goals.rs @@ -1,13 +1,14 @@ //! Dealing with trait goals, i.e. `T: Trait<'a, U>`. use super::assembly::{self, structural_traits}; +use super::search_graph::OverflowHandler; use super::{EvalCtxt, SolverMode}; use rustc_hir::def_id::DefId; use rustc_hir::{LangItem, Movability}; use rustc_infer::traits::query::NoSolution; -use rustc_infer::traits::util::supertraits; -use rustc_middle::traits::solve::{CanonicalResponse, Certainty, Goal, QueryResult}; -use rustc_middle::traits::Reveal; +use rustc_middle::traits::solve::inspect::CandidateKind; +use rustc_middle::traits::solve::{CanonicalResponse, Certainty, Goal, MaybeCause, QueryResult}; +use rustc_middle::traits::{BuiltinImplSource, Reveal}; use rustc_middle::ty::fast_reject::{DeepRejectCtxt, TreatParams, TreatProjections}; use rustc_middle::ty::{self, ToPredicate, Ty, TyCtxt}; use rustc_middle::ty::{TraitPredicate, TypeVisitableExt}; @@ -365,198 +366,67 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> { ) } - fn consider_builtin_unsize_candidate( + fn consider_builtin_unsize_and_upcast_candidates( ecx: &mut EvalCtxt<'_, 'tcx>, goal: Goal<'tcx, Self>, - ) -> QueryResult<'tcx> { - if goal.predicate.polarity != ty::ImplPolarity::Positive { - return Err(NoSolution); - } - - let tcx = ecx.tcx(); - let a_ty = goal.predicate.self_ty(); - let b_ty = goal.predicate.trait_ref.args.type_at(1); - if b_ty.is_ty_var() { - return ecx.evaluate_added_goals_and_make_canonical_response(Certainty::AMBIGUOUS); - } - ecx.probe_candidate("builtin unsize").enter(|ecx| { - match (a_ty.kind(), b_ty.kind()) { - // Trait upcasting, or `dyn Trait + Auto + 'a` -> `dyn Trait + 'b` - (&ty::Dynamic(_, _, ty::Dyn), &ty::Dynamic(_, _, ty::Dyn)) => { - // Dyn upcasting is handled separately, since due to upcasting, - // when there are two supertraits that differ by args, we - // may return more than one query response. - Err(NoSolution) - } - // `T` -> `dyn Trait` unsizing - (_, &ty::Dynamic(data, region, ty::Dyn)) => { - // Can only unsize to an object-safe type - if data - .principal_def_id() - .is_some_and(|def_id| !tcx.check_is_object_safe(def_id)) - { - return Err(NoSolution); - } - - let Some(sized_def_id) = tcx.lang_items().sized_trait() else { - return Err(NoSolution); - }; - // Check that the type implements all of the predicates of the def-id. - // (i.e. the principal, all of the associated types match, and any auto traits) - ecx.add_goals( - data.iter().map(|pred| goal.with(tcx, pred.with_self_ty(tcx, a_ty))), - ); - // The type must be Sized to be unsized. - ecx.add_goal(goal.with(tcx, ty::TraitRef::new(tcx, sized_def_id, [a_ty]))); - // The type must outlive the lifetime of the `dyn` we're unsizing into. - ecx.add_goal( - goal.with(tcx, ty::Binder::dummy(ty::OutlivesPredicate(a_ty, region))), - ); - ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) - } - // `[T; n]` -> `[T]` unsizing - (&ty::Array(a_elem_ty, ..), &ty::Slice(b_elem_ty)) => { - // We just require that the element type stays the same - ecx.eq(goal.param_env, a_elem_ty, b_elem_ty)?; - ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) - } - // Struct unsizing `Struct` -> `Struct` where `T: Unsize` - (&ty::Adt(a_def, a_args), &ty::Adt(b_def, b_args)) - if a_def.is_struct() && a_def.did() == b_def.did() => - { - let unsizing_params = tcx.unsizing_params_for_adt(a_def.did()); - // We must be unsizing some type parameters. This also implies - // that the struct has a tail field. - if unsizing_params.is_empty() { - return Err(NoSolution); - } - - let tail_field = a_def.non_enum_variant().tail(); - let tail_field_ty = tcx.type_of(tail_field.did); - - let a_tail_ty = tail_field_ty.instantiate(tcx, a_args); - let b_tail_ty = tail_field_ty.instantiate(tcx, b_args); - - // Substitute just the unsizing params from B into A. The type after - // this substitution must be equal to B. This is so we don't unsize - // unrelated type parameters. - let new_a_args = - tcx.mk_args_from_iter(a_args.iter().enumerate().map(|(i, a)| { - if unsizing_params.contains(i as u32) { b_args[i] } else { a } - })); - let unsized_a_ty = Ty::new_adt(tcx, a_def, new_a_args); - - // Finally, we require that `TailA: Unsize` for the tail field - // types. - ecx.eq(goal.param_env, unsized_a_ty, b_ty)?; - ecx.add_goal(goal.with( - tcx, - ty::TraitRef::new(tcx, goal.predicate.def_id(), [a_tail_ty, b_tail_ty]), - )); - ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) - } - // Tuple unsizing `(.., T)` -> `(.., U)` where `T: Unsize` - (&ty::Tuple(a_tys), &ty::Tuple(b_tys)) - if a_tys.len() == b_tys.len() && !a_tys.is_empty() => - { - let (a_last_ty, a_rest_tys) = a_tys.split_last().unwrap(); - let b_last_ty = b_tys.last().unwrap(); - - // Substitute just the tail field of B., and require that they're equal. - let unsized_a_ty = - Ty::new_tup_from_iter(tcx, a_rest_tys.iter().chain([b_last_ty]).copied()); - ecx.eq(goal.param_env, unsized_a_ty, b_ty)?; - - // Similar to ADTs, require that the rest of the fields are equal. - ecx.add_goal(goal.with( - tcx, - ty::TraitRef::new(tcx, goal.predicate.def_id(), [*a_last_ty, *b_last_ty]), - )); - ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) - } - _ => Err(NoSolution), - } - }) - } - - fn consider_builtin_dyn_upcast_candidates( - ecx: &mut EvalCtxt<'_, 'tcx>, - goal: Goal<'tcx, Self>, - ) -> Vec> { + ) -> Vec<(CanonicalResponse<'tcx>, BuiltinImplSource)> { if goal.predicate.polarity != ty::ImplPolarity::Positive { return vec![]; } - let tcx = ecx.tcx(); + ecx.probe(|_| CandidateKind::DynUpcastingAssembly).enter(|ecx| { + let a_ty = goal.predicate.self_ty(); + // We need to normalize the b_ty since it's matched structurally + // in the other functions below. + let b_ty = match ecx + .normalize_non_self_ty(goal.predicate.trait_ref.args.type_at(1), goal.param_env) + { + Ok(Some(b_ty)) => { + // If we have a type var, then bail with ambiguity. + if b_ty.is_ty_var() { + return vec![( + ecx.evaluate_added_goals_and_make_canonical_response( + Certainty::AMBIGUOUS, + ) + .unwrap(), + BuiltinImplSource::Misc, + )]; + } else { + b_ty + } + } + Ok(None) => { + return vec![( + ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Maybe( + MaybeCause::Overflow, + )) + .unwrap(), + BuiltinImplSource::Misc, + )]; + } + Err(_) => return vec![], + }; - let a_ty = goal.predicate.self_ty(); - let b_ty = goal.predicate.trait_ref.args.type_at(1); - let ty::Dynamic(a_data, a_region, ty::Dyn) = *a_ty.kind() else { - return vec![]; - }; - let ty::Dynamic(b_data, b_region, ty::Dyn) = *b_ty.kind() else { - return vec![]; - }; - - // All of a's auto traits need to be in b's auto traits. - let auto_traits_compatible = - b_data.auto_traits().all(|b| a_data.auto_traits().any(|a| a == b)); - if !auto_traits_compatible { - return vec![]; - } - - let mut unsize_dyn_to_principal = |principal: Option>| { - ecx.probe_candidate("upcast dyn to principle").enter(|ecx| -> Result<_, NoSolution> { - // Require that all of the trait predicates from A match B, except for - // the auto traits. We do this by constructing a new A type with B's - // auto traits, and equating these types. - let new_a_data = principal + let mut results = vec![]; + results.extend(ecx.consider_builtin_dyn_upcast_candidates(goal.param_env, a_ty, b_ty)); + results.extend( + ecx.consider_builtin_unsize_candidate(goal.with(ecx.tcx(), (a_ty, b_ty))) .into_iter() - .map(|trait_ref| trait_ref.map_bound(ty::ExistentialPredicate::Trait)) - .chain(a_data.iter().filter(|a| { - matches!(a.skip_binder(), ty::ExistentialPredicate::Projection(_)) - })) - .chain( - b_data - .auto_traits() - .map(ty::ExistentialPredicate::AutoTrait) - .map(ty::Binder::dummy), - ); - let new_a_data = tcx.mk_poly_existential_predicates_from_iter(new_a_data); - let new_a_ty = Ty::new_dynamic(tcx, new_a_data, b_region, ty::Dyn); + .map(|resp| { + // If we're unsizing from tuple -> tuple, detect + let source = + if matches!((a_ty.kind(), b_ty.kind()), (ty::Tuple(..), ty::Tuple(..))) + { + BuiltinImplSource::TupleUnsizing + } else { + BuiltinImplSource::Misc + }; + (resp, source) + }), + ); - // We also require that A's lifetime outlives B's lifetime. - ecx.eq(goal.param_env, new_a_ty, b_ty)?; - ecx.add_goal( - goal.with(tcx, ty::Binder::dummy(ty::OutlivesPredicate(a_region, b_region))), - ); - ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) - }) - }; - - let mut responses = vec![]; - // If the principal def ids match (or are both none), then we're not doing - // trait upcasting. We're just removing auto traits (or shortening the lifetime). - if a_data.principal_def_id() == b_data.principal_def_id() { - if let Ok(response) = unsize_dyn_to_principal(a_data.principal()) { - responses.push(response); - } - } else if let Some(a_principal) = a_data.principal() - && let Some(b_principal) = b_data.principal() - { - for super_trait_ref in supertraits(tcx, a_principal.with_self_ty(tcx, a_ty)) { - if super_trait_ref.def_id() != b_principal.def_id() { - continue; - } - let erased_trait_ref = super_trait_ref - .map_bound(|trait_ref| ty::ExistentialTraitRef::erase_self_ty(tcx, trait_ref)); - if let Ok(response) = unsize_dyn_to_principal(Some(erased_trait_ref)) { - responses.push(response); - } - } - } - - responses + results + }) } fn consider_builtin_discriminant_kind_candidate( @@ -622,6 +492,220 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> { } impl<'tcx> EvalCtxt<'_, 'tcx> { + fn consider_builtin_unsize_candidate( + &mut self, + goal: Goal<'tcx, (Ty<'tcx>, Ty<'tcx>)>, + ) -> QueryResult<'tcx> { + let Goal { param_env, predicate: (a_ty, b_ty) } = goal; + self.probe_candidate("builtin unsize").enter(|ecx| { + let tcx = ecx.tcx(); + match (a_ty.kind(), b_ty.kind()) { + (ty::Infer(ty::TyVar(_)), _) | (_, ty::Infer(ty::TyVar(_))) => { + bug!("unexpected type variable in unsize goal") + } + // Trait upcasting, or `dyn Trait + Auto + 'a` -> `dyn Trait + 'b` + (&ty::Dynamic(_, _, ty::Dyn), &ty::Dynamic(_, _, ty::Dyn)) => { + // Dyn upcasting is handled separately, since due to upcasting, + // when there are two supertraits that differ by args, we + // may return more than one query response. + Err(NoSolution) + } + // `T` -> `dyn Trait` unsizing + (_, &ty::Dynamic(data, region, ty::Dyn)) => { + // Can only unsize to an object-safe type + if data + .principal_def_id() + .is_some_and(|def_id| !tcx.check_is_object_safe(def_id)) + { + return Err(NoSolution); + } + + let Some(sized_def_id) = tcx.lang_items().sized_trait() else { + return Err(NoSolution); + }; + // Check that the type implements all of the predicates of the def-id. + // (i.e. the principal, all of the associated types match, and any auto traits) + ecx.add_goals( + data.iter() + .map(|pred| Goal::new(tcx, param_env, pred.with_self_ty(tcx, a_ty))), + ); + // The type must be Sized to be unsized. + ecx.add_goal(Goal::new( + tcx, + param_env, + ty::TraitRef::new(tcx, sized_def_id, [a_ty]), + )); + // The type must outlive the lifetime of the `dyn` we're unsizing into. + ecx.add_goal(Goal::new( + tcx, + param_env, + ty::Binder::dummy(ty::OutlivesPredicate(a_ty, region)), + )); + ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) + } + // `[T; n]` -> `[T]` unsizing + (&ty::Array(a_elem_ty, ..), &ty::Slice(b_elem_ty)) => { + // We just require that the element type stays the same + ecx.eq(param_env, a_elem_ty, b_elem_ty)?; + ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) + } + // Struct unsizing `Struct` -> `Struct` where `T: Unsize` + (&ty::Adt(a_def, a_args), &ty::Adt(b_def, b_args)) + if a_def.is_struct() && a_def.did() == b_def.did() => + { + let unsizing_params = tcx.unsizing_params_for_adt(a_def.did()); + // We must be unsizing some type parameters. This also implies + // that the struct has a tail field. + if unsizing_params.is_empty() { + return Err(NoSolution); + } + + let tail_field = a_def.non_enum_variant().tail(); + let tail_field_ty = tcx.type_of(tail_field.did); + + let a_tail_ty = tail_field_ty.instantiate(tcx, a_args); + let b_tail_ty = tail_field_ty.instantiate(tcx, b_args); + + // Substitute just the unsizing params from B into A. The type after + // this substitution must be equal to B. This is so we don't unsize + // unrelated type parameters. + let new_a_args = + tcx.mk_args_from_iter(a_args.iter().enumerate().map(|(i, a)| { + if unsizing_params.contains(i as u32) { b_args[i] } else { a } + })); + let unsized_a_ty = Ty::new_adt(tcx, a_def, new_a_args); + + // Finally, we require that `TailA: Unsize` for the tail field + // types. + ecx.eq(param_env, unsized_a_ty, b_ty)?; + ecx.add_goal(Goal::new( + tcx, + param_env, + ty::TraitRef::new( + tcx, + tcx.lang_items().unsize_trait().unwrap(), + [a_tail_ty, b_tail_ty], + ), + )); + ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) + } + // Tuple unsizing `(.., T)` -> `(.., U)` where `T: Unsize` + (&ty::Tuple(a_tys), &ty::Tuple(b_tys)) + if a_tys.len() == b_tys.len() && !a_tys.is_empty() => + { + let (a_last_ty, a_rest_tys) = a_tys.split_last().unwrap(); + let b_last_ty = b_tys.last().unwrap(); + + // Substitute just the tail field of B., and require that they're equal. + let unsized_a_ty = + Ty::new_tup_from_iter(tcx, a_rest_tys.iter().chain([b_last_ty]).copied()); + ecx.eq(param_env, unsized_a_ty, b_ty)?; + + // Similar to ADTs, require that the rest of the fields are equal. + ecx.add_goal(Goal::new( + tcx, + param_env, + ty::TraitRef::new( + tcx, + tcx.lang_items().unsize_trait().unwrap(), + [*a_last_ty, *b_last_ty], + ), + )); + ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) + } + _ => Err(NoSolution), + } + }) + } + + fn consider_builtin_dyn_upcast_candidates( + &mut self, + param_env: ty::ParamEnv<'tcx>, + a_ty: Ty<'tcx>, + b_ty: Ty<'tcx>, + ) -> Vec<(CanonicalResponse<'tcx>, BuiltinImplSource)> { + if a_ty.is_ty_var() || b_ty.is_ty_var() { + bug!("unexpected type variable in unsize goal") + } + + let ty::Dynamic(a_data, a_region, ty::Dyn) = *a_ty.kind() else { + return vec![]; + }; + let ty::Dynamic(b_data, b_region, ty::Dyn) = *b_ty.kind() else { + return vec![]; + }; + + let tcx = self.tcx(); + // All of a's auto traits need to be in b's auto traits. + let auto_traits_compatible = + b_data.auto_traits().all(|b| a_data.auto_traits().any(|a| a == b)); + if !auto_traits_compatible { + return vec![]; + } + + // Try to match `a_ty` against `b_ty`, replacing `a_ty`'s principal trait ref with + // the supertrait principal and subtyping the types. + let unsize_dyn_to_principal = + |ecx: &mut Self, principal: Option>| { + ecx.probe_candidate("upcast dyn to principle").enter( + |ecx| -> Result<_, NoSolution> { + // Require that all of the trait predicates from A match B, except for + // the auto traits. We do this by constructing a new A type with B's + // auto traits, and equating these types. + let new_a_data = principal + .into_iter() + .map(|trait_ref| trait_ref.map_bound(ty::ExistentialPredicate::Trait)) + .chain(a_data.iter().filter(|a| { + matches!(a.skip_binder(), ty::ExistentialPredicate::Projection(_)) + })) + .chain( + b_data + .auto_traits() + .map(ty::ExistentialPredicate::AutoTrait) + .map(ty::Binder::dummy), + ); + let new_a_data = tcx.mk_poly_existential_predicates_from_iter(new_a_data); + let new_a_ty = Ty::new_dynamic(tcx, new_a_data, b_region, ty::Dyn); + + // We also require that A's lifetime outlives B's lifetime. + ecx.eq(param_env, new_a_ty, b_ty)?; + ecx.add_goal(Goal::new( + tcx, + param_env, + ty::Binder::dummy(ty::OutlivesPredicate(a_region, b_region)), + )); + ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) + }, + ) + }; + + let mut responses = vec![]; + // If the principal def ids match (or are both none), then we're not doing + // trait upcasting. We're just removing auto traits (or shortening the lifetime). + if a_data.principal_def_id() == b_data.principal_def_id() { + if let Ok(resp) = unsize_dyn_to_principal(self, a_data.principal()) { + responses.push((resp, BuiltinImplSource::Misc)); + } + } else if let Some(a_principal) = a_data.principal() { + self.walk_vtable( + a_principal.with_self_ty(tcx, a_ty), + |ecx, new_a_principal, _, vtable_vptr_slot| { + if let Ok(resp) = unsize_dyn_to_principal( + ecx, + Some(new_a_principal.map_bound(|trait_ref| { + ty::ExistentialTraitRef::erase_self_ty(tcx, trait_ref) + })), + ) { + responses + .push((resp, BuiltinImplSource::TraitUpcasting { vtable_vptr_slot })); + } + }, + ); + } + + responses + } + // Return `Some` if there is an impl (built-in or user provided) that may // hold for the self type of the goal, which for coherence and soundness // purposes must disqualify the built-in auto impl assembled by considering @@ -750,4 +834,47 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { let candidates = self.assemble_and_evaluate_candidates(goal); self.merge_candidates(candidates) } + + /// Normalize a non-self type when it is structually matched on when solving + /// a built-in goal. This is handled already through `assemble_candidates_after_normalizing_self_ty` + /// for the self type, but for other goals, additional normalization of other + /// arguments may be needed to completely implement the semantics of the trait. + /// + /// This is required when structurally matching on any trait argument that is + /// not the self type. + fn normalize_non_self_ty( + &mut self, + mut ty: Ty<'tcx>, + param_env: ty::ParamEnv<'tcx>, + ) -> Result>, NoSolution> { + if !matches!(ty.kind(), ty::Alias(..)) { + return Ok(Some(ty)); + } + + self.repeat_while_none( + |_| Ok(None), + |ecx| { + let ty::Alias(_, projection_ty) = *ty.kind() else { + return Some(Ok(Some(ty))); + }; + + let normalized_ty = ecx.next_ty_infer(); + let normalizes_to_goal = Goal::new( + ecx.tcx(), + param_env, + ty::Binder::dummy(ty::ProjectionPredicate { + projection_ty, + term: normalized_ty.into(), + }), + ); + ecx.add_goal(normalizes_to_goal); + if let Err(err) = ecx.try_evaluate_added_goals() { + return Some(Err(err)); + } + + ty = ecx.resolve_vars_if_possible(normalized_ty); + None + }, + ) + } } diff --git a/compiler/rustc_trait_selection/src/solve/weak_types.rs b/compiler/rustc_trait_selection/src/solve/weak_types.rs index c7717879a4ac..54de32cf6189 100644 --- a/compiler/rustc_trait_selection/src/solve/weak_types.rs +++ b/compiler/rustc_trait_selection/src/solve/weak_types.rs @@ -1,3 +1,8 @@ +//! Computes a normalizes-to (projection) goal for inherent associated types, +//! `#![feature(lazy_type_alias)]` and `#![feature(type_alias_impl_trait)]`. +//! +//! Since a weak alias is not ambiguous, this just computes the `type_of` of +//! the alias and registers the where-clauses of the type alias. use rustc_middle::traits::solve::{Certainty, Goal, QueryResult}; use rustc_middle::ty; diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs index fbe8d4a66803..a530b27bc918 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs @@ -329,18 +329,13 @@ pub struct OnUnimplementedNote { } /// Append a message for `~const Trait` errors. -#[derive(Clone, Copy, PartialEq, Eq, Debug)] +#[derive(Clone, Copy, PartialEq, Eq, Debug, Default)] pub enum AppendConstMessage { + #[default] Default, Custom(Symbol), } -impl Default for AppendConstMessage { - fn default() -> Self { - AppendConstMessage::Default - } -} - impl<'tcx> OnUnimplementedDirective { fn parse( tcx: TyCtxt<'tcx>, diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs index 05d2934d4c53..220b3576ddbd 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs @@ -777,18 +777,14 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { real_trait_pred = parent_trait_pred; } - let real_ty = real_trait_pred.self_ty(); // We `erase_late_bound_regions` here because `make_subregion` does not handle // `ReLateBound`, and we don't particularly care about the regions. - if !self.can_eq( - obligation.param_env, - self.tcx.erase_late_bound_regions(real_ty), - arg_ty, - ) { + let real_ty = self.tcx.erase_late_bound_regions(real_trait_pred.self_ty()); + if !self.can_eq(obligation.param_env, real_ty, arg_ty) { continue; } - if let ty::Ref(region, base_ty, mutbl) = *real_ty.skip_binder().kind() { + if let ty::Ref(region, base_ty, mutbl) = *real_ty.kind() { let autoderef = (self.autoderef_steps)(base_ty); if let Some(steps) = autoderef.into_iter().enumerate().find_map(|(steps, (ty, obligations))| { @@ -1471,7 +1467,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { let span = if needs_parens { span } else { span.shrink_to_lo() }; let suggestions = if !needs_parens { - vec![(span.shrink_to_lo(), format!("{}", sugg_prefix))] + vec![(span.shrink_to_lo(), sugg_prefix)] } else { vec![ (span.shrink_to_lo(), format!("{}(", sugg_prefix)), diff --git a/compiler/rustc_trait_selection/src/traits/mod.rs b/compiler/rustc_trait_selection/src/traits/mod.rs index 1c1459991841..6bab87e5de54 100644 --- a/compiler/rustc_trait_selection/src/traits/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/mod.rs @@ -474,11 +474,14 @@ fn subst_and_check_impossible_predicates<'tcx>( result } -/// Checks whether a trait's method is impossible to call on a given impl. +/// Checks whether a trait's associated item is impossible to reference on a given impl. /// /// This only considers predicates that reference the impl's generics, and not /// those that reference the method's generics. -fn is_impossible_method(tcx: TyCtxt<'_>, (impl_def_id, trait_item_def_id): (DefId, DefId)) -> bool { +fn is_impossible_associated_item( + tcx: TyCtxt<'_>, + (impl_def_id, trait_item_def_id): (DefId, DefId), +) -> bool { struct ReferencesOnlyParentGenerics<'tcx> { tcx: TyCtxt<'tcx>, generics: &'tcx ty::Generics, @@ -556,7 +559,7 @@ pub fn provide(providers: &mut Providers) { specializes: specialize::specializes, subst_and_check_impossible_predicates, check_tys_might_be_eq: misc::check_tys_might_be_eq, - is_impossible_method, + is_impossible_associated_item, ..*providers }; } diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs index a39fc1f17718..a35dd1f1a591 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -4,7 +4,6 @@ use super::check_args_compatible; use super::specialization_graph; use super::translate_args; use super::util; -use super::ImplSourceUserDefinedData; use super::MismatchedProjectionTypes; use super::Obligation; use super::ObligationCause; @@ -13,6 +12,9 @@ use super::Selection; use super::SelectionContext; use super::SelectionError; use super::{Normalized, NormalizedTy, ProjectionCacheEntry, ProjectionCacheKey}; +use rustc_middle::traits::BuiltinImplSource; +use rustc_middle::traits::ImplSource; +use rustc_middle::traits::ImplSourceUserDefinedData; use crate::errors::InherentProjectionNormalizationOverflow; use crate::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; @@ -1717,7 +1719,7 @@ fn assemble_candidates_from_impls<'cx, 'tcx>( }; let eligible = match &impl_source { - super::ImplSource::UserDefined(impl_data) => { + ImplSource::UserDefined(impl_data) => { // We have to be careful when projecting out of an // impl because of specialization. If we are not in // codegen (i.e., projection mode is not "any"), and the @@ -1767,7 +1769,7 @@ fn assemble_candidates_from_impls<'cx, 'tcx>( } } } - super::ImplSource::Builtin(..) => { + ImplSource::Builtin(BuiltinImplSource::Misc, _) => { // While a builtin impl may be known to exist, the associated type may not yet // be known. Any type with multiple potential associated types is therefore // not eligible. @@ -1891,7 +1893,7 @@ fn assemble_candidates_from_impls<'cx, 'tcx>( bug!("unexpected builtin trait with associated type: {trait_ref:?}") } } - super::ImplSource::Param(..) => { + ImplSource::Param(..) => { // This case tell us nothing about the value of an // associated type. Consider: // @@ -1919,13 +1921,14 @@ fn assemble_candidates_from_impls<'cx, 'tcx>( // in `assemble_candidates_from_param_env`. false } - super::ImplSource::Object(_) => { + ImplSource::Builtin(BuiltinImplSource::Object { .. }, _) => { // Handled by the `Object` projection candidate. See // `assemble_candidates_from_object_ty` for an explanation of // why we special case object types. false } - | super::ImplSource::TraitUpcasting(_) => { + ImplSource::Builtin(BuiltinImplSource::TraitUpcasting { .. }, _) + | ImplSource::Builtin(BuiltinImplSource::TupleUnsizing, _) => { // These traits have no associated types. selcx.tcx().sess.delay_span_bug( obligation.cause.span, @@ -1985,8 +1988,8 @@ fn confirm_select_candidate<'cx, 'tcx>( impl_source: Selection<'tcx>, ) -> Progress<'tcx> { match impl_source { - super::ImplSource::UserDefined(data) => confirm_impl_candidate(selcx, obligation, data), - super::ImplSource::Builtin(data) => { + ImplSource::UserDefined(data) => confirm_impl_candidate(selcx, obligation, data), + ImplSource::Builtin(BuiltinImplSource::Misc, data) => { let trait_def_id = obligation.predicate.trait_def_id(selcx.tcx()); let lang_items = selcx.tcx().lang_items(); if lang_items.gen_trait() == Some(trait_def_id) { @@ -2003,9 +2006,10 @@ fn confirm_select_candidate<'cx, 'tcx>( confirm_builtin_candidate(selcx, obligation, data) } } - super::ImplSource::Object(_) - | super::ImplSource::Param(..) - | super::ImplSource::TraitUpcasting(_) => { + ImplSource::Builtin(BuiltinImplSource::Object { .. }, _) + | ImplSource::Param(..) + | ImplSource::Builtin(BuiltinImplSource::TraitUpcasting { .. }, _) + | ImplSource::Builtin(BuiltinImplSource::TupleUnsizing, _) => { // we don't create Select candidates with this kind of resolution span_bug!( obligation.cause.span, diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs index 2cb2895b4764..92b9364adfa1 100644 --- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs +++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs @@ -11,7 +11,7 @@ use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_hir::lang_items::LangItem; use rustc_infer::infer::LateBoundRegionConversionTime::HigherRankedType; use rustc_infer::infer::{DefineOpaqueTypes, InferOk}; -use rustc_middle::traits::SelectionOutputTypeParameterMismatch; +use rustc_middle::traits::{BuiltinImplSource, SelectionOutputTypeParameterMismatch}; use rustc_middle::ty::{ self, Binder, GenericArgs, GenericArgsRef, GenericParamDefKind, ToPolyTraitRef, ToPredicate, TraitPredicate, TraitRef, Ty, TyCtxt, TypeVisitableExt, @@ -26,9 +26,9 @@ use crate::traits::vtable::{ }; use crate::traits::{ BuiltinDerivedObligation, ImplDerivedObligation, ImplDerivedObligationCause, ImplSource, - ImplSourceObjectData, ImplSourceTraitUpcastingData, ImplSourceUserDefinedData, Normalized, - Obligation, ObligationCause, OutputTypeParameterMismatch, PolyTraitObligation, - PredicateObligation, Selection, SelectionError, TraitNotObjectSafe, Unimplemented, + ImplSourceUserDefinedData, Normalized, Obligation, ObligationCause, + OutputTypeParameterMismatch, PolyTraitObligation, PredicateObligation, Selection, + SelectionError, TraitNotObjectSafe, Unimplemented, }; use super::BuiltinImplConditions; @@ -48,18 +48,18 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { let mut impl_src = match candidate { BuiltinCandidate { has_nested } => { let data = self.confirm_builtin_candidate(obligation, has_nested); - ImplSource::Builtin(data) + ImplSource::Builtin(BuiltinImplSource::Misc, data) } TransmutabilityCandidate => { let data = self.confirm_transmutability_candidate(obligation)?; - ImplSource::Builtin(data) + ImplSource::Builtin(BuiltinImplSource::Misc, data) } ParamCandidate(param) => { let obligations = self.confirm_param_candidate(obligation, param.map_bound(|t| t.trait_ref)); - ImplSource::Param(obligations, param.skip_binder().constness) + ImplSource::Param(param.skip_binder().constness, obligations) } ImplCandidate(impl_def_id) => { @@ -68,64 +68,57 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { AutoImplCandidate => { let data = self.confirm_auto_impl_candidate(obligation)?; - ImplSource::Builtin(data) + ImplSource::Builtin(BuiltinImplSource::Misc, data) } ProjectionCandidate(idx, constness) => { let obligations = self.confirm_projection_candidate(obligation, idx)?; - ImplSource::Param(obligations, constness) + ImplSource::Param(constness, obligations) } - ObjectCandidate(idx) => { - let data = self.confirm_object_candidate(obligation, idx)?; - ImplSource::Object(data) - } + ObjectCandidate(idx) => self.confirm_object_candidate(obligation, idx)?, ClosureCandidate { .. } => { let vtable_closure = self.confirm_closure_candidate(obligation)?; - ImplSource::Builtin(vtable_closure) + ImplSource::Builtin(BuiltinImplSource::Misc, vtable_closure) } GeneratorCandidate => { let vtable_generator = self.confirm_generator_candidate(obligation)?; - ImplSource::Builtin(vtable_generator) + ImplSource::Builtin(BuiltinImplSource::Misc, vtable_generator) } FutureCandidate => { let vtable_future = self.confirm_future_candidate(obligation)?; - ImplSource::Builtin(vtable_future) + ImplSource::Builtin(BuiltinImplSource::Misc, vtable_future) } FnPointerCandidate { is_const } => { let data = self.confirm_fn_pointer_candidate(obligation, is_const)?; - ImplSource::Builtin(data) + ImplSource::Builtin(BuiltinImplSource::Misc, data) } TraitAliasCandidate => { let data = self.confirm_trait_alias_candidate(obligation); - ImplSource::Builtin(data) + ImplSource::Builtin(BuiltinImplSource::Misc, data) } BuiltinObjectCandidate => { // This indicates something like `Trait + Send: Send`. In this case, we know that // this holds because that's what the object type is telling us, and there's really // no additional obligations to prove and no types in particular to unify, etc. - ImplSource::Builtin(Vec::new()) + ImplSource::Builtin(BuiltinImplSource::Misc, Vec::new()) } - BuiltinUnsizeCandidate => { - let data = self.confirm_builtin_unsize_candidate(obligation)?; - ImplSource::Builtin(data) - } + BuiltinUnsizeCandidate => self.confirm_builtin_unsize_candidate(obligation)?, TraitUpcastingUnsizeCandidate(idx) => { - let data = self.confirm_trait_upcasting_unsize_candidate(obligation, idx)?; - ImplSource::TraitUpcasting(data) + self.confirm_trait_upcasting_unsize_candidate(obligation, idx)? } ConstDestructCandidate(def_id) => { let data = self.confirm_const_destruct_candidate(obligation, def_id)?; - ImplSource::Builtin(data) + ImplSource::Builtin(BuiltinImplSource::Misc, data) } }; @@ -484,7 +477,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { &mut self, obligation: &PolyTraitObligation<'tcx>, index: usize, - ) -> Result>, SelectionError<'tcx>> { + ) -> Result>, SelectionError<'tcx>> { let tcx = self.tcx(); debug!(?obligation, ?index, "confirm_object_candidate"); @@ -648,7 +641,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { (unnormalized_upcast_trait_ref, ty::Binder::dummy(object_trait_ref)), ); - Ok(ImplSourceObjectData { vtable_base, nested }) + Ok(ImplSource::Builtin(BuiltinImplSource::Object { vtable_base: vtable_base }, nested)) } fn confirm_fn_pointer_candidate( @@ -897,7 +890,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { &mut self, obligation: &PolyTraitObligation<'tcx>, idx: usize, - ) -> Result>, SelectionError<'tcx>> { + ) -> Result>, SelectionError<'tcx>> { let tcx = self.tcx(); // `assemble_candidates_for_unsizing` should ensure there are no late-bound @@ -994,13 +987,13 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { let vtable_vptr_slot = prepare_vtable_segments(tcx, source_trait_ref, vtable_segment_callback).unwrap(); - Ok(ImplSourceTraitUpcastingData { vtable_vptr_slot, nested }) + Ok(ImplSource::Builtin(BuiltinImplSource::TraitUpcasting { vtable_vptr_slot }, nested)) } fn confirm_builtin_unsize_candidate( &mut self, obligation: &PolyTraitObligation<'tcx>, - ) -> Result>, SelectionError<'tcx>> { + ) -> Result>, SelectionError<'tcx>> { let tcx = self.tcx(); // `assemble_candidates_for_unsizing` should ensure there are no late-bound @@ -1008,10 +1001,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { let source = self.infcx.shallow_resolve(obligation.self_ty().no_bound_vars().unwrap()); let target = obligation.predicate.skip_binder().trait_ref.args.type_at(1); let target = self.infcx.shallow_resolve(target); - debug!(?source, ?target, "confirm_builtin_unsize_candidate"); let mut nested = vec![]; + let src; match (source.kind(), target.kind()) { // Trait+Kx+'a -> Trait+Ky+'b (auto traits and lifetime subtyping). (&ty::Dynamic(ref data_a, r_a, dyn_a), &ty::Dynamic(ref data_b, r_b, dyn_b)) @@ -1055,6 +1048,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { obligation.param_env, obligation.predicate.rebind(outlives), )); + + src = BuiltinImplSource::Misc; } // `T` -> `Trait` @@ -1101,6 +1096,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { nested.push(predicate_to_obligation( ty::Binder::dummy(ty::ClauseKind::TypeOutlives(outlives)).to_predicate(tcx), )); + + src = BuiltinImplSource::Misc; } // `[T; n]` -> `[T]` @@ -1111,6 +1108,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { .eq(DefineOpaqueTypes::No, b, a) .map_err(|_| Unimplemented)?; nested.extend(obligations); + + src = BuiltinImplSource::Misc; } // `Struct` -> `Struct` @@ -1167,6 +1166,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { ), ); nested.push(tail_unsize_obligation); + + src = BuiltinImplSource::Misc; } // `(.., T)` -> `(.., U)` @@ -1194,12 +1195,14 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { ty::TraitRef::new(tcx, obligation.predicate.def_id(), [a_last, b_last]), ); nested.push(last_unsize_obligation); + + src = BuiltinImplSource::TupleUnsizing; } _ => bug!("source: {source}, target: {target}"), }; - Ok(nested) + Ok(ImplSource::Builtin(src, nested)) } fn confirm_const_destruct_candidate( diff --git a/compiler/rustc_trait_selection/src/traits/util.rs b/compiler/rustc_trait_selection/src/traits/util.rs index 7b34908c4bed..3eab885a089b 100644 --- a/compiler/rustc_trait_selection/src/traits/util.rs +++ b/compiler/rustc_trait_selection/src/traits/util.rs @@ -241,9 +241,9 @@ pub fn upcast_choices<'tcx>( /// Given an upcast trait object described by `object`, returns the /// index of the method `method_def_id` (which should be part of /// `object.upcast_trait_ref`) within the vtable for `object`. -pub fn get_vtable_index_of_object_method<'tcx, N>( +pub fn get_vtable_index_of_object_method<'tcx>( tcx: TyCtxt<'tcx>, - object: &super::ImplSourceObjectData, + vtable_base: usize, method_def_id: DefId, ) -> Option { // Count number of methods preceding the one we are selecting and @@ -252,7 +252,7 @@ pub fn get_vtable_index_of_object_method<'tcx, N>( .iter() .copied() .position(|def_id| def_id == method_def_id) - .map(|index| object.vtable_base + index) + .map(|index| vtable_base + index) } pub fn closure_trait_ref_and_return_type<'tcx>( diff --git a/compiler/rustc_trait_selection/src/traits/vtable.rs b/compiler/rustc_trait_selection/src/traits/vtable.rs index b4f614e3e220..c4cc89aa9077 100644 --- a/compiler/rustc_trait_selection/src/traits/vtable.rs +++ b/compiler/rustc_trait_selection/src/traits/vtable.rs @@ -5,6 +5,7 @@ use rustc_hir::lang_items::LangItem; use rustc_infer::traits::util::PredicateSet; use rustc_infer::traits::ImplSource; use rustc_middle::query::Providers; +use rustc_middle::traits::BuiltinImplSource; use rustc_middle::ty::visit::TypeVisitableExt; use rustc_middle::ty::GenericArgs; use rustc_middle::ty::{self, GenericParamDefKind, ToPredicate, Ty, TyCtxt, VtblEntry}; @@ -384,8 +385,8 @@ pub(crate) fn vtable_trait_upcasting_coercion_new_vptr_slot<'tcx>( let trait_ref = ty::TraitRef::new(tcx, unsize_trait_did, [source, target]); match tcx.codegen_select_candidate((ty::ParamEnv::reveal_all(), trait_ref)) { - Ok(ImplSource::TraitUpcasting(implsrc_traitcasting)) => { - implsrc_traitcasting.vtable_vptr_slot + Ok(ImplSource::Builtin(BuiltinImplSource::TraitUpcasting { vtable_vptr_slot }, _)) => { + *vtable_vptr_slot } otherwise => bug!("expected TraitUpcasting candidate, got {otherwise:?}"), } diff --git a/compiler/rustc_ty_utils/src/implied_bounds.rs b/compiler/rustc_ty_utils/src/implied_bounds.rs index be063a097c02..fa1976510cf2 100644 --- a/compiler/rustc_ty_utils/src/implied_bounds.rs +++ b/compiler/rustc_ty_utils/src/implied_bounds.rs @@ -51,7 +51,7 @@ fn assumed_wf_types<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> &'tcx [(Ty<' // assumed_wf_types should include those of `Opaque`, `Opaque` itself // and `&'static T`. DefKind::OpaqueTy => bug!("unimplemented implied bounds for nested opaque types"), - def_kind @ _ => { + def_kind => { bug!("unimplemented implied bounds for opaque types with parent {def_kind:?}") } }, diff --git a/compiler/rustc_ty_utils/src/instance.rs b/compiler/rustc_ty_utils/src/instance.rs index 16b1836ba9fa..a21b5ef05e60 100644 --- a/compiler/rustc_ty_utils/src/instance.rs +++ b/compiler/rustc_ty_utils/src/instance.rs @@ -2,7 +2,7 @@ use rustc_errors::ErrorGuaranteed; use rustc_hir::def_id::DefId; use rustc_infer::infer::TyCtxtInferExt; use rustc_middle::query::Providers; -use rustc_middle::traits::CodegenObligationError; +use rustc_middle::traits::{BuiltinImplSource, CodegenObligationError}; use rustc_middle::ty::GenericArgsRef; use rustc_middle::ty::{self, Instance, TyCtxt, TypeVisitableExt}; use rustc_span::sym; @@ -177,12 +177,15 @@ fn resolve_associated_item<'tcx>( Some(ty::Instance::new(leaf_def.item.def_id, args)) } - traits::ImplSource::Object(ref data) => { - traits::get_vtable_index_of_object_method(tcx, data, trait_item_id).map(|index| { - Instance { def: ty::InstanceDef::Virtual(trait_item_id, index), args: rcvr_args } - }) + traits::ImplSource::Builtin(BuiltinImplSource::Object { vtable_base }, _) => { + traits::get_vtable_index_of_object_method(tcx, *vtable_base, trait_item_id).map( + |index| Instance { + def: ty::InstanceDef::Virtual(trait_item_id, index), + args: rcvr_args, + }, + ) } - traits::ImplSource::Builtin(..) => { + traits::ImplSource::Builtin(BuiltinImplSource::Misc, _) => { let lang_items = tcx.lang_items(); if Some(trait_ref.def_id) == lang_items.clone_trait() { // FIXME(eddyb) use lang items for methods instead of names. @@ -290,7 +293,9 @@ fn resolve_associated_item<'tcx>( None } } - traits::ImplSource::Param(..) | traits::ImplSource::TraitUpcasting(_) => None, + traits::ImplSource::Param(..) + | traits::ImplSource::Builtin(BuiltinImplSource::TraitUpcasting { .. }, _) + | traits::ImplSource::Builtin(BuiltinImplSource::TupleUnsizing, _) => None, }) } diff --git a/library/alloc/src/alloc.rs b/library/alloc/src/alloc.rs index c8751ba49117..5205ed9fb50a 100644 --- a/library/alloc/src/alloc.rs +++ b/library/alloc/src/alloc.rs @@ -392,7 +392,6 @@ pub mod __alloc_error_handler { static __rust_alloc_error_handler_should_panic: u8; } - #[allow(unused_unsafe)] if unsafe { __rust_alloc_error_handler_should_panic != 0 } { panic!("memory allocation of {size} bytes failed") } else { diff --git a/library/alloc/src/string.rs b/library/alloc/src/string.rs index 0019f51b3d70..9254786d1295 100644 --- a/library/alloc/src/string.rs +++ b/library/alloc/src/string.rs @@ -2527,6 +2527,7 @@ impl ToString for T { } } +#[doc(hidden)] #[cfg(not(no_global_oom_handling))] #[unstable(feature = "ascii_char", issue = "110998")] impl ToString for core::ascii::Char { @@ -2536,6 +2537,7 @@ impl ToString for core::ascii::Char { } } +#[doc(hidden)] #[cfg(not(no_global_oom_handling))] #[stable(feature = "char_to_string_specialization", since = "1.46.0")] impl ToString for char { @@ -2545,6 +2547,7 @@ impl ToString for char { } } +#[doc(hidden)] #[cfg(not(no_global_oom_handling))] #[stable(feature = "bool_to_string_specialization", since = "1.68.0")] impl ToString for bool { @@ -2554,6 +2557,7 @@ impl ToString for bool { } } +#[doc(hidden)] #[cfg(not(no_global_oom_handling))] #[stable(feature = "u8_to_string_specialization", since = "1.54.0")] impl ToString for u8 { @@ -2574,6 +2578,7 @@ impl ToString for u8 { } } +#[doc(hidden)] #[cfg(not(no_global_oom_handling))] #[stable(feature = "i8_to_string_specialization", since = "1.54.0")] impl ToString for i8 { @@ -2597,6 +2602,7 @@ impl ToString for i8 { } } +#[doc(hidden)] #[cfg(not(no_global_oom_handling))] #[stable(feature = "str_to_string_specialization", since = "1.9.0")] impl ToString for str { @@ -2606,6 +2612,7 @@ impl ToString for str { } } +#[doc(hidden)] #[cfg(not(no_global_oom_handling))] #[stable(feature = "cow_str_to_string_specialization", since = "1.17.0")] impl ToString for Cow<'_, str> { @@ -2615,6 +2622,7 @@ impl ToString for Cow<'_, str> { } } +#[doc(hidden)] #[cfg(not(no_global_oom_handling))] #[stable(feature = "string_to_string_specialization", since = "1.17.0")] impl ToString for String { @@ -2624,6 +2632,7 @@ impl ToString for String { } } +#[doc(hidden)] #[cfg(not(no_global_oom_handling))] #[stable(feature = "fmt_arguments_to_string_specialization", since = "1.71.0")] impl ToString for fmt::Arguments<'_> { diff --git a/library/core/src/intrinsics.rs b/library/core/src/intrinsics.rs index deef68e4699c..d042aaf3084d 100644 --- a/library/core/src/intrinsics.rs +++ b/library/core/src/intrinsics.rs @@ -2524,12 +2524,14 @@ pub(crate) use assert_unsafe_precondition; /// Checks whether `ptr` is properly aligned with respect to /// `align_of::()`. +#[inline] pub(crate) fn is_aligned_and_not_null(ptr: *const T) -> bool { !ptr.is_null() && ptr.is_aligned() } /// Checks whether an allocation of `len` instances of `T` exceeds /// the maximum allowed allocation size. +#[inline] pub(crate) fn is_valid_allocation_size(len: usize) -> bool { let max_len = const { let size = crate::mem::size_of::(); @@ -2540,6 +2542,7 @@ pub(crate) fn is_valid_allocation_size(len: usize) -> bool { /// Checks whether the regions of memory starting at `src` and `dst` of size /// `count * size_of::()` do *not* overlap. +#[inline] pub(crate) fn is_nonoverlapping(src: *const T, dst: *const T, count: usize) -> bool { let src_usize = src.addr(); let dst_usize = dst.addr(); diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index 9510e9efcdc3..741de3221ee8 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -418,7 +418,7 @@ pub mod arch; // set up in such a way that directly pulling it here works such that the // crate uses this crate as its core. #[path = "../../portable-simd/crates/core_simd/src/mod.rs"] -#[allow(missing_debug_implementations, dead_code, unsafe_op_in_unsafe_fn, unused_unsafe)] +#[allow(missing_debug_implementations, dead_code, unsafe_op_in_unsafe_fn)] #[allow(rustdoc::bare_urls)] #[unstable(feature = "portable_simd", issue = "86656")] mod core_simd; diff --git a/library/proc_macro/src/lib.rs b/library/proc_macro/src/lib.rs index 7fb0d989cdba..2c0d113dbc58 100644 --- a/library/proc_macro/src/lib.rs +++ b/library/proc_macro/src/lib.rs @@ -177,6 +177,7 @@ impl FromStr for TokenStream { // N.B., the bridge only provides `to_string`, implement `fmt::Display` // based on it (the reverse of the usual relationship between the two). +#[doc(hidden)] #[stable(feature = "proc_macro_lib", since = "1.15.0")] impl ToString for TokenStream { fn to_string(&self) -> String { @@ -738,6 +739,7 @@ impl From for TokenTree { // N.B., the bridge only provides `to_string`, implement `fmt::Display` // based on it (the reverse of the usual relationship between the two). +#[doc(hidden)] #[stable(feature = "proc_macro_lib", since = "1.15.0")] impl ToString for TokenTree { fn to_string(&self) -> String { @@ -872,6 +874,7 @@ impl Group { // N.B., the bridge only provides `to_string`, implement `fmt::Display` // based on it (the reverse of the usual relationship between the two). +#[doc(hidden)] #[stable(feature = "proc_macro_lib", since = "1.15.0")] impl ToString for Group { fn to_string(&self) -> String { @@ -981,6 +984,7 @@ impl Punct { } } +#[doc(hidden)] #[stable(feature = "proc_macro_lib2", since = "1.29.0")] impl ToString for Punct { fn to_string(&self) -> String { @@ -1083,8 +1087,7 @@ impl Ident { } } -/// Converts the identifier to a string that should be losslessly convertible -/// back into the same identifier. +#[doc(hidden)] #[stable(feature = "proc_macro_lib2", since = "1.29.0")] impl ToString for Ident { fn to_string(&self) -> String { @@ -1423,6 +1426,7 @@ impl FromStr for Literal { } } +#[doc(hidden)] #[stable(feature = "proc_macro_lib2", since = "1.29.0")] impl ToString for Literal { fn to_string(&self) -> String { diff --git a/library/std/Cargo.toml b/library/std/Cargo.toml index c129a753912f..c47f910dadfa 100644 --- a/library/std/Cargo.toml +++ b/library/std/Cargo.toml @@ -18,7 +18,7 @@ panic_unwind = { path = "../panic_unwind", optional = true } panic_abort = { path = "../panic_abort" } core = { path = "../core", public = true } libc = { version = "0.2.146", default-features = false, features = ['rustc-dep-of-std'], public = true } -compiler_builtins = { version = "0.1.95" } +compiler_builtins = { version = "0.1.98" } profiler_builtins = { path = "../profiler_builtins", optional = true } unwind = { path = "../unwind" } hashbrown = { version = "0.14", default-features = false, features = ['rustc-dep-of-std'] } diff --git a/library/std/src/alloc.rs b/library/std/src/alloc.rs index ec774e62debb..1eae7fa6a954 100644 --- a/library/std/src/alloc.rs +++ b/library/std/src/alloc.rs @@ -336,7 +336,6 @@ fn default_alloc_error_hook(layout: Layout) { static __rust_alloc_error_handler_should_panic: u8; } - #[allow(unused_unsafe)] if unsafe { __rust_alloc_error_handler_should_panic != 0 } { panic!("memory allocation of {} bytes failed", layout.size()); } else { diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index 5bf66850f03d..4cd251d0ac26 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -542,7 +542,7 @@ pub mod time; // Pull in `std_float` crate into std. The contents of // `std_float` are in a different repository: rust-lang/portable-simd. #[path = "../../portable-simd/crates/std_float/src/lib.rs"] -#[allow(missing_debug_implementations, dead_code, unsafe_op_in_unsafe_fn, unused_unsafe)] +#[allow(missing_debug_implementations, dead_code, unsafe_op_in_unsafe_fn)] #[allow(rustdoc::bare_urls)] #[unstable(feature = "portable_simd", issue = "86656")] mod std_float; diff --git a/library/std/src/sync/lazy_lock.rs b/library/std/src/sync/lazy_lock.rs index a6bc468b0928..37bdec5abcc7 100644 --- a/library/std/src/sync/lazy_lock.rs +++ b/library/std/src/sync/lazy_lock.rs @@ -25,6 +25,8 @@ union Data { /// /// # Examples /// +/// Initialize static variables with `LazyLock`. +/// /// ``` /// #![feature(lazy_cell)] /// @@ -54,6 +56,24 @@ union Data { /// // Some("Hoyten") /// } /// ``` +/// Initialize fields with `LazyLock`. +/// ``` +/// #![feature(lazy_cell)] +/// +/// use std::sync::LazyLock; +/// +/// #[derive(Debug)] +/// struct UseCellLock { +/// number: LazyLock, +/// } +/// fn main() { +/// let lock: LazyLock = LazyLock::new(|| 0u32); +/// +/// let data = UseCellLock { number: lock }; +/// println!("{}", *data.number); +/// } +/// ``` + #[unstable(feature = "lazy_cell", issue = "109736")] pub struct LazyLock T> { once: Once, diff --git a/library/std/src/sys/common/thread_local/fast_local.rs b/library/std/src/sys/common/thread_local/fast_local.rs index bc5da1a18967..c0a9619bf7bf 100644 --- a/library/std/src/sys/common/thread_local/fast_local.rs +++ b/library/std/src/sys/common/thread_local/fast_local.rs @@ -87,10 +87,6 @@ pub macro thread_local_inner { static __KEY: $crate::thread::local_impl::Key<$t> = $crate::thread::local_impl::Key::<$t>::new(); - // FIXME: remove the #[allow(...)] marker when macros don't - // raise warning for missing/extraneous unsafe blocks anymore. - // See https://github.com/rust-lang/rust/issues/74838. - #[allow(unused_unsafe)] unsafe { __KEY.get(move || { if let $crate::option::Option::Some(init) = init { diff --git a/library/std/src/sys/common/thread_local/os_local.rs b/library/std/src/sys/common/thread_local/os_local.rs index 5d48ce1e03bc..7cf291921228 100644 --- a/library/std/src/sys/common/thread_local/os_local.rs +++ b/library/std/src/sys/common/thread_local/os_local.rs @@ -24,7 +24,6 @@ pub macro thread_local_inner { const fn __init() -> $t { INIT_EXPR } static __KEY: $crate::thread::local_impl::Key<$t> = $crate::thread::local_impl::Key::new(); - #[allow(unused_unsafe)] unsafe { __KEY.get(move || { if let $crate::option::Option::Some(init) = _init { @@ -59,10 +58,6 @@ pub macro thread_local_inner { static __KEY: $crate::thread::local_impl::Key<$t> = $crate::thread::local_impl::Key::new(); - // FIXME: remove the #[allow(...)] marker when macros don't - // raise warning for missing/extraneous unsafe blocks anymore. - // See https://github.com/rust-lang/rust/issues/74838. - #[allow(unused_unsafe)] unsafe { __KEY.get(move || { if let $crate::option::Option::Some(init) = init { diff --git a/library/std/src/sys/common/thread_local/static_local.rs b/library/std/src/sys/common/thread_local/static_local.rs index 80322a978646..5cb6c541a0ec 100644 --- a/library/std/src/sys/common/thread_local/static_local.rs +++ b/library/std/src/sys/common/thread_local/static_local.rs @@ -43,10 +43,6 @@ pub macro thread_local_inner { static __KEY: $crate::thread::local_impl::Key<$t> = $crate::thread::local_impl::Key::new(); - // FIXME: remove the #[allow(...)] marker when macros don't - // raise warning for missing/extraneous unsafe blocks anymore. - // See https://github.com/rust-lang/rust/issues/74838. - #[allow(unused_unsafe)] unsafe { __KEY.get(move || { if let $crate::option::Option::Some(init) = init { diff --git a/library/std/src/sys/sgx/thread.rs b/library/std/src/sys/sgx/thread.rs index 1608b8cb642d..7ac9d1d64b42 100644 --- a/library/std/src/sys/sgx/thread.rs +++ b/library/std/src/sys/sgx/thread.rs @@ -121,8 +121,16 @@ impl Thread { rtassert!(wait_error.kind() == io::ErrorKind::WouldBlock); } + /// SGX should protect in-enclave data from the outside (attacker), + /// so there should be no data leakage to the OS, + /// and therefore also no 1-1 mapping between SGX thread names and OS thread names. + /// + /// This is why the method is intentionally No-Op. pub fn set_name(_name: &CStr) { - // FIXME: could store this pointer in TLS somewhere + // Note that the internally visible SGX thread name is already provided + // by the platform-agnostic (target-agnostic) Rust thread code. + // This can be observed in the [`std::thread::tests::test_named_thread`] test, + // which succeeds as-is with the SGX target. } pub fn sleep(dur: Duration) { diff --git a/library/std/src/sys/unix/mod.rs b/library/std/src/sys/unix/mod.rs index 326f1481e191..77ef086f29b5 100644 --- a/library/std/src/sys/unix/mod.rs +++ b/library/std/src/sys/unix/mod.rs @@ -110,6 +110,11 @@ pub unsafe fn init(argc: isize, argv: *const *const u8, sigpipe: u8) { while libc::poll(pfds.as_mut_ptr(), 3, 0) == -1 { match errno() { libc::EINTR => continue, + #[cfg(target_vendor = "unikraft")] + libc::ENOSYS => { + // Not all configurations of Unikraft enable `LIBPOSIX_EVENT`. + break 'poll; + } libc::EINVAL | libc::EAGAIN | libc::ENOMEM => { // RLIMIT_NOFILE or temporary allocation failures // may be preventing use of poll(), fall back to fcntl @@ -165,7 +170,14 @@ pub unsafe fn init(argc: isize, argv: *const *const u8, sigpipe: u8) { } unsafe fn reset_sigpipe(#[allow(unused_variables)] sigpipe: u8) { - #[cfg(not(any(target_os = "emscripten", target_os = "fuchsia", target_os = "horizon")))] + #[cfg(not(any( + target_os = "emscripten", + target_os = "fuchsia", + target_os = "horizon", + // Unikraft's `signal` implementation is currently broken: + // https://github.com/unikraft/lib-musl/issues/57 + target_vendor = "unikraft", + )))] { // We don't want to add this as a public type to std, nor do we // want to `include!` a file from the compiler (which would break diff --git a/library/std/src/sys/windows/compat.rs b/library/std/src/sys/windows/compat.rs index 4fe95d41116b..e28dd4935367 100644 --- a/library/std/src/sys/windows/compat.rs +++ b/library/std/src/sys/windows/compat.rs @@ -69,10 +69,7 @@ unsafe extern "C" fn init() { /// Helper macro for creating CStrs from literals and symbol names. macro_rules! ansi_str { - (sym $ident:ident) => {{ - #[allow(unused_unsafe)] - crate::sys::compat::const_cstr_from_bytes(concat!(stringify!($ident), "\0").as_bytes()) - }}; + (sym $ident:ident) => {{ crate::sys::compat::const_cstr_from_bytes(concat!(stringify!($ident), "\0").as_bytes()) }}; ($lit:literal) => {{ crate::sys::compat::const_cstr_from_bytes(concat!($lit, "\0").as_bytes()) }}; } diff --git a/library/std/src/sys_common/thread_info.rs b/library/std/src/sys_common/thread_info.rs index 38c9e50009af..88d937a7db15 100644 --- a/library/std/src/sys_common/thread_info.rs +++ b/library/std/src/sys_common/thread_info.rs @@ -1,5 +1,4 @@ #![allow(dead_code)] // stack_guard isn't used right now on all platforms -#![allow(unused_unsafe)] // thread_local with `const {}` triggers this liny use crate::cell::RefCell; use crate::sys::thread::guard::Guard; diff --git a/library/test/src/formatters/junit.rs b/library/test/src/formatters/junit.rs index 9f5bf24367ea..a211ebf1ded1 100644 --- a/library/test/src/formatters/junit.rs +++ b/library/test/src/formatters/junit.rs @@ -32,7 +32,7 @@ fn str_to_cdata(s: &str) -> String { let escaped_output = s.replace("]]>", "]]]]>"); let escaped_output = escaped_output.replace(" ", ""); format!("", escaped_output) diff --git a/library/test/src/lib.rs b/library/test/src/lib.rs index b40b6009ea45..0bd447552cf5 100644 --- a/library/test/src/lib.rs +++ b/library/test/src/lib.rs @@ -183,8 +183,7 @@ pub fn test_main_static_abort(tests: &[&TestDescAndFn]) { let test = tests .into_iter() - .filter(|test| test.desc.name.as_slice() == name) - .next() + .find(|test| test.desc.name.as_slice() == name) .unwrap_or_else(|| panic!("couldn't find a test with the provided name '{name}'")); let TestDescAndFn { desc, testfn } = test; match testfn.into_runnable() { diff --git a/src/bootstrap/compile.rs b/src/bootstrap/compile.rs index f3d95b57a76d..400b07b1882c 100644 --- a/src/bootstrap/compile.rs +++ b/src/bootstrap/compile.rs @@ -261,7 +261,7 @@ fn copy_self_contained_objects( // to using gcc from a glibc-targeting toolchain for linking. // To do that we have to distribute musl startup objects as a part of Rust toolchain // and link with them manually in the self-contained mode. - if target.contains("musl") { + if target.contains("musl") && !target.contains("unikraft") { let srcdir = builder.musl_libdir(target).unwrap_or_else(|| { panic!("Target {:?} does not have a \"musl-libdir\" key", target.triple) }); diff --git a/src/bootstrap/dist.rs b/src/bootstrap/dist.rs index 8c71b7f7fc22..c8750c193887 100644 --- a/src/bootstrap/dist.rs +++ b/src/bootstrap/dist.rs @@ -1085,13 +1085,6 @@ impl Step for Cargo { tarball.add_dir(etc.join("man"), "share/man/man1"); tarball.add_legal_and_readme_to("share/doc/cargo"); - for dirent in fs::read_dir(cargo.parent().unwrap()).expect("read_dir") { - let dirent = dirent.expect("read dir entry"); - if dirent.file_name().to_str().expect("utf8").starts_with("cargo-credential-") { - tarball.add_file(&dirent.path(), "libexec", 0o755); - } - } - Some(tarball.generate()) } } diff --git a/src/bootstrap/doc.rs b/src/bootstrap/doc.rs index e58f736d67f5..2ccbf179ccaf 100644 --- a/src/bootstrap/doc.rs +++ b/src/bootstrap/doc.rs @@ -16,7 +16,7 @@ use crate::cache::{Interned, INTERNER}; use crate::compile; use crate::config::{Config, TargetSelection}; use crate::tool::{self, prepare_tool_cargo, SourceType, Tool}; -use crate::util::{symlink_dir, t, up_to_date}; +use crate::util::{dir_is_empty, symlink_dir, t, up_to_date}; use crate::Mode; macro_rules! submodule_helper { @@ -197,11 +197,21 @@ impl Step for TheBook { let compiler = self.compiler; let target = self.target; + let absolute_path = builder.src.join(&relative_path); + let redirect_path = absolute_path.join("redirects"); + if !absolute_path.exists() + || !redirect_path.exists() + || dir_is_empty(&absolute_path) + || dir_is_empty(&redirect_path) + { + eprintln!("Please checkout submodule: {}", relative_path.display()); + crate::exit!(1); + } // build book builder.ensure(RustbookSrc { target, name: INTERNER.intern_str("book"), - src: INTERNER.intern_path(builder.src.join(&relative_path)), + src: INTERNER.intern_path(absolute_path.clone()), parent: Some(self), }); @@ -210,7 +220,7 @@ impl Step for TheBook { builder.ensure(RustbookSrc { target, name: INTERNER.intern_string(format!("book/{}", edition)), - src: INTERNER.intern_path(builder.src.join(&relative_path).join(edition)), + src: INTERNER.intern_path(absolute_path.join(edition)), // There should only be one book that is marked as the parent for each target, so // treat the other editions as not having a parent. parent: Option::::None, @@ -225,7 +235,7 @@ impl Step for TheBook { // build the redirect pages let _guard = builder.msg_doc(compiler, "book redirect pages", target); - for file in t!(fs::read_dir(builder.src.join(&relative_path).join("redirects"))) { + for file in t!(fs::read_dir(redirect_path)) { let file = t!(file); let path = file.path(); let path = path.to_str().unwrap(); @@ -884,19 +894,10 @@ tool_doc!( "-p", "cargo-credential", "-p", - "cargo-credential-1password", - "-p", "mdman", // FIXME: this trips a license check in tidy. // "-p", // "resolver-tests", - // FIXME: we should probably document these, but they're different per-platform so we can't use `tool_doc`. - // "-p", - // "cargo-credential-gnome-secret", - // "-p", - // "cargo-credential-macos-keychain", - // "-p", - // "cargo-credential-wincred", ] ); tool_doc!(Tidy, "tidy", "src/tools/tidy", rustc_tool = false, ["-p", "tidy"]); diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs index 059eb9ffc7bc..365deb8e155d 100644 --- a/src/bootstrap/lib.rs +++ b/src/bootstrap/lib.rs @@ -36,7 +36,7 @@ use once_cell::sync::OnceCell; use crate::builder::Kind; use crate::config::{LlvmLibunwind, TargetSelection}; use crate::util::{ - exe, libdir, mtime, output, run, run_suppressed, symlink_dir, try_run_suppressed, + dir_is_empty, exe, libdir, mtime, output, run, run_suppressed, symlink_dir, try_run_suppressed, }; mod bolt; @@ -131,6 +131,8 @@ const EXTRA_CHECK_CFGS: &[(Option, &'static str, Option<&[&'static str]>)] (Some(Mode::Std), "freebsd13", None), (Some(Mode::Std), "backtrace_in_libstd", None), /* Extra values not defined in the built-in targets yet, but used in std */ + // #[cfg(bootstrap)] + (Some(Mode::Std), "target_vendor", Some(&["unikraft"])), (Some(Mode::Std), "target_env", Some(&["libnx"])), // (Some(Mode::Std), "target_os", Some(&[])), // #[cfg(bootstrap)] mips32r6, mips64r6 @@ -535,10 +537,6 @@ impl Build { /// /// `relative_path` should be relative to the root of the git repository, not an absolute path. pub(crate) fn update_submodule(&self, relative_path: &Path) { - fn dir_is_empty(dir: &Path) -> bool { - t!(std::fs::read_dir(dir)).next().is_none() - } - if !self.config.submodules(&self.rust_info()) { return; } diff --git a/src/bootstrap/sanity.rs b/src/bootstrap/sanity.rs index 9321fc1bcb8b..145ae6f44da3 100644 --- a/src/bootstrap/sanity.rs +++ b/src/bootstrap/sanity.rs @@ -206,7 +206,7 @@ than building it. } // Make sure musl-root is valid - if target.contains("musl") { + if target.contains("musl") && !target.contains("unikraft") { // If this is a native target (host is also musl) and no musl-root is given, // fall back to the system toolchain in /usr before giving up if build.musl_root(*target).is_none() && build.config.build == *target { diff --git a/src/bootstrap/tool.rs b/src/bootstrap/tool.rs index 725f864b718c..e6d27757ac66 100644 --- a/src/bootstrap/tool.rs +++ b/src/bootstrap/tool.rs @@ -558,39 +558,6 @@ impl Step for Cargo { allow_features: "", }) .expect("expected to build -- essential tool"); - - let build_cred = |name, path| { - // These credential helpers are currently experimental. - // Any build failures will be ignored. - let _ = builder.ensure(ToolBuild { - compiler: self.compiler, - target: self.target, - tool: name, - mode: Mode::ToolRustc, - path, - is_optional_tool: true, - source_type: SourceType::Submodule, - extra_features: Vec::new(), - allow_features: "", - }); - }; - - if self.target.contains("windows") { - build_cred( - "cargo-credential-wincred", - "src/tools/cargo/credential/cargo-credential-wincred", - ); - } - if self.target.contains("apple-darwin") { - build_cred( - "cargo-credential-macos-keychain", - "src/tools/cargo/credential/cargo-credential-macos-keychain", - ); - } - build_cred( - "cargo-credential-1password", - "src/tools/cargo/credential/cargo-credential-1password", - ); cargo_bin_path } } diff --git a/src/bootstrap/util.rs b/src/bootstrap/util.rs index 2725813aba3a..84ed29854647 100644 --- a/src/bootstrap/util.rs +++ b/src/bootstrap/util.rs @@ -493,3 +493,7 @@ pub fn lld_flag_no_threads(is_windows: bool) -> &'static str { }); if is_windows { windows } else { other } } + +pub fn dir_is_empty(dir: &Path) -> bool { + t!(std::fs::read_dir(dir)).next().is_none() +} diff --git a/src/doc/rustc/src/SUMMARY.md b/src/doc/rustc/src/SUMMARY.md index 96ee9a586dee..f108831138d8 100644 --- a/src/doc/rustc/src/SUMMARY.md +++ b/src/doc/rustc/src/SUMMARY.md @@ -42,6 +42,8 @@ - [sparc-unknown-none-elf](./platform-support/sparc-unknown-none-elf.md) - [*-pc-windows-gnullvm](platform-support/pc-windows-gnullvm.md) - [\*-nto-qnx-\*](platform-support/nto-qnx.md) + - [*-unikraft-linux-musl](platform-support/unikraft-linux-musl.md) + - [*-unknown-hermit](platform-support/hermit.md) - [\*-unknown-netbsd\*](platform-support/netbsd.md) - [*-unknown-openbsd](platform-support/openbsd.md) - [\*-unknown-uefi](platform-support/unknown-uefi.md) diff --git a/src/doc/rustc/src/platform-support.md b/src/doc/rustc/src/platform-support.md index 351b03b9337b..8c5dc11eeef3 100644 --- a/src/doc/rustc/src/platform-support.md +++ b/src/doc/rustc/src/platform-support.md @@ -223,7 +223,7 @@ target | std | host | notes [`aarch64-unknown-linux-ohos`](platform-support/openharmony.md) | ✓ | | ARM64 OpenHarmony | [`aarch64-unknown-nto-qnx710`](platform-support/nto-qnx.md) | ✓ | | ARM64 QNX Neutrino 7.1 RTOS | `aarch64-unknown-freebsd` | ✓ | ✓ | ARM64 FreeBSD -`aarch64-unknown-hermit` | ✓ | | ARM64 HermitCore +[`aarch64-unknown-hermit`](platform-support/hermit.md) | ✓ | | ARM64 Hermit `aarch64-unknown-linux-gnu_ilp32` | ✓ | ✓ | ARM64 Linux (ILP32 ABI) [`aarch64-unknown-netbsd`](platform-support/netbsd.md) | ✓ | ✓ | ARM64 NetBSD [`aarch64-unknown-openbsd`](platform-support/openbsd.md) | ✓ | ✓ | ARM64 OpenBSD @@ -303,6 +303,7 @@ target | std | host | notes [`riscv32imac-unknown-xous-elf`](platform-support/riscv32imac-unknown-xous-elf.md) | ? | | RISC-V Xous (RV32IMAC ISA) [`riscv32imc-esp-espidf`](platform-support/esp-idf.md) | ✓ | | RISC-V ESP-IDF [`riscv32imac-esp-espidf`](platform-support/esp-idf.md) | ✓ | | RISC-V ESP-IDF +[`riscv64gc-unknown-hermit`](platform-support/hermit.md) | ✓ | | RISC-V Hermit `riscv64gc-unknown-freebsd` | | | RISC-V FreeBSD `riscv64gc-unknown-fuchsia` | | | RISC-V Fuchsia `riscv64gc-unknown-linux-musl` | | | RISC-V Linux (kernel 4.20, musl 1.2.0) @@ -325,9 +326,10 @@ target | std | host | notes [`x86_64-pc-windows-gnullvm`](platform-support/pc-windows-gnullvm.md) | ✓ | ✓ | `x86_64-pc-windows-msvc` | * | | 64-bit Windows XP support `x86_64-sun-solaris` | ? | | Deprecated target for 64-bit Solaris 10/11, illumos +[`x86_64-unikraft-linux-musl`](platform-support/unikraft-linux-musl.md) | ✓ | | 64-bit Unikraft with musl `x86_64-unknown-dragonfly` | ✓ | ✓ | 64-bit DragonFlyBSD `x86_64-unknown-haiku` | ✓ | ✓ | 64-bit Haiku -`x86_64-unknown-hermit` | ✓ | | HermitCore +[`x86_64-unknown-hermit`](platform-support/hermit.md) | ✓ | | x86_64 Hermit `x86_64-unknown-l4re-uclibc` | ? | | [`x86_64-unknown-linux-ohos`](platform-support/openharmony.md) | ✓ | | x86_64 OpenHarmony | [`x86_64-unknown-openbsd`](platform-support/openbsd.md) | ✓ | ✓ | 64-bit OpenBSD diff --git a/src/doc/rustc/src/platform-support/hermit.md b/src/doc/rustc/src/platform-support/hermit.md new file mode 100644 index 000000000000..146079e36f44 --- /dev/null +++ b/src/doc/rustc/src/platform-support/hermit.md @@ -0,0 +1,75 @@ +# `*-unknown-hermit` + +**Tier: 3** + +The [Hermit] unikernel target allows compiling your applications into self-contained, specialized unikernel images that can be run in small virtual machines. + +[Hermit]: https://github.com/hermitcore + +Target triplets available so far: + +- `x86_64-unknown-hermit` +- `aarch64-unknown-hermit` +- `riscv64gc-unknown-hermit` + +## Target maintainers + +- Stefan Lankes ([@stlankes](https://github.com/stlankes)) +- Martin Kröning ([@mkroening](https://github.com/mkroening)) + +## Requirements + +These targets only support cross-compilation. +The targets do support std. + +When building binaries for this target, the Hermit unikernel is built from scratch. +The application developer themselves specializes the target and sets corresponding expectations. + +The Hermit targets follow Linux's `extern "C"` calling convention. + +Hermit binaries have the ELF format. + +## Building the target + +You can build Rust with support for the targets by adding it to the `target` list in `config.toml`. +To run the Hermit build scripts, you also have to enable your host target. +The build scripts rely on `llvm-tools` and binaries are linked using `rust-lld`, so those have to be enabled as well. + +```toml +[build] +build-stage = 1 +target = [ + "", + "x86_64-unknown-hermit", + "aarch64-unknown-hermit", + "riscv64gc-unknown-hermit", +] + +[rust] +lld = true +llvm-tools = true +``` + +## Building Rust programs + +Rust does not yet ship pre-compiled artifacts for these targets. +To compile for these targets, you will either need to build Rust with the targets enabled +(see “Building the targets” above), or build your own copy of `core` by using `build-std` or similar. + +Building Rust programs can be done by following the tutorial in our starter application [rusty-demo]. + +[rusty-demo]: https://github.com/hermitcore/rusty-demo + +## Testing + +The targets support running binaries in the form of self-contained unikernel images. +These images can be chainloaded by Hermit's [loader] or hypervisor ([Uhyve]). +QEMU can be used to boot Hermit binaries using the loader on any architecture. +The targets do not support running the Rust test suite. + +[loader]: https://github.com/hermitcore/rusty-loader +[Uhyve]: https://github.com/hermitcore/uhyve + +## Cross-compilation toolchains and C code + +The targets do not yet support C code and Rust code at the same time. diff --git a/src/doc/rustc/src/platform-support/sparc-unknown-none-elf.md b/src/doc/rustc/src/platform-support/sparc-unknown-none-elf.md index efd58e8302fd..f579b1fb8d48 100644 --- a/src/doc/rustc/src/platform-support/sparc-unknown-none-elf.md +++ b/src/doc/rustc/src/platform-support/sparc-unknown-none-elf.md @@ -17,13 +17,6 @@ Rust for bare-metal 32-bit SPARC V7 and V8 systems, e.g. the Gaisler LEON3. This target is cross-compiled. There is no support for `std`. There is no default allocator, but it's possible to use `alloc` by supplying an allocator. -This allows the generated code to run in environments, such as kernels, which -may need to avoid the use of such registers or which may have special -considerations about the use of such registers (e.g. saving and restoring them -to avoid breaking userspace code using the same registers). You can change code -generation to use additional CPU features via the `-C target-feature=` codegen -options to rustc, or via the `#[target_feature]` mechanism within Rust code. - By default, code generated with this target should run on any `SPARC` hardware; enabling additional target features may raise this baseline. @@ -46,20 +39,31 @@ list in `config.toml`: ```toml [build] build-stage = 1 -target = ["sparc-unknown-none-elf"] +host = [""] +target = ["", "sparc-unknown-none-elf"] ``` +Replace `` with `x86_64-unknown-linux-gnu` or whatever +else is appropriate for your host machine. + ## Building Rust programs -```text +To build with this target, pass it to the `--target` argument, like: + +```console cargo build --target sparc-unknown-none-elf ``` This target uses GCC as a linker, and so you will need an appropriate GCC -compatible `sparc-unknown-none` toolchain. +compatible `sparc-unknown-none` toolchain. The default linker binary is +`sparc-elf-gcc`, but you can override this in your project configuration, as +follows: -The default linker name is `sparc-elf-gcc`, but you can override this in your -project configuration. +`.cargo/config.toml`: +```toml +[target.sparc-unknown-none-elf] +linker = "sparc-custom-elf-gcc" +``` ## Testing @@ -81,6 +85,26 @@ something like: linker = "sparc-gaisler-elf-gcc" runner = "tsim-leon3" +[build] +target = ["sparc-unknown-none-elf"] +rustflags = "-Ctarget-cpu=leon3" +``` + +With this configuration, running `cargo run` will compile your code for the +SPARC V8 compatible Gaisler Leon3 processor and then start the `tsim-leon3` +simulator. The `libcore` was pre-compiled as part of the `rustc` compilation +process using the SPARC V7 baseline, but if you are using a nightly toolchain +you can use the +[`-Z build-std=core`](https://doc.rust-lang.org/cargo/reference/unstable.html#build-std) +option to rebuild `libcore` from source. This may be useful if you want to +compile it for SPARC V8 and take advantage of the extra instructions. + +`.cargo/config.toml`: +```toml +[target.sparc-unknown-none-elf] +linker = "sparc-gaisler-elf-gcc" +runner = "tsim-leon3" + [build] target = ["sparc-unknown-none-elf"] rustflags = "-Ctarget-cpu=leon3" @@ -89,16 +113,16 @@ rustflags = "-Ctarget-cpu=leon3" build-std = ["core"] ``` -With this configuration, running `cargo run` will compile your code for the -SPARC V8 compatible Gaisler Leon3 processor and then start the `tsim-leon3` -simulator. Once the simulator is running, simply enter the command -`run` to start the code executing in the simulator. +Either way, once the simulator is running, simply enter the command `run` to +start the code executing in the simulator. The default C toolchain libraries are linked in, so with the Gaisler [BCC2] toolchain, and using its default Leon3 BSP, you can use call the C `putchar` -function and friends to output to the simulator console. +function and friends to output to the simulator console. The default linker +script is also appropriate for the Leon3 simulator, so no linker script is +required. -Here's a complete example: +Here's a complete example using the above config file: ```rust,ignore (cannot-test-this-because-it-assumes-special-libc-functions) #![no_std] diff --git a/src/doc/rustc/src/platform-support/unikraft-linux-musl.md b/src/doc/rustc/src/platform-support/unikraft-linux-musl.md new file mode 100644 index 000000000000..90fa18b98578 --- /dev/null +++ b/src/doc/rustc/src/platform-support/unikraft-linux-musl.md @@ -0,0 +1,67 @@ +# `*-unikraft-linux-musl` + +**Tier: 3** + +Targets for the [Unikraft] Unikernel Development Kit (with musl). + +[Unikraft]: https://unikraft.org/ + +Target triplets available so far: + +- `x86_64-unikraft-linux-musl` + +## Target maintainers + +- Martin Kröning ([@mkroening](https://github.com/mkroening)) + +## Requirements + +These targets only support cross-compilation. +The targets do support std. + +Unikraft pretends to behave exactly like Linux. +How much of that functionality is available depends on the individual unikernel configuration. +For example, the basic Unikraft + musl config does not support `poll` or networking out of the box. +That functionality requires enabling [`LIBPOSIX_EVENT`] or [lwIP] respectively. + +[`LIBPOSIX_EVENT`]: https://github.com/unikraft/unikraft/blob/RELEASE-0.13.1/lib/posix-event/Config.uk +[lwIP]: https://github.com/unikraft/lib-lwip + +The Unikraft targets follow Linux's `extern "C"` calling convention. + +For these targets, `rustc` does not perform the final linking step. +Instead, the Unikraft build system will produce the final Unikernel image for the selected platform (e.g., KVM, Linux user space, and Xen). + +## Building the targets + +You can build Rust with support for the targets by adding it to the `target` list in `config.toml`: + +```toml +[build] +build-stage = 1 +target = [ "x86_64-unikraft-linux-musl" ] +``` + +## Building Rust programs + +Rust does not yet ship pre-compiled artifacts for these targets. +To compile for these targets, you will either need to build Rust with the targets enabled +(see “Building the targets” above), or build your own copy of `core` by using `build-std` or similar. + +Linking requires a [KraftKit] shim. +See [unikraft/kraftkit#612] for more information. + +[KraftKit]: https://github.com/unikraft/kraftkit +[unikraft/kraftkit#612]: https://github.com/unikraft/kraftkit/issues/612 + +## Testing + +The targets do support running binaries in the form of unikernel images. +How the unikernel image is run depends on the specific platform (e.g., KVM, Linux user space, and Xen). +The targets do not support running the Rust test suite. + +## Cross-compilation toolchains and C code + +The targets do support C code. +To build compatible C code, you have to use the same compiler and flags as does the Unikraft build system for your specific configuration. +The easiest way to achieve that, is to build the C code with the Unikraft build system when building your unikernel image. diff --git a/src/librustdoc/clean/blanket_impl.rs b/src/librustdoc/clean/blanket_impl.rs index f5e02940c82e..9d744237b577 100644 --- a/src/librustdoc/clean/blanket_impl.rs +++ b/src/librustdoc/clean/blanket_impl.rs @@ -121,7 +121,8 @@ impl<'a, 'tcx> BlanketImplFinder<'a, 'tcx> { .tcx .associated_items(impl_def_id) .in_definition_order() - .map(|x| clean_middle_assoc_item(x, cx)) + .filter(|item| !item.is_impl_trait_in_trait()) + .map(|item| clean_middle_assoc_item(item, cx)) .collect::>(), polarity: ty::ImplPolarity::Positive, kind: ImplKind::Blanket(Box::new(clean_middle_ty( diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index cfd9875e1c8f..89eaf561e6a5 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -216,6 +216,7 @@ pub(crate) fn build_external_trait(cx: &mut DocContext<'_>, did: DefId) -> clean .tcx .associated_items(did) .in_definition_order() + .filter(|item| !item.is_impl_trait_in_trait()) .map(|item| clean_middle_assoc_item(item, cx)) .collect(); @@ -459,6 +460,7 @@ pub(crate) fn build_impl( None => ( tcx.associated_items(did) .in_definition_order() + .filter(|item| !item.is_impl_trait_in_trait()) .filter(|item| { // If this is a trait impl, filter out associated items whose corresponding item // in the associated trait is marked `doc(hidden)`. diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index d14953f1bb78..440874df14cf 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -2643,15 +2643,12 @@ fn clean_extern_crate<'tcx>( } } - // FIXME: using `from_def_id_and_kind` breaks `rustdoc/masked` for some reason - vec![Item { - name: Some(name), - attrs: Box::new(Attributes::from_ast(attrs)), - item_id: crate_def_id.into(), - kind: Box::new(ExternCrateItem { src: orig_name }), - cfg: attrs.cfg(cx.tcx, &cx.cache.hidden_cfg), - inline_stmt_id: Some(krate_owner_def_id), - }] + vec![Item::from_def_id_and_parts( + krate_owner_def_id, + Some(name), + ExternCrateItem { src: orig_name }, + cx, + )] } fn clean_use_statement<'tcx>( diff --git a/src/librustdoc/clean/utils.rs b/src/librustdoc/clean/utils.rs index df9da9e7c7fd..5c8db3b87744 100644 --- a/src/librustdoc/clean/utils.rs +++ b/src/librustdoc/clean/utils.rs @@ -38,11 +38,15 @@ pub(crate) fn krate(cx: &mut DocContext<'_>) -> Crate { for it in &module.items { // `compiler_builtins` should be masked too, but we can't apply // `#[doc(masked)]` to the injected `extern crate` because it's unstable. - if it.is_extern_crate() - && (it.attrs.has_doc_flag(sym::masked) - || cx.tcx.is_compiler_builtins(it.item_id.krate())) - { + if cx.tcx.is_compiler_builtins(it.item_id.krate()) { cx.cache.masked_crates.insert(it.item_id.krate()); + } else if it.is_extern_crate() + && it.attrs.has_doc_flag(sym::masked) + && let Some(def_id) = it.item_id.as_def_id() + && let Some(local_def_id) = def_id.as_local() + && let Some(cnum) = cx.tcx.extern_mod_stmt_cnum(local_def_id) + { + cx.cache.masked_crates.insert(cnum); } } } diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs index 1099c68b004c..f60f40267d63 100644 --- a/src/librustdoc/html/format.rs +++ b/src/librustdoc/html/format.rs @@ -18,7 +18,7 @@ use rustc_data_structures::captures::Captures; use rustc_data_structures::fx::FxHashSet; use rustc_hir as hir; use rustc_hir::def::DefKind; -use rustc_hir::def_id::DefId; +use rustc_hir::def_id::{DefId, LOCAL_CRATE}; use rustc_metadata::creader::{CStore, LoadedMacro}; use rustc_middle::ty; use rustc_middle::ty::TyCtxt; @@ -662,6 +662,14 @@ pub(crate) fn href_with_root_path( // documented on their parent's page tcx.parent(did) } + DefKind::ExternCrate => { + // Link to the crate itself, not the `extern crate` item. + if let Some(local_did) = did.as_local() { + tcx.extern_mod_stmt_cnum(local_did).unwrap_or(LOCAL_CRATE).as_def_id() + } else { + did + } + } _ => did, }; let cache = cx.cache(); diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs index 4d029407afa4..2fcf61d00490 100644 --- a/src/librustdoc/html/render/mod.rs +++ b/src/librustdoc/html/render/mod.rs @@ -1678,11 +1678,11 @@ fn render_impl( rendering_params: ImplRenderingParameters, ) { for trait_item in &t.items { - // Skip over any default trait items that are impossible to call + // Skip over any default trait items that are impossible to reference // (e.g. if it has a `Self: Sized` bound on an unsized type). if let Some(impl_def_id) = parent.item_id.as_def_id() && let Some(trait_item_def_id) = trait_item.item_id.as_def_id() - && cx.tcx().is_impossible_method((impl_def_id, trait_item_def_id)) + && cx.tcx().is_impossible_associated_item((impl_def_id, trait_item_def_id)) { continue; } diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs index 91f3729bfa24..4de30e4ed9d2 100644 --- a/src/librustdoc/passes/collect_intra_doc_links.rs +++ b/src/librustdoc/passes/collect_intra_doc_links.rs @@ -14,7 +14,7 @@ use rustc_hir::def::{DefKind, Namespace, PerNS}; use rustc_hir::def_id::{DefId, CRATE_DEF_ID}; use rustc_hir::Mutability; use rustc_middle::ty::{Ty, TyCtxt}; -use rustc_middle::{bug, ty}; +use rustc_middle::{bug, span_bug, ty}; use rustc_resolve::rustdoc::{has_primitive_or_keyword_docs, prepare_to_doc_link_resolution}; use rustc_resolve::rustdoc::{strip_generics_from_path, MalformedGenerics}; use rustc_session::lint::Lint; @@ -402,7 +402,12 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> { // `doc_link_resolutions` is missing a `path_str`, that means that there are valid links // that are being missed. To fix the ICE, change // `rustc_resolve::rustdoc::attrs_to_preprocessed_links` to cache the link. - .unwrap_or_else(|| panic!("no resolution for {:?} {:?} {:?}", path_str, ns, module_id)) + .unwrap_or_else(|| { + span_bug!( + self.cx.tcx.def_span(item_id), + "no resolution for {path_str:?} {ns:?} {module_id:?}", + ) + }) .and_then(|res| res.try_into().ok()) .or_else(|| resolve_primitive(path_str, ns)); debug!("{} resolved to {:?} in namespace {:?}", path_str, result, ns); @@ -963,6 +968,7 @@ fn preprocessed_markdown_links(s: &str) -> Vec { } impl LinkCollector<'_, '_> { + #[instrument(level = "debug", skip_all)] fn resolve_links(&mut self, item: &Item) { if !self.cx.render_options.document_private && let Some(def_id) = item.item_id.as_def_id() diff --git a/src/tools/build-manifest/src/main.rs b/src/tools/build-manifest/src/main.rs index 14618f89aedb..a02ce68903d1 100644 --- a/src/tools/build-manifest/src/main.rs +++ b/src/tools/build-manifest/src/main.rs @@ -122,6 +122,7 @@ static TARGETS: &[&str] = &[ "riscv32imac-unknown-none-elf", "riscv32gc-unknown-linux-gnu", "riscv64imac-unknown-none-elf", + "riscv64gc-unknown-hermit", "riscv64gc-unknown-none-elf", "riscv64gc-unknown-linux-gnu", "s390x-unknown-linux-gnu", @@ -147,6 +148,7 @@ static TARGETS: &[&str] = &[ "x86_64-pc-windows-msvc", "x86_64-sun-solaris", "x86_64-pc-solaris", + "x86_64-unikraft-linux-musl", "x86_64-unknown-freebsd", "x86_64-unknown-illumos", "x86_64-unknown-linux-gnu", diff --git a/src/tools/build_helper/src/ci.rs b/src/tools/build_helper/src/ci.rs index b70ea5ec1139..a8505ec95967 100644 --- a/src/tools/build_helper/src/ci.rs +++ b/src/tools/build_helper/src/ci.rs @@ -36,25 +36,26 @@ impl CiEnv { } pub mod gha { - use std::sync::atomic::{AtomicBool, Ordering}; + use std::sync::Mutex; - static GROUP_ACTIVE: AtomicBool = AtomicBool::new(false); + static ACTIVE_GROUPS: Mutex> = Mutex::new(Vec::new()); /// All github actions log messages from this call to the Drop of the return value - /// will be grouped and hidden by default in logs. Note that nesting these does - /// not really work. + /// will be grouped and hidden by default in logs. Note that since github actions doesn't + /// support group nesting, any active group will be first finished when a subgroup is started, + /// and then re-started when the subgroup finishes. #[track_caller] pub fn group(name: impl std::fmt::Display) -> Group { - if std::env::var_os("GITHUB_ACTIONS").is_some() { - eprintln!("::group::{name}"); - } else { - eprintln!("{name}") + let mut groups = ACTIVE_GROUPS.lock().unwrap(); + + // A group is currently active. End it first to avoid nesting. + if !groups.is_empty() { + end_group(); } - // https://github.com/actions/toolkit/issues/1001 - assert!( - !GROUP_ACTIVE.swap(true, Ordering::Relaxed), - "nested groups are not supported by GHA!" - ); + + let name = name.to_string(); + start_group(&name); + groups.push(name); Group(()) } @@ -64,13 +65,36 @@ pub mod gha { impl Drop for Group { fn drop(&mut self) { - if std::env::var_os("GITHUB_ACTIONS").is_some() { - eprintln!("::endgroup::"); + end_group(); + + let mut groups = ACTIVE_GROUPS.lock().unwrap(); + // Remove the current group + groups.pop(); + + // If there was some previous group, restart it + if is_in_gha() { + if let Some(name) = groups.last() { + start_group(format!("{name} (continued)")); + } } - assert!( - GROUP_ACTIVE.swap(false, Ordering::Relaxed), - "group dropped but no group active!" - ); } } + + fn start_group(name: impl std::fmt::Display) { + if is_in_gha() { + eprintln!("::group::{name}"); + } else { + eprintln!("{name}") + } + } + + fn end_group() { + if is_in_gha() { + eprintln!("::endgroup::"); + } + } + + fn is_in_gha() -> bool { + std::env::var_os("GITHUB_ACTIONS").is_some() + } } diff --git a/src/tools/cargo b/src/tools/cargo index 1b15556767f4..7ac9416d82cd 160000 --- a/src/tools/cargo +++ b/src/tools/cargo @@ -1 +1 @@ -Subproject commit 1b15556767f4b78a64e868eedf4073c423f02b93 +Subproject commit 7ac9416d82cd4fc5e707c9ec3574d22dff6466e5 diff --git a/src/tools/clippy/clippy_lints/src/strings.rs b/src/tools/clippy/clippy_lints/src/strings.rs index 58724852b3c4..4d45091f4b5b 100644 --- a/src/tools/clippy/clippy_lints/src/strings.rs +++ b/src/tools/clippy/clippy_lints/src/strings.rs @@ -328,7 +328,7 @@ impl<'tcx> LateLintPass<'tcx> for StringLitAsBytes { { // Don't lint. Byte strings produce `&[u8; N]` whereas `as_bytes()` produces // `&[u8]`. This change would prevent matching with different sized slices. - } else { + } else if !callsite.starts_with("env!") { span_lint_and_sugg( cx, STRING_LIT_AS_BYTES, diff --git a/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs b/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs index 1c29d614fa34..e563e41ab2aa 100644 --- a/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs +++ b/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs @@ -14,7 +14,7 @@ use rustc_middle::mir::{ Body, CastKind, NonDivergingIntrinsic, NullOp, Operand, Place, ProjectionElem, Rvalue, Statement, StatementKind, Terminator, TerminatorKind, }; -use rustc_middle::traits::{ImplSource, ObligationCause}; +use rustc_middle::traits::{ImplSource, ObligationCause, BuiltinImplSource}; use rustc_middle::ty::adjustment::PointerCoercion; use rustc_middle::ty::{self, BoundConstness, GenericArgKind, TraitRef, Ty, TyCtxt}; use rustc_semver::RustcVersion; @@ -411,7 +411,7 @@ fn is_ty_const_destruct<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, body: &Body<'tcx> if !matches!( impl_src, - ImplSource::Builtin(_) | ImplSource::Param(_, ty::BoundConstness::ConstIfConst) + ImplSource::Builtin(BuiltinImplSource::Misc, _) | ImplSource::Param(ty::BoundConstness::ConstIfConst, _) ) { return false; } diff --git a/src/tools/clippy/tests/ui/self_assignment.rs b/src/tools/clippy/tests/ui/self_assignment.rs index d6682cc63dcf..a7f9fbaae7cf 100644 --- a/src/tools/clippy/tests/ui/self_assignment.rs +++ b/src/tools/clippy/tests/ui/self_assignment.rs @@ -14,7 +14,7 @@ pub fn positives(mut a: usize, b: &mut u32, mut s: S) { *b = *b; s = s; s.a = s.a; - s.b[10] = s.b[5 + 5]; + s.b[9] = s.b[5 + 4]; s.c[0][1] = s.c[0][1]; s.b[a] = s.b[a]; *s.e = *s.e; diff --git a/src/tools/clippy/tests/ui/self_assignment.stderr b/src/tools/clippy/tests/ui/self_assignment.stderr index bed88244eea7..25b8569fa3d0 100644 --- a/src/tools/clippy/tests/ui/self_assignment.stderr +++ b/src/tools/clippy/tests/ui/self_assignment.stderr @@ -24,11 +24,11 @@ error: self-assignment of `s.a` to `s.a` LL | s.a = s.a; | ^^^^^^^^^ -error: self-assignment of `s.b[5 + 5]` to `s.b[10]` +error: self-assignment of `s.b[5 + 4]` to `s.b[9]` --> $DIR/self_assignment.rs:17:5 | -LL | s.b[10] = s.b[5 + 5]; - | ^^^^^^^^^^^^^^^^^^^^ +LL | s.b[9] = s.b[5 + 4]; + | ^^^^^^^^^^^^^^^^^^^ error: self-assignment of `s.c[0][1]` to `s.c[0][1]` --> $DIR/self_assignment.rs:18:5 diff --git a/src/tools/compiletest/src/header.rs b/src/tools/compiletest/src/header.rs index 4ae2249097f6..269d9384376f 100644 --- a/src/tools/compiletest/src/header.rs +++ b/src/tools/compiletest/src/header.rs @@ -6,7 +6,6 @@ use std::io::BufReader; use std::path::{Path, PathBuf}; use std::process::Command; -use build_helper::ci::CiEnv; use tracing::*; use crate::common::{Config, Debugger, FailMode, Mode, PassMode}; @@ -298,13 +297,6 @@ impl TestProps { /// `//[foo]`), then the property is ignored unless `cfg` is /// `Some("foo")`. fn load_from(&mut self, testfile: &Path, cfg: Option<&str>, config: &Config) { - // In CI, we've sometimes encountered non-determinism related to truncating very long paths. - // Set a consistent (short) prefix to avoid issues, but only in CI to avoid regressing the - // contributor experience. - if CiEnv::is_ci() { - self.remap_src_base = config.mode == Mode::Ui && !config.suite.contains("rustdoc"); - } - let mut has_edition = false; if !testfile.is_dir() { let file = File::open(testfile).unwrap(); diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index 7eeb987063fc..ba068995d44a 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -2330,6 +2330,7 @@ impl<'test> TestCx<'test> { // Hide line numbers to reduce churn rustc.arg("-Zui-testing"); rustc.arg("-Zdeduplicate-diagnostics=no"); + rustc.arg("-Zwrite-long-types-to-disk=no"); // FIXME: use this for other modes too, for perf? rustc.arg("-Cstrip=debuginfo"); } diff --git a/src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs b/src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs index 1aed436e88d8..8059fddb1008 100644 --- a/src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs +++ b/src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs @@ -928,13 +928,13 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { Ok(()) } } - impl<'ecx, 'mir, 'tcx> MutValueVisitor<'mir, 'tcx, MiriMachine<'mir, 'tcx>> + impl<'ecx, 'mir, 'tcx> ValueVisitor<'mir, 'tcx, MiriMachine<'mir, 'tcx>> for RetagVisitor<'ecx, 'mir, 'tcx> { type V = PlaceTy<'tcx, Provenance>; #[inline(always)] - fn ecx(&mut self) -> &mut MiriInterpCx<'mir, 'tcx> { + fn ecx(&self) -> &MiriInterpCx<'mir, 'tcx> { self.ecx } diff --git a/src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs b/src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs index 2afd45829bd8..9073f6954429 100644 --- a/src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs +++ b/src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs @@ -413,13 +413,13 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { Ok(()) } } - impl<'ecx, 'mir, 'tcx> MutValueVisitor<'mir, 'tcx, MiriMachine<'mir, 'tcx>> + impl<'ecx, 'mir, 'tcx> ValueVisitor<'mir, 'tcx, MiriMachine<'mir, 'tcx>> for RetagVisitor<'ecx, 'mir, 'tcx> { type V = PlaceTy<'tcx, Provenance>; #[inline(always)] - fn ecx(&mut self) -> &mut MiriInterpCx<'mir, 'tcx> { + fn ecx(&self) -> &MiriInterpCx<'mir, 'tcx> { self.ecx } @@ -578,14 +578,14 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { /// I.e. input is what you get from the visitor upon encountering an `adt` that is `Unique`, /// and output can be used by `retag_ptr_inplace`. fn inner_ptr_of_unique<'tcx>( - ecx: &mut MiriInterpCx<'_, 'tcx>, + ecx: &MiriInterpCx<'_, 'tcx>, place: &PlaceTy<'tcx, Provenance>, ) -> InterpResult<'tcx, PlaceTy<'tcx, Provenance>> { // Follows the same layout as `interpret/visitor.rs:walk_value` for `Box` in // `rustc_const_eval`, just with one fewer layer. // Here we have a `Unique(NonNull(*mut), PhantomData)` assert_eq!(place.layout.fields.count(), 2, "Unique must have exactly 2 fields"); - let (nonnull, phantom) = (ecx.place_field(place, 0)?, ecx.place_field(place, 1)?); + let (nonnull, phantom) = (ecx.project_field(place, 0)?, ecx.project_field(place, 1)?); assert!( phantom.layout.ty.ty_adt_def().is_some_and(|adt| adt.is_phantom_data()), "2nd field of `Unique` should be `PhantomData` but is `{:?}`", @@ -593,7 +593,7 @@ fn inner_ptr_of_unique<'tcx>( ); // Now down to `NonNull(*mut)` assert_eq!(nonnull.layout.fields.count(), 1, "NonNull must have exactly 1 field"); - let ptr = ecx.place_field(&nonnull, 0)?; + let ptr = ecx.project_field(&nonnull, 0)?; // Finally a plain `*mut` Ok(ptr) } diff --git a/src/tools/miri/src/eval.rs b/src/tools/miri/src/eval.rs index 79a7115f24e6..4f7b70649a93 100644 --- a/src/tools/miri/src/eval.rs +++ b/src/tools/miri/src/eval.rs @@ -320,7 +320,7 @@ pub fn create_ecx<'mir, 'tcx: 'mir>( ))?; let argvs_place = ecx.allocate(argvs_layout, MiriMemoryKind::Machine.into())?; for (idx, arg) in argvs.into_iter().enumerate() { - let place = ecx.mplace_field(&argvs_place, idx)?; + let place = ecx.project_field(&argvs_place, idx)?; ecx.write_immediate(arg, &place.into())?; } ecx.mark_immutable(&argvs_place); @@ -354,7 +354,7 @@ pub fn create_ecx<'mir, 'tcx: 'mir>( ecx.machine.cmd_line = Some(*cmd_place); // Store the UTF-16 string. We just allocated so we know the bounds are fine. for (idx, &c) in cmd_utf16.iter().enumerate() { - let place = ecx.mplace_field(&cmd_place, idx)?; + let place = ecx.project_field(&cmd_place, idx)?; ecx.write_scalar(Scalar::from_u16(c), &place.into())?; } ecx.mark_immutable(&cmd_place); diff --git a/src/tools/miri/src/helpers.rs b/src/tools/miri/src/helpers.rs index c19d691ede6a..f6a438f5d629 100644 --- a/src/tools/miri/src/helpers.rs +++ b/src/tools/miri/src/helpers.rs @@ -10,6 +10,7 @@ use log::trace; use rustc_hir::def::{DefKind, Namespace}; use rustc_hir::def_id::{DefId, CRATE_DEF_INDEX}; +use rustc_index::IndexVec; use rustc_middle::mir; use rustc_middle::ty::{ self, @@ -17,7 +18,7 @@ use rustc_middle::ty::{ List, TyCtxt, }; use rustc_span::{def_id::CrateNum, sym, Span, Symbol}; -use rustc_target::abi::{Align, FieldsShape, Size, Variants}; +use rustc_target::abi::{Align, FieldIdx, FieldsShape, Size, Variants}; use rustc_target::spec::abi::Abi; use rand::RngCore; @@ -229,20 +230,20 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { this.layout_of(ty).unwrap() } - /// Project to the given *named* field of the mplace (which must be a struct or union type). - fn mplace_field_named( + /// Project to the given *named* field (which must be a struct or union type). + fn project_field_named>( &self, - mplace: &MPlaceTy<'tcx, Provenance>, + base: &P, name: &str, - ) -> InterpResult<'tcx, MPlaceTy<'tcx, Provenance>> { + ) -> InterpResult<'tcx, P> { let this = self.eval_context_ref(); - let adt = mplace.layout.ty.ty_adt_def().unwrap(); + let adt = base.layout().ty.ty_adt_def().unwrap(); for (idx, field) in adt.non_enum_variant().fields.iter().enumerate() { if field.name.as_str() == name { - return this.mplace_field(mplace, idx); + return this.project_field(base, idx); } } - bug!("No field named {} in type {}", name, mplace.layout.ty); + bug!("No field named {} in type {}", name, base.layout().ty); } /// Write an int of the appropriate size to `dest`. The target type may be signed or unsigned, @@ -270,7 +271,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { ) -> InterpResult<'tcx> { let this = self.eval_context_mut(); for (idx, &val) in values.iter().enumerate() { - let field = this.mplace_field(dest, idx)?; + let field = this.project_field(dest, idx)?; this.write_int(val, &field.into())?; } Ok(()) @@ -284,7 +285,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { ) -> InterpResult<'tcx> { let this = self.eval_context_mut(); for &(name, val) in values.iter() { - let field = this.mplace_field_named(dest, name)?; + let field = this.project_field_named(dest, name)?; this.write_int(val, &field.into())?; } Ok(()) @@ -301,8 +302,8 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { } /// Get the `Place` for a local - fn local_place(&mut self, local: mir::Local) -> InterpResult<'tcx, PlaceTy<'tcx, Provenance>> { - let this = self.eval_context_mut(); + fn local_place(&self, local: mir::Local) -> InterpResult<'tcx, PlaceTy<'tcx, Provenance>> { + let this = self.eval_context_ref(); let place = mir::Place { local, projection: List::empty() }; this.eval_place(place) } @@ -479,6 +480,16 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { self.ecx } + fn aggregate_field_order(memory_index: &IndexVec, idx: usize) -> usize { + // We need to do an *inverse* lookup: find the field that has position `idx` in memory order. + for (src_field, &mem_pos) in memory_index.iter_enumerated() { + if mem_pos as usize == idx { + return src_field.as_usize(); + } + } + panic!("invalid `memory_index`, could not find {}-th field in memory order", idx); + } + // Hook to detect `UnsafeCell`. fn visit_value(&mut self, v: &MPlaceTy<'tcx, Provenance>) -> InterpResult<'tcx> { trace!("UnsafeCellVisitor: {:?} {:?}", *v, v.layout.ty); @@ -524,33 +535,6 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { } } - // Make sure we visit aggregates in increasing offset order. - fn visit_aggregate( - &mut self, - place: &MPlaceTy<'tcx, Provenance>, - fields: impl Iterator>>, - ) -> InterpResult<'tcx> { - match place.layout.fields { - FieldsShape::Array { .. } => { - // For the array layout, we know the iterator will yield sorted elements so - // we can avoid the allocation. - self.walk_aggregate(place, fields) - } - FieldsShape::Arbitrary { .. } => { - // Gather the subplaces and sort them before visiting. - let mut places = fields - .collect::>>>()?; - // we just compare offsets, the abs. value never matters - places.sort_by_key(|place| place.ptr.addr()); - self.walk_aggregate(place, places.into_iter().map(Ok)) - } - FieldsShape::Union { .. } | FieldsShape::Primitive => { - // Uh, what? - bug!("unions/primitives are not aggregates we should ever visit") - } - } - } - fn visit_union( &mut self, _v: &MPlaceTy<'tcx, Provenance>, @@ -746,7 +730,8 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { Ok(mplace) } - fn deref_pointer_as( + /// Deref' a pointer *without* checking that the place is dereferenceable. + fn deref_pointer_unchecked( &self, val: &ImmTy<'tcx, Provenance>, layout: TyAndLayout<'tcx>, @@ -811,10 +796,10 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { tp: &MPlaceTy<'tcx, Provenance>, ) -> InterpResult<'tcx, Option> { let this = self.eval_context_mut(); - let seconds_place = this.mplace_field(tp, 0)?; + let seconds_place = this.project_field(tp, 0)?; let seconds_scalar = this.read_scalar(&seconds_place.into())?; let seconds = seconds_scalar.to_target_isize(this)?; - let nanoseconds_place = this.mplace_field(tp, 1)?; + let nanoseconds_place = this.project_field(tp, 1)?; let nanoseconds_scalar = this.read_scalar(&nanoseconds_place.into())?; let nanoseconds = nanoseconds_scalar.to_target_isize(this)?; diff --git a/src/tools/miri/src/shims/backtrace.rs b/src/tools/miri/src/shims/backtrace.rs index adf9a35d5c3a..e4aa7467cbe0 100644 --- a/src/tools/miri/src/shims/backtrace.rs +++ b/src/tools/miri/src/shims/backtrace.rs @@ -83,7 +83,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { // Write pointers into array for (i, ptr) in ptrs.into_iter().enumerate() { - let place = this.mplace_index(&alloc, i as u64)?; + let place = this.project_index(&alloc, i as u64)?; this.write_pointer(ptr, &place.into())?; } @@ -196,33 +196,33 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { this.write_immediate( name_alloc.to_ref(this), - &this.mplace_field(&dest, 0)?.into(), + &this.project_field(&dest, 0)?.into(), )?; this.write_immediate( filename_alloc.to_ref(this), - &this.mplace_field(&dest, 1)?.into(), + &this.project_field(&dest, 1)?.into(), )?; } 1 => { this.write_scalar( Scalar::from_target_usize(name.len().try_into().unwrap(), this), - &this.mplace_field(&dest, 0)?.into(), + &this.project_field(&dest, 0)?.into(), )?; this.write_scalar( Scalar::from_target_usize(filename.len().try_into().unwrap(), this), - &this.mplace_field(&dest, 1)?.into(), + &this.project_field(&dest, 1)?.into(), )?; } _ => throw_unsup_format!("unknown `miri_resolve_frame` flags {}", flags), } - this.write_scalar(Scalar::from_u32(lineno), &this.mplace_field(&dest, 2)?.into())?; - this.write_scalar(Scalar::from_u32(colno), &this.mplace_field(&dest, 3)?.into())?; + this.write_scalar(Scalar::from_u32(lineno), &this.project_field(&dest, 2)?.into())?; + this.write_scalar(Scalar::from_u32(colno), &this.project_field(&dest, 3)?.into())?; // Support a 4-field struct for now - this is deprecated // and slated for removal. if num_fields == 5 { - this.write_pointer(fn_ptr, &this.mplace_field(&dest, 4)?.into())?; + this.write_pointer(fn_ptr, &this.project_field(&dest, 4)?.into())?; } Ok(()) diff --git a/src/tools/miri/src/shims/env.rs b/src/tools/miri/src/shims/env.rs index 1dcb877a83f0..f98fd0431ae6 100644 --- a/src/tools/miri/src/shims/env.rs +++ b/src/tools/miri/src/shims/env.rs @@ -456,7 +456,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { ))?; let vars_place = this.allocate(vars_layout, MiriMemoryKind::Runtime.into())?; for (idx, var) in vars.into_iter().enumerate() { - let place = this.mplace_field(&vars_place, idx)?; + let place = this.project_field(&vars_place, idx)?; this.write_pointer(var, &place.into())?; } this.write_pointer(vars_place.ptr, &this.machine.env_vars.environ.unwrap().into())?; diff --git a/src/tools/miri/src/shims/foreign_items.rs b/src/tools/miri/src/shims/foreign_items.rs index 72a4adba8d41..c753eadbbad3 100644 --- a/src/tools/miri/src/shims/foreign_items.rs +++ b/src/tools/miri/src/shims/foreign_items.rs @@ -942,9 +942,9 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { #[allow(clippy::arithmetic_side_effects)] // it's a u128, we can shift by 64 let (c_out, sum) = ((wide_sum >> 64).truncate::(), wide_sum.truncate::()); - let c_out_field = this.place_field(dest, 0)?; + let c_out_field = this.project_field(dest, 0)?; this.write_scalar(Scalar::from_u8(c_out), &c_out_field)?; - let sum_field = this.place_field(dest, 1)?; + let sum_field = this.project_field(dest, 1)?; this.write_scalar(Scalar::from_u64(sum), &sum_field)?; } "llvm.x86.sse2.pause" diff --git a/src/tools/miri/src/shims/intrinsics/simd.rs b/src/tools/miri/src/shims/intrinsics/simd.rs index 94f8cfbfb1c3..3afe5214f08b 100644 --- a/src/tools/miri/src/shims/intrinsics/simd.rs +++ b/src/tools/miri/src/shims/intrinsics/simd.rs @@ -57,8 +57,8 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { }; for i in 0..dest_len { - let op = this.read_immediate(&this.mplace_index(&op, i)?.into())?; - let dest = this.mplace_index(&dest, i)?; + let op = this.read_immediate(&this.project_index(&op, i)?.into())?; + let dest = this.project_index(&dest, i)?; let val = match which { Op::MirOp(mir_op) => this.unary_op(mir_op, &op)?.to_scalar(), Op::Abs => { @@ -172,9 +172,9 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { }; for i in 0..dest_len { - let left = this.read_immediate(&this.mplace_index(&left, i)?.into())?; - let right = this.read_immediate(&this.mplace_index(&right, i)?.into())?; - let dest = this.mplace_index(&dest, i)?; + let left = this.read_immediate(&this.project_index(&left, i)?.into())?; + let right = this.read_immediate(&this.project_index(&right, i)?.into())?; + let dest = this.project_index(&dest, i)?; let val = match which { Op::MirOp(mir_op) => { let (val, overflowed, ty) = this.overflowing_binary_op(mir_op, &left, &right)?; @@ -232,10 +232,10 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { assert_eq!(dest_len, c_len); for i in 0..dest_len { - let a = this.read_scalar(&this.mplace_index(&a, i)?.into())?; - let b = this.read_scalar(&this.mplace_index(&b, i)?.into())?; - let c = this.read_scalar(&this.mplace_index(&c, i)?.into())?; - let dest = this.mplace_index(&dest, i)?; + let a = this.read_scalar(&this.project_index(&a, i)?.into())?; + let b = this.read_scalar(&this.project_index(&b, i)?.into())?; + let c = this.read_scalar(&this.project_index(&c, i)?.into())?; + let dest = this.project_index(&dest, i)?; // Works for f32 and f64. // FIXME: using host floats to work around https://github.com/rust-lang/miri/issues/2468. @@ -295,13 +295,13 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { }; // Initialize with first lane, then proceed with the rest. - let mut res = this.read_immediate(&this.mplace_index(&op, 0)?.into())?; + let mut res = this.read_immediate(&this.project_index(&op, 0)?.into())?; if matches!(which, Op::MirOpBool(_)) { // Convert to `bool` scalar. res = imm_from_bool(simd_element_to_bool(res)?); } for i in 1..op_len { - let op = this.read_immediate(&this.mplace_index(&op, i)?.into())?; + let op = this.read_immediate(&this.project_index(&op, i)?.into())?; res = match which { Op::MirOp(mir_op) => { this.binary_op(mir_op, &res, &op)? @@ -355,7 +355,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { let mut res = init; for i in 0..op_len { - let op = this.read_immediate(&this.mplace_index(&op, i)?.into())?; + let op = this.read_immediate(&this.project_index(&op, i)?.into())?; res = this.binary_op(mir_op, &res, &op)?; } this.write_immediate(*res, dest)?; @@ -372,10 +372,10 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { assert_eq!(dest_len, no_len); for i in 0..dest_len { - let mask = this.read_immediate(&this.mplace_index(&mask, i)?.into())?; - let yes = this.read_immediate(&this.mplace_index(&yes, i)?.into())?; - let no = this.read_immediate(&this.mplace_index(&no, i)?.into())?; - let dest = this.mplace_index(&dest, i)?; + let mask = this.read_immediate(&this.project_index(&mask, i)?.into())?; + let yes = this.read_immediate(&this.project_index(&yes, i)?.into())?; + let no = this.read_immediate(&this.project_index(&no, i)?.into())?; + let dest = this.project_index(&dest, i)?; let val = if simd_element_to_bool(mask)? { yes } else { no }; this.write_immediate(*val, &dest.into())?; @@ -403,9 +403,9 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { & 1u64 .checked_shl(simd_bitmask_index(i, dest_len, this.data_layout().endian)) .unwrap(); - let yes = this.read_immediate(&this.mplace_index(&yes, i.into())?.into())?; - let no = this.read_immediate(&this.mplace_index(&no, i.into())?.into())?; - let dest = this.mplace_index(&dest, i.into())?; + let yes = this.read_immediate(&this.project_index(&yes, i.into())?.into())?; + let no = this.read_immediate(&this.project_index(&no, i.into())?.into())?; + let dest = this.project_index(&dest, i.into())?; let val = if mask != 0 { yes } else { no }; this.write_immediate(*val, &dest.into())?; @@ -435,8 +435,8 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { let from_exposed_cast = intrinsic_name == "from_exposed_addr"; for i in 0..dest_len { - let op = this.read_immediate(&this.mplace_index(&op, i)?.into())?; - let dest = this.mplace_index(&dest, i)?; + let op = this.read_immediate(&this.project_index(&op, i)?.into())?; + let dest = this.project_index(&dest, i)?; let val = match (op.layout.ty.kind(), dest.layout.ty.kind()) { // Int-to-(int|float): always safe @@ -496,17 +496,17 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { for i in 0..dest_len { let src_index: u64 = this - .read_immediate(&this.operand_index(index, i)?)? + .read_immediate(&this.project_index(index, i)?)? .to_scalar() .to_u32()? .into(); - let dest = this.mplace_index(&dest, i)?; + let dest = this.project_index(&dest, i)?; let val = if src_index < left_len { - this.read_immediate(&this.mplace_index(&left, src_index)?.into())? + this.read_immediate(&this.project_index(&left, src_index)?.into())? } else if src_index < left_len.checked_add(right_len).unwrap() { let right_idx = src_index.checked_sub(left_len).unwrap(); - this.read_immediate(&this.mplace_index(&right, right_idx)?.into())? + this.read_immediate(&this.project_index(&right, right_idx)?.into())? } else { span_bug!( this.cur_span(), @@ -528,10 +528,10 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { assert_eq!(dest_len, mask_len); for i in 0..dest_len { - let passthru = this.read_immediate(&this.mplace_index(&passthru, i)?.into())?; - let ptr = this.read_immediate(&this.mplace_index(&ptrs, i)?.into())?; - let mask = this.read_immediate(&this.mplace_index(&mask, i)?.into())?; - let dest = this.mplace_index(&dest, i)?; + let passthru = this.read_immediate(&this.project_index(&passthru, i)?.into())?; + let ptr = this.read_immediate(&this.project_index(&ptrs, i)?.into())?; + let mask = this.read_immediate(&this.project_index(&mask, i)?.into())?; + let dest = this.project_index(&dest, i)?; let val = if simd_element_to_bool(mask)? { let place = this.deref_operand(&ptr.into())?; @@ -552,9 +552,9 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { assert_eq!(ptrs_len, mask_len); for i in 0..ptrs_len { - let value = this.read_immediate(&this.mplace_index(&value, i)?.into())?; - let ptr = this.read_immediate(&this.mplace_index(&ptrs, i)?.into())?; - let mask = this.read_immediate(&this.mplace_index(&mask, i)?.into())?; + let value = this.read_immediate(&this.project_index(&value, i)?.into())?; + let ptr = this.read_immediate(&this.project_index(&ptrs, i)?.into())?; + let mask = this.read_immediate(&this.project_index(&mask, i)?.into())?; if simd_element_to_bool(mask)? { let place = this.deref_operand(&ptr.into())?; @@ -578,7 +578,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { let mut res = 0u64; for i in 0..op_len { - let op = this.read_immediate(&this.mplace_index(&op, i.into())?.into())?; + let op = this.read_immediate(&this.project_index(&op, i.into())?.into())?; if simd_element_to_bool(op)? { res |= 1u64 .checked_shl(simd_bitmask_index(i, op_len, this.data_layout().endian)) diff --git a/src/tools/miri/src/shims/unix/foreign_items.rs b/src/tools/miri/src/shims/unix/foreign_items.rs index 4931f3688572..14297845d3db 100644 --- a/src/tools/miri/src/shims/unix/foreign_items.rs +++ b/src/tools/miri/src/shims/unix/foreign_items.rs @@ -593,7 +593,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { #[allow(deprecated)] let home_dir = std::env::home_dir().unwrap(); let (written, _) = this.write_path_to_c_str(&home_dir, buf, buflen)?; - let pw_dir = this.mplace_field_named(&pwd, "pw_dir")?; + let pw_dir = this.project_field_named(&pwd, "pw_dir")?; this.write_pointer(buf, &pw_dir.into())?; if written { diff --git a/src/tools/miri/src/shims/unix/fs.rs b/src/tools/miri/src/shims/unix/fs.rs index 0fdd55b407cd..3da6c17f3b0b 100644 --- a/src/tools/miri/src/shims/unix/fs.rs +++ b/src/tools/miri/src/shims/unix/fs.rs @@ -1141,7 +1141,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { ("tv_sec", access_sec.into()), ("tv_nsec", access_nsec.into()), ], - &this.mplace_field_named(&statxbuf, "stx_atime")?, + &this.project_field_named(&statxbuf, "stx_atime")?, )?; #[rustfmt::skip] this.write_int_fields_named( @@ -1149,7 +1149,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { ("tv_sec", created_sec.into()), ("tv_nsec", created_nsec.into()), ], - &this.mplace_field_named(&statxbuf, "stx_btime")?, + &this.project_field_named(&statxbuf, "stx_btime")?, )?; #[rustfmt::skip] this.write_int_fields_named( @@ -1157,7 +1157,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { ("tv_sec", 0.into()), ("tv_nsec", 0.into()), ], - &this.mplace_field_named(&statxbuf, "stx_ctime")?, + &this.project_field_named(&statxbuf, "stx_ctime")?, )?; #[rustfmt::skip] this.write_int_fields_named( @@ -1165,7 +1165,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { ("tv_sec", modified_sec.into()), ("tv_nsec", modified_nsec.into()), ], - &this.mplace_field_named(&statxbuf, "stx_mtime")?, + &this.project_field_named(&statxbuf, "stx_mtime")?, )?; Ok(0) @@ -1421,7 +1421,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { // } let entry_place = this.deref_operand_as(entry_op, this.libc_ty_layout("dirent"))?; - let name_place = this.mplace_field(&entry_place, 5)?; + let name_place = this.project_field(&entry_place, 5)?; let file_name = dir_entry.file_name(); // not a Path as there are no separators! let (name_fits, file_name_buf_len) = this.write_os_str_to_c_str( diff --git a/src/tools/miri/src/shims/unix/linux/fd.rs b/src/tools/miri/src/shims/unix/linux/fd.rs index 87e887000c52..9c43651132b7 100644 --- a/src/tools/miri/src/shims/unix/linux/fd.rs +++ b/src/tools/miri/src/shims/unix/linux/fd.rs @@ -73,9 +73,9 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { if op == epoll_ctl_add || op == epoll_ctl_mod { let event = this.deref_operand_as(event, this.libc_ty_layout("epoll_event"))?; - let events = this.mplace_field(&event, 0)?; + let events = this.project_field(&event, 0)?; let events = this.read_scalar(&events.into())?.to_u32()?; - let data = this.mplace_field(&event, 1)?; + let data = this.project_field(&event, 1)?; let data = this.read_scalar(&data.into())?; let event = EpollEvent { events, data }; diff --git a/src/tools/miri/src/shims/unix/linux/sync.rs b/src/tools/miri/src/shims/unix/linux/sync.rs index 873b84e30599..0474c9fd90a5 100644 --- a/src/tools/miri/src/shims/unix/linux/sync.rs +++ b/src/tools/miri/src/shims/unix/linux/sync.rs @@ -85,7 +85,8 @@ pub fn futex<'tcx>( return Ok(()); } - let timeout = this.deref_pointer_as( + // `read_timespec` will check the place when it is not null. + let timeout = this.deref_pointer_unchecked( &this.read_immediate(&args[3])?, this.libc_ty_layout("timespec"), )?; diff --git a/src/tools/miri/src/shims/windows/foreign_items.rs b/src/tools/miri/src/shims/windows/foreign_items.rs index 2888424c21e1..d64aa53ed958 100644 --- a/src/tools/miri/src/shims/windows/foreign_items.rs +++ b/src/tools/miri/src/shims/windows/foreign_items.rs @@ -122,7 +122,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { // We have to put the result into io_status_block. if let Some(n) = written { let io_status_information = - this.mplace_field_named(&io_status_block, "Information")?; + this.project_field_named(&io_status_block, "Information")?; this.write_scalar( Scalar::from_target_usize(n.into(), this), &io_status_information.into(), diff --git a/src/tools/miri/tests/pass/intrinsics.rs b/src/tools/miri/tests/pass/intrinsics.rs index 6267e6e6bc11..a6a4a06f8600 100644 --- a/src/tools/miri/tests/pass/intrinsics.rs +++ b/src/tools/miri/tests/pass/intrinsics.rs @@ -3,7 +3,7 @@ //! Tests for various intrinsics that do not fit anywhere else. use std::intrinsics; -use std::mem::{size_of, size_of_val, size_of_val_raw}; +use std::mem::{size_of, size_of_val, size_of_val_raw, discriminant}; struct Bomb; @@ -39,4 +39,7 @@ fn main() { let _v = intrinsics::discriminant_value(&0); let _v = intrinsics::discriminant_value(&true); let _v = intrinsics::discriminant_value(&vec![1, 2, 3]); + // Make sure that even if the discriminant is stored together with data, the intrinsic returns + // only the discriminant, nothing about the data. + assert_eq!(discriminant(&Some(false)), discriminant(&Some(true))); } diff --git a/src/tools/rust-analyzer/.github/workflows/ci.yaml b/src/tools/rust-analyzer/.github/workflows/ci.yaml index 31bb7eed8d73..9f246098e767 100644 --- a/src/tools/rust-analyzer/.github/workflows/ci.yaml +++ b/src/tools/rust-analyzer/.github/workflows/ci.yaml @@ -161,10 +161,21 @@ jobs: # if: runner.os == 'Linux' # working-directory: ./editors/code + # If this steps fails, your code's type integrity might be wrong at some places at TypeScript level. + - run: npm run typecheck + working-directory: ./editors/code + if: needs.changes.outputs.typescript == 'true' + + # You may fix the code automatically by running `npm run lint:fix` if this steps fails. - run: npm run lint working-directory: ./editors/code if: needs.changes.outputs.typescript == 'true' + # To fix this steps, please run `npm run format`. + - run: npm run format:check + working-directory: ./editors/code + if: needs.changes.outputs.typescript == 'true' + - name: Run VS Code tests (Linux) if: matrix.os == 'ubuntu-latest' && needs.changes.outputs.typescript == 'true' env: @@ -179,10 +190,6 @@ jobs: run: npm test working-directory: ./editors/code - - run: npm run pretest - working-directory: ./editors/code - if: needs.changes.outputs.typescript == 'true' - - run: npm run package --scripts-prepend-node-path working-directory: ./editors/code if: needs.changes.outputs.typescript == 'true' diff --git a/src/tools/rust-analyzer/crates/hir-def/src/body/pretty.rs b/src/tools/rust-analyzer/crates/hir-def/src/body/pretty.rs index 0c6cf0b49a26..eeaed87164dc 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/body/pretty.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/body/pretty.rs @@ -634,7 +634,7 @@ impl Printer<'_> { match literal { Literal::String(it) => w!(self, "{:?}", it), Literal::ByteString(it) => w!(self, "\"{}\"", it.escape_ascii()), - Literal::CString(it) => w!(self, "\"{}\\0\"", it), + Literal::CString(it) => w!(self, "\"{}\\0\"", it.escape_ascii()), Literal::Char(it) => w!(self, "'{}'", it.escape_debug()), Literal::Bool(it) => w!(self, "{}", it), Literal::Int(i, suffix) => { diff --git a/src/tools/rust-analyzer/crates/hir-def/src/hir.rs b/src/tools/rust-analyzer/crates/hir-def/src/hir.rs index 500e880061ac..8a140a1ec181 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/hir.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/hir.rs @@ -85,7 +85,7 @@ impl fmt::Display for FloatTypeWrapper { pub enum Literal { String(Box), ByteString(Box<[u8]>), - CString(Box), + CString(Box<[u8]>), Char(char), Bool(bool), Int(i128, Option), diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/consteval.rs b/src/tools/rust-analyzer/crates/hir-ty/src/consteval.rs index 4de90d40a7c7..1c0f7b08da8c 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/consteval.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/consteval.rs @@ -16,7 +16,8 @@ use triomphe::Arc; use crate::{ db::HirDatabase, infer::InferenceContext, lower::ParamLoweringMode, mir::monomorphize_mir_body_bad, to_placeholder_idx, utils::Generics, Const, ConstData, - ConstScalar, ConstValue, GenericArg, Interner, MemoryMap, Substitution, Ty, TyBuilder, + ConstScalar, ConstValue, GenericArg, Interner, MemoryMap, Substitution, TraitEnvironment, Ty, + TyBuilder, }; use super::mir::{interpret_mir, lower_to_mir, pad16, MirEvalError, MirLowerError}; @@ -135,7 +136,7 @@ pub fn intern_const_ref( ty: Ty, krate: CrateId, ) -> Const { - let layout = db.layout_of_ty(ty.clone(), krate); + let layout = db.layout_of_ty(ty.clone(), Arc::new(TraitEnvironment::empty(krate))); let bytes = match value { LiteralConstRef::Int(i) => { // FIXME: We should handle failure of layout better. @@ -173,7 +174,7 @@ pub fn try_const_usize(db: &dyn HirDatabase, c: &Const) -> Option { chalk_ir::ConstValue::Concrete(c) => match &c.interned { ConstScalar::Bytes(it, _) => Some(u128::from_le_bytes(pad16(&it, false))), ConstScalar::UnevaluatedConst(c, subst) => { - let ec = db.const_eval(*c, subst.clone()).ok()?; + let ec = db.const_eval(*c, subst.clone(), None).ok()?; try_const_usize(db, &ec) } _ => None, @@ -186,6 +187,7 @@ pub(crate) fn const_eval_recover( _: &[String], _: &GeneralConstId, _: &Substitution, + _: &Option>, ) -> Result { Err(ConstEvalError::MirLowerError(MirLowerError::Loop)) } @@ -210,6 +212,7 @@ pub(crate) fn const_eval_query( db: &dyn HirDatabase, def: GeneralConstId, subst: Substitution, + trait_env: Option>, ) -> Result { let body = match def { GeneralConstId::ConstId(c) => { @@ -228,7 +231,7 @@ pub(crate) fn const_eval_query( } GeneralConstId::InTypeConstId(c) => db.mir_body(c.into())?, }; - let c = interpret_mir(db, body, false).0?; + let c = interpret_mir(db, body, false, trait_env).0?; Ok(c) } @@ -241,7 +244,7 @@ pub(crate) fn const_eval_static_query( Substitution::empty(Interner), db.trait_environment_for_body(def.into()), )?; - let c = interpret_mir(db, body, false).0?; + let c = interpret_mir(db, body, false, None).0?; Ok(c) } @@ -268,7 +271,7 @@ pub(crate) fn const_eval_discriminant_variant( Substitution::empty(Interner), db.trait_environment_for_body(def), )?; - let c = interpret_mir(db, mir_body, false).0?; + let c = interpret_mir(db, mir_body, false, None).0?; let c = try_const_usize(db, &c).unwrap() as i128; Ok(c) } @@ -293,7 +296,7 @@ pub(crate) fn eval_to_const( } let infer = ctx.clone().resolve_all(); if let Ok(mir_body) = lower_to_mir(ctx.db, ctx.owner, &ctx.body, &infer, expr) { - if let Ok(result) = interpret_mir(db, Arc::new(mir_body), true).0 { + if let Ok(result) = interpret_mir(db, Arc::new(mir_body), true, None).0 { return result; } } diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/consteval/tests.rs b/src/tools/rust-analyzer/crates/hir-ty/src/consteval/tests.rs index 5bb327606d32..98ebe557245f 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/consteval/tests.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/consteval/tests.rs @@ -114,7 +114,7 @@ fn eval_goal(db: &TestDB, file_id: FileId) -> Result { _ => None, }) .expect("No const named GOAL found in the test"); - db.const_eval(const_id.into(), Substitution::empty(Interner)) + db.const_eval(const_id.into(), Substitution::empty(Interner), None) } #[test] @@ -1941,6 +1941,33 @@ fn dyn_trait() { "#, 900, ); + check_number( + r#" + //- minicore: coerce_unsized, index, slice + trait A { + fn x(&self) -> i32; + } + + trait B: A {} + + impl A for i32 { + fn x(&self) -> i32 { + 5 + } + } + + impl B for i32 { + + } + + const fn f(x: &dyn B) -> i32 { + x.x() + } + + const GOAL: i32 = f(&2i32); + "#, + 5, + ); } #[test] @@ -2492,6 +2519,28 @@ fn const_trait_assoc() { "#, 5, ); + check_number( + r#" + //- minicore: size_of + //- /a/lib.rs crate:a + use core::mem::size_of; + pub struct S(T); + impl S { + pub const X: usize = core::mem::size_of::(); + } + //- /main.rs crate:main deps:a + use a::{S}; + trait Tr { + type Ty; + } + impl Tr for i32 { + type Ty = u64; + } + struct K(::Ty); + const GOAL: usize = S::>::X; + "#, + 8, + ); check_number( r#" struct S(*mut T); diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/db.rs b/src/tools/rust-analyzer/crates/hir-ty/src/db.rs index 14b719ea4124..9c96b5ab8dbb 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/db.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/db.rs @@ -77,8 +77,12 @@ pub trait HirDatabase: DefDatabase + Upcast { #[salsa::invoke(crate::consteval::const_eval_query)] #[salsa::cycle(crate::consteval::const_eval_recover)] - fn const_eval(&self, def: GeneralConstId, subst: Substitution) - -> Result; + fn const_eval( + &self, + def: GeneralConstId, + subst: Substitution, + trait_env: Option>, + ) -> Result; #[salsa::invoke(crate::consteval::const_eval_static_query)] #[salsa::cycle(crate::consteval::const_eval_static_recover)] @@ -100,12 +104,16 @@ pub trait HirDatabase: DefDatabase + Upcast { &self, def: AdtId, subst: Substitution, - krate: CrateId, + env: Arc, ) -> Result, LayoutError>; #[salsa::invoke(crate::layout::layout_of_ty_query)] #[salsa::cycle(crate::layout::layout_of_ty_recover)] - fn layout_of_ty(&self, ty: Ty, krate: CrateId) -> Result, LayoutError>; + fn layout_of_ty( + &self, + ty: Ty, + env: Arc, + ) -> Result, LayoutError>; #[salsa::invoke(crate::layout::target_data_layout_query)] fn target_data_layout(&self, krate: CrateId) -> Option>; diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/decl_check.rs b/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/decl_check.rs index 73c8ad3dd5a9..5aaa2bcc7c2c 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/decl_check.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/decl_check.rs @@ -14,13 +14,12 @@ mod case_conv; use std::fmt; -use base_db::CrateId; use hir_def::{ data::adt::VariantData, hir::{Pat, PatId}, src::HasSource, - AdtId, AttrDefId, ConstId, EnumId, FunctionId, ItemContainerId, Lookup, ModuleDefId, StaticId, - StructId, + AdtId, AttrDefId, ConstId, DefWithBodyId, EnumId, EnumVariantId, FunctionId, ItemContainerId, + Lookup, ModuleDefId, StaticId, StructId, }; use hir_expand::{ name::{AsName, Name}, @@ -44,13 +43,9 @@ mod allow { pub(super) const NON_CAMEL_CASE_TYPES: &str = "non_camel_case_types"; } -pub fn incorrect_case( - db: &dyn HirDatabase, - krate: CrateId, - owner: ModuleDefId, -) -> Vec { +pub fn incorrect_case(db: &dyn HirDatabase, owner: ModuleDefId) -> Vec { let _p = profile::span("validate_module_item"); - let mut validator = DeclValidator::new(db, krate); + let mut validator = DeclValidator::new(db); validator.validate_item(owner); validator.sink } @@ -120,7 +115,6 @@ pub struct IncorrectCase { pub(super) struct DeclValidator<'a> { db: &'a dyn HirDatabase, - krate: CrateId, pub(super) sink: Vec, } @@ -132,8 +126,8 @@ struct Replacement { } impl<'a> DeclValidator<'a> { - pub(super) fn new(db: &'a dyn HirDatabase, krate: CrateId) -> DeclValidator<'a> { - DeclValidator { db, krate, sink: Vec::new() } + pub(super) fn new(db: &'a dyn HirDatabase) -> DeclValidator<'a> { + DeclValidator { db, sink: Vec::new() } } pub(super) fn validate_item(&mut self, item: ModuleDefId) { @@ -195,8 +189,7 @@ impl<'a> DeclValidator<'a> { AttrDefId::TypeAliasId(_) => None, AttrDefId::GenericParamId(_) => None, } - .map(|mid| self.allowed(mid, allow_name, true)) - .unwrap_or(false) + .is_some_and(|mid| self.allowed(mid, allow_name, true)) } fn validate_func(&mut self, func: FunctionId) { @@ -206,17 +199,7 @@ impl<'a> DeclValidator<'a> { return; } - let body = self.db.body(func.into()); - - // Recursively validate inner scope items, such as static variables and constants. - for (_, block_def_map) in body.blocks(self.db.upcast()) { - for (_, module) in block_def_map.modules() { - for def_id in module.scope.declarations() { - let mut validator = DeclValidator::new(self.db, self.krate); - validator.validate_item(def_id); - } - } - } + self.validate_body_inner_items(func.into()); // Check whether non-snake case identifiers are allowed for this function. if self.allowed(func.into(), allow::NON_SNAKE_CASE, false) { @@ -231,6 +214,8 @@ impl<'a> DeclValidator<'a> { expected_case: CaseType::LowerSnakeCase, }); + let body = self.db.body(func.into()); + // Check the patterns inside the function body. // This includes function parameters. let pats_replacements = body @@ -496,6 +481,11 @@ impl<'a> DeclValidator<'a> { fn validate_enum(&mut self, enum_id: EnumId) { let data = self.db.enum_data(enum_id); + for (local_id, _) in data.variants.iter() { + let variant_id = EnumVariantId { parent: enum_id, local_id }; + self.validate_body_inner_items(variant_id.into()); + } + // Check whether non-camel case names are allowed for this enum. if self.allowed(enum_id.into(), allow::NON_CAMEL_CASE_TYPES, false) { return; @@ -512,13 +502,11 @@ impl<'a> DeclValidator<'a> { // Check the field names. let enum_fields_replacements = data .variants - .iter() - .filter_map(|(_, variant)| { + .values() + .filter_map(|variant| { Some(Replacement { current_name: variant.name.clone(), - suggested_text: to_camel_case( - &variant.name.display(self.db.upcast()).to_string(), - )?, + suggested_text: to_camel_case(&variant.name.to_smol_str())?, expected_case: CaseType::UpperCamelCase, }) }) @@ -622,6 +610,8 @@ impl<'a> DeclValidator<'a> { fn validate_const(&mut self, const_id: ConstId) { let data = self.db.const_data(const_id); + self.validate_body_inner_items(const_id.into()); + if self.allowed(const_id.into(), allow::NON_UPPER_CASE_GLOBAL, false) { return; } @@ -631,7 +621,7 @@ impl<'a> DeclValidator<'a> { None => return, }; - let const_name = name.display(self.db.upcast()).to_string(); + let const_name = name.to_smol_str(); let replacement = if let Some(new_name) = to_upper_snake_case(&const_name) { Replacement { current_name: name.clone(), @@ -670,13 +660,15 @@ impl<'a> DeclValidator<'a> { return; } + self.validate_body_inner_items(static_id.into()); + if self.allowed(static_id.into(), allow::NON_UPPER_CASE_GLOBAL, false) { return; } let name = &data.name; - let static_name = name.display(self.db.upcast()).to_string(); + let static_name = name.to_smol_str(); let replacement = if let Some(new_name) = to_upper_snake_case(&static_name) { Replacement { current_name: name.clone(), @@ -707,4 +699,17 @@ impl<'a> DeclValidator<'a> { self.sink.push(diagnostic); } + + // FIXME: We don't currently validate names within `DefWithBodyId::InTypeConstId`. + /// Recursively validates inner scope items, such as static variables and constants. + fn validate_body_inner_items(&mut self, body_id: DefWithBodyId) { + let body = self.db.body(body_id); + for (_, block_def_map) in body.blocks(self.db.upcast()) { + for (_, module) in block_def_map.modules() { + for def_id in module.scope.declarations() { + self.validate_item(def_id); + } + } + } + } } diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/display.rs b/src/tools/rust-analyzer/crates/hir-ty/src/display.rs index 8cffdef289ea..96787959e1f2 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/display.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/display.rs @@ -29,6 +29,7 @@ use itertools::Itertools; use la_arena::ArenaMap; use smallvec::SmallVec; use stdx::never; +use triomphe::Arc; use crate::{ consteval::try_const_usize, @@ -43,7 +44,7 @@ use crate::{ AdtId, AliasEq, AliasTy, Binders, CallableDefId, CallableSig, Const, ConstScalar, ConstValue, DomainGoal, GenericArg, ImplTraitId, Interner, Lifetime, LifetimeData, LifetimeOutlives, MemoryMap, Mutability, OpaqueTy, ProjectionTy, ProjectionTyExt, QuantifiedWhereClause, Scalar, - Substitution, TraitRef, TraitRefExt, Ty, TyExt, WhereClause, + Substitution, TraitEnvironment, TraitRef, TraitRefExt, Ty, TyExt, WhereClause, }; pub trait HirWrite: fmt::Write { @@ -454,7 +455,9 @@ fn render_const_scalar( ) -> Result<(), HirDisplayError> { // FIXME: We need to get krate from the final callers of the hir display // infrastructure and have it here as a field on `f`. - let krate = *f.db.crate_graph().crates_in_topological_order().last().unwrap(); + let trait_env = Arc::new(TraitEnvironment::empty( + *f.db.crate_graph().crates_in_topological_order().last().unwrap(), + )); match ty.kind(Interner) { TyKind::Scalar(s) => match s { Scalar::Bool => write!(f, "{}", if b[0] == 0 { false } else { true }), @@ -497,7 +500,7 @@ fn render_const_scalar( TyKind::Slice(ty) => { let addr = usize::from_le_bytes(b[0..b.len() / 2].try_into().unwrap()); let count = usize::from_le_bytes(b[b.len() / 2..].try_into().unwrap()); - let Ok(layout) = f.db.layout_of_ty(ty.clone(), krate) else { + let Ok(layout) = f.db.layout_of_ty(ty.clone(), trait_env) else { return f.write_str(""); }; let size_one = layout.size.bytes_usize(); @@ -523,7 +526,7 @@ fn render_const_scalar( let Ok(t) = memory_map.vtable.ty(ty_id) else { return f.write_str(""); }; - let Ok(layout) = f.db.layout_of_ty(t.clone(), krate) else { + let Ok(layout) = f.db.layout_of_ty(t.clone(), trait_env) else { return f.write_str(""); }; let size = layout.size.bytes_usize(); @@ -555,7 +558,7 @@ fn render_const_scalar( return f.write_str(""); } }); - let Ok(layout) = f.db.layout_of_ty(t.clone(), krate) else { + let Ok(layout) = f.db.layout_of_ty(t.clone(), trait_env) else { return f.write_str(""); }; let size = layout.size.bytes_usize(); @@ -567,7 +570,7 @@ fn render_const_scalar( } }, TyKind::Tuple(_, subst) => { - let Ok(layout) = f.db.layout_of_ty(ty.clone(), krate) else { + let Ok(layout) = f.db.layout_of_ty(ty.clone(), trait_env.clone()) else { return f.write_str(""); }; f.write_str("(")?; @@ -580,7 +583,7 @@ fn render_const_scalar( } let ty = ty.assert_ty_ref(Interner); // Tuple only has type argument let offset = layout.fields.offset(id).bytes_usize(); - let Ok(layout) = f.db.layout_of_ty(ty.clone(), krate) else { + let Ok(layout) = f.db.layout_of_ty(ty.clone(), trait_env.clone()) else { f.write_str("")?; continue; }; @@ -590,7 +593,7 @@ fn render_const_scalar( f.write_str(")") } TyKind::Adt(adt, subst) => { - let Ok(layout) = f.db.layout_of_adt(adt.0, subst.clone(), krate) else { + let Ok(layout) = f.db.layout_of_adt(adt.0, subst.clone(), trait_env.clone()) else { return f.write_str(""); }; match adt.0 { @@ -602,7 +605,7 @@ fn render_const_scalar( &data.variant_data, f, &field_types, - adt.0.module(f.db.upcast()).krate(), + f.db.trait_environment(adt.0.into()), &layout, subst, b, @@ -614,7 +617,7 @@ fn render_const_scalar( } hir_def::AdtId::EnumId(e) => { let Some((var_id, var_layout)) = - detect_variant_from_bytes(&layout, f.db, krate, b, e) + detect_variant_from_bytes(&layout, f.db, trait_env.clone(), b, e) else { return f.write_str(""); }; @@ -626,7 +629,7 @@ fn render_const_scalar( &data.variant_data, f, &field_types, - adt.0.module(f.db.upcast()).krate(), + f.db.trait_environment(adt.0.into()), &var_layout, subst, b, @@ -645,7 +648,7 @@ fn render_const_scalar( let Some(len) = try_const_usize(f.db, len) else { return f.write_str(""); }; - let Ok(layout) = f.db.layout_of_ty(ty.clone(), krate) else { + let Ok(layout) = f.db.layout_of_ty(ty.clone(), trait_env) else { return f.write_str(""); }; let size_one = layout.size.bytes_usize(); @@ -684,7 +687,7 @@ fn render_variant_after_name( data: &VariantData, f: &mut HirFormatter<'_>, field_types: &ArenaMap>, - krate: CrateId, + trait_env: Arc, layout: &Layout, subst: &Substitution, b: &[u8], @@ -695,7 +698,7 @@ fn render_variant_after_name( let render_field = |f: &mut HirFormatter<'_>, id: LocalFieldId| { let offset = layout.fields.offset(u32::from(id.into_raw()) as usize).bytes_usize(); let ty = field_types[id].clone().substitute(Interner, subst); - let Ok(layout) = f.db.layout_of_ty(ty.clone(), krate) else { + let Ok(layout) = f.db.layout_of_ty(ty.clone(), trait_env.clone()) else { return f.write_str(""); }; let size = layout.size.bytes_usize(); diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/infer/expr.rs b/src/tools/rust-analyzer/crates/hir-ty/src/infer/expr.rs index 4b14345aa39f..72e6443beb77 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/infer/expr.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/infer/expr.rs @@ -1665,6 +1665,7 @@ impl InferenceContext<'_> { // the parameter to coerce to the expected type (for example in // `coerce_unsize_expected_type_4`). let param_ty = self.normalize_associated_types_in(param_ty); + let expected_ty = self.normalize_associated_types_in(expected_ty); let expected = Expectation::rvalue_hint(self, expected_ty); // infer with the expected type we have... let ty = self.infer_expr_inner(arg, &expected); diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/infer/unify.rs b/src/tools/rust-analyzer/crates/hir-ty/src/infer/unify.rs index 385f39f5374d..0fb71135b4de 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/infer/unify.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/infer/unify.rs @@ -252,7 +252,8 @@ impl<'a> InferenceTable<'a> { // and registering an obligation. But it needs chalk support, so we handle the most basic // case (a non associated const without generic parameters) manually. if subst.len(Interner) == 0 { - if let Ok(eval) = self.db.const_eval((*c_id).into(), subst.clone()) + if let Ok(eval) = + self.db.const_eval((*c_id).into(), subst.clone(), None) { eval } else { @@ -785,7 +786,7 @@ impl<'a> InferenceTable<'a> { crate::ConstScalar::Unknown => self.new_const_var(data.ty.clone()), // try to evaluate unevaluated const. Replace with new var if const eval failed. crate::ConstScalar::UnevaluatedConst(id, subst) => { - if let Ok(eval) = self.db.const_eval(*id, subst.clone()) { + if let Ok(eval) = self.db.const_eval(*id, subst.clone(), None) { eval } else { self.new_const_var(data.ty.clone()) diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/layout.rs b/src/tools/rust-analyzer/crates/hir-ty/src/layout.rs index 72e2bcc55590..ffc7a6f2ebd7 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/layout.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/layout.rs @@ -1,6 +1,5 @@ //! Compute the binary representation of a type -use base_db::CrateId; use chalk_ir::{AdtId, FloatTy, IntTy, TyKind, UintTy}; use hir_def::{ layout::{ @@ -61,7 +60,6 @@ pub enum LayoutError { } struct LayoutCx<'a> { - krate: CrateId, target: &'a TargetDataLayout, } @@ -82,7 +80,7 @@ fn layout_of_simd_ty( db: &dyn HirDatabase, id: StructId, subst: &Substitution, - krate: CrateId, + env: Arc, dl: &TargetDataLayout, ) -> Result, LayoutError> { let fields = db.field_types(id.into()); @@ -111,7 +109,7 @@ fn layout_of_simd_ty( // * the homogeneous field type and the number of fields. let (e_ty, e_len, is_array) = if let TyKind::Array(e_ty, _) = f0_ty.kind(Interner) { // Extract the number of elements from the layout of the array field: - let FieldsShape::Array { count, .. } = db.layout_of_ty(f0_ty.clone(), krate)?.fields else { + let FieldsShape::Array { count, .. } = db.layout_of_ty(f0_ty.clone(), env.clone())?.fields else { user_error!("Array with non array layout"); }; @@ -122,7 +120,7 @@ fn layout_of_simd_ty( }; // Compute the ABI of the element type: - let e_ly = db.layout_of_ty(e_ty, krate)?; + let e_ly = db.layout_of_ty(e_ty, env.clone())?; let Abi::Scalar(e_abi) = e_ly.abi else { user_error!("simd type with inner non scalar type"); }; @@ -152,25 +150,25 @@ fn layout_of_simd_ty( pub fn layout_of_ty_query( db: &dyn HirDatabase, ty: Ty, - krate: CrateId, + trait_env: Arc, ) -> Result, LayoutError> { + let krate = trait_env.krate; let Some(target) = db.target_data_layout(krate) else { return Err(LayoutError::TargetLayoutNotAvailable); }; - let cx = LayoutCx { krate, target: &target }; + let cx = LayoutCx { target: &target }; let dl = &*cx.current_data_layout(); - let trait_env = Arc::new(TraitEnvironment::empty(krate)); - let ty = normalize(db, trait_env, ty.clone()); + let ty = normalize(db, trait_env.clone(), ty.clone()); let result = match ty.kind(Interner) { TyKind::Adt(AdtId(def), subst) => { if let hir_def::AdtId::StructId(s) = def { let data = db.struct_data(*s); let repr = data.repr.unwrap_or_default(); if repr.simd() { - return layout_of_simd_ty(db, *s, subst, krate, &target); + return layout_of_simd_ty(db, *s, subst, trait_env.clone(), &target); } }; - return db.layout_of_adt(*def, subst.clone(), krate); + return db.layout_of_adt(*def, subst.clone(), trait_env.clone()); } TyKind::Scalar(s) => match s { chalk_ir::Scalar::Bool => Layout::scalar( @@ -228,7 +226,7 @@ pub fn layout_of_ty_query( let fields = tys .iter(Interner) - .map(|k| db.layout_of_ty(k.assert_ty_ref(Interner).clone(), krate)) + .map(|k| db.layout_of_ty(k.assert_ty_ref(Interner).clone(), trait_env.clone())) .collect::, _>>()?; let fields = fields.iter().map(|it| &**it).collect::>(); let fields = fields.iter().collect::>(); @@ -238,7 +236,7 @@ pub fn layout_of_ty_query( let count = try_const_usize(db, &count).ok_or(LayoutError::UserError( "unevaluated or mistyped const generic parameter".to_string(), ))? as u64; - let element = db.layout_of_ty(element.clone(), krate)?; + let element = db.layout_of_ty(element.clone(), trait_env.clone())?; let size = element.size.checked_mul(count, dl).ok_or(LayoutError::SizeOverflow)?; let abi = if count != 0 && matches!(element.abi, Abi::Uninhabited) { @@ -259,7 +257,7 @@ pub fn layout_of_ty_query( } } TyKind::Slice(element) => { - let element = db.layout_of_ty(element.clone(), krate)?; + let element = db.layout_of_ty(element.clone(), trait_env.clone())?; Layout { variants: Variants::Single { index: struct_variant_idx() }, fields: FieldsShape::Array { stride: element.size, count: 0 }, @@ -335,7 +333,7 @@ pub fn layout_of_ty_query( match impl_trait_id { crate::ImplTraitId::ReturnTypeImplTrait(func, idx) => { let infer = db.infer(func.into()); - return db.layout_of_ty(infer.type_of_rpit[idx].clone(), krate); + return db.layout_of_ty(infer.type_of_rpit[idx].clone(), trait_env.clone()); } crate::ImplTraitId::AsyncBlockTypeImplTrait(_, _) => { return Err(LayoutError::NotImplemented) @@ -351,7 +349,7 @@ pub fn layout_of_ty_query( .map(|it| { db.layout_of_ty( it.ty.clone().substitute(Interner, ClosureSubst(subst).parent_subst()), - krate, + trait_env.clone(), ) }) .collect::, _>>()?; @@ -377,7 +375,7 @@ pub fn layout_of_ty_recover( _: &dyn HirDatabase, _: &[String], _: &Ty, - _: &CrateId, + _: &Arc, ) -> Result, LayoutError> { user_error!("infinite sized recursive type"); } diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/layout/adt.rs b/src/tools/rust-analyzer/crates/hir-ty/src/layout/adt.rs index 19d5e98e7389..1c92e80f3355 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/layout/adt.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/layout/adt.rs @@ -2,7 +2,6 @@ use std::{cmp, ops::Bound}; -use base_db::CrateId; use hir_def::{ data::adt::VariantData, layout::{Integer, LayoutCalculator, ReprOptions, TargetDataLayout}, @@ -16,7 +15,7 @@ use crate::{ db::HirDatabase, lang_items::is_unsafe_cell, layout::{field_ty, Layout, LayoutError, RustcEnumVariantIdx}, - Substitution, + Substitution, TraitEnvironment, }; use super::LayoutCx; @@ -29,17 +28,18 @@ pub fn layout_of_adt_query( db: &dyn HirDatabase, def: AdtId, subst: Substitution, - krate: CrateId, + trait_env: Arc, ) -> Result, LayoutError> { + let krate = trait_env.krate; let Some(target) = db.target_data_layout(krate) else { return Err(LayoutError::TargetLayoutNotAvailable); }; - let cx = LayoutCx { krate, target: &target }; + let cx = LayoutCx { target: &target }; let dl = cx.current_data_layout(); let handle_variant = |def: VariantId, var: &VariantData| { var.fields() .iter() - .map(|(fd, _)| db.layout_of_ty(field_ty(db, def, fd, &subst), cx.krate)) + .map(|(fd, _)| db.layout_of_ty(field_ty(db, def, fd, &subst), trait_env.clone())) .collect::, _>>() }; let (variants, repr) = match def { @@ -134,7 +134,7 @@ pub fn layout_of_adt_recover( _: &[String], _: &AdtId, _: &Substitution, - _: &CrateId, + _: &Arc, ) -> Result, LayoutError> { user_error!("infinite sized recursive type"); } diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/layout/tests.rs b/src/tools/rust-analyzer/crates/hir-ty/src/layout/tests.rs index a3ced2bac0a2..333ad473a8b2 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/layout/tests.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/layout/tests.rs @@ -26,7 +26,7 @@ fn eval_goal(ra_fixture: &str, minicore: &str) -> Result, LayoutErro ); let (db, file_ids) = TestDB::with_many_files(&ra_fixture); - let (adt_or_type_alias_id, module_id) = file_ids + let adt_or_type_alias_id = file_ids .into_iter() .find_map(|file_id| { let module_id = db.module_for_file(file_id); @@ -47,7 +47,7 @@ fn eval_goal(ra_fixture: &str, minicore: &str) -> Result, LayoutErro } _ => None, })?; - Some((adt_or_type_alias_id, module_id)) + Some(adt_or_type_alias_id) }) .unwrap(); let goal_ty = match adt_or_type_alias_id { @@ -58,7 +58,13 @@ fn eval_goal(ra_fixture: &str, minicore: &str) -> Result, LayoutErro db.ty(ty_id.into()).substitute(Interner, &Substitution::empty(Interner)) } }; - db.layout_of_ty(goal_ty, module_id.krate()) + db.layout_of_ty( + goal_ty, + db.trait_environment(match adt_or_type_alias_id { + Either::Left(adt) => hir_def::GenericDefId::AdtId(adt), + Either::Right(ty) => hir_def::GenericDefId::TypeAliasId(ty), + }), + ) } /// A version of `eval_goal` for types that can not be expressed in ADTs, like closures and `impl Trait` @@ -72,7 +78,7 @@ fn eval_expr(ra_fixture: &str, minicore: &str) -> Result, LayoutErro let module_id = db.module_for_file(file_id); let def_map = module_id.def_map(&db); let scope = &def_map[module_id.local_id].scope; - let adt_id = scope + let function_id = scope .declarations() .find_map(|x| match x { hir_def::ModuleDefId::FunctionId(x) => { @@ -82,11 +88,11 @@ fn eval_expr(ra_fixture: &str, minicore: &str) -> Result, LayoutErro _ => None, }) .unwrap(); - let hir_body = db.body(adt_id.into()); + let hir_body = db.body(function_id.into()); let b = hir_body.bindings.iter().find(|x| x.1.name.to_smol_str() == "goal").unwrap().0; - let infer = db.infer(adt_id.into()); + let infer = db.infer(function_id.into()); let goal_ty = infer.type_of_binding[b].clone(); - db.layout_of_ty(goal_ty, module_id.krate()) + db.layout_of_ty(goal_ty, db.trait_environment(function_id.into())) } #[track_caller] diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/method_resolution.rs b/src/tools/rust-analyzer/crates/hir-ty/src/method_resolution.rs index 5e1040bc6aac..f3a5f69b2a63 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/method_resolution.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/method_resolution.rs @@ -665,13 +665,21 @@ pub fn is_dyn_method( }; let self_ty = trait_ref.self_type_parameter(Interner); if let TyKind::Dyn(d) = self_ty.kind(Interner) { - let is_my_trait_in_bounds = - d.bounds.skip_binders().as_slice(Interner).iter().any(|it| match it.skip_binders() { - // rustc doesn't accept `impl Foo<2> for dyn Foo<5>`, so if the trait id is equal, no matter - // what the generics are, we are sure that the method is come from the vtable. - WhereClause::Implemented(tr) => tr.trait_id == trait_ref.trait_id, - _ => false, - }); + let is_my_trait_in_bounds = d + .bounds + .skip_binders() + .as_slice(Interner) + .iter() + .map(|it| it.skip_binders()) + .flat_map(|it| match it { + WhereClause::Implemented(tr) => { + all_super_traits(db.upcast(), from_chalk_trait_id(tr.trait_id)) + } + _ => smallvec![], + }) + // rustc doesn't accept `impl Foo<2> for dyn Foo<5>`, so if the trait id is equal, no matter + // what the generics are, we are sure that the method is come from the vtable. + .any(|x| x == trait_id); if is_my_trait_in_bounds { return Some(fn_params); } @@ -1504,7 +1512,7 @@ fn autoderef_method_receiver( ty: Ty, ) -> Vec<(Canonical, ReceiverAdjustments)> { let mut deref_chain: Vec<_> = Vec::new(); - let mut autoderef = autoderef::Autoderef::new(table, ty, true); + let mut autoderef = autoderef::Autoderef::new(table, ty, false); while let Some((ty, derefs)) = autoderef.next() { deref_chain.push(( autoderef.table.canonicalize(ty).value, diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/mir.rs b/src/tools/rust-analyzer/crates/hir-ty/src/mir.rs index da5b496e141e..922e49d281d0 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/mir.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/mir.rs @@ -142,7 +142,7 @@ impl ProjectionElem { closure_field: impl FnOnce(ClosureId, &Substitution, usize) -> Ty, krate: CrateId, ) -> Ty { - if matches!(base.data(Interner).kind, TyKind::Alias(_) | TyKind::AssociatedType(..)) { + if matches!(base.kind(Interner), TyKind::Alias(_) | TyKind::AssociatedType(..)) { base = normalize( db, // FIXME: we should get this from caller @@ -151,7 +151,7 @@ impl ProjectionElem { ); } match self { - ProjectionElem::Deref => match &base.data(Interner).kind { + ProjectionElem::Deref => match &base.kind(Interner) { TyKind::Raw(_, inner) | TyKind::Ref(_, _, inner) => inner.clone(), TyKind::Adt(adt, subst) if is_box(db, adt.0) => { subst.at(Interner, 0).assert_ty_ref(Interner).clone() @@ -161,7 +161,7 @@ impl ProjectionElem { return TyKind::Error.intern(Interner); } }, - ProjectionElem::Field(f) => match &base.data(Interner).kind { + ProjectionElem::Field(f) => match &base.kind(Interner) { TyKind::Adt(_, subst) => { db.field_types(f.parent)[f.local_id].clone().substitute(Interner, subst) } @@ -170,7 +170,7 @@ impl ProjectionElem { return TyKind::Error.intern(Interner); } }, - ProjectionElem::TupleOrClosureField(f) => match &base.data(Interner).kind { + ProjectionElem::TupleOrClosureField(f) => match &base.kind(Interner) { TyKind::Tuple(_, subst) => subst .as_slice(Interner) .get(*f) @@ -187,7 +187,7 @@ impl ProjectionElem { } }, ProjectionElem::ConstantIndex { .. } | ProjectionElem::Index(_) => { - match &base.data(Interner).kind { + match &base.kind(Interner) { TyKind::Array(inner, _) | TyKind::Slice(inner) => inner.clone(), _ => { never!("Overloaded index is not a projection"); @@ -195,7 +195,7 @@ impl ProjectionElem { } } } - &ProjectionElem::Subslice { from, to } => match &base.data(Interner).kind { + &ProjectionElem::Subslice { from, to } => match &base.kind(Interner) { TyKind::Array(inner, c) => { let next_c = usize_const( db, diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval.rs b/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval.rs index d7820de629ae..7bd2756c14f4 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval.rs @@ -484,9 +484,10 @@ pub fn interpret_mir( // a zero size, hoping that they are all outside of our current body. Even without a fix for #7434, we can // (and probably should) do better here, for example by excluding bindings outside of the target expression. assert_placeholder_ty_is_unused: bool, + trait_env: Option>, ) -> (Result, String, String) { let ty = body.locals[return_slot()].ty.clone(); - let mut evaluator = Evaluator::new(db, body.owner, assert_placeholder_ty_is_unused); + let mut evaluator = Evaluator::new(db, body.owner, assert_placeholder_ty_is_unused, trait_env); let it: Result = (|| { if evaluator.ptr_size() != std::mem::size_of::() { not_supported!("targets with different pointer size from host"); @@ -512,9 +513,9 @@ impl Evaluator<'_> { db: &'a dyn HirDatabase, owner: DefWithBodyId, assert_placeholder_ty_is_unused: bool, + trait_env: Option>, ) -> Evaluator<'a> { let crate_id = owner.module(db.upcast()).krate(); - let trait_env = db.trait_environment_for_body(owner); Evaluator { stack: vec![0], heap: vec![0], @@ -524,7 +525,7 @@ impl Evaluator<'_> { static_locations: HashMap::default(), db, random_state: oorandom::Rand64::new(0), - trait_env, + trait_env: trait_env.unwrap_or_else(|| db.trait_environment_for_body(owner)), crate_id, stdout: vec![], stderr: vec![], @@ -634,7 +635,7 @@ impl Evaluator<'_> { addr = addr.offset(ty_size * offset); } &ProjectionElem::Subslice { from, to } => { - let inner_ty = match &ty.data(Interner).kind { + let inner_ty = match &ty.kind(Interner) { TyKind::Array(inner, _) | TyKind::Slice(inner) => inner.clone(), _ => TyKind::Error.intern(Interner), }; @@ -694,14 +695,14 @@ impl Evaluator<'_> { } let r = self .db - .layout_of_ty(ty.clone(), self.crate_id) + .layout_of_ty(ty.clone(), self.trait_env.clone()) .map_err(|e| MirEvalError::LayoutError(e, ty.clone()))?; self.layout_cache.borrow_mut().insert(ty.clone(), r.clone()); Ok(r) } fn layout_adt(&self, adt: AdtId, subst: Substitution) -> Result> { - self.db.layout_of_adt(adt, subst.clone(), self.crate_id).map_err(|e| { + self.db.layout_of_adt(adt, subst.clone(), self.trait_env.clone()).map_err(|e| { MirEvalError::LayoutError(e, TyKind::Adt(chalk_ir::AdtId(adt), subst).intern(Interner)) }) } @@ -793,7 +794,7 @@ impl Evaluator<'_> { .iter() .map(|it| self.operand_ty_and_eval(it, &mut locals)) .collect::>>()?; - let stack_frame = match &fn_ty.data(Interner).kind { + let stack_frame = match &fn_ty.kind(Interner) { TyKind::Function(_) => { let bytes = self.eval_operand(func, &mut locals)?; self.exec_fn_pointer( @@ -1255,7 +1256,7 @@ impl Evaluator<'_> { PointerCast::ReifyFnPointer | PointerCast::ClosureFnPointer(_) => { let current_ty = self.operand_ty(operand, locals)?; if let TyKind::FnDef(_, _) | TyKind::Closure(_, _) = - ¤t_ty.data(Interner).kind + ¤t_ty.kind(Interner) { let id = self.vtable_map.id(current_ty); let ptr_size = self.ptr_size(); @@ -1408,8 +1409,8 @@ impl Evaluator<'_> { addr: Interval, ) -> Result { use IntervalOrOwned::*; - Ok(match &target_ty.data(Interner).kind { - TyKind::Slice(_) => match ¤t_ty.data(Interner).kind { + Ok(match &target_ty.kind(Interner) { + TyKind::Slice(_) => match ¤t_ty.kind(Interner) { TyKind::Array(_, size) => { let len = match try_const_usize(self.db, size) { None => { @@ -1435,7 +1436,7 @@ impl Evaluator<'_> { r.extend(vtable.to_le_bytes().into_iter()); Owned(r) } - TyKind::Adt(id, target_subst) => match ¤t_ty.data(Interner).kind { + TyKind::Adt(id, target_subst) => match ¤t_ty.kind(Interner) { TyKind::Adt(current_id, current_subst) => { if id != current_id { not_supported!("unsizing struct with different type"); @@ -1582,10 +1583,13 @@ impl Evaluator<'_> { const_id = hir_def::GeneralConstId::ConstId(c); subst = s; } - result_owner = self.db.const_eval(const_id.into(), subst).map_err(|e| { - let name = const_id.name(self.db.upcast()); - MirEvalError::ConstEvalError(name, Box::new(e)) - })?; + result_owner = self + .db + .const_eval(const_id.into(), subst, Some(self.trait_env.clone())) + .map_err(|e| { + let name = const_id.name(self.db.upcast()); + MirEvalError::ConstEvalError(name, Box::new(e)) + })?; if let chalk_ir::ConstValue::Concrete(c) = &result_owner.data(Interner).value { if let ConstScalar::Bytes(v, mm) = &c.interned { break 'b (v, mm); @@ -1818,9 +1822,13 @@ impl Evaluator<'_> { } AdtId::EnumId(e) => { let layout = this.layout(ty)?; - if let Some((v, l)) = - detect_variant_from_bytes(&layout, this.db, this.crate_id, bytes, e) - { + if let Some((v, l)) = detect_variant_from_bytes( + &layout, + this.db, + this.trait_env.clone(), + bytes, + e, + ) { let data = &this.db.enum_data(e).variants[v].variant_data; let field_types = this .db @@ -1931,7 +1939,7 @@ impl Evaluator<'_> { ) -> Result> { let id = from_bytes!(usize, bytes.get(self)?); let next_ty = self.vtable_map.ty(id)?.clone(); - match &next_ty.data(Interner).kind { + match &next_ty.kind(Interner) { TyKind::FnDef(def, generic_args) => { self.exec_fn_def(*def, generic_args, destination, args, &locals, target_bb, span) } @@ -2182,7 +2190,7 @@ impl Evaluator<'_> { let size = self.size_of_sized(&func_ty, locals, "self type of fn trait")?; func_data = Interval { addr: Address::from_bytes(func_data.get(self)?)?, size }; } - match &func_ty.data(Interner).kind { + match &func_ty.kind(Interner) { TyKind::FnDef(def, subst) => { return self.exec_fn_def( *def, @@ -2409,7 +2417,7 @@ pub fn render_const_using_debug_impl( owner: ConstId, c: &Const, ) -> Result { - let mut evaluator = Evaluator::new(db, owner.into(), false); + let mut evaluator = Evaluator::new(db, owner.into(), false, None); let locals = &Locals { ptr: ArenaMap::new(), body: db diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval/tests.rs b/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval/tests.rs index 03c083bac422..93f4b699147f 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval/tests.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval/tests.rs @@ -30,7 +30,7 @@ fn eval_main(db: &TestDB, file_id: FileId) -> Result<(String, String), MirEvalEr db.trait_environment(func_id.into()), ) .map_err(|e| MirEvalError::MirLowerError(func_id.into(), e))?; - let (result, stdout, stderr) = interpret_mir(db, body, false); + let (result, stdout, stderr) = interpret_mir(db, body, false, None); result?; Ok((stdout, stderr)) } diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/mir/lower.rs b/src/tools/rust-analyzer/crates/hir-ty/src/mir/lower.rs index 361085879041..9f25175a3a9f 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/mir/lower.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/mir/lower.rs @@ -633,7 +633,7 @@ impl<'ctx> MirLowerCtx<'ctx> { ); } let callee_ty = self.expr_ty_after_adjustments(*callee); - match &callee_ty.data(Interner).kind { + match &callee_ty.kind(Interner) { chalk_ir::TyKind::FnDef(..) => { let func = Operand::from_bytes(vec![], callee_ty.clone()); self.lower_call_and_args( @@ -1229,7 +1229,7 @@ impl<'ctx> MirLowerCtx<'ctx> { } Expr::Array(l) => match l { Array::ElementList { elements, .. } => { - let elem_ty = match &self.expr_ty_without_adjust(expr_id).data(Interner).kind { + let elem_ty = match &self.expr_ty_without_adjust(expr_id).kind(Interner) { TyKind::Array(ty, _) => ty.clone(), _ => { return Err(MirLowerError::TypeError( @@ -1260,7 +1260,7 @@ impl<'ctx> MirLowerCtx<'ctx> { else { return Ok(None); }; - let len = match &self.expr_ty_without_adjust(expr_id).data(Interner).kind { + let len = match &self.expr_ty_without_adjust(expr_id).kind(Interner) { TyKind::Array(_, len) => len.clone(), _ => { return Err(MirLowerError::TypeError( @@ -1341,7 +1341,7 @@ impl<'ctx> MirLowerCtx<'ctx> { fn lower_literal_to_operand(&mut self, ty: Ty, l: &Literal) -> Result { let size = self .db - .layout_of_ty(ty.clone(), self.owner.module(self.db.upcast()).krate())? + .layout_of_ty(ty.clone(), self.db.trait_environment_for_body(self.owner))? .size .bytes_usize(); let bytes = match l { @@ -1355,7 +1355,6 @@ impl<'ctx> MirLowerCtx<'ctx> { return Ok(Operand::from_concrete_const(data, mm, ty)); } hir_def::hir::Literal::CString(b) => { - let b = b.as_bytes(); let bytes = b.iter().copied().chain(iter::once(0)).collect::>(); let mut data = Vec::with_capacity(mem::size_of::() * 2); @@ -1418,7 +1417,7 @@ impl<'ctx> MirLowerCtx<'ctx> { } else { let name = const_id.name(self.db.upcast()); self.db - .const_eval(const_id.into(), subst) + .const_eval(const_id.into(), subst, None) .map_err(|e| MirLowerError::ConstEvalError(name, Box::new(e)))? }; Ok(Operand::Constant(c)) diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/tests/method_resolution.rs b/src/tools/rust-analyzer/crates/hir-ty/src/tests/method_resolution.rs index a8e146b096a4..c837fae3fef4 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/tests/method_resolution.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/tests/method_resolution.rs @@ -1236,6 +1236,27 @@ fn main() { ); } +#[test] +fn inherent_method_ref_self_deref_raw() { + check_types( + r#" +struct Val; + +impl Val { + pub fn method(&self) -> u32 { + 0 + } +} + +fn main() { + let foo: *const Val; + foo.method(); + // ^^^^^^^^^^^^ {unknown} +} +"#, + ); +} + #[test] fn trait_method_deref_raw() { check_types( diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/tests/traits.rs b/src/tools/rust-analyzer/crates/hir-ty/src/tests/traits.rs index 5f5cd794512c..542df8b3468f 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/tests/traits.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/tests/traits.rs @@ -4434,3 +4434,47 @@ fn test(v: S) { "#, ); } + +#[test] +fn associated_type_in_argument() { + check( + r#" + trait A { + fn m(&self) -> i32; + } + + fn x(k: &::Ty) { + k.m(); + } + + struct X; + struct Y; + + impl A for X { + fn m(&self) -> i32 { + 8 + } + } + + impl A for Y { + fn m(&self) -> i32 { + 32 + } + } + + trait B { + type Ty: A; + } + + impl B for u16 { + type Ty = X; + } + + fn ttt() { + let inp = Y; + x::(&inp); + //^^^^ expected &X, got &Y + } + "#, + ); +} diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/utils.rs b/src/tools/rust-analyzer/crates/hir-ty/src/utils.rs index 0c38fe5d6ab3..75b8b9afa708 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/utils.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/utils.rs @@ -28,14 +28,15 @@ use intern::Interned; use rustc_hash::FxHashSet; use smallvec::{smallvec, SmallVec}; use stdx::never; +use triomphe::Arc; use crate::{ consteval::unknown_const, db::HirDatabase, layout::{Layout, TagEncoding}, mir::pad16, - ChalkTraitId, Const, ConstScalar, GenericArg, Interner, Substitution, TraitRef, TraitRefExt, - Ty, WhereClause, + ChalkTraitId, Const, ConstScalar, GenericArg, Interner, Substitution, TraitEnvironment, + TraitRef, TraitRefExt, Ty, WhereClause, }; pub(crate) fn fn_traits( @@ -417,7 +418,7 @@ impl FallibleTypeFolder for UnevaluatedConstEvaluatorFolder<'_> { ) -> Result { if let chalk_ir::ConstValue::Concrete(c) = &constant.data(Interner).value { if let ConstScalar::UnevaluatedConst(id, subst) = &c.interned { - if let Ok(eval) = self.db.const_eval(*id, subst.clone()) { + if let Ok(eval) = self.db.const_eval(*id, subst.clone(), None) { return Ok(eval); } else { return Ok(unknown_const(constant.data(Interner).ty.clone())); @@ -431,10 +432,11 @@ impl FallibleTypeFolder for UnevaluatedConstEvaluatorFolder<'_> { pub(crate) fn detect_variant_from_bytes<'a>( layout: &'a Layout, db: &dyn HirDatabase, - krate: CrateId, + trait_env: Arc, b: &[u8], e: EnumId, ) -> Option<(LocalEnumVariantId, &'a Layout)> { + let krate = trait_env.krate; let (var_id, var_layout) = match &layout.variants { hir_def::layout::Variants::Single { index } => (index.0, &*layout), hir_def::layout::Variants::Multiple { tag, tag_encoding, variants, .. } => { diff --git a/src/tools/rust-analyzer/crates/hir/src/lib.rs b/src/tools/rust-analyzer/crates/hir/src/lib.rs index f8d9398ae2c5..b094bb7a0688 100644 --- a/src/tools/rust-analyzer/crates/hir/src/lib.rs +++ b/src/tools/rust-analyzer/crates/hir/src/lib.rs @@ -378,11 +378,6 @@ impl ModuleDef { ModuleDef::BuiltinType(_) | ModuleDef::Macro(_) => return Vec::new(), }; - let module = match self.module(db) { - Some(it) => it, - None => return Vec::new(), - }; - let mut acc = Vec::new(); match self.as_def_with_body() { @@ -390,7 +385,7 @@ impl ModuleDef { def.diagnostics(db, &mut acc); } None => { - for diag in hir_ty::diagnostics::incorrect_case(db, module.id.krate(), id) { + for diag in hir_ty::diagnostics::incorrect_case(db, id) { acc.push(diag.into()) } } @@ -965,8 +960,15 @@ impl Field { } pub fn layout(&self, db: &dyn HirDatabase) -> Result { - db.layout_of_ty(self.ty(db).ty.clone(), self.parent.module(db).krate().into()) - .map(|layout| Layout(layout, db.target_data_layout(self.krate(db).into()).unwrap())) + db.layout_of_ty( + self.ty(db).ty.clone(), + db.trait_environment(match hir_def::VariantId::from(self.parent) { + hir_def::VariantId::EnumVariantId(id) => GenericDefId::EnumVariantId(id), + hir_def::VariantId::StructId(id) => GenericDefId::AdtId(id.into()), + hir_def::VariantId::UnionId(id) => GenericDefId::AdtId(id.into()), + }), + ) + .map(|layout| Layout(layout, db.target_data_layout(self.krate(db).into()).unwrap())) } pub fn parent_def(&self, _db: &dyn HirDatabase) -> VariantDef { @@ -1246,8 +1248,12 @@ impl Adt { return Err(LayoutError::HasPlaceholder); } let krate = self.krate(db).id; - db.layout_of_adt(self.into(), Substitution::empty(Interner), krate) - .map(|layout| Layout(layout, db.target_data_layout(krate).unwrap())) + db.layout_of_adt( + self.into(), + Substitution::empty(Interner), + db.trait_environment(self.into()), + ) + .map(|layout| Layout(layout, db.target_data_layout(krate).unwrap())) } /// Turns this ADT into a type. Any type parameters of the ADT will be @@ -1820,7 +1826,7 @@ impl DefWithBody { // FIXME: don't ignore diagnostics for in type const DefWithBody::InTypeConst(_) => return, }; - for diag in hir_ty::diagnostics::incorrect_case(db, krate, def.into()) { + for diag in hir_ty::diagnostics::incorrect_case(db, def.into()) { acc.push(diag.into()) } } @@ -1987,7 +1993,7 @@ impl Function { return r; } }; - let (result, stdout, stderr) = interpret_mir(db, body, false); + let (result, stdout, stderr) = interpret_mir(db, body, false, None); let mut text = match result { Ok(_) => "pass".to_string(), Err(e) => { @@ -2156,7 +2162,7 @@ impl Const { } pub fn render_eval(self, db: &dyn HirDatabase) -> Result { - let c = db.const_eval(self.id.into(), Substitution::empty(Interner))?; + let c = db.const_eval(self.id.into(), Substitution::empty(Interner), None)?; let data = &c.data(Interner); if let TyKind::Scalar(s) = data.ty.kind(Interner) { if matches!(s, Scalar::Int(_) | Scalar::Uint(_)) { @@ -4322,7 +4328,7 @@ impl Type { } pub fn layout(&self, db: &dyn HirDatabase) -> Result { - db.layout_of_ty(self.ty.clone(), self.env.krate) + db.layout_of_ty(self.ty.clone(), self.env.clone()) .map(|layout| Layout(layout, db.target_data_layout(self.env.krate).unwrap())) } } diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/change_visibility.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/change_visibility.rs index 2b1d8f6f0132..e6179ab8b1ba 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/change_visibility.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/change_visibility.rs @@ -2,9 +2,10 @@ use syntax::{ ast::{self, HasName, HasVisibility}, AstNode, SyntaxKind::{ - CONST, ENUM, FN, MACRO_DEF, MODULE, STATIC, STRUCT, TRAIT, TYPE_ALIAS, USE, VISIBILITY, + self, ASSOC_ITEM_LIST, CONST, ENUM, FN, MACRO_DEF, MODULE, SOURCE_FILE, STATIC, STRUCT, + TRAIT, TYPE_ALIAS, USE, VISIBILITY, }, - T, + SyntaxNode, T, }; use crate::{utils::vis_offset, AssistContext, AssistId, AssistKind, Assists}; @@ -46,13 +47,11 @@ fn add_vis(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()> { let (offset, target) = if let Some(keyword) = item_keyword { let parent = keyword.parent()?; - let def_kws = - vec![CONST, STATIC, TYPE_ALIAS, FN, MODULE, STRUCT, ENUM, TRAIT, USE, MACRO_DEF]; - // Parent is not a definition, can't add visibility - if !def_kws.iter().any(|&def_kw| def_kw == parent.kind()) { + + if !can_add(&parent) { return None; } - // Already have visibility, do nothing + // Already has visibility, do nothing if parent.children().any(|child| child.kind() == VISIBILITY) { return None; } @@ -86,6 +85,29 @@ fn add_vis(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()> { ) } +fn can_add(node: &SyntaxNode) -> bool { + const LEGAL: &[SyntaxKind] = + &[CONST, STATIC, TYPE_ALIAS, FN, MODULE, STRUCT, ENUM, TRAIT, USE, MACRO_DEF]; + + LEGAL.contains(&node.kind()) && { + let Some(p) = node.parent() else { + return false; + }; + + if p.kind() == ASSOC_ITEM_LIST { + p.parent() + .and_then(|it| ast::Impl::cast(it)) + // inherent impls i.e 'non-trait impls' have a non-local + // effect, thus can have visibility even when nested. + // so filter them out + .filter(|imp| imp.for_token().is_none()) + .is_some() + } else { + matches!(p.kind(), SOURCE_FILE | MODULE) + } + } +} + fn change_vis(acc: &mut Assists, vis: ast::Visibility) -> Option<()> { if vis.syntax().text() == "pub" { let target = vis.syntax().text_range(); @@ -129,6 +151,16 @@ mod tests { check_assist(change_visibility, "unsafe f$0n foo() {}", "pub(crate) unsafe fn foo() {}"); check_assist(change_visibility, "$0macro foo() {}", "pub(crate) macro foo() {}"); check_assist(change_visibility, "$0use foo;", "pub(crate) use foo;"); + check_assist( + change_visibility, + "impl Foo { f$0n foo() {} }", + "impl Foo { pub(crate) fn foo() {} }", + ); + check_assist( + change_visibility, + "fn bar() { impl Foo { f$0n foo() {} } }", + "fn bar() { impl Foo { pub(crate) fn foo() {} } }", + ); } #[test] @@ -213,4 +245,33 @@ mod tests { check_assist_target(change_visibility, "pub(crate)$0 fn foo() {}", "pub(crate)"); check_assist_target(change_visibility, "struct S { $0field: u32 }", "field"); } + + #[test] + fn not_applicable_for_items_within_traits() { + check_assist_not_applicable(change_visibility, "trait Foo { f$0n run() {} }"); + check_assist_not_applicable(change_visibility, "trait Foo { con$0st FOO: u8 = 69; }"); + check_assist_not_applicable(change_visibility, "impl Foo for Bar { f$0n quox() {} }"); + } + + #[test] + fn not_applicable_for_items_within_fns() { + check_assist_not_applicable(change_visibility, "fn foo() { f$0n inner() {} }"); + check_assist_not_applicable(change_visibility, "fn foo() { unsafe f$0n inner() {} }"); + check_assist_not_applicable(change_visibility, "fn foo() { const f$0n inner() {} }"); + check_assist_not_applicable(change_visibility, "fn foo() { con$0st FOO: u8 = 69; }"); + check_assist_not_applicable(change_visibility, "fn foo() { en$0um Foo {} }"); + check_assist_not_applicable(change_visibility, "fn foo() { stru$0ct Foo {} }"); + check_assist_not_applicable(change_visibility, "fn foo() { mo$0d foo {} }"); + check_assist_not_applicable(change_visibility, "fn foo() { $0use foo; }"); + check_assist_not_applicable(change_visibility, "fn foo() { $0type Foo = Bar; }"); + check_assist_not_applicable(change_visibility, "fn foo() { tr$0ait Foo {} }"); + check_assist_not_applicable( + change_visibility, + "fn foo() { impl Trait for Bar { f$0n bar() {} } }", + ); + check_assist_not_applicable( + change_visibility, + "fn foo() { impl Trait for Bar { con$0st FOO: u8 = 69; } }", + ); + } } diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/incorrect_case.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/incorrect_case.rs index 92fd4f71ca5d..235062bf531f 100644 --- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/incorrect_case.rs +++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/incorrect_case.rs @@ -545,4 +545,100 @@ pub static SomeStatic: u8 = 10; "#, ); } + + #[test] + fn fn_inner_items() { + check_diagnostics( + r#" +fn main() { + const foo: bool = true; + //^^^ 💡 warn: Constant `foo` should have UPPER_SNAKE_CASE name, e.g. `FOO` + static bar: bool = true; + //^^^ 💡 warn: Static variable `bar` should have UPPER_SNAKE_CASE name, e.g. `BAR` + fn BAZ() { + //^^^ 💡 warn: Function `BAZ` should have snake_case name, e.g. `baz` + const foo: bool = true; + //^^^ 💡 warn: Constant `foo` should have UPPER_SNAKE_CASE name, e.g. `FOO` + static bar: bool = true; + //^^^ 💡 warn: Static variable `bar` should have UPPER_SNAKE_CASE name, e.g. `BAR` + fn BAZ() { + //^^^ 💡 warn: Function `BAZ` should have snake_case name, e.g. `baz` + let INNER_INNER = 42; + //^^^^^^^^^^^ 💡 warn: Variable `INNER_INNER` should have snake_case name, e.g. `inner_inner` + } + + let INNER_LOCAL = 42; + //^^^^^^^^^^^ 💡 warn: Variable `INNER_LOCAL` should have snake_case name, e.g. `inner_local` + } +} +"#, + ); + } + + #[test] + fn const_body_inner_items() { + check_diagnostics( + r#" +const _: () = { + static bar: bool = true; + //^^^ 💡 warn: Static variable `bar` should have UPPER_SNAKE_CASE name, e.g. `BAR` + fn BAZ() {} + //^^^ 💡 warn: Function `BAZ` should have snake_case name, e.g. `baz` + + const foo: () = { + //^^^ 💡 warn: Constant `foo` should have UPPER_SNAKE_CASE name, e.g. `FOO` + const foo: bool = true; + //^^^ 💡 warn: Constant `foo` should have UPPER_SNAKE_CASE name, e.g. `FOO` + static bar: bool = true; + //^^^ 💡 warn: Static variable `bar` should have UPPER_SNAKE_CASE name, e.g. `BAR` + fn BAZ() {} + //^^^ 💡 warn: Function `BAZ` should have snake_case name, e.g. `baz` + }; +}; +"#, + ); + } + + #[test] + fn static_body_inner_items() { + check_diagnostics( + r#" +static FOO: () = { + const foo: bool = true; + //^^^ 💡 warn: Constant `foo` should have UPPER_SNAKE_CASE name, e.g. `FOO` + fn BAZ() {} + //^^^ 💡 warn: Function `BAZ` should have snake_case name, e.g. `baz` + + static bar: () = { + //^^^ 💡 warn: Static variable `bar` should have UPPER_SNAKE_CASE name, e.g. `BAR` + const foo: bool = true; + //^^^ 💡 warn: Constant `foo` should have UPPER_SNAKE_CASE name, e.g. `FOO` + static bar: bool = true; + //^^^ 💡 warn: Static variable `bar` should have UPPER_SNAKE_CASE name, e.g. `BAR` + fn BAZ() {} + //^^^ 💡 warn: Function `BAZ` should have snake_case name, e.g. `baz` + }; +}; +"#, + ); + } + + #[test] + fn enum_variant_body_inner_item() { + check_diagnostics( + r#" +enum E { + A = { + const foo: bool = true; + //^^^ 💡 warn: Constant `foo` should have UPPER_SNAKE_CASE name, e.g. `FOO` + static bar: bool = true; + //^^^ 💡 warn: Static variable `bar` should have UPPER_SNAKE_CASE name, e.g. `BAR` + fn BAZ() {} + //^^^ 💡 warn: Function `BAZ` should have snake_case name, e.g. `baz` + 42 + }, +} +"#, + ); + } } diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting.rs b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting.rs index 577bd2bc1f89..ae97236409eb 100644 --- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting.rs +++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting.rs @@ -24,7 +24,7 @@ use syntax::{ use crate::{ syntax_highlighting::{ - escape::{highlight_escape_char, highlight_escape_string}, + escape::{highlight_escape_byte, highlight_escape_char, highlight_escape_string}, format::highlight_format_string, highlights::Highlights, macro_::MacroHighlighter, @@ -471,6 +471,14 @@ fn traverse( }; highlight_escape_char(hl, &char, range.start()) + } else if ast::Byte::can_cast(token.kind()) + && ast::Byte::can_cast(descended_token.kind()) + { + let Some(byte) = ast::Byte::cast(token) else { + continue; + }; + + highlight_escape_byte(hl, &byte, range.start()) } } diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/escape.rs b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/escape.rs index 211e3588095c..5913ca5e454c 100644 --- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/escape.rs +++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/escape.rs @@ -1,7 +1,7 @@ //! Syntax highlighting for escape sequences use crate::syntax_highlighting::highlights::Highlights; use crate::{HlRange, HlTag}; -use syntax::ast::{Char, IsString}; +use syntax::ast::{Byte, Char, IsString}; use syntax::{AstToken, TextRange, TextSize}; pub(super) fn highlight_escape_string( @@ -10,14 +10,14 @@ pub(super) fn highlight_escape_string( start: TextSize, ) { string.escaped_char_ranges(&mut |piece_range, char| { - if char.is_err() { - return; - } - if string.text()[piece_range.start().into()..].starts_with('\\') { + let highlight = match char { + Ok(_) => HlTag::EscapeSequence, + Err(_) => HlTag::InvalidEscapeSequence, + }; stack.add(HlRange { range: piece_range + start, - highlight: HlTag::EscapeSequence.into(), + highlight: highlight.into(), binding_hash: None, }); } @@ -26,6 +26,9 @@ pub(super) fn highlight_escape_string( pub(super) fn highlight_escape_char(stack: &mut Highlights, char: &Char, start: TextSize) { if char.value().is_none() { + // We do not emit invalid escapes highlighting here. The lexer would likely be in a bad + // state and this token contains junks, since `'` is not a reliable delimiter (consider + // lifetimes). Nonetheless, parser errors should already be emitted. return; } @@ -43,3 +46,24 @@ pub(super) fn highlight_escape_char(stack: &mut Highlights, char: &Char, start: TextRange::new(start + TextSize::from(1), start + TextSize::from(text.len() as u32 + 1)); stack.add(HlRange { range, highlight: HlTag::EscapeSequence.into(), binding_hash: None }) } + +pub(super) fn highlight_escape_byte(stack: &mut Highlights, byte: &Byte, start: TextSize) { + if byte.value().is_none() { + // See `highlight_escape_char` for why no error highlighting here. + return; + } + + let text = byte.text(); + if !text.starts_with("b'") || !text.ends_with('\'') { + return; + } + + let text = &text[2..text.len() - 1]; + if !text.starts_with('\\') { + return; + } + + let range = + TextRange::new(start + TextSize::from(2), start + TextSize::from(text.len() as u32 + 2)); + stack.add(HlRange { range, highlight: HlTag::EscapeSequence.into(), binding_hash: None }) +} diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/html.rs b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/html.rs index 2c7823069b3f..bbc6b55a6422 100644 --- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/html.rs +++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/html.rs @@ -109,6 +109,7 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd .control { font-style: italic; } .reference { font-style: italic; font-weight: bold; } -.unresolved_reference { color: #FC5555; text-decoration: wavy underline; } +.invalid_escape_sequence { color: #FC5555; text-decoration: wavy underline; } +.unresolved_reference { color: #FC5555; text-decoration: wavy underline; } "; diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/tags.rs b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/tags.rs index f983109115f6..6d4cdd0efe21 100644 --- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/tags.rs +++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/tags.rs @@ -29,6 +29,7 @@ pub enum HlTag { Comment, EscapeSequence, FormatSpecifier, + InvalidEscapeSequence, Keyword, NumericLiteral, Operator(HlOperator), @@ -166,6 +167,7 @@ impl HlTag { HlTag::CharLiteral => "char_literal", HlTag::Comment => "comment", HlTag::EscapeSequence => "escape_sequence", + HlTag::InvalidEscapeSequence => "invalid_escape_sequence", HlTag::FormatSpecifier => "format_specifier", HlTag::Keyword => "keyword", HlTag::Punctuation(punct) => match punct { diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_assoc_functions.html b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_assoc_functions.html index 9ed65fbc8548..4dcbfe4eb62c 100644 --- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_assoc_functions.html +++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_assoc_functions.html @@ -40,7 +40,8 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd .control { font-style: italic; } .reference { font-style: italic; font-weight: bold; } -.unresolved_reference { color: #FC5555; text-decoration: wavy underline; } +.invalid_escape_sequence { color: #FC5555; text-decoration: wavy underline; } +.unresolved_reference { color: #FC5555; text-decoration: wavy underline; }

fn not_static() {}
 
diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_attributes.html b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_attributes.html
index 567ab8ccc11d..bf5505caf376 100644
--- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_attributes.html
+++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_attributes.html
@@ -40,7 +40,8 @@ pre                 { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
 .control            { font-style: italic; }
 .reference          { font-style: italic; font-weight: bold; }
 
-.unresolved_reference { color: #FC5555; text-decoration: wavy underline; }
+.invalid_escape_sequence { color: #FC5555; text-decoration: wavy underline; }
+.unresolved_reference    { color: #FC5555; text-decoration: wavy underline; }
 
 
#[allow(dead_code)]
 #[rustfmt::skip]
diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_crate_root.html b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_crate_root.html
index 1e4c06df7ea0..0d1b3c1f1831 100644
--- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_crate_root.html
+++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_crate_root.html
@@ -40,7 +40,8 @@ pre                 { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
 .control            { font-style: italic; }
 .reference          { font-style: italic; font-weight: bold; }
 
-.unresolved_reference { color: #FC5555; text-decoration: wavy underline; }
+.invalid_escape_sequence { color: #FC5555; text-decoration: wavy underline; }
+.unresolved_reference    { color: #FC5555; text-decoration: wavy underline; }
 
 
extern crate foo;
 use core::iter;
diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_default_library.html b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_default_library.html
index 5d66f832daf9..dd1528ed03f0 100644
--- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_default_library.html
+++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_default_library.html
@@ -40,7 +40,8 @@ pre                 { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
 .control            { font-style: italic; }
 .reference          { font-style: italic; font-weight: bold; }
 
-.unresolved_reference { color: #FC5555; text-decoration: wavy underline; }
+.invalid_escape_sequence { color: #FC5555; text-decoration: wavy underline; }
+.unresolved_reference    { color: #FC5555; text-decoration: wavy underline; }
 
 
use core::iter;
 
diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_doctest.html b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_doctest.html
index 35f240d42847..d5f92aa5d478 100644
--- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_doctest.html
+++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_doctest.html
@@ -40,7 +40,8 @@ pre                 { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
 .control            { font-style: italic; }
 .reference          { font-style: italic; font-weight: bold; }
 
-.unresolved_reference { color: #FC5555; text-decoration: wavy underline; }
+.invalid_escape_sequence { color: #FC5555; text-decoration: wavy underline; }
+.unresolved_reference    { color: #FC5555; text-decoration: wavy underline; }
 
 
//! This is a module to test doc injection.
 //! ```
diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_extern_crate.html b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_extern_crate.html
index 87b9da46e2cc..b15f7bca72b9 100644
--- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_extern_crate.html
+++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_extern_crate.html
@@ -40,7 +40,8 @@ pre                 { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
 .control            { font-style: italic; }
 .reference          { font-style: italic; font-weight: bold; }
 
-.unresolved_reference { color: #FC5555; text-decoration: wavy underline; }
+.invalid_escape_sequence { color: #FC5555; text-decoration: wavy underline; }
+.unresolved_reference    { color: #FC5555; text-decoration: wavy underline; }
 
 
extern crate std;
 extern crate alloc as abc;
diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_general.html b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_general.html
index 6b049f379ac1..bdeb09d2f83c 100644
--- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_general.html
+++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_general.html
@@ -40,7 +40,8 @@ pre                 { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
 .control            { font-style: italic; }
 .reference          { font-style: italic; font-weight: bold; }
 
-.unresolved_reference { color: #FC5555; text-decoration: wavy underline; }
+.invalid_escape_sequence { color: #FC5555; text-decoration: wavy underline; }
+.unresolved_reference    { color: #FC5555; text-decoration: wavy underline; }
 
 
use inner::{self as inner_mod};
 mod inner {}
diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_injection.html b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_injection.html
index d9c3db6fbb51..f9c33b8a6017 100644
--- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_injection.html
+++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_injection.html
@@ -40,7 +40,8 @@ pre                 { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
 .control            { font-style: italic; }
 .reference          { font-style: italic; font-weight: bold; }
 
-.unresolved_reference { color: #FC5555; text-decoration: wavy underline; }
+.invalid_escape_sequence { color: #FC5555; text-decoration: wavy underline; }
+.unresolved_reference    { color: #FC5555; text-decoration: wavy underline; }
 
 
fn fixture(ra_fixture: &str) {}
 
diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_keywords.html b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_keywords.html
index 3900959bedf8..fd3b39855e20 100644
--- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_keywords.html
+++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_keywords.html
@@ -40,7 +40,8 @@ pre                 { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
 .control            { font-style: italic; }
 .reference          { font-style: italic; font-weight: bold; }
 
-.unresolved_reference { color: #FC5555; text-decoration: wavy underline; }
+.invalid_escape_sequence { color: #FC5555; text-decoration: wavy underline; }
+.unresolved_reference    { color: #FC5555; text-decoration: wavy underline; }
 
 
extern crate self;
 
diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_lifetimes.html b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_lifetimes.html
index f98e0b1cda6e..ec39998de268 100644
--- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_lifetimes.html
+++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_lifetimes.html
@@ -40,7 +40,8 @@ pre                 { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
 .control            { font-style: italic; }
 .reference          { font-style: italic; font-weight: bold; }
 
-.unresolved_reference { color: #FC5555; text-decoration: wavy underline; }
+.invalid_escape_sequence { color: #FC5555; text-decoration: wavy underline; }
+.unresolved_reference    { color: #FC5555; text-decoration: wavy underline; }
 
 

 #[derive()]
diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_macros.html b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_macros.html
index 2cbbf6964152..c5fcec756808 100644
--- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_macros.html
+++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_macros.html
@@ -40,7 +40,8 @@ pre                 { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
 .control            { font-style: italic; }
 .reference          { font-style: italic; font-weight: bold; }
 
-.unresolved_reference { color: #FC5555; text-decoration: wavy underline; }
+.invalid_escape_sequence { color: #FC5555; text-decoration: wavy underline; }
+.unresolved_reference    { color: #FC5555; text-decoration: wavy underline; }
 
 
proc_macros::mirror! {
     {
diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_module_docs_inline.html b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_module_docs_inline.html
index 8a1d69816e68..4dcf8e5f01f9 100644
--- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_module_docs_inline.html
+++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_module_docs_inline.html
@@ -40,7 +40,8 @@ pre                 { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
 .control            { font-style: italic; }
 .reference          { font-style: italic; font-weight: bold; }
 
-.unresolved_reference { color: #FC5555; text-decoration: wavy underline; }
+.invalid_escape_sequence { color: #FC5555; text-decoration: wavy underline; }
+.unresolved_reference    { color: #FC5555; text-decoration: wavy underline; }
 
 
//! [Struct]
 //! This is an intra doc injection test for modules
diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_module_docs_outline.html b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_module_docs_outline.html
index c4c3e3dc2606..084bbf2f7420 100644
--- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_module_docs_outline.html
+++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_module_docs_outline.html
@@ -40,7 +40,8 @@ pre                 { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
 .control            { font-style: italic; }
 .reference          { font-style: italic; font-weight: bold; }
 
-.unresolved_reference { color: #FC5555; text-decoration: wavy underline; }
+.invalid_escape_sequence { color: #FC5555; text-decoration: wavy underline; }
+.unresolved_reference    { color: #FC5555; text-decoration: wavy underline; }
 
 
/// [crate::foo::Struct]
 /// This is an intra doc injection test for modules
diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_operators.html b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_operators.html
index 2369071ae2aa..1af4bcfbd9dd 100644
--- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_operators.html
+++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_operators.html
@@ -40,7 +40,8 @@ pre                 { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
 .control            { font-style: italic; }
 .reference          { font-style: italic; font-weight: bold; }
 
-.unresolved_reference { color: #FC5555; text-decoration: wavy underline; }
+.invalid_escape_sequence { color: #FC5555; text-decoration: wavy underline; }
+.unresolved_reference    { color: #FC5555; text-decoration: wavy underline; }
 
 
fn main() {
     1 + 1 - 1 * 1 / 1 % 1 | 1 & 1 ! 1 ^ 1 >> 1 << 1;
diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_rainbow.html b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_rainbow.html
index bff35c897e1d..ec18c3ea1f9b 100644
--- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_rainbow.html
+++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_rainbow.html
@@ -40,7 +40,8 @@ pre                 { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
 .control            { font-style: italic; }
 .reference          { font-style: italic; font-weight: bold; }
 
-.unresolved_reference { color: #FC5555; text-decoration: wavy underline; }
+.invalid_escape_sequence { color: #FC5555; text-decoration: wavy underline; }
+.unresolved_reference    { color: #FC5555; text-decoration: wavy underline; }
 
 
fn main() {
     let hello = "hello";
diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_strings.html b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_strings.html
index f4f164aa1de6..dcac8eb73689 100644
--- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_strings.html
+++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_strings.html
@@ -40,7 +40,8 @@ pre                 { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
 .control            { font-style: italic; }
 .reference          { font-style: italic; font-weight: bold; }
 
-.unresolved_reference { color: #FC5555; text-decoration: wavy underline; }
+.invalid_escape_sequence { color: #FC5555; text-decoration: wavy underline; }
+.unresolved_reference    { color: #FC5555; text-decoration: wavy underline; }
 
 
macro_rules! println {
     ($($arg:tt)*) => ({
@@ -105,6 +106,8 @@ pre                 { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
     let a = '\x65';
     let a = '\x00';
 
+    let a = b'\xFF';
+
     println!("Hello {{Hello}}");
     // from https://doc.rust-lang.org/std/fmt/index.html
     println!("Hello");                 // => "Hello"
@@ -159,8 +162,9 @@ pre                 { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
     println!("Hello\nWorld");
     println!("\u{48}\x65\x6C\x6C\x6F World");
 
-    let _ = "\x28\x28\x00\x63\n";
-    let _ = b"\x28\x28\x00\x63\n";
+    let _ = "\x28\x28\x00\x63\xFF\u{FF}\n"; // invalid non-UTF8 escape sequences
+    let _ = b"\x28\x28\x00\x63\xFF\u{FF}\n"; // valid bytes, invalid unicodes
+    let _ = c"\u{FF}\xFF"; // valid bytes, valid unicodes
     let backslash = r"\\";
 
     println!("{\x41}", A = 92);
diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_unsafe.html b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_unsafe.html
index 654d51b8a43d..c72ea54e948e 100644
--- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_unsafe.html
+++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_unsafe.html
@@ -40,7 +40,8 @@ pre                 { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
 .control            { font-style: italic; }
 .reference          { font-style: italic; font-weight: bold; }
 
-.unresolved_reference { color: #FC5555; text-decoration: wavy underline; }
+.invalid_escape_sequence { color: #FC5555; text-decoration: wavy underline; }
+.unresolved_reference    { color: #FC5555; text-decoration: wavy underline; }
 
 
macro_rules! id {
     ($($tt:tt)*) => {
diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/tests.rs b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/tests.rs
index 1ee451a06d04..696aa5900252 100644
--- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/tests.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/tests.rs
@@ -451,6 +451,8 @@ fn main() {
     let a = '\x65';
     let a = '\x00';
 
+    let a = b'\xFF';
+
     println!("Hello {{Hello}}");
     // from https://doc.rust-lang.org/std/fmt/index.html
     println!("Hello");                 // => "Hello"
@@ -505,8 +507,9 @@ fn main() {
     println!("Hello\nWorld");
     println!("\u{48}\x65\x6C\x6C\x6F World");
 
-    let _ = "\x28\x28\x00\x63\n";
-    let _ = b"\x28\x28\x00\x63\n";
+    let _ = "\x28\x28\x00\x63\xFF\u{FF}\n"; // invalid non-UTF8 escape sequences
+    let _ = b"\x28\x28\x00\x63\xFF\u{FF}\n"; // valid bytes, invalid unicodes
+    let _ = c"\u{FF}\xFF"; // valid bytes, valid unicodes
     let backslash = r"\\";
 
     println!("{\x41}", A = 92);
diff --git a/src/tools/rust-analyzer/crates/parser/src/grammar.rs b/src/tools/rust-analyzer/crates/parser/src/grammar.rs
index 1814e0e54c59..a868419821d8 100644
--- a/src/tools/rust-analyzer/crates/parser/src/grammar.rs
+++ b/src/tools/rust-analyzer/crates/parser/src/grammar.rs
@@ -211,70 +211,54 @@ impl BlockLike {
 const VISIBILITY_FIRST: TokenSet = TokenSet::new(&[T![pub], T![crate]]);
 
 fn opt_visibility(p: &mut Parser<'_>, in_tuple_field: bool) -> bool {
-    match p.current() {
-        T![pub] => {
-            let m = p.start();
-            p.bump(T![pub]);
-            if p.at(T!['(']) {
-                match p.nth(1) {
-                    // test crate_visibility
-                    // pub(crate) struct S;
-                    // pub(self) struct S;
-                    // pub(super) struct S;
+    if !p.at(T![pub]) {
+        return false;
+    }
 
-                    // test_err crate_visibility_empty_recover
-                    // pub() struct S;
+    let m = p.start();
+    p.bump(T![pub]);
+    if p.at(T!['(']) {
+        match p.nth(1) {
+            // test crate_visibility
+            // pub(crate) struct S;
+            // pub(self) struct S;
+            // pub(super) struct S;
 
-                    // test pub_parens_typepath
-                    // struct B(pub (super::A));
-                    // struct B(pub (crate::A,));
-                    T![crate] | T![self] | T![super] | T![ident] | T![')'] if p.nth(2) != T![:] => {
-                        // If we are in a tuple struct, then the parens following `pub`
-                        // might be an tuple field, not part of the visibility. So in that
-                        // case we don't want to consume an identifier.
+            // test_err crate_visibility_empty_recover
+            // pub() struct S;
 
-                        // test pub_tuple_field
-                        // struct MyStruct(pub (u32, u32));
-                        // struct MyStruct(pub (u32));
-                        // struct MyStruct(pub ());
-                        if !(in_tuple_field && matches!(p.nth(1), T![ident] | T![')'])) {
-                            p.bump(T!['(']);
-                            paths::use_path(p);
-                            p.expect(T![')']);
-                        }
-                    }
-                    // test crate_visibility_in
-                    // pub(in super::A) struct S;
-                    // pub(in crate) struct S;
-                    T![in] => {
-                        p.bump(T!['(']);
-                        p.bump(T![in]);
-                        paths::use_path(p);
-                        p.expect(T![')']);
-                    }
-                    _ => {}
+            // test pub_parens_typepath
+            // struct B(pub (super::A));
+            // struct B(pub (crate::A,));
+            T![crate] | T![self] | T![super] | T![ident] | T![')'] if p.nth(2) != T![:] => {
+                // If we are in a tuple struct, then the parens following `pub`
+                // might be an tuple field, not part of the visibility. So in that
+                // case we don't want to consume an identifier.
+
+                // test pub_tuple_field
+                // struct MyStruct(pub (u32, u32));
+                // struct MyStruct(pub (u32));
+                // struct MyStruct(pub ());
+                if !(in_tuple_field && matches!(p.nth(1), T![ident] | T![')'])) {
+                    p.bump(T!['(']);
+                    paths::use_path(p);
+                    p.expect(T![')']);
                 }
             }
-            m.complete(p, VISIBILITY);
-            true
-        }
-        // test crate_keyword_vis
-        // crate fn main() { }
-        // struct S { crate field: u32 }
-        // struct T(crate u32);
-        T![crate] => {
-            if p.nth_at(1, T![::]) {
-                // test crate_keyword_path
-                // fn foo() { crate::foo(); }
-                return false;
+            // test crate_visibility_in
+            // pub(in super::A) struct S;
+            // pub(in crate) struct S;
+            T![in] => {
+                p.bump(T!['(']);
+                p.bump(T![in]);
+                paths::use_path(p);
+                p.expect(T![')']);
             }
-            let m = p.start();
-            p.bump(T![crate]);
-            m.complete(p, VISIBILITY);
-            true
+            _ => {}
         }
-        _ => false,
     }
+    m.complete(p, VISIBILITY);
+    true
 }
 
 fn opt_rename(p: &mut Parser<'_>) {
diff --git a/src/tools/rust-analyzer/crates/parser/src/tests/prefix_entries.rs b/src/tools/rust-analyzer/crates/parser/src/tests/prefix_entries.rs
index 11f9c34abdf1..2f3c7febc040 100644
--- a/src/tools/rust-analyzer/crates/parser/src/tests/prefix_entries.rs
+++ b/src/tools/rust-analyzer/crates/parser/src/tests/prefix_entries.rs
@@ -6,7 +6,6 @@ fn vis() {
     check(PrefixEntryPoint::Vis, "fn foo() {}", "");
     check(PrefixEntryPoint::Vis, "pub(fn foo() {}", "pub");
     check(PrefixEntryPoint::Vis, "pub(crate fn foo() {}", "pub(crate");
-    check(PrefixEntryPoint::Vis, "crate fn foo() {}", "crate");
 }
 
 #[test]
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0040_crate_keyword_vis.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0040_crate_keyword_vis.rast
deleted file mode 100644
index 07b0210e44d0..000000000000
--- a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0040_crate_keyword_vis.rast
+++ /dev/null
@@ -1,63 +0,0 @@
-SOURCE_FILE
-  FN
-    VISIBILITY
-      CRATE_KW "crate"
-    WHITESPACE " "
-    FN_KW "fn"
-    WHITESPACE " "
-    NAME
-      IDENT "main"
-    PARAM_LIST
-      L_PAREN "("
-      R_PAREN ")"
-    WHITESPACE " "
-    BLOCK_EXPR
-      STMT_LIST
-        L_CURLY "{"
-        WHITESPACE " "
-        R_CURLY "}"
-  WHITESPACE "\n"
-  STRUCT
-    STRUCT_KW "struct"
-    WHITESPACE " "
-    NAME
-      IDENT "S"
-    WHITESPACE " "
-    RECORD_FIELD_LIST
-      L_CURLY "{"
-      WHITESPACE " "
-      RECORD_FIELD
-        VISIBILITY
-          CRATE_KW "crate"
-        WHITESPACE " "
-        NAME
-          IDENT "field"
-        COLON ":"
-        WHITESPACE " "
-        PATH_TYPE
-          PATH
-            PATH_SEGMENT
-              NAME_REF
-                IDENT "u32"
-      WHITESPACE " "
-      R_CURLY "}"
-  WHITESPACE "\n"
-  STRUCT
-    STRUCT_KW "struct"
-    WHITESPACE " "
-    NAME
-      IDENT "T"
-    TUPLE_FIELD_LIST
-      L_PAREN "("
-      TUPLE_FIELD
-        VISIBILITY
-          CRATE_KW "crate"
-        WHITESPACE " "
-        PATH_TYPE
-          PATH
-            PATH_SEGMENT
-              NAME_REF
-                IDENT "u32"
-      R_PAREN ")"
-    SEMICOLON ";"
-  WHITESPACE "\n"
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0040_crate_keyword_vis.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0040_crate_keyword_vis.rs
deleted file mode 100644
index e2b5f2161dfc..000000000000
--- a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0040_crate_keyword_vis.rs
+++ /dev/null
@@ -1,3 +0,0 @@
-crate fn main() { }
-struct S { crate field: u32 }
-struct T(crate u32);
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0125_crate_keyword_path.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0125_crate_keyword_path.rast
deleted file mode 100644
index 8d9b61630ae6..000000000000
--- a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0125_crate_keyword_path.rast
+++ /dev/null
@@ -1,33 +0,0 @@
-SOURCE_FILE
-  FN
-    FN_KW "fn"
-    WHITESPACE " "
-    NAME
-      IDENT "foo"
-    PARAM_LIST
-      L_PAREN "("
-      R_PAREN ")"
-    WHITESPACE " "
-    BLOCK_EXPR
-      STMT_LIST
-        L_CURLY "{"
-        WHITESPACE " "
-        EXPR_STMT
-          CALL_EXPR
-            PATH_EXPR
-              PATH
-                PATH
-                  PATH_SEGMENT
-                    NAME_REF
-                      CRATE_KW "crate"
-                COLON2 "::"
-                PATH_SEGMENT
-                  NAME_REF
-                    IDENT "foo"
-            ARG_LIST
-              L_PAREN "("
-              R_PAREN ")"
-          SEMICOLON ";"
-        WHITESPACE " "
-        R_CURLY "}"
-  WHITESPACE "\n"
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0125_crate_keyword_path.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0125_crate_keyword_path.rs
deleted file mode 100644
index 0f454d121d69..000000000000
--- a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0125_crate_keyword_path.rs
+++ /dev/null
@@ -1 +0,0 @@
-fn foo() { crate::foo(); }
diff --git a/src/tools/rust-analyzer/crates/project-model/src/cargo_workspace.rs b/src/tools/rust-analyzer/crates/project-model/src/cargo_workspace.rs
index e1117ac464bd..e47808a2cc9f 100644
--- a/src/tools/rust-analyzer/crates/project-model/src/cargo_workspace.rs
+++ b/src/tools/rust-analyzer/crates/project-model/src/cargo_workspace.rs
@@ -145,7 +145,7 @@ pub struct PackageDependency {
     pub kind: DepKind,
 }
 
-#[derive(Debug, Clone, Eq, PartialEq, PartialOrd, Ord)]
+#[derive(Debug, Clone, Copy, PartialEq, Eq)]
 pub enum DepKind {
     /// Available to the library, binary, and dev targets in the package (but not the build script).
     Normal,
@@ -156,23 +156,20 @@ pub enum DepKind {
 }
 
 impl DepKind {
-    fn iter(list: &[cargo_metadata::DepKindInfo]) -> impl Iterator + '_ {
-        let mut dep_kinds = Vec::new();
+    fn iter(list: &[cargo_metadata::DepKindInfo]) -> impl Iterator {
+        let mut dep_kinds = [None; 3];
         if list.is_empty() {
-            dep_kinds.push(Self::Normal);
+            dep_kinds[0] = Some(Self::Normal);
         }
         for info in list {
-            let kind = match info.kind {
-                cargo_metadata::DependencyKind::Normal => Self::Normal,
-                cargo_metadata::DependencyKind::Development => Self::Dev,
-                cargo_metadata::DependencyKind::Build => Self::Build,
+            match info.kind {
+                cargo_metadata::DependencyKind::Normal => dep_kinds[0] = Some(Self::Normal),
+                cargo_metadata::DependencyKind::Development => dep_kinds[1] = Some(Self::Dev),
+                cargo_metadata::DependencyKind::Build => dep_kinds[2] = Some(Self::Build),
                 cargo_metadata::DependencyKind::Unknown => continue,
-            };
-            dep_kinds.push(kind);
+            }
         }
-        dep_kinds.sort_unstable();
-        dep_kinds.dedup();
-        dep_kinds.into_iter()
+        dep_kinds.into_iter().flatten()
     }
 }
 
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/analysis_stats.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/analysis_stats.rs
index 8d68bf160a2d..33d7b5ed8789 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/analysis_stats.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/analysis_stats.rs
@@ -8,7 +8,7 @@ use std::{
 
 use hir::{
     db::{DefDatabase, ExpandDatabase, HirDatabase},
-    Adt, AssocItem, Crate, DefWithBody, HasCrate, HasSource, HirDisplay, ModuleDef, Name,
+    Adt, AssocItem, Crate, DefWithBody, HasSource, HirDisplay, ModuleDef, Name,
 };
 use hir_def::{
     body::{BodySourceMap, SyntheticSyntax},
@@ -277,7 +277,7 @@ impl flags::AnalysisStats {
             let Err(e) = db.layout_of_adt(
                 hir_def::AdtId::from(a).into(),
                 Substitution::empty(Interner),
-                a.krate(db).into(),
+                db.trait_environment(a.into()),
             ) else {
                 continue;
             };
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/semantic_tokens.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/semantic_tokens.rs
index d4bb20c8f448..1fe02fc7ead0 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/semantic_tokens.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/semantic_tokens.rs
@@ -78,6 +78,7 @@ define_semantic_token_types![
         (DERIVE_HELPER, "deriveHelper") => DECORATOR,
         (DOT, "dot"),
         (ESCAPE_SEQUENCE, "escapeSequence") => STRING,
+        (INVALID_ESCAPE_SEQUENCE, "invalidEscapeSequence") => STRING,
         (FORMAT_SPECIFIER, "formatSpecifier") => STRING,
         (GENERIC, "generic") => TYPE_PARAMETER,
         (LABEL, "label"),
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/to_proto.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/to_proto.rs
index ba3421bf9e76..7a89533a5e92 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/to_proto.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/to_proto.rs
@@ -640,6 +640,7 @@ fn semantic_token_type_and_modifiers(
         HlTag::CharLiteral => semantic_tokens::CHAR,
         HlTag::Comment => semantic_tokens::COMMENT,
         HlTag::EscapeSequence => semantic_tokens::ESCAPE_SEQUENCE,
+        HlTag::InvalidEscapeSequence => semantic_tokens::INVALID_ESCAPE_SEQUENCE,
         HlTag::FormatSpecifier => semantic_tokens::FORMAT_SPECIFIER,
         HlTag::Keyword => semantic_tokens::KEYWORD,
         HlTag::None => semantic_tokens::GENERIC,
diff --git a/src/tools/rust-analyzer/crates/syntax/src/ast/token_ext.rs b/src/tools/rust-analyzer/crates/syntax/src/ast/token_ext.rs
index 090eb89f4704..87fd51d703cf 100644
--- a/src/tools/rust-analyzer/crates/syntax/src/ast/token_ext.rs
+++ b/src/tools/rust-analyzer/crates/syntax/src/ast/token_ext.rs
@@ -2,7 +2,9 @@
 
 use std::borrow::Cow;
 
-use rustc_lexer::unescape::{unescape_byte, unescape_char, unescape_literal, Mode};
+use rustc_lexer::unescape::{
+    unescape_byte, unescape_c_string, unescape_char, unescape_literal, CStrUnit, Mode,
+};
 
 use crate::{
     ast::{self, AstToken},
@@ -146,6 +148,7 @@ impl QuoteOffsets {
 
 pub trait IsString: AstToken {
     const RAW_PREFIX: &'static str;
+    const MODE: Mode;
     fn is_raw(&self) -> bool {
         self.text().starts_with(Self::RAW_PREFIX)
     }
@@ -181,7 +184,7 @@ pub trait IsString: AstToken {
         let text = &self.text()[text_range_no_quotes - start];
         let offset = text_range_no_quotes.start() - start;
 
-        unescape_literal(text, Mode::Str, &mut |range, unescaped_char| {
+        unescape_literal(text, Self::MODE, &mut |range, unescaped_char| {
             let text_range =
                 TextRange::new(range.start.try_into().unwrap(), range.end.try_into().unwrap());
             cb(text_range + offset, unescaped_char);
@@ -196,6 +199,7 @@ pub trait IsString: AstToken {
 
 impl IsString for ast::String {
     const RAW_PREFIX: &'static str = "r";
+    const MODE: Mode = Mode::Str;
 }
 
 impl ast::String {
@@ -213,7 +217,7 @@ impl ast::String {
         let mut buf = String::new();
         let mut prev_end = 0;
         let mut has_error = false;
-        unescape_literal(text, Mode::Str, &mut |char_range, unescaped_char| match (
+        unescape_literal(text, Self::MODE, &mut |char_range, unescaped_char| match (
             unescaped_char,
             buf.capacity() == 0,
         ) {
@@ -239,6 +243,7 @@ impl ast::String {
 
 impl IsString for ast::ByteString {
     const RAW_PREFIX: &'static str = "br";
+    const MODE: Mode = Mode::ByteStr;
 }
 
 impl ast::ByteString {
@@ -256,7 +261,7 @@ impl ast::ByteString {
         let mut buf: Vec = Vec::new();
         let mut prev_end = 0;
         let mut has_error = false;
-        unescape_literal(text, Mode::ByteStr, &mut |char_range, unescaped_char| match (
+        unescape_literal(text, Self::MODE, &mut |char_range, unescaped_char| match (
             unescaped_char,
             buf.capacity() == 0,
         ) {
@@ -282,42 +287,70 @@ impl ast::ByteString {
 
 impl IsString for ast::CString {
     const RAW_PREFIX: &'static str = "cr";
+    const MODE: Mode = Mode::CStr;
+
+    fn escaped_char_ranges(
+        &self,
+        cb: &mut dyn FnMut(TextRange, Result),
+    ) {
+        let text_range_no_quotes = match self.text_range_between_quotes() {
+            Some(it) => it,
+            None => return,
+        };
+
+        let start = self.syntax().text_range().start();
+        let text = &self.text()[text_range_no_quotes - start];
+        let offset = text_range_no_quotes.start() - start;
+
+        unescape_c_string(text, Self::MODE, &mut |range, unescaped_char| {
+            let text_range =
+                TextRange::new(range.start.try_into().unwrap(), range.end.try_into().unwrap());
+            // XXX: This method should only be used for highlighting ranges. The unescaped
+            // char/byte is not used. For simplicity, we return an arbitrary placeholder char.
+            cb(text_range + offset, unescaped_char.map(|_| ' '));
+        });
+    }
 }
 
 impl ast::CString {
-    pub fn value(&self) -> Option> {
+    pub fn value(&self) -> Option> {
         if self.is_raw() {
             let text = self.text();
             let text =
                 &text[self.text_range_between_quotes()? - self.syntax().text_range().start()];
-            return Some(Cow::Borrowed(text));
+            return Some(Cow::Borrowed(text.as_bytes()));
         }
 
         let text = self.text();
         let text = &text[self.text_range_between_quotes()? - self.syntax().text_range().start()];
 
-        let mut buf = String::new();
+        let mut buf = Vec::new();
         let mut prev_end = 0;
         let mut has_error = false;
-        unescape_literal(text, Mode::Str, &mut |char_range, unescaped_char| match (
-            unescaped_char,
+        let mut char_buf = [0u8; 4];
+        let mut extend_unit = |buf: &mut Vec, unit: CStrUnit| match unit {
+            CStrUnit::Byte(b) => buf.push(b),
+            CStrUnit::Char(c) => buf.extend(c.encode_utf8(&mut char_buf).as_bytes()),
+        };
+        unescape_c_string(text, Self::MODE, &mut |char_range, unescaped| match (
+            unescaped,
             buf.capacity() == 0,
         ) {
-            (Ok(c), false) => buf.push(c),
+            (Ok(u), false) => extend_unit(&mut buf, u),
             (Ok(_), true) if char_range.len() == 1 && char_range.start == prev_end => {
                 prev_end = char_range.end
             }
-            (Ok(c), true) => {
+            (Ok(u), true) => {
                 buf.reserve_exact(text.len());
-                buf.push_str(&text[..prev_end]);
-                buf.push(c);
+                buf.extend(text[..prev_end].as_bytes());
+                extend_unit(&mut buf, u);
             }
             (Err(_), _) => has_error = true,
         });
 
         match (has_error, buf.capacity() == 0) {
             (true, _) => None,
-            (false, true) => Some(Cow::Borrowed(text)),
+            (false, true) => Some(Cow::Borrowed(text.as_bytes())),
             (false, false) => Some(Cow::Owned(buf)),
         }
     }
diff --git a/src/tools/rust-analyzer/docs/user/manual.adoc b/src/tools/rust-analyzer/docs/user/manual.adoc
index 31035c4b7295..2cf985adabc7 100644
--- a/src/tools/rust-analyzer/docs/user/manual.adoc
+++ b/src/tools/rust-analyzer/docs/user/manual.adoc
@@ -449,27 +449,24 @@ You'll need to close and reopen all .rs and Cargo files, or to restart the IDE,
 Support for the language server protocol is built into Kate through the LSP plugin, which is included by default.
 It is preconfigured to use rust-analyzer for Rust sources since Kate 21.12.
 
-Earlier versions allow you to use rust-analyzer through a simple settings change.
-In the LSP Client settings of Kate, copy the content of the third tab "default parameters" to the second tab "server configuration".
-Then in the configuration replace:
+To change rust-analyzer config options, start from the following example and put it into Kate's "User Server Settings" tab (located under the LSP Client settings):
 [source,json]
 ----
+{
+    "servers": {
         "rust": {
-            "command": ["rls"],
-            "rootIndicationFileNames": ["Cargo.lock", "Cargo.toml"],
-            "url": "https://github.com/rust-lang/rls",
-            "highlightingModeRegex": "^Rust$"
-        },
-----
-With
-[source,json]
-----
-        "rust": {
-            "command": ["rust-analyzer"],
-            "rootIndicationFileNames": ["Cargo.lock", "Cargo.toml"],
-            "url": "https://github.com/rust-lang/rust-analyzer",
-            "highlightingModeRegex": "^Rust$"
-        },
+            "initializationOptions": {
+                "cachePriming": {
+                    "enable": false
+                },
+                "check": {
+                    "allTargets": false
+                },
+                "checkOnSave": false
+            }
+        }
+    }
+}
 ----
 Then click on apply, and restart the LSP server for your rust project.
 
diff --git a/src/tools/rust-analyzer/editors/code/package.json b/src/tools/rust-analyzer/editors/code/package.json
index ffb5dd9079ad..a4897899cab1 100644
--- a/src/tools/rust-analyzer/editors/code/package.json
+++ b/src/tools/rust-analyzer/editors/code/package.json
@@ -35,9 +35,12 @@
         "build-base": "esbuild ./src/main.ts --bundle --outfile=out/main.js --external:vscode --format=cjs --platform=node --target=node16",
         "build": "npm run build-base -- --sourcemap",
         "watch": "npm run build-base -- --sourcemap --watch",
-        "lint": "prettier --check . && eslint -c .eslintrc.js --ext ts ./src ./tests",
-        "fix": "prettier --write . && eslint -c .eslintrc.js --ext ts ./src ./tests --fix",
-        "pretest": "tsc && npm run build",
+        "format": "prettier --write .",
+        "format:check": "prettier --check .",
+        "lint": "eslint -c .eslintrc.js --ext ts ./src ./tests",
+        "lint:fix": "npm run lint -- --fix",
+        "typecheck": "tsc",
+        "pretest": "npm run typecheck && npm run build",
         "test": "node ./out/tests/runTests.js"
     },
     "dependencies": {
@@ -1801,12 +1804,16 @@
             },
             {
                 "id": "escapeSequence",
-                "description": "Style for char escapes in strings"
+                "description": "Style for char or byte escapes in strings"
             },
             {
                 "id": "formatSpecifier",
                 "description": "Style for {} placeholders in format strings"
             },
+            {
+                "id": "invalidEscapeSequence",
+                "description": "Style for invalid char or byte escapes in strings"
+            },
             {
                 "id": "label",
                 "description": "Style for labels"
diff --git a/src/tools/rust-analyzer/editors/code/src/debug.ts b/src/tools/rust-analyzer/editors/code/src/debug.ts
index f3d6238d51b4..e817d680eaef 100644
--- a/src/tools/rust-analyzer/editors/code/src/debug.ts
+++ b/src/tools/rust-analyzer/editors/code/src/debug.ts
@@ -66,6 +66,12 @@ export async function startDebugSession(ctx: Ctx, runnable: ra.Runnable): Promis
     return vscode.debug.startDebugging(undefined, debugConfig);
 }
 
+function createCommandLink(extensionId: string): string {
+    // do not remove the second quotes inside
+    // encodeURIComponent or it won't work
+    return `extension.open?${encodeURIComponent(`"${extensionId}"`)}`;
+}
+
 async function getDebugConfiguration(
     ctx: Ctx,
     runnable: ra.Runnable,
@@ -90,9 +96,12 @@ async function getDebugConfiguration(
     }
 
     if (!debugEngine) {
+        const commandCodeLLDB: string = createCommandLink("vadimcn.vscode-lldb");
+        const commandCpp: string = createCommandLink("ms-vscode.cpptools");
+
         await vscode.window.showErrorMessage(
-            `Install [CodeLLDB](https://marketplace.visualstudio.com/items?itemName=vadimcn.vscode-lldb)` +
-                ` or [MS C++ tools](https://marketplace.visualstudio.com/items?itemName=ms-vscode.cpptools) extension for debugging.`,
+            `Install [CodeLLDB](command:${commandCodeLLDB} "Open CodeLLDB")` +
+                ` or [C/C++](command:${commandCpp} "Open C/C++") extension for debugging.`,
         );
         return;
     }
diff --git a/src/tools/rust-installer/install-template.sh b/src/tools/rust-installer/install-template.sh
index 6415644e0451..b477c3eac350 100644
--- a/src/tools/rust-installer/install-template.sh
+++ b/src/tools/rust-installer/install-template.sh
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!/usr/bin/env bash
 
 # No undefined variables
 set -u
diff --git a/src/tools/tidy/src/issues.txt b/src/tools/tidy/src/issues.txt
new file mode 100644
index 000000000000..9f1e8d1b3f35
--- /dev/null
+++ b/src/tools/tidy/src/issues.txt
@@ -0,0 +1,4282 @@
+/*
+============================================================
+    ⚠️⚠️⚠️NOTHING SHOULD EVER BE ADDED TO THIS LIST⚠️⚠️⚠️
+============================================================
+*/
+[
+"ui/abi/issues/issue-22565-rust-call.rs",
+"ui/abi/issues/issue-62350-sysv-neg-reg-counts.rs",
+"ui/abi/issues/issue-97463-broken-abi-leaked-uninit-data.rs",
+"ui/abi/issue-28676.rs",
+"ui/abi/issue-94223.rs",
+"ui/argument-suggestions/issue-100154.rs",
+"ui/argument-suggestions/issue-100478.rs",
+"ui/argument-suggestions/issue-101097.rs",
+"ui/argument-suggestions/issue-109831.rs",
+"ui/argument-suggestions/issue-96638.rs",
+"ui/argument-suggestions/issue-97197.rs",
+"ui/argument-suggestions/issue-97484.rs",
+"ui/argument-suggestions/issue-98894.rs",
+"ui/argument-suggestions/issue-98897.rs",
+"ui/argument-suggestions/issue-99482.rs",
+"ui/argument-suggestions/issue-112507.rs",
+"ui/argument-suggestions/issue-109425.rs",
+"ui/array-slice-vec/issue-15730.rs",
+"ui/array-slice-vec/issue-18425.rs",
+"ui/array-slice-vec/issue-69103-extra-binding-subslice.rs",
+"ui/asm/x86_64/issue-82869.rs",
+"ui/asm/x86_64/issue-89875.rs",
+"ui/asm/x86_64/issue-96797.rs",
+"ui/asm/issue-72570.rs",
+"ui/asm/issue-85247.rs",
+"ui/asm/issue-87802.rs",
+"ui/asm/issue-89305.rs",
+"ui/asm/issue-92378.rs",
+"ui/asm/issue-97490.rs",
+"ui/asm/issue-99071.rs",
+"ui/asm/issue-99122-2.rs",
+"ui/asm/issue-99122.rs",
+"ui/associated-consts/issue-102335-const.rs",
+"ui/associated-consts/issue-105330.rs",
+"ui/associated-consts/issue-24949-assoc-const-static-recursion-impl.rs",
+"ui/associated-consts/issue-24949-assoc-const-static-recursion-trait-default.rs",
+"ui/associated-consts/issue-24949-assoc-const-static-recursion-trait.rs",
+"ui/associated-consts/issue-47814.rs",
+"ui/associated-consts/issue-58022.rs",
+"ui/associated-consts/issue-63496.rs",
+"ui/associated-consts/issue-93775.rs",
+"ui/associated-consts/issue-93835.rs",
+"ui/associated-consts/issue-69020-assoc-const-arith-overflow.rs",
+"ui/associated-consts/issue-88599-ref-self.rs",
+"ui/associated-consts/issue-110933.rs",
+"ui/associated-inherent-types/issue-109299-1.rs",
+"ui/associated-inherent-types/issue-109299.rs",
+"ui/associated-inherent-types/issue-109768.rs",
+"ui/associated-inherent-types/issue-109789.rs",
+"ui/associated-inherent-types/issue-111879-0.rs",
+"ui/associated-inherent-types/issue-111879-1.rs",
+"ui/associated-inherent-types/issue-111404-1.rs",
+"ui/associated-inherent-types/issue-104260.rs",
+"ui/associated-inherent-types/issue-109790.rs",
+"ui/associated-inherent-types/issue-111404-0.rs",
+"ui/associated-inherent-types/issue-109071.rs",
+"ui/associated-item/issue-48027.rs",
+"ui/associated-item/issue-105449.rs",
+"ui/associated-item/issue-87638.rs",
+"ui/associated-type-bounds/issue-102335-ty.rs",
+"ui/associated-type-bounds/issue-104916.rs",
+"ui/associated-type-bounds/issue-71443-1.rs",
+"ui/associated-type-bounds/issue-99828.rs",
+"ui/associated-type-bounds/issue-61752.rs",
+"ui/associated-type-bounds/issue-70292.rs",
+"ui/associated-type-bounds/issue-71443-2.rs",
+"ui/associated-type-bounds/issue-73818.rs",
+"ui/associated-type-bounds/issue-79949.rs",
+"ui/associated-type-bounds/issue-81193.rs",
+"ui/associated-type-bounds/issue-83017.rs",
+"ui/associated-types/issue-18655.rs",
+"ui/associated-types/issue-19883.rs",
+"ui/associated-types/issue-20005.rs",
+"ui/associated-types/issue-20825.rs",
+"ui/associated-types/issue-22037.rs",
+"ui/associated-types/issue-22560.rs",
+"ui/associated-types/issue-22828.rs",
+"ui/associated-types/issue-23208.rs",
+"ui/associated-types/issue-23595-1.rs",
+"ui/associated-types/issue-23595-2.rs",
+"ui/associated-types/issue-25339.rs",
+"ui/associated-types/issue-25700-1.rs",
+"ui/associated-types/issue-25700-2.rs",
+"ui/associated-types/issue-25700.rs",
+"ui/associated-types/issue-26681.rs",
+"ui/associated-types/issue-27675-unchecked-bounds.rs",
+"ui/associated-types/issue-27901.rs",
+"ui/associated-types/issue-38821.rs",
+"ui/associated-types/issue-43784-associated-type.rs",
+"ui/associated-types/issue-43924.rs",
+"ui/associated-types/issue-44153.rs",
+"ui/associated-types/issue-47139-1.rs",
+"ui/associated-types/issue-47139-2.rs",
+"ui/associated-types/issue-47814.rs",
+"ui/associated-types/issue-54108.rs",
+"ui/associated-types/issue-54182-1.rs",
+"ui/associated-types/issue-54467.rs",
+"ui/associated-types/issue-55846.rs",
+"ui/associated-types/issue-59324.rs",
+"ui/associated-types/issue-62200.rs",
+"ui/associated-types/issue-63593.rs",
+"ui/associated-types/issue-64848.rs",
+"ui/associated-types/issue-64855.rs",
+"ui/associated-types/issue-65774-1.rs",
+"ui/associated-types/issue-65774-2.rs",
+"ui/associated-types/issue-72806.rs",
+"ui/associated-types/issue-85103.rs",
+"ui/associated-types/issue-87261.rs",
+"ui/associated-types/issue-19081.rs",
+"ui/associated-types/issue-20825-2.rs",
+"ui/associated-types/issue-21363.rs",
+"ui/associated-types/issue-21726.rs",
+"ui/associated-types/issue-22066.rs",
+"ui/associated-types/issue-24159.rs",
+"ui/associated-types/issue-24204.rs",
+"ui/associated-types/issue-24338.rs",
+"ui/associated-types/issue-28871.rs",
+"ui/associated-types/issue-31597.rs",
+"ui/associated-types/issue-32350.rs",
+"ui/associated-types/issue-36499.rs",
+"ui/associated-types/issue-37808.rs",
+"ui/associated-types/issue-37883.rs",
+"ui/associated-types/issue-38917.rs",
+"ui/associated-types/issue-39532.rs",
+"ui/associated-types/issue-40093.rs",
+"ui/associated-types/issue-41868.rs",
+"ui/associated-types/issue-43475.rs",
+"ui/associated-types/issue-47385.rs",
+"ui/associated-types/issue-48010.rs",
+"ui/associated-types/issue-48551.rs",
+"ui/associated-types/issue-50301.rs",
+"ui/associated-types/issue-54182-2.rs",
+"ui/associated-types/issue-63591.rs",
+"ui/associated-types/issue-64855-2.rs",
+"ui/associated-types/issue-65934.rs",
+"ui/associated-types/issue-67684.rs",
+"ui/associated-types/issue-69398.rs",
+"ui/associated-types/issue-71113.rs",
+"ui/associated-types/issue-76179.rs",
+"ui/associated-types/issue-82079.rs",
+"ui/associated-types/issue-88856.rs",
+"ui/associated-types/issue-91069.rs",
+"ui/associated-types/issue-91231.rs",
+"ui/associated-types/issue-91234.rs",
+"ui/async-await/auxiliary/issue-107036.rs",
+"ui/async-await/auxiliary/issue-72470-lib.rs",
+"ui/async-await/in-trait/issue-102138.rs",
+"ui/async-await/in-trait/issue-102219.rs",
+"ui/async-await/in-trait/issue-102310.rs",
+"ui/async-await/in-trait/issue-104678.rs",
+"ui/async-await/issues/auxiliary/issue-60674.rs",
+"ui/async-await/issues/auxiliary/issue_67893.rs",
+"ui/async-await/issues/issue-65419/issue-65419-async-fn-resume-after-completion.rs",
+"ui/async-await/issues/issue-65419/issue-65419-async-fn-resume-after-panic.rs",
+"ui/async-await/issues/issue-65419/issue-65419-generator-resume-after-completion.rs",
+"ui/async-await/issues/issue-102206.rs",
+"ui/async-await/issues/issue-107280.rs",
+"ui/async-await/issues/issue-112225-1.rs",
+"ui/async-await/issues/issue-112225-2.rs",
+"ui/async-await/issues/issue-51719.rs",
+"ui/async-await/issues/issue-51751.rs",
+"ui/async-await/issues/issue-53249.rs",
+"ui/async-await/issues/issue-54752-async-block.rs",
+"ui/async-await/issues/issue-54974.rs",
+"ui/async-await/issues/issue-55324.rs",
+"ui/async-await/issues/issue-55809.rs",
+"ui/async-await/issues/issue-58885.rs",
+"ui/async-await/issues/issue-59001.rs",
+"ui/async-await/issues/issue-59972.rs",
+"ui/async-await/issues/issue-60518.rs",
+"ui/async-await/issues/issue-60655-latebound-regions.rs",
+"ui/async-await/issues/issue-60674.rs",
+"ui/async-await/issues/issue-61187.rs",
+"ui/async-await/issues/issue-61986.rs",
+"ui/async-await/issues/issue-62009-1.rs",
+"ui/async-await/issues/issue-62009-2.rs",
+"ui/async-await/issues/issue-62097.rs",
+"ui/async-await/issues/issue-62517-1.rs",
+"ui/async-await/issues/issue-62517-2.rs",
+"ui/async-await/issues/issue-63388-1.rs",
+"ui/async-await/issues/issue-63388-2.rs",
+"ui/async-await/issues/issue-63388-3.rs",
+"ui/async-await/issues/issue-63388-4.rs",
+"ui/async-await/issues/issue-64391-2.rs",
+"ui/async-await/issues/issue-64433.rs",
+"ui/async-await/issues/issue-64477-2.rs",
+"ui/async-await/issues/issue-64477.rs",
+"ui/async-await/issues/issue-64964.rs",
+"ui/async-await/issues/issue-65159.rs",
+"ui/async-await/issues/issue-65436-raw-ptr-not-send.rs",
+"ui/async-await/issues/issue-66695-static-refs.rs",
+"ui/async-await/issues/issue-66958-non-copy-infered-type-arg.rs",
+"ui/async-await/issues/issue-67611-static-mut-refs.rs",
+"ui/async-await/issues/issue-67893.rs",
+"ui/async-await/issues/issue-69307-nested.rs",
+"ui/async-await/issues/issue-69307.rs",
+"ui/async-await/issues/issue-72312.rs",
+"ui/async-await/issues/issue-78600.rs",
+"ui/async-await/issues/issue-78654.rs",
+"ui/async-await/issues/issue-78938-async-block.rs",
+"ui/async-await/issues/issue-95307.rs",
+"ui/async-await/return-type-notation/issue-110963-early.rs",
+"ui/async-await/return-type-notation/issue-110963-late.rs",
+"ui/async-await/track-caller/issue-105134.rs",
+"ui/async-await/issue-73541-3.rs",
+"ui/async-await/issue-73541.rs",
+"ui/async-await/issue-101715.rs",
+"ui/async-await/issue-105501.rs",
+"ui/async-await/issue-107036.rs",
+"ui/async-await/issue-108572.rs",
+"ui/async-await/issue-54239-private-type-triggers-lint.rs",
+"ui/async-await/issue-60709.rs",
+"ui/async-await/issue-61076.rs",
+"ui/async-await/issue-61452.rs",
+"ui/async-await/issue-61793.rs",
+"ui/async-await/issue-61949-self-return-type.rs",
+"ui/async-await/issue-62658.rs",
+"ui/async-await/issue-63832-await-short-temporary-lifetime-1.rs",
+"ui/async-await/issue-63832-await-short-temporary-lifetime.rs",
+"ui/async-await/issue-64130-1-sync.rs",
+"ui/async-await/issue-64130-2-send.rs",
+"ui/async-await/issue-64130-3-other.rs",
+"ui/async-await/issue-64130-4-async-move.rs",
+"ui/async-await/issue-64130-non-send-future-diags.rs",
+"ui/async-await/issue-64391.rs",
+"ui/async-await/issue-66312.rs",
+"ui/async-await/issue-66387-if-without-else.rs",
+"ui/async-await/issue-67252-unnamed-future.rs",
+"ui/async-await/issue-67651.rs",
+"ui/async-await/issue-67765-async-diagnostic.rs",
+"ui/async-await/issue-68112.rs",
+"ui/async-await/issue-68523-start.rs",
+"ui/async-await/issue-68523.rs",
+"ui/async-await/issue-69446-fnmut-capture.rs",
+"ui/async-await/issue-70594.rs",
+"ui/async-await/issue-70818.rs",
+"ui/async-await/issue-71137.rs",
+"ui/async-await/issue-72442.rs",
+"ui/async-await/issue-72470-llvm-dominate.rs",
+"ui/async-await/issue-72590-type-error-sized.rs",
+"ui/async-await/issue-73050.rs",
+"ui/async-await/issue-73137.rs",
+"ui/async-await/issue-73541-1.rs",
+"ui/async-await/issue-73541-2.rs",
+"ui/async-await/issue-73741-type-err-drop-tracking.rs",
+"ui/async-await/issue-73741-type-err.rs",
+"ui/async-await/issue-74047.rs",
+"ui/async-await/issue-74072-lifetime-name-annotations.rs",
+"ui/async-await/issue-74497-lifetime-in-opaque.rs",
+"ui/async-await/issue-75785-confusing-named-region.rs",
+"ui/async-await/issue-76547.rs",
+"ui/async-await/issue-77993-2.rs",
+"ui/async-await/issue-78115.rs",
+"ui/async-await/issue-84841.rs",
+"ui/async-await/issue-86507.rs",
+"ui/async-await/issue-93197.rs",
+"ui/async-await/issue-93648.rs",
+"ui/async-await/issue-98634.rs",
+"ui/async-await/issue-70935-complex-spans.rs",
+"ui/attributes/issue-100631.rs",
+"ui/attributes/issue-105594-invalid-attr-validation.rs",
+"ui/attributes/issue-90873.rs",
+"ui/attributes/issue-40962.rs",
+"ui/auto-traits/issue-23080.rs",
+"ui/auto-traits/issue-84075.rs",
+"ui/auto-traits/issue-23080-2.rs",
+"ui/auxiliary/issue-13560-1.rs",
+"ui/auxiliary/issue-13560-2.rs",
+"ui/auxiliary/issue-13560-3.rs",
+"ui/auxiliary/issue-16822.rs",
+"ui/auxiliary/issue-18502.rs",
+"ui/auxiliary/issue-24106.rs",
+"ui/auxiliary/issue-76387.rs",
+"ui/bench/issue-32062.rs",
+"ui/binding/issue-53114-borrow-checks.rs",
+"ui/binding/issue-53114-safety-checks.rs",
+"ui/binop/issue-25916.rs",
+"ui/binop/issue-28837.rs",
+"ui/binop/issue-3820.rs",
+"ui/binop/issue-77910-1.rs",
+"ui/binop/issue-77910-2.rs",
+"ui/binop/issue-93927.rs",
+"ui/block-result/issue-11714.rs",
+"ui/block-result/issue-13428.rs",
+"ui/block-result/issue-13624.rs",
+"ui/block-result/issue-20862.rs",
+"ui/block-result/issue-22645.rs",
+"ui/block-result/issue-3563.rs",
+"ui/block-result/issue-5500.rs",
+"ui/borrowck/issue-85765-closure.rs",
+"ui/borrowck/issue-101119.rs",
+"ui/borrowck/issue-102209.rs",
+"ui/borrowck/issue-17545.rs",
+"ui/borrowck/issue-17718-static-move.rs",
+"ui/borrowck/issue-20801.rs",
+"ui/borrowck/issue-23338-params-outlive-temps-of-body.rs",
+"ui/borrowck/issue-24267-flow-exit.rs",
+"ui/borrowck/issue-25793.rs",
+"ui/borrowck/issue-29166.rs",
+"ui/borrowck/issue-31287-drop-in-guard.rs",
+"ui/borrowck/issue-33819.rs",
+"ui/borrowck/issue-41962.rs",
+"ui/borrowck/issue-42344.rs",
+"ui/borrowck/issue-45983.rs",
+"ui/borrowck/issue-46095.rs",
+"ui/borrowck/issue-46471.rs",
+"ui/borrowck/issue-47215-ice-from-drop-elab.rs",
+"ui/borrowck/issue-47646.rs",
+"ui/borrowck/issue-51117.rs",
+"ui/borrowck/issue-51301.rs",
+"ui/borrowck/issue-51348-multi-ref-mut-in-guard.rs",
+"ui/borrowck/issue-52713-bug.rs",
+"ui/borrowck/issue-53432-nested-closure-outlives-borrowed-value.rs",
+"ui/borrowck/issue-54499-field-mutation-marks-mut-as-used.rs",
+"ui/borrowck/issue-54499-field-mutation-of-moved-out-with-mut.rs",
+"ui/borrowck/issue-54499-field-mutation-of-moved-out.rs",
+"ui/borrowck/issue-54499-field-mutation-of-never-init.rs",
+"ui/borrowck/issue-54597-reject-move-out-of-borrow-via-pat.rs",
+"ui/borrowck/issue-55492-borrowck-migrate-scans-parents.rs",
+"ui/borrowck/issue-58776-borrowck-scans-children.rs",
+"ui/borrowck/issue-62007-assign-box.rs",
+"ui/borrowck/issue-62007-assign-field.rs",
+"ui/borrowck/issue-62107-match-arm-scopes.rs",
+"ui/borrowck/issue-64453.rs",
+"ui/borrowck/issue-69789-iterator-mut-suggestion.rs",
+"ui/borrowck/issue-7573.rs",
+"ui/borrowck/issue-81365-1.rs",
+"ui/borrowck/issue-81365-10.rs",
+"ui/borrowck/issue-81365-11.rs",
+"ui/borrowck/issue-81365-2.rs",
+"ui/borrowck/issue-81365-3.rs",
+"ui/borrowck/issue-81365-4.rs",
+"ui/borrowck/issue-81365-5.rs",
+"ui/borrowck/issue-81365-6.rs",
+"ui/borrowck/issue-81365-7.rs",
+"ui/borrowck/issue-81365-8.rs",
+"ui/borrowck/issue-81365-9.rs",
+"ui/borrowck/issue-81899.rs",
+"ui/borrowck/issue-82032.rs",
+"ui/borrowck/issue-82462.rs",
+"ui/borrowck/issue-83309-ice-immut-in-for-loop.rs",
+"ui/borrowck/issue-83760.rs",
+"ui/borrowck/issue-85581.rs",
+"ui/borrowck/issue-85765.rs",
+"ui/borrowck/issue-87456-point-to-closure.rs",
+"ui/borrowck/issue-88434-minimal-example.rs",
+"ui/borrowck/issue-88434-removal-index-should-be-less.rs",
+"ui/borrowck/issue-91206.rs",
+"ui/borrowck/issue-92015.rs",
+"ui/borrowck/issue-92157.rs",
+"ui/borrowck/issue-93078.rs",
+"ui/borrowck/issue-111554.rs",
+"ui/borrowck/issue-45199.rs",
+"ui/borrowck/issue-103095.rs",
+"ui/borrowck/issue-103250.rs",
+"ui/borrowck/issue-103624.rs",
+"ui/borrowck/issue-104639-lifetime-order.rs",
+"ui/borrowck/issue-10876.rs",
+"ui/borrowck/issue-109271-pass-self-into-closure.rs",
+"ui/borrowck/issue-11493.rs",
+"ui/borrowck/issue-17263.rs",
+"ui/borrowck/issue-28934.rs",
+"ui/borrowck/issue-36082.rs",
+"ui/borrowck/issue-51415.rs",
+"ui/borrowck/issue-52967-edition-2018-needs-two-phase-borrows.rs",
+"ui/borrowck/issue-55552-ascribe-wildcard-to-structured-pattern.rs",
+"ui/borrowck/issue-70919-drop-in-loop.rs",
+"ui/borrowck/issue-71546.rs",
+"ui/borrowck/issue-80772.rs",
+"ui/borrowck/issue-82126-mismatched-subst-and-hir.rs",
+"ui/borrowck/issue-83924.rs",
+"ui/borrowck/issue-93093.rs",
+"ui/borrowck/issue-95079-missing-move-in-nested-closure.rs",
+"ui/box/issue-82446.rs",
+"ui/box/issue-95036.rs",
+"ui/c-variadic/issue-32201.rs",
+"ui/c-variadic/issue-86053-2.rs",
+"ui/c-variadic/issue-86053-1.rs",
+"ui/cast/issue-106883-is-empty.rs",
+"ui/cast/issue-10991.rs",
+"ui/cast/issue-17444.rs",
+"ui/cast/issue-85586.rs",
+"ui/cast/issue-88621.rs",
+"ui/cast/issue-84213.rs",
+"ui/cast/issue-89497.rs",
+"ui/closure-expected-type/issue-24421.rs",
+"ui/closure_context/issue-26046-fn-mut.rs",
+"ui/closure_context/issue-26046-fn-once.rs",
+"ui/closure_context/issue-42065.rs",
+"ui/closures/2229_closure_analysis/match/issue-87097.rs",
+"ui/closures/2229_closure_analysis/match/issue-87426.rs",
+"ui/closures/2229_closure_analysis/match/issue-87988.rs",
+"ui/closures/2229_closure_analysis/match/issue-88331.rs",
+"ui/closures/2229_closure_analysis/migrations/issue-78720.rs",
+"ui/closures/2229_closure_analysis/migrations/issue-86753.rs",
+"ui/closures/2229_closure_analysis/migrations/issue-90024-adt-correct-subst.rs",
+"ui/closures/2229_closure_analysis/run_pass/issue-87378.rs",
+"ui/closures/2229_closure_analysis/run_pass/issue-88372.rs",
+"ui/closures/2229_closure_analysis/run_pass/issue-88431.rs",
+"ui/closures/2229_closure_analysis/run_pass/issue-88476.rs",
+"ui/closures/2229_closure_analysis/issue-87378.rs",
+"ui/closures/2229_closure_analysis/issue-87987.rs",
+"ui/closures/2229_closure_analysis/issue-88118-2.rs",
+"ui/closures/2229_closure_analysis/issue-88476.rs",
+"ui/closures/2229_closure_analysis/issue-89606.rs",
+"ui/closures/2229_closure_analysis/issue-90465.rs",
+"ui/closures/2229_closure_analysis/issue-92724-needsdrop-query-cycle.rs",
+"ui/closures/2229_closure_analysis/issue_88118.rs",
+"ui/closures/issue-10398.rs",
+"ui/closures/issue-109188.rs",
+"ui/closures/issue-42463.rs",
+"ui/closures/issue-52437.rs",
+"ui/closures/issue-67123.rs",
+"ui/closures/issue-6801.rs",
+"ui/closures/issue-78720.rs",
+"ui/closures/issue-80313-mutable-borrow-in-closure.rs",
+"ui/closures/issue-80313-mutable-borrow-in-move-closure.rs",
+"ui/closures/issue-80313-mutation-in-closure.rs",
+"ui/closures/issue-80313-mutation-in-move-closure.rs",
+"ui/closures/issue-81700-mut-borrow.rs",
+"ui/closures/issue-82438-mut-without-upvar.rs",
+"ui/closures/issue-84044-drop-non-mut.rs",
+"ui/closures/issue-84128.rs",
+"ui/closures/issue-868.rs",
+"ui/closures/issue-90871.rs",
+"ui/closures/issue-99565.rs",
+"ui/closures/issue-111932.rs",
+"ui/closures/issue-72408-nested-closures-exponential.rs",
+"ui/closures/issue-101696.rs",
+"ui/closures/issue-102089-multiple-opaque-cast.rs",
+"ui/closures/issue-23012-supertrait-signature-inference.rs",
+"ui/closures/issue-41366.rs",
+"ui/closures/issue-46742.rs",
+"ui/closures/issue-48109.rs",
+"ui/closures/issue-68025.rs",
+"ui/closures/issue-87461.rs",
+"ui/closures/issue-87814-1.rs",
+"ui/closures/issue-87814-2.rs",
+"ui/closures/issue-97607.rs",
+"ui/closures/issue-113087.rs",
+"ui/cmse-nonsecure/cmse-nonsecure-entry/issue-83475.rs",
+"ui/codegen/auxiliary/issue-97708-aux.rs",
+"ui/codegen/issue-101585-128bit-repeat.rs",
+"ui/codegen/issue-16602-1.rs",
+"ui/codegen/issue-16602-2.rs",
+"ui/codegen/issue-16602-3.rs",
+"ui/codegen/issue-55976.rs",
+"ui/codegen/issue-64401.rs",
+"ui/codegen/issue-97708.rs",
+"ui/codegen/issue-99551.rs",
+"ui/codegen/issue-28950.rs",
+"ui/codegen/issue-63787.rs",
+"ui/codegen/issue-82859-slice-miscompile.rs",
+"ui/codegen/issue-88043-bb-does-not-have-terminator.rs",
+"ui/codemap_tests/issue-11715.rs",
+"ui/codemap_tests/issue-28308.rs",
+"ui/coercion/auxiliary/issue-39823.rs",
+"ui/coercion/issue-14589.rs",
+"ui/coercion/issue-39823.rs",
+"ui/coercion/issue-53475.rs",
+"ui/coercion/issue-73886.rs",
+"ui/coercion/issue-3794.rs",
+"ui/coercion/issue-101066.rs",
+"ui/coercion/issue-36007.rs",
+"ui/coercion/issue-37655.rs",
+"ui/coercion/issue-88097.rs",
+"ui/coherence/issue-85026.rs",
+"ui/coherence/issue-99663-2.rs",
+"ui/coherence/issue-99663.rs",
+"ui/command/issue-10626.rs",
+"ui/compare-method/issue-90444.rs",
+"ui/conditional-compilation/issue-34028.rs",
+"ui/confuse-field-and-method/issue-18343.rs",
+"ui/confuse-field-and-method/issue-2392.rs",
+"ui/confuse-field-and-method/issue-32128.rs",
+"ui/confuse-field-and-method/issue-33784.rs",
+"ui/const-generics/generic_arg_infer/issue-91614.rs",
+"ui/const-generics/generic_const_exprs/auxiliary/issue-94287-aux.rs",
+"ui/const-generics/generic_const_exprs/issue-100217.rs",
+"ui/const-generics/generic_const_exprs/issue-102768.rs",
+"ui/const-generics/generic_const_exprs/issue-105257.rs",
+"ui/const-generics/generic_const_exprs/issue-105608.rs",
+"ui/const-generics/generic_const_exprs/issue-69654.rs",
+"ui/const-generics/generic_const_exprs/issue-73298.rs",
+"ui/const-generics/generic_const_exprs/issue-73899.rs",
+"ui/const-generics/generic_const_exprs/issue-74713.rs",
+"ui/const-generics/generic_const_exprs/issue-76595.rs",
+"ui/const-generics/generic_const_exprs/issue-79518-default_trait_method_normalization.rs",
+"ui/const-generics/generic_const_exprs/issue-80742.rs",
+"ui/const-generics/generic_const_exprs/issue-82268.rs",
+"ui/const-generics/generic_const_exprs/issue-83765.rs",
+"ui/const-generics/generic_const_exprs/issue-83972.rs",
+"ui/const-generics/generic_const_exprs/issue-84669.rs",
+"ui/const-generics/generic_const_exprs/issue-85848.rs",
+"ui/const-generics/generic_const_exprs/issue-94287.rs",
+"ui/const-generics/generic_const_exprs/issue-86710.rs",
+"ui/const-generics/generic_const_exprs/issue-100360.rs",
+"ui/const-generics/generic_const_exprs/issue-102074.rs",
+"ui/const-generics/generic_const_exprs/issue-62504.rs",
+"ui/const-generics/generic_const_exprs/issue-72787.rs",
+"ui/const-generics/generic_const_exprs/issue-72819-generic-in-const-eval.rs",
+"ui/const-generics/generic_const_exprs/issue-74634.rs",
+"ui/const-generics/generic_const_exprs/issue-80561-incorrect-param-env.rs",
+"ui/const-generics/generic_const_exprs/issue-84408.rs",
+"ui/const-generics/generic_const_exprs/issue-89851.rs",
+"ui/const-generics/generic_const_exprs/issue-90847.rs",
+"ui/const-generics/generic_const_exprs/issue-94293.rs",
+"ui/const-generics/generic_const_exprs/issue-97047-ice-1.rs",
+"ui/const-generics/generic_const_exprs/issue-97047-ice-2.rs",
+"ui/const-generics/generic_const_exprs/issue-99647.rs",
+"ui/const-generics/generic_const_exprs/issue-99705.rs",
+"ui/const-generics/generic_const_exprs/issue-109141.rs",
+"ui/const-generics/generic_const_exprs/issue-96699.rs",
+"ui/const-generics/infer/issue-77092.rs",
+"ui/const-generics/issues/issue-105037.rs",
+"ui/const-generics/issues/issue-56445-2.rs",
+"ui/const-generics/issues/issue-56445-3.rs",
+"ui/const-generics/issues/issue-61336-1.rs",
+"ui/const-generics/issues/issue-61336-2.rs",
+"ui/const-generics/issues/issue-61336.rs",
+"ui/const-generics/issues/issue-61432.rs",
+"ui/const-generics/issues/issue-62187-encountered-polymorphic-const.rs",
+"ui/const-generics/issues/issue-67185-2.rs",
+"ui/const-generics/issues/issue-68104-print-stack-overflow.rs",
+"ui/const-generics/issues/issue-69654-run-pass.rs",
+"ui/const-generics/issues/issue-70125-1.rs",
+"ui/const-generics/issues/issue-70125-2.rs",
+"ui/const-generics/issues/issue-70180-1-stalled_on.rs",
+"ui/const-generics/issues/issue-70180-2-stalled_on.rs",
+"ui/const-generics/issues/issue-71202.rs",
+"ui/const-generics/issues/issue-72845.rs",
+"ui/const-generics/issues/issue-73260.rs",
+"ui/const-generics/issues/issue-76701-ty-param-in-const.rs",
+"ui/const-generics/issues/issue-79674.rs",
+"ui/const-generics/issues/issue-80062.rs",
+"ui/const-generics/issues/issue-80375.rs",
+"ui/const-generics/issues/issue-82956.rs",
+"ui/const-generics/issues/issue-83249.rs",
+"ui/const-generics/issues/issue-83288.rs",
+"ui/const-generics/issues/issue-83466.rs",
+"ui/const-generics/issues/issue-83765.rs",
+"ui/const-generics/issues/issue-84659.rs",
+"ui/const-generics/issues/issue-86530.rs",
+"ui/const-generics/issues/issue-86535-2.rs",
+"ui/const-generics/issues/issue-86535.rs",
+"ui/const-generics/issues/issue-86820.rs",
+"ui/const-generics/issues/issue-87470.rs",
+"ui/const-generics/issues/issue-87493.rs",
+"ui/const-generics/issues/issue-87964.rs",
+"ui/const-generics/issues/issue-88997.rs",
+"ui/const-generics/issues/issue-89146.rs",
+"ui/const-generics/issues/issue-89320.rs",
+"ui/const-generics/issues/issue-89334.rs",
+"ui/const-generics/issues/issue-90318.rs",
+"ui/const-generics/issues/issue-90364.rs",
+"ui/const-generics/issues/issue-90455.rs",
+"ui/const-generics/issues/issue-97634.rs",
+"ui/const-generics/issues/issue-98629.rs",
+"ui/const-generics/issues/issue-100313.rs",
+"ui/const-generics/issues/issue-87076.rs",
+"ui/const-generics/issues/issue-97278.rs",
+"ui/const-generics/issues/issue-99641.rs",
+"ui/const-generics/issues/issue-105821.rs",
+"ui/const-generics/issues/issue-56445-1.rs",
+"ui/const-generics/issues/issue-60818-struct-constructors.rs",
+"ui/const-generics/issues/issue-61422.rs",
+"ui/const-generics/issues/issue-62878.rs",
+"ui/const-generics/issues/issue-63322-forbid-dyn.rs",
+"ui/const-generics/issues/issue-64519.rs",
+"ui/const-generics/issues/issue-66596-impl-trait-for-str-const-arg.rs",
+"ui/const-generics/issues/issue-66906.rs",
+"ui/const-generics/issues/issue-67185-1.rs",
+"ui/const-generics/issues/issue-67375.rs",
+"ui/const-generics/issues/issue-67739.rs",
+"ui/const-generics/issues/issue-67945-1.rs",
+"ui/const-generics/issues/issue-67945-2.rs",
+"ui/const-generics/issues/issue-67945-3.rs",
+"ui/const-generics/issues/issue-67945-4.rs",
+"ui/const-generics/issues/issue-68366.rs",
+"ui/const-generics/issues/issue-68596.rs",
+"ui/const-generics/issues/issue-68615-adt.rs",
+"ui/const-generics/issues/issue-68615-array.rs",
+"ui/const-generics/issues/issue-70167.rs",
+"ui/const-generics/issues/issue-70225.rs",
+"ui/const-generics/issues/issue-70273-assoc-fn.rs",
+"ui/const-generics/issues/issue-71169.rs",
+"ui/const-generics/issues/issue-71381.rs",
+"ui/const-generics/issues/issue-71382.rs",
+"ui/const-generics/issues/issue-71547.rs",
+"ui/const-generics/issues/issue-71611.rs",
+"ui/const-generics/issues/issue-71986.rs",
+"ui/const-generics/issues/issue-72352.rs",
+"ui/const-generics/issues/issue-73120.rs",
+"ui/const-generics/issues/issue-73491.rs",
+"ui/const-generics/issues/issue-73727-static-reference-array-const-param.rs",
+"ui/const-generics/issues/issue-74101.rs",
+"ui/const-generics/issues/issue-74255.rs",
+"ui/const-generics/issues/issue-74906.rs",
+"ui/const-generics/issues/issue-74950.rs",
+"ui/const-generics/issues/issue-75047.rs",
+"ui/const-generics/issues/issue-75299.rs",
+"ui/const-generics/issues/issue-85031-2.rs",
+"ui/const-generics/issues/issue-86033.rs",
+"ui/const-generics/issues/issue-88119.rs",
+"ui/const-generics/issues/issue-88468.rs",
+"ui/const-generics/issues/issue-89304.rs",
+"ui/const-generics/issues/issue-92186.rs",
+"ui/const-generics/issues/issue-96654.rs",
+"ui/const-generics/parser-error-recovery/issue-89013-no-assoc.rs",
+"ui/const-generics/parser-error-recovery/issue-89013-no-kw.rs",
+"ui/const-generics/parser-error-recovery/issue-89013-type.rs",
+"ui/const-generics/parser-error-recovery/issue-89013.rs",
+"ui/const-generics/type-dependent/issue-61936.rs",
+"ui/const-generics/type-dependent/issue-63695.rs",
+"ui/const-generics/type-dependent/issue-69816.rs",
+"ui/const-generics/type-dependent/issue-70507.rs",
+"ui/const-generics/type-dependent/issue-71382.rs",
+"ui/const-generics/type-dependent/issue-71805.rs",
+"ui/const-generics/type-dependent/issue-67144-1.rs",
+"ui/const-generics/type-dependent/issue-67144-2.rs",
+"ui/const-generics/type-dependent/issue-70217.rs",
+"ui/const-generics/type-dependent/issue-70586.rs",
+"ui/const-generics/type-dependent/issue-71348.rs",
+"ui/const-generics/type-dependent/issue-73730.rs",
+"ui/const-generics/issue-46511.rs",
+"ui/const-generics/issue-70408.rs",
+"ui/const-generics/issue-93647.rs",
+"ui/const-generics/issue-112505-overflow.rs",
+"ui/const-generics/issue-66451.rs",
+"ui/const-generics/issue-80471.rs",
+"ui/const-generics/issue-102124.rs",
+"ui/const-generics/issue-105689.rs",
+"ui/const-generics/issue-106419-struct-with-multiple-const-params.rs",
+"ui/const-generics/issue-97007.rs",
+"ui/const_prop/issue-102553.rs",
+"ui/const_prop/issue-86351.rs",
+"ui/consts/auxiliary/issue-17718-aux.rs",
+"ui/consts/auxiliary/issue-63226.rs",
+"ui/consts/const-eval/issue-100878.rs",
+"ui/consts/const-eval/issue-104390.rs",
+"ui/consts/const-eval/issue-43197.rs",
+"ui/consts/const-eval/issue-44578.rs",
+"ui/consts/const-eval/issue-49296.rs",
+"ui/consts/const-eval/issue-50814-2.rs",
+"ui/consts/const-eval/issue-50814.rs",
+"ui/consts/const-eval/issue-64908.rs",
+"ui/consts/const-eval/issue-64970.rs",
+"ui/consts/const-eval/issue-65394.rs",
+"ui/consts/const-eval/issue-84957-const-str-as-bytes.rs",
+"ui/consts/const-eval/issue-85155.rs",
+"ui/consts/const-eval/issue-85907.rs",
+"ui/consts/const-eval/issue-91827-extern-types.rs",
+"ui/consts/const-eval/issue-52475.rs",
+"ui/consts/const-eval/issue-70723.rs",
+"ui/consts/const-eval/issue-47971.rs",
+"ui/consts/const-eval/issue-50706.rs",
+"ui/consts/const-eval/issue-51300.rs",
+"ui/consts/const-eval/issue-53157.rs",
+"ui/consts/const-eval/issue-53401.rs",
+"ui/consts/const-eval/issue-55541.rs",
+"ui/consts/const-eval/issue-70804-fn-subtyping.rs",
+"ui/consts/const-extern-fn/issue-68062-const-extern-fns-dont-need-fn-specifier-2.rs",
+"ui/consts/const-extern-fn/issue-68062-const-extern-fns-dont-need-fn-specifier.rs",
+"ui/consts/const-mut-refs/issue-76510.rs",
+"ui/consts/const_in_pattern/issue-44333.rs",
+"ui/consts/const_in_pattern/issue-62614.rs",
+"ui/consts/const_in_pattern/issue-78057.rs",
+"ui/consts/const_in_pattern/issue-53708.rs",
+"ui/consts/const_in_pattern/issue-65466.rs",
+"ui/consts/const_in_pattern/issue-73431.rs",
+"ui/consts/control-flow/issue-46843.rs",
+"ui/consts/control-flow/issue-50577.rs",
+"ui/consts/extra-const-ub/issue-100771.rs",
+"ui/consts/extra-const-ub/issue-101034.rs",
+"ui/consts/issue-102117.rs",
+"ui/consts/issue-103790.rs",
+"ui/consts/issue-104609.rs",
+"ui/consts/issue-104768.rs",
+"ui/consts/issue-13902.rs",
+"ui/consts/issue-17458.rs",
+"ui/consts/issue-17718-borrow-interior.rs",
+"ui/consts/issue-17718-const-bad-values.rs",
+"ui/consts/issue-17718-const-borrow.rs",
+"ui/consts/issue-17718-constants-not-static.rs",
+"ui/consts/issue-17718-references.rs",
+"ui/consts/issue-17718.rs",
+"ui/consts/issue-17756.rs",
+"ui/consts/issue-18294.rs",
+"ui/consts/issue-19244.rs",
+"ui/consts/issue-21562.rs",
+"ui/consts/issue-21721.rs",
+"ui/consts/issue-23833.rs",
+"ui/consts/issue-23968-const-not-overflow.rs",
+"ui/consts/issue-25826.rs",
+"ui/consts/issue-27890.rs",
+"ui/consts/issue-28113.rs",
+"ui/consts/issue-29914-2.rs",
+"ui/consts/issue-29914-3.rs",
+"ui/consts/issue-29914.rs",
+"ui/consts/issue-29927-1.rs",
+"ui/consts/issue-29927.rs",
+"ui/consts/issue-32829-2.rs",
+"ui/consts/issue-32829.rs",
+"ui/consts/issue-33537.rs",
+"ui/consts/issue-34784.rs",
+"ui/consts/issue-36163.rs",
+"ui/consts/issue-37222.rs",
+"ui/consts/issue-37550.rs",
+"ui/consts/issue-37991.rs",
+"ui/consts/issue-39974.rs",
+"ui/consts/issue-43105.rs",
+"ui/consts/issue-44415.rs",
+"ui/consts/issue-46553.rs",
+"ui/consts/issue-50439.rs",
+"ui/consts/issue-52023-array-size-pointer-cast.rs",
+"ui/consts/issue-52060.rs",
+"ui/consts/issue-54224.rs",
+"ui/consts/issue-54348.rs",
+"ui/consts/issue-54582.rs",
+"ui/consts/issue-54954.rs",
+"ui/consts/issue-56164.rs",
+"ui/consts/issue-58435-ice-with-assoc-const.rs",
+"ui/consts/issue-64506.rs",
+"ui/consts/issue-64662.rs",
+"ui/consts/issue-66693-panic-in-array-len.rs",
+"ui/consts/issue-66693.rs",
+"ui/consts/issue-68542-closure-in-array-len.rs",
+"ui/consts/issue-69191-ice-on-uninhabited-enum-field.rs",
+"ui/consts/issue-69310-array-size-lit-wrong-ty.rs",
+"ui/consts/issue-69312.rs",
+"ui/consts/issue-69488.rs",
+"ui/consts/issue-69532.rs",
+"ui/consts/issue-70773-mir-typeck-lt-norm.rs",
+"ui/consts/issue-70942-trait-vs-impl-mismatch.rs",
+"ui/consts/issue-73976-monomorphic.rs",
+"ui/consts/issue-73976-polymorphic.rs",
+"ui/consts/issue-76064.rs",
+"ui/consts/issue-77062-large-zst-array.rs",
+"ui/consts/issue-78655.rs",
+"ui/consts/issue-79137-toogeneric.rs",
+"ui/consts/issue-83182.rs",
+"ui/consts/issue-87046.rs",
+"ui/consts/issue-90762.rs",
+"ui/consts/issue-90878-2.rs",
+"ui/consts/issue-90878-3.rs",
+"ui/consts/issue-90878.rs",
+"ui/consts/issue-91434.rs",
+"ui/consts/issue-94675.rs",
+"ui/consts/issue-104155.rs",
+"ui/consts/issue-104396.rs",
+"ui/consts/issue-13837.rs",
+"ui/consts/issue-16538.rs",
+"ui/consts/issue-28822.rs",
+"ui/consts/issue-29798.rs",
+"ui/consts/issue-33903.rs",
+"ui/consts/issue-3521.rs",
+"ui/consts/issue-37550-1.rs",
+"ui/consts/issue-39161-bogus-error.rs",
+"ui/consts/issue-47789.rs",
+"ui/consts/issue-54387.rs",
+"ui/consts/issue-62045.rs",
+"ui/consts/issue-63226.rs",
+"ui/consts/issue-63952.rs",
+"ui/consts/issue-64059.rs",
+"ui/consts/issue-65348.rs",
+"ui/consts/issue-66342.rs",
+"ui/consts/issue-66345.rs",
+"ui/consts/issue-66397.rs",
+"ui/consts/issue-66787.rs",
+"ui/consts/issue-67529.rs",
+"ui/consts/issue-67640.rs",
+"ui/consts/issue-67641.rs",
+"ui/consts/issue-67696-const-prop-ice.rs",
+"ui/consts/issue-67862.rs",
+"ui/consts/issue-68264-overflow.rs",
+"ui/consts/issue-68684.rs",
+"ui/consts/issue-6991.rs",
+"ui/consts/issue-79137-monomorphic.rs",
+"ui/consts/issue-79152-const-array-index.rs",
+"ui/consts/issue-79690.rs",
+"ui/consts/issue-88071.rs",
+"ui/consts/issue-88649.rs",
+"ui/consts/issue-89088.rs",
+"ui/consts/issue-90870.rs",
+"ui/consts/issue-91560.rs",
+"ui/consts/issue-94371.rs",
+"ui/consts/issue-96169.rs",
+"ui/consts/issue-17074.rs",
+"ui/cross-crate/issue-64872/issue-64872.rs",
+"ui/cycle-trait/issue-12511.rs",
+"ui/debuginfo/issue-105386-debuginfo-ub.rs",
+"ui/deprecation/issue-66340-deprecated-attr-non-meta-grammar.rs",
+"ui/deprecation/issue-84637-deprecated-associated-function.rs",
+"ui/derived-errors/issue-30580.rs",
+"ui/derived-errors/issue-31997-1.rs",
+"ui/derived-errors/issue-31997.rs",
+"ui/derives/issue-36617.rs",
+"ui/derives/issue-43023.rs",
+"ui/derives/issue-91492.rs",
+"ui/derives/issue-91550.rs",
+"ui/derives/issue-97343.rs",
+"ui/deriving/issue-103157.rs",
+"ui/deriving/issue-15689-1.rs",
+"ui/deriving/issue-19358.rs",
+"ui/deriving/issue-3935.rs",
+"ui/deriving/issue-58319.rs",
+"ui/deriving/issue-105101.rs",
+"ui/deriving/issue-15689-2.rs",
+"ui/deriving/issue-6341.rs",
+"ui/deriving/issue-89188-gat-hrtb.rs",
+"ui/did_you_mean/issue-103909.rs",
+"ui/did_you_mean/issue-21659-show-relevant-trait-impls-1.rs",
+"ui/did_you_mean/issue-21659-show-relevant-trait-impls-2.rs",
+"ui/did_you_mean/issue-31424.rs",
+"ui/did_you_mean/issue-34126.rs",
+"ui/did_you_mean/issue-34337.rs",
+"ui/did_you_mean/issue-35937.rs",
+"ui/did_you_mean/issue-36798.rs",
+"ui/did_you_mean/issue-36798_unknown_field.rs",
+"ui/did_you_mean/issue-37139.rs",
+"ui/did_you_mean/issue-38054-do-not-show-unresolved-names.rs",
+"ui/did_you_mean/issue-38147-1.rs",
+"ui/did_you_mean/issue-38147-2.rs",
+"ui/did_you_mean/issue-38147-3.rs",
+"ui/did_you_mean/issue-38147-4.rs",
+"ui/did_you_mean/issue-39544.rs",
+"ui/did_you_mean/issue-39802-show-5-trait-impls.rs",
+"ui/did_you_mean/issue-40006.rs",
+"ui/did_you_mean/issue-40396.rs",
+"ui/did_you_mean/issue-40823.rs",
+"ui/did_you_mean/issue-42599_available_fields_note.rs",
+"ui/did_you_mean/issue-42764.rs",
+"ui/did_you_mean/issue-43871-enum-instead-of-variant.rs",
+"ui/did_you_mean/issue-46718-struct-pattern-dotdotdot.rs",
+"ui/did_you_mean/issue-46836-identifier-not-instead-of-negation.rs",
+"ui/did_you_mean/issue-48492-tuple-destructure-missing-parens.rs",
+"ui/did_you_mean/issue-49746-unicode-confusable-in-float-literal-expt.rs",
+"ui/did_you_mean/issue-53280-expected-float-found-integer-literal.rs",
+"ui/did_you_mean/issue-54109-and_instead_of_ampersands.rs",
+"ui/did_you_mean/issue-56028-there-is-an-enum-variant.rs",
+"ui/did_you_mean/issue-87830-try-brackets-for-arrays.rs",
+"ui/did_you_mean/issue-93210-ignore-doc-hidden.rs",
+"ui/did_you_mean/issue-41679-tilde-bitwise-negation-attempt.rs",
+"ui/did_you_mean/issue-54109-without-witness.rs",
+"ui/drop/auxiliary/issue-10028.rs",
+"ui/drop/issue-10028.rs",
+"ui/drop/issue-21486.rs",
+"ui/drop/issue-23338-ensure-param-drop-order.rs",
+"ui/drop/issue-2734.rs",
+"ui/drop/issue-2735-2.rs",
+"ui/drop/issue-2735-3.rs",
+"ui/drop/issue-2735.rs",
+"ui/drop/issue-30018-nopanic.rs",
+"ui/drop/issue-35546.rs",
+"ui/drop/issue-48962.rs",
+"ui/drop/issue-90752-raw-ptr-shenanigans.rs",
+"ui/drop/issue-90752.rs",
+"ui/drop/issue-979.rs",
+"ui/drop/issue-100276.rs",
+"ui/drop/issue-103107.rs",
+"ui/drop/issue-110682.rs",
+"ui/drop/issue-17718-const-destructors.rs",
+"ui/dropck/issue-24805-dropck-itemless.rs",
+"ui/dropck/issue-28498-ugeh-with-lifetime-param.rs",
+"ui/dropck/issue-28498-ugeh-with-passed-to-fn.rs",
+"ui/dropck/issue-28498-ugeh-with-trait-bound.rs",
+"ui/dropck/issue-29844.rs",
+"ui/dropck/issue-34053.rs",
+"ui/dropck/issue-38868.rs",
+"ui/dropck/issue-54943-1.rs",
+"ui/dropck/issue-54943-2.rs",
+"ui/dst/issue-90528-unsizing-suggestion-1.rs",
+"ui/dst/issue-90528-unsizing-suggestion-2.rs",
+"ui/dst/issue-90528-unsizing-suggestion-3.rs",
+"ui/dst/issue-90528-unsizing-suggestion-4.rs",
+"ui/dyn-keyword/issue-56327-dyn-trait-in-macro-is-okay.rs",
+"ui/dyn-star/issue-102430.rs",
+"ui/empty/issue-37026.rs",
+"ui/enum-discriminant/auxiliary/issue-41394.rs",
+"ui/enum-discriminant/issue-104519.rs",
+"ui/enum-discriminant/issue-41394-rpass.rs",
+"ui/enum-discriminant/issue-41394.rs",
+"ui/enum-discriminant/issue-43398.rs",
+"ui/enum-discriminant/issue-51582.rs",
+"ui/enum-discriminant/issue-61696.rs",
+"ui/enum-discriminant/issue-70453-generics-in-discr-ice-2.rs",
+"ui/enum-discriminant/issue-70453-generics-in-discr-ice.rs",
+"ui/enum-discriminant/issue-70453-polymorphic-ctfe.rs",
+"ui/enum-discriminant/issue-70509-partial_eq.rs",
+"ui/enum-discriminant/issue-72554.rs",
+"ui/enum-discriminant/issue-90038.rs",
+"ui/enum-discriminant/issue-50689.rs",
+"ui/enum-discriminant/issue-46519.rs",
+"ui/enum/issue-42747.rs",
+"ui/enum/issue-67945-1.rs",
+"ui/enum/issue-67945-2.rs",
+"ui/enum/issue-1821.rs",
+"ui/error-codes/e0119/auxiliary/issue-23563-a.rs",
+"ui/error-codes/e0119/issue-23563.rs",
+"ui/error-codes/e0119/issue-27403.rs",
+"ui/error-codes/e0119/issue-28981.rs",
+"ui/errors/issue-99572-impl-trait-on-pointer.rs",
+"ui/errors/issue-104621-extern-bad-file.rs",
+"ui/errors/issue-104621-extern-not-file.rs",
+"ui/errors/issue-89280-emitter-overflow-splice-lines.rs",
+"ui/expr/if/issue-4201.rs",
+"ui/extenv/issue-55897.rs",
+"ui/extenv/issue-110547.rs",
+"ui/extern/auxiliary/issue-80074-macro.rs",
+"ui/extern/issue-10025.rs",
+"ui/extern/issue-10763.rs",
+"ui/extern/issue-10764-rpass.rs",
+"ui/extern/issue-13655.rs",
+"ui/extern/issue-36122-accessing-externed-dst.rs",
+"ui/extern/issue-112363-extern-item-where-clauses-debug-ice.rs",
+"ui/extern/issue-1251.rs",
+"ui/extern/issue-28324.rs",
+"ui/extern/issue-64655-allow-unwind-when-calling-panic-directly.rs",
+"ui/extern/issue-64655-extern-rust-must-allow-unwind.rs",
+"ui/extern/issue-80074.rs",
+"ui/extern/issue-95829.rs",
+"ui/feature-gates/issue-43106-gating-of-bench.rs",
+"ui/feature-gates/issue-43106-gating-of-builtin-attrs-error.rs",
+"ui/feature-gates/issue-43106-gating-of-derive-2.rs",
+"ui/feature-gates/issue-43106-gating-of-derive.rs",
+"ui/feature-gates/issue-43106-gating-of-macro_use.rs",
+"ui/feature-gates/issue-43106-gating-of-proc_macro_derive.rs",
+"ui/feature-gates/issue-43106-gating-of-stable.rs",
+"ui/feature-gates/issue-43106-gating-of-test.rs",
+"ui/feature-gates/issue-43106-gating-of-unstable.rs",
+"ui/feature-gates/issue-49983-see-issue-0.rs",
+"ui/feature-gates/issue-43106-gating-of-builtin-attrs.rs",
+"ui/feature-gates/issue-43106-gating-of-deprecated.rs",
+"ui/feature-gates/issue-43106-gating-of-macro_escape.rs",
+"ui/fmt/issue-103826.rs",
+"ui/fmt/issue-104142.rs",
+"ui/fmt/issue-75307.rs",
+"ui/fmt/issue-86085.rs",
+"ui/fmt/issue-89173.rs",
+"ui/fmt/issue-91556.rs",
+"ui/fn/issue-3044.rs",
+"ui/fn/issue-3099.rs",
+"ui/fn/issue-3904.rs",
+"ui/fn/issue-39259.rs",
+"ui/fn/issue-80179.rs",
+"ui/for-loop-while/issue-2216.rs",
+"ui/for-loop-while/issue-51345.rs",
+"ui/for-loop-while/issue-69841.rs",
+"ui/for-loop-while/issue-1257.rs",
+"ui/for/issue-20605.rs",
+"ui/foreign/issue-91370-foreign-fn-block-impl.rs",
+"ui/foreign/issue-74120-lowering-of-ffi-block-bodies.rs",
+"ui/foreign/issue-99276-same-type-lifetimes.rs",
+"ui/function-pointer/issue-102289.rs",
+"ui/functions-closures/closure-expected-type/issue-38714.rs",
+"ui/generator/issue-113279.rs",
+"ui/generator/issue-44197.rs",
+"ui/generator/issue-48048.rs",
+"ui/generator/issue-52398.rs",
+"ui/generator/issue-64620-yield-array-element.rs",
+"ui/generator/issue-69039.rs",
+"ui/generator/issue-88653.rs",
+"ui/generator/issue-91477.rs",
+"ui/generator/issue-102645.rs",
+"ui/generator/issue-105084.rs",
+"ui/generator/issue-110929-generator-conflict-error-ice.rs",
+"ui/generator/issue-45729-unsafe-in-generator.rs",
+"ui/generator/issue-52304.rs",
+"ui/generator/issue-53548-1.rs",
+"ui/generator/issue-53548.rs",
+"ui/generator/issue-57017.rs",
+"ui/generator/issue-57084.rs",
+"ui/generator/issue-57478.rs",
+"ui/generator/issue-58888.rs",
+"ui/generator/issue-61442-stmt-expr-with-drop.rs",
+"ui/generator/issue-62506-two_awaits.rs",
+"ui/generator/issue-68112.rs",
+"ui/generator/issue-69017.rs",
+"ui/generator/issue-87142.rs",
+"ui/generator/issue-93161.rs",
+"ui/generic-associated-types/bugs/issue-87735.rs",
+"ui/generic-associated-types/bugs/issue-87755.rs",
+"ui/generic-associated-types/bugs/issue-87803.rs",
+"ui/generic-associated-types/bugs/issue-88382.rs",
+"ui/generic-associated-types/bugs/issue-88460.rs",
+"ui/generic-associated-types/bugs/issue-88526.rs",
+"ui/generic-associated-types/bugs/issue-91762.rs",
+"ui/generic-associated-types/bugs/issue-100013.rs",
+"ui/generic-associated-types/bugs/issue-80626.rs",
+"ui/generic-associated-types/issue-101020.rs",
+"ui/generic-associated-types/issue-102114.rs",
+"ui/generic-associated-types/issue-102335-gat.rs",
+"ui/generic-associated-types/issue-47206-where-clause.rs",
+"ui/generic-associated-types/issue-67510.rs",
+"ui/generic-associated-types/issue-68641-check-gat-bounds.rs",
+"ui/generic-associated-types/issue-68642-broken-llvm-ir.rs",
+"ui/generic-associated-types/issue-68643-broken-mir.rs",
+"ui/generic-associated-types/issue-68644-codegen-selection.rs",
+"ui/generic-associated-types/issue-68645-codegen-fulfillment.rs",
+"ui/generic-associated-types/issue-68648-2.rs",
+"ui/generic-associated-types/issue-68656-unsized-values.rs",
+"ui/generic-associated-types/issue-70304.rs",
+"ui/generic-associated-types/issue-71176.rs",
+"ui/generic-associated-types/issue-74684-1.rs",
+"ui/generic-associated-types/issue-74684-2.rs",
+"ui/generic-associated-types/issue-74816.rs",
+"ui/generic-associated-types/issue-74824.rs",
+"ui/generic-associated-types/issue-76826.rs",
+"ui/generic-associated-types/issue-78113-lifetime-mismatch-dyn-trait-box.rs",
+"ui/generic-associated-types/issue-79636-1.rs",
+"ui/generic-associated-types/issue-79636-2.rs",
+"ui/generic-associated-types/issue-80433.rs",
+"ui/generic-associated-types/issue-81487.rs",
+"ui/generic-associated-types/issue-81712-cyclic-traits.rs",
+"ui/generic-associated-types/issue-81862.rs",
+"ui/generic-associated-types/issue-84931.rs",
+"ui/generic-associated-types/issue-86787.rs",
+"ui/generic-associated-types/issue-87258_a.rs",
+"ui/generic-associated-types/issue-87258_b.rs",
+"ui/generic-associated-types/issue-87429-associated-type-default.rs",
+"ui/generic-associated-types/issue-87429-specialization.rs",
+"ui/generic-associated-types/issue-91139.rs",
+"ui/generic-associated-types/issue-91883.rs",
+"ui/generic-associated-types/issue-92033.rs",
+"ui/generic-associated-types/issue-95305.rs",
+"ui/generic-associated-types/issue-102333.rs",
+"ui/generic-associated-types/issue-58694-parameter-out-of-range.rs",
+"ui/generic-associated-types/issue-62326-parameter-out-of-range.rs",
+"ui/generic-associated-types/issue-67424.rs",
+"ui/generic-associated-types/issue-67510-pass.rs",
+"ui/generic-associated-types/issue-68648-1.rs",
+"ui/generic-associated-types/issue-68649-pass.rs",
+"ui/generic-associated-types/issue-68653.rs",
+"ui/generic-associated-types/issue-70303.rs",
+"ui/generic-associated-types/issue-76407.rs",
+"ui/generic-associated-types/issue-76535.rs",
+"ui/generic-associated-types/issue-78671.rs",
+"ui/generic-associated-types/issue-79422.rs",
+"ui/generic-associated-types/issue-80433-reduced.rs",
+"ui/generic-associated-types/issue-85921.rs",
+"ui/generic-associated-types/issue-86218-2.rs",
+"ui/generic-associated-types/issue-86218.rs",
+"ui/generic-associated-types/issue-86483.rs",
+"ui/generic-associated-types/issue-87429-2.rs",
+"ui/generic-associated-types/issue-87429.rs",
+"ui/generic-associated-types/issue-87748.rs",
+"ui/generic-associated-types/issue-87750.rs",
+"ui/generic-associated-types/issue-88287.rs",
+"ui/generic-associated-types/issue-88360.rs",
+"ui/generic-associated-types/issue-88405.rs",
+"ui/generic-associated-types/issue-88459.rs",
+"ui/generic-associated-types/issue-89008.rs",
+"ui/generic-associated-types/issue-89352.rs",
+"ui/generic-associated-types/issue-90014.rs",
+"ui/generic-associated-types/issue-90729.rs",
+"ui/generic-associated-types/issue-92096.rs",
+"ui/generic-associated-types/issue-92280.rs",
+"ui/generic-associated-types/issue-92954.rs",
+"ui/generic-associated-types/issue-93141.rs",
+"ui/generic-associated-types/issue-93262.rs",
+"ui/generic-associated-types/issue-93340.rs",
+"ui/generic-associated-types/issue-93341.rs",
+"ui/generic-associated-types/issue-93342.rs",
+"ui/generic-associated-types/issue-93874.rs",
+"ui/generic-associated-types/issue-88595.rs",
+"ui/generic-associated-types/issue-90014-tait.rs",
+"ui/generic-associated-types/issue-90014-tait2.rs",
+"ui/generics/issue-106694.rs",
+"ui/generics/issue-1112.rs",
+"ui/generics/issue-2936.rs",
+"ui/generics/issue-32498.rs",
+"ui/generics/issue-333.rs",
+"ui/generics/issue-59508-1.rs",
+"ui/generics/issue-61631-default-type-param-can-reference-self-in-trait.rs",
+"ui/generics/issue-61631-default-type-param-cannot-reference-self.rs",
+"ui/generics/issue-65285-incorrect-explicit-lifetime-name-needed.rs",
+"ui/generics/issue-79605.rs",
+"ui/generics/issue-80512-param-reordering-with-defaults.rs",
+"ui/generics/issue-94432-garbage-ice.rs",
+"ui/generics/issue-98432.rs",
+"ui/generics/issue-59508.rs",
+"ui/generics/issue-94923.rs",
+"ui/generics/issue-95208-ignore-qself.rs",
+"ui/generics/issue-95208.rs",
+"ui/hygiene/issue-15221.rs",
+"ui/hygiene/issue-40847.rs",
+"ui/hygiene/issue-77523-def-site-async-await.rs",
+"ui/hygiene/issue-32922.rs",
+"ui/hygiene/issue-44128.rs",
+"ui/hygiene/issue-47311.rs",
+"ui/hygiene/issue-47312.rs",
+"ui/hygiene/issue-61574-const-parameters.rs",
+"ui/impl-trait/explicit-generic-args-with-impl-trait/issue-87718.rs",
+"ui/impl-trait/in-trait/issue-102140.rs",
+"ui/impl-trait/in-trait/issue-102301.rs",
+"ui/impl-trait/in-trait/issue-102571.rs",
+"ui/impl-trait/issues/issue-21659-show-relevant-trait-impls-3.rs",
+"ui/impl-trait/issues/issue-54600.rs",
+"ui/impl-trait/issues/issue-54840.rs",
+"ui/impl-trait/issues/issue-54895.rs",
+"ui/impl-trait/issues/issue-57979-deeply-nested-impl-trait-in-assoc-proj.rs",
+"ui/impl-trait/issues/issue-57979-impl-trait-in-path.rs",
+"ui/impl-trait/issues/issue-57979-nested-impl-trait-in-assoc-proj.rs",
+"ui/impl-trait/issues/issue-58504.rs",
+"ui/impl-trait/issues/issue-58956.rs",
+"ui/impl-trait/issues/issue-62742.rs",
+"ui/impl-trait/issues/issue-67830.rs",
+"ui/impl-trait/issues/issue-70971.rs",
+"ui/impl-trait/issues/issue-79099.rs",
+"ui/impl-trait/issues/issue-82139.rs",
+"ui/impl-trait/issues/issue-83929-impl-trait-in-generic-default.rs",
+"ui/impl-trait/issues/issue-84073.rs",
+"ui/impl-trait/issues/issue-84919.rs",
+"ui/impl-trait/issues/issue-86642.rs",
+"ui/impl-trait/issues/issue-86719.rs",
+"ui/impl-trait/issues/issue-87295.rs",
+"ui/impl-trait/issues/issue-87340.rs",
+"ui/impl-trait/issues/issue-88236-2.rs",
+"ui/impl-trait/issues/issue-88236.rs",
+"ui/impl-trait/issues/issue-99348-impl-compatibility.rs",
+"ui/impl-trait/issues/issue-104815.rs",
+"ui/impl-trait/issues/issue-105826.rs",
+"ui/impl-trait/issues/issue-42479.rs",
+"ui/impl-trait/issues/issue-49376.rs",
+"ui/impl-trait/issues/issue-52128.rs",
+"ui/impl-trait/issues/issue-53457.rs",
+"ui/impl-trait/issues/issue-55608-captures-empty-region.rs",
+"ui/impl-trait/issues/issue-57464-unexpected-regions.rs",
+"ui/impl-trait/issues/issue-77987.rs",
+"ui/impl-trait/issues/issue-83919.rs",
+"ui/impl-trait/issues/issue-86201.rs",
+"ui/impl-trait/issues/issue-86800.rs",
+"ui/impl-trait/issues/issue-89312.rs",
+"ui/impl-trait/issues/issue-92305.rs",
+"ui/impl-trait/issues/issue-93788.rs",
+"ui/impl-trait/issues/issue-65581.rs",
+"ui/impl-trait/issues/issue-70877.rs",
+"ui/impl-trait/issues/issue-74282.rs",
+"ui/impl-trait/issues/issue-78722-2.rs",
+"ui/impl-trait/issues/issue-78722.rs",
+"ui/impl-trait/issue-100075-2.rs",
+"ui/impl-trait/issue-100075.rs",
+"ui/impl-trait/issue-35668.rs",
+"ui/impl-trait/issue-36792.rs",
+"ui/impl-trait/issue-49685.rs",
+"ui/impl-trait/issue-51185.rs",
+"ui/impl-trait/issue-54966.rs",
+"ui/impl-trait/issue-55872-1.rs",
+"ui/impl-trait/issue-55872.rs",
+"ui/impl-trait/issue-72911.rs",
+"ui/impl-trait/issue-86465.rs",
+"ui/impl-trait/issue-87450.rs",
+"ui/impl-trait/issue-99073-2.rs",
+"ui/impl-trait/issue-99073.rs",
+"ui/impl-trait/issue-100187.rs",
+"ui/impl-trait/issue-102605.rs",
+"ui/impl-trait/issue-103181-1.rs",
+"ui/impl-trait/issue-103599.rs",
+"ui/impl-trait/issue-108591.rs",
+"ui/impl-trait/issue-108592.rs",
+"ui/impl-trait/issue-46959.rs",
+"ui/impl-trait/issue-49556.rs",
+"ui/impl-trait/issue-49579.rs",
+"ui/impl-trait/issue-55872-2.rs",
+"ui/impl-trait/issue-56445.rs",
+"ui/impl-trait/issue-68532.rs",
+"ui/impl-trait/issue-99642-2.rs",
+"ui/impl-trait/issue-99642.rs",
+"ui/impl-trait/issue-99914.rs",
+"ui/impl-trait/issue-103181-2.rs",
+"ui/impl-trait/issue-55872-3.rs",
+"ui/implied-bounds/issue-100690.rs",
+"ui/implied-bounds/issue-101951.rs",
+"ui/implied-bounds/issue-110161.rs",
+"ui/imports/auxiliary/issue-36881-aux.rs",
+"ui/imports/auxiliary/issue-52891.rs",
+"ui/imports/auxiliary/issue-55811.rs",
+"ui/imports/auxiliary/issue-56125.rs",
+"ui/imports/auxiliary/issue-59764.rs",
+"ui/imports/auxiliary/issue-85992-extern-1.rs",
+"ui/imports/auxiliary/issue-85992-extern-2.rs",
+"ui/imports/issue-26873-multifile/issue-26873-multifile.rs",
+"ui/imports/issue-26873-multifile/issue-26873-onefile.rs",
+"ui/imports/issue-45829/auxiliary/issue-45829-a.rs",
+"ui/imports/issue-45829/auxiliary/issue-45829-b.rs",
+"ui/imports/issue-45829/issue-45829.rs",
+"ui/imports/issue-113953.rs",
+"ui/imports/issue-109343.rs",
+"ui/imports/issue-13404.rs",
+"ui/imports/issue-1697.rs",
+"ui/imports/issue-19498.rs",
+"ui/imports/issue-24081.rs",
+"ui/imports/issue-25396.rs",
+"ui/imports/issue-26886.rs",
+"ui/imports/issue-28388-1.rs",
+"ui/imports/issue-28388-2.rs",
+"ui/imports/issue-2937.rs",
+"ui/imports/issue-30560.rs",
+"ui/imports/issue-31212.rs",
+"ui/imports/issue-32833.rs",
+"ui/imports/issue-33464.rs",
+"ui/imports/issue-36881.rs",
+"ui/imports/issue-37887.rs",
+"ui/imports/issue-38293.rs",
+"ui/imports/issue-4366-2.rs",
+"ui/imports/issue-4366.rs",
+"ui/imports/issue-47623.rs",
+"ui/imports/issue-4865-1.rs",
+"ui/imports/issue-4865-2.rs",
+"ui/imports/issue-4865-3.rs",
+"ui/imports/issue-53269.rs",
+"ui/imports/issue-53512.rs",
+"ui/imports/issue-53565.rs",
+"ui/imports/issue-55457.rs",
+"ui/imports/issue-55884-1.rs",
+"ui/imports/issue-57015.rs",
+"ui/imports/issue-8208.rs",
+"ui/imports/issue-8640.rs",
+"ui/imports/issue-55884-2.rs",
+"ui/imports/issue-109148.rs",
+"ui/imports/issue-18083.rs",
+"ui/imports/issue-24883.rs",
+"ui/imports/issue-26930.rs",
+"ui/imports/issue-28134.rs",
+"ui/imports/issue-32119.rs",
+"ui/imports/issue-32222.rs",
+"ui/imports/issue-32354-suggest-import-rename.rs",
+"ui/imports/issue-45799-bad-extern-crate-rename-suggestion-formatting.rs",
+"ui/imports/issue-52891.rs",
+"ui/imports/issue-53140.rs",
+"ui/imports/issue-55811.rs",
+"ui/imports/issue-56125.rs",
+"ui/imports/issue-56263.rs",
+"ui/imports/issue-57539.rs",
+"ui/imports/issue-59764.rs",
+"ui/imports/issue-62767.rs",
+"ui/imports/issue-68103.rs",
+"ui/imports/issue-99695-b.rs",
+"ui/imports/issue-99695.rs",
+"ui/imports/issue-85992.rs",
+"ui/inference/need_type_info/issue-103053.rs",
+"ui/inference/need_type_info/issue-107745-avoid-expr-from-macro-expansion.rs",
+"ui/inference/need_type_info/issue-109905.rs",
+"ui/inference/need_type_info/issue-113264-incorrect-impl-trait-in-path-suggestion.rs",
+"ui/inference/issue-103587.rs",
+"ui/inference/issue-104649.rs",
+"ui/inference/issue-107090.rs",
+"ui/inference/issue-36053.rs",
+"ui/inference/issue-70082.rs",
+"ui/inference/issue-71309.rs",
+"ui/inference/issue-71584.rs",
+"ui/inference/issue-71732.rs",
+"ui/inference/issue-72616.rs",
+"ui/inference/issue-72690.rs",
+"ui/inference/issue-80816.rs",
+"ui/inference/issue-81522.rs",
+"ui/inference/issue-83606.rs",
+"ui/inference/issue-86162-1.rs",
+"ui/inference/issue-86162-2.rs",
+"ui/inference/issue-28935.rs",
+"ui/inference/issue-70703.rs",
+"ui/inference/issue-80409.rs",
+"ui/inference/issue-113354.rs",
+"ui/infinite/issue-41731-infinite-macro-print.rs",
+"ui/infinite/issue-41731-infinite-macro-println.rs",
+"ui/intrinsics/issue-28575.rs",
+"ui/intrinsics/issue-84297-reifying-copy.rs",
+"ui/issues/auxiliary/issue-11224.rs",
+"ui/issues/auxiliary/issue-11508.rs",
+"ui/issues/auxiliary/issue-11529.rs",
+"ui/issues/auxiliary/issue-11680.rs",
+"ui/issues/auxiliary/issue-12133-dylib.rs",
+"ui/issues/auxiliary/issue-12133-dylib2.rs",
+"ui/issues/auxiliary/issue-12133-rlib.rs",
+"ui/issues/auxiliary/issue-12612-1.rs",
+"ui/issues/auxiliary/issue-12612-2.rs",
+"ui/issues/auxiliary/issue-12660-aux.rs",
+"ui/issues/auxiliary/issue-13507.rs",
+"ui/issues/auxiliary/issue-13620-1.rs",
+"ui/issues/auxiliary/issue-13620-2.rs",
+"ui/issues/auxiliary/issue-13872-1.rs",
+"ui/issues/auxiliary/issue-13872-2.rs",
+"ui/issues/auxiliary/issue-13872-3.rs",
+"ui/issues/auxiliary/issue-14344-1.rs",
+"ui/issues/auxiliary/issue-14344-2.rs",
+"ui/issues/auxiliary/issue-14421.rs",
+"ui/issues/auxiliary/issue-14422.rs",
+"ui/issues/auxiliary/issue-15562.rs",
+"ui/issues/auxiliary/issue-16643.rs",
+"ui/issues/auxiliary/issue-16725.rs",
+"ui/issues/auxiliary/issue-17662.rs",
+"ui/issues/auxiliary/issue-18501.rs",
+"ui/issues/auxiliary/issue-18514.rs",
+"ui/issues/auxiliary/issue-18711.rs",
+"ui/issues/auxiliary/issue-18913-1.rs",
+"ui/issues/auxiliary/issue-18913-2.rs",
+"ui/issues/auxiliary/issue-1920.rs",
+"ui/issues/auxiliary/issue-19293.rs",
+"ui/issues/auxiliary/issue-19340-1.rs",
+"ui/issues/auxiliary/issue-20389.rs",
+"ui/issues/auxiliary/issue-21202.rs",
+"ui/issues/auxiliary/issue-2170-lib.rs",
+"ui/issues/auxiliary/issue-2316-a.rs",
+"ui/issues/auxiliary/issue-2316-b.rs",
+"ui/issues/auxiliary/issue-2380.rs",
+"ui/issues/auxiliary/issue-2414-a.rs",
+"ui/issues/auxiliary/issue-2414-b.rs",
+"ui/issues/auxiliary/issue-2472-b.rs",
+"ui/issues/auxiliary/issue-25185-1.rs",
+"ui/issues/auxiliary/issue-25185-2.rs",
+"ui/issues/auxiliary/issue-2526.rs",
+"ui/issues/auxiliary/issue-25467.rs",
+"ui/issues/auxiliary/issue-2631-a.rs",
+"ui/issues/auxiliary/issue-2723-a.rs",
+"ui/issues/auxiliary/issue-29181.rs",
+"ui/issues/auxiliary/issue-29265.rs",
+"ui/issues/auxiliary/issue-29485.rs",
+"ui/issues/auxiliary/issue-3012-1.rs",
+"ui/issues/auxiliary/issue-30123-aux.rs",
+"ui/issues/auxiliary/issue-3136-a.rs",
+"ui/issues/auxiliary/issue-31702-1.rs",
+"ui/issues/auxiliary/issue-34796-aux.rs",
+"ui/issues/auxiliary/issue-36954.rs",
+"ui/issues/auxiliary/issue-38190.rs",
+"ui/issues/auxiliary/issue-38226-aux.rs",
+"ui/issues/auxiliary/issue-3979-traits.rs",
+"ui/issues/auxiliary/issue-41053.rs",
+"ui/issues/auxiliary/issue-41549.rs",
+"ui/issues/auxiliary/issue-42007-s.rs",
+"ui/issues/auxiliary/issue-4208-cc.rs",
+"ui/issues/auxiliary/issue-4545.rs",
+"ui/issues/auxiliary/issue-48984-aux.rs",
+"ui/issues/auxiliary/issue-49544.rs",
+"ui/issues/auxiliary/issue-51798.rs",
+"ui/issues/auxiliary/issue-52489.rs",
+"ui/issues/auxiliary/issue-5518.rs",
+"ui/issues/auxiliary/issue-5521.rs",
+"ui/issues/auxiliary/issue-56943.rs",
+"ui/issues/auxiliary/issue-57271-lib.rs",
+"ui/issues/auxiliary/issue-5844-aux.rs",
+"ui/issues/auxiliary/issue-7178.rs",
+"ui/issues/auxiliary/issue-73112.rs",
+"ui/issues/auxiliary/issue-7899.rs",
+"ui/issues/auxiliary/issue-8044.rs",
+"ui/issues/auxiliary/issue-8259.rs",
+"ui/issues/auxiliary/issue-8401.rs",
+"ui/issues/auxiliary/issue-9123.rs",
+"ui/issues/auxiliary/issue-9155.rs",
+"ui/issues/auxiliary/issue-9188.rs",
+"ui/issues/auxiliary/issue-9906.rs",
+"ui/issues/auxiliary/issue-9968.rs",
+"ui/issues/auxiliary/issue-111011.rs",
+"ui/issues/auxiliary/issue-31702-2.rs",
+"ui/issues/issue-24687-embed-debuginfo/auxiliary/issue-24687-lib.rs",
+"ui/issues/issue-24687-embed-debuginfo/auxiliary/issue-24687-mbcs-in-comments.rs",
+"ui/issues/issue-37311-type-length-limit/issue-37311.rs",
+"ui/issues/issue-38875/auxiliary/issue-38875-b.rs",
+"ui/issues/issue-38875/issue-38875.rs",
+"ui/issues/issue-40402-ref-hints/issue-40402-1.rs",
+"ui/issues/issue-40402-ref-hints/issue-40402-2.rs",
+"ui/issues/issue-41652/auxiliary/issue-41652-b.rs",
+"ui/issues/issue-41652/issue-41652.rs",
+"ui/issues/issue-70093/issue-70093-link-directives.rs",
+"ui/issues/issue-70093/issue-70093.rs",
+"ui/issues/issue-77218/issue-77218-2.rs",
+"ui/issues/issue-77218/issue-77218.rs",
+"ui/issues/issue-100605.rs",
+"ui/issues/issue-10228.rs",
+"ui/issues/issue-10291.rs",
+"ui/issues/issue-102964.rs",
+"ui/issues/issue-10412.rs",
+"ui/issues/issue-10436.rs",
+"ui/issues/issue-10465.rs",
+"ui/issues/issue-10545.rs",
+"ui/issues/issue-10638.rs",
+"ui/issues/issue-10656.rs",
+"ui/issues/issue-10682.rs",
+"ui/issues/issue-10683.rs",
+"ui/issues/issue-10718.rs",
+"ui/issues/issue-10734.rs",
+"ui/issues/issue-10764.rs",
+"ui/issues/issue-10767.rs",
+"ui/issues/issue-10802.rs",
+"ui/issues/issue-10806.rs",
+"ui/issues/issue-10877.rs",
+"ui/issues/issue-11004.rs",
+"ui/issues/issue-11192.rs",
+"ui/issues/issue-11205.rs",
+"ui/issues/issue-11224.rs",
+"ui/issues/issue-11267.rs",
+"ui/issues/issue-11374.rs",
+"ui/issues/issue-11382.rs",
+"ui/issues/issue-11508.rs",
+"ui/issues/issue-11529.rs",
+"ui/issues/issue-11552.rs",
+"ui/issues/issue-11593.rs",
+"ui/issues/issue-11677.rs",
+"ui/issues/issue-11680.rs",
+"ui/issues/issue-11681.rs",
+"ui/issues/issue-11692-1.rs",
+"ui/issues/issue-11692-2.rs",
+"ui/issues/issue-11771.rs",
+"ui/issues/issue-11820.rs",
+"ui/issues/issue-11844.rs",
+"ui/issues/issue-11873.rs",
+"ui/issues/issue-11958.rs",
+"ui/issues/issue-12028.rs",
+"ui/issues/issue-12033.rs",
+"ui/issues/issue-12041.rs",
+"ui/issues/issue-12127.rs",
+"ui/issues/issue-12133-1.rs",
+"ui/issues/issue-12133-2.rs",
+"ui/issues/issue-12187-1.rs",
+"ui/issues/issue-12187-2.rs",
+"ui/issues/issue-12285.rs",
+"ui/issues/issue-12567.rs",
+"ui/issues/issue-12612.rs",
+"ui/issues/issue-12660.rs",
+"ui/issues/issue-12677.rs",
+"ui/issues/issue-12699.rs",
+"ui/issues/issue-12744.rs",
+"ui/issues/issue-12860.rs",
+"ui/issues/issue-12863.rs",
+"ui/issues/issue-12909.rs",
+"ui/issues/issue-13027.rs",
+"ui/issues/issue-13033.rs",
+"ui/issues/issue-13058.rs",
+"ui/issues/issue-13204.rs",
+"ui/issues/issue-13214.rs",
+"ui/issues/issue-13259-windows-tcb-trash.rs",
+"ui/issues/issue-13264.rs",
+"ui/issues/issue-13323.rs",
+"ui/issues/issue-13359.rs",
+"ui/issues/issue-13407.rs",
+"ui/issues/issue-13434.rs",
+"ui/issues/issue-13446.rs",
+"ui/issues/issue-13466.rs",
+"ui/issues/issue-13482.rs",
+"ui/issues/issue-13497-2.rs",
+"ui/issues/issue-13497.rs",
+"ui/issues/issue-13507-2.rs",
+"ui/issues/issue-1362.rs",
+"ui/issues/issue-13620.rs",
+"ui/issues/issue-13665.rs",
+"ui/issues/issue-13763.rs",
+"ui/issues/issue-13808.rs",
+"ui/issues/issue-13847.rs",
+"ui/issues/issue-13867.rs",
+"ui/issues/issue-13872.rs",
+"ui/issues/issue-14091-2.rs",
+"ui/issues/issue-14091.rs",
+"ui/issues/issue-14092.rs",
+"ui/issues/issue-14229.rs",
+"ui/issues/issue-14285.rs",
+"ui/issues/issue-14308.rs",
+"ui/issues/issue-14344.rs",
+"ui/issues/issue-14366.rs",
+"ui/issues/issue-14382.rs",
+"ui/issues/issue-14393.rs",
+"ui/issues/issue-14399.rs",
+"ui/issues/issue-14421.rs",
+"ui/issues/issue-14422.rs",
+"ui/issues/issue-1448-2.rs",
+"ui/issues/issue-1451.rs",
+"ui/issues/issue-14541.rs",
+"ui/issues/issue-1460.rs",
+"ui/issues/issue-14721.rs",
+"ui/issues/issue-1476.rs",
+"ui/issues/issue-14821.rs",
+"ui/issues/issue-14845.rs",
+"ui/issues/issue-14853.rs",
+"ui/issues/issue-14865.rs",
+"ui/issues/issue-14875.rs",
+"ui/issues/issue-14915.rs",
+"ui/issues/issue-14919.rs",
+"ui/issues/issue-15034.rs",
+"ui/issues/issue-15043.rs",
+"ui/issues/issue-15063.rs",
+"ui/issues/issue-15094.rs",
+"ui/issues/issue-15104.rs",
+"ui/issues/issue-15129-rpass.rs",
+"ui/issues/issue-15155.rs",
+"ui/issues/issue-15167.rs",
+"ui/issues/issue-15189.rs",
+"ui/issues/issue-15207.rs",
+"ui/issues/issue-15260.rs",
+"ui/issues/issue-15381.rs",
+"ui/issues/issue-15444.rs",
+"ui/issues/issue-15523-big.rs",
+"ui/issues/issue-15523.rs",
+"ui/issues/issue-15562.rs",
+"ui/issues/issue-15571.rs",
+"ui/issues/issue-15673.rs",
+"ui/issues/issue-15756.rs",
+"ui/issues/issue-15763.rs",
+"ui/issues/issue-15774.rs",
+"ui/issues/issue-15783.rs",
+"ui/issues/issue-15793.rs",
+"ui/issues/issue-15858.rs",
+"ui/issues/issue-15896.rs",
+"ui/issues/issue-15965.rs",
+"ui/issues/issue-16048.rs",
+"ui/issues/issue-16149.rs",
+"ui/issues/issue-16151.rs",
+"ui/issues/issue-16250.rs",
+"ui/issues/issue-16256.rs",
+"ui/issues/issue-16278.rs",
+"ui/issues/issue-16338.rs",
+"ui/issues/issue-16401.rs",
+"ui/issues/issue-16441.rs",
+"ui/issues/issue-16452.rs",
+"ui/issues/issue-16492.rs",
+"ui/issues/issue-16530.rs",
+"ui/issues/issue-16560.rs",
+"ui/issues/issue-16562.rs",
+"ui/issues/issue-1660.rs",
+"ui/issues/issue-16643.rs",
+"ui/issues/issue-16648.rs",
+"ui/issues/issue-16671.rs",
+"ui/issues/issue-16683.rs",
+"ui/issues/issue-16725.rs",
+"ui/issues/issue-16739.rs",
+"ui/issues/issue-16745.rs",
+"ui/issues/issue-16774.rs",
+"ui/issues/issue-16783.rs",
+"ui/issues/issue-16819.rs",
+"ui/issues/issue-16922-rpass.rs",
+"ui/issues/issue-16922.rs",
+"ui/issues/issue-16939.rs",
+"ui/issues/issue-1696.rs",
+"ui/issues/issue-16966.rs",
+"ui/issues/issue-17001.rs",
+"ui/issues/issue-17033.rs",
+"ui/issues/issue-17068.rs",
+"ui/issues/issue-17216.rs",
+"ui/issues/issue-17252.rs",
+"ui/issues/issue-17302.rs",
+"ui/issues/issue-17322.rs",
+"ui/issues/issue-17336.rs",
+"ui/issues/issue-17337.rs",
+"ui/issues/issue-17351.rs",
+"ui/issues/issue-17361.rs",
+"ui/issues/issue-17373.rs",
+"ui/issues/issue-17385.rs",
+"ui/issues/issue-17405.rs",
+"ui/issues/issue-17431-1.rs",
+"ui/issues/issue-17431-2.rs",
+"ui/issues/issue-17431-3.rs",
+"ui/issues/issue-17431-4.rs",
+"ui/issues/issue-17431-5.rs",
+"ui/issues/issue-17431-6.rs",
+"ui/issues/issue-17431-7.rs",
+"ui/issues/issue-17441.rs",
+"ui/issues/issue-17450.rs",
+"ui/issues/issue-17503.rs",
+"ui/issues/issue-17546.rs",
+"ui/issues/issue-17551.rs",
+"ui/issues/issue-17651.rs",
+"ui/issues/issue-17662.rs",
+"ui/issues/issue-17734.rs",
+"ui/issues/issue-17740.rs",
+"ui/issues/issue-17758.rs",
+"ui/issues/issue-17771.rs",
+"ui/issues/issue-17800.rs",
+"ui/issues/issue-17816.rs",
+"ui/issues/issue-17877.rs",
+"ui/issues/issue-17897.rs",
+"ui/issues/issue-17904-2.rs",
+"ui/issues/issue-17905-2.rs",
+"ui/issues/issue-17905.rs",
+"ui/issues/issue-17933.rs",
+"ui/issues/issue-17954.rs",
+"ui/issues/issue-17959.rs",
+"ui/issues/issue-17994.rs",
+"ui/issues/issue-17999.rs",
+"ui/issues/issue-18058.rs",
+"ui/issues/issue-18107.rs",
+"ui/issues/issue-18110.rs",
+"ui/issues/issue-18119.rs",
+"ui/issues/issue-18159.rs",
+"ui/issues/issue-18173.rs",
+"ui/issues/issue-18183.rs",
+"ui/issues/issue-18232.rs",
+"ui/issues/issue-18352.rs",
+"ui/issues/issue-18353.rs",
+"ui/issues/issue-18423.rs",
+"ui/issues/issue-18446.rs",
+"ui/issues/issue-18464.rs",
+"ui/issues/issue-18501.rs",
+"ui/issues/issue-18514.rs",
+"ui/issues/issue-18532.rs",
+"ui/issues/issue-18539.rs",
+"ui/issues/issue-18566.rs",
+"ui/issues/issue-18611.rs",
+"ui/issues/issue-18685.rs",
+"ui/issues/issue-18711.rs",
+"ui/issues/issue-18767.rs",
+"ui/issues/issue-18783.rs",
+"ui/issues/issue-18819.rs",
+"ui/issues/issue-18845.rs",
+"ui/issues/issue-18859.rs",
+"ui/issues/issue-18913.rs",
+"ui/issues/issue-18919.rs",
+"ui/issues/issue-18952.rs",
+"ui/issues/issue-18959.rs",
+"ui/issues/issue-1900.rs",
+"ui/issues/issue-19001.rs",
+"ui/issues/issue-19086.rs",
+"ui/issues/issue-19127.rs",
+"ui/issues/issue-19135.rs",
+"ui/issues/issue-1920-1.rs",
+"ui/issues/issue-1920-2.rs",
+"ui/issues/issue-1920-3.rs",
+"ui/issues/issue-19244-1.rs",
+"ui/issues/issue-19244-2.rs",
+"ui/issues/issue-19293.rs",
+"ui/issues/issue-19340-1.rs",
+"ui/issues/issue-19340-2.rs",
+"ui/issues/issue-19367.rs",
+"ui/issues/issue-19380.rs",
+"ui/issues/issue-19404.rs",
+"ui/issues/issue-19482.rs",
+"ui/issues/issue-19499.rs",
+"ui/issues/issue-19521.rs",
+"ui/issues/issue-19692.rs",
+"ui/issues/issue-19707.rs",
+"ui/issues/issue-19734.rs",
+"ui/issues/issue-1974.rs",
+"ui/issues/issue-19811-escape-unicode.rs",
+"ui/issues/issue-19922.rs",
+"ui/issues/issue-19991.rs",
+"ui/issues/issue-20055-box-trait.rs",
+"ui/issues/issue-20055-box-unsized-array.rs",
+"ui/issues/issue-20162.rs",
+"ui/issues/issue-20174.rs",
+"ui/issues/issue-20225.rs",
+"ui/issues/issue-20261.rs",
+"ui/issues/issue-20313-rpass.rs",
+"ui/issues/issue-20313.rs",
+"ui/issues/issue-20389.rs",
+"ui/issues/issue-20413.rs",
+"ui/issues/issue-20427.rs",
+"ui/issues/issue-20433.rs",
+"ui/issues/issue-20544.rs",
+"ui/issues/issue-20575.rs",
+"ui/issues/issue-20616.rs",
+"ui/issues/issue-20676.rs",
+"ui/issues/issue-20714.rs",
+"ui/issues/issue-2074.rs",
+"ui/issues/issue-20772.rs",
+"ui/issues/issue-20797.rs",
+"ui/issues/issue-20803.rs",
+"ui/issues/issue-20831-debruijn.rs",
+"ui/issues/issue-20847.rs",
+"ui/issues/issue-20939.rs",
+"ui/issues/issue-20953.rs",
+"ui/issues/issue-21033.rs",
+"ui/issues/issue-21160.rs",
+"ui/issues/issue-21174.rs",
+"ui/issues/issue-21177.rs",
+"ui/issues/issue-21202.rs",
+"ui/issues/issue-21291.rs",
+"ui/issues/issue-21306.rs",
+"ui/issues/issue-21332.rs",
+"ui/issues/issue-21361.rs",
+"ui/issues/issue-21384.rs",
+"ui/issues/issue-21400.rs",
+"ui/issues/issue-21449.rs",
+"ui/issues/issue-2150.rs",
+"ui/issues/issue-2151.rs",
+"ui/issues/issue-21546.rs",
+"ui/issues/issue-21554.rs",
+"ui/issues/issue-21596.rs",
+"ui/issues/issue-21600.rs",
+"ui/issues/issue-21634.rs",
+"ui/issues/issue-21655.rs",
+"ui/issues/issue-2170-exe.rs",
+"ui/issues/issue-21701.rs",
+"ui/issues/issue-21763.rs",
+"ui/issues/issue-21837.rs",
+"ui/issues/issue-21891.rs",
+"ui/issues/issue-2190-1.rs",
+"ui/issues/issue-21909.rs",
+"ui/issues/issue-21922.rs",
+"ui/issues/issue-21946.rs",
+"ui/issues/issue-21950.rs",
+"ui/issues/issue-21974.rs",
+"ui/issues/issue-22008.rs",
+"ui/issues/issue-22034.rs",
+"ui/issues/issue-22036.rs",
+"ui/issues/issue-2214.rs",
+"ui/issues/issue-22258.rs",
+"ui/issues/issue-22289.rs",
+"ui/issues/issue-22312.rs",
+"ui/issues/issue-22346.rs",
+"ui/issues/issue-22370.rs",
+"ui/issues/issue-22403.rs",
+"ui/issues/issue-22426.rs",
+"ui/issues/issue-22434.rs",
+"ui/issues/issue-22468.rs",
+"ui/issues/issue-22577.rs",
+"ui/issues/issue-22599.rs",
+"ui/issues/issue-22629.rs",
+"ui/issues/issue-22638.rs",
+"ui/issues/issue-22644.rs",
+"ui/issues/issue-22684.rs",
+"ui/issues/issue-22706.rs",
+"ui/issues/issue-2281-part1.rs",
+"ui/issues/issue-2284.rs",
+"ui/issues/issue-22864-1.rs",
+"ui/issues/issue-22864-2.rs",
+"ui/issues/issue-22872.rs",
+"ui/issues/issue-22874.rs",
+"ui/issues/issue-2288.rs",
+"ui/issues/issue-22886.rs",
+"ui/issues/issue-22894.rs",
+"ui/issues/issue-22933-2.rs",
+"ui/issues/issue-22992-2.rs",
+"ui/issues/issue-22992.rs",
+"ui/issues/issue-23024.rs",
+"ui/issues/issue-23036.rs",
+"ui/issues/issue-23041.rs",
+"ui/issues/issue-23046.rs",
+"ui/issues/issue-23073.rs",
+"ui/issues/issue-23122-1.rs",
+"ui/issues/issue-23122-2.rs",
+"ui/issues/issue-2316-c.rs",
+"ui/issues/issue-23173.rs",
+"ui/issues/issue-23189.rs",
+"ui/issues/issue-23217.rs",
+"ui/issues/issue-23253.rs",
+"ui/issues/issue-23261.rs",
+"ui/issues/issue-23281.rs",
+"ui/issues/issue-23302-1.rs",
+"ui/issues/issue-23302-2.rs",
+"ui/issues/issue-23302-3.rs",
+"ui/issues/issue-23304-1.rs",
+"ui/issues/issue-23304-2.rs",
+"ui/issues/issue-23311.rs",
+"ui/issues/issue-23336.rs",
+"ui/issues/issue-23406.rs",
+"ui/issues/issue-23433.rs",
+"ui/issues/issue-23485.rs",
+"ui/issues/issue-23491.rs",
+"ui/issues/issue-23543.rs",
+"ui/issues/issue-23544.rs",
+"ui/issues/issue-23550.rs",
+"ui/issues/issue-23589.rs",
+"ui/issues/issue-23611-enum-swap-in-drop.rs",
+"ui/issues/issue-23649-1.rs",
+"ui/issues/issue-23649-2.rs",
+"ui/issues/issue-23649-3.rs",
+"ui/issues/issue-23699.rs",
+"ui/issues/issue-23781.rs",
+"ui/issues/issue-2380-b.rs",
+"ui/issues/issue-2383.rs",
+"ui/issues/issue-23891.rs",
+"ui/issues/issue-23898.rs",
+"ui/issues/issue-23958.rs",
+"ui/issues/issue-23966.rs",
+"ui/issues/issue-23992.rs",
+"ui/issues/issue-24013.rs",
+"ui/issues/issue-24036.rs",
+"ui/issues/issue-24086.rs",
+"ui/issues/issue-2414-c.rs",
+"ui/issues/issue-2428.rs",
+"ui/issues/issue-24308.rs",
+"ui/issues/issue-24322.rs",
+"ui/issues/issue-24352.rs",
+"ui/issues/issue-24353.rs",
+"ui/issues/issue-24357.rs",
+"ui/issues/issue-24363.rs",
+"ui/issues/issue-24365.rs",
+"ui/issues/issue-24424.rs",
+"ui/issues/issue-24446.rs",
+"ui/issues/issue-2445-b.rs",
+"ui/issues/issue-2445.rs",
+"ui/issues/issue-24533.rs",
+"ui/issues/issue-24589.rs",
+"ui/issues/issue-2463.rs",
+"ui/issues/issue-24682.rs",
+"ui/issues/issue-2472.rs",
+"ui/issues/issue-24779.rs",
+"ui/issues/issue-24819.rs",
+"ui/issues/issue-2487-a.rs",
+"ui/issues/issue-24947.rs",
+"ui/issues/issue-24954.rs",
+"ui/issues/issue-25076.rs",
+"ui/issues/issue-25089.rs",
+"ui/issues/issue-25145.rs",
+"ui/issues/issue-25185.rs",
+"ui/issues/issue-2526-a.rs",
+"ui/issues/issue-25279.rs",
+"ui/issues/issue-25343.rs",
+"ui/issues/issue-25368.rs",
+"ui/issues/issue-25386.rs",
+"ui/issues/issue-25439.rs",
+"ui/issues/issue-25467.rs",
+"ui/issues/issue-25497.rs",
+"ui/issues/issue-2550.rs",
+"ui/issues/issue-25515.rs",
+"ui/issues/issue-25549-multiple-drop.rs",
+"ui/issues/issue-25679.rs",
+"ui/issues/issue-25693.rs",
+"ui/issues/issue-25746-bool-transmute.rs",
+"ui/issues/issue-25757.rs",
+"ui/issues/issue-25810.rs",
+"ui/issues/issue-2590.rs",
+"ui/issues/issue-25901.rs",
+"ui/issues/issue-26056.rs",
+"ui/issues/issue-26093.rs",
+"ui/issues/issue-26127.rs",
+"ui/issues/issue-26217.rs",
+"ui/issues/issue-26237.rs",
+"ui/issues/issue-26262.rs",
+"ui/issues/issue-2631-b.rs",
+"ui/issues/issue-2642.rs",
+"ui/issues/issue-26468.rs",
+"ui/issues/issue-26472.rs",
+"ui/issues/issue-26619.rs",
+"ui/issues/issue-26641.rs",
+"ui/issues/issue-26655.rs",
+"ui/issues/issue-26709.rs",
+"ui/issues/issue-26802.rs",
+"ui/issues/issue-26805.rs",
+"ui/issues/issue-26812.rs",
+"ui/issues/issue-26905-rpass.rs",
+"ui/issues/issue-26905.rs",
+"ui/issues/issue-26948.rs",
+"ui/issues/issue-27008.rs",
+"ui/issues/issue-27033.rs",
+"ui/issues/issue-27042.rs",
+"ui/issues/issue-27054-primitive-binary-ops.rs",
+"ui/issues/issue-27078.rs",
+"ui/issues/issue-2708.rs",
+"ui/issues/issue-2723-b.rs",
+"ui/issues/issue-27240.rs",
+"ui/issues/issue-27268.rs",
+"ui/issues/issue-27340.rs",
+"ui/issues/issue-27401-dropflag-reinit.rs",
+"ui/issues/issue-27592.rs",
+"ui/issues/issue-27639.rs",
+"ui/issues/issue-27815.rs",
+"ui/issues/issue-27842.rs",
+"ui/issues/issue-27859.rs",
+"ui/issues/issue-27942.rs",
+"ui/issues/issue-27949.rs",
+"ui/issues/issue-27997.rs",
+"ui/issues/issue-28105.rs",
+"ui/issues/issue-28109.rs",
+"ui/issues/issue-28181.rs",
+"ui/issues/issue-2823.rs",
+"ui/issues/issue-28344.rs",
+"ui/issues/issue-28433.rs",
+"ui/issues/issue-28472.rs",
+"ui/issues/issue-2848.rs",
+"ui/issues/issue-2849.rs",
+"ui/issues/issue-28498-must-work-ex1.rs",
+"ui/issues/issue-28498-must-work-ex2.rs",
+"ui/issues/issue-28498-ugeh-ex1.rs",
+"ui/issues/issue-28550.rs",
+"ui/issues/issue-28568.rs",
+"ui/issues/issue-28586.rs",
+"ui/issues/issue-28625.rs",
+"ui/issues/issue-28777.rs",
+"ui/issues/issue-28828.rs",
+"ui/issues/issue-28839.rs",
+"ui/issues/issue-2895.rs",
+"ui/issues/issue-28971.rs",
+"ui/issues/issue-28983.rs",
+"ui/issues/issue-28992-empty.rs",
+"ui/issues/issue-2904.rs",
+"ui/issues/issue-29053.rs",
+"ui/issues/issue-29071-2.rs",
+"ui/issues/issue-29092.rs",
+"ui/issues/issue-29147-rpass.rs",
+"ui/issues/issue-29147.rs",
+"ui/issues/issue-29181.rs",
+"ui/issues/issue-2935.rs",
+"ui/issues/issue-29466.rs",
+"ui/issues/issue-29485.rs",
+"ui/issues/issue-2951.rs",
+"ui/issues/issue-29522.rs",
+"ui/issues/issue-29540.rs",
+"ui/issues/issue-29663.rs",
+"ui/issues/issue-29668.rs",
+"ui/issues/issue-29723.rs",
+"ui/issues/issue-29746.rs",
+"ui/issues/issue-29821.rs",
+"ui/issues/issue-29861.rs",
+"ui/issues/issue-2989.rs",
+"ui/issues/issue-29948.rs",
+"ui/issues/issue-2995.rs",
+"ui/issues/issue-30007.rs",
+"ui/issues/issue-30018-panic.rs",
+"ui/issues/issue-30081.rs",
+"ui/issues/issue-3012-2.rs",
+"ui/issues/issue-30123.rs",
+"ui/issues/issue-3021-b.rs",
+"ui/issues/issue-3021-d.rs",
+"ui/issues/issue-30236.rs",
+"ui/issues/issue-30255.rs",
+"ui/issues/issue-3026.rs",
+"ui/issues/issue-3037.rs",
+"ui/issues/issue-30371.rs",
+"ui/issues/issue-3038.rs",
+"ui/issues/issue-30490.rs",
+"ui/issues/issue-3052.rs",
+"ui/issues/issue-30530.rs",
+"ui/issues/issue-30589.rs",
+"ui/issues/issue-30615.rs",
+"ui/issues/issue-30756.rs",
+"ui/issues/issue-30891.rs",
+"ui/issues/issue-3091.rs",
+"ui/issues/issue-31011.rs",
+"ui/issues/issue-3109.rs",
+"ui/issues/issue-3121.rs",
+"ui/issues/issue-31267-additional.rs",
+"ui/issues/issue-31267.rs",
+"ui/issues/issue-31299.rs",
+"ui/issues/issue-3136-b.rs",
+"ui/issues/issue-31511.rs",
+"ui/issues/issue-3154.rs",
+"ui/issues/issue-31702.rs",
+"ui/issues/issue-31769.rs",
+"ui/issues/issue-31776.rs",
+"ui/issues/issue-31910.rs",
+"ui/issues/issue-32004.rs",
+"ui/issues/issue-32008.rs",
+"ui/issues/issue-32086.rs",
+"ui/issues/issue-3214.rs",
+"ui/issues/issue-3220.rs",
+"ui/issues/issue-32292.rs",
+"ui/issues/issue-32323.rs",
+"ui/issues/issue-32326.rs",
+"ui/issues/issue-32377.rs",
+"ui/issues/issue-32389.rs",
+"ui/issues/issue-32518.rs",
+"ui/issues/issue-32655.rs",
+"ui/issues/issue-32709.rs",
+"ui/issues/issue-32782.rs",
+"ui/issues/issue-32805.rs",
+"ui/issues/issue-3290.rs",
+"ui/issues/issue-32950.rs",
+"ui/issues/issue-32995-2.rs",
+"ui/issues/issue-32995.rs",
+"ui/issues/issue-33187.rs",
+"ui/issues/issue-33202.rs",
+"ui/issues/issue-33287.rs",
+"ui/issues/issue-33293.rs",
+"ui/issues/issue-33387.rs",
+"ui/issues/issue-3344.rs",
+"ui/issues/issue-33461.rs",
+"ui/issues/issue-33504.rs",
+"ui/issues/issue-33525.rs",
+"ui/issues/issue-33571.rs",
+"ui/issues/issue-33687.rs",
+"ui/issues/issue-33770.rs",
+"ui/issues/issue-3389.rs",
+"ui/issues/issue-33992.rs",
+"ui/issues/issue-34047.rs",
+"ui/issues/issue-34074.rs",
+"ui/issues/issue-34209.rs",
+"ui/issues/issue-34229.rs",
+"ui/issues/issue-3429.rs",
+"ui/issues/issue-34334.rs",
+"ui/issues/issue-34349.rs",
+"ui/issues/issue-34373.rs",
+"ui/issues/issue-34427.rs",
+"ui/issues/issue-3447.rs",
+"ui/issues/issue-34503.rs",
+"ui/issues/issue-34571.rs",
+"ui/issues/issue-3477.rs",
+"ui/issues/issue-34796.rs",
+"ui/issues/issue-3500.rs",
+"ui/issues/issue-35139.rs",
+"ui/issues/issue-35241.rs",
+"ui/issues/issue-35423.rs",
+"ui/issues/issue-3556.rs",
+"ui/issues/issue-3559.rs",
+"ui/issues/issue-35600.rs",
+"ui/issues/issue-3563-3.rs",
+"ui/issues/issue-3574.rs",
+"ui/issues/issue-35815.rs",
+"ui/issues/issue-35988.rs",
+"ui/issues/issue-36023.rs",
+"ui/issues/issue-36036-associated-type-layout.rs",
+"ui/issues/issue-36260.rs",
+"ui/issues/issue-36278-prefix-nesting.rs",
+"ui/issues/issue-36299.rs",
+"ui/issues/issue-36400.rs",
+"ui/issues/issue-36401.rs",
+"ui/issues/issue-36474.rs",
+"ui/issues/issue-3668.rs",
+"ui/issues/issue-36744-bitcast-args-if-needed.rs",
+"ui/issues/issue-36786-resolve-call.rs",
+"ui/issues/issue-3680.rs",
+"ui/issues/issue-36816.rs",
+"ui/issues/issue-36836.rs",
+"ui/issues/issue-36936.rs",
+"ui/issues/issue-36954.rs",
+"ui/issues/issue-3702-2.rs",
+"ui/issues/issue-3702.rs",
+"ui/issues/issue-3707.rs",
+"ui/issues/issue-37109.rs",
+"ui/issues/issue-3743.rs",
+"ui/issues/issue-3753.rs",
+"ui/issues/issue-37534.rs",
+"ui/issues/issue-37576.rs",
+"ui/issues/issue-3763.rs",
+"ui/issues/issue-37686.rs",
+"ui/issues/issue-37725.rs",
+"ui/issues/issue-37733.rs",
+"ui/issues/issue-3779.rs",
+"ui/issues/issue-37884.rs",
+"ui/issues/issue-38190.rs",
+"ui/issues/issue-38412.rs",
+"ui/issues/issue-38437.rs",
+"ui/issues/issue-38458.rs",
+"ui/issues/issue-3847.rs",
+"ui/issues/issue-38556.rs",
+"ui/issues/issue-38727.rs",
+"ui/issues/issue-3874.rs",
+"ui/issues/issue-38763.rs",
+"ui/issues/issue-3878.rs",
+"ui/issues/issue-38857.rs",
+"ui/issues/issue-38919.rs",
+"ui/issues/issue-38942.rs",
+"ui/issues/issue-3895.rs",
+"ui/issues/issue-38954.rs",
+"ui/issues/issue-38987.rs",
+"ui/issues/issue-39175.rs",
+"ui/issues/issue-39211.rs",
+"ui/issues/issue-39548.rs",
+"ui/issues/issue-39687.rs",
+"ui/issues/issue-39709.rs",
+"ui/issues/issue-3979-generics.rs",
+"ui/issues/issue-3979-xcrate.rs",
+"ui/issues/issue-3979.rs",
+"ui/issues/issue-39808.rs",
+"ui/issues/issue-39827.rs",
+"ui/issues/issue-39848.rs",
+"ui/issues/issue-3993.rs",
+"ui/issues/issue-39970.rs",
+"ui/issues/issue-40000.rs",
+"ui/issues/issue-40085.rs",
+"ui/issues/issue-40235.rs",
+"ui/issues/issue-40288-2.rs",
+"ui/issues/issue-40288.rs",
+"ui/issues/issue-40408.rs",
+"ui/issues/issue-40510-1.rs",
+"ui/issues/issue-40510-3.rs",
+"ui/issues/issue-40610.rs",
+"ui/issues/issue-40749.rs",
+"ui/issues/issue-40827.rs",
+"ui/issues/issue-40845.rs",
+"ui/issues/issue-40861.rs",
+"ui/issues/issue-40883.rs",
+"ui/issues/issue-40951.rs",
+"ui/issues/issue-41053.rs",
+"ui/issues/issue-41139.rs",
+"ui/issues/issue-41213.rs",
+"ui/issues/issue-41229-ref-str.rs",
+"ui/issues/issue-41479.rs",
+"ui/issues/issue-41498.rs",
+"ui/issues/issue-41549.rs",
+"ui/issues/issue-41604.rs",
+"ui/issues/issue-41677.rs",
+"ui/issues/issue-41696.rs",
+"ui/issues/issue-41726.rs",
+"ui/issues/issue-41742.rs",
+"ui/issues/issue-41744.rs",
+"ui/issues/issue-41849-variance-req.rs",
+"ui/issues/issue-41880.rs",
+"ui/issues/issue-41888.rs",
+"ui/issues/issue-41974.rs",
+"ui/issues/issue-42007.rs",
+"ui/issues/issue-4208.rs",
+"ui/issues/issue-42106.rs",
+"ui/issues/issue-42148.rs",
+"ui/issues/issue-4228.rs",
+"ui/issues/issue-42312.rs",
+"ui/issues/issue-42453.rs",
+"ui/issues/issue-4252.rs",
+"ui/issues/issue-42552.rs",
+"ui/issues/issue-4265.rs",
+"ui/issues/issue-42755.rs",
+"ui/issues/issue-42796.rs",
+"ui/issues/issue-42880.rs",
+"ui/issues/issue-43162.rs",
+"ui/issues/issue-43205.rs",
+"ui/issues/issue-43250.rs",
+"ui/issues/issue-43291.rs",
+"ui/issues/issue-4333.rs",
+"ui/issues/issue-4335.rs",
+"ui/issues/issue-43355.rs",
+"ui/issues/issue-43420-no-over-suggest.rs",
+"ui/issues/issue-43424.rs",
+"ui/issues/issue-43431.rs",
+"ui/issues/issue-43692.rs",
+"ui/issues/issue-43853.rs",
+"ui/issues/issue-4387.rs",
+"ui/issues/issue-43910.rs",
+"ui/issues/issue-43923.rs",
+"ui/issues/issue-43925.rs",
+"ui/issues/issue-43926.rs",
+"ui/issues/issue-43988.rs",
+"ui/issues/issue-44023.rs",
+"ui/issues/issue-44078.rs",
+"ui/issues/issue-44255.rs",
+"ui/issues/issue-44405.rs",
+"ui/issues/issue-4517.rs",
+"ui/issues/issue-4541.rs",
+"ui/issues/issue-4542.rs",
+"ui/issues/issue-4545.rs",
+"ui/issues/issue-45510.rs",
+"ui/issues/issue-45730.rs",
+"ui/issues/issue-45801.rs",
+"ui/issues/issue-45965.rs",
+"ui/issues/issue-46069.rs",
+"ui/issues/issue-46101.rs",
+"ui/issues/issue-46302.rs",
+"ui/issues/issue-46311.rs",
+"ui/issues/issue-46332.rs",
+"ui/issues/issue-46438.rs",
+"ui/issues/issue-46471-1.rs",
+"ui/issues/issue-46472.rs",
+"ui/issues/issue-46604.rs",
+"ui/issues/issue-46771.rs",
+"ui/issues/issue-46983.rs",
+"ui/issues/issue-47073-zero-padded-tuple-struct-indices.rs",
+"ui/issues/issue-47094.rs",
+"ui/issues/issue-47184.rs",
+"ui/issues/issue-4734.rs",
+"ui/issues/issue-4735.rs",
+"ui/issues/issue-4736.rs",
+"ui/issues/issue-47377.rs",
+"ui/issues/issue-47380.rs",
+"ui/issues/issue-47486.rs",
+"ui/issues/issue-4759-1.rs",
+"ui/issues/issue-4759.rs",
+"ui/issues/issue-47638.rs",
+"ui/issues/issue-47715.rs",
+"ui/issues/issue-47725.rs",
+"ui/issues/issue-48006.rs",
+"ui/issues/issue-48132.rs",
+"ui/issues/issue-48159.rs",
+"ui/issues/issue-48276.rs",
+"ui/issues/issue-48364.rs",
+"ui/issues/issue-48728.rs",
+"ui/issues/issue-4875.rs",
+"ui/issues/issue-48838.rs",
+"ui/issues/issue-48984.rs",
+"ui/issues/issue-49298.rs",
+"ui/issues/issue-4935.rs",
+"ui/issues/issue-49632.rs",
+"ui/issues/issue-4968.rs",
+"ui/issues/issue-4972.rs",
+"ui/issues/issue-49824.rs",
+"ui/issues/issue-49854.rs",
+"ui/issues/issue-49919.rs",
+"ui/issues/issue-49934-errors.rs",
+"ui/issues/issue-49934.rs",
+"ui/issues/issue-49955.rs",
+"ui/issues/issue-49973.rs",
+"ui/issues/issue-5008-borrowed-traitobject-method-call.rs",
+"ui/issues/issue-50403.rs",
+"ui/issues/issue-50415.rs",
+"ui/issues/issue-50442.rs",
+"ui/issues/issue-50581.rs",
+"ui/issues/issue-50582.rs",
+"ui/issues/issue-50585.rs",
+"ui/issues/issue-50600.rs",
+"ui/issues/issue-50618.rs",
+"ui/issues/issue-5062.rs",
+"ui/issues/issue-50688.rs",
+"ui/issues/issue-50714-1.rs",
+"ui/issues/issue-50714.rs",
+"ui/issues/issue-50761.rs",
+"ui/issues/issue-50781.rs",
+"ui/issues/issue-50802.rs",
+"ui/issues/issue-5100.rs",
+"ui/issues/issue-51022.rs",
+"ui/issues/issue-51044.rs",
+"ui/issues/issue-51102.rs",
+"ui/issues/issue-51116.rs",
+"ui/issues/issue-51154.rs",
+"ui/issues/issue-51515.rs",
+"ui/issues/issue-5153.rs",
+"ui/issues/issue-51632-try-desugar-incompatible-types.rs",
+"ui/issues/issue-51874.rs",
+"ui/issues/issue-5192.rs",
+"ui/issues/issue-51947.rs",
+"ui/issues/issue-52049.rs",
+"ui/issues/issue-52126-assign-op-invariance.rs",
+"ui/issues/issue-52262.rs",
+"ui/issues/issue-5239-1.rs",
+"ui/issues/issue-5239-2.rs",
+"ui/issues/issue-52533.rs",
+"ui/issues/issue-52717.rs",
+"ui/issues/issue-5280.rs",
+"ui/issues/issue-5315.rs",
+"ui/issues/issue-5321-immediates-with-bare-self.rs",
+"ui/issues/issue-53251.rs",
+"ui/issues/issue-53275.rs",
+"ui/issues/issue-53300.rs",
+"ui/issues/issue-53348.rs",
+"ui/issues/issue-53498.rs",
+"ui/issues/issue-5358-1.rs",
+"ui/issues/issue-53728.rs",
+"ui/issues/issue-53843.rs",
+"ui/issues/issue-54044.rs",
+"ui/issues/issue-54062.rs",
+"ui/issues/issue-5439.rs",
+"ui/issues/issue-54410.rs",
+"ui/issues/issue-54477-reduced-2.rs",
+"ui/issues/issue-54696.rs",
+"ui/issues/issue-5518.rs",
+"ui/issues/issue-5521.rs",
+"ui/issues/issue-55376.rs",
+"ui/issues/issue-55380.rs",
+"ui/issues/issue-5550.rs",
+"ui/issues/issue-5554.rs",
+"ui/issues/issue-55587.rs",
+"ui/issues/issue-55731.rs",
+"ui/issues/issue-56199.rs",
+"ui/issues/issue-56237.rs",
+"ui/issues/issue-5666.rs",
+"ui/issues/issue-56806.rs",
+"ui/issues/issue-56835.rs",
+"ui/issues/issue-56870.rs",
+"ui/issues/issue-5688.rs",
+"ui/issues/issue-56943.rs",
+"ui/issues/issue-5708.rs",
+"ui/issues/issue-5718.rs",
+"ui/issues/issue-57198-pass.rs",
+"ui/issues/issue-57271.rs",
+"ui/issues/issue-57362-1.rs",
+"ui/issues/issue-57362-2.rs",
+"ui/issues/issue-5741.rs",
+"ui/issues/issue-57741-1.rs",
+"ui/issues/issue-57781.rs",
+"ui/issues/issue-57924.rs",
+"ui/issues/issue-58712.rs",
+"ui/issues/issue-58734.rs",
+"ui/issues/issue-5884.rs",
+"ui/issues/issue-58857.rs",
+"ui/issues/issue-5917.rs",
+"ui/issues/issue-59488.rs",
+"ui/issues/issue-59494.rs",
+"ui/issues/issue-5988.rs",
+"ui/issues/issue-5997-enum.rs",
+"ui/issues/issue-5997-struct.rs",
+"ui/issues/issue-5997.rs",
+"ui/issues/issue-60218.rs",
+"ui/issues/issue-60622.rs",
+"ui/issues/issue-60989.rs",
+"ui/issues/issue-61106.rs",
+"ui/issues/issue-61108.rs",
+"ui/issues/issue-6117.rs",
+"ui/issues/issue-6130.rs",
+"ui/issues/issue-61475.rs",
+"ui/issues/issue-6153.rs",
+"ui/issues/issue-61623.rs",
+"ui/issues/issue-61894.rs",
+"ui/issues/issue-62375.rs",
+"ui/issues/issue-62480.rs",
+"ui/issues/issue-6318.rs",
+"ui/issues/issue-6344-let.rs",
+"ui/issues/issue-6344-match.rs",
+"ui/issues/issue-63983.rs",
+"ui/issues/issue-64559.rs",
+"ui/issues/issue-64792-bad-unicode-ctor.rs",
+"ui/issues/issue-65131.rs",
+"ui/issues/issue-65230.rs",
+"ui/issues/issue-65462.rs",
+"ui/issues/issue-6596-2.rs",
+"ui/issues/issue-66353.rs",
+"ui/issues/issue-6642.rs",
+"ui/issues/issue-66667-function-cmp-cycle.rs",
+"ui/issues/issue-66702-break-outside-loop-val.rs",
+"ui/issues/issue-66706.rs",
+"ui/issues/issue-66923-show-error-for-correct-call.rs",
+"ui/issues/issue-67039-unsound-pin-partialeq.rs",
+"ui/issues/issue-6738.rs",
+"ui/issues/issue-67535.rs",
+"ui/issues/issue-68010-large-zst-consts.rs",
+"ui/issues/issue-68696-catch-during-unwind.rs",
+"ui/issues/issue-6892.rs",
+"ui/issues/issue-69130.rs",
+"ui/issues/issue-6919.rs",
+"ui/issues/issue-69306.rs",
+"ui/issues/issue-6936.rs",
+"ui/issues/issue-69455.rs",
+"ui/issues/issue-69602-type-err-during-codegen-ice.rs",
+"ui/issues/issue-69683.rs",
+"ui/issues/issue-7012.rs",
+"ui/issues/issue-70381.rs",
+"ui/issues/issue-7044.rs",
+"ui/issues/issue-7061.rs",
+"ui/issues/issue-70673.rs",
+"ui/issues/issue-70724-add_type_neq_err_label-unwrap.rs",
+"ui/issues/issue-7092.rs",
+"ui/issues/issue-71406.rs",
+"ui/issues/issue-71676-2.rs",
+"ui/issues/issue-7178.rs",
+"ui/issues/issue-72076.rs",
+"ui/issues/issue-72278.rs",
+"ui/issues/issue-7246.rs",
+"ui/issues/issue-72839-error-overflow.rs",
+"ui/issues/issue-72933-match-stack-overflow.rs",
+"ui/issues/issue-73112.rs",
+"ui/issues/issue-7344.rs",
+"ui/issues/issue-7364.rs",
+"ui/issues/issue-74082.rs",
+"ui/issues/issue-74564-if-expr-stack-overflow.rs",
+"ui/issues/issue-7519-match-unit-in-arg.rs",
+"ui/issues/issue-75283.rs",
+"ui/issues/issue-7563.rs",
+"ui/issues/issue-75704.rs",
+"ui/issues/issue-7575.rs",
+"ui/issues/issue-7607-1.rs",
+"ui/issues/issue-76077.rs",
+"ui/issues/issue-76191.rs",
+"ui/issues/issue-7660.rs",
+"ui/issues/issue-7663.rs",
+"ui/issues/issue-7784.rs",
+"ui/issues/issue-77919.rs",
+"ui/issues/issue-78192.rs",
+"ui/issues/issue-78622.rs",
+"ui/issues/issue-7867.rs",
+"ui/issues/issue-78957.rs",
+"ui/issues/issue-7899.rs",
+"ui/issues/issue-7911.rs",
+"ui/issues/issue-7950.rs",
+"ui/issues/issue-7970a.rs",
+"ui/issues/issue-8044.rs",
+"ui/issues/issue-80607.rs",
+"ui/issues/issue-8248.rs",
+"ui/issues/issue-8249.rs",
+"ui/issues/issue-8259.rs",
+"ui/issues/issue-8391.rs",
+"ui/issues/issue-8401.rs",
+"ui/issues/issue-8498.rs",
+"ui/issues/issue-8506.rs",
+"ui/issues/issue-86756.rs",
+"ui/issues/issue-87199.rs",
+"ui/issues/issue-8727.rs",
+"ui/issues/issue-87490.rs",
+"ui/issues/issue-8761.rs",
+"ui/issues/issue-8767.rs",
+"ui/issues/issue-8783.rs",
+"ui/issues/issue-8860.rs",
+"ui/issues/issue-8898.rs",
+"ui/issues/issue-9047.rs",
+"ui/issues/issue-9123.rs",
+"ui/issues/issue-9129.rs",
+"ui/issues/issue-9155.rs",
+"ui/issues/issue-9188.rs",
+"ui/issues/issue-9243.rs",
+"ui/issues/issue-9259.rs",
+"ui/issues/issue-9382.rs",
+"ui/issues/issue-9446.rs",
+"ui/issues/issue-9575.rs",
+"ui/issues/issue-9719.rs",
+"ui/issues/issue-9725.rs",
+"ui/issues/issue-9737.rs",
+"ui/issues/issue-9814.rs",
+"ui/issues/issue-98299.rs",
+"ui/issues/issue-9837.rs",
+"ui/issues/issue-9906.rs",
+"ui/issues/issue-9918.rs",
+"ui/issues/issue-9942.rs",
+"ui/issues/issue-9951.rs",
+"ui/issues/issue-9968.rs",
+"ui/issues/issue-99838.rs",
+"ui/issues/issue-11047.rs",
+"ui/issues/issue-11709.rs",
+"ui/issues/issue-20644.rs",
+"ui/issues/issue-23808.rs",
+"ui/issues/issue-26997.rs",
+"ui/issues/issue-28600.rs",
+"ui/issues/issue-3656.rs",
+"ui/issues/issue-50811.rs",
+"ui/issues/issue-51907.rs",
+"ui/issues/issue-5754.rs",
+"ui/issues/issue-10396.rs",
+"ui/issues/issue-10456.rs",
+"ui/issues/issue-106755.rs",
+"ui/issues/issue-10853.rs",
+"ui/issues/issue-10902.rs",
+"ui/issues/issue-11085.rs",
+"ui/issues/issue-11384.rs",
+"ui/issues/issue-11592.rs",
+"ui/issues/issue-11740.rs",
+"ui/issues/issue-11869.rs",
+"ui/issues/issue-12729.rs",
+"ui/issues/issue-12920.rs",
+"ui/issues/issue-13105.rs",
+"ui/issues/issue-13167.rs",
+"ui/issues/issue-13202.rs",
+"ui/issues/issue-13405.rs",
+"ui/issues/issue-13482-2.rs",
+"ui/issues/issue-13703.rs",
+"ui/issues/issue-13775.rs",
+"ui/issues/issue-14082.rs",
+"ui/issues/issue-14254.rs",
+"ui/issues/issue-14330.rs",
+"ui/issues/issue-14901.rs",
+"ui/issues/issue-14959.rs",
+"ui/issues/issue-15734.rs",
+"ui/issues/issue-15735.rs",
+"ui/issues/issue-16596.rs",
+"ui/issues/issue-16668.rs",
+"ui/issues/issue-16994.rs",
+"ui/issues/issue-17121.rs",
+"ui/issues/issue-17732.rs",
+"ui/issues/issue-17746.rs",
+"ui/issues/issue-17904.rs",
+"ui/issues/issue-18088.rs",
+"ui/issues/issue-18188.rs",
+"ui/issues/issue-18446-2.rs",
+"ui/issues/issue-18576.rs",
+"ui/issues/issue-18738.rs",
+"ui/issues/issue-18809.rs",
+"ui/issues/issue-18906.rs",
+"ui/issues/issue-18988.rs",
+"ui/issues/issue-19037.rs",
+"ui/issues/issue-19097.rs",
+"ui/issues/issue-19098.rs",
+"ui/issues/issue-19100.rs",
+"ui/issues/issue-19102.rs",
+"ui/issues/issue-19129-1.rs",
+"ui/issues/issue-19129-2.rs",
+"ui/issues/issue-19398.rs",
+"ui/issues/issue-19479.rs",
+"ui/issues/issue-19601.rs",
+"ui/issues/issue-1962.rs",
+"ui/issues/issue-19631.rs",
+"ui/issues/issue-19632.rs",
+"ui/issues/issue-19850.rs",
+"ui/issues/issue-19982.rs",
+"ui/issues/issue-20009.rs",
+"ui/issues/issue-20186.rs",
+"ui/issues/issue-20396.rs",
+"ui/issues/issue-20414.rs",
+"ui/issues/issue-20454.rs",
+"ui/issues/issue-20763-1.rs",
+"ui/issues/issue-20763-2.rs",
+"ui/issues/issue-20971.rs",
+"ui/issues/issue-21140.rs",
+"ui/issues/issue-21174-2.rs",
+"ui/issues/issue-21245.rs",
+"ui/issues/issue-21402.rs",
+"ui/issues/issue-21622.rs",
+"ui/issues/issue-22356.rs",
+"ui/issues/issue-22471.rs",
+"ui/issues/issue-22603.rs",
+"ui/issues/issue-22673.rs",
+"ui/issues/issue-22777.rs",
+"ui/issues/issue-22781.rs",
+"ui/issues/issue-22789.rs",
+"ui/issues/issue-22814.rs",
+"ui/issues/issue-22933-1.rs",
+"ui/issues/issue-2311-2.rs",
+"ui/issues/issue-2311.rs",
+"ui/issues/issue-2312.rs",
+"ui/issues/issue-23354-2.rs",
+"ui/issues/issue-23354.rs",
+"ui/issues/issue-23442.rs",
+"ui/issues/issue-23477.rs",
+"ui/issues/issue-24161.rs",
+"ui/issues/issue-24227.rs",
+"ui/issues/issue-24389.rs",
+"ui/issues/issue-24434.rs",
+"ui/issues/issue-2470-bounds-check-overflow.rs",
+"ui/issues/issue-24945-repeat-dash-opts.rs",
+"ui/issues/issue-2502.rs",
+"ui/issues/issue-25180.rs",
+"ui/issues/issue-25394.rs",
+"ui/issues/issue-25579.rs",
+"ui/issues/issue-26095.rs",
+"ui/issues/issue-2611-3.rs",
+"ui/issues/issue-26186.rs",
+"ui/issues/issue-26205.rs",
+"ui/issues/issue-26484.rs",
+"ui/issues/issue-26614.rs",
+"ui/issues/issue-26646.rs",
+"ui/issues/issue-27105.rs",
+"ui/issues/issue-27281.rs",
+"ui/issues/issue-27433.rs",
+"ui/issues/issue-2761.rs",
+"ui/issues/issue-27697.rs",
+"ui/issues/issue-27889.rs",
+"ui/issues/issue-28279.rs",
+"ui/issues/issue-28561.rs",
+"ui/issues/issue-28776.rs",
+"ui/issues/issue-28936.rs",
+"ui/issues/issue-28999.rs",
+"ui/issues/issue-29030.rs",
+"ui/issues/issue-29037.rs",
+"ui/issues/issue-29048.rs",
+"ui/issues/issue-29071.rs",
+"ui/issues/issue-29265.rs",
+"ui/issues/issue-29276.rs",
+"ui/issues/issue-29516.rs",
+"ui/issues/issue-29710.rs",
+"ui/issues/issue-29740.rs",
+"ui/issues/issue-29743.rs",
+"ui/issues/issue-29857.rs",
+"ui/issues/issue-3029.rs",
+"ui/issues/issue-30380.rs",
+"ui/issues/issue-31260.rs",
+"ui/issues/issue-3149.rs",
+"ui/issues/issue-32122-1.rs",
+"ui/issues/issue-32122-2.rs",
+"ui/issues/issue-32324.rs",
+"ui/issues/issue-32797.rs",
+"ui/issues/issue-33096.rs",
+"ui/issues/issue-33241.rs",
+"ui/issues/issue-33941.rs",
+"ui/issues/issue-3424.rs",
+"ui/issues/issue-34418.rs",
+"ui/issues/issue-34569.rs",
+"ui/issues/issue-34721.rs",
+"ui/issues/issue-34751.rs",
+"ui/issues/issue-34780.rs",
+"ui/issues/issue-34839.rs",
+"ui/issues/issue-3521-2.rs",
+"ui/issues/issue-35976.rs",
+"ui/issues/issue-36075.rs",
+"ui/issues/issue-3609.rs",
+"ui/issues/issue-36116.rs",
+"ui/issues/issue-36379.rs",
+"ui/issues/issue-3668-2.rs",
+"ui/issues/issue-36839.rs",
+"ui/issues/issue-36856.rs",
+"ui/issues/issue-37051.rs",
+"ui/issues/issue-37131.rs",
+"ui/issues/issue-37510.rs",
+"ui/issues/issue-37598.rs",
+"ui/issues/issue-37665.rs",
+"ui/issues/issue-38160.rs",
+"ui/issues/issue-38226.rs",
+"ui/issues/issue-38381.rs",
+"ui/issues/issue-3888-2.rs",
+"ui/issues/issue-39089.rs",
+"ui/issues/issue-39367.rs",
+"ui/issues/issue-39467.rs",
+"ui/issues/issue-3979-2.rs",
+"ui/issues/issue-3991.rs",
+"ui/issues/issue-39984.rs",
+"ui/issues/issue-40136.rs",
+"ui/issues/issue-4025.rs",
+"ui/issues/issue-40350.rs",
+"ui/issues/issue-40510-2.rs",
+"ui/issues/issue-40510-4.rs",
+"ui/issues/issue-40782.rs",
+"ui/issues/issue-41272.rs",
+"ui/issues/issue-41298.rs",
+"ui/issues/issue-41628.rs",
+"ui/issues/issue-41936-variance-coerce-unsized-cycle.rs",
+"ui/issues/issue-41998.rs",
+"ui/issues/issue-42210.rs",
+"ui/issues/issue-42467.rs",
+"ui/issues/issue-42956.rs",
+"ui/issues/issue-43057.rs",
+"ui/issues/issue-43357.rs",
+"ui/issues/issue-43483.rs",
+"ui/issues/issue-43806.rs",
+"ui/issues/issue-44056.rs",
+"ui/issues/issue-44216-add-instant.rs",
+"ui/issues/issue-44216-add-system-time.rs",
+"ui/issues/issue-44216-sub-instant.rs",
+"ui/issues/issue-44216-sub-system-time.rs",
+"ui/issues/issue-44239.rs",
+"ui/issues/issue-44247.rs",
+"ui/issues/issue-4464.rs",
+"ui/issues/issue-44730.rs",
+"ui/issues/issue-44851.rs",
+"ui/issues/issue-45425.rs",
+"ui/issues/issue-45562.rs",
+"ui/issues/issue-45697-1.rs",
+"ui/issues/issue-45697.rs",
+"ui/issues/issue-45731.rs",
+"ui/issues/issue-46756-consider-borrowing-cast-or-binexpr.rs",
+"ui/issues/issue-46855.rs",
+"ui/issues/issue-46964.rs",
+"ui/issues/issue-47309.rs",
+"ui/issues/issue-47364.rs",
+"ui/issues/issue-47673.rs",
+"ui/issues/issue-47703-1.rs",
+"ui/issues/issue-47703-tuple.rs",
+"ui/issues/issue-47703.rs",
+"ui/issues/issue-47722.rs",
+"ui/issues/issue-48131.rs",
+"ui/issues/issue-4830.rs",
+"ui/issues/issue-49544.rs",
+"ui/issues/issue-50187.rs",
+"ui/issues/issue-50411.rs",
+"ui/issues/issue-50471.rs",
+"ui/issues/issue-50518.rs",
+"ui/issues/issue-50571.rs",
+"ui/issues/issue-5067.rs",
+"ui/issues/issue-51655.rs",
+"ui/issues/issue-51798.rs",
+"ui/issues/issue-52489.rs",
+"ui/issues/issue-53333.rs",
+"ui/issues/issue-53419.rs",
+"ui/issues/issue-53568.rs",
+"ui/issues/issue-54094.rs",
+"ui/issues/issue-54462-mutable-noalias-correctness.rs",
+"ui/issues/issue-5572.rs",
+"ui/issues/issue-56128.rs",
+"ui/issues/issue-56175.rs",
+"ui/issues/issue-56229.rs",
+"ui/issues/issue-57156.rs",
+"ui/issues/issue-57162.rs",
+"ui/issues/issue-57399-self-return-impl-trait.rs",
+"ui/issues/issue-57741.rs",
+"ui/issues/issue-58212.rs",
+"ui/issues/issue-58344.rs",
+"ui/issues/issue-58375-monomorphize-default-impls.rs",
+"ui/issues/issue-5844.rs",
+"ui/issues/issue-58463.rs",
+"ui/issues/issue-5900.rs",
+"ui/issues/issue-59020.rs",
+"ui/issues/issue-59326.rs",
+"ui/issues/issue-5950.rs",
+"ui/issues/issue-59756.rs",
+"ui/issues/issue-64430.rs",
+"ui/issues/issue-64593.rs",
+"ui/issues/issue-6557.rs",
+"ui/issues/issue-65634-raw-ident-suggestion.rs",
+"ui/issues/issue-66308.rs",
+"ui/issues/issue-66768.rs",
+"ui/issues/issue-68951.rs",
+"ui/issues/issue-6898.rs",
+"ui/issues/issue-69225-SCEVAddExpr-wrap-flag.rs",
+"ui/issues/issue-69225-layout-repeated-checked-add.rs",
+"ui/issues/issue-70746.rs",
+"ui/issues/issue-71676-1.rs",
+"ui/issues/issue-72002.rs",
+"ui/issues/issue-7268.rs",
+"ui/issues/issue-73229.rs",
+"ui/issues/issue-76042.rs",
+"ui/issues/issue-7607-2.rs",
+"ui/issues/issue-76077-1.rs",
+"ui/issues/issue-7673-cast-generically-implemented-trait.rs",
+"ui/issues/issue-81584.rs",
+"ui/issues/issue-8171-default-method-self-inherit-builtin-trait.rs",
+"ui/issues/issue-81918.rs",
+"ui/issues/issue-82833-slice-miscompile.rs",
+"ui/issues/issue-83048.rs",
+"ui/issues/issue-8398.rs",
+"ui/issues/issue-8521.rs",
+"ui/issues/issue-8578.rs",
+"ui/issues/issue-87707.rs",
+"ui/issues/issue-88150.rs",
+"ui/issues/issue-9110.rs",
+"ui/issues/issue-91489.rs",
+"ui/issues/issue-9249.rs",
+"ui/issues/issue-92741.rs",
+"ui/issues/issue-12133-3.rs",
+"ui/issues/issue-18389.rs",
+"ui/issues/issue-35570.rs",
+"ui/issues/issue-51714.rs",
+"ui/issues/issue-5883.rs",
+"ui/issues/issue-67552.rs",
+"ui/issues/issue-85461.rs",
+"ui/iterators/issue-28098.rs",
+"ui/iterators/issue-58952-filter-type-length.rs",
+"ui/lang-items/issue-31076.rs",
+"ui/lang-items/issue-83471.rs",
+"ui/lang-items/issue-86238.rs",
+"ui/lang-items/issue-87573.rs",
+"ui/lang-items/issue-19660.rs",
+"ui/late-bound-lifetimes/issue-36381.rs",
+"ui/late-bound-lifetimes/issue-80618.rs",
+"ui/late-bound-lifetimes/issue-47511.rs",
+"ui/layout/issue-60431-unsized-tail-behind-projection.rs",
+"ui/layout/issue-84108.rs",
+"ui/layout/issue-113941.rs",
+"ui/layout/issue-96158-scalarpair-payload-might-be-uninit.rs",
+"ui/layout/issue-96185-overaligned-enum.rs",
+"ui/layout/issue-112048-unsizing-field-order.rs",
+"ui/layout/issue-112048-unsizing-niche.rs",
+"ui/let-else/issue-94176.rs",
+"ui/let-else/issue-100103.rs",
+"ui/let-else/issue-102317.rs",
+"ui/let-else/issue-99975.rs",
+"ui/lifetimes/auxiliary/issue-91763-aux.rs",
+"ui/lifetimes/lifetime-errors/issue_74400.rs",
+"ui/lifetimes/issue-105675.rs",
+"ui/lifetimes/issue-107492-default-value-for-lifetime.rs",
+"ui/lifetimes/issue-107988.rs",
+"ui/lifetimes/issue-17728.rs",
+"ui/lifetimes/issue-26638.rs",
+"ui/lifetimes/issue-34979.rs",
+"ui/lifetimes/issue-36744-without-calls.rs",
+"ui/lifetimes/issue-55796.rs",
+"ui/lifetimes/issue-64173-unused-lifetimes.rs",
+"ui/lifetimes/issue-79187-2.rs",
+"ui/lifetimes/issue-79187.rs",
+"ui/lifetimes/issue-83753-invalid-associated-type-supertrait-hrtb.rs",
+"ui/lifetimes/issue-83907-invalid-fn-like-path.rs",
+"ui/lifetimes/issue-90600-expected-return-static-indirect.rs",
+"ui/lifetimes/issue-91763.rs",
+"ui/lifetimes/issue-95023.rs",
+"ui/lifetimes/issue-97193.rs",
+"ui/lifetimes/issue-97194.rs",
+"ui/lifetimes/issue-103582-hint-for-missing-lifetime-bound-on-trait-object-using-type-alias.rs",
+"ui/lifetimes/issue-104432-unused-lifetimes-in-expansion.rs",
+"ui/lifetimes/issue-105227.rs",
+"ui/lifetimes/issue-105507.rs",
+"ui/lifetimes/issue-54378.rs",
+"ui/lifetimes/issue-67498.rs",
+"ui/lifetimes/issue-69314.rs",
+"ui/lifetimes/issue-70917-lifetimes-in-fn-def.rs",
+"ui/lifetimes/issue-76168-hr-outlives-2.rs",
+"ui/lifetimes/issue-76168-hr-outlives.rs",
+"ui/lifetimes/issue-77175.rs",
+"ui/lifetimes/issue-83737-binders-across-types.rs",
+"ui/lifetimes/issue-83737-erasing-bound-vars.rs",
+"ui/lifetimes/issue-84398.rs",
+"ui/lifetimes/issue-84604.rs",
+"ui/lifetimes/issue-90170-elision-mismatch.rs",
+"ui/lifetimes/issue-93911.rs",
+"ui/limits/issue-75158-64.rs",
+"ui/limits/issue-55878.rs",
+"ui/limits/issue-69485-var-size-diffs-too-large.rs",
+"ui/limits/issue-15919-32.rs",
+"ui/limits/issue-15919-64.rs",
+"ui/limits/issue-17913.rs",
+"ui/limits/issue-56762.rs",
+"ui/linkage-attr/issue-109144.rs",
+"ui/linkage-attr/issue-10755.rs",
+"ui/lint/dead-code/issue-59003.rs",
+"ui/lint/dead-code/issue-68408-false-positive.rs",
+"ui/lint/dead-code/issue-85071-2.rs",
+"ui/lint/dead-code/issue-85071.rs",
+"ui/lint/dead-code/issue-85255.rs",
+"ui/lint/must_not_suspend/issue-89562.rs",
+"ui/lint/unused/issue-105061-array-lint.rs",
+"ui/lint/unused/issue-105061-should-lint.rs",
+"ui/lint/unused/issue-105061.rs",
+"ui/lint/unused/issue-30730.rs",
+"ui/lint/unused/issue-46576.rs",
+"ui/lint/unused/issue-59896.rs",
+"ui/lint/unused/issue-67691-unused-field-in-or-pattern.rs",
+"ui/lint/unused/issue-74883-unused-paren-baren-yield.rs",
+"ui/lint/unused/issue-85913.rs",
+"ui/lint/unused/issue-90807-unused-paren-error.rs",
+"ui/lint/unused/issue-92751.rs",
+"ui/lint/unused/issue-96606.rs",
+"ui/lint/unused/issue-103320-must-use-ops.rs",
+"ui/lint/unused/issue-104397.rs",
+"ui/lint/unused/issue-47390-unused-variable-in-struct-pattern.rs",
+"ui/lint/unused/issue-54180-unused-ref-field.rs",
+"ui/lint/unused/issue-54538-unused-parens-lint.rs",
+"ui/lint/unused/issue-70041.rs",
+"ui/lint/unused/issue-71290-unused-paren-binop.rs",
+"ui/lint/unused/issue-81314-unused-span-ident.rs",
+"ui/lint/unused/issue-88519-unused-paren.rs",
+"ui/lint/unused/issue-90807-unused-paren.rs",
+"ui/lint/use-redundant/issue-92904.rs",
+"ui/lint/issue-104392.rs",
+"ui/lint/issue-106991.rs",
+"ui/lint/issue-109152.rs",
+"ui/lint/issue-111359.rs",
+"ui/lint/issue-14309.rs",
+"ui/lint/issue-17718-const-naming.rs",
+"ui/lint/issue-1866.rs",
+"ui/lint/issue-20343.rs",
+"ui/lint/issue-30302.rs",
+"ui/lint/issue-34798.rs",
+"ui/lint/issue-35075.rs",
+"ui/lint/issue-49588-non-shorthand-field-patterns-in-pattern-macro.rs",
+"ui/lint/issue-63364.rs",
+"ui/lint/issue-66362-no-snake-case-warning-for-field-puns.rs",
+"ui/lint/issue-79744.rs",
+"ui/lint/issue-97094.rs",
+"ui/lint/issue-101284.rs",
+"ui/lint/issue-102705.rs",
+"ui/lint/issue-103317.rs",
+"ui/lint/issue-103435-extra-parentheses.rs",
+"ui/lint/issue-104897.rs",
+"ui/lint/issue-108155.rs",
+"ui/lint/issue-109529.rs",
+"ui/lint/issue-110573.rs",
+"ui/lint/issue-112489.rs",
+"ui/lint/issue-14837.rs",
+"ui/lint/issue-31924-non-snake-ffi.rs",
+"ui/lint/issue-47775-nested-macro-unnecessary-parens-arg.rs",
+"ui/lint/issue-54099-camel-case-underscore-types.rs",
+"ui/lint/issue-57410-1.rs",
+"ui/lint/issue-57410.rs",
+"ui/lint/issue-70819-dont-override-forbid-in-same-scope.rs",
+"ui/lint/issue-79546-fuel-ice.rs",
+"ui/lint/issue-80988.rs",
+"ui/lint/issue-81218.rs",
+"ui/lint/issue-83477.rs",
+"ui/lint/issue-86600-lint-twice.rs",
+"ui/lint/issue-87274-paren-parent.rs",
+"ui/lint/issue-89469.rs",
+"ui/lint/issue-90614-accept-allow-text-direction-codepoint-in-comment-lint.rs",
+"ui/lint/issue-99387.rs",
+"ui/loops/issue-50576.rs",
+"ui/loops/issue-82916.rs",
+"ui/lowering/issue-96847.rs",
+"ui/lto/issue-105637.rs",
+"ui/lto/issue-100772.rs",
+"ui/lto/issue-11154.rs",
+"ui/macros/auxiliary/issue-100199.rs",
+"ui/macros/auxiliary/issue-19163.rs",
+"ui/macros/auxiliary/issue-40469.rs",
+"ui/macros/auxiliary/issue-75982.rs",
+"ui/macros/issue-100199.rs",
+"ui/macros/issue-102878.rs",
+"ui/macros/issue-103529.rs",
+"ui/macros/issue-104769-concat_bytes-invalid-literal.rs",
+"ui/macros/issue-105011.rs",
+"ui/macros/issue-10536.rs",
+"ui/macros/issue-106837.rs",
+"ui/macros/issue-109237.rs",
+"ui/macros/issue-111749.rs",
+"ui/macros/issue-16098.rs",
+"ui/macros/issue-19163.rs",
+"ui/macros/issue-21356.rs",
+"ui/macros/issue-22463.rs",
+"ui/macros/issue-25274.rs",
+"ui/macros/issue-25385.rs",
+"ui/macros/issue-26094.rs",
+"ui/macros/issue-26322.rs",
+"ui/macros/issue-29084.rs",
+"ui/macros/issue-30143.rs",
+"ui/macros/issue-33185.rs",
+"ui/macros/issue-34421-mac-expr-bad-stmt-good-add-semi.rs",
+"ui/macros/issue-35450.rs",
+"ui/macros/issue-37175.rs",
+"ui/macros/issue-38715.rs",
+"ui/macros/issue-39388.rs",
+"ui/macros/issue-39404.rs",
+"ui/macros/issue-40469.rs",
+"ui/macros/issue-40770.rs",
+"ui/macros/issue-41776.rs",
+"ui/macros/issue-41803.rs",
+"ui/macros/issue-44127.rs",
+"ui/macros/issue-5060.rs",
+"ui/macros/issue-51848.rs",
+"ui/macros/issue-52169.rs",
+"ui/macros/issue-54441.rs",
+"ui/macros/issue-58490.rs",
+"ui/macros/issue-61033-1.rs",
+"ui/macros/issue-61033-2.rs",
+"ui/macros/issue-61053-different-kleene.rs",
+"ui/macros/issue-61053-duplicate-binder.rs",
+"ui/macros/issue-61053-missing-repetition.rs",
+"ui/macros/issue-61053-unbound.rs",
+"ui/macros/issue-6596-1.rs",
+"ui/macros/issue-68060.rs",
+"ui/macros/issue-69396-const-no-type-in-macro.rs",
+"ui/macros/issue-78325-inconsistent-resolution.rs",
+"ui/macros/issue-78333.rs",
+"ui/macros/issue-81006.rs",
+"ui/macros/issue-83340.rs",
+"ui/macros/issue-83344.rs",
+"ui/macros/issue-84195-lint-anon-const.rs",
+"ui/macros/issue-84632-eager-expansion-recursion-limit.rs",
+"ui/macros/issue-86865.rs",
+"ui/macros/issue-8709.rs",
+"ui/macros/issue-8851.rs",
+"ui/macros/issue-92267.rs",
+"ui/macros/issue-98790.rs",
+"ui/macros/issue-112342-1.rs",
+"ui/macros/issue-112342-2.rs",
+"ui/macros/issue-2804-2.rs",
+"ui/macros/issue-34171.rs",
+"ui/macros/issue-42954.rs",
+"ui/macros/issue-57597.rs",
+"ui/macros/issue-63102.rs",
+"ui/macros/issue-68058.rs",
+"ui/macros/issue-69838-mods-relative-to-included-path.rs",
+"ui/macros/issue-70446.rs",
+"ui/macros/issue-75982-foreign-macro-weird-mod.rs",
+"ui/macros/issue-77475.rs",
+"ui/macros/issue-78892-substitution-in-statement-attr.rs",
+"ui/macros/issue-84429-matches-edition.rs",
+"ui/macros/issue-86082-option-env-invalid-char.rs",
+"ui/macros/issue-87877.rs",
+"ui/macros/issue-88206.rs",
+"ui/macros/issue-88228.rs",
+"ui/macros/issue-95267.rs",
+"ui/macros/issue-95533.rs",
+"ui/macros/issue-98466-allow.rs",
+"ui/macros/issue-98466.rs",
+"ui/macros/issue-99261.rs",
+"ui/macros/issue-99265.rs",
+"ui/macros/issue-99907.rs",
+"ui/malformed/issue-69341-malformed-derive-inert.rs",
+"ui/malformed/issue-107423-unused-delim-only-one-no-pair.rs",
+"ui/marker_trait_attr/issue-61651-type-mismatch.rs",
+"ui/match/issue-11319.rs",
+"ui/match/issue-11940.rs",
+"ui/match/issue-12552.rs",
+"ui/match/issue-18060.rs",
+"ui/match/issue-26251.rs",
+"ui/match/issue-26996.rs",
+"ui/match/issue-27021.rs",
+"ui/match/issue-33498.rs",
+"ui/match/issue-41255.rs",
+"ui/match/issue-42679.rs",
+"ui/match/issue-46920-byte-array-patterns.rs",
+"ui/match/issue-5530.rs",
+"ui/match/issue-56685.rs",
+"ui/match/issue-72680.rs",
+"ui/match/issue-72896.rs",
+"ui/match/issue-74050-end-span.rs",
+"ui/match/issue-82866.rs",
+"ui/match/issue-91058.rs",
+"ui/match/issue-92100.rs",
+"ui/match/issue-112438.rs",
+"ui/match/issue-70972-dyn-trait.rs",
+"ui/match/issue-82392.rs",
+"ui/match/issue-84434.rs",
+"ui/match/issue-113012.rs",
+"ui/methods/issues/issue-105732.rs",
+"ui/methods/issues/issue-61525.rs",
+"ui/methods/issues/issue-84495.rs",
+"ui/methods/issues/issue-90315.rs",
+"ui/methods/issues/issue-94581.rs",
+"ui/mir/auxiliary/issue_76375_aux.rs",
+"ui/mir/validate/issue-95978-validator-lifetime-comparison.rs",
+"ui/mir/issue-102389.rs",
+"ui/mir/issue-107678-projection-with-lifetime.rs",
+"ui/mir/issue-29227.rs",
+"ui/mir/issue-67947.rs",
+"ui/mir/issue-75419-validation-impl-trait.rs",
+"ui/mir/issue-76803-branches-not-same.rs",
+"ui/mir/issue-77359-simplify-arm-identity.rs",
+"ui/mir/issue-83499-input-output-iteration-ice.rs",
+"ui/mir/issue-89485.rs",
+"ui/mir/issue-92893.rs",
+"ui/mir/issue-112269.rs",
+"ui/mir/issue-80949.rs",
+"ui/mir/issue-101844.rs",
+"ui/mir/issue-105809.rs",
+"ui/mir/issue-106062.rs",
+"ui/mir/issue-107691.rs",
+"ui/mir/issue-109004-drop-large-array.rs",
+"ui/mir/issue-109743.rs",
+"ui/mir/issue-46845.rs",
+"ui/mir/issue-60390.rs",
+"ui/mir/issue-66851.rs",
+"ui/mir/issue-66930.rs",
+"ui/mir/issue-67639-normalization-ice.rs",
+"ui/mir/issue-67710-inline-projection.rs",
+"ui/mir/issue-68841.rs",
+"ui/mir/issue-71793-inline-args-storage.rs",
+"ui/mir/issue-73914.rs",
+"ui/mir/issue-74739.rs",
+"ui/mir/issue-75053.rs",
+"ui/mir/issue-76248.rs",
+"ui/mir/issue-76375.rs",
+"ui/mir/issue-76740-copy-propagation.rs",
+"ui/mir/issue-77002.rs",
+"ui/mir/issue-77911.rs",
+"ui/mir/issue-78496.rs",
+"ui/mir/issue-91745.rs",
+"ui/mir/issue-99852.rs",
+"ui/mir/issue-99866.rs",
+"ui/mir/issue66339.rs",
+"ui/mismatched_types/issue-19109.rs",
+"ui/mismatched_types/issue-26480.rs",
+"ui/mismatched_types/issue-35030.rs",
+"ui/mismatched_types/issue-36053-2.rs",
+"ui/mismatched_types/issue-38371-unfixable.rs",
+"ui/mismatched_types/issue-47706-trait.rs",
+"ui/mismatched_types/issue-47706.rs",
+"ui/mismatched_types/issue-74918-missing-lifetime.rs",
+"ui/mismatched_types/issue-75361-mismatched-impl.rs",
+"ui/mismatched_types/issue-84976.rs",
+"ui/mismatched_types/issue-112036.rs",
+"ui/mismatched_types/issue-106182.rs",
+"ui/mismatched_types/issue-38371.rs",
+"ui/missing-trait-bounds/auxiliary/issue-69725.rs",
+"ui/missing-trait-bounds/issue-35677.rs",
+"ui/missing-trait-bounds/issue-69725.rs",
+"ui/modules/issue-56411.rs",
+"ui/modules/issue-107649.rs",
+"ui/modules/issue-56411-aux.rs",
+"ui/moves/issue-22536-copy-mustnt-zero.rs",
+"ui/moves/issue-46099-move-in-macro.rs",
+"ui/moves/issue-72649-uninit-in-loop.rs",
+"ui/moves/issue-75904-move-closure-loop.rs",
+"ui/moves/issue-99470-move-out-of-some.rs",
+"ui/never_type/issue-10176.rs",
+"ui/never_type/issue-13352.rs",
+"ui/never_type/issue-2149.rs",
+"ui/never_type/issue-51506.rs",
+"ui/never_type/issue-52443.rs",
+"ui/never_type/issue-96335.rs",
+"ui/never_type/issue-44402.rs",
+"ui/never_type/issue-5500-1.rs",
+"ui/nll/closure-requirements/issue-58127-mutliple-requirements.rs",
+"ui/nll/polonius/issue-46589.rs",
+"ui/nll/relate_tys/issue-48071.rs",
+"ui/nll/ty-outlives/issue-53789-1.rs",
+"ui/nll/ty-outlives/issue-53789-2.rs",
+"ui/nll/ty-outlives/issue-55756.rs",
+"ui/nll/user-annotations/issue-54124.rs",
+"ui/nll/user-annotations/issue-55241.rs",
+"ui/nll/user-annotations/issue-55748-pat-types-constrain-bindings.rs",
+"ui/nll/user-annotations/issue-57731-ascibed-coupled-types.rs",
+"ui/nll/user-annotations/issue-54570-bootstrapping.rs",
+"ui/nll/user-annotations/issue-55219.rs",
+"ui/nll/issue-21232-partial-init-and-erroneous-use.rs",
+"ui/nll/issue-21232-partial-init-and-use.rs",
+"ui/nll/issue-24535-allow-mutable-borrow-in-match-guard.rs",
+"ui/nll/issue-27282-move-match-input-into-guard.rs",
+"ui/nll/issue-27282-move-ref-mut-into-guard.rs",
+"ui/nll/issue-27282-mutate-before-diverging-arm-1.rs",
+"ui/nll/issue-27282-mutate-before-diverging-arm-2.rs",
+"ui/nll/issue-27282-mutate-before-diverging-arm-3.rs",
+"ui/nll/issue-27282-mutation-in-guard.rs",
+"ui/nll/issue-27282-reborrow-ref-mut-in-guard.rs",
+"ui/nll/issue-27868.rs",
+"ui/nll/issue-30438-a.rs",
+"ui/nll/issue-30438-b.rs",
+"ui/nll/issue-30438-c.rs",
+"ui/nll/issue-31567.rs",
+"ui/nll/issue-42574-diagnostic-in-nested-closure.rs",
+"ui/nll/issue-45157.rs",
+"ui/nll/issue-45696-long-live-borrows-in-boxes.rs",
+"ui/nll/issue-45696-no-variant-box-recur.rs",
+"ui/nll/issue-45696-scribble-on-boxed-borrow.rs",
+"ui/nll/issue-46023.rs",
+"ui/nll/issue-46036.rs",
+"ui/nll/issue-46589.rs",
+"ui/nll/issue-47153-generic-const.rs",
+"ui/nll/issue-47388.rs",
+"ui/nll/issue-47470.rs",
+"ui/nll/issue-47589.rs",
+"ui/nll/issue-48070.rs",
+"ui/nll/issue-48238.rs",
+"ui/nll/issue-48623-closure.rs",
+"ui/nll/issue-48623-generator.rs",
+"ui/nll/issue-48697.rs",
+"ui/nll/issue-48803.rs",
+"ui/nll/issue-50343.rs",
+"ui/nll/issue-50461-used-mut-from-moves.rs",
+"ui/nll/issue-50716.rs",
+"ui/nll/issue-51191.rs",
+"ui/nll/issue-51244.rs",
+"ui/nll/issue-51268.rs",
+"ui/nll/issue-51512.rs",
+"ui/nll/issue-52057.rs",
+"ui/nll/issue-52059-report-when-borrow-and-drop-conflict.rs",
+"ui/nll/issue-52086.rs",
+"ui/nll/issue-52113.rs",
+"ui/nll/issue-52213.rs",
+"ui/nll/issue-52533-1.rs",
+"ui/nll/issue-52534-1.rs",
+"ui/nll/issue-52534-2.rs",
+"ui/nll/issue-52534.rs",
+"ui/nll/issue-52663-span-decl-captured-variable.rs",
+"ui/nll/issue-52663-trait-object.rs",
+"ui/nll/issue-52669.rs",
+"ui/nll/issue-52742.rs",
+"ui/nll/issue-53040.rs",
+"ui/nll/issue-53123-raw-pointer-cast.rs",
+"ui/nll/issue-53773.rs",
+"ui/nll/issue-53807.rs",
+"ui/nll/issue-54189.rs",
+"ui/nll/issue-54302-cases.rs",
+"ui/nll/issue-54302.rs",
+"ui/nll/issue-54382-use-span-of-tail-of-block.rs",
+"ui/nll/issue-54556-niconii.rs",
+"ui/nll/issue-54556-stephaneyfx.rs",
+"ui/nll/issue-54556-temps-in-tail-diagnostic.rs",
+"ui/nll/issue-54556-used-vs-unused-tails.rs",
+"ui/nll/issue-54556-wrap-it-up.rs",
+"ui/nll/issue-54779-anon-static-lifetime.rs",
+"ui/nll/issue-54943.rs",
+"ui/nll/issue-55394.rs",
+"ui/nll/issue-55401.rs",
+"ui/nll/issue-55511.rs",
+"ui/nll/issue-55850.rs",
+"ui/nll/issue-57100.rs",
+"ui/nll/issue-57265-return-type-wf-check.rs",
+"ui/nll/issue-57280-1-flipped.rs",
+"ui/nll/issue-57642-higher-ranked-subtype.rs",
+"ui/nll/issue-57843.rs",
+"ui/nll/issue-57960.rs",
+"ui/nll/issue-57989.rs",
+"ui/nll/issue-58053.rs",
+"ui/nll/issue-58299.rs",
+"ui/nll/issue-62007-assign-const-index.rs",
+"ui/nll/issue-62007-assign-differing-fields.rs",
+"ui/nll/issue-67007-escaping-data.rs",
+"ui/nll/issue-68550.rs",
+"ui/nll/issue-69114-static-mut-ty.rs",
+"ui/nll/issue-69114-static-ty.rs",
+"ui/nll/issue-73159-rpit-static.rs",
+"ui/nll/issue-75777.rs",
+"ui/nll/issue-95272.rs",
+"ui/nll/issue-97997.rs",
+"ui/nll/issue-98170.rs",
+"ui/nll/issue-98589-closures-relate-named-regions.rs",
+"ui/nll/issue-98693.rs",
+"ui/nll/issue-112604-closure-output-normalize.rs",
+"ui/nll/issue-16223.rs",
+"ui/nll/issue-21114-ebfull.rs",
+"ui/nll/issue-21114-kixunil.rs",
+"ui/nll/issue-22323-temp-destruction.rs",
+"ui/nll/issue-27583.rs",
+"ui/nll/issue-30104.rs",
+"ui/nll/issue-32382-index-assoc-type-with-lifetime.rs",
+"ui/nll/issue-43058.rs",
+"ui/nll/issue-47022.rs",
+"ui/nll/issue-48179.rs",
+"ui/nll/issue-50716-1.rs",
+"ui/nll/issue-51345-2.rs",
+"ui/nll/issue-51351.rs",
+"ui/nll/issue-51770.rs",
+"ui/nll/issue-52078.rs",
+"ui/nll/issue-52992.rs",
+"ui/nll/issue-53119.rs",
+"ui/nll/issue-53570.rs",
+"ui/nll/issue-54943-3.rs",
+"ui/nll/issue-55288.rs",
+"ui/nll/issue-55344.rs",
+"ui/nll/issue-55651.rs",
+"ui/nll/issue-55825-const-fn.rs",
+"ui/nll/issue-57280-1.rs",
+"ui/nll/issue-57280.rs",
+"ui/nll/issue-61311-normalize.rs",
+"ui/nll/issue-61320-normalize.rs",
+"ui/nll/issue-61424.rs",
+"ui/nll/issue-63154-normalize.rs",
+"ui/nll/issue-78561.rs",
+"ui/numbers-arithmetic/issue-8460.rs",
+"ui/numbers-arithmetic/issue-105626.rs",
+"ui/numbers-arithmetic/issue-8460-const.rs",
+"ui/object-safety/issue-19538.rs",
+"ui/object-safety/issue-102762.rs",
+"ui/object-safety/issue-102933.rs",
+"ui/object-safety/issue-106247.rs",
+"ui/on-unimplemented/issue-104140.rs",
+"ui/or-patterns/issue-64879-trailing-before-guard.rs",
+"ui/or-patterns/issue-69875-should-have-been-expanded-earlier-non-exhaustive.rs",
+"ui/or-patterns/issue-67514-irrefutable-param.rs",
+"ui/or-patterns/issue-68785-irrefutable-param-with-at.rs",
+"ui/or-patterns/issue-69875-should-have-been-expanded-earlier.rs",
+"ui/or-patterns/issue-70413-no-unreachable-pat-and-guard.rs",
+"ui/overloaded/issue-14958.rs",
+"ui/packed/issue-27060-2.rs",
+"ui/packed/issue-27060.rs",
+"ui/packed/issue-46152.rs",
+"ui/panics/issue-47429-short-backtraces.rs",
+"ui/parser/issues/auxiliary/issue-21146-inc.rs",
+"ui/parser/issues/auxiliary/issue-89971-outer-attr-following-inner-attr-ice.rs",
+"ui/parser/issues/auxiliary/issue-94340-inc.rs",
+"ui/parser/issues/issue-101540.rs",
+"ui/parser/issues/issue-102182-impl-trait-recover.rs",
+"ui/parser/issues/issue-10392.rs",
+"ui/parser/issues/issue-104088.rs",
+"ui/parser/issues/issue-104367.rs",
+"ui/parser/issues/issue-10636-1.rs",
+"ui/parser/issues/issue-108242-semicolon-recovery.rs",
+"ui/parser/issues/issue-110014.rs",
+"ui/parser/issues/issue-111416.rs",
+"ui/parser/issues/issue-13483.rs",
+"ui/parser/issues/issue-14303.rs",
+"ui/parser/issues/issue-15914.rs",
+"ui/parser/issues/issue-15980.rs",
+"ui/parser/issues/issue-1655.rs",
+"ui/parser/issues/issue-17718-const-mut.rs",
+"ui/parser/issues/issue-17904-2.rs",
+"ui/parser/issues/issue-1802-1.rs",
+"ui/parser/issues/issue-1802-2.rs",
+"ui/parser/issues/issue-19096.rs",
+"ui/parser/issues/issue-19398.rs",
+"ui/parser/issues/issue-20616-1.rs",
+"ui/parser/issues/issue-20616-2.rs",
+"ui/parser/issues/issue-20616-3.rs",
+"ui/parser/issues/issue-20616-4.rs",
+"ui/parser/issues/issue-20616-5.rs",
+"ui/parser/issues/issue-20616-6.rs",
+"ui/parser/issues/issue-20616-7.rs",
+"ui/parser/issues/issue-20616-8.rs",
+"ui/parser/issues/issue-20616-9.rs",
+"ui/parser/issues/issue-20711-2.rs",
+"ui/parser/issues/issue-20711.rs",
+"ui/parser/issues/issue-21153.rs",
+"ui/parser/issues/issue-21475.rs",
+"ui/parser/issues/issue-22647.rs",
+"ui/parser/issues/issue-22712.rs",
+"ui/parser/issues/issue-2354-1.rs",
+"ui/parser/issues/issue-2354.rs",
+"ui/parser/issues/issue-23620-invalid-escapes.rs",
+"ui/parser/issues/issue-24197.rs",
+"ui/parser/issues/issue-24375.rs",
+"ui/parser/issues/issue-24780.rs",
+"ui/parser/issues/issue-27255.rs",
+"ui/parser/issues/issue-31804.rs",
+"ui/parser/issues/issue-32214.rs",
+"ui/parser/issues/issue-32446.rs",
+"ui/parser/issues/issue-32501.rs",
+"ui/parser/issues/issue-32505.rs",
+"ui/parser/issues/issue-33262.rs",
+"ui/parser/issues/issue-33413.rs",
+"ui/parser/issues/issue-33418.rs",
+"ui/parser/issues/issue-33455.rs",
+"ui/parser/issues/issue-34222-1.rs",
+"ui/parser/issues/issue-34255-1.rs",
+"ui/parser/issues/issue-41155.rs",
+"ui/parser/issues/issue-43196.rs",
+"ui/parser/issues/issue-43692.rs",
+"ui/parser/issues/issue-44021.rs",
+"ui/parser/issues/issue-44406.rs",
+"ui/parser/issues/issue-45296.rs",
+"ui/parser/issues/issue-48137-macros-cannot-interpolate-impl-items-bad-variants.rs",
+"ui/parser/issues/issue-48508-aux.rs",
+"ui/parser/issues/issue-49040.rs",
+"ui/parser/issues/issue-51602.rs",
+"ui/parser/issues/issue-52496.rs",
+"ui/parser/issues/issue-5544-a.rs",
+"ui/parser/issues/issue-5544-b.rs",
+"ui/parser/issues/issue-56031.rs",
+"ui/parser/issues/issue-57198.rs",
+"ui/parser/issues/issue-5806.rs",
+"ui/parser/issues/issue-58856-1.rs",
+"ui/parser/issues/issue-58856-2.rs",
+"ui/parser/issues/issue-59418.rs",
+"ui/parser/issues/issue-60075.rs",
+"ui/parser/issues/issue-62546.rs",
+"ui/parser/issues/issue-62660.rs",
+"ui/parser/issues/issue-62881.rs",
+"ui/parser/issues/issue-62895.rs",
+"ui/parser/issues/issue-62913.rs",
+"ui/parser/issues/issue-64732.rs",
+"ui/parser/issues/issue-65122-mac-invoc-in-mut-patterns.rs",
+"ui/parser/issues/issue-65257-invalid-var-decl-recovery.rs",
+"ui/parser/issues/issue-65846-rollback-gating-failing-matcher.rs",
+"ui/parser/issues/issue-6610.rs",
+"ui/parser/issues/issue-66357-unexpected-unreachable.rs",
+"ui/parser/issues/issue-67377-invalid-syntax-in-enum-discriminant.rs",
+"ui/parser/issues/issue-68000-unicode-ident-after-missing-comma.rs",
+"ui/parser/issues/issue-68890-2.rs",
+"ui/parser/issues/issue-68890.rs",
+"ui/parser/issues/issue-69259.rs",
+"ui/parser/issues/issue-70388-recover-dotdotdot-rest-pat.rs",
+"ui/parser/issues/issue-70549-resolve-after-recovered-self-ctor.rs",
+"ui/parser/issues/issue-70552-ascription-in-parens-after-call.rs",
+"ui/parser/issues/issue-70583-block-is-empty-1.rs",
+"ui/parser/issues/issue-70583-block-is-empty-2.rs",
+"ui/parser/issues/issue-7222.rs",
+"ui/parser/issues/issue-72253.rs",
+"ui/parser/issues/issue-72373.rs",
+"ui/parser/issues/issue-73568-lifetime-after-mut.rs",
+"ui/parser/issues/issue-7970b.rs",
+"ui/parser/issues/issue-81806.rs",
+"ui/parser/issues/issue-83639.rs",
+"ui/parser/issues/issue-84117.rs",
+"ui/parser/issues/issue-84148-1.rs",
+"ui/parser/issues/issue-8537.rs",
+"ui/parser/issues/issue-86895.rs",
+"ui/parser/issues/issue-87086-colon-path-sep.rs",
+"ui/parser/issues/issue-87635.rs",
+"ui/parser/issues/issue-87812-path.rs",
+"ui/parser/issues/issue-87812.rs",
+"ui/parser/issues/issue-88818.rs",
+"ui/parser/issues/issue-89388.rs",
+"ui/parser/issues/issue-89574.rs",
+"ui/parser/issues/issue-89971-outer-attr-following-inner-attr-ice.rs",
+"ui/parser/issues/issue-90993.rs",
+"ui/parser/issues/issue-91461.rs",
+"ui/parser/issues/issue-93282.rs",
+"ui/parser/issues/issue-93867.rs",
+"ui/parser/issues/issue-94340.rs",
+"ui/parser/issues/issue-111148.rs",
+"ui/parser/issues/issue-111692.rs",
+"ui/parser/issues/issue-10392-2.rs",
+"ui/parser/issues/issue-105209.rs",
+"ui/parser/issues/issue-10636-2.rs",
+"ui/parser/issues/issue-14303-fncall.rs",
+"ui/parser/issues/issue-17904.rs",
+"ui/parser/issues/issue-21146.rs",
+"ui/parser/issues/issue-30318.rs",
+"ui/parser/issues/issue-3036.rs",
+"ui/parser/issues/issue-35813-postfix-after-cast.rs",
+"ui/parser/issues/issue-46186.rs",
+"ui/parser/issues/issue-48137-macros-cannot-interpolate-impl-items.rs",
+"ui/parser/issues/issue-48508.rs",
+"ui/parser/issues/issue-48636.rs",
+"ui/parser/issues/issue-54521-1.rs",
+"ui/parser/issues/issue-54521-2.rs",
+"ui/parser/issues/issue-54521-3.rs",
+"ui/parser/issues/issue-57684.rs",
+"ui/parser/issues/issue-57819.rs",
+"ui/parser/issues/issue-58094-missing-right-square-bracket.rs",
+"ui/parser/issues/issue-62524.rs",
+"ui/parser/issues/issue-62554.rs",
+"ui/parser/issues/issue-62894.rs",
+"ui/parser/issues/issue-62973.rs",
+"ui/parser/issues/issue-63115-range-pat-interpolated.rs",
+"ui/parser/issues/issue-63116.rs",
+"ui/parser/issues/issue-63135.rs",
+"ui/parser/issues/issue-65041-empty-vis-matcher-in-enum.rs",
+"ui/parser/issues/issue-65041-empty-vis-matcher-in-trait.rs",
+"ui/parser/issues/issue-66473.rs",
+"ui/parser/issues/issue-67146-negative-outlives-bound-syntactic-fail.rs",
+"ui/parser/issues/issue-68629.rs",
+"ui/parser/issues/issue-68730.rs",
+"ui/parser/issues/issue-68788-in-trait-item-propagation.rs",
+"ui/parser/issues/issue-70050-ntliteral-accepts-negated-lit.rs",
+"ui/parser/issues/issue-70388-without-witness.rs",
+"ui/parser/issues/issue-75599.rs",
+"ui/parser/issues/issue-76437-async.rs",
+"ui/parser/issues/issue-76437-const-async-unsafe.rs",
+"ui/parser/issues/issue-76437-const-async.rs",
+"ui/parser/issues/issue-76437-const.rs",
+"ui/parser/issues/issue-76437-pub-crate-unsafe.rs",
+"ui/parser/issues/issue-76437-unsafe.rs",
+"ui/parser/issues/issue-76597.rs",
+"ui/parser/issues/issue-84104.rs",
+"ui/parser/issues/issue-84148-2.rs",
+"ui/parser/issues/issue-87197-missing-semicolon.rs",
+"ui/parser/issues/issue-88276-unary-plus.rs",
+"ui/parser/issues/issue-88583-union-as-ident.rs",
+"ui/parser/issues/issue-88770.rs",
+"ui/parser/issues/issue-89396.rs",
+"ui/parser/issues/issue-112458.rs",
+"ui/parser/macro/issue-33569.rs",
+"ui/parser/macro/issue-37113.rs",
+"ui/parser/macro/issue-37234.rs",
+"ui/parser/raw/issue-70677-panic-on-unterminated-raw-str-at-eof.rs",
+"ui/parser/shebang/issue-71471-ignore-tidy.rs",
+"ui/parser/issue-102806.rs",
+"ui/parser/issue-103143.rs",
+"ui/parser/issue-103425.rs",
+"ui/parser/issue-103748-ICE-wrong-braces.rs",
+"ui/parser/issue-104620.rs",
+"ui/parser/issue-104867-inc-dec-2.rs",
+"ui/parser/issue-104867-inc-dec.rs",
+"ui/parser/issue-108495-dec.rs",
+"ui/parser/issue-17718-parse-const.rs",
+"ui/parser/issue-39616.rs",
+"ui/parser/issue-49257.rs",
+"ui/parser/issue-61858.rs",
+"ui/parser/issue-68091-unicode-ident-after-if.rs",
+"ui/parser/issue-68092-unicode-ident-after-incomplete-expr.rs",
+"ui/parser/issue-68987-unmatch-issue-1.rs",
+"ui/parser/issue-68987-unmatch-issue-2.rs",
+"ui/parser/issue-68987-unmatch-issue-3.rs",
+"ui/parser/issue-68987-unmatch-issue.rs",
+"ui/parser/issue-87694-duplicated-pub.rs",
+"ui/parser/issue-87694-misplaced-pub.rs",
+"ui/parser/issue-90728.rs",
+"ui/parser/issue-91421.rs",
+"ui/parser/issue-100197-mut-let.rs",
+"ui/parser/issue-101477-enum.rs",
+"ui/parser/issue-101477-let.rs",
+"ui/parser/issue-103381.rs",
+"ui/parser/issue-103451.rs",
+"ui/parser/issue-105366.rs",
+"ui/parser/issue-105634.rs",
+"ui/parser/issue-107705.rs",
+"ui/parser/issue-112188.rs",
+"ui/parser/issue-81804.rs",
+"ui/parser/issue-81827.rs",
+"ui/parser/issue-99625-enum-struct-mutually-exclusive.rs",
+"ui/parser/issue-99910-const-let-mutually-exclusive.rs",
+"ui/parser/issue-113342.rs",
+"ui/pattern/move-ref-patterns/issue-53840.rs",
+"ui/pattern/usefulness/issue-12116.rs",
+"ui/pattern/usefulness/issue-12369.rs",
+"ui/pattern/usefulness/issue-13727.rs",
+"ui/pattern/usefulness/issue-15129.rs",
+"ui/pattern/usefulness/issue-2111.rs",
+"ui/pattern/usefulness/issue-30240-b.rs",
+"ui/pattern/usefulness/issue-30240-rpass.rs",
+"ui/pattern/usefulness/issue-30240.rs",
+"ui/pattern/usefulness/issue-3096-1.rs",
+"ui/pattern/usefulness/issue-3096-2.rs",
+"ui/pattern/usefulness/issue-31221.rs",
+"ui/pattern/usefulness/issue-31561.rs",
+"ui/pattern/usefulness/issue-35609.rs",
+"ui/pattern/usefulness/issue-39362.rs",
+"ui/pattern/usefulness/issue-40221.rs",
+"ui/pattern/usefulness/issue-4321.rs",
+"ui/pattern/usefulness/issue-50900.rs",
+"ui/pattern/usefulness/issue-56379.rs",
+"ui/pattern/usefulness/issue-57472.rs",
+"ui/pattern/usefulness/issue-72377.rs",
+"ui/pattern/usefulness/issue-78123-non-exhaustive-reference.rs",
+"ui/pattern/usefulness/issue-82772-match-box-as-struct.rs",
+"ui/pattern/usefulness/issue-53820-slice-pattern-large-array.rs",
+"ui/pattern/usefulness/issue-65413-constants-and-slices-exhaustiveness.rs",
+"ui/pattern/usefulness/issue-66501.rs",
+"ui/pattern/usefulness/issue-71930-type-of-match-scrutinee.rs",
+"ui/pattern/usefulness/issue-72476-and-89393-associated-type.rs",
+"ui/pattern/usefulness/issue-78549-ref-pat-and-str.rs",
+"ui/pattern/usefulness/issue-80501-or-pat-and-macro.rs",
+"ui/pattern/usefulness/issue-88747.rs",
+"ui/pattern/usefulness/issue-3601.rs",
+"ui/pattern/issue-10392.rs",
+"ui/pattern/issue-106552.rs",
+"ui/pattern/issue-11577.rs",
+"ui/pattern/issue-12582.rs",
+"ui/pattern/issue-14221.rs",
+"ui/pattern/issue-15080.rs",
+"ui/pattern/issue-17718-patterns.rs",
+"ui/pattern/issue-22546.rs",
+"ui/pattern/issue-27320.rs",
+"ui/pattern/issue-52240.rs",
+"ui/pattern/issue-6449.rs",
+"ui/pattern/issue-66270-pat-struct-parser-recovery.rs",
+"ui/pattern/issue-67037-pat-tup-scrut-ty-diff-less-fields.rs",
+"ui/pattern/issue-67776-match-same-name-enum-variant-refs.rs",
+"ui/pattern/issue-68393-let-pat-assoc-constant.rs",
+"ui/pattern/issue-72574-1.rs",
+"ui/pattern/issue-72574-2.rs",
+"ui/pattern/issue-74539.rs",
+"ui/pattern/issue-74702.rs",
+"ui/pattern/issue-80186-mut-binding-help-suggestion.rs",
+"ui/pattern/issue-8351-1.rs",
+"ui/pattern/issue-8351-2.rs",
+"ui/pattern/issue-88074-pat-range-type-inference-err.rs",
+"ui/pattern/issue-92074-macro-ice.rs",
+"ui/pattern/issue-95878.rs",
+"ui/pattern/issue-72565.rs",
+"ui/pattern/issue-94866.rs",
+"ui/pattern/issue-106862.rs",
+"ui/pattern/issue-74954.rs",
+"ui/pattern/issue-88074-pat-range-type-inference.rs",
+"ui/pattern/issue-110508.rs",
+"ui/polymorphization/issue-74614.rs",
+"ui/polymorphization/issue-74636.rs",
+"ui/privacy/auxiliary/issue-17718-const-privacy.rs",
+"ui/privacy/auxiliary/issue-57264-1.rs",
+"ui/privacy/auxiliary/issue-57264-2.rs",
+"ui/privacy/auxiliary/issue-75907.rs",
+"ui/privacy/auxiliary/issue-92755.rs",
+"ui/privacy/issue-13641.rs",
+"ui/privacy/issue-17718-const-privacy.rs",
+"ui/privacy/issue-29161.rs",
+"ui/privacy/issue-30079.rs",
+"ui/privacy/issue-46209-private-enum-variant-reexport.rs",
+"ui/privacy/issue-75062-fieldless-tuple-struct.rs",
+"ui/privacy/issue-75906.rs",
+"ui/privacy/issue-75907.rs",
+"ui/privacy/issue-75907_b.rs",
+"ui/privacy/issue-79593.rs",
+"ui/privacy/issue-92755.rs",
+"ui/privacy/issue-111220-2-tuple-struct-fields-projection.rs",
+"ui/privacy/issue-111220-tuple-struct-fields.rs",
+"ui/privacy/issue-57264-1.rs",
+"ui/privacy/issue-57264-2.rs",
+"ui/proc-macro/auxiliary/issue-104884.rs",
+"ui/proc-macro/auxiliary/issue-38586.rs",
+"ui/proc-macro/auxiliary/issue-39889.rs",
+"ui/proc-macro/auxiliary/issue-42708.rs",
+"ui/proc-macro/auxiliary/issue-50061.rs",
+"ui/proc-macro/auxiliary/issue-50493.rs",
+"ui/proc-macro/auxiliary/issue-66286.rs",
+"ui/proc-macro/auxiliary/issue-75801.rs",
+"ui/proc-macro/auxiliary/issue-79242.rs",
+"ui/proc-macro/auxiliary/issue-79825.rs",
+"ui/proc-macro/auxiliary/issue-83510.rs",
+"ui/proc-macro/auxiliary/issue-91800-macro.rs",
+"ui/proc-macro/auxiliary/issue-59191.rs",
+"ui/proc-macro/issue-104884-trait-impl-sugg-err.rs",
+"ui/proc-macro/issue-36935.rs",
+"ui/proc-macro/issue-37788.rs",
+"ui/proc-macro/issue-38586.rs",
+"ui/proc-macro/issue-39889.rs",
+"ui/proc-macro/issue-42708.rs",
+"ui/proc-macro/issue-50061.rs",
+"ui/proc-macro/issue-50493.rs",
+"ui/proc-macro/issue-53481.rs",
+"ui/proc-macro/issue-66286.rs",
+"ui/proc-macro/issue-75801.rs",
+"ui/proc-macro/issue-81543-item-parse-err.rs",
+"ui/proc-macro/issue-83469-global-alloc-invalid-stmt.rs",
+"ui/proc-macro/issue-83510.rs",
+"ui/proc-macro/issue-91800.rs",
+"ui/proc-macro/issue-59191-replace-root-with-fn.rs",
+"ui/proc-macro/issue-73933-procedural-masquerade.rs",
+"ui/proc-macro/issue-75734-pp-paren.rs",
+"ui/proc-macro/issue-75930-derive-cfg.rs",
+"ui/proc-macro/issue-76182-leading-vert-pat.rs",
+"ui/proc-macro/issue-76270-panic-in-libproc-macro.rs",
+"ui/proc-macro/issue-78675-captured-inner-attrs.rs",
+"ui/proc-macro/issue-79148.rs",
+"ui/proc-macro/issue-79242-slow-retokenize-check.rs",
+"ui/proc-macro/issue-79825.rs",
+"ui/proc-macro/issue-80760-empty-stmt.rs",
+"ui/proc-macro/issue-81007-item-attrs.rs",
+"ui/proc-macro/issue-81555.rs",
+"ui/proc-macro/issue-86781-bad-inner-doc.rs",
+"ui/process/issue-13304.rs",
+"ui/process/issue-14456.rs",
+"ui/process/issue-14940.rs",
+"ui/process/issue-16272.rs",
+"ui/process/issue-20091.rs",
+"ui/ptr_ops/issue-80309-safe.rs",
+"ui/ptr_ops/issue-80309.rs",
+"ui/pub/issue-33174-restricted-type-in-public-interface.rs",
+"ui/query-system/issue-83479.rs",
+"ui/range/issue-54505-no-std.rs",
+"ui/range/issue-73553-misinterp-range-literal.rs",
+"ui/range/issue-54505-no-literals.rs",
+"ui/range/issue-54505.rs",
+"ui/reachable/auxiliary/issue-11225-1.rs",
+"ui/reachable/auxiliary/issue-11225-2.rs",
+"ui/reachable/auxiliary/issue-11225-3.rs",
+"ui/reachable/issue-11225-1.rs",
+"ui/reachable/issue-11225-2.rs",
+"ui/reachable/issue-11225-3.rs",
+"ui/reachable/issue-948.rs",
+"ui/recursion/issue-26548-recursion-via-normalize.rs",
+"ui/recursion/issue-38591-non-regular-dropck-recursion.rs",
+"ui/recursion/issue-86784.rs",
+"ui/recursion/issue-83150.rs",
+"ui/recursion/issue-95134.rs",
+"ui/recursion_limit/issue-105700.rs",
+"ui/recursion_limit/issue-40003.rs",
+"ui/regions/issue-101280.rs",
+"ui/regions/issue-102374.rs",
+"ui/regions/issue-102392.rs",
+"ui/regions/issue-12470.rs",
+"ui/regions/issue-26448-1.rs",
+"ui/regions/issue-28848.rs",
+"ui/regions/issue-5243.rs",
+"ui/regions/issue-6157.rs",
+"ui/regions/issue-11612.rs",
+"ui/regions/issue-21520.rs",
+"ui/regions/issue-24085.rs",
+"ui/regions/issue-26448-2.rs",
+"ui/regions/issue-26448-3.rs",
+"ui/regions/issue-56537-closure-uses-region-from-container.rs",
+"ui/regions/issue-72051-member-region-hang.rs",
+"ui/regions/issue-78262.rs",
+"ui/repr/issue-83505-repr-simd.rs",
+"ui/repr/issue-83921-ice.rs",
+"ui/resolve/auxiliary/issue-19452-aux.rs",
+"ui/resolve/auxiliary/issue-21221-3.rs",
+"ui/resolve/auxiliary/issue-21221-4.rs",
+"ui/resolve/auxiliary/issue-30535.rs",
+"ui/resolve/auxiliary/issue-3907.rs",
+"ui/resolve/auxiliary/issue-80079.rs",
+"ui/resolve/auxiliary/issue-112831-aux.rs",
+"ui/resolve/issue-113808-invalid-unused-qualifications-suggestion.rs",
+"ui/resolve/issue-100365.rs",
+"ui/resolve/issue-101749-2.rs",
+"ui/resolve/issue-10200.rs",
+"ui/resolve/issue-102946.rs",
+"ui/resolve/issue-103202.rs",
+"ui/resolve/issue-103474.rs",
+"ui/resolve/issue-104700-inner_scope.rs",
+"ui/resolve/issue-105069.rs",
+"ui/resolve/issue-107563-ambiguous-glob-reexports.rs",
+"ui/resolve/issue-108529.rs",
+"ui/resolve/issue-109250.rs",
+"ui/resolve/issue-12796.rs",
+"ui/resolve/issue-14254.rs",
+"ui/resolve/issue-16058.rs",
+"ui/resolve/issue-17518.rs",
+"ui/resolve/issue-18252.rs",
+"ui/resolve/issue-19452.rs",
+"ui/resolve/issue-21221-1.rs",
+"ui/resolve/issue-21221-2.rs",
+"ui/resolve/issue-21221-3.rs",
+"ui/resolve/issue-21221-4.rs",
+"ui/resolve/issue-22692.rs",
+"ui/resolve/issue-2330.rs",
+"ui/resolve/issue-23305.rs",
+"ui/resolve/issue-2356.rs",
+"ui/resolve/issue-23716.rs",
+"ui/resolve/issue-24968.rs",
+"ui/resolve/issue-26545.rs",
+"ui/resolve/issue-3021-c.rs",
+"ui/resolve/issue-3021.rs",
+"ui/resolve/issue-30535.rs",
+"ui/resolve/issue-3099-a.rs",
+"ui/resolve/issue-3099-b.rs",
+"ui/resolve/issue-31845.rs",
+"ui/resolve/issue-33876.rs",
+"ui/resolve/issue-35675.rs",
+"ui/resolve/issue-3907-2.rs",
+"ui/resolve/issue-3907.rs",
+"ui/resolve/issue-39226.rs",
+"ui/resolve/issue-39559-2.rs",
+"ui/resolve/issue-39559.rs",
+"ui/resolve/issue-42944.rs",
+"ui/resolve/issue-49074.rs",
+"ui/resolve/issue-5035-2.rs",
+"ui/resolve/issue-5035.rs",
+"ui/resolve/issue-50599.rs",
+"ui/resolve/issue-5099.rs",
+"ui/resolve/issue-54379.rs",
+"ui/resolve/issue-55673.rs",
+"ui/resolve/issue-5927.rs",
+"ui/resolve/issue-60057.rs",
+"ui/resolve/issue-65025-extern-static-parent-generics.rs",
+"ui/resolve/issue-65035-static-with-parent-generics.rs",
+"ui/resolve/issue-6702.rs",
+"ui/resolve/issue-69401-trait-fn-no-body-ty-local.rs",
+"ui/resolve/issue-73427.rs",
+"ui/resolve/issue-80079.rs",
+"ui/resolve/issue-81508.rs",
+"ui/resolve/issue-82156.rs",
+"ui/resolve/issue-82865.rs",
+"ui/resolve/issue-85348.rs",
+"ui/resolve/issue-88472.rs",
+"ui/resolve/issue-90113.rs",
+"ui/resolve/issue-109153.rs",
+"ui/resolve/issue-101749.rs",
+"ui/resolve/issue-111312.rs",
+"ui/resolve/issue-111727.rs",
+"ui/resolve/issue-112472-multi-generics-suggestion.rs",
+"ui/resolve/issue-112831.rs",
+"ui/resolve/issue-57523.rs",
+"ui/resolve/issue-70736-async-fn-no-body-def-collector.rs",
+"ui/resolve/issue-85671.rs",
+"ui/return/issue-82612-return-mutable-reference.rs",
+"ui/return/issue-64620.rs",
+"ui/return/issue-86188-return-not-in-fn-body.rs",
+"ui/rfcs/rfc-1937-termination-trait/issue-103052-1.rs",
+"ui/rfcs/rfc-1937-termination-trait/issue-103052-2.rs",
+"ui/rfcs/rfc-2005-default-binding-mode/issue-44912-or.rs",
+"ui/rfcs/rfc-2396-target_feature-11/issue-108645-target-feature-on-main.rs",
+"ui/rfcs/rfc-2396-target_feature-11/issue-108645-target-feature-on-start.rs",
+"ui/rfcs/rfc-2396-target_feature-11/issue-99876.rs",
+"ui/rfcs/rfc-2396-target_feature-11/issue-108655-inline-always-closure.rs",
+"ui/rfcs/rfc-2528-type-changing-struct-update/issue-92010-trait-bound-not-satisfied.rs",
+"ui/rfcs/rfc-2528-type-changing-struct-update/issue-96878.rs",
+"ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-61188-match-slice-forbidden-without-eq.rs",
+"ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-62307-match-ref-ref-forbidden-without-eq.rs",
+"ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-63479-match-fnptr.rs",
+"ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-6804.rs",
+"ui/rfcs/rfc-2008-non-exhaustive/uninhabited/issue-65157-repeated-match-arm.rs",
+"ui/rfcs/rfc-2093-infer-outlives/issue-54467.rs",
+"ui/rfcs/rfc-2497-if-let-chains/issue-93150.rs",
+"ui/rfcs/rfc-2497-if-let-chains/issue-88498.rs",
+"ui/rfcs/rfc-2497-if-let-chains/issue-90722.rs",
+"ui/rfcs/rfc-2497-if-let-chains/issue-92145.rs",
+"ui/rfcs/rfc-2497-if-let-chains/issue-99938.rs",
+"ui/rfcs/rfc-2565-param-attrs/issue-64682-dropping-first-attrs-in-impl-fns.rs",
+"ui/rfcs/rfc-2632-const-trait-impl/issue-102156.rs",
+"ui/rfcs/rfc-2632-const-trait-impl/issue-102985.rs",
+"ui/rfcs/rfc-2632-const-trait-impl/issue-79450.rs",
+"ui/rfcs/rfc-2632-const-trait-impl/issue-88155.rs",
+"ui/rfcs/rfc-2632-const-trait-impl/issue-90052.rs",
+"ui/rfcs/rfc-2632-const-trait-impl/specialization/issue-95186-specialize-on-tilde-const.rs",
+"ui/rfcs/rfc-2632-const-trait-impl/specialization/issue-95187-same-trait-bound-different-constness.rs",
+"ui/rfcs/rfc-2632-const-trait-impl/issue-100222.rs",
+"ui/rfcs/rfc-2632-const-trait-impl/issue-103677.rs",
+"ui/rfcs/rfc-2632-const-trait-impl/issue-92111.rs",
+"ui/rfcs/rfc-2632-const-trait-impl/issue-92230-wf-super-trait-env.rs",
+"ui/rust-2018/uniform-paths/auxiliary/issue-55779-extern-trait.rs",
+"ui/rust-2018/uniform-paths/auxiliary/issue-56596-2.rs",
+"ui/rust-2018/uniform-paths/auxiliary/issue-56596.rs",
+"ui/rust-2018/uniform-paths/auxiliary/issue-87932-a.rs",
+"ui/rust-2018/uniform-paths/issue-54253.rs",
+"ui/rust-2018/uniform-paths/issue-55779.rs",
+"ui/rust-2018/uniform-paths/issue-56596-2.rs",
+"ui/rust-2018/uniform-paths/issue-56596.rs",
+"ui/rust-2018/uniform-paths/issue-87932.rs",
+"ui/rust-2018/issue-51008-1.rs",
+"ui/rust-2018/issue-51008.rs",
+"ui/rust-2018/issue-52202-use-suggestions.rs",
+"ui/rust-2018/issue-54006.rs",
+"ui/rust-2018/issue-54400-unused-extern-crate-attr-span.rs",
+"ui/sanitize/issue-111184-generator-witness.rs",
+"ui/sanitize/issue-72154-lifetime-markers.rs",
+"ui/self/issue-61882-2.rs",
+"ui/self/issue-61882.rs",
+"ui/simd/intrinsic/issue-85855.rs",
+"ui/simd/issue-17170.rs",
+"ui/simd/issue-32947.rs",
+"ui/simd/issue-39720.rs",
+"ui/simd/issue-85915-simd-ptrs.rs",
+"ui/simd/issue-89193.rs",
+"ui/simd/issue-105439.rs",
+"ui/single-use-lifetime/issue-104440.rs",
+"ui/single-use-lifetime/issue-107998.rs",
+"ui/span/issue28498-reject-ex1.rs",
+"ui/span/issue28498-reject-lifetime-param.rs",
+"ui/span/issue28498-reject-passed-to-fn.rs",
+"ui/span/issue28498-reject-trait-bound.rs",
+"ui/span/issue-11925.rs",
+"ui/span/issue-23338-locals-die-before-temps-of-body.rs",
+"ui/span/issue-23729.rs",
+"ui/span/issue-23827.rs",
+"ui/span/issue-24356.rs",
+"ui/span/issue-24805-dropck-child-has-items-via-parent.rs",
+"ui/span/issue-24805-dropck-trait-has-items.rs",
+"ui/span/issue-24895-copy-clone-dropck.rs",
+"ui/span/issue-25199.rs",
+"ui/span/issue-26656.rs",
+"ui/span/issue-27522.rs",
+"ui/span/issue-29106.rs",
+"ui/span/issue-29595.rs",
+"ui/span/issue-33884.rs",
+"ui/span/issue-34264.rs",
+"ui/span/issue-35987.rs",
+"ui/span/issue-36537.rs",
+"ui/span/issue-37767.rs",
+"ui/span/issue-39018.rs",
+"ui/span/issue-39698.rs",
+"ui/span/issue-40157.rs",
+"ui/span/issue-43927-non-ADT-derive.rs",
+"ui/span/issue-81800.rs",
+"ui/span/issue-107353.rs",
+"ui/span/issue-15480.rs",
+"ui/span/issue-24690.rs",
+"ui/span/issue-42234-unknown-receiver-type.rs",
+"ui/span/issue-71363.rs",
+"ui/specialization/min_specialization/issue-79224.rs",
+"ui/specialization/issue-111232.rs",
+"ui/specialization/issue-33017.rs",
+"ui/specialization/issue-38091-2.rs",
+"ui/specialization/issue-38091.rs",
+"ui/specialization/issue-39448.rs",
+"ui/specialization/issue-44861.rs",
+"ui/specialization/issue-50452-fail.rs",
+"ui/specialization/issue-50452.rs",
+"ui/specialization/issue-51892.rs",
+"ui/specialization/issue-52050.rs",
+"ui/specialization/issue-59435.rs",
+"ui/specialization/issue-68830-spurious-diagnostics.rs",
+"ui/specialization/issue-35376.rs",
+"ui/specialization/issue-36804.rs",
+"ui/specialization/issue-39618.rs",
+"ui/specialization/issue-40582.rs",
+"ui/specialization/issue-43037.rs",
+"ui/specialization/issue-45814.rs",
+"ui/specialization/issue-63716-parse-async.rs",
+"ui/specialization/issue-70442.rs",
+"ui/stability-attribute/issue-106589.rs",
+"ui/stability-attribute/issue-109177.rs",
+"ui/stability-attribute/issue-28075.rs",
+"ui/stability-attribute/issue-28388-3.rs",
+"ui/stability-attribute/issue-99286-stable-intrinsics.rs",
+"ui/static/auxiliary/issue_24843.rs",
+"ui/static/issue-18118-2.rs",
+"ui/static/issue-18118.rs",
+"ui/static/issue-34194.rs",
+"ui/static/issue-5216.rs",
+"ui/static/issue-24843.rs",
+"ui/statics/issue-15261.rs",
+"ui/statics/issue-17233.rs",
+"ui/statics/issue-17718-static-sync.rs",
+"ui/statics/issue-17718-static-unsafe-interior.rs",
+"ui/statics/issue-44373.rs",
+"ui/statics/issue-14227.rs",
+"ui/statics/issue-44373-2.rs",
+"ui/statics/issue-91050-1.rs",
+"ui/statics/issue-91050-2.rs",
+"ui/std/issue-15149.rs",
+"ui/std/issue-81357-unsound-file-methods.rs",
+"ui/stdlib-unit-tests/issue-21058.rs",
+"ui/structs-enums/struct-rec/issue-74224.rs",
+"ui/structs-enums/struct-rec/issue-84611.rs",
+"ui/structs-enums/issue-1701.rs",
+"ui/structs-enums/issue-2718-a.rs",
+"ui/structs-enums/issue-38002.rs",
+"ui/structs-enums/issue-50731.rs",
+"ui/structs-enums/issue-3008-1.rs",
+"ui/structs-enums/issue-3008-2.rs",
+"ui/structs-enums/issue-3008-3.rs",
+"ui/structs-enums/issue-103869.rs",
+"ui/structs/issue-80853.rs",
+"ui/suggestions/auxiliary/issue-61963-1.rs",
+"ui/suggestions/auxiliary/issue-61963.rs",
+"ui/suggestions/auxiliary/issue-81839.rs",
+"ui/suggestions/lifetimes/issue-105544.rs",
+"ui/suggestions/issue-101421.rs",
+"ui/suggestions/issue-101465.rs",
+"ui/suggestions/issue-101623.rs",
+"ui/suggestions/issue-101984.rs",
+"ui/suggestions/issue-102354.rs",
+"ui/suggestions/issue-102892.rs",
+"ui/suggestions/issue-103112.rs",
+"ui/suggestions/issue-104086-suggest-let.rs",
+"ui/suggestions/issue-104287.rs",
+"ui/suggestions/issue-104327.rs",
+"ui/suggestions/issue-104328.rs",
+"ui/suggestions/issue-105226.rs",
+"ui/suggestions/issue-105494.rs",
+"ui/suggestions/issue-105645.rs",
+"ui/suggestions/issue-106443-sugg-clone-for-arg.rs",
+"ui/suggestions/issue-106443-sugg-clone-for-bound.rs",
+"ui/suggestions/issue-109291.rs",
+"ui/suggestions/issue-109396.rs",
+"ui/suggestions/issue-109436.rs",
+"ui/suggestions/issue-109854.rs",
+"ui/suggestions/issue-21673.rs",
+"ui/suggestions/issue-51055-missing-semicolon-between-call-and-tuple.rs",
+"ui/suggestions/issue-61963.rs",
+"ui/suggestions/issue-62843.rs",
+"ui/suggestions/issue-64252-self-type.rs",
+"ui/suggestions/issue-66968-suggest-sorted-words.rs",
+"ui/suggestions/issue-68049-1.rs",
+"ui/suggestions/issue-68049-2.rs",
+"ui/suggestions/issue-71394-no-from-impl.rs",
+"ui/suggestions/issue-81098.rs",
+"ui/suggestions/issue-82566-1.rs",
+"ui/suggestions/issue-82566-2.rs",
+"ui/suggestions/issue-84592.rs",
+"ui/suggestions/issue-84700.rs",
+"ui/suggestions/issue-84973-2.rs",
+"ui/suggestions/issue-84973-blacklist.rs",
+"ui/suggestions/issue-84973-negative.rs",
+"ui/suggestions/issue-84973.rs",
+"ui/suggestions/issue-85347.rs",
+"ui/suggestions/issue-85943-no-suggest-unsized-indirection-in-where-clause.rs",
+"ui/suggestions/issue-85945-check-where-clause-before-suggesting-unsized.rs",
+"ui/suggestions/issue-86100-tuple-paren-comma.rs",
+"ui/suggestions/issue-88730.rs",
+"ui/suggestions/issue-89064.rs",
+"ui/suggestions/issue-89333.rs",
+"ui/suggestions/issue-90974.rs",
+"ui/suggestions/issue-94171.rs",
+"ui/suggestions/issue-96223.rs",
+"ui/suggestions/issue-97760.rs",
+"ui/suggestions/issue-98500.rs",
+"ui/suggestions/issue-99080.rs",
+"ui/suggestions/issue-99240-2.rs",
+"ui/suggestions/issue-99240.rs",
+"ui/suggestions/issue-99597.rs",
+"ui/suggestions/issue-103646.rs",
+"ui/suggestions/issue-88696.rs",
+"ui/suggestions/issue-101065.rs",
+"ui/suggestions/issue-104961.rs",
+"ui/suggestions/issue-105761-suggest-self-for-closure.rs",
+"ui/suggestions/issue-107860.rs",
+"ui/suggestions/issue-108470.rs",
+"ui/suggestions/issue-52820.rs",
+"ui/suggestions/issue-53692.rs",
+"ui/suggestions/issue-57672.rs",
+"ui/suggestions/issue-59819.rs",
+"ui/suggestions/issue-61226.rs",
+"ui/suggestions/issue-72766.rs",
+"ui/suggestions/issue-79843-impl-trait-with-missing-bounds-on-async-fn.rs",
+"ui/suggestions/issue-81839.rs",
+"ui/suggestions/issue-82361.rs",
+"ui/suggestions/issue-83892.rs",
+"ui/suggestions/issue-83943.rs",
+"ui/suggestions/issue-86667.rs",
+"ui/suggestions/issue-90213-expected-boxfuture-self-ice.rs",
+"ui/suggestions/issue-96555.rs",
+"ui/suggestions/issue-97677.rs",
+"ui/suggestions/issue-97704.rs",
+"ui/suggestions/issue-102972.rs",
+"ui/suggestions/issue-109991.rs",
+"ui/suggestions/issue-112590-suggest-import.rs",
+"ui/suggestions/issue-89640.rs",
+"ui/symbol-names/issue-53912.rs",
+"ui/symbol-names/issue-60925.rs",
+"ui/symbol-names/issue-75326.rs",
+"ui/symbol-names/issue-76365.rs",
+"ui/test-attrs/custom-test-frameworks/issue-107454.rs",
+"ui/test-attrs/issue-109816.rs",
+"ui/test-attrs/issue-12997-1.rs",
+"ui/test-attrs/issue-12997-2.rs",
+"ui/test-attrs/issue-16597-empty.rs",
+"ui/test-attrs/issue-16597.rs",
+"ui/test-attrs/issue-20823.rs",
+"ui/test-attrs/issue-34932.rs",
+"ui/test-attrs/issue-36768.rs",
+"ui/test-attrs/issue-52557.rs",
+"ui/test-attrs/issue-53675-a-test-called-panic.rs",
+"ui/threads-sendsync/issue-24313.rs",
+"ui/threads-sendsync/issue-29488.rs",
+"ui/threads-sendsync/issue-43733-2.rs",
+"ui/threads-sendsync/issue-4446.rs",
+"ui/threads-sendsync/issue-4448.rs",
+"ui/threads-sendsync/issue-8827.rs",
+"ui/threads-sendsync/issue-9396.rs",
+"ui/threads-sendsync/issue-43733.rs",
+"ui/trait-bounds/issue-75961.rs",
+"ui/trait-bounds/issue-93008.rs",
+"ui/trait-bounds/issue-94680.rs",
+"ui/trait-bounds/issue-94999.rs",
+"ui/trait-bounds/issue-95640.rs",
+"ui/traits/alias/issue-108072-unmet-trait-alias-bound.rs",
+"ui/traits/alias/issue-108132-unmet-trait-alias-bound-on-generic-impl.rs",
+"ui/traits/alias/issue-83613.rs",
+"ui/traits/alias/issue-107747-do-not-assemble-supertraits.rs",
+"ui/traits/alias/issue-60021-assoc-method-resolve.rs",
+"ui/traits/alias/issue-60755.rs",
+"ui/traits/alias/issue-72415-assoc-const-resolve.rs",
+"ui/traits/alias/issue-75983.rs",
+"ui/traits/associated_type_bound/issue-51446.rs",
+"ui/traits/auxiliary/issue_89119_intercrate_caching.rs",
+"ui/traits/new-solver/coherence/issue-102048.rs",
+"ui/traits/object/issue-44454-1.rs",
+"ui/traits/object/issue-44454-2.rs",
+"ui/traits/object/issue-44454-3.rs",
+"ui/traits/object/issue-33140-traitobject-crate.rs",
+"ui/traits/suggest-deferences/issue-39029.rs",
+"ui/traits/suggest-deferences/issue-62530.rs",
+"ui/traits/trait-upcasting/issue-11515.rs",
+"ui/traits/trait-upcasting/issue-11515-upcast-fn_mut-fn.rs",
+"ui/traits/vtable/issue-97381.rs",
+"ui/traits/vtable/issue-91807.rs",
+"ui/traits/issue-102989.rs",
+"ui/traits/issue-103563.rs",
+"ui/traits/issue-104322.rs",
+"ui/traits/issue-106072.rs",
+"ui/traits/issue-18400.rs",
+"ui/traits/issue-18412.rs",
+"ui/traits/issue-20692.rs",
+"ui/traits/issue-22019.rs",
+"ui/traits/issue-22110.rs",
+"ui/traits/issue-22384.rs",
+"ui/traits/issue-22655.rs",
+"ui/traits/issue-23003.rs",
+"ui/traits/issue-23825.rs",
+"ui/traits/issue-24010.rs",
+"ui/traits/issue-26339.rs",
+"ui/traits/issue-28576.rs",
+"ui/traits/issue-32963.rs",
+"ui/traits/issue-33140-hack-boundaries.rs",
+"ui/traits/issue-33140.rs",
+"ui/traits/issue-35869.rs",
+"ui/traits/issue-3683.rs",
+"ui/traits/issue-38033.rs",
+"ui/traits/issue-38404.rs",
+"ui/traits/issue-38604.rs",
+"ui/traits/issue-3973.rs",
+"ui/traits/issue-4107.rs",
+"ui/traits/issue-43132.rs",
+"ui/traits/issue-43784-supertrait.rs",
+"ui/traits/issue-50480.rs",
+"ui/traits/issue-52893.rs",
+"ui/traits/issue-56202.rs",
+"ui/traits/issue-56488.rs",
+"ui/traits/issue-59029-1.rs",
+"ui/traits/issue-59029-2.rs",
+"ui/traits/issue-6128.rs",
+"ui/traits/issue-6334.rs",
+"ui/traits/issue-65284-suggest-generic-trait-bound.rs",
+"ui/traits/issue-65673.rs",
+"ui/traits/issue-68295.rs",
+"ui/traits/issue-7013.rs",
+"ui/traits/issue-71036.rs",
+"ui/traits/issue-71136.rs",
+"ui/traits/issue-72410.rs",
+"ui/traits/issue-75627.rs",
+"ui/traits/issue-77982.rs",
+"ui/traits/issue-78372.rs",
+"ui/traits/issue-79458.rs",
+"ui/traits/issue-8153.rs",
+"ui/traits/issue-85735.rs",
+"ui/traits/issue-87558.rs",
+"ui/traits/issue-91594.rs",
+"ui/traits/issue-9394-inherited-calls.rs",
+"ui/traits/issue-97576.rs",
+"ui/traits/issue-99875.rs",
+"ui/traits/issue-105231.rs",
+"ui/traits/issue-83538-tainted-cache-after-cycle.rs",
+"ui/traits/issue-23003-overflow.rs",
+"ui/traits/issue-70944.rs",
+"ui/traits/issue-72455.rs",
+"ui/traits/issue-78632.rs",
+"ui/traits/issue-82830.rs",
+"ui/traits/issue-84399-bad-fresh-caching.rs",
+"ui/traits/issue-85360-eval-obligation-ice.rs",
+"ui/traits/issue-89119.rs",
+"ui/traits/issue-90195-2.rs",
+"ui/traits/issue-90195.rs",
+"ui/traits/issue-90662-projection-caching.rs",
+"ui/traits/issue-91949-hangs-on-recursion.rs",
+"ui/traits/issue-92292.rs",
+"ui/traits/issue-95311.rs",
+"ui/traits/issue-95898.rs",
+"ui/traits/issue-96664.rs",
+"ui/traits/issue-96665.rs",
+"ui/traits/issue-97695-double-trivial-bound.rs",
+"ui/transmutability/arrays/issue-103783-array-length.rs",
+"ui/transmutability/issue-101739-1.rs",
+"ui/transmutability/issue-101739-2.rs",
+"ui/transmutability/issue-110467.rs",
+"ui/transmutability/issue-110892.rs",
+"ui/trivial-bounds/issue-73021-impossible-inline.rs",
+"ui/try-block/issue-45124.rs",
+"ui/type-alias-enum-variants/issue-57866.rs",
+"ui/type-alias-enum-variants/issue-61801-path-pattern-can-infer.rs",
+"ui/type-alias-enum-variants/issue-63151-dead-code-lint-fields-in-patterns.rs",
+"ui/type-alias-impl-trait/issue-52843-closure-constrain.rs",
+"ui/type-alias-impl-trait/issue-52843.rs",
+"ui/type-alias-impl-trait/issue-53092-2.rs",
+"ui/type-alias-impl-trait/issue-53092.rs",
+"ui/type-alias-impl-trait/issue-53096.rs",
+"ui/type-alias-impl-trait/issue-53598.rs",
+"ui/type-alias-impl-trait/issue-57700.rs",
+"ui/type-alias-impl-trait/issue-58887.rs",
+"ui/type-alias-impl-trait/issue-60371.rs",
+"ui/type-alias-impl-trait/issue-60407.rs",
+"ui/type-alias-impl-trait/issue-63279.rs",
+"ui/type-alias-impl-trait/issue-65384.rs",
+"ui/type-alias-impl-trait/issue-65918.rs",
+"ui/type-alias-impl-trait/issue-74244.rs",
+"ui/type-alias-impl-trait/issue-74280.rs",
+"ui/type-alias-impl-trait/issue-74761-2.rs",
+"ui/type-alias-impl-trait/issue-74761.rs",
+"ui/type-alias-impl-trait/issue-84660-unsoundness.rs",
+"ui/type-alias-impl-trait/issue-90400-1.rs",
+"ui/type-alias-impl-trait/issue-90400-2.rs",
+"ui/type-alias-impl-trait/issue-94429.rs",
+"ui/type-alias-impl-trait/issue-96572-unconstrained-mismatch.rs",
+"ui/type-alias-impl-trait/issue-98608.rs",
+"ui/type-alias-impl-trait/issue-101750.rs",
+"ui/type-alias-impl-trait/issue-104817.rs",
+"ui/type-alias-impl-trait/issue-53398-cyclic-types.rs",
+"ui/type-alias-impl-trait/issue-55099-lifetime-inference.rs",
+"ui/type-alias-impl-trait/issue-57188-associate-impl-capture.rs",
+"ui/type-alias-impl-trait/issue-57611-trait-alias.rs",
+"ui/type-alias-impl-trait/issue-57807-associated-type.rs",
+"ui/type-alias-impl-trait/issue-58662-generator-with-lifetime.rs",
+"ui/type-alias-impl-trait/issue-58662-simplified.rs",
+"ui/type-alias-impl-trait/issue-58951-2.rs",
+"ui/type-alias-impl-trait/issue-58951.rs",
+"ui/type-alias-impl-trait/issue-60564-working.rs",
+"ui/type-alias-impl-trait/issue-60662.rs",
+"ui/type-alias-impl-trait/issue-62000-associate-impl-trait-lifetimes.rs",
+"ui/type-alias-impl-trait/issue-63355.rs",
+"ui/type-alias-impl-trait/issue-63677-type-alias-coherence.rs",
+"ui/type-alias-impl-trait/issue-66580-closure-coherence.rs",
+"ui/type-alias-impl-trait/issue-67844-nested-opaque.rs",
+"ui/type-alias-impl-trait/issue-69136-inner-lifetime-resolve-ok.rs",
+"ui/type-alias-impl-trait/issue-69323.rs",
+"ui/type-alias-impl-trait/issue-72793.rs",
+"ui/type-alias-impl-trait/issue-76202-trait-impl-for-tait.rs",
+"ui/type-alias-impl-trait/issue-78450.rs",
+"ui/type-alias-impl-trait/issue-84660-trait-impl-for-tait.rs",
+"ui/type-alias-impl-trait/issue-87455-static-lifetime-ice.rs",
+"ui/type-alias-impl-trait/issue-89686.rs",
+"ui/type-alias-impl-trait/issue-89952.rs",
+"ui/type-alias-impl-trait/issue-93411.rs",
+"ui/type-alias-impl-trait/issue-96572-unconstrained.rs",
+"ui/type-alias-impl-trait/issue-98604.rs",
+"ui/type-alias-impl-trait/issue-109054.rs",
+"ui/type-alias-impl-trait/issue-53678-generator-and-const-fn.rs",
+"ui/type-alias-impl-trait/issue-57961.rs",
+"ui/type-alias-impl-trait/issue-60564.rs",
+"ui/type-alias-impl-trait/issue-63263-closure-return.rs",
+"ui/type-alias-impl-trait/issue-65679-inst-opaque-ty-from-val-twice.rs",
+"ui/type-alias-impl-trait/issue-68368-non-defining-use-2.rs",
+"ui/type-alias-impl-trait/issue-68368-non-defining-use.rs",
+"ui/type-alias-impl-trait/issue-69136-inner-lifetime-resolve-error.rs",
+"ui/type-alias-impl-trait/issue-70121.rs",
+"ui/type-alias-impl-trait/issue-77179.rs",
+"ui/type-alias/issue-62263-self-in-atb.rs",
+"ui/type-alias/issue-62305-self-assoc-ty.rs",
+"ui/type-alias/issue-62364-self-ty-arg.rs",
+"ui/type-alias/issue-14933.rs",
+"ui/type-alias/issue-37515.rs",
+"ui/type-inference/issue-30225.rs",
+"ui/type-inference/issue-113283-alllocator-trait-eq.rs",
+"ui/type/ascription/issue-34255-1.rs",
+"ui/type/ascription/issue-47666.rs",
+"ui/type/ascription/issue-54516.rs",
+"ui/type/ascription/issue-60933.rs",
+"ui/type/type-check/issue-22897.rs",
+"ui/type/type-check/issue-40294.rs",
+"ui/type/type-check/issue-41314.rs",
+"ui/type/type-check/issue-67273-assignment-match-prior-arm-bool-expected-unit.rs",
+"ui/type/type-check/issue-88577-check-fn-with-more-than-65535-arguments.rs",
+"ui/type/issue-100584.rs",
+"ui/type/issue-101866.rs",
+"ui/type/issue-102598.rs",
+"ui/type/issue-103271.rs",
+"ui/type/issue-58355.rs",
+"ui/type/issue-67690-type-alias-bound-diagnostic-crash.rs",
+"ui/type/issue-91268.rs",
+"ui/type/issue-94187-verbose-type-name.rs",
+"ui/typeck/auxiliary/issue-36708.rs",
+"ui/typeck/auxiliary/issue-81943-lib.rs",
+"ui/typeck/issue-100246.rs",
+"ui/typeck/issue-100285.rs",
+"ui/typeck/issue-103899.rs",
+"ui/typeck/issue-10401.rs",
+"ui/typeck/issue-104513-ice.rs",
+"ui/typeck/issue-104582.rs",
+"ui/typeck/issue-105946.rs",
+"ui/typeck/issue-107087.rs",
+"ui/typeck/issue-10969.rs",
+"ui/typeck/issue-110052.rs",
+"ui/typeck/issue-13853-2.rs",
+"ui/typeck/issue-13853-5.rs",
+"ui/typeck/issue-13853.rs",
+"ui/typeck/issue-18937-1.rs",
+"ui/typeck/issue-18937.rs",
+"ui/typeck/issue-29124.rs",
+"ui/typeck/issue-31173.rs",
+"ui/typeck/issue-33575.rs",
+"ui/typeck/issue-36708.rs",
+"ui/typeck/issue-43189.rs",
+"ui/typeck/issue-46112.rs",
+"ui/typeck/issue-50687-ice-on-borrow.rs",
+"ui/typeck/issue-52082-type-param-shadows-existing-type.rs",
+"ui/typeck/issue-53712.rs",
+"ui/typeck/issue-57404.rs",
+"ui/typeck/issue-57673-ice-on-deref-of-boxed-trait.rs",
+"ui/typeck/issue-65611.rs",
+"ui/typeck/issue-67971.rs",
+"ui/typeck/issue-69378-ice-on-invalid-type-node-after-recovery.rs",
+"ui/typeck/issue-74086.rs",
+"ui/typeck/issue-75883.rs",
+"ui/typeck/issue-75889.rs",
+"ui/typeck/issue-7813.rs",
+"ui/typeck/issue-79040.rs",
+"ui/typeck/issue-80779.rs",
+"ui/typeck/issue-81293.rs",
+"ui/typeck/issue-81885.rs",
+"ui/typeck/issue-81943.rs",
+"ui/typeck/issue-83621-placeholder-static-in-extern.rs",
+"ui/typeck/issue-83693.rs",
+"ui/typeck/issue-84160.rs",
+"ui/typeck/issue-84768.rs",
+"ui/typeck/issue-84831.rs",
+"ui/typeck/issue-87771-ice-assign-assign-to-bool.rs",
+"ui/typeck/issue-87872-missing-inaccessible-field-literal.rs",
+"ui/typeck/issue-87872-missing-inaccessible-field-pattern.rs",
+"ui/typeck/issue-88609.rs",
+"ui/typeck/issue-88643.rs",
+"ui/typeck/issue-88844.rs",
+"ui/typeck/issue-89275.rs",
+"ui/typeck/issue-89806.rs",
+"ui/typeck/issue-90101.rs",
+"ui/typeck/issue-90164.rs",
+"ui/typeck/issue-90319.rs",
+"ui/typeck/issue-90804-incorrect-reference-suggestion.rs",
+"ui/typeck/issue-91267.rs",
+"ui/typeck/issue-91450-inner-ty-error.rs",
+"ui/typeck/issue-92481.rs",
+"ui/typeck/issue-93486.rs",
+"ui/typeck/issue-96530.rs",
+"ui/typeck/issue-96738.rs",
+"ui/typeck/issue-98260.rs",
+"ui/typeck/issue-98982.rs",
+"ui/typeck/issue-106929.rs",
+"ui/typeck/issue-112385-while-assign-lhs-place-expr-ice.rs",
+"ui/typeck/issue-1871.rs",
+"ui/typeck/issue-2063.rs",
+"ui/typeck/issue-100164.rs",
+"ui/typeck/issue-104510-ice.rs",
+"ui/typeck/issue-107775.rs",
+"ui/typeck/issue-112252-ptr-arithmetics-help.rs",
+"ui/typeck/issue-2063-resource.rs",
+"ui/typeck/issue-22375.rs",
+"ui/typeck/issue-55810-must-typeck-match-pats-before-guards.rs",
+"ui/typeck/issue-61711-once-caused-rustc-inf-loop.rs",
+"ui/typeck/issue-68590-reborrow-through-derefmut.rs",
+"ui/typeck/issue-72225-call-fnmut-through-derefmut.rs",
+"ui/typeck/issue-73592-borrow_mut-through-deref.rs",
+"ui/typeck/issue-74933.rs",
+"ui/typeck/issue-80207-unsized-return.rs",
+"ui/typeck/issue-82772.rs",
+"ui/typeck/issue-88803-call-expr-method.rs",
+"ui/typeck/issue-89044-wrapped-expr-method.rs",
+"ui/typeck/issue-89856.rs",
+"ui/typeck/issue-89935.rs",
+"ui/typeck/issue-90027-async-fn-return-suggestion.rs",
+"ui/typeck/issue-90483-inaccessible-field-adjustment.rs",
+"ui/typeck/issue-91210-ptr-method.rs",
+"ui/typeck/issue-91328.rs",
+"ui/typeck/issue-91334.rs",
+"ui/typeck/issue-91633.rs",
+"ui/typeck/issue-86721-return-expr-ice.rs",
+"ui/typeof/issue-100183.rs",
+"ui/typeof/issue-29184.rs",
+"ui/typeof/issue-42060.rs",
+"ui/unboxed-closures/issue-18652.rs",
+"ui/unboxed-closures/issue-18661.rs",
+"ui/unboxed-closures/issue-30906.rs",
+"ui/unboxed-closures/issue-53448.rs",
+"ui/underscore-imports/issue-110164.rs",
+"ui/uniform-paths/auxiliary/issue-53691.rs",
+"ui/uniform-paths/issue-53691.rs",
+"ui/uninhabited/issue-107505.rs",
+"ui/union/issue-41073.rs",
+"ui/union/issue-81199.rs",
+"ui/union/issue-99375.rs",
+"ui/unsafe/auxiliary/issue-106126.rs",
+"ui/unsafe/issue-106126-good-path-bug.rs",
+"ui/unsafe/issue-3080.rs",
+"ui/unsafe/issue-45087-unreachable-unsafe.rs",
+"ui/unsafe/issue-45107-unnecessary-unsafe-in-closure.rs",
+"ui/unsafe/issue-47412.rs",
+"ui/unsafe/issue-85435-unsafe-op-in-let-under-unsafe-under-closure.rs",
+"ui/unsafe/issue-87414-query-cycle.rs",
+"ui/unsized-locals/issue-30276-feature-flagged.rs",
+"ui/unsized-locals/issue-30276.rs",
+"ui/unsized-locals/issue-50940-with-feature.rs",
+"ui/unsized-locals/issue-50940.rs",
+"ui/unsized-locals/issue-67981.rs",
+"ui/unsized/issue-30355.rs",
+"ui/unsized/issue-75707.rs",
+"ui/unsized/issue-91801.rs",
+"ui/unsized/issue-91803.rs",
+"ui/unsized/issue-40231-1.rs",
+"ui/unsized/issue-40231-2.rs",
+"ui/unsized/issue-71659.rs",
+"ui/unsized/issue-75899-but-gats.rs",
+"ui/unsized/issue-75899.rs",
+"ui/unsized/issue-97732.rs",
+"ui/use/issue-18986.rs",
+"ui/use/issue-60976-extern-use-primitive-type.rs",
+"ui/wf/issue-103573.rs",
+"ui/wf/issue-110157.rs",
+"ui/wf/issue-87495.rs",
+"ui/wf/issue-95665.rs",
+"ui/wf/issue-96810.rs",
+"ui/wf/issue-48638.rs",
+"ui/where-clauses/issue-50825-1.rs",
+"ui/where-clauses/issue-50825.rs",
+"ui/issues-71798.rs",
+"ui/issue-11881.rs",
+"ui/issue-13560.rs",
+"ui/issue-16822.rs",
+"ui/issue-18502.rs",
+"ui/issue-2804.rs",
+"ui/higher-ranked/trait-bounds/issue-30786.rs",
+"ui/higher-ranked/trait-bounds/issue-36139-normalize-closure-sig.rs",
+"ui/higher-ranked/trait-bounds/issue-39292.rs",
+"ui/higher-ranked/trait-bounds/issue-46989.rs",
+"ui/higher-ranked/trait-bounds/issue-58451.rs",
+"ui/higher-ranked/trait-bounds/issue-59311.rs",
+"ui/higher-ranked/trait-bounds/issue-62203-hrtb-ice.rs",
+"ui/higher-ranked/trait-bounds/normalize-under-binder/issue-62529-3.rs",
+"ui/higher-ranked/trait-bounds/normalize-under-binder/issue-71955.rs",
+"ui/higher-ranked/trait-bounds/normalize-under-binder/issue-85455.rs",
+"ui/higher-ranked/trait-bounds/normalize-under-binder/issue-89118.rs",
+"ui/higher-ranked/trait-bounds/normalize-under-binder/issue-90950.rs",
+"ui/higher-ranked/trait-bounds/normalize-under-binder/issue-44005.rs",
+"ui/higher-ranked/trait-bounds/normalize-under-binder/issue-56556.rs",
+"ui/higher-ranked/trait-bounds/normalize-under-binder/issue-62529-1.rs",
+"ui/higher-ranked/trait-bounds/normalize-under-binder/issue-62529-2.rs",
+"ui/higher-ranked/trait-bounds/normalize-under-binder/issue-62529-4.rs",
+"ui/higher-ranked/trait-bounds/normalize-under-binder/issue-62529-5.rs",
+"ui/higher-ranked/trait-bounds/normalize-under-binder/issue-62529-6.rs",
+"ui/higher-ranked/trait-bounds/normalize-under-binder/issue-70120.rs",
+"ui/higher-ranked/trait-bounds/normalize-under-binder/issue-74261.rs",
+"ui/higher-ranked/trait-bounds/normalize-under-binder/issue-76956.rs",
+"ui/higher-ranked/trait-bounds/normalize-under-binder/issue-80706.rs",
+"ui/higher-ranked/trait-bounds/normalize-under-binder/issue-80956.rs",
+"ui/higher-ranked/trait-bounds/normalize-under-binder/issue-81809.rs",
+"ui/higher-ranked/trait-bounds/normalize-under-binder/issue-89436.rs",
+"ui/higher-ranked/trait-bounds/normalize-under-binder/issue-90612.rs",
+"ui/higher-ranked/trait-bounds/normalize-under-binder/issue-90638.rs",
+"ui/higher-ranked/trait-bounds/normalize-under-binder/issue-90875.rs",
+"ui/higher-ranked/trait-bounds/issue-100689.rs",
+"ui/higher-ranked/trait-bounds/issue-102899.rs",
+"ui/higher-ranked/trait-bounds/issue-42114.rs",
+"ui/higher-ranked/trait-bounds/issue-43623.rs",
+"ui/higher-ranked/trait-bounds/issue-57639.rs",
+"ui/higher-ranked/trait-bounds/issue-60283.rs",
+"ui/higher-ranked/trait-bounds/issue-88446.rs",
+"ui/higher-ranked/trait-bounds/issue-88586-hr-self-outlives-in-trait-def.rs",
+"ui/higher-ranked/trait-bounds/issue-90177.rs",
+"ui/higher-ranked/trait-bounds/issue-95034.rs",
+"ui/higher-ranked/trait-bounds/issue-95230.rs",
+"ui/issue-76387-llvm-miscompile.rs",
+"ui/issue-15924.rs",
+"ui/issue-24106.rs",
+"ui-fulldeps/plugin/auxiliary/issue-40001-plugin.rs",
+"ui-fulldeps/plugin/issue-40001.rs",
+"ui-fulldeps/plugin/issue-15778-fail.rs",
+]
\ No newline at end of file
diff --git a/src/tools/tidy/src/ui_tests.rs b/src/tools/tidy/src/ui_tests.rs
index c3a639528413..f9a90bf3a005 100644
--- a/src/tools/tidy/src/ui_tests.rs
+++ b/src/tools/tidy/src/ui_tests.rs
@@ -3,14 +3,16 @@
 //! - there are no stray `.stderr` files
 
 use ignore::Walk;
-use std::collections::HashMap;
+use lazy_static::lazy_static;
+use regex::Regex;
+use std::collections::{HashMap, HashSet};
 use std::ffi::OsStr;
 use std::fs;
 use std::path::{Path, PathBuf};
 
 const ENTRY_LIMIT: usize = 900;
 // FIXME: The following limits should be reduced eventually.
-const ISSUES_ENTRY_LIMIT: usize = 1894;
+const ISSUES_ENTRY_LIMIT: usize = 1893;
 const ROOT_ENTRY_LIMIT: usize = 870;
 
 const EXPECTED_TEST_FILE_EXTENSIONS: &[&str] = &[
@@ -88,6 +90,12 @@ fn check_entries(tests_path: &Path, bad: &mut bool) {
 
 pub fn check(path: &Path, bad: &mut bool) {
     check_entries(&path, bad);
+
+    // the list of files in ui tests that are allowed to start with `issue-XXXX`
+    let mut allowed_issue_filenames: HashSet = HashSet::from(
+        include!("issues.txt").map(|path| path.replace("/", std::path::MAIN_SEPARATOR_STR)),
+    );
+
     let (ui, ui_fulldeps) = (path.join("ui"), path.join("ui-fulldeps"));
     let paths = [ui.as_path(), ui_fulldeps.as_path()];
     crate::walk::walk_no_read(&paths, |_, _| false, &mut |entry| {
@@ -100,6 +108,11 @@ pub fn check(path: &Path, bad: &mut bool) {
             {
                 tidy_error!(bad, "file {} has unexpected extension {}", file_path.display(), ext);
             }
+
+            // NB: We do not use file_stem() as some file names have multiple `.`s and we
+            // must strip all of them.
+            let testname =
+                file_path.file_name().unwrap().to_str().unwrap().split_once('.').unwrap().0;
             if ext == "stderr" || ext == "stdout" {
                 // Test output filenames have one of the formats:
                 // ```
@@ -111,12 +124,10 @@ pub fn check(path: &Path, bad: &mut bool) {
                 //
                 // For now, just make sure that there is a corresponding
                 // `$testname.rs` file.
-                //
-                // NB: We do not use file_stem() as some file names have multiple `.`s and we
-                // must strip all of them.
-                let testname =
-                    file_path.file_name().unwrap().to_str().unwrap().split_once('.').unwrap().0;
-                if !file_path.with_file_name(testname).with_extension("rs").exists() {
+
+                if !file_path.with_file_name(testname).with_extension("rs").exists()
+                    && !testname.contains("ignore-tidy")
+                {
                     tidy_error!(bad, "Stray file with UI testing output: {:?}", file_path);
                 }
 
@@ -126,6 +137,38 @@ pub fn check(path: &Path, bad: &mut bool) {
                     }
                 }
             }
+
+            if ext == "rs" {
+                lazy_static! {
+                    static ref ISSUE_NAME_REGEX: Regex =
+                        Regex::new(r"^issues?[-_]?\d{3,}").unwrap();
+                }
+
+                if ISSUE_NAME_REGEX.is_match(testname) {
+                    // these paths are always relative to the passed `path` and always UTF8
+                    let stripped_path = file_path.strip_prefix(path).unwrap().to_str().unwrap();
+                    if !allowed_issue_filenames.remove(stripped_path) {
+                        tidy_error!(
+                            bad,
+                            "UI test `{}` should use a name that describes the test and link the issue in a comment instead.",
+                            file_path.display(),
+                        );
+                    }
+                }
+            }
         }
     });
+
+    // if an excluded file is renamed, it must be removed from this list
+    if allowed_issue_filenames.len() > 0 {
+        for file_name in allowed_issue_filenames {
+            let mut p = PathBuf::from(path);
+            p.push(file_name);
+            tidy_error!(
+                bad,
+                "file `{}` no longer exists and should be removed from the exclusions in `src/tools/tidy/src/issues.txt`",
+                p.display()
+            );
+        }
+    }
 }
diff --git a/tests/mir-opt/const_allocation.main.ConstProp.after.32bit.mir b/tests/mir-opt/const_allocation.main.ConstProp.after.32bit.mir
index 3797dbabb3c1..8c8e69595950 100644
--- a/tests/mir-opt/const_allocation.main.ConstProp.after.32bit.mir
+++ b/tests/mir-opt/const_allocation.main.ConstProp.after.32bit.mir
@@ -23,17 +23,17 @@ alloc1 (static: FOO, size: 8, align: 4) {
 
 alloc19 (size: 48, align: 4) {
     0x00 │ 00 00 00 00 __ __ __ __ ╾─alloc6──╼ 00 00 00 00 │ ....░░░░╾──╼....
-    0x10 │ 00 00 00 00 __ __ __ __ ╾─alloc9──╼ 02 00 00 00 │ ....░░░░╾──╼....
-    0x20 │ 01 00 00 00 2a 00 00 00 ╾─alloc14─╼ 03 00 00 00 │ ....*...╾──╼....
+    0x10 │ 00 00 00 00 __ __ __ __ ╾─alloc10─╼ 02 00 00 00 │ ....░░░░╾──╼....
+    0x20 │ 01 00 00 00 2a 00 00 00 ╾─alloc15─╼ 03 00 00 00 │ ....*...╾──╼....
 }
 
 alloc6 (size: 0, align: 4) {}
 
-alloc9 (size: 16, align: 4) {
-    ╾─alloc10─╼ 03 00 00 00 ╾─alloc11─╼ 03 00 00 00 │ ╾──╼....╾──╼....
+alloc10 (size: 16, align: 4) {
+    ╾─alloc9──╼ 03 00 00 00 ╾─alloc11─╼ 03 00 00 00 │ ╾──╼....╾──╼....
 }
 
-alloc10 (size: 3, align: 1) {
+alloc9 (size: 3, align: 1) {
     66 6f 6f                                        │ foo
 }
 
@@ -41,12 +41,12 @@ alloc11 (size: 3, align: 1) {
     62 61 72                                        │ bar
 }
 
-alloc14 (size: 24, align: 4) {
-    0x00 │ ╾─alloc15─╼ 03 00 00 00 ╾─alloc16─╼ 03 00 00 00 │ ╾──╼....╾──╼....
+alloc15 (size: 24, align: 4) {
+    0x00 │ ╾─alloc14─╼ 03 00 00 00 ╾─alloc16─╼ 03 00 00 00 │ ╾──╼....╾──╼....
     0x10 │ ╾─alloc17─╼ 04 00 00 00                         │ ╾──╼....
 }
 
-alloc15 (size: 3, align: 1) {
+alloc14 (size: 3, align: 1) {
     6d 65 68                                        │ meh
 }
 
diff --git a/tests/mir-opt/const_allocation.main.ConstProp.after.64bit.mir b/tests/mir-opt/const_allocation.main.ConstProp.after.64bit.mir
index dc16c064009d..e22547032967 100644
--- a/tests/mir-opt/const_allocation.main.ConstProp.after.64bit.mir
+++ b/tests/mir-opt/const_allocation.main.ConstProp.after.64bit.mir
@@ -24,19 +24,19 @@ alloc1 (static: FOO, size: 16, align: 8) {
 alloc19 (size: 72, align: 8) {
     0x00 │ 00 00 00 00 __ __ __ __ ╾───────alloc6────────╼ │ ....░░░░╾──────╼
     0x10 │ 00 00 00 00 00 00 00 00 00 00 00 00 __ __ __ __ │ ............░░░░
-    0x20 │ ╾───────alloc9────────╼ 02 00 00 00 00 00 00 00 │ ╾──────╼........
-    0x30 │ 01 00 00 00 2a 00 00 00 ╾───────alloc14───────╼ │ ....*...╾──────╼
+    0x20 │ ╾───────alloc10───────╼ 02 00 00 00 00 00 00 00 │ ╾──────╼........
+    0x30 │ 01 00 00 00 2a 00 00 00 ╾───────alloc15───────╼ │ ....*...╾──────╼
     0x40 │ 03 00 00 00 00 00 00 00                         │ ........
 }
 
 alloc6 (size: 0, align: 8) {}
 
-alloc9 (size: 32, align: 8) {
-    0x00 │ ╾───────alloc10───────╼ 03 00 00 00 00 00 00 00 │ ╾──────╼........
+alloc10 (size: 32, align: 8) {
+    0x00 │ ╾───────alloc9────────╼ 03 00 00 00 00 00 00 00 │ ╾──────╼........
     0x10 │ ╾───────alloc11───────╼ 03 00 00 00 00 00 00 00 │ ╾──────╼........
 }
 
-alloc10 (size: 3, align: 1) {
+alloc9 (size: 3, align: 1) {
     66 6f 6f                                        │ foo
 }
 
@@ -44,13 +44,13 @@ alloc11 (size: 3, align: 1) {
     62 61 72                                        │ bar
 }
 
-alloc14 (size: 48, align: 8) {
-    0x00 │ ╾───────alloc15───────╼ 03 00 00 00 00 00 00 00 │ ╾──────╼........
+alloc15 (size: 48, align: 8) {
+    0x00 │ ╾───────alloc14───────╼ 03 00 00 00 00 00 00 00 │ ╾──────╼........
     0x10 │ ╾───────alloc16───────╼ 03 00 00 00 00 00 00 00 │ ╾──────╼........
     0x20 │ ╾───────alloc17───────╼ 04 00 00 00 00 00 00 00 │ ╾──────╼........
 }
 
-alloc15 (size: 3, align: 1) {
+alloc14 (size: 3, align: 1) {
     6d 65 68                                        │ meh
 }
 
diff --git a/tests/mir-opt/pre-codegen/mem_replace.mem_replace.PreCodegen.after.mir b/tests/mir-opt/pre-codegen/mem_replace.mem_replace.PreCodegen.after.mir
index eeb2e3a1b03f..26919dd98dd2 100644
--- a/tests/mir-opt/pre-codegen/mem_replace.mem_replace.PreCodegen.after.mir
+++ b/tests/mir-opt/pre-codegen/mem_replace.mem_replace.PreCodegen.after.mir
@@ -10,22 +10,16 @@ fn mem_replace(_1: &mut u32, _2: u32) -> u32 {
         scope 2 {
             scope 3 {
                 debug result => _0;
-                scope 7 (inlined std::ptr::write::) {
+                scope 6 (inlined std::ptr::write::) {
                     debug dst => _1;
                     debug src => _2;
-                    scope 8 {
-                        scope 9 (inlined std::ptr::write::runtime::) {
-                            debug dst => _1;
-                        }
+                    scope 7 {
                     }
                 }
             }
             scope 4 (inlined std::ptr::read::) {
                 debug src => _1;
                 scope 5 {
-                    scope 6 (inlined std::ptr::read::runtime::) {
-                        debug src => _1;
-                    }
                 }
             }
         }
diff --git a/tests/rustdoc-gui/label-next-to-symbol.goml b/tests/rustdoc-gui/label-next-to-symbol.goml
index eb603d6c6b6a..d23f9114d361 100644
--- a/tests/rustdoc-gui/label-next-to-symbol.goml
+++ b/tests/rustdoc-gui/label-next-to-symbol.goml
@@ -10,11 +10,11 @@ assert: (".stab.portability")
 // make sure that deprecated and portability have the right colors
 assert-css: (
     ".item-table .item-name .stab.deprecated",
-    { "background-color": "rgb(255, 245, 214)" },
+    { "background-color": "#fff5d6" },
 )
 assert-css: (
     ".item-table .item-name .stab.portability",
-    { "background-color": "rgb(255, 245, 214)" },
+    { "background-color": "#fff5d6" },
 )
 
 // table like view
diff --git a/tests/rustdoc-ui/intra-doc/broken-link-in-unused-doc-string.rs b/tests/rustdoc-ui/intra-doc/broken-link-in-unused-doc-string.rs
new file mode 100644
index 000000000000..f3f044f61058
--- /dev/null
+++ b/tests/rustdoc-ui/intra-doc/broken-link-in-unused-doc-string.rs
@@ -0,0 +1,16 @@
+// Test that we don't ICE with broken links that don't show up in the docs.
+
+// check-pass
+// edition: 2021
+
+/// [1]
+//~^ WARN unresolved link to `1`
+//~| WARN unresolved link to `1`
+pub use {std, core};
+
+/// [2]
+pub use {};
+
+/// [3]
+//~^ WARN unresolved link to `3`
+pub extern crate alloc;
diff --git a/tests/rustdoc-ui/intra-doc/broken-link-in-unused-doc-string.stderr b/tests/rustdoc-ui/intra-doc/broken-link-in-unused-doc-string.stderr
new file mode 100644
index 000000000000..83e0d3962ca1
--- /dev/null
+++ b/tests/rustdoc-ui/intra-doc/broken-link-in-unused-doc-string.stderr
@@ -0,0 +1,27 @@
+warning: unresolved link to `3`
+  --> $DIR/broken-link-in-unused-doc-string.rs:14:6
+   |
+LL | /// [3]
+   |      ^ no item named `3` in scope
+   |
+   = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
+   = note: `#[warn(rustdoc::broken_intra_doc_links)]` on by default
+
+warning: unresolved link to `1`
+  --> $DIR/broken-link-in-unused-doc-string.rs:6:6
+   |
+LL | /// [1]
+   |      ^ no item named `1` in scope
+   |
+   = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
+
+warning: unresolved link to `1`
+  --> $DIR/broken-link-in-unused-doc-string.rs:6:6
+   |
+LL | /// [1]
+   |      ^ no item named `1` in scope
+   |
+   = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
+
+warning: 3 warnings emitted
+
diff --git a/tests/rustdoc-ui/lints/invalid-doc-attr.rs b/tests/rustdoc-ui/lints/invalid-doc-attr.rs
index c231e43b35ca..16b12cca5a0b 100644
--- a/tests/rustdoc-ui/lints/invalid-doc-attr.rs
+++ b/tests/rustdoc-ui/lints/invalid-doc-attr.rs
@@ -1,5 +1,10 @@
 #![crate_type = "lib"]
 #![deny(warnings)]
+#![feature(doc_masked)]
+
+#![doc(masked)]
+//~^ ERROR this attribute can only be applied to an `extern crate` item
+//~| WARN is being phased out
 
 #[doc(test(no_crate_inject))]
 //~^ ERROR can only be applied at the crate level
@@ -30,3 +35,13 @@ pub mod bar {
 //~^^ ERROR conflicting doc inlining attributes
 //~|  HELP remove one of the conflicting attributes
 pub use bar::baz;
+
+#[doc(masked)]
+//~^ ERROR this attribute can only be applied to an `extern crate` item
+//~| WARN is being phased out
+pub struct Masked;
+
+#[doc(masked)]
+//~^ ERROR this attribute cannot be applied to an `extern crate self` item
+//~| WARN is being phased out
+pub extern crate self as reexport;
diff --git a/tests/rustdoc-ui/lints/invalid-doc-attr.stderr b/tests/rustdoc-ui/lints/invalid-doc-attr.stderr
index b23b8ded8674..82ea33e1d895 100644
--- a/tests/rustdoc-ui/lints/invalid-doc-attr.stderr
+++ b/tests/rustdoc-ui/lints/invalid-doc-attr.stderr
@@ -1,5 +1,5 @@
 error: this attribute can only be applied at the crate level
-  --> $DIR/invalid-doc-attr.rs:4:7
+  --> $DIR/invalid-doc-attr.rs:9:7
    |
 LL | #[doc(test(no_crate_inject))]
    |       ^^^^^^^^^^^^^^^^^^^^^
@@ -19,7 +19,7 @@ LL | #![doc(test(no_crate_inject))]
    |  +
 
 error: this attribute can only be applied to a `use` item
-  --> $DIR/invalid-doc-attr.rs:9:7
+  --> $DIR/invalid-doc-attr.rs:14:7
    |
 LL | #[doc(inline)]
    |       ^^^^^^ only applicable on `use` items
@@ -32,7 +32,7 @@ LL | pub fn foo() {}
    = note: read  for more information
 
 error: this attribute can only be applied at the crate level
-  --> $DIR/invalid-doc-attr.rs:15:12
+  --> $DIR/invalid-doc-attr.rs:20:12
    |
 LL |     #![doc(test(no_crate_inject))]
    |            ^^^^^^^^^^^^^^^^^^^^^
@@ -42,7 +42,7 @@ LL |     #![doc(test(no_crate_inject))]
    = note: read  for more information
 
 error: conflicting doc inlining attributes
-  --> $DIR/invalid-doc-attr.rs:28:7
+  --> $DIR/invalid-doc-attr.rs:33:7
    |
 LL | #[doc(inline)]
    |       ^^^^^^ this attribute...
@@ -51,8 +51,43 @@ LL | #[doc(no_inline)]
    |
    = help: remove one of the conflicting attributes
 
+error: this attribute can only be applied to an `extern crate` item
+  --> $DIR/invalid-doc-attr.rs:39:7
+   |
+LL | #[doc(masked)]
+   |       ^^^^^^ only applicable on `extern crate` items
+...
+LL | pub struct Masked;
+   | ----------------- not an `extern crate` item
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #82730 
+   = note: read  for more information
+
+error: this attribute cannot be applied to an `extern crate self` item
+  --> $DIR/invalid-doc-attr.rs:44:7
+   |
+LL | #[doc(masked)]
+   |       ^^^^^^ not applicable on `extern crate self` items
+...
+LL | pub extern crate self as reexport;
+   | --------------------------------- `extern crate self` defined here
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #82730 
+
+error: this attribute can only be applied to an `extern crate` item
+  --> $DIR/invalid-doc-attr.rs:5:8
+   |
+LL | #![doc(masked)]
+   |        ^^^^^^ only applicable on `extern crate` items
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #82730 
+   = note: read  for more information
+
 error: this attribute can only be applied at the crate level
-  --> $DIR/invalid-doc-attr.rs:19:11
+  --> $DIR/invalid-doc-attr.rs:24:11
    |
 LL |     #[doc(test(no_crate_inject))]
    |           ^^^^^^^^^^^^^^^^^^^^^
@@ -62,7 +97,7 @@ LL |     #[doc(test(no_crate_inject))]
    = note: read  for more information
 
 error: this attribute can only be applied to a `use` item
-  --> $DIR/invalid-doc-attr.rs:22:11
+  --> $DIR/invalid-doc-attr.rs:27:11
    |
 LL |     #[doc(inline)]
    |           ^^^^^^ only applicable on `use` items
@@ -74,5 +109,5 @@ LL |     pub fn baz() {}
    = note: for more information, see issue #82730 
    = note: read  for more information
 
-error: aborting due to 6 previous errors
+error: aborting due to 9 previous errors
 
diff --git a/tests/rustdoc/inline_cross/auxiliary/ret-pos-impl-trait-in-trait.rs b/tests/rustdoc/inline_cross/auxiliary/ret-pos-impl-trait-in-trait.rs
new file mode 100644
index 000000000000..c72f011152d8
--- /dev/null
+++ b/tests/rustdoc/inline_cross/auxiliary/ret-pos-impl-trait-in-trait.rs
@@ -0,0 +1,35 @@
+#![feature(return_position_impl_trait_in_trait)]
+
+pub trait Trait {
+    fn create() -> impl Iterator {
+        std::iter::empty()
+    }
+}
+
+pub struct Basic;
+pub struct Intermediate;
+pub struct Advanced;
+
+impl Trait for Basic {
+    // method provided by the trait
+}
+
+impl Trait for Intermediate {
+    fn create() -> std::ops::Range { // concrete return type
+        0..1
+    }
+}
+
+impl Trait for Advanced {
+    fn create() -> impl Iterator { // opaque return type
+        std::iter::repeat(0)
+    }
+}
+
+// Regression test for issue #113929:
+
+pub trait Def {
+    fn def() -> impl Default {}
+}
+
+impl Def for () {}
diff --git a/tests/rustdoc/inline_cross/ret-pos-impl-trait-in-trait.rs b/tests/rustdoc/inline_cross/ret-pos-impl-trait-in-trait.rs
new file mode 100644
index 000000000000..8e9ef9020153
--- /dev/null
+++ b/tests/rustdoc/inline_cross/ret-pos-impl-trait-in-trait.rs
@@ -0,0 +1,35 @@
+#![crate_name = "user"]
+// aux-crate:rpitit=ret-pos-impl-trait-in-trait.rs
+// edition:2021
+
+// Test that we can correctly render cross-crate RPITITs.
+// In particular, check that we don't render the internal associated type generated by
+// their desugaring. We count the number of associated items and ensure that it is exactly one.
+// This is more robust than checking for the absence of the associated type.
+
+// @has user/trait.Trait.html
+// @has - '//*[@id="method.create"]' 'fn create() -> impl Iterator'
+// The class "method" is used for all three kinds of associated items at the time of writing.
+// @count - '//*[@id="main-content"]//section[@class="method"]' 1
+pub use rpitit::Trait;
+
+// @has user/struct.Basic.html
+// @has - '//*[@id="method.create"]' 'fn create() -> impl Iterator'
+// @count - '//*[@id="trait-implementations-list"]//*[@class="impl-items"]' 1
+pub use rpitit::Basic;
+
+// @has user/struct.Intermediate.html
+// @has - '//*[@id="method.create"]' 'fn create() -> Range'
+// @count - '//*[@id="trait-implementations-list"]//*[@class="impl-items"]' 1
+pub use rpitit::Intermediate;
+
+// @has user/struct.Advanced.html
+// @has - '//*[@id="method.create"]' 'fn create() -> impl Iterator'
+// @count - '//*[@id="trait-implementations-list"]//*[@class="impl-items"]' 1
+pub use rpitit::Advanced;
+
+// Regression test for issue #113929:
+
+// @has user/trait.Def.html
+// @has - '//*[@id="method.def"]' 'fn def() -> impl Default'
+pub use rpitit::Def;
diff --git a/tests/rustdoc/intra-doc/nested-use.rs b/tests/rustdoc/intra-doc/nested-use.rs
new file mode 100644
index 000000000000..19ebfff1bce0
--- /dev/null
+++ b/tests/rustdoc/intra-doc/nested-use.rs
@@ -0,0 +1,16 @@
+// Regression test for issue #113896: Intra-doc links on nested use items.
+
+#![crate_name = "foo"]
+
+// @has foo/struct.Foo.html
+// @has - '//a[@href="struct.Foo.html"]' 'Foo'
+// @has - '//a[@href="struct.Bar.html"]' 'Bar'
+
+/// [`Foo`]
+pub use m::{Foo, Bar};
+
+mod m {
+    /// [`Bar`]
+    pub struct Foo;
+    pub struct Bar;
+}
diff --git a/tests/rustdoc/issue-33178.rs b/tests/rustdoc/issue-33178.rs
index 1f45fe723918..ed643f5ae118 100644
--- a/tests/rustdoc/issue-33178.rs
+++ b/tests/rustdoc/issue-33178.rs
@@ -4,10 +4,11 @@
 // ignore-cross-compile
 
 // @has issue_33178/index.html
-// @has - //a/@title empty
-// @has - //a/@href ../empty/index.html
+// @has - '//a[@title="mod empty"][@href="../empty/index.html"]' empty
 pub extern crate empty;
 
-// @has - //a/@title variant_struct
-// @has - //a/@href ../variant_struct/index.html
+// @has - '//a[@title="mod variant_struct"][@href="../variant_struct/index.html"]' variant_struct
 pub extern crate variant_struct as foo;
+
+// @has - '//a[@title="mod issue_33178"][@href="index.html"]' self
+pub extern crate self as bar;
diff --git a/tests/ui/associated-types/dont-suggest-cyclic-constraint.fixed b/tests/ui/associated-types/dont-suggest-cyclic-constraint.fixed
new file mode 100644
index 000000000000..ec4165cc71e2
--- /dev/null
+++ b/tests/ui/associated-types/dont-suggest-cyclic-constraint.fixed
@@ -0,0 +1,13 @@
+// run-rustfix
+
+use std::fmt::Debug;
+
+pub fn foo(mut iter: I, value: &I::Item)
+where
+    I::Item: Eq + Debug,
+{
+    debug_assert_eq!(iter.next().as_ref(), Some(value));
+    //~^ ERROR mismatched types
+}
+
+fn main() {}
diff --git a/tests/ui/associated-types/dont-suggest-cyclic-constraint.rs b/tests/ui/associated-types/dont-suggest-cyclic-constraint.rs
index 6894f6b6cc4a..0b4df08783d6 100644
--- a/tests/ui/associated-types/dont-suggest-cyclic-constraint.rs
+++ b/tests/ui/associated-types/dont-suggest-cyclic-constraint.rs
@@ -1,6 +1,8 @@
+// run-rustfix
+
 use std::fmt::Debug;
 
-fn foo(mut iter: I, value: &I::Item)
+pub fn foo(mut iter: I, value: &I::Item)
 where
     I::Item: Eq + Debug,
 {
diff --git a/tests/ui/associated-types/dont-suggest-cyclic-constraint.stderr b/tests/ui/associated-types/dont-suggest-cyclic-constraint.stderr
index 3ecac9c83e57..c06c506a311a 100644
--- a/tests/ui/associated-types/dont-suggest-cyclic-constraint.stderr
+++ b/tests/ui/associated-types/dont-suggest-cyclic-constraint.stderr
@@ -1,11 +1,15 @@
 error[E0308]: mismatched types
-  --> $DIR/dont-suggest-cyclic-constraint.rs:7:35
+  --> $DIR/dont-suggest-cyclic-constraint.rs:9:35
    |
 LL |     debug_assert_eq!(iter.next(), Some(value));
    |                                   ^^^^^^^^^^^ expected `Option<::Item>`, found `Option<&::Item>`
    |
    = note: expected enum `Option<::Item>`
               found enum `Option<&::Item>`
+help: use `Option::as_ref()` to convert `Option<::Item>` to `Option<&::Item>`
+   |
+LL |     debug_assert_eq!(iter.next().as_ref(), Some(value));
+   |                                 +++++++++
 
 error: aborting due to previous error
 
diff --git a/tests/ui/attributes/invalid-doc-attr.rs b/tests/ui/attributes/invalid-doc-attr.rs
deleted file mode 100644
index c231e43b35ca..000000000000
--- a/tests/ui/attributes/invalid-doc-attr.rs
+++ /dev/null
@@ -1,32 +0,0 @@
-#![crate_type = "lib"]
-#![deny(warnings)]
-
-#[doc(test(no_crate_inject))]
-//~^ ERROR can only be applied at the crate level
-//~| WARN is being phased out
-//~| HELP to apply to the crate, use an inner attribute
-//~| SUGGESTION !
-#[doc(inline)]
-//~^ ERROR can only be applied to a `use` item
-//~| WARN is being phased out
-pub fn foo() {}
-
-pub mod bar {
-    #![doc(test(no_crate_inject))]
-    //~^ ERROR can only be applied at the crate level
-    //~| WARN is being phased out
-
-    #[doc(test(no_crate_inject))]
-    //~^ ERROR can only be applied at the crate level
-    //~| WARN is being phased out
-    #[doc(inline)]
-    //~^ ERROR can only be applied to a `use` item
-    //~| WARN is being phased out
-    pub fn baz() {}
-}
-
-#[doc(inline)]
-#[doc(no_inline)]
-//~^^ ERROR conflicting doc inlining attributes
-//~|  HELP remove one of the conflicting attributes
-pub use bar::baz;
diff --git a/tests/ui/attributes/invalid-doc-attr.stderr b/tests/ui/attributes/invalid-doc-attr.stderr
deleted file mode 100644
index b23b8ded8674..000000000000
--- a/tests/ui/attributes/invalid-doc-attr.stderr
+++ /dev/null
@@ -1,78 +0,0 @@
-error: this attribute can only be applied at the crate level
-  --> $DIR/invalid-doc-attr.rs:4:7
-   |
-LL | #[doc(test(no_crate_inject))]
-   |       ^^^^^^^^^^^^^^^^^^^^^
-   |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #82730 
-   = note: read  for more information
-note: the lint level is defined here
-  --> $DIR/invalid-doc-attr.rs:2:9
-   |
-LL | #![deny(warnings)]
-   |         ^^^^^^^^
-   = note: `#[deny(invalid_doc_attributes)]` implied by `#[deny(warnings)]`
-help: to apply to the crate, use an inner attribute
-   |
-LL | #![doc(test(no_crate_inject))]
-   |  +
-
-error: this attribute can only be applied to a `use` item
-  --> $DIR/invalid-doc-attr.rs:9:7
-   |
-LL | #[doc(inline)]
-   |       ^^^^^^ only applicable on `use` items
-...
-LL | pub fn foo() {}
-   | ------------ not a `use` item
-   |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #82730 
-   = note: read  for more information
-
-error: this attribute can only be applied at the crate level
-  --> $DIR/invalid-doc-attr.rs:15:12
-   |
-LL |     #![doc(test(no_crate_inject))]
-   |            ^^^^^^^^^^^^^^^^^^^^^
-   |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #82730 
-   = note: read  for more information
-
-error: conflicting doc inlining attributes
-  --> $DIR/invalid-doc-attr.rs:28:7
-   |
-LL | #[doc(inline)]
-   |       ^^^^^^ this attribute...
-LL | #[doc(no_inline)]
-   |       ^^^^^^^^^ ...conflicts with this attribute
-   |
-   = help: remove one of the conflicting attributes
-
-error: this attribute can only be applied at the crate level
-  --> $DIR/invalid-doc-attr.rs:19:11
-   |
-LL |     #[doc(test(no_crate_inject))]
-   |           ^^^^^^^^^^^^^^^^^^^^^
-   |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #82730 
-   = note: read  for more information
-
-error: this attribute can only be applied to a `use` item
-  --> $DIR/invalid-doc-attr.rs:22:11
-   |
-LL |     #[doc(inline)]
-   |           ^^^^^^ only applicable on `use` items
-...
-LL |     pub fn baz() {}
-   |     ------------ not a `use` item
-   |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #82730 
-   = note: read  for more information
-
-error: aborting due to 6 previous errors
-
diff --git a/tests/ui/command/need-crate-arg-ignore-tidy.x.rs b/tests/ui/command/need-crate-arg-ignore-tidy.x.rs
new file mode 100644
index 000000000000..b1ac4a4ae216
--- /dev/null
+++ b/tests/ui/command/need-crate-arg-ignore-tidy.x.rs
@@ -0,0 +1,2 @@
+// issue: 113981
+pub fn main() {}
diff --git a/tests/ui/command/need-crate-arg-ignore-tidy.x.stderr b/tests/ui/command/need-crate-arg-ignore-tidy.x.stderr
new file mode 100644
index 000000000000..305f76694f71
--- /dev/null
+++ b/tests/ui/command/need-crate-arg-ignore-tidy.x.stderr
@@ -0,0 +1,6 @@
+error: invalid character `'.'` in crate name: `need_crate_arg_ignore_tidy.x`
+   |
+   = help: you can either pass `--crate-name` on the command line or add `#![crate_name="…"]` to set the crate name
+
+error: aborting due to previous error
+
diff --git a/tests/ui/consts/const-eval/raw-bytes.32bit.stderr b/tests/ui/consts/const-eval/raw-bytes.32bit.stderr
index c0ddaceea4ce..8a5424b3a6c6 100644
--- a/tests/ui/consts/const-eval/raw-bytes.32bit.stderr
+++ b/tests/ui/consts/const-eval/raw-bytes.32bit.stderr
@@ -24,7 +24,7 @@ error[E0080]: it is undefined behavior to use this value
   --> $DIR/raw-bytes.rs:42:1
    |
 LL | const BAD_UNINHABITED_VARIANT1: UninhDiscriminant = unsafe { mem::transmute(1u8) };
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at ..0: encountered a value of the never type `!`
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .: encountered an uninhabited enum variant
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 1, align: 1) {
@@ -35,7 +35,7 @@ error[E0080]: it is undefined behavior to use this value
   --> $DIR/raw-bytes.rs:44:1
    |
 LL | const BAD_UNINHABITED_VARIANT2: UninhDiscriminant = unsafe { mem::transmute(3u8) };
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at ..0: encountered a value of uninhabited type `Never`
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .: encountered an uninhabited enum variant
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 1, align: 1) {
diff --git a/tests/ui/consts/const-eval/raw-bytes.64bit.stderr b/tests/ui/consts/const-eval/raw-bytes.64bit.stderr
index 20c905878e07..08b98b37bd81 100644
--- a/tests/ui/consts/const-eval/raw-bytes.64bit.stderr
+++ b/tests/ui/consts/const-eval/raw-bytes.64bit.stderr
@@ -24,7 +24,7 @@ error[E0080]: it is undefined behavior to use this value
   --> $DIR/raw-bytes.rs:42:1
    |
 LL | const BAD_UNINHABITED_VARIANT1: UninhDiscriminant = unsafe { mem::transmute(1u8) };
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at ..0: encountered a value of the never type `!`
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .: encountered an uninhabited enum variant
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 1, align: 1) {
@@ -35,7 +35,7 @@ error[E0080]: it is undefined behavior to use this value
   --> $DIR/raw-bytes.rs:44:1
    |
 LL | const BAD_UNINHABITED_VARIANT2: UninhDiscriminant = unsafe { mem::transmute(3u8) };
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at ..0: encountered a value of uninhabited type `Never`
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .: encountered an uninhabited enum variant
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 1, align: 1) {
diff --git a/tests/ui/consts/const-eval/ub-enum.32bit.stderr b/tests/ui/consts/const-eval/ub-enum.32bit.stderr
index 1810600b7851..5ef0d0146f2f 100644
--- a/tests/ui/consts/const-eval/ub-enum.32bit.stderr
+++ b/tests/ui/consts/const-eval/ub-enum.32bit.stderr
@@ -75,7 +75,7 @@ error[E0080]: it is undefined behavior to use this value
   --> $DIR/ub-enum.rs:81:1
    |
 LL | const BAD_UNINHABITED_VARIANT1: UninhDiscriminant = unsafe { mem::transmute(1u8) };
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at ..0: encountered a value of the never type `!`
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .: encountered an uninhabited enum variant
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: $SIZE, align: $ALIGN) {
@@ -86,7 +86,7 @@ error[E0080]: it is undefined behavior to use this value
   --> $DIR/ub-enum.rs:83:1
    |
 LL | const BAD_UNINHABITED_VARIANT2: UninhDiscriminant = unsafe { mem::transmute(3u8) };
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at ..0: encountered a value of uninhabited type `Never`
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .: encountered an uninhabited enum variant
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: $SIZE, align: $ALIGN) {
@@ -108,14 +108,27 @@ error[E0080]: evaluation of constant value failed
   --> $DIR/ub-enum.rs:96:77
    |
 LL | const BAD_UNINHABITED_WITH_DATA1: Result<(i32, Never), (i32, !)> = unsafe { mem::transmute(0u64) };
-   |                                                                             ^^^^^^^^^^^^^^^^^^^^ constructing invalid value at ..0.1: encountered a value of uninhabited type `Never`
+   |                                                                             ^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .: encountered an uninhabited enum variant
 
 error[E0080]: evaluation of constant value failed
   --> $DIR/ub-enum.rs:98:77
    |
 LL | const BAD_UNINHABITED_WITH_DATA2: Result<(i32, !), (i32, Never)> = unsafe { mem::transmute(0u64) };
-   |                                                                             ^^^^^^^^^^^^^^^^^^^^ constructing invalid value at ..0.1: encountered a value of the never type `!`
+   |                                                                             ^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .: encountered an uninhabited enum variant
 
-error: aborting due to 13 previous errors
+error[E0080]: evaluation of constant value failed
+  --> $SRC_DIR/core/src/mem/mod.rs:LL:COL
+   |
+   = note: read discriminant of an uninhabited enum variant
+   |
+note: inside `discriminant::`
+  --> $SRC_DIR/core/src/mem/mod.rs:LL:COL
+note: inside `TEST_ICE_89765`
+  --> $DIR/ub-enum.rs:103:14
+   |
+LL |     unsafe { std::mem::discriminant(&*(&() as *const () as *const Never)); };
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 14 previous errors
 
 For more information about this error, try `rustc --explain E0080`.
diff --git a/tests/ui/consts/const-eval/ub-enum.64bit.stderr b/tests/ui/consts/const-eval/ub-enum.64bit.stderr
index fb40babb0b9c..c28a1b722aef 100644
--- a/tests/ui/consts/const-eval/ub-enum.64bit.stderr
+++ b/tests/ui/consts/const-eval/ub-enum.64bit.stderr
@@ -75,7 +75,7 @@ error[E0080]: it is undefined behavior to use this value
   --> $DIR/ub-enum.rs:81:1
    |
 LL | const BAD_UNINHABITED_VARIANT1: UninhDiscriminant = unsafe { mem::transmute(1u8) };
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at ..0: encountered a value of the never type `!`
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .: encountered an uninhabited enum variant
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: $SIZE, align: $ALIGN) {
@@ -86,7 +86,7 @@ error[E0080]: it is undefined behavior to use this value
   --> $DIR/ub-enum.rs:83:1
    |
 LL | const BAD_UNINHABITED_VARIANT2: UninhDiscriminant = unsafe { mem::transmute(3u8) };
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at ..0: encountered a value of uninhabited type `Never`
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .: encountered an uninhabited enum variant
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: $SIZE, align: $ALIGN) {
@@ -108,14 +108,27 @@ error[E0080]: evaluation of constant value failed
   --> $DIR/ub-enum.rs:96:77
    |
 LL | const BAD_UNINHABITED_WITH_DATA1: Result<(i32, Never), (i32, !)> = unsafe { mem::transmute(0u64) };
-   |                                                                             ^^^^^^^^^^^^^^^^^^^^ constructing invalid value at ..0.1: encountered a value of uninhabited type `Never`
+   |                                                                             ^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .: encountered an uninhabited enum variant
 
 error[E0080]: evaluation of constant value failed
   --> $DIR/ub-enum.rs:98:77
    |
 LL | const BAD_UNINHABITED_WITH_DATA2: Result<(i32, !), (i32, Never)> = unsafe { mem::transmute(0u64) };
-   |                                                                             ^^^^^^^^^^^^^^^^^^^^ constructing invalid value at ..0.1: encountered a value of the never type `!`
+   |                                                                             ^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .: encountered an uninhabited enum variant
 
-error: aborting due to 13 previous errors
+error[E0080]: evaluation of constant value failed
+  --> $SRC_DIR/core/src/mem/mod.rs:LL:COL
+   |
+   = note: read discriminant of an uninhabited enum variant
+   |
+note: inside `discriminant::`
+  --> $SRC_DIR/core/src/mem/mod.rs:LL:COL
+note: inside `TEST_ICE_89765`
+  --> $DIR/ub-enum.rs:103:14
+   |
+LL |     unsafe { std::mem::discriminant(&*(&() as *const () as *const Never)); };
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 14 previous errors
 
 For more information about this error, try `rustc --explain E0080`.
diff --git a/tests/ui/consts/const-eval/ub-enum.rs b/tests/ui/consts/const-eval/ub-enum.rs
index 8f26d9a00d71..078283fbd1f7 100644
--- a/tests/ui/consts/const-eval/ub-enum.rs
+++ b/tests/ui/consts/const-eval/ub-enum.rs
@@ -2,7 +2,7 @@
 // Strip out raw byte dumps to make comparison platform-independent:
 // normalize-stderr-test "(the raw bytes of the constant) \(size: [0-9]*, align: [0-9]*\)" -> "$1 (size: $$SIZE, align: $$ALIGN)"
 // normalize-stderr-test "([0-9a-f][0-9a-f] |╾─*a(lloc)?[0-9]+(\+[a-z0-9]+)?─*╼ )+ *│.*" -> "HEX_DUMP"
-#![feature(never_type)]
+#![feature(never_type, const_discriminant)]
 #![allow(invalid_value)]
 
 use std::mem;
@@ -66,8 +66,8 @@ const BAD_ENUM2_OPTION_PTR: Option = unsafe { mem::transmute(&0) };
 
 // # valid discriminant for uninhabited variant
 
-// An enum with 3 variants of which some are uninhabited -- so the uninhabited variants *do*
-// have a discriminant.
+// An enum with uninhabited variants but also at least 2 inhabited variants -- so the uninhabited
+// variants *do* have a discriminant.
 enum UninhDiscriminant {
     A,
     B(!),
@@ -98,5 +98,11 @@ const BAD_UNINHABITED_WITH_DATA1: Result<(i32, Never), (i32, !)> = unsafe { mem:
 const BAD_UNINHABITED_WITH_DATA2: Result<(i32, !), (i32, Never)> = unsafe { mem::transmute(0u64) };
 //~^ ERROR evaluation of constant value failed
 
+const TEST_ICE_89765: () = {
+    // This is a regression test for https://github.com/rust-lang/rust/issues/89765.
+    unsafe { std::mem::discriminant(&*(&() as *const () as *const Never)); };
+    //~^ inside `TEST_ICE_89765`
+};
+
 fn main() {
 }
diff --git a/tests/ui/consts/const-eval/ub-ref-ptr.stderr b/tests/ui/consts/const-eval/ub-ref-ptr.stderr
index 1d19dfff50b3..d1644f8a4dc1 100644
--- a/tests/ui/consts/const-eval/ub-ref-ptr.stderr
+++ b/tests/ui/consts/const-eval/ub-ref-ptr.stderr
@@ -141,7 +141,7 @@ error[E0080]: it is undefined behavior to use this value
   --> $DIR/ub-ref-ptr.rs:59:1
    |
 LL | const DATA_FN_PTR: fn() = unsafe { mem::transmute(&13) };
-   | ^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered alloc41, but expected a function pointer
+   | ^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered alloc39, but expected a function pointer
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: $SIZE, align: $ALIGN) {
diff --git a/tests/ui/consts/const_discriminant.rs b/tests/ui/consts/const_discriminant.rs
index 79e68590e85d..b1180faa6977 100644
--- a/tests/ui/consts/const_discriminant.rs
+++ b/tests/ui/consts/const_discriminant.rs
@@ -24,13 +24,6 @@ enum SingleVariant {
 
 const TEST_V: Discriminant = discriminant(&SingleVariant::V);
 
-pub const TEST_VOID: () = {
-    // This is UB, but CTFE does not check validity so it does not detect this.
-    // This is a regression test for https://github.com/rust-lang/rust/issues/89765.
-    unsafe { std::mem::discriminant(&*(&() as *const () as *const Void)); };
-};
-
-
 fn main() {
     assert_eq!(TEST_A, TEST_A_OTHER);
     assert_eq!(TEST_A, discriminant(black_box(&Test::A(17))));
diff --git a/tests/ui/consts/extra-const-ub/detect-extra-ub.rs b/tests/ui/consts/extra-const-ub/detect-extra-ub.rs
index 6a3c93ce7a67..5bff34bbe933 100644
--- a/tests/ui/consts/extra-const-ub/detect-extra-ub.rs
+++ b/tests/ui/consts/extra-const-ub/detect-extra-ub.rs
@@ -1,8 +1,26 @@
 // revisions: no_flag with_flag
 // [no_flag] check-pass
 // [with_flag] compile-flags: -Zextra-const-ub-checks
+#![feature(never_type)]
 
 use std::mem::transmute;
+use std::ptr::addr_of;
+
+#[derive(Clone, Copy)]
+enum E { A, B }
+
+#[derive(Clone, Copy)]
+enum Never {}
+
+// An enum with uninhabited variants but also at least 2 inhabited variants -- so the uninhabited
+// variants *do* have a discriminant.
+#[derive(Clone, Copy)]
+enum UninhDiscriminant {
+    A,
+    B(!),
+    C,
+    D(Never),
+}
 
 const INVALID_BOOL: () = unsafe {
     let _x: bool = transmute(3u8);
@@ -27,4 +45,15 @@ const UNALIGNED_PTR: () = unsafe {
     //[with_flag]~| invalid value
 };
 
+const UNINHABITED_VARIANT: () = unsafe {
+    let data = [1u8];
+    // Not using transmute, we want to hit the ImmTy code path.
+    let v = *addr_of!(data).cast::();
+    //[with_flag]~^ ERROR: evaluation of constant value failed
+};
+
+// Regression tests for an ICE (related to ).
+const VALID_ENUM1: E = { let e = E::A; e };
+const VALID_ENUM2: Result<&'static [u8], ()> = { let e = Err(()); e };
+
 fn main() {}
diff --git a/tests/ui/consts/extra-const-ub/detect-extra-ub.with_flag.stderr b/tests/ui/consts/extra-const-ub/detect-extra-ub.with_flag.stderr
index 3970baefcb35..19f1748ff9c9 100644
--- a/tests/ui/consts/extra-const-ub/detect-extra-ub.with_flag.stderr
+++ b/tests/ui/consts/extra-const-ub/detect-extra-ub.with_flag.stderr
@@ -1,11 +1,11 @@
 error[E0080]: evaluation of constant value failed
-  --> $DIR/detect-extra-ub.rs:8:20
+  --> $DIR/detect-extra-ub.rs:26:20
    |
 LL |     let _x: bool = transmute(3u8);
    |                    ^^^^^^^^^^^^^^ constructing invalid value: encountered 0x03, but expected a boolean
 
 error[E0080]: evaluation of constant value failed
-  --> $DIR/detect-extra-ub.rs:14:21
+  --> $DIR/detect-extra-ub.rs:32:21
    |
 LL |     let _x: usize = transmute(&3u8);
    |                     ^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
@@ -14,7 +14,7 @@ LL |     let _x: usize = transmute(&3u8);
    = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
 
 error[E0080]: evaluation of constant value failed
-  --> $DIR/detect-extra-ub.rs:20:30
+  --> $DIR/detect-extra-ub.rs:38:30
    |
 LL |     let _x: (usize, usize) = transmute(x);
    |                              ^^^^^^^^^^^^ unable to turn pointer into raw bytes
@@ -23,11 +23,17 @@ LL |     let _x: (usize, usize) = transmute(x);
    = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
 
 error[E0080]: evaluation of constant value failed
-  --> $DIR/detect-extra-ub.rs:25:20
+  --> $DIR/detect-extra-ub.rs:43:20
    |
 LL |     let _x: &u32 = transmute(&[0u8; 4]);
    |                    ^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered an unaligned reference (required 4 byte alignment but found 1)
 
-error: aborting due to 4 previous errors
+error[E0080]: evaluation of constant value failed
+  --> $DIR/detect-extra-ub.rs:51:13
+   |
+LL |     let v = *addr_of!(data).cast::();
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .: encountered an uninhabited enum variant
+
+error: aborting due to 5 previous errors
 
 For more information about this error, try `rustc --explain E0080`.
diff --git a/tests/ui/diagnostic-width/E0271.stderr b/tests/ui/diagnostic-width/E0271.stderr
index 52f415037d35..c1b8b32071ce 100644
--- a/tests/ui/diagnostic-width/E0271.stderr
+++ b/tests/ui/diagnostic-width/E0271.stderr
@@ -15,8 +15,7 @@ note: expected this to be `Foo`
    |
 LL |     type Error = E;
    |                  ^
-   = note: required for the cast from `Box>` to `Box<(dyn Future + 'static)>`
-   = note: the full name for the source type has been written to '$TEST_BUILD_DIR/diagnostic-width/E0271/E0271.long-type-hash.txt'
+   = note: required for the cast from `Box>, ()>>, ()>>, ()>>` to `Box<(dyn Future + 'static)>`
 
 error: aborting due to previous error
 
diff --git a/tests/ui/diagnostic-width/long-E0308.rs b/tests/ui/diagnostic-width/long-E0308.rs
index f021f1029334..0ae5e19ab2af 100644
--- a/tests/ui/diagnostic-width/long-E0308.rs
+++ b/tests/ui/diagnostic-width/long-E0308.rs
@@ -1,4 +1,4 @@
-// compile-flags: --diagnostic-width=60
+// compile-flags: --diagnostic-width=60 -Zwrite-long-types-to-disk=yes
 // normalize-stderr-test: "long-type-\d+" -> "long-type-hash"
 
 mod a {
diff --git a/tests/ui/error-codes/E0275.stderr b/tests/ui/error-codes/E0275.stderr
index 03c37d6f0e1d..c702c3790a7c 100644
--- a/tests/ui/error-codes/E0275.stderr
+++ b/tests/ui/error-codes/E0275.stderr
@@ -5,12 +5,11 @@ LL | impl Foo for T where Bar: Foo {}
    |                                 ^^^
    |
    = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`E0275`)
-note: required for `Bar>>>>>>>>>>>>>>>>>>>>` to implement `Foo`
+note: required for `Bar>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>` to implement `Foo`
   --> $DIR/E0275.rs:6:9
    |
 LL | impl Foo for T where Bar: Foo {}
    |         ^^^     ^               --- unsatisfied trait bound introduced here
-   = note: the full type name has been written to '$TEST_BUILD_DIR/error-codes/E0275/E0275.long-type-hash.txt'
    = note: 126 redundant requirements hidden
    = note: required for `Bar` to implement `Foo`
 
diff --git a/tests/ui/generator/issue-113279.rs b/tests/ui/generator/issue-113279.rs
new file mode 100644
index 000000000000..f69f804b716d
--- /dev/null
+++ b/tests/ui/generator/issue-113279.rs
@@ -0,0 +1,27 @@
+#![feature(generators)]
+
+// `foo` attempts to dereference `""`, which results in an error being reported. Later, the
+// generator transform for `foo` then produces a union which contains a `str` type - unions should
+// not contain unsized types, but this is okay because an error has been reported already.
+// When const propagation happens later in compilation, it attempts to compute the layout of the
+// generator (as part of checking whether something can be const propagated) and in turn attempts
+// to compute the layout of `str` in the context of a union - where this caused an ICE. This test
+// makes sure that doesn't happen again.
+
+fn foo() {
+    let _y = static || {
+        let x = &mut 0;
+        *{
+            yield;
+            x
+        } += match { *"" }.len() {
+            //~^ ERROR cannot move a value of type `str` [E0161]
+            //~^^ ERROR cannot move out of a shared reference [E0507]
+            _ => 0,
+        };
+    };
+}
+
+fn main() {
+    foo()
+}
diff --git a/tests/ui/generator/issue-113279.stderr b/tests/ui/generator/issue-113279.stderr
new file mode 100644
index 000000000000..cc9b64ef9ac2
--- /dev/null
+++ b/tests/ui/generator/issue-113279.stderr
@@ -0,0 +1,16 @@
+error[E0161]: cannot move a value of type `str`
+  --> $DIR/issue-113279.rs:17:20
+   |
+LL |         } += match { *"" }.len() {
+   |                    ^^^^^^^ the size of `str` cannot be statically determined
+
+error[E0507]: cannot move out of a shared reference
+  --> $DIR/issue-113279.rs:17:22
+   |
+LL |         } += match { *"" }.len() {
+   |                      ^^^ move occurs because value has type `str`, which does not implement the `Copy` trait
+
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0161, E0507.
+For more information about an error, try `rustc --explain E0161`.
diff --git a/tests/ui/higher-ranked/trait-bounds/hang-on-deeply-nested-dyn.stderr b/tests/ui/higher-ranked/trait-bounds/hang-on-deeply-nested-dyn.stderr
index a9d649b82852..139c844d8a22 100644
--- a/tests/ui/higher-ranked/trait-bounds/hang-on-deeply-nested-dyn.stderr
+++ b/tests/ui/higher-ranked/trait-bounds/hang-on-deeply-nested-dyn.stderr
@@ -13,8 +13,7 @@ LL | | ) {
 LL |       f
    |       ^ expected `&dyn Fn(&dyn Fn(&dyn Fn(&...)))`, found `&dyn Fn(u32)`
    |
-   = note: expected reference `&dyn Fn(&dyn Fn(&dyn Fn(&dyn Fn(&dyn Fn(&dyn Fn(&dyn Fn(&dyn Fn(&dyn Fn(&dyn Fn(&dyn Fn(&...)))))))))))`
-           the full type name has been written to '$TEST_BUILD_DIR/higher-ranked/trait-bounds/hang-on-deeply-nested-dyn/hang-on-deeply-nested-dyn.long-type-hash.txt'
+   = note: expected reference `&dyn for<'a> Fn(&'a (dyn for<'a> Fn(&'a (dyn for<'a> Fn(&'a (dyn for<'a> Fn(&'a (dyn for<'a> Fn(&'a (dyn for<'a> Fn(&'a (dyn for<'a> Fn(&'a (dyn for<'a> Fn(&'a (dyn for<'a> Fn(&'a (dyn for<'a> Fn(&'a (dyn for<'a> Fn(&'a (dyn Fn(u32) + 'a)) + 'a)) + 'a)) + 'a)) + 'a)) + 'a)) + 'a)) + 'a)) + 'a)) + 'a)) + 'a))`
               found reference `&dyn Fn(u32)`
 
 error: aborting due to previous error
diff --git a/tests/ui/higher-ranked/trait-bounds/issue-30786.stderr b/tests/ui/higher-ranked/trait-bounds/issue-30786.stderr
index f32ba57200d5..957082b6010c 100644
--- a/tests/ui/higher-ranked/trait-bounds/issue-30786.stderr
+++ b/tests/ui/higher-ranked/trait-bounds/issue-30786.stderr
@@ -31,7 +31,6 @@ LL | pub struct Filter {
 LL |     let count = filter.countx();
    |                        ^^^^^^ method cannot be called due to unsatisfied trait bounds
    |
-   = note: the full type name has been written to '$TEST_BUILD_DIR/higher-ranked/trait-bounds/issue-30786/issue-30786.long-type-hash.txt'
 note: the following trait bounds were not satisfied:
       `&'a mut &Filter fn(&'a u64) -> &'a u64 {identity::}>, [closure@$DIR/issue-30786.rs:131:30: 131:37]>: Stream`
       `&'a mut &mut Filter fn(&'a u64) -> &'a u64 {identity::}>, [closure@$DIR/issue-30786.rs:131:30: 131:37]>: Stream`
diff --git a/tests/ui/imports/issue-113953.rs b/tests/ui/imports/issue-113953.rs
new file mode 100644
index 000000000000..449a074f4b5d
--- /dev/null
+++ b/tests/ui/imports/issue-113953.rs
@@ -0,0 +1,6 @@
+// edition: 2021
+use u8 as imported_u8;
+use unresolved as u8;
+//~^ ERROR unresolved import `unresolved`
+
+fn main() {}
diff --git a/tests/ui/imports/issue-113953.stderr b/tests/ui/imports/issue-113953.stderr
new file mode 100644
index 000000000000..70f91bd3c5bf
--- /dev/null
+++ b/tests/ui/imports/issue-113953.stderr
@@ -0,0 +1,9 @@
+error[E0432]: unresolved import `unresolved`
+  --> $DIR/issue-113953.rs:3:5
+   |
+LL | use unresolved as u8;
+   |     ^^^^^^^^^^^^^^^^ no external crate `unresolved`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0432`.
diff --git a/tests/ui/issues/issue-20413.stderr b/tests/ui/issues/issue-20413.stderr
index 8891a26784e4..8793029dd224 100644
--- a/tests/ui/issues/issue-20413.stderr
+++ b/tests/ui/issues/issue-20413.stderr
@@ -14,12 +14,11 @@ LL | impl Foo for T where NoData: Foo {
    |                                    ^^^
    |
    = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`issue_20413`)
-note: required for `NoData>>>>>>>>>>>>` to implement `Foo`
+note: required for `NoData>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>` to implement `Foo`
   --> $DIR/issue-20413.rs:9:9
    |
 LL | impl Foo for T where NoData: Foo {
    |         ^^^     ^                  --- unsatisfied trait bound introduced here
-   = note: the full type name has been written to '$TEST_BUILD_DIR/issues/issue-20413/issue-20413.long-type-hash.txt'
    = note: 126 redundant requirements hidden
    = note: required for `NoData` to implement `Foo`
 
@@ -30,18 +29,16 @@ LL | impl Bar for T where EvenLessData: Baz {
    |                                          ^^^
    |
    = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`issue_20413`)
-note: required for `EvenLessData>>>>>>` to implement `Baz`
+note: required for `EvenLessData>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>` to implement `Baz`
   --> $DIR/issue-20413.rs:35:9
    |
 LL | impl Baz for T where AlmostNoData: Bar {
    |         ^^^     ^                        --- unsatisfied trait bound introduced here
-   = note: the full type name has been written to '$TEST_BUILD_DIR/issues/issue-20413/issue-20413.long-type-hash.txt'
-note: required for `AlmostNoData>>>>>>` to implement `Bar`
+note: required for `AlmostNoData>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>` to implement `Bar`
   --> $DIR/issue-20413.rs:28:9
    |
 LL | impl Bar for T where EvenLessData: Baz {
    |         ^^^     ^                        --- unsatisfied trait bound introduced here
-   = note: the full type name has been written to '$TEST_BUILD_DIR/issues/issue-20413/issue-20413.long-type-hash.txt'
    = note: 125 redundant requirements hidden
    = note: required for `EvenLessData` to implement `Baz`
 
@@ -52,18 +49,16 @@ LL | impl Baz for T where AlmostNoData: Bar {
    |                                          ^^^
    |
    = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`issue_20413`)
-note: required for `AlmostNoData>>>>>>` to implement `Bar`
+note: required for `AlmostNoData>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>` to implement `Bar`
   --> $DIR/issue-20413.rs:28:9
    |
 LL | impl Bar for T where EvenLessData: Baz {
    |         ^^^     ^                        --- unsatisfied trait bound introduced here
-   = note: the full type name has been written to '$TEST_BUILD_DIR/issues/issue-20413/issue-20413.long-type-hash.txt'
-note: required for `EvenLessData>>>>>>` to implement `Baz`
+note: required for `EvenLessData>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>` to implement `Baz`
   --> $DIR/issue-20413.rs:35:9
    |
 LL | impl Baz for T where AlmostNoData: Bar {
    |         ^^^     ^                        --- unsatisfied trait bound introduced here
-   = note: the full type name has been written to '$TEST_BUILD_DIR/issues/issue-20413/issue-20413.long-type-hash.txt'
    = note: 125 redundant requirements hidden
    = note: required for `AlmostNoData` to implement `Bar`
 
diff --git a/tests/ui/issues/issue-23122-2.stderr b/tests/ui/issues/issue-23122-2.stderr
index 06e5b711a822..af77e4b1a412 100644
--- a/tests/ui/issues/issue-23122-2.stderr
+++ b/tests/ui/issues/issue-23122-2.stderr
@@ -5,14 +5,13 @@ LL |     type Next =  as Next>::Next;
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`issue_23122_2`)
-note: required for `GetNext<<<<<<<... as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next>` to implement `Next`
+note: required for `GetNext<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next>` to implement `Next`
   --> $DIR/issue-23122-2.rs:10:15
    |
 LL | impl Next for GetNext {
    |      -        ^^^^     ^^^^^^^^^^
    |      |
    |      unsatisfied trait bound introduced here
-   = note: the full type name has been written to '$TEST_BUILD_DIR/issues/issue-23122-2/issue-23122-2.long-type-hash.txt'
 
 error: aborting due to previous error
 
diff --git a/tests/ui/lint/lint-ctypes-113900.rs b/tests/ui/lint/lint-ctypes-113900.rs
new file mode 100644
index 000000000000..ac4ff1ae2dfd
--- /dev/null
+++ b/tests/ui/lint/lint-ctypes-113900.rs
@@ -0,0 +1,12 @@
+// check-pass
+
+// Extending `improper_ctypes` to check external-ABI fn-ptrs means that it can encounter
+// projections which cannot be normalized - unsurprisingly, this shouldn't crash the compiler.
+
+trait Bar {
+    type Assoc;
+}
+
+type Foo = extern "C" fn() -> ::Assoc;
+
+fn main() {}
diff --git a/tests/ui/lint/unused/const-local-var.rs b/tests/ui/lint/unused/const-local-var.rs
new file mode 100644
index 000000000000..89ca16fe003e
--- /dev/null
+++ b/tests/ui/lint/unused/const-local-var.rs
@@ -0,0 +1,23 @@
+// regression test for https://github.com/rust-lang/rust/issues/69016
+// check-pass
+
+#![warn(unused)]
+#![deny(warnings)]
+
+fn _unused1(x: i32) -> i32 {
+    const F: i32 = 2;
+    let g = 1;
+    x * F + g
+}
+
+pub struct Foo {}
+
+impl Foo {
+    fn _unused2(x: i32) -> i32 {
+        const F: i32 = 2;
+        let g = 1;
+        x * F + g
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/macros/builtin-env-issue-114010.rs b/tests/ui/macros/builtin-env-issue-114010.rs
new file mode 100644
index 000000000000..819b8b1e8abe
--- /dev/null
+++ b/tests/ui/macros/builtin-env-issue-114010.rs
@@ -0,0 +1,10 @@
+// unset-rustc-env:oopsie
+// unset-rustc-env:a""a
+
+env![r#"oopsie"#];
+//~^ ERROR environment variable `oopsie` not defined at compile time
+
+env![r#"a""a"#];
+//~^ ERROR environment variable `a""a` not defined at compile time
+
+fn main() {}
diff --git a/tests/ui/macros/builtin-env-issue-114010.stderr b/tests/ui/macros/builtin-env-issue-114010.stderr
new file mode 100644
index 000000000000..0da42089cce7
--- /dev/null
+++ b/tests/ui/macros/builtin-env-issue-114010.stderr
@@ -0,0 +1,20 @@
+error: environment variable `oopsie` not defined at compile time
+  --> $DIR/builtin-env-issue-114010.rs:4:1
+   |
+LL | env![r#"oopsie"#];
+   | ^^^^^^^^^^^^^^^^^
+   |
+   = help: use `std::env::var(r#"oopsie"#)` to read the variable at run time
+   = note: this error originates in the macro `env` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: environment variable `a""a` not defined at compile time
+  --> $DIR/builtin-env-issue-114010.rs:7:1
+   |
+LL | env![r#"a""a"#];
+   | ^^^^^^^^^^^^^^^
+   |
+   = help: use `std::env::var(r#"a""a"#)` to read the variable at run time
+   = note: this error originates in the macro `env` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: aborting due to 2 previous errors
+
diff --git a/tests/ui/methods/inherent-bound-in-probe.stderr b/tests/ui/methods/inherent-bound-in-probe.stderr
index ff03a7edb054..8d7cc462280d 100644
--- a/tests/ui/methods/inherent-bound-in-probe.stderr
+++ b/tests/ui/methods/inherent-bound-in-probe.stderr
@@ -24,8 +24,7 @@ LL | where
 LL |     &'a T: IntoIterator,
    |                         ------------- unsatisfied trait bound introduced here
    = note: 126 redundant requirements hidden
-   = note: required for `&BitReaderWrapper>>>>` to implement `IntoIterator`
-   = note: the full type name has been written to '$TEST_BUILD_DIR/methods/inherent-bound-in-probe/inherent-bound-in-probe.long-type-hash.txt'
+   = note: required for `&BitReaderWrapper>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>` to implement `IntoIterator`
 note: required by a bound in `Helper<'a, T>`
   --> $DIR/inherent-bound-in-probe.rs:25:25
    |
diff --git a/tests/ui/recursion/issue-83150.stderr b/tests/ui/recursion/issue-83150.stderr
index eae58771a416..543b7308472f 100644
--- a/tests/ui/recursion/issue-83150.stderr
+++ b/tests/ui/recursion/issue-83150.stderr
@@ -14,8 +14,7 @@ error[E0275]: overflow evaluating the requirement `Map<&mut std::ops::Range,
    = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`issue_83150`)
    = note: required for `&mut Map<&mut std::ops::Range, [closure@$DIR/issue-83150.rs:13:24: 13:27]>` to implement `Iterator`
    = note: 65 redundant requirements hidden
-   = note: required for `&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<..., ...>, ...>, ...>, ...>, ...>, ...>, ...>` to implement `Iterator`
-   = note: the full type name has been written to '$TEST_BUILD_DIR/recursion/issue-83150/issue-83150.long-type-hash.txt'
+   = note: required for `&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut std::ops::Range, [closure@$DIR/issue-83150.rs:13:24: 13:27]>, [closure@$DIR/issue-83150.rs:13:24: 13:27]>, [closure@$DIR/issue-83150.rs:13:24: 13:27]>, [closure@$DIR/issue-83150.rs:13:24: 13:27]>, [closure@$DIR/issue-83150.rs:13:24: 13:27]>, [closure@$DIR/issue-83150.rs:13:24: 13:27]>, [closure@$DIR/issue-83150.rs:13:24: 13:27]>, [closure@$DIR/issue-83150.rs:13:24: 13:27]>, [closure@$DIR/issue-83150.rs:13:24: 13:27]>, [closure@$DIR/issue-83150.rs:13:24: 13:27]>, [closure@$DIR/issue-83150.rs:13:24: 13:27]>, [closure@$DIR/issue-83150.rs:13:24: 13:27]>, [closure@$DIR/issue-83150.rs:13:24: 13:27]>, [closure@$DIR/issue-83150.rs:13:24: 13:27]>, [closure@$DIR/issue-83150.rs:13:24: 13:27]>, [closure@$DIR/issue-83150.rs:13:24: 13:27]>, [closure@$DIR/issue-83150.rs:13:24: 13:27]>, [closure@$DIR/issue-83150.rs:13:24: 13:27]>, [closure@$DIR/issue-83150.rs:13:24: 13:27]>, [closure@$DIR/issue-83150.rs:13:24: 13:27]>, [closure@$DIR/issue-83150.rs:13:24: 13:27]>, [closure@$DIR/issue-83150.rs:13:24: 13:27]>, [closure@$DIR/issue-83150.rs:13:24: 13:27]>, [closure@$DIR/issue-83150.rs:13:24: 13:27]>, [closure@$DIR/issue-83150.rs:13:24: 13:27]>, [closure@$DIR/issue-83150.rs:13:24: 13:27]>, [closure@$DIR/issue-83150.rs:13:24: 13:27]>, [closure@$DIR/issue-83150.rs:13:24: 13:27]>, [closure@$DIR/issue-83150.rs:13:24: 13:27]>, [closure@$DIR/issue-83150.rs:13:24: 13:27]>, [closure@$DIR/issue-83150.rs:13:24: 13:27]>, [closure@$DIR/issue-83150.rs:13:24: 13:27]>, [closure@$DIR/issue-83150.rs:13:24: 13:27]>, [closure@$DIR/issue-83150.rs:13:24: 13:27]>, [closure@$DIR/issue-83150.rs:13:24: 13:27]>, [closure@$DIR/issue-83150.rs:13:24: 13:27]>, [closure@$DIR/issue-83150.rs:13:24: 13:27]>, [closure@$DIR/issue-83150.rs:13:24: 13:27]>, [closure@$DIR/issue-83150.rs:13:24: 13:27]>, [closure@$DIR/issue-83150.rs:13:24: 13:27]>, [closure@$DIR/issue-83150.rs:13:24: 13:27]>, [closure@$DIR/issue-83150.rs:13:24: 13:27]>, [closure@$DIR/issue-83150.rs:13:24: 13:27]>, [closure@$DIR/issue-83150.rs:13:24: 13:27]>, [closure@$DIR/issue-83150.rs:13:24: 13:27]>, [closure@$DIR/issue-83150.rs:13:24: 13:27]>, [closure@$DIR/issue-83150.rs:13:24: 13:27]>, [closure@$DIR/issue-83150.rs:13:24: 13:27]>, [closure@$DIR/issue-83150.rs:13:24: 13:27]>, [closure@$DIR/issue-83150.rs:13:24: 13:27]>, [closure@$DIR/issue-83150.rs:13:24: 13:27]>, [closure@$DIR/issue-83150.rs:13:24: 13:27]>, [closure@$DIR/issue-83150.rs:13:24: 13:27]>, [closure@$DIR/issue-83150.rs:13:24: 13:27]>, [closure@$DIR/issue-83150.rs:13:24: 13:27]>, [closure@$DIR/issue-83150.rs:13:24: 13:27]>, [closure@$DIR/issue-83150.rs:13:24: 13:27]>, [closure@$DIR/issue-83150.rs:13:24: 13:27]>, [closure@$DIR/issue-83150.rs:13:24: 13:27]>, [closure@$DIR/issue-83150.rs:13:24: 13:27]>, [closure@$DIR/issue-83150.rs:13:24: 13:27]>, [closure@$DIR/issue-83150.rs:13:24: 13:27]>, [closure@$DIR/issue-83150.rs:13:24: 13:27]>, [closure@$DIR/issue-83150.rs:13:24: 13:27]>, [closure@$DIR/issue-83150.rs:13:24: 13:27]>` to implement `Iterator`
 
 error: aborting due to previous error; 1 warning emitted
 
diff --git a/tests/ui/regions/issue-102374.stderr b/tests/ui/regions/issue-102374.stderr
index af64b6867bb0..a4230cf8b5a2 100644
--- a/tests/ui/regions/issue-102374.stderr
+++ b/tests/ui/regions/issue-102374.stderr
@@ -7,8 +7,7 @@ LL |     f
    |     ^ expected `i32`, found fn pointer
    |
    = note:    expected type `i32`
-           found fn pointer `fn(Cell<...>)`
-           the full type name has been written to '$TEST_BUILD_DIR/regions/issue-102374/issue-102374.long-type-hash.txt'
+           found fn pointer `for<'z1, 'a, 'b, 'c, 'd, 'e, 'f, 'g, 'h, 'i, 'j, 'k, 'l, 'm, 'n, 'o, 'p, 'q, 'r, 's, 't, 'u, 'v, 'w, 'x, 'y, 'z, 'z0> fn(Cell<(&'z1 i32, &'a i32, &'b i32, &'c i32, &'d i32, &'e i32, &'f i32, &'g i32, &'h i32, &'i i32, &'j i32, &'k i32, &'l i32, &'m i32, &'n i32, &'o i32, &'p i32, &'q i32, &'r i32, &'s i32, &'t i32, &'u i32, &'v i32, &'w i32, &'x i32, &'y i32, &'z i32, &'z0 i32)>)`
 
 error: aborting due to previous error
 
diff --git a/tests/ui/rfcs/rfc-3348-c-string-literals/auxiliary/count.rs b/tests/ui/rfcs/rfc-3348-c-string-literals/auxiliary/count.rs
new file mode 100644
index 000000000000..0907061d64a1
--- /dev/null
+++ b/tests/ui/rfcs/rfc-3348-c-string-literals/auxiliary/count.rs
@@ -0,0 +1,14 @@
+// force-host
+// edition: 2018
+// no-prefer-dynamic
+#![crate_type = "proc-macro"]
+
+extern crate proc_macro;
+
+use proc_macro::TokenStream;
+use std::str::FromStr;
+
+#[proc_macro]
+pub fn number_of_tokens(_: TokenStream) -> TokenStream {
+    TokenStream::from_str("c\"\"").unwrap().into_iter().count().to_string().parse().unwrap()
+}
diff --git a/tests/ui/rfcs/rfc-3348-c-string-literals/basic.rs b/tests/ui/rfcs/rfc-3348-c-string-literals/basic.rs
index 3fc5fd481ea6..5037396000bf 100644
--- a/tests/ui/rfcs/rfc-3348-c-string-literals/basic.rs
+++ b/tests/ui/rfcs/rfc-3348-c-string-literals/basic.rs
@@ -1,5 +1,4 @@
-// FIXME(c_str_literals): This should be `run-pass`
-// known-bug: #113333
+// run-pass
 // edition: 2021
 
 #![feature(c_str_literals)]
diff --git a/tests/ui/rfcs/rfc-3348-c-string-literals/basic.stderr b/tests/ui/rfcs/rfc-3348-c-string-literals/basic.stderr
deleted file mode 100644
index 571c319d8c53..000000000000
--- a/tests/ui/rfcs/rfc-3348-c-string-literals/basic.stderr
+++ /dev/null
@@ -1,25 +0,0 @@
-error: prefix `c` is unknown
-  --> $DIR/basic.rs:8:27
-   |
-LL |     assert_eq!(b"test\0", c"test".to_bytes_with_nul());
-   |                           ^ unknown prefix
-   |
-   = note: prefixed identifiers and literals are reserved since Rust 2021
-help: consider inserting whitespace here
-   |
-LL |     assert_eq!(b"test\0", c "test".to_bytes_with_nul());
-   |                            +
-
-error: no rules expected the token `"test"`
-  --> $DIR/basic.rs:8:28
-   |
-LL |     assert_eq!(b"test\0", c"test".to_bytes_with_nul());
-   |                            -^^^^^
-   |                            |
-   |                            no rules expected this token in macro call
-   |                            help: missing comma here
-   |
-   = note: while trying to match sequence start
-
-error: aborting due to 2 previous errors
-
diff --git a/tests/ui/rfcs/rfc-3348-c-string-literals/edition-spans.rs b/tests/ui/rfcs/rfc-3348-c-string-literals/edition-spans.rs
new file mode 100644
index 000000000000..b3557c71b744
--- /dev/null
+++ b/tests/ui/rfcs/rfc-3348-c-string-literals/edition-spans.rs
@@ -0,0 +1,16 @@
+// even if this crate is edition 2021, proc macros compiled using older
+// editions should still be able to observe the pre-2021 token behavior
+//
+// adapted from tests/ui/rust-2021/reserved-prefixes-via-macro.rs
+
+// edition: 2021
+// check-pass
+
+// aux-build: count.rs
+extern crate count;
+
+const _: () = {
+    assert!(count::number_of_tokens!() == 2);
+};
+
+fn main() {}
diff --git a/tests/ui/rfcs/rfc-3348-c-string-literals/gate.stderr b/tests/ui/rfcs/rfc-3348-c-string-literals/gate.stderr
index 8de36ca4a6ed..ea666e433083 100644
--- a/tests/ui/rfcs/rfc-3348-c-string-literals/gate.stderr
+++ b/tests/ui/rfcs/rfc-3348-c-string-literals/gate.stderr
@@ -1,32 +1,21 @@
-error: prefix `c` is unknown
+error[E0658]: `c".."` literals are experimental
   --> $DIR/gate.rs:10:5
    |
 LL |     c"foo";
-   |     ^ unknown prefix
+   |     ^^^^^^
    |
-   = note: prefixed identifiers and literals are reserved since Rust 2021
-help: consider inserting whitespace here
-   |
-LL |     c "foo";
-   |      +
+   = note: see issue #105723  for more information
+   = help: add `#![feature(c_str_literals)]` to the crate attributes to enable
 
-error: prefix `c` is unknown
+error[E0658]: `c".."` literals are experimental
   --> $DIR/gate.rs:13:8
    |
 LL |     m!(c"test");
-   |        ^ unknown prefix
+   |        ^^^^^^^
    |
-   = note: prefixed identifiers and literals are reserved since Rust 2021
-help: consider inserting whitespace here
-   |
-LL |     m!(c "test");
-   |         +
+   = note: see issue #105723  for more information
+   = help: add `#![feature(c_str_literals)]` to the crate attributes to enable
 
-error: expected one of `!`, `.`, `::`, `;`, `?`, `{`, `}`, or an operator, found `"foo"`
-  --> $DIR/gate.rs:10:6
-   |
-LL |     c"foo";
-   |      ^^^^^ expected one of 8 possible tokens
-
-error: aborting due to 3 previous errors
+error: aborting due to 2 previous errors
 
+For more information about this error, try `rustc --explain E0658`.
diff --git a/tests/ui/rfcs/rfc-3348-c-string-literals/no-nuls.rs b/tests/ui/rfcs/rfc-3348-c-string-literals/no-nuls.rs
index 96945f125da7..369173e23184 100644
Binary files a/tests/ui/rfcs/rfc-3348-c-string-literals/no-nuls.rs and b/tests/ui/rfcs/rfc-3348-c-string-literals/no-nuls.rs differ
diff --git a/tests/ui/rfcs/rfc-3348-c-string-literals/no-nuls.stderr b/tests/ui/rfcs/rfc-3348-c-string-literals/no-nuls.stderr
index 2226c7aa6a9a..82d9f9cb3209 100644
Binary files a/tests/ui/rfcs/rfc-3348-c-string-literals/no-nuls.stderr and b/tests/ui/rfcs/rfc-3348-c-string-literals/no-nuls.stderr differ
diff --git a/tests/ui/rfcs/rfc-3348-c-string-literals/non-ascii.rs b/tests/ui/rfcs/rfc-3348-c-string-literals/non-ascii.rs
index 066505c23dfc..380445d7a7fb 100644
--- a/tests/ui/rfcs/rfc-3348-c-string-literals/non-ascii.rs
+++ b/tests/ui/rfcs/rfc-3348-c-string-literals/non-ascii.rs
@@ -1,5 +1,4 @@
-// FIXME(c_str_literals): This should be `run-pass`
-// known-bug: #113333
+// run-pass
 // edition: 2021
 
 #![feature(c_str_literals)]
diff --git a/tests/ui/rfcs/rfc-3348-c-string-literals/non-ascii.stderr b/tests/ui/rfcs/rfc-3348-c-string-literals/non-ascii.stderr
deleted file mode 100644
index 47361fb61d27..000000000000
--- a/tests/ui/rfcs/rfc-3348-c-string-literals/non-ascii.stderr
+++ /dev/null
@@ -1,38 +0,0 @@
-error: prefix `c` is unknown
-  --> $DIR/non-ascii.rs:9:9
-   |
-LL |         c"\xEF\x80🦀\u{1F980}".to_bytes_with_nul(),
-   |         ^ unknown prefix
-   |
-   = note: prefixed identifiers and literals are reserved since Rust 2021
-help: consider inserting whitespace here
-   |
-LL |         c "\xEF\x80🦀\u{1F980}".to_bytes_with_nul(),
-   |          +
-
-error: out of range hex escape
-  --> $DIR/non-ascii.rs:9:11
-   |
-LL |         c"\xEF\x80🦀\u{1F980}".to_bytes_with_nul(),
-   |           ^^^^ must be a character in the range [\x00-\x7f]
-
-error: out of range hex escape
-  --> $DIR/non-ascii.rs:9:15
-   |
-LL |         c"\xEF\x80🦀\u{1F980}".to_bytes_with_nul(),
-   |               ^^^^ must be a character in the range [\x00-\x7f]
-
-error: no rules expected the token `"\xEF\x80🦀\u{1F980}"`
-  --> $DIR/non-ascii.rs:9:10
-   |
-LL |         c"\xEF\x80🦀\u{1F980}".to_bytes_with_nul(),
-   |          -^^^^^^^^^^^^^^^^^^^^
-   |          |
-   |          no rules expected this token in macro call
-   |          help: missing comma here
-   |
-note: while trying to match `,`
-  --> $SRC_DIR/core/src/macros/mod.rs:LL:COL
-
-error: aborting due to 4 previous errors
-
diff --git a/tests/ui/suggestions/copied-and-cloned.fixed b/tests/ui/suggestions/copied-and-cloned.fixed
index f801403feec4..13031f424cbe 100644
--- a/tests/ui/suggestions/copied-and-cloned.fixed
+++ b/tests/ui/suggestions/copied-and-cloned.fixed
@@ -20,4 +20,12 @@ fn main() {
     expect::>(x.cloned());
     //~^ ERROR mismatched types
     //~| HELP use `Result::cloned` to clone the value inside the `Result`
+
+    let s = String::new();
+    let x = Some(s.clone());
+    let y = Some(&s);
+    println!("{}", x.as_ref() == y);
+    //~^ ERROR mismatched types
+    //~| HELP use `Option::as_ref()` to convert `Option` to `Option<&String>`
+
 }
diff --git a/tests/ui/suggestions/copied-and-cloned.rs b/tests/ui/suggestions/copied-and-cloned.rs
index 640450b76552..2927d66dea94 100644
--- a/tests/ui/suggestions/copied-and-cloned.rs
+++ b/tests/ui/suggestions/copied-and-cloned.rs
@@ -20,4 +20,12 @@ fn main() {
     expect::>(x);
     //~^ ERROR mismatched types
     //~| HELP use `Result::cloned` to clone the value inside the `Result`
+
+    let s = String::new();
+    let x = Some(s.clone());
+    let y = Some(&s);
+    println!("{}", x == y);
+    //~^ ERROR mismatched types
+    //~| HELP use `Option::as_ref()` to convert `Option` to `Option<&String>`
+
 }
diff --git a/tests/ui/suggestions/copied-and-cloned.stderr b/tests/ui/suggestions/copied-and-cloned.stderr
index 067808141824..19aaf6e00b13 100644
--- a/tests/ui/suggestions/copied-and-cloned.stderr
+++ b/tests/ui/suggestions/copied-and-cloned.stderr
@@ -78,6 +78,19 @@ help: use `Result::cloned` to clone the value inside the `Result`
 LL |     expect::>(x.cloned());
    |                                   +++++++++
 
-error: aborting due to 4 previous errors
+error[E0308]: mismatched types
+  --> $DIR/copied-and-cloned.rs:27:25
+   |
+LL |     println!("{}", x == y);
+   |                         ^ expected `Option`, found `Option<&String>`
+   |
+   = note: expected enum `Option`
+              found enum `Option<&String>`
+help: use `Option::as_ref()` to convert `Option` to `Option<&String>`
+   |
+LL |     println!("{}", x.as_ref() == y);
+   |                     +++++++++
+
+error: aborting due to 5 previous errors
 
 For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/traits/dont-autoderef-ty-with-escaping-var.rs b/tests/ui/traits/dont-autoderef-ty-with-escaping-var.rs
new file mode 100644
index 000000000000..d5ba3847ac38
--- /dev/null
+++ b/tests/ui/traits/dont-autoderef-ty-with-escaping-var.rs
@@ -0,0 +1,22 @@
+// issue:113951
+
+trait Foo<'x, T> {}
+
+trait RefFoo {
+    fn ref_foo(&self);
+}
+
+impl RefFoo for T
+where
+    for<'a> &'a mut Vec<&'a u32>: Foo<'static, T>,
+{
+    fn ref_foo(&self) {}
+}
+
+fn coerce_lifetime2() {
+    >::ref_foo(unknown);
+    //~^ ERROR cannot find value `unknown` in this scope
+    //~| ERROR the trait bound `for<'a> &'a mut Vec<&'a u32>: Foo<'static, i32>` is not satisfied
+}
+
+fn main() {}
diff --git a/tests/ui/traits/dont-autoderef-ty-with-escaping-var.stderr b/tests/ui/traits/dont-autoderef-ty-with-escaping-var.stderr
new file mode 100644
index 000000000000..934d20b22677
--- /dev/null
+++ b/tests/ui/traits/dont-autoderef-ty-with-escaping-var.stderr
@@ -0,0 +1,27 @@
+error[E0425]: cannot find value `unknown` in this scope
+  --> $DIR/dont-autoderef-ty-with-escaping-var.rs:17:35
+   |
+LL |     >::ref_foo(unknown);
+   |                                   ^^^^^^^ not found in this scope
+
+error[E0277]: the trait bound `for<'a> &'a mut Vec<&'a u32>: Foo<'static, i32>` is not satisfied
+  --> $DIR/dont-autoderef-ty-with-escaping-var.rs:17:35
+   |
+LL |     >::ref_foo(unknown);
+   |     ----------------------------- ^^^^^^^ the trait `for<'a> Foo<'static, i32>` is not implemented for `&'a mut Vec<&'a u32>`
+   |     |
+   |     required by a bound introduced by this call
+   |
+note: required for `i32` to implement `RefFoo`
+  --> $DIR/dont-autoderef-ty-with-escaping-var.rs:9:9
+   |
+LL | impl RefFoo for T
+   |         ^^^^^^^^^     ^
+LL | where
+LL |     for<'a> &'a mut Vec<&'a u32>: Foo<'static, T>,
+   |                                   --------------- unsatisfied trait bound introduced here
+
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0277, E0425.
+For more information about an error, try `rustc --explain E0277`.
diff --git a/tests/ui/traits/issue-91949-hangs-on-recursion.stderr b/tests/ui/traits/issue-91949-hangs-on-recursion.stderr
index c721dd41a2c1..c6fc7bb12c9b 100644
--- a/tests/ui/traits/issue-91949-hangs-on-recursion.stderr
+++ b/tests/ui/traits/issue-91949-hangs-on-recursion.stderr
@@ -23,8 +23,7 @@ LL | impl> Iterator for IteratorOfWrapped {
    |                     |
    |                     unsatisfied trait bound introduced here
    = note: 256 redundant requirements hidden
-   = note: required for `IteratorOfWrapped<(), Map>, ...>>, ...>>` to implement `Iterator`
-   = note: the full type name has been written to '$TEST_BUILD_DIR/traits/issue-91949-hangs-on-recursion/issue-91949-hangs-on-recursion.long-type-hash.txt'
+   = note: required for `IteratorOfWrapped<(), Map>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:28:45: 28:48]>>` to implement `Iterator`
 
 error: aborting due to previous error; 1 warning emitted
 
diff --git a/tests/ui/traits/new-solver/normalize-unsize-rhs.rs b/tests/ui/traits/new-solver/normalize-unsize-rhs.rs
new file mode 100644
index 000000000000..a398ab4f2f2c
--- /dev/null
+++ b/tests/ui/traits/new-solver/normalize-unsize-rhs.rs
@@ -0,0 +1,23 @@
+// compile-flags: -Ztrait-solver=next
+// check-pass
+
+#![feature(trait_upcasting)]
+
+trait A {}
+trait B: A {}
+
+impl A for usize {}
+impl B for usize {}
+
+trait Mirror {
+    type Assoc: ?Sized;
+}
+
+impl Mirror for T {
+    type Assoc = T;
+}
+
+fn main() {
+    let x = Box::new(1usize) as Box<::Assoc>;
+    let y = x as Box<::Assoc>;
+}
diff --git a/tests/ui/traits/new-solver/trait-upcast-lhs-needs-normalization.rs b/tests/ui/traits/new-solver/trait-upcast-lhs-needs-normalization.rs
index 79114b93b78d..43cd773bf3ce 100644
--- a/tests/ui/traits/new-solver/trait-upcast-lhs-needs-normalization.rs
+++ b/tests/ui/traits/new-solver/trait-upcast-lhs-needs-normalization.rs
@@ -1,6 +1,8 @@
 // check-pass
 // compile-flags: -Ztrait-solver=next
 
+#![feature(trait_upcasting)]
+
 pub trait A {}
 pub trait B: A {}
 
diff --git a/tests/ui/type-alias-impl-trait/hidden_type_mismatch.rs b/tests/ui/type-alias-impl-trait/hidden_type_mismatch.rs
new file mode 100644
index 000000000000..12ce6b14e31d
--- /dev/null
+++ b/tests/ui/type-alias-impl-trait/hidden_type_mismatch.rs
@@ -0,0 +1,57 @@
+//! This test checks that we don't lose hidden types
+//! for *other* opaque types that we register and use
+//! to prove bounds while checking that a hidden type
+//! satisfies its opaque type's bounds.
+
+#![feature(trivial_bounds, type_alias_impl_trait)]
+#![allow(trivial_bounds)]
+
+mod sus {
+    use super::*;
+    pub type Sep = impl Sized + std::fmt::Display;
+    //~^ ERROR: concrete type differs from previous defining opaque type use
+    pub fn mk_sep() -> Sep {
+        String::from("hello")
+    }
+
+    pub trait Proj {
+        type Assoc;
+    }
+    impl Proj for () {
+        type Assoc = sus::Sep;
+    }
+
+    pub struct Bar {
+        pub inner: ::Assoc,
+        pub _marker: T,
+    }
+    impl Clone for Bar {
+        fn clone(&self) -> Self {
+            todo!()
+        }
+    }
+    impl + Copy> Copy for Bar {}
+    // This allows producing `Tait`s via `From`, even though
+    // `define_tait` is not actually callable, and thus assumed
+    // `Bar<()>: Copy` even though it isn't.
+    pub type Tait = impl Copy + From> + Into>;
+    pub fn define_tait() -> Tait
+    where
+        // this proves `Bar<()>: Copy`, but `define_tait` is
+        // now uncallable
+        (): Proj,
+    {
+        Bar { inner: 1i32, _marker: () }
+    }
+}
+
+fn copy_tait(x: sus::Tait) -> (sus::Tait, sus::Tait) {
+    (x, x)
+}
+
+fn main() {
+    let bar = sus::Bar { inner: sus::mk_sep(), _marker: () };
+    let (y, z) = copy_tait(bar.into()); // copy a string
+    drop(y.into()); // drop one instance
+    println!("{}", z.into().inner); // print the other
+}
diff --git a/tests/ui/type-alias-impl-trait/hidden_type_mismatch.stderr b/tests/ui/type-alias-impl-trait/hidden_type_mismatch.stderr
new file mode 100644
index 000000000000..85e8a600ce37
--- /dev/null
+++ b/tests/ui/type-alias-impl-trait/hidden_type_mismatch.stderr
@@ -0,0 +1,14 @@
+error: concrete type differs from previous defining opaque type use
+  --> $DIR/hidden_type_mismatch.rs:11:20
+   |
+LL |     pub type Sep = impl Sized + std::fmt::Display;
+   |                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `i32`, got `String`
+   |
+note: previous use here
+  --> $DIR/hidden_type_mismatch.rs:37:21
+   |
+LL |     pub type Tait = impl Copy + From> + Into>;
+   |                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/tests/ui/issues/issue-83190.rs b/tests/ui/type-alias-impl-trait/nested-rpit-with-lifetimes.rs
similarity index 100%
rename from tests/ui/issues/issue-83190.rs
rename to tests/ui/type-alias-impl-trait/nested-rpit-with-lifetimes.rs
index da931c3edaf6..11b659eec973 100644
--- a/tests/ui/issues/issue-83190.rs
+++ b/tests/ui/type-alias-impl-trait/nested-rpit-with-lifetimes.rs
@@ -1,7 +1,7 @@
-// check-pass
-
 // Regression test for issue #83190, triggering an ICE in borrowck.
 
+// check-pass
+
 pub trait Any {}
 impl Any for T {}
 
diff --git a/tests/ui/typeck/apit-with-error-type-in-sig.rs b/tests/ui/typeck/apit-with-error-type-in-sig.rs
new file mode 100644
index 000000000000..35990fc16c89
--- /dev/null
+++ b/tests/ui/typeck/apit-with-error-type-in-sig.rs
@@ -0,0 +1,8 @@
+type Foo = Bar;
+//~^ ERROR cannot find type `Bar` in this scope
+
+fn check(f: impl FnOnce(Foo), val: Foo) {
+    f(val);
+}
+
+fn main() {}
diff --git a/tests/ui/typeck/apit-with-error-type-in-sig.stderr b/tests/ui/typeck/apit-with-error-type-in-sig.stderr
new file mode 100644
index 000000000000..49b2eac1b65e
--- /dev/null
+++ b/tests/ui/typeck/apit-with-error-type-in-sig.stderr
@@ -0,0 +1,9 @@
+error[E0412]: cannot find type `Bar` in this scope
+  --> $DIR/apit-with-error-type-in-sig.rs:1:12
+   |
+LL | type Foo = Bar;
+   |            ^^^ not found in this scope
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0412`.
diff --git a/tests/ui/typeck/explain_clone_autoref.rs b/tests/ui/typeck/explain_clone_autoref.rs
index 4d21574700ad..88aaac469b21 100644
--- a/tests/ui/typeck/explain_clone_autoref.rs
+++ b/tests/ui/typeck/explain_clone_autoref.rs
@@ -11,3 +11,119 @@ fn clone_thing(nc: &NotClone) -> NotClone {
     //~| NOTE `NotClone` does not implement `Clone`, so `&NotClone` was cloned instead
     //~| NOTE expected `NotClone`, found `&NotClone`
 }
+
+fn clone_thing2(nc: &NotClone) -> NotClone {
+    let nc: NotClone = nc.clone();
+    //~^ ERROR mismatched type
+    //~| NOTE expected due to this
+    //~| NOTE `NotClone` does not implement `Clone`, so `&NotClone` was cloned instead
+    //~| NOTE expected `NotClone`, found `&NotClone`
+    nc
+}
+
+fn clone_thing3(nc: &NotClone) -> NotClone {
+    //~^ NOTE expected `NotClone` because of return type
+    let nc = nc.clone();
+    //~^ NOTE `NotClone` does not implement `Clone`, so `&NotClone` was cloned instead
+    nc
+    //~^ ERROR mismatched type
+    //~| NOTE expected `NotClone`, found `&NotClone`
+}
+
+fn clone_thing4(nc: &NotClone) -> NotClone {
+    //~^ NOTE expected `NotClone` because of return type
+    let nc = nc.clone();
+    //~^ NOTE `NotClone` does not implement `Clone`, so `&NotClone` was cloned instead
+    let nc2 = nc;
+    nc2
+    //~^ ERROR mismatched type
+    //~| NOTE expected `NotClone`, found `&NotClone`
+}
+
+impl NotClone {
+    fn other_fn(&self) {}
+    fn get_ref_notclone(&self) -> &Self {
+        self
+    }
+}
+
+fn clone_thing5(nc: &NotClone) -> NotClone {
+    //~^ NOTE expected `NotClone` because of return type
+    let nc = nc.clone();
+    //~^ NOTE `NotClone` does not implement `Clone`, so `&NotClone` was cloned instead
+    let nc2 = nc;
+    nc2.other_fn();
+    let nc3 = nc2;
+    nc3
+    //~^ ERROR mismatched type
+    //~| NOTE expected `NotClone`, found `&NotClone`
+}
+
+fn clone_thing6(nc: &NotClone) -> NotClone {
+    //~^ NOTE expected `NotClone` because of return type
+    let (ret, _) = (nc.clone(), 1);
+    //~^ NOTE `NotClone` does not implement `Clone`, so `&NotClone` was cloned instead
+    let _ = nc.clone();
+    ret
+    //~^ ERROR mismatched type
+    //~| NOTE expected `NotClone`, found `&NotClone`
+}
+
+fn clone_thing7(nc: Vec<&NotClone>) -> NotClone {
+    //~^ NOTE expected `NotClone` because of return type
+    let ret = nc[0].clone();
+    //~^ NOTE `NotClone` does not implement `Clone`, so `&NotClone` was cloned instead
+    ret
+    //~^ ERROR mismatched type
+    //~| NOTE expected `NotClone`, found `&NotClone`
+}
+
+fn clone_thing8(nc: &NotClone) -> NotClone {
+    //~^ NOTE expected `NotClone` because of return type
+    let ret = {
+        let a = nc.clone();
+        //~^ NOTE `NotClone` does not implement `Clone`, so `&NotClone` was cloned instead
+        a
+    };
+    ret
+    //~^ ERROR mismatched type
+    //~| NOTE expected `NotClone`, found `&NotClone`
+}
+
+fn clone_thing9(nc: &NotClone) -> NotClone {
+    //~^ NOTE expected `NotClone` because of return type
+    let cl = || nc.clone();
+    //~^ NOTE `NotClone` does not implement `Clone`, so `&NotClone` was cloned instead
+    let ret = cl();
+    ret
+    //~^ ERROR mismatched type
+    //~| NOTE expected `NotClone`, found `&NotClone`
+}
+
+fn clone_thing10(nc: &NotClone) -> (NotClone, NotClone) {
+    let (a, b) = {
+        let a = nc.clone();
+        //~^ NOTE `NotClone` does not implement `Clone`, so `&NotClone` was cloned instead
+        (a, nc.clone())
+        //~^ NOTE `NotClone` does not implement `Clone`, so `&NotClone` was cloned instead
+    };
+    (a, b)
+    //~^ ERROR mismatched type
+    //~| ERROR mismatched type
+    //~| NOTE expected `NotClone`, found `&NotClone`
+    //~| NOTE expected `NotClone`, found `&NotClone`
+}
+
+fn clone_thing11(nc: &NotClone) -> NotClone {
+    //~^ NOTE expected `NotClone` because of return type
+    let a = {
+        let nothing = nc.clone();
+        let a = nc.clone();
+        //~^ NOTE `NotClone` does not implement `Clone`, so `&NotClone` was cloned instead
+        let nothing = nc.clone();
+        a
+    };
+    a
+    //~^ ERROR mismatched type
+    //~| NOTE expected `NotClone`, found `&NotClone`
+}
diff --git a/tests/ui/typeck/explain_clone_autoref.stderr b/tests/ui/typeck/explain_clone_autoref.stderr
index 38cb7fe55184..40d3df301190 100644
--- a/tests/ui/typeck/explain_clone_autoref.stderr
+++ b/tests/ui/typeck/explain_clone_autoref.stderr
@@ -18,6 +18,219 @@ LL + #[derive(Clone)]
 LL | struct NotClone;
    |
 
-error: aborting due to previous error
+error[E0308]: mismatched types
+  --> $DIR/explain_clone_autoref.rs:16:24
+   |
+LL |     let nc: NotClone = nc.clone();
+   |             --------   ^^^^^^^^^^ expected `NotClone`, found `&NotClone`
+   |             |
+   |             expected due to this
+   |
+note: `NotClone` does not implement `Clone`, so `&NotClone` was cloned instead
+  --> $DIR/explain_clone_autoref.rs:16:24
+   |
+LL |     let nc: NotClone = nc.clone();
+   |                        ^^
+help: consider annotating `NotClone` with `#[derive(Clone)]`
+   |
+LL + #[derive(Clone)]
+LL | struct NotClone;
+   |
+
+error[E0308]: mismatched types
+  --> $DIR/explain_clone_autoref.rs:28:5
+   |
+LL | fn clone_thing3(nc: &NotClone) -> NotClone {
+   |                                   -------- expected `NotClone` because of return type
+...
+LL |     nc
+   |     ^^ expected `NotClone`, found `&NotClone`
+   |
+note: `NotClone` does not implement `Clone`, so `&NotClone` was cloned instead
+  --> $DIR/explain_clone_autoref.rs:26:14
+   |
+LL |     let nc = nc.clone();
+   |              ^^
+help: consider annotating `NotClone` with `#[derive(Clone)]`
+   |
+LL + #[derive(Clone)]
+LL | struct NotClone;
+   |
+
+error[E0308]: mismatched types
+  --> $DIR/explain_clone_autoref.rs:38:5
+   |
+LL | fn clone_thing4(nc: &NotClone) -> NotClone {
+   |                                   -------- expected `NotClone` because of return type
+...
+LL |     nc2
+   |     ^^^ expected `NotClone`, found `&NotClone`
+   |
+note: `NotClone` does not implement `Clone`, so `&NotClone` was cloned instead
+  --> $DIR/explain_clone_autoref.rs:35:14
+   |
+LL |     let nc = nc.clone();
+   |              ^^
+help: consider annotating `NotClone` with `#[derive(Clone)]`
+   |
+LL + #[derive(Clone)]
+LL | struct NotClone;
+   |
+
+error[E0308]: mismatched types
+  --> $DIR/explain_clone_autoref.rs:57:5
+   |
+LL | fn clone_thing5(nc: &NotClone) -> NotClone {
+   |                                   -------- expected `NotClone` because of return type
+...
+LL |     nc3
+   |     ^^^ expected `NotClone`, found `&NotClone`
+   |
+note: `NotClone` does not implement `Clone`, so `&NotClone` was cloned instead
+  --> $DIR/explain_clone_autoref.rs:52:14
+   |
+LL |     let nc = nc.clone();
+   |              ^^
+help: consider annotating `NotClone` with `#[derive(Clone)]`
+   |
+LL + #[derive(Clone)]
+LL | struct NotClone;
+   |
+
+error[E0308]: mismatched types
+  --> $DIR/explain_clone_autoref.rs:67:5
+   |
+LL | fn clone_thing6(nc: &NotClone) -> NotClone {
+   |                                   -------- expected `NotClone` because of return type
+...
+LL |     ret
+   |     ^^^ expected `NotClone`, found `&NotClone`
+   |
+note: `NotClone` does not implement `Clone`, so `&NotClone` was cloned instead
+  --> $DIR/explain_clone_autoref.rs:64:21
+   |
+LL |     let (ret, _) = (nc.clone(), 1);
+   |                     ^^
+help: consider annotating `NotClone` with `#[derive(Clone)]`
+   |
+LL + #[derive(Clone)]
+LL | struct NotClone;
+   |
+
+error[E0308]: mismatched types
+  --> $DIR/explain_clone_autoref.rs:76:5
+   |
+LL | fn clone_thing7(nc: Vec<&NotClone>) -> NotClone {
+   |                                        -------- expected `NotClone` because of return type
+...
+LL |     ret
+   |     ^^^ expected `NotClone`, found `&NotClone`
+   |
+note: `NotClone` does not implement `Clone`, so `&NotClone` was cloned instead
+  --> $DIR/explain_clone_autoref.rs:74:15
+   |
+LL |     let ret = nc[0].clone();
+   |               ^^^^^
+help: consider annotating `NotClone` with `#[derive(Clone)]`
+   |
+LL + #[derive(Clone)]
+LL | struct NotClone;
+   |
+
+error[E0308]: mismatched types
+  --> $DIR/explain_clone_autoref.rs:88:5
+   |
+LL | fn clone_thing8(nc: &NotClone) -> NotClone {
+   |                                   -------- expected `NotClone` because of return type
+...
+LL |     ret
+   |     ^^^ expected `NotClone`, found `&NotClone`
+   |
+note: `NotClone` does not implement `Clone`, so `&NotClone` was cloned instead
+  --> $DIR/explain_clone_autoref.rs:84:17
+   |
+LL |         let a = nc.clone();
+   |                 ^^
+help: consider annotating `NotClone` with `#[derive(Clone)]`
+   |
+LL + #[derive(Clone)]
+LL | struct NotClone;
+   |
+
+error[E0308]: mismatched types
+  --> $DIR/explain_clone_autoref.rs:98:5
+   |
+LL | fn clone_thing9(nc: &NotClone) -> NotClone {
+   |                                   -------- expected `NotClone` because of return type
+...
+LL |     ret
+   |     ^^^ expected `NotClone`, found `&NotClone`
+   |
+note: `NotClone` does not implement `Clone`, so `&NotClone` was cloned instead
+  --> $DIR/explain_clone_autoref.rs:95:17
+   |
+LL |     let cl = || nc.clone();
+   |                 ^^
+help: consider annotating `NotClone` with `#[derive(Clone)]`
+   |
+LL + #[derive(Clone)]
+LL | struct NotClone;
+   |
+
+error[E0308]: mismatched types
+  --> $DIR/explain_clone_autoref.rs:110:6
+   |
+LL |     (a, b)
+   |      ^ expected `NotClone`, found `&NotClone`
+   |
+note: `NotClone` does not implement `Clone`, so `&NotClone` was cloned instead
+  --> $DIR/explain_clone_autoref.rs:105:17
+   |
+LL |         let a = nc.clone();
+   |                 ^^
+help: consider annotating `NotClone` with `#[derive(Clone)]`
+   |
+LL + #[derive(Clone)]
+LL | struct NotClone;
+   |
+
+error[E0308]: mismatched types
+  --> $DIR/explain_clone_autoref.rs:110:9
+   |
+LL |     (a, b)
+   |         ^ expected `NotClone`, found `&NotClone`
+   |
+note: `NotClone` does not implement `Clone`, so `&NotClone` was cloned instead
+  --> $DIR/explain_clone_autoref.rs:107:13
+   |
+LL |         (a, nc.clone())
+   |             ^^
+help: consider annotating `NotClone` with `#[derive(Clone)]`
+   |
+LL + #[derive(Clone)]
+LL | struct NotClone;
+   |
+
+error[E0308]: mismatched types
+  --> $DIR/explain_clone_autoref.rs:126:5
+   |
+LL | fn clone_thing11(nc: &NotClone) -> NotClone {
+   |                                    -------- expected `NotClone` because of return type
+...
+LL |     a
+   |     ^ expected `NotClone`, found `&NotClone`
+   |
+note: `NotClone` does not implement `Clone`, so `&NotClone` was cloned instead
+  --> $DIR/explain_clone_autoref.rs:121:17
+   |
+LL |         let a = nc.clone();
+   |                 ^^
+help: consider annotating `NotClone` with `#[derive(Clone)]`
+   |
+LL + #[derive(Clone)]
+LL | struct NotClone;
+   |
+
+error: aborting due to 12 previous errors
 
 For more information about this error, try `rustc --explain E0308`.