diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index dacf929278ab9..32c18cab09902 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -326,7 +326,7 @@ jobs: NO_DEBUG_ASSERTIONS: 1 NO_OVERFLOW_CHECKS: 1 DIST_REQUIRE_ALL_TOOLS: 1 - os: macos-12-xl + os: macos-latest - name: dist-apple-various env: SCRIPT: "./x.py dist bootstrap --include-default-paths --host='' --target=aarch64-apple-ios,x86_64-apple-ios,aarch64-apple-ios-sim" @@ -337,7 +337,7 @@ jobs: NO_LLVM_ASSERTIONS: 1 NO_DEBUG_ASSERTIONS: 1 NO_OVERFLOW_CHECKS: 1 - os: macos-12-xl + os: macos-latest - name: dist-x86_64-apple-alt env: SCRIPT: "./x.py dist bootstrap --include-default-paths" @@ -348,7 +348,7 @@ jobs: NO_LLVM_ASSERTIONS: 1 NO_DEBUG_ASSERTIONS: 1 NO_OVERFLOW_CHECKS: 1 - os: macos-12-xl + os: macos-latest - name: x86_64-apple-1 env: SCRIPT: "./x.py --stage 2 test --exclude tests/ui --exclude tests/rustdoc --exclude tests/run-make-fulldeps" @@ -359,7 +359,7 @@ jobs: NO_LLVM_ASSERTIONS: 1 NO_DEBUG_ASSERTIONS: 1 NO_OVERFLOW_CHECKS: 1 - os: macos-12-xl + os: macos-latest - name: x86_64-apple-2 env: SCRIPT: "./x.py --stage 2 test tests/ui tests/rustdoc tests/run-make-fulldeps" @@ -370,7 +370,7 @@ jobs: NO_LLVM_ASSERTIONS: 1 NO_DEBUG_ASSERTIONS: 1 NO_OVERFLOW_CHECKS: 1 - os: macos-12-xl + os: macos-latest - name: dist-aarch64-apple env: SCRIPT: "./x.py dist bootstrap --include-default-paths --stage 2" @@ -385,7 +385,7 @@ jobs: NO_OVERFLOW_CHECKS: 1 DIST_REQUIRE_ALL_TOOLS: 1 JEMALLOC_SYS_WITH_LG_PAGE: 14 - os: macos-12-xl + os: macos-latest - name: x86_64-msvc-1 env: RUST_CONFIGURE_ARGS: "--build=x86_64-pc-windows-msvc --enable-profiler" diff --git a/Cargo.lock b/Cargo.lock index 696727c106bf3..06a2a36f4552b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1170,13 +1170,13 @@ dependencies = [ [[package]] name = "errno" -version = "0.2.8" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f639046355ee4f37944e44f60642c6f3a7efa3cf6b78c78a0d989a8ce6c396a1" +checksum = "4bcfec3a70f97c962c307b2d2c56e358cf1d00b558d74262b5f929ee8cc7e73a" dependencies = [ "errno-dragonfly", "libc", - "winapi", + "windows-sys 0.48.0", ] [[package]] @@ -1831,14 +1831,14 @@ dependencies = [ [[package]] name = "is-terminal" -version = "0.4.4" +version = "0.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21b6b32576413a8e69b90e952e4a026476040d81017b80445deda5f2d3921857" +checksum = "adcf93614601c8129ddf72e2d5633df827ba6551541c6d8c59520a371475be1f" dependencies = [ "hermit-abi 0.3.0", "io-lifetimes", "rustix", - "windows-sys 0.45.0", + "windows-sys 0.48.0", ] [[package]] @@ -1937,9 +1937,9 @@ checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" [[package]] name = "libc" -version = "0.2.140" +version = "0.2.142" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99227334921fae1a979cf0bfdfcc6b3e5ce376ef57e16fb6fb3ea2ed6095f80c" +checksum = "6a987beff54b60ffa6d51982e1aa1146bc42f19bd26be28b0586f252fccf5317" dependencies = [ "rustc-std-workspace-core", ] @@ -2025,9 +2025,9 @@ dependencies = [ [[package]] name = "linux-raw-sys" -version = "0.1.4" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f051f77a7c8e6957c0696eac88f26b0117e54f52d3fc682ab19397a8812846a4" +checksum = "36eb31c1778188ae1e64398743890d0877fef36d11521ac60406b42016e8c2cf" [[package]] name = "litemap" @@ -4350,16 +4350,16 @@ dependencies = [ [[package]] name = "rustix" -version = "0.36.5" +version = "0.37.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3807b5d10909833d3e9acd1eb5fb988f79376ff10fce42937de71a449c4c588" +checksum = "2aae838e49b3d63e9274e1c01833cc8139d3fec468c3b84688c628f44b1ae11d" dependencies = [ "bitflags", "errno", "io-lifetimes", "libc", "linux-raw-sys", - "windows-sys 0.42.0", + "windows-sys 0.45.0", ] [[package]] @@ -4791,12 +4791,12 @@ dependencies = [ [[package]] name = "terminal_size" -version = "0.2.3" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb20089a8ba2b69debd491f8d2d023761cbf196e999218c591fa1e7e15a21907" +checksum = "8e6bf6f19e9f8ed8d4048dc22981458ebcf406d67e94cd422e5ecd73d63b3237" dependencies = [ "rustix", - "windows-sys 0.42.0", + "windows-sys 0.48.0", ] [[package]] @@ -5513,6 +5513,15 @@ dependencies = [ "windows-targets 0.42.2", ] +[[package]] +name = "windows-sys" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" +dependencies = [ + "windows-targets 0.48.0", +] + [[package]] name = "windows-targets" version = "0.42.2" diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs index 6863100d9bac0..7a0a7da969572 100644 --- a/compiler/rustc_ast_lowering/src/expr.rs +++ b/compiler/rustc_ast_lowering/src/expr.rs @@ -858,13 +858,8 @@ impl<'hir> LoweringContext<'_, 'hir> { let awaitee_arm = self.arm(awaitee_pat, loop_expr); // `match ::std::future::IntoFuture::into_future() { ... }` - let into_future_span = self.mark_span_with_reason( - DesugaringKind::Await, - dot_await_span, - self.allow_into_future.clone(), - ); let into_future_expr = self.expr_call_lang_item_fn( - into_future_span, + span, hir::LangItem::IntoFutureIntoFuture, arena_vec![self; expr], Some(expr_hir_id), diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index a9fd8db281b58..3d154a93fb2da 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -83,7 +83,6 @@ impl<'a, 'hir> ItemLowerer<'a, 'hir> { impl_trait_bounds: Vec::new(), allow_try_trait: Some([sym::try_trait_v2, sym::yeet_desugar_details][..].into()), allow_gen_future: Some([sym::gen_future, sym::closure_track_caller][..].into()), - allow_into_future: Some([sym::into_future][..].into()), generics_def_id_map: Default::default(), }; lctx.with_hir_id_owner(owner, |lctx| f(lctx)); diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index d07355a415402..b5b28bf8e31e5 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -136,7 +136,6 @@ struct LoweringContext<'a, 'hir> { allow_try_trait: Option>, allow_gen_future: Option>, - allow_into_future: Option>, /// Mapping from generics `def_id`s to TAIT generics `def_id`s. /// For each captured lifetime (e.g., 'a), we create a new lifetime parameter that is a generic diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs index 8dd03aaa72d16..5db0f72919d03 100644 --- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs @@ -702,7 +702,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { .copied() .find_map(find_fn_kind_from_did), ty::Alias(ty::Opaque, ty::AliasTy { def_id, substs, .. }) => tcx - .bound_explicit_item_bounds(def_id) + .explicit_item_bounds(def_id) .subst_iter_copied(tcx, substs) .find_map(find_fn_kind_from_did), ty::Closure(_, substs) => match substs.as_closure().kind() { diff --git a/compiler/rustc_builtin_macros/messages.ftl b/compiler/rustc_builtin_macros/messages.ftl index fca6012a408c1..74049406426ed 100644 --- a/compiler/rustc_builtin_macros/messages.ftl +++ b/compiler/rustc_builtin_macros/messages.ftl @@ -149,6 +149,25 @@ builtin_macros_format_pos_mismatch = {$n} positional {$n -> [one] argument *[more] arguments } in format string, but {$desc} + builtin_macros_offset_of_expected_field = expected field builtin_macros_offset_of_expected_two_args = expected 2 arguments + +builtin_macros_test_case_non_item = `#[test_case]` attribute is only allowed on items + +builtin_macros_test_bad_fn = {$kind} functions cannot be used for tests + .label = `{$kind}` because of this + +builtin_macros_asm_explicit_register_name = explicit register arguments cannot have names + +builtin_macros_asm_mutually_exclusive = the `{$opt1}` and `{$opt2}` options are mutually exclusive + +builtin_macros_asm_pure_combine = the `pure` option must be combined with either `nomem` or `readonly` + +builtin_macros_asm_pure_no_output = asm with the `pure` option must have at least one output + +builtin_macros_asm_modifier_invalid = asm template modifier must be a single character + +builtin_macros_test_runner_invalid = `test_runner` argument must be a path +builtin_macros_test_runner_nargs = `#![test_runner(..)]` accepts exactly 1 argument diff --git a/compiler/rustc_builtin_macros/src/asm.rs b/compiler/rustc_builtin_macros/src/asm.rs index 8c1579baacb08..bcdd58a090162 100644 --- a/compiler/rustc_builtin_macros/src/asm.rs +++ b/compiler/rustc_builtin_macros/src/asm.rs @@ -15,6 +15,8 @@ use rustc_span::{InnerSpan, Span}; use rustc_target::asm::InlineAsmArch; use smallvec::smallvec; +use crate::errors; + pub struct AsmArgs { pub templates: Vec>, pub operands: Vec<(ast::InlineAsmOperand, Span)>, @@ -205,7 +207,7 @@ pub fn parse_asm_args<'a>( // of the argument available. if explicit_reg { if name.is_some() { - diag.struct_span_err(span, "explicit register arguments cannot have names").emit(); + diag.emit_err(errors::AsmExplicitRegisterName { span }); } args.reg_args.insert(slot); } else if let Some(name) = name { @@ -240,25 +242,19 @@ pub fn parse_asm_args<'a>( && args.options.contains(ast::InlineAsmOptions::READONLY) { let spans = args.options_spans.clone(); - diag.struct_span_err(spans, "the `nomem` and `readonly` options are mutually exclusive") - .emit(); + diag.emit_err(errors::AsmMutuallyExclusive { spans, opt1: "nomem", opt2: "readonly" }); } if args.options.contains(ast::InlineAsmOptions::PURE) && args.options.contains(ast::InlineAsmOptions::NORETURN) { let spans = args.options_spans.clone(); - diag.struct_span_err(spans, "the `pure` and `noreturn` options are mutually exclusive") - .emit(); + diag.emit_err(errors::AsmMutuallyExclusive { spans, opt1: "pure", opt2: "noreturn" }); } if args.options.contains(ast::InlineAsmOptions::PURE) && !args.options.intersects(ast::InlineAsmOptions::NOMEM | ast::InlineAsmOptions::READONLY) { let spans = args.options_spans.clone(); - diag.struct_span_err( - spans, - "the `pure` option must be combined with either `nomem` or `readonly`", - ) - .emit(); + diag.emit_err(errors::AsmPureCombine { spans }); } let mut have_real_output = false; @@ -285,11 +281,7 @@ pub fn parse_asm_args<'a>( } } if args.options.contains(ast::InlineAsmOptions::PURE) && !have_real_output { - diag.struct_span_err( - args.options_spans.clone(), - "asm with the `pure` option must have at least one output", - ) - .emit(); + diag.emit_err(errors::AsmPureNoOutput { spans: args.options_spans.clone() }); } if args.options.contains(ast::InlineAsmOptions::NORETURN) && !outputs_sp.is_empty() { let err = diag @@ -705,11 +697,7 @@ fn expand_preparsed_asm(ecx: &mut ExtCtxt<'_>, args: AsmArgs) -> Option, + pub(crate) opt1: &'static str, + pub(crate) opt2: &'static str, +} + +#[derive(Diagnostic)] +#[diag(builtin_macros_asm_pure_combine)] +pub(crate) struct AsmPureCombine { + #[primary_span] + pub(crate) spans: Vec, +} + +#[derive(Diagnostic)] +#[diag(builtin_macros_asm_pure_no_output)] +pub(crate) struct AsmPureNoOutput { + #[primary_span] + pub(crate) spans: Vec, +} + +#[derive(Diagnostic)] +#[diag(builtin_macros_asm_modifier_invalid)] +pub(crate) struct AsmModifierInvalid { + #[primary_span] + pub(crate) span: Span, +} + +#[derive(Diagnostic)] +#[diag(builtin_macros_test_runner_invalid)] +pub(crate) struct TestRunnerInvalid { + #[primary_span] + pub(crate) span: Span, +} + +#[derive(Diagnostic)] +#[diag(builtin_macros_test_runner_nargs)] +pub(crate) struct TestRunnerNargs { + #[primary_span] + pub(crate) span: Span, +} diff --git a/compiler/rustc_builtin_macros/src/test.rs b/compiler/rustc_builtin_macros/src/test.rs index 79d8be2484b59..49ee276af4e6f 100644 --- a/compiler/rustc_builtin_macros/src/test.rs +++ b/compiler/rustc_builtin_macros/src/test.rs @@ -1,3 +1,4 @@ +use crate::errors; /// The expansion from a test function to the appropriate test struct for libtest /// Ideally, this code would be in libtest but for efficiency and error messages it lives here. use crate::util::{check_builtin_macro_attribute, warn_on_duplicate_attribute}; @@ -40,12 +41,7 @@ pub fn expand_test_case( unreachable!() }, _ => { - ecx.struct_span_err( - anno_item.span(), - "`#[test_case]` attribute is only allowed on items", - ) - .emit(); - + ecx.emit_err(errors::TestCaseNonItem { span: anno_item.span() }); return vec![]; } }; @@ -533,15 +529,11 @@ fn has_test_signature(cx: &ExtCtxt<'_>, i: &ast::Item) -> bool { match &i.kind { ast::ItemKind::Fn(box ast::Fn { sig, generics, .. }) => { if let ast::Unsafe::Yes(span) = sig.header.unsafety { - sd.struct_span_err(i.span, "unsafe functions cannot be used for tests") - .span_label(span, "`unsafe` because of this") - .emit(); + sd.emit_err(errors::TestBadFn { span: i.span, cause: span, kind: "unsafe" }); return false; } if let ast::Async::Yes { span, .. } = sig.header.asyncness { - sd.struct_span_err(i.span, "async functions cannot be used for tests") - .span_label(span, "`async` because of this") - .emit(); + sd.emit_err(errors::TestBadFn { span: i.span, cause: span, kind: "async" }); return false; } diff --git a/compiler/rustc_builtin_macros/src/test_harness.rs b/compiler/rustc_builtin_macros/src/test_harness.rs index 80f497333a632..be4ba66c082aa 100644 --- a/compiler/rustc_builtin_macros/src/test_harness.rs +++ b/compiler/rustc_builtin_macros/src/test_harness.rs @@ -19,6 +19,8 @@ use tracing::debug; use std::{iter, mem}; +use crate::errors; + #[derive(Clone)] struct Test { span: Span, @@ -385,11 +387,11 @@ fn get_test_runner(sd: &rustc_errors::Handler, krate: &ast::Crate) -> Option match single.meta_item() { Some(meta_item) if meta_item.is_word() => return Some(meta_item.path.clone()), _ => { - sd.struct_span_err(span, "`test_runner` argument must be a path").emit(); + sd.emit_err(errors::TestRunnerInvalid { span }); } }, _ => { - sd.struct_span_err(span, "`#![test_runner(..)]` accepts exactly 1 argument").emit(); + sd.emit_err(errors::TestRunnerNargs { span }); } } None diff --git a/compiler/rustc_codegen_cranelift/src/abi/mod.rs b/compiler/rustc_codegen_cranelift/src/abi/mod.rs index 91c085d3d6986..0b4d4ecf2e46d 100644 --- a/compiler/rustc_codegen_cranelift/src/abi/mod.rs +++ b/compiler/rustc_codegen_cranelift/src/abi/mod.rs @@ -70,7 +70,7 @@ pub(crate) fn get_function_sig<'tcx>( default_call_conv: CallConv, inst: Instance<'tcx>, ) -> Signature { - assert!(!inst.substs.needs_infer()); + assert!(!inst.substs.has_infer()); clif_sig_from_fn_abi( tcx, default_call_conv, diff --git a/compiler/rustc_codegen_cranelift/src/base.rs b/compiler/rustc_codegen_cranelift/src/base.rs index 98ba23c6f5799..c181c73e4be94 100644 --- a/compiler/rustc_codegen_cranelift/src/base.rs +++ b/compiler/rustc_codegen_cranelift/src/base.rs @@ -28,7 +28,7 @@ pub(crate) fn codegen_fn<'tcx>( module: &mut dyn Module, instance: Instance<'tcx>, ) -> CodegenedFunction { - debug_assert!(!instance.substs.needs_infer()); + debug_assert!(!instance.substs.has_infer()); let symbol_name = tcx.symbol_name(instance).name.to_string(); let _timer = tcx.prof.generic_activity_with_arg("codegen fn", &*symbol_name); diff --git a/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs b/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs index 03f2a65fccad2..90b36c6111429 100644 --- a/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs +++ b/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs @@ -534,7 +534,7 @@ fn codegen_regular_intrinsic_call<'tcx>( // The only difference between offset and arith_offset is regarding UB. Because Cranelift // doesn't have UB both are codegen'ed the same way - sym::offset | sym::arith_offset => { + sym::arith_offset => { intrinsic_args!(fx, args => (base, offset); intrinsic); let offset = offset.load_scalar(fx); diff --git a/compiler/rustc_codegen_gcc/src/asm.rs b/compiler/rustc_codegen_gcc/src/asm.rs index 65de02b356712..738cdb6f119f2 100644 --- a/compiler/rustc_codegen_gcc/src/asm.rs +++ b/compiler/rustc_codegen_gcc/src/asm.rs @@ -593,6 +593,8 @@ fn reg_to_gcc(reg: InlineAsmRegOrRegClass) -> ConstraintOrRegister { InlineAsmRegClass::Bpf(BpfInlineAsmRegClass::reg) => "r", InlineAsmRegClass::Bpf(BpfInlineAsmRegClass::wreg) => "w", InlineAsmRegClass::Hexagon(HexagonInlineAsmRegClass::reg) => "r", + InlineAsmRegClass::LoongArch(LoongArchInlineAsmRegClass::reg) => "r", + InlineAsmRegClass::LoongArch(LoongArchInlineAsmRegClass::freg) => "f", InlineAsmRegClass::M68k(M68kInlineAsmRegClass::reg) => "r", InlineAsmRegClass::M68k(M68kInlineAsmRegClass::reg_addr) => "a", InlineAsmRegClass::M68k(M68kInlineAsmRegClass::reg_data) => "d", @@ -667,6 +669,8 @@ fn dummy_output_type<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, reg: InlineAsmRegCl InlineAsmRegClass::Avr(_) => unimplemented!(), InlineAsmRegClass::Bpf(_) => unimplemented!(), InlineAsmRegClass::Hexagon(HexagonInlineAsmRegClass::reg) => cx.type_i32(), + InlineAsmRegClass::LoongArch(LoongArchInlineAsmRegClass::reg) => cx.type_i32(), + InlineAsmRegClass::LoongArch(LoongArchInlineAsmRegClass::freg) => cx.type_f32(), InlineAsmRegClass::M68k(M68kInlineAsmRegClass::reg) => cx.type_i32(), InlineAsmRegClass::M68k(M68kInlineAsmRegClass::reg_addr) => cx.type_i32(), InlineAsmRegClass::M68k(M68kInlineAsmRegClass::reg_data) => cx.type_i32(), @@ -804,6 +808,7 @@ fn modifier_to_gcc(arch: InlineAsmArch, reg: InlineAsmRegClass, modifier: Option } } InlineAsmRegClass::Hexagon(_) => None, + InlineAsmRegClass::LoongArch(_) => None, InlineAsmRegClass::Mips(_) => None, InlineAsmRegClass::Nvptx(_) => None, InlineAsmRegClass::PowerPC(_) => None, diff --git a/compiler/rustc_codegen_gcc/src/callee.rs b/compiler/rustc_codegen_gcc/src/callee.rs index ba1e86562089e..433b2585f82a8 100644 --- a/compiler/rustc_codegen_gcc/src/callee.rs +++ b/compiler/rustc_codegen_gcc/src/callee.rs @@ -17,7 +17,7 @@ use crate::context::CodegenCx; pub fn get_fn<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, instance: Instance<'tcx>) -> Function<'gcc> { let tcx = cx.tcx(); - assert!(!instance.substs.needs_infer()); + assert!(!instance.substs.has_infer()); assert!(!instance.substs.has_escaping_bound_vars()); let sym = tcx.symbol_name(instance).name; diff --git a/compiler/rustc_codegen_gcc/src/mono_item.rs b/compiler/rustc_codegen_gcc/src/mono_item.rs index c1f6340866cac..342b830cedb12 100644 --- a/compiler/rustc_codegen_gcc/src/mono_item.rs +++ b/compiler/rustc_codegen_gcc/src/mono_item.rs @@ -31,7 +31,7 @@ impl<'gcc, 'tcx> PreDefineMethods<'tcx> for CodegenCx<'gcc, 'tcx> { #[cfg_attr(not(feature="master"), allow(unused_variables))] fn predefine_fn(&self, instance: Instance<'tcx>, linkage: Linkage, visibility: Visibility, symbol_name: &str) { - assert!(!instance.substs.needs_infer()); + assert!(!instance.substs.has_infer()); let fn_abi = self.fn_abi_of_instance(instance, ty::List::empty()); self.linkage.set(base::linkage_to_gcc(linkage)); diff --git a/compiler/rustc_codegen_llvm/src/asm.rs b/compiler/rustc_codegen_llvm/src/asm.rs index 1a3865360a3c6..98d5b3599d965 100644 --- a/compiler/rustc_codegen_llvm/src/asm.rs +++ b/compiler/rustc_codegen_llvm/src/asm.rs @@ -236,6 +236,7 @@ impl<'ll, 'tcx> AsmBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> { InlineAsmArch::Nvptx64 => {} InlineAsmArch::PowerPC | InlineAsmArch::PowerPC64 => {} InlineAsmArch::Hexagon => {} + InlineAsmArch::LoongArch64 => {} InlineAsmArch::Mips | InlineAsmArch::Mips64 => {} InlineAsmArch::S390x => {} InlineAsmArch::SpirV => {} @@ -633,6 +634,8 @@ fn reg_to_llvm(reg: InlineAsmRegOrRegClass, layout: Option<&TyAndLayout<'_>>) -> InlineAsmRegClass::Arm(ArmInlineAsmRegClass::dreg) | InlineAsmRegClass::Arm(ArmInlineAsmRegClass::qreg) => "w", InlineAsmRegClass::Hexagon(HexagonInlineAsmRegClass::reg) => "r", + InlineAsmRegClass::LoongArch(LoongArchInlineAsmRegClass::reg) => "r", + InlineAsmRegClass::LoongArch(LoongArchInlineAsmRegClass::freg) => "f", InlineAsmRegClass::Mips(MipsInlineAsmRegClass::reg) => "r", InlineAsmRegClass::Mips(MipsInlineAsmRegClass::freg) => "f", InlineAsmRegClass::Nvptx(NvptxInlineAsmRegClass::reg16) => "h", @@ -719,6 +722,7 @@ fn modifier_to_llvm( } } InlineAsmRegClass::Hexagon(_) => None, + InlineAsmRegClass::LoongArch(_) => None, InlineAsmRegClass::Mips(_) => None, InlineAsmRegClass::Nvptx(_) => None, InlineAsmRegClass::PowerPC(_) => None, @@ -803,6 +807,8 @@ fn dummy_output_type<'ll>(cx: &CodegenCx<'ll, '_>, reg: InlineAsmRegClass) -> &' cx.type_vector(cx.type_i64(), 2) } InlineAsmRegClass::Hexagon(HexagonInlineAsmRegClass::reg) => cx.type_i32(), + InlineAsmRegClass::LoongArch(LoongArchInlineAsmRegClass::reg) => cx.type_i32(), + InlineAsmRegClass::LoongArch(LoongArchInlineAsmRegClass::freg) => cx.type_f32(), InlineAsmRegClass::Mips(MipsInlineAsmRegClass::reg) => cx.type_i32(), InlineAsmRegClass::Mips(MipsInlineAsmRegClass::freg) => cx.type_f32(), InlineAsmRegClass::Nvptx(NvptxInlineAsmRegClass::reg16) => cx.type_i16(), diff --git a/compiler/rustc_codegen_llvm/src/callee.rs b/compiler/rustc_codegen_llvm/src/callee.rs index 6ee2a05ffd7b5..30a0cf1d01914 100644 --- a/compiler/rustc_codegen_llvm/src/callee.rs +++ b/compiler/rustc_codegen_llvm/src/callee.rs @@ -27,7 +27,7 @@ pub fn get_fn<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>, instance: Instance<'tcx>) -> debug!("get_fn(instance={:?})", instance); - assert!(!instance.substs.needs_infer()); + assert!(!instance.substs.has_infer()); assert!(!instance.substs.has_escaping_bound_vars()); if let Some(&llfn) = cx.instances.borrow().get(&instance) { diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs b/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs index 824cffa28bac3..2e9f89f419696 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs @@ -515,7 +515,7 @@ impl<'ll, 'tcx> DebugInfoMethods<'tcx> for CodegenCx<'ll, 'tcx> { ty::Adt(def, ..) if !def.is_box() => { // Again, only create type information if full debuginfo is enabled if cx.sess().opts.debuginfo == DebugInfo::Full - && !impl_self_ty.needs_subst() + && !impl_self_ty.has_param() { Some(type_di_node(cx, impl_self_ty)) } else { diff --git a/compiler/rustc_codegen_llvm/src/mono_item.rs b/compiler/rustc_codegen_llvm/src/mono_item.rs index d0ae36349df1a..59bdc60830f80 100644 --- a/compiler/rustc_codegen_llvm/src/mono_item.rs +++ b/compiler/rustc_codegen_llvm/src/mono_item.rs @@ -48,7 +48,7 @@ impl<'tcx> PreDefineMethods<'tcx> for CodegenCx<'_, 'tcx> { visibility: Visibility, symbol_name: &str, ) { - assert!(!instance.substs.needs_infer()); + assert!(!instance.substs.has_infer()); let fn_abi = self.fn_abi_of_instance(instance, ty::List::empty()); let lldecl = self.declare_fn(symbol_name, fn_abi); diff --git a/compiler/rustc_codegen_ssa/messages.ftl b/compiler/rustc_codegen_ssa/messages.ftl index 85a96e3e89c05..375fdec10075a 100644 --- a/compiler/rustc_codegen_ssa/messages.ftl +++ b/compiler/rustc_codegen_ssa/messages.ftl @@ -291,3 +291,16 @@ codegen_ssa_invalid_monomorphization_unsupported_cast = invalid monomorphization codegen_ssa_invalid_monomorphization_unsupported_operation = invalid monomorphization of `{$name}` intrinsic: unsupported operation on `{$in_ty}` with element `{$in_elem}` codegen_ssa_invalid_monomorphization_expected_vector_element_type = invalid monomorphization of `{$name}` intrinsic: expected element type `{$expected_element}` of vector type `{$vector_type}` to be a signed or unsigned integer type + +codegen_ssa_invalid_no_sanitize = invalid argument for `no_sanitize` + .note = expected one of: `address`, `cfi`, `hwaddress`, `kcfi`, `memory`, `memtag`, `shadow-call-stack`, or `thread` + +codegen_ssa_invalid_link_ordinal_nargs = incorrect number of arguments to `#[link_ordinal]` + .note = the attribute requires exactly one argument + +codegen_ssa_illegal_link_ordinal_format = illegal ordinal format in `link_ordinal` + .note = an unsuffixed integer value, e.g., `1`, is expected + +codegen_ssa_target_feature_safe_trait = `#[target_feature(..)]` cannot be applied to safe trait method + .label = cannot be applied to safe trait method + .label_def = not an `unsafe` function diff --git a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs index 9bfe426c00766..5bd42622f2c33 100644 --- a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs +++ b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs @@ -14,6 +14,7 @@ use rustc_span::symbol::Ident; use rustc_span::{sym, Span}; use rustc_target::spec::{abi, SanitizerSet}; +use crate::errors; use crate::target_features::from_target_feature; use crate::{errors::ExpectedUsedSymbol, target_features::check_target_feature_trait_unsafe}; @@ -334,10 +335,7 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs { codegen_fn_attrs.no_sanitize |= SanitizerSet::HWADDRESS } _ => { - tcx.sess - .struct_span_err(item.span(), "invalid argument for `no_sanitize`") - .note("expected one of: `address`, `cfi`, `hwaddress`, `kcfi`, `memory`, `memtag`, `shadow-call-stack`, or `thread`") - .emit(); + tcx.sess.emit_err(errors::InvalidNoSanitize { span: item.span() }); } } } @@ -608,10 +606,7 @@ fn check_link_ordinal(tcx: TyCtxt<'_>, attr: &ast::Attribute) -> Option { let sole_meta_list = match meta_item_list { Some([item]) => item.lit(), Some(_) => { - tcx.sess - .struct_span_err(attr.span, "incorrect number of arguments to `#[link_ordinal]`") - .note("the attribute requires exactly one argument") - .emit(); + tcx.sess.emit_err(errors::InvalidLinkOrdinalNargs { span: attr.span }); return None; } _ => None, @@ -642,10 +637,7 @@ fn check_link_ordinal(tcx: TyCtxt<'_>, attr: &ast::Attribute) -> Option { None } } else { - tcx.sess - .struct_span_err(attr.span, "illegal ordinal format in `link_ordinal`") - .note("an unsuffixed integer value, e.g., `1`, is expected") - .emit(); + tcx.sess.emit_err(errors::InvalidLinkOrdinalFormat { span: attr.span }); None } } diff --git a/compiler/rustc_codegen_ssa/src/errors.rs b/compiler/rustc_codegen_ssa/src/errors.rs index 4493176667867..cf4893b822651 100644 --- a/compiler/rustc_codegen_ssa/src/errors.rs +++ b/compiler/rustc_codegen_ssa/src/errors.rs @@ -981,3 +981,37 @@ impl IntoDiagnosticArg for ExpectedPointerMutability { } } } + +#[derive(Diagnostic)] +#[diag(codegen_ssa_invalid_no_sanitize)] +#[note] +pub struct InvalidNoSanitize { + #[primary_span] + pub span: Span, +} + +#[derive(Diagnostic)] +#[diag(codegen_ssa_invalid_link_ordinal_nargs)] +#[note] +pub struct InvalidLinkOrdinalNargs { + #[primary_span] + pub span: Span, +} + +#[derive(Diagnostic)] +#[diag(codegen_ssa_illegal_link_ordinal_format)] +#[note] +pub struct InvalidLinkOrdinalFormat { + #[primary_span] + pub span: Span, +} + +#[derive(Diagnostic)] +#[diag(codegen_ssa_target_feature_safe_trait)] +pub struct TargetFeatureSafeTrait { + #[primary_span] + #[label] + pub span: Span, + #[label(codegen_ssa_label_def)] + pub def: Span, +} diff --git a/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs b/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs index 7af7fc92dbce2..1479242f23a6c 100644 --- a/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs +++ b/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs @@ -135,13 +135,6 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { .unwrap(); OperandRef::from_const(bx, value, ret_ty).immediate_or_packed_pair(bx) } - sym::offset => { - let ty = substs.type_at(0); - let layout = bx.layout_of(ty); - let ptr = args[0].immediate(); - let offset = args[1].immediate(); - bx.inbounds_gep(bx.backend_type(layout), ptr, &[offset]) - } sym::arith_offset => { let ty = substs.type_at(0); let layout = bx.layout_of(ty); diff --git a/compiler/rustc_codegen_ssa/src/mir/mod.rs b/compiler/rustc_codegen_ssa/src/mir/mod.rs index e4f04b83d58cf..f706ecea97512 100644 --- a/compiler/rustc_codegen_ssa/src/mir/mod.rs +++ b/compiler/rustc_codegen_ssa/src/mir/mod.rs @@ -152,7 +152,7 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( cx: &'a Bx::CodegenCx, instance: Instance<'tcx>, ) { - assert!(!instance.substs.needs_infer()); + assert!(!instance.substs.has_infer()); let llfn = cx.get_fn(instance); @@ -304,7 +304,17 @@ fn arg_local_refs<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( bug!("spread argument isn't a tuple?!"); }; - let place = PlaceRef::alloca(bx, bx.layout_of(arg_ty)); + let layout = bx.layout_of(arg_ty); + + // FIXME: support unsized params in "rust-call" ABI + if layout.is_unsized() { + span_bug!( + arg_decl.source_info.span, + "\"rust-call\" ABI does not support unsized params", + ); + } + + let place = PlaceRef::alloca(bx, layout); for i in 0..tupled_arg_tys.len() { let arg = &fx.fn_abi.args[idx]; idx += 1; diff --git a/compiler/rustc_codegen_ssa/src/target_features.rs b/compiler/rustc_codegen_ssa/src/target_features.rs index 611dd3d1cd18a..a936b62dd4eba 100644 --- a/compiler/rustc_codegen_ssa/src/target_features.rs +++ b/compiler/rustc_codegen_ssa/src/target_features.rs @@ -1,3 +1,4 @@ +use crate::errors; use rustc_ast::ast; use rustc_attr::InstructionSetAttr; use rustc_data_structures::fx::FxHashMap; @@ -443,14 +444,10 @@ pub fn check_target_feature_trait_unsafe(tcx: TyCtxt<'_>, id: LocalDefId, attr_s if let DefKind::AssocFn = tcx.def_kind(id) { let parent_id = tcx.local_parent(id); if let DefKind::Trait | DefKind::Impl { of_trait: true } = tcx.def_kind(parent_id) { - tcx.sess - .struct_span_err( - attr_span, - "`#[target_feature(..)]` cannot be applied to safe trait method", - ) - .span_label(attr_span, "cannot be applied to safe trait method") - .span_label(tcx.def_span(id), "not an `unsafe` function") - .emit(); + tcx.sess.emit_err(errors::TargetFeatureSafeTrait { + span: attr_span, + def: tcx.def_span(id), + }); } } } diff --git a/compiler/rustc_const_eval/src/const_eval/machine.rs b/compiler/rustc_const_eval/src/const_eval/machine.rs index 814b67b46ec7a..bfca58a15b3ac 100644 --- a/compiler/rustc_const_eval/src/const_eval/machine.rs +++ b/compiler/rustc_const_eval/src/const_eval/machine.rs @@ -559,11 +559,20 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir, } fn binary_ptr_op( - _ecx: &InterpCx<'mir, 'tcx, Self>, - _bin_op: mir::BinOp, - _left: &ImmTy<'tcx>, - _right: &ImmTy<'tcx>, + ecx: &InterpCx<'mir, 'tcx, Self>, + bin_op: mir::BinOp, + left: &ImmTy<'tcx>, + right: &ImmTy<'tcx>, ) -> InterpResult<'tcx, (Scalar, bool, Ty<'tcx>)> { + if bin_op == mir::BinOp::Offset { + let ptr = left.to_scalar().to_pointer(ecx)?; + let offset_count = right.to_scalar().to_target_isize(ecx)?; + let pointee_ty = left.layout.ty.builtin_deref(true).unwrap().ty; + + let offset_ptr = ecx.ptr_offset_inbounds(ptr, pointee_ty, offset_count)?; + return Ok((Scalar::from_maybe_pointer(offset_ptr, ecx), false, left.layout.ty)); + } + throw_unsup_format!("pointer arithmetic or comparison is not supported at compile-time"); } diff --git a/compiler/rustc_const_eval/src/interpret/intrinsics.rs b/compiler/rustc_const_eval/src/interpret/intrinsics.rs index eada75ae391cb..a77c699c22f7e 100644 --- a/compiler/rustc_const_eval/src/interpret/intrinsics.rs +++ b/compiler/rustc_const_eval/src/interpret/intrinsics.rs @@ -286,14 +286,6 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { sym::write_bytes => { self.write_bytes_intrinsic(&args[0], &args[1], &args[2])?; } - sym::offset => { - let ptr = self.read_pointer(&args[0])?; - let offset_count = self.read_target_isize(&args[1])?; - let pointee_ty = substs.type_at(0); - - let offset_ptr = self.ptr_offset_inbounds(ptr, pointee_ty, offset_count)?; - self.write_pointer(offset_ptr, dest)?; - } sym::arith_offset => { let ptr = self.read_pointer(&args[0])?; let offset_count = self.read_target_isize(&args[1])?; diff --git a/compiler/rustc_const_eval/src/interpret/util.rs b/compiler/rustc_const_eval/src/interpret/util.rs index 7cb19744987c2..22bdd4d2c3fbc 100644 --- a/compiler/rustc_const_eval/src/interpret/util.rs +++ b/compiler/rustc_const_eval/src/interpret/util.rs @@ -14,7 +14,7 @@ where T: TypeVisitable>, { debug!("ensure_monomorphic_enough: ty={:?}", ty); - if !ty.needs_subst() { + if !ty.has_param() { return Ok(()); } @@ -27,7 +27,7 @@ where type BreakTy = FoundParam; fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow { - if !ty.needs_subst() { + if !ty.has_param() { return ControlFlow::Continue(()); } @@ -46,7 +46,7 @@ where // are used and require substitution. // Just in case there are closures or generators within this subst, // recurse. - if unused_params.is_used(index) && subst.needs_subst() { + if unused_params.is_used(index) && subst.has_param() { return subst.visit_with(self); } } diff --git a/compiler/rustc_data_structures/src/intern.rs b/compiler/rustc_data_structures/src/intern.rs index ba94f3776eb90..43d16919e1583 100644 --- a/compiler/rustc_data_structures/src/intern.rs +++ b/compiler/rustc_data_structures/src/intern.rs @@ -1,4 +1,5 @@ use crate::stable_hasher::{HashStable, StableHasher}; +use crate::tagged_ptr::Pointer; use std::cmp::Ordering; use std::hash::{Hash, Hasher}; use std::ops::Deref; @@ -108,5 +109,21 @@ where } } +unsafe impl<'a, T: 'a> Pointer for Interned<'a, T> { + const BITS: u32 = <&'a T>::BITS; + + fn into_ptr(self) -> ptr::NonNull { + <&'a T>::into_ptr(self.0) + } + + unsafe fn from_ptr(ptr: ptr::NonNull) -> Self { + // Safety: + // `Self::into_ptr` uses `<&T>::into_ptr`, + // which is compatible with `<&T>::from_ptr`. + let reference = unsafe { <&'a T>::from_ptr(ptr) }; + Self::new_unchecked(reference) + } +} + #[cfg(test)] mod tests; diff --git a/compiler/rustc_data_structures/src/lib.rs b/compiler/rustc_data_structures/src/lib.rs index 426d2c4034bd8..004017ec5f31a 100644 --- a/compiler/rustc_data_structures/src/lib.rs +++ b/compiler/rustc_data_structures/src/lib.rs @@ -31,6 +31,7 @@ #![feature(unwrap_infallible)] #![feature(strict_provenance)] #![feature(ptr_alignment_type)] +#![feature(macro_metavar_expr)] #![allow(rustc::default_hash_types)] #![allow(rustc::potential_query_instability)] #![deny(rustc::untranslatable_diagnostic)] diff --git a/compiler/rustc_data_structures/src/tagged_ptr.rs b/compiler/rustc_data_structures/src/tagged_ptr.rs index 8568aac67c08c..2914eece6796b 100644 --- a/compiler/rustc_data_structures/src/tagged_ptr.rs +++ b/compiler/rustc_data_structures/src/tagged_ptr.rs @@ -24,6 +24,7 @@ use crate::aligned::Aligned; mod copy; mod drop; +mod impl_tag; pub use copy::CopyTaggedPtr; pub use drop::TaggedPtr; @@ -141,6 +142,30 @@ pub unsafe trait Tag: Copy { unsafe fn from_usize(tag: usize) -> Self; } +/// Returns the number of bits available for use for tags in a pointer to `T` +/// (this is based on `T`'s alignment). +pub const fn bits_for() -> u32 { + crate::aligned::align_of::().as_nonzero().trailing_zeros() +} + +/// Returns the correct [`Tag::BITS`] constant for a set of tag values. +pub const fn bits_for_tags(mut tags: &[usize]) -> u32 { + let mut bits = 0; + + while let &[tag, ref rest @ ..] = tags { + tags = rest; + + // bits required to represent `tag`, + // position of the most significant 1 + let b = usize::BITS - tag.leading_zeros(); + if b > bits { + bits = b; + } + } + + bits +} + unsafe impl Pointer for Box { const BITS: u32 = bits_for::(); @@ -221,12 +246,6 @@ unsafe impl<'a, T: 'a + ?Sized + Aligned> Pointer for &'a mut T { } } -/// Returns the number of bits available for use for tags in a pointer to `T` -/// (this is based on `T`'s alignment). -pub const fn bits_for() -> u32 { - crate::aligned::align_of::().as_nonzero().trailing_zeros() -} - /// A tag type used in [`CopyTaggedPtr`] and [`TaggedPtr`] tests. #[derive(Copy, Clone, Debug, PartialEq, Eq)] #[cfg(test)] diff --git a/compiler/rustc_data_structures/src/tagged_ptr/copy.rs b/compiler/rustc_data_structures/src/tagged_ptr/copy.rs index 691e92f196a26..e893a2c781346 100644 --- a/compiler/rustc_data_structures/src/tagged_ptr/copy.rs +++ b/compiler/rustc_data_structures/src/tagged_ptr/copy.rs @@ -82,11 +82,13 @@ where /// drop, use [`TaggedPtr`] instead. /// /// [`TaggedPtr`]: crate::tagged_ptr::TaggedPtr + #[inline] pub fn new(pointer: P, tag: T) -> Self { Self { packed: Self::pack(P::into_ptr(pointer), tag), tag_ghost: PhantomData } } /// Retrieves the pointer. + #[inline] pub fn pointer(self) -> P where P: Copy, @@ -123,6 +125,7 @@ where /// according to `self.packed` encoding scheme. /// /// [`P::into_ptr`]: Pointer::into_ptr + #[inline] fn pack(ptr: NonNull, tag: T) -> NonNull { // Trigger assert! let () = Self::ASSERTION; @@ -145,6 +148,7 @@ where } /// Retrieves the original raw pointer from `self.packed`. + #[inline] pub(super) fn pointer_raw(&self) -> NonNull { self.packed.map_addr(|addr| unsafe { NonZeroUsize::new_unchecked(addr.get() << T::BITS) }) } @@ -184,6 +188,7 @@ where P: Pointer + Copy, T: Tag, { + #[inline] fn clone(&self) -> Self { *self } @@ -196,6 +201,7 @@ where { type Target = P::Target; + #[inline] fn deref(&self) -> &Self::Target { // Safety: // `pointer_raw` returns the original pointer from `P::into_ptr` which, @@ -209,6 +215,7 @@ where P: Pointer + DerefMut, T: Tag, { + #[inline] fn deref_mut(&mut self) -> &mut Self::Target { // Safety: // `pointer_raw` returns the original pointer from `P::into_ptr` which, @@ -235,6 +242,7 @@ where P: Pointer, T: Tag, { + #[inline] fn eq(&self, other: &Self) -> bool { self.packed == other.packed } @@ -252,6 +260,7 @@ where P: Pointer, T: Tag, { + #[inline] fn hash(&self, state: &mut H) { self.packed.hash(state); } diff --git a/compiler/rustc_data_structures/src/tagged_ptr/drop.rs b/compiler/rustc_data_structures/src/tagged_ptr/drop.rs index d418c06b7ebb4..4e42b5b4afe8a 100644 --- a/compiler/rustc_data_structures/src/tagged_ptr/drop.rs +++ b/compiler/rustc_data_structures/src/tagged_ptr/drop.rs @@ -30,16 +30,19 @@ where T: Tag, { /// Tags `pointer` with `tag`. + #[inline] pub fn new(pointer: P, tag: T) -> Self { TaggedPtr { raw: CopyTaggedPtr::new(pointer, tag) } } /// Retrieves the tag. + #[inline] pub fn tag(&self) -> T { self.raw.tag() } /// Sets the tag to a new value. + #[inline] pub fn set_tag(&mut self, tag: T) { self.raw.set_tag(tag) } @@ -63,6 +66,8 @@ where T: Tag, { type Target = P::Target; + + #[inline] fn deref(&self) -> &Self::Target { self.raw.deref() } @@ -73,6 +78,7 @@ where P: Pointer + DerefMut, T: Tag, { + #[inline] fn deref_mut(&mut self) -> &mut Self::Target { self.raw.deref_mut() } @@ -108,6 +114,7 @@ where P: Pointer, T: Tag, { + #[inline] fn eq(&self, other: &Self) -> bool { self.raw.eq(&other.raw) } @@ -125,6 +132,7 @@ where P: Pointer, T: Tag, { + #[inline] fn hash(&self, state: &mut H) { self.raw.hash(state); } diff --git a/compiler/rustc_data_structures/src/tagged_ptr/impl_tag.rs b/compiler/rustc_data_structures/src/tagged_ptr/impl_tag.rs new file mode 100644 index 0000000000000..cb7f7d318dc41 --- /dev/null +++ b/compiler/rustc_data_structures/src/tagged_ptr/impl_tag.rs @@ -0,0 +1,144 @@ +/// Implements [`Tag`] for a given type. +/// +/// You can use `impl_tag` on structs and enums. +/// You need to specify the type and all its possible values, +/// which can only be paths with optional fields. +/// +/// [`Tag`]: crate::tagged_ptr::Tag +/// +/// # Examples +/// +/// Basic usage: +/// +/// ``` +/// #![feature(macro_metavar_expr)] +/// use rustc_data_structures::{impl_tag, tagged_ptr::Tag}; +/// +/// #[derive(Copy, Clone, PartialEq, Debug)] +/// enum SomeTag { +/// A, +/// B, +/// X { v: bool }, +/// Y(bool, bool), +/// } +/// +/// impl_tag! { +/// // The type for which the `Tag` will be implemented +/// impl Tag for SomeTag; +/// // You need to specify all possible tag values: +/// SomeTag::A, // 0 +/// SomeTag::B, // 1 +/// // For variants with fields, you need to specify the fields: +/// SomeTag::X { v: true }, // 2 +/// SomeTag::X { v: false }, // 3 +/// // For tuple variants use named syntax: +/// SomeTag::Y { 0: true, 1: true }, // 4 +/// SomeTag::Y { 0: false, 1: true }, // 5 +/// SomeTag::Y { 0: true, 1: false }, // 6 +/// SomeTag::Y { 0: false, 1: false }, // 7 +/// } +/// +/// // Tag values are assigned in order: +/// assert_eq!(SomeTag::A.into_usize(), 0); +/// assert_eq!(SomeTag::X { v: false }.into_usize(), 3); +/// assert_eq!(SomeTag::Y(false, true).into_usize(), 5); +/// +/// assert_eq!(unsafe { SomeTag::from_usize(1) }, SomeTag::B); +/// assert_eq!(unsafe { SomeTag::from_usize(2) }, SomeTag::X { v: true }); +/// assert_eq!(unsafe { SomeTag::from_usize(7) }, SomeTag::Y(false, false)); +/// ``` +/// +/// Structs are supported: +/// +/// ``` +/// #![feature(macro_metavar_expr)] +/// # use rustc_data_structures::impl_tag; +/// #[derive(Copy, Clone)] +/// struct Flags { a: bool, b: bool } +/// +/// impl_tag! { +/// impl Tag for Flags; +/// Flags { a: true, b: true }, +/// Flags { a: false, b: true }, +/// Flags { a: true, b: false }, +/// Flags { a: false, b: false }, +/// } +/// ``` +/// +/// Not specifying all values results in a compile error: +/// +/// ```compile_fail,E0004 +/// #![feature(macro_metavar_expr)] +/// # use rustc_data_structures::impl_tag; +/// #[derive(Copy, Clone)] +/// enum E { +/// A, +/// B, +/// } +/// +/// impl_tag! { +/// impl Tag for E; +/// E::A, +/// } +/// ``` +#[macro_export] +macro_rules! impl_tag { + ( + impl Tag for $Self:ty; + $( + $($path:ident)::* $( { $( $fields:tt )* })?, + )* + ) => { + // Safety: + // `bits_for_tags` is called on the same `${index()}`-es as + // `into_usize` returns, thus `BITS` constant is correct. + unsafe impl $crate::tagged_ptr::Tag for $Self { + const BITS: u32 = $crate::tagged_ptr::bits_for_tags(&[ + $( + ${index()}, + $( ${ignore(path)} )* + )* + ]); + + #[inline] + fn into_usize(self) -> usize { + // This forbids use of repeating patterns (`Enum::V`&`Enum::V`, etc) + // (or at least it should, see ) + #[forbid(unreachable_patterns)] + match self { + // `match` is doing heavy lifting here, by requiring exhaustiveness + $( + $($path)::* $( { $( $fields )* } )? => ${index()}, + )* + } + } + + #[inline] + unsafe fn from_usize(tag: usize) -> Self { + match tag { + $( + ${index()} => $($path)::* $( { $( $fields )* } )?, + )* + + // Safety: + // `into_usize` only returns `${index()}` of the same + // repetition as we are filtering above, thus if this is + // reached, the safety contract of this function was + // already breached. + _ => unsafe { + debug_assert!( + false, + "invalid tag: {tag}\ + (this is a bug in the caller of `from_usize`)" + ); + std::hint::unreachable_unchecked() + }, + } + } + + } + }; +} + +#[cfg(test)] +mod tests; diff --git a/compiler/rustc_data_structures/src/tagged_ptr/impl_tag/tests.rs b/compiler/rustc_data_structures/src/tagged_ptr/impl_tag/tests.rs new file mode 100644 index 0000000000000..62c926153e1e9 --- /dev/null +++ b/compiler/rustc_data_structures/src/tagged_ptr/impl_tag/tests.rs @@ -0,0 +1,34 @@ +#[test] +fn bits_constant() { + use crate::tagged_ptr::Tag; + + #[derive(Copy, Clone)] + struct Unit; + impl_tag! { impl Tag for Unit; Unit, } + assert_eq!(Unit::BITS, 0); + + #[derive(Copy, Clone)] + enum Enum3 { + A, + B, + C, + } + impl_tag! { impl Tag for Enum3; Enum3::A, Enum3::B, Enum3::C, } + assert_eq!(Enum3::BITS, 2); + + #[derive(Copy, Clone)] + struct Eight(bool, bool, bool); + impl_tag! { + impl Tag for Eight; + Eight { 0: true, 1: true, 2: true }, + Eight { 0: true, 1: true, 2: false }, + Eight { 0: true, 1: false, 2: true }, + Eight { 0: true, 1: false, 2: false }, + Eight { 0: false, 1: true, 2: true }, + Eight { 0: false, 1: true, 2: false }, + Eight { 0: false, 1: false, 2: true }, + Eight { 0: false, 1: false, 2: false }, + } + + assert_eq!(Eight::BITS, 3); +} diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs index 1a80b4fc3140d..5fac485de6417 100644 --- a/compiler/rustc_driver_impl/src/lib.rs +++ b/compiler/rustc_driver_impl/src/lib.rs @@ -58,8 +58,16 @@ use std::str; use std::sync::LazyLock; use std::time::Instant; +// This import blocks the use of panicking `print` and `println` in all the code +// below. Please use `safe_print` and `safe_println` to avoid ICE when +// encountering an I/O error during print. +#[allow(unused_imports)] +use std::{compile_error as print, compile_error as println}; + pub mod args; pub mod pretty; +#[macro_use] +mod print; mod session_diagnostics; use crate::session_diagnostics::{ @@ -511,7 +519,7 @@ fn handle_explain(registry: Registry, code: &str, output: ErrorOutputType) { if io::stdout().is_terminal() { show_content_with_pager(&text); } else { - print!("{text}"); + safe_print!("{text}"); } } Err(InvalidErrorCode) => { @@ -547,7 +555,7 @@ fn show_content_with_pager(content: &str) { // If pager fails for whatever reason, we should still print the content // to standard output if fallback_to_println { - print!("{content}"); + safe_print!("{content}"); } } @@ -601,7 +609,7 @@ pub fn list_metadata(sess: &Session, metadata_loader: &dyn MetadataLoader) -> Co let path = &(*ifile); let mut v = Vec::new(); locator::list_file_metadata(&sess.target, path, metadata_loader, &mut v).unwrap(); - println!("{}", String::from_utf8(v).unwrap()); + safe_println!("{}", String::from_utf8(v).unwrap()); } Input::Str { .. } => { early_error(ErrorOutputType::default(), "cannot list metadata for stdin"); @@ -642,12 +650,12 @@ fn print_crate_info( TargetList => { let mut targets = rustc_target::spec::TARGETS.to_vec(); targets.sort_unstable(); - println!("{}", targets.join("\n")); + safe_println!("{}", targets.join("\n")); } - Sysroot => println!("{}", sess.sysroot.display()), - TargetLibdir => println!("{}", sess.target_tlib_path.dir.display()), + Sysroot => safe_println!("{}", sess.sysroot.display()), + TargetLibdir => safe_println!("{}", sess.target_tlib_path.dir.display()), TargetSpec => { - println!("{}", serde_json::to_string_pretty(&sess.target.to_json()).unwrap()); + safe_println!("{}", serde_json::to_string_pretty(&sess.target.to_json()).unwrap()); } AllTargetSpecs => { let mut targets = BTreeMap::new(); @@ -656,7 +664,7 @@ fn print_crate_info( let target = Target::expect_builtin(&triple); targets.insert(name, target.to_json()); } - println!("{}", serde_json::to_string_pretty(&targets).unwrap()); + safe_println!("{}", serde_json::to_string_pretty(&targets).unwrap()); } FileNames | CrateName => { let Some(attrs) = attrs.as_ref() else { @@ -666,14 +674,14 @@ fn print_crate_info( let t_outputs = rustc_interface::util::build_output_filenames(attrs, sess); let id = rustc_session::output::find_crate_name(sess, attrs); if *req == PrintRequest::CrateName { - println!("{id}"); + safe_println!("{id}"); continue; } let crate_types = collect_crate_types(sess, attrs); for &style in &crate_types { let fname = rustc_session::output::filename_for_input(sess, style, id, &t_outputs); - println!("{}", fname.file_name().unwrap().to_string_lossy()); + safe_println!("{}", fname.file_name().unwrap().to_string_lossy()); } } Cfg => { @@ -707,13 +715,13 @@ fn print_crate_info( cfgs.sort(); for cfg in cfgs { - println!("{cfg}"); + safe_println!("{cfg}"); } } CallingConventions => { let mut calling_conventions = rustc_target::spec::abi::all_names(); calling_conventions.sort_unstable(); - println!("{}", calling_conventions.join("\n")); + safe_println!("{}", calling_conventions.join("\n")); } RelocationModels | CodeModels @@ -733,7 +741,7 @@ fn print_crate_info( let stable = sess.target.options.supported_split_debuginfo.contains(split); let unstable_ok = sess.unstable_options(); if stable || unstable_ok { - println!("{split}"); + safe_println!("{split}"); } } } @@ -770,14 +778,14 @@ pub fn version_at_macro_invocation( ) { let verbose = matches.opt_present("verbose"); - println!("{binary} {version}"); + safe_println!("{binary} {version}"); if verbose { - println!("binary: {binary}"); - println!("commit-hash: {commit_hash}"); - println!("commit-date: {commit_date}"); - println!("host: {}", config::host_triple()); - println!("release: {release}"); + safe_println!("binary: {binary}"); + safe_println!("commit-hash: {commit_hash}"); + safe_println!("commit-date: {commit_date}"); + safe_println!("host: {}", config::host_triple()); + safe_println!("release: {release}"); let debug_flags = matches.opt_strs("Z"); let backend_name = debug_flags.iter().find_map(|x| x.strip_prefix("codegen-backend=")); @@ -807,7 +815,7 @@ fn usage(verbose: bool, include_unstable_options: bool, nightly_build: bool) { } else { "" }; - println!( + safe_println!( "{options}{at_path}\nAdditional help: -C help Print codegen options -W help \ @@ -820,7 +828,7 @@ fn usage(verbose: bool, include_unstable_options: bool, nightly_build: bool) { } fn print_wall_help() { - println!( + safe_println!( " The flag `-Wall` does not exist in `rustc`. Most useful lints are enabled by default. Use `rustc -W help` to see all available lints. It's more common to put @@ -832,7 +840,7 @@ the command line flag directly. /// Write to stdout lint command options, together with a list of all available lints pub fn describe_lints(sess: &Session, lint_store: &LintStore, loaded_plugins: bool) { - println!( + safe_println!( " Available lint options: -W Warn about @@ -877,21 +885,21 @@ Available lint options: s }; - println!("Lint checks provided by rustc:\n"); + safe_println!("Lint checks provided by rustc:\n"); let print_lints = |lints: Vec<&Lint>| { - println!(" {} {:7.7} {}", padded("name"), "default", "meaning"); - println!(" {} {:7.7} {}", padded("----"), "-------", "-------"); + safe_println!(" {} {:7.7} {}", padded("name"), "default", "meaning"); + safe_println!(" {} {:7.7} {}", padded("----"), "-------", "-------"); for lint in lints { let name = lint.name_lower().replace('_', "-"); - println!( + safe_println!( " {} {:7.7} {}", padded(&name), lint.default_level(sess.edition()).as_str(), lint.desc ); } - println!("\n"); + safe_println!("\n"); }; print_lints(builtin); @@ -912,14 +920,14 @@ Available lint options: s }; - println!("Lint groups provided by rustc:\n"); + safe_println!("Lint groups provided by rustc:\n"); let print_lint_groups = |lints: Vec<(&'static str, Vec)>, all_warnings| { - println!(" {} sub-lints", padded("name")); - println!(" {} ---------", padded("----")); + safe_println!(" {} sub-lints", padded("name")); + safe_println!(" {} ---------", padded("----")); if all_warnings { - println!(" {} all lints that are set to issue warnings", padded("warnings")); + safe_println!(" {} all lints that are set to issue warnings", padded("warnings")); } for (name, to) in lints { @@ -929,26 +937,26 @@ Available lint options: .map(|x| x.to_string().replace('_', "-")) .collect::>() .join(", "); - println!(" {} {}", padded(&name), desc); + safe_println!(" {} {}", padded(&name), desc); } - println!("\n"); + safe_println!("\n"); }; print_lint_groups(builtin_groups, true); match (loaded_plugins, plugin.len(), plugin_groups.len()) { (false, 0, _) | (false, _, 0) => { - println!("Lint tools like Clippy can provide additional lints and lint groups."); + safe_println!("Lint tools like Clippy can provide additional lints and lint groups."); } (false, ..) => panic!("didn't load lint plugins but got them anyway!"), - (true, 0, 0) => println!("This crate does not load any lint plugins or lint groups."), + (true, 0, 0) => safe_println!("This crate does not load any lint plugins or lint groups."), (true, l, g) => { if l > 0 { - println!("Lint checks provided by plugins loaded by this crate:\n"); + safe_println!("Lint checks provided by plugins loaded by this crate:\n"); print_lints(plugin); } if g > 0 { - println!("Lint groups provided by plugins loaded by this crate:\n"); + safe_println!("Lint groups provided by plugins loaded by this crate:\n"); print_lint_groups(plugin_groups, false); } } @@ -996,12 +1004,12 @@ pub fn describe_flag_categories(matches: &Matches) -> bool { } fn describe_debug_flags() { - println!("\nAvailable options:\n"); + safe_println!("\nAvailable options:\n"); print_flag_list("-Z", config::Z_OPTIONS); } fn describe_codegen_flags() { - println!("\nAvailable codegen options:\n"); + safe_println!("\nAvailable codegen options:\n"); print_flag_list("-C", config::CG_OPTIONS); } @@ -1012,7 +1020,7 @@ fn print_flag_list( let max_len = flag_list.iter().map(|&(name, _, _, _)| name.chars().count()).max().unwrap_or(0); for &(name, _, _, desc) in flag_list { - println!( + safe_println!( " {} {:>width$}=val -- {}", cmdline_opt, name.replace('_', "-"), diff --git a/compiler/rustc_driver_impl/src/print.rs b/compiler/rustc_driver_impl/src/print.rs new file mode 100644 index 0000000000000..70de55320f7ae --- /dev/null +++ b/compiler/rustc_driver_impl/src/print.rs @@ -0,0 +1,20 @@ +use std::fmt; +use std::io::{self, Write as _}; + +macro_rules! safe_print { + ($($arg:tt)*) => {{ + $crate::print::print(std::format_args!($($arg)*)); + }}; +} + +macro_rules! safe_println { + ($($arg:tt)*) => { + safe_print!("{}\n", std::format_args!($($arg)*)) + }; +} + +pub(crate) fn print(args: fmt::Arguments<'_>) { + if let Err(_) = io::stdout().write_fmt(args) { + rustc_errors::FatalError.raise(); + } +} diff --git a/compiler/rustc_expand/messages.ftl b/compiler/rustc_expand/messages.ftl index 5d999d0db5dbd..70d2718b70639 100644 --- a/compiler/rustc_expand/messages.ftl +++ b/compiler/rustc_expand/messages.ftl @@ -136,3 +136,7 @@ expand_proc_macro_panicked = expand_proc_macro_derive_tokens = proc-macro derive produced unparsable tokens + +expand_duplicate_matcher_binding = duplicate matcher binding + .label = duplicate binding + .label2 = previous binding diff --git a/compiler/rustc_expand/src/errors.rs b/compiler/rustc_expand/src/errors.rs index e5102a952e741..e3a0ae3570eb0 100644 --- a/compiler/rustc_expand/src/errors.rs +++ b/compiler/rustc_expand/src/errors.rs @@ -397,3 +397,13 @@ pub struct ProcMacroDeriveTokens { #[primary_span] pub span: Span, } + +#[derive(Diagnostic)] +#[diag(expand_duplicate_matcher_binding)] +pub struct DuplicateMatcherBinding { + #[primary_span] + #[label] + pub span: Span, + #[label(expand_label2)] + pub prev: Span, +} diff --git a/compiler/rustc_expand/src/mbe/macro_check.rs b/compiler/rustc_expand/src/mbe/macro_check.rs index 5be134f4e664c..75b6396f0be38 100644 --- a/compiler/rustc_expand/src/mbe/macro_check.rs +++ b/compiler/rustc_expand/src/mbe/macro_check.rs @@ -104,6 +104,7 @@ //! Kleene operators under which a meta-variable is repeating is the concatenation of the stacks //! stored when entering a macro definition starting from the state in which the meta-variable is //! bound. +use crate::errors; use crate::mbe::{KleeneToken, TokenTree}; use rustc_ast::token::{Delimiter, Token, TokenKind}; @@ -281,10 +282,7 @@ fn check_binders( // Duplicate binders at the top-level macro definition are errors. The lint is only // for nested macro definitions. sess.span_diagnostic - .struct_span_err(span, "duplicate matcher binding") - .span_label(span, "duplicate binding") - .span_label(prev_info.span, "previous binding") - .emit(); + .emit_err(errors::DuplicateMatcherBinding { span, prev: prev_info.span }); *valid = false; } else { binders.insert(name, BinderInfo { span, ops: ops.into() }); diff --git a/compiler/rustc_hir_analysis/messages.ftl b/compiler/rustc_hir_analysis/messages.ftl index 1d7965ff5f66e..5d45d09797b0b 100644 --- a/compiler/rustc_hir_analysis/messages.ftl +++ b/compiler/rustc_hir_analysis/messages.ftl @@ -225,3 +225,54 @@ hir_analysis_functions_names_duplicated = functions names are duplicated hir_analysis_simd_ffi_highly_experimental = use of SIMD type{$snip} in FFI is highly experimental and may result in invalid code .help = add `#![feature(simd_ffi)]` to the crate attributes to enable + +hir_analysis_impl_not_marked_default = `{$ident}` specializes an item from a parent `impl`, but that item is not marked `default` + .label = cannot specialize default item `{$ident}` + .ok_label = parent `impl` is here + .note = to specialize, `{$ident}` in the parent `impl` must be marked `default` + +hir_analysis_impl_not_marked_default_err = `{$ident}` specializes an item from a parent `impl`, but that item is not marked `default` + .note = parent implementation is in crate `{$cname}` + +hir_analysis_missing_trait_item = not all trait items implemented, missing: `{$missing_items_msg}` + .label = missing `{$missing_items_msg}` in implementation + +hir_analysis_missing_trait_item_suggestion = implement the missing item: `{$snippet}` + +hir_analysis_missing_trait_item_label = `{$item}` from trait + +hir_analysis_missing_one_of_trait_item = not all trait items implemented, missing one of: `{$missing_items_msg}` + .label = missing one of `{$missing_items_msg}` in implementation + .note = required because of this annotation + +hir_analysis_missing_trait_item_unstable = not all trait items implemented, missing: `{$missing_item_name}` + .note = default implementation of `{$missing_item_name}` is unstable + .some_note = use of unstable library feature '{$feature}': {$r} + .none_note = use of unstable library feature '{$feature}' + +hir_analysis_transparent_enum_variant = transparent enum needs exactly one variant, but has {$number} + .label = needs exactly one variant, but has {$number} + .many_label = too many variants in `{$path}` + .multi_label = variant here + +hir_analysis_transparent_non_zero_sized_enum = the variant of a transparent {$desc} needs at most one non-zero-sized field, but has {$field_count} + .label = needs at most one non-zero-sized field, but has {$field_count} + .labels = this field is non-zero-sized + +hir_analysis_transparent_non_zero_sized = transparent {$desc} needs at most one non-zero-sized field, but has {$field_count} + .label = needs at most one non-zero-sized field, but has {$field_count} + .labels = this field is non-zero-sized + +hir_analysis_too_large_static = extern static is too large for the current architecture + +hir_analysis_specialization_trait = implementing `rustc_specialization_trait` traits is unstable + .help = add `#![feature(min_specialization)]` to the crate attributes to enable + +hir_analysis_closure_implicit_hrtb = implicit types in closure signatures are forbidden when `for<...>` is present + .label = `for<...>` is here + +hir_analysis_const_specialize = cannot specialize on const impl with non-const impl + +hir_analysis_static_specialize = cannot specialize on `'static` lifetime + +hir_analysis_missing_tilde_const = missing `~const` qualifier for specialization diff --git a/compiler/rustc_hir_analysis/src/astconv/mod.rs b/compiler/rustc_hir_analysis/src/astconv/mod.rs index 992316edb6309..709dea43d84aa 100644 --- a/compiler/rustc_hir_analysis/src/astconv/mod.rs +++ b/compiler/rustc_hir_analysis/src/astconv/mod.rs @@ -2318,7 +2318,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { let infcx = match self.infcx() { Some(infcx) => infcx, None => { - assert!(!self_ty.needs_infer()); + assert!(!self_ty.has_infer()); infcx_ = tcx.infer_ctxt().ignoring_regions().build(); &infcx_ } @@ -2489,7 +2489,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { let infcx = if let Some(infcx) = self.infcx() { infcx } else { - assert!(!qself_ty.needs_infer()); + assert!(!qself_ty.has_infer()); infcx_ = tcx.infer_ctxt().build(); &infcx_ }; @@ -3039,7 +3039,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { // the anon const, which is empty. This is why the // `AlwaysApplicable` impl needs a `T: ?Sized` bound for // this to compile if we were to normalize here. - if forbid_generic && ty.needs_subst() { + if forbid_generic && ty.has_param() { let mut err = tcx.sess.struct_span_err( path.span, "generic `Self` types are currently not permitted in anonymous constants", diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs index ad2624a5d2d7b..68e957f9d8e3a 100644 --- a/compiler/rustc_hir_analysis/src/check/check.rs +++ b/compiler/rustc_hir_analysis/src/check/check.rs @@ -170,9 +170,7 @@ fn check_static_inhabited(tcx: TyCtxt<'_>, def_id: LocalDefId) { if matches!(tcx.def_kind(def_id), DefKind::Static(_) if tcx.def_kind(tcx.local_parent(def_id)) == DefKind::ForeignMod) => { - tcx.sess - .struct_span_err(span, "extern static is too large for the current architecture") - .emit(); + tcx.sess.emit_err(errors::TooLargeStatic { span }); return; } // Generic statics are rejected, but we still reach this case. @@ -320,7 +318,7 @@ pub(super) fn check_opaque_for_inheriting_lifetimes( }; let prohibit_opaque = tcx .explicit_item_bounds(def_id) - .iter() + .subst_identity_iter_copied() .try_for_each(|(predicate, _)| predicate.visit_with(&mut visitor)); if let Some(ty) = prohibit_opaque.break_value() { diff --git a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs index fe87aae8ed111..48214b899a4b8 100644 --- a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs +++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs @@ -839,7 +839,7 @@ impl<'tcx> TypeFolder> for ImplTraitInTraitCollector<'_, 'tcx> { }); self.types.insert(proj.def_id, (infer_ty, proj.substs)); // Recurse into bounds - for (pred, pred_span) in self.interner().bound_explicit_item_bounds(proj.def_id).subst_iter_copied(self.interner(), proj.substs) { + for (pred, pred_span) in self.interner().explicit_item_bounds(proj.def_id).subst_iter_copied(self.interner(), proj.substs) { let pred = pred.fold_with(self); let pred = self.ocx.normalize( &ObligationCause::misc(self.span, self.body_id), @@ -2023,7 +2023,7 @@ pub(super) fn check_type_bounds<'tcx>( }; let obligations: Vec<_> = tcx - .bound_explicit_item_bounds(trait_ty.def_id) + .explicit_item_bounds(trait_ty.def_id) .subst_iter_copied(tcx, rebased_substs) .map(|(concrete_ty_bound, span)| { debug!("check_type_bounds: concrete_ty_bound = {:?}", concrete_ty_bound); diff --git a/compiler/rustc_hir_analysis/src/check/mod.rs b/compiler/rustc_hir_analysis/src/check/mod.rs index 4b3f3cf169dc0..08154cdae4784 100644 --- a/compiler/rustc_hir_analysis/src/check/mod.rs +++ b/compiler/rustc_hir_analysis/src/check/mod.rs @@ -74,7 +74,7 @@ pub use check::check_abi; use check::check_mod_item_types; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; -use rustc_errors::{pluralize, struct_span_err, Applicability, Diagnostic, DiagnosticBuilder}; +use rustc_errors::{pluralize, struct_span_err, Diagnostic, DiagnosticBuilder}; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_hir::intravisit::Visitor; use rustc_index::bit_set::BitSet; @@ -90,6 +90,7 @@ use rustc_target::spec::abi::Abi; use rustc_trait_selection::traits::error_reporting::suggestions::ReturnsVisitor; use std::num::NonZeroU32; +use crate::errors; use crate::require_c_abi_if_c_variadic; use crate::util::common::indenter; @@ -171,29 +172,13 @@ fn maybe_check_static_with_link_section(tcx: TyCtxt<'_>, id: LocalDefId) { fn report_forbidden_specialization(tcx: TyCtxt<'_>, impl_item: DefId, parent_impl: DefId) { let span = tcx.def_span(impl_item); let ident = tcx.item_name(impl_item); - let mut err = struct_span_err!( - tcx.sess, - span, - E0520, - "`{}` specializes an item from a parent `impl`, but that item is not marked `default`", - ident, - ); - err.span_label(span, format!("cannot specialize default item `{}`", ident)); - - match tcx.span_of_impl(parent_impl) { - Ok(span) => { - err.span_label(span, "parent `impl` is here"); - err.note(&format!( - "to specialize, `{}` in the parent `impl` must be marked `default`", - ident - )); - } - Err(cname) => { - err.note(&format!("parent implementation is in crate `{cname}`")); - } - } - err.emit(); + let err = match tcx.span_of_impl(parent_impl) { + Ok(sp) => errors::ImplNotMarkedDefault::Ok { span, ident, ok_label: sp }, + Err(cname) => errors::ImplNotMarkedDefault::Err { span, ident, cname }, + }; + + tcx.sess.emit_err(err); } fn missing_items_err( @@ -211,15 +196,6 @@ fn missing_items_err( .collect::>() .join("`, `"); - let impl_span = tcx.def_span(impl_def_id); - let mut err = struct_span_err!( - tcx.sess, - impl_span, - E0046, - "not all trait items implemented, missing: `{missing_items_msg}`", - ); - err.span_label(impl_span, format!("missing `{missing_items_msg}` in implementation")); - // `Span` before impl block closing brace. let hi = full_impl_span.hi() - BytePos(1); // Point at the place right before the closing brace of the relevant `impl` to suggest @@ -228,6 +204,8 @@ fn missing_items_err( // Obtain the level of indentation ending in `sugg_sp`. let padding = tcx.sess.source_map().indentation_before(sugg_sp).unwrap_or_else(|| String::new()); + let (mut missing_trait_item, mut missing_trait_item_none, mut missing_trait_item_label) = + (Vec::new(), Vec::new(), Vec::new()); for &trait_item in missing_items { let snippet = suggestion_signature( @@ -236,16 +214,30 @@ fn missing_items_err( tcx.impl_trait_ref(impl_def_id).unwrap().subst_identity(), ); let code = format!("{}{}\n{}", padding, snippet, padding); - let msg = format!("implement the missing item: `{snippet}`"); - let appl = Applicability::HasPlaceholders; if let Some(span) = tcx.hir().span_if_local(trait_item.def_id) { - err.span_label(span, format!("`{}` from trait", trait_item.name)); - err.tool_only_span_suggestion(sugg_sp, &msg, code, appl); + missing_trait_item_label + .push(errors::MissingTraitItemLabel { span, item: trait_item.name }); + missing_trait_item.push(errors::MissingTraitItemSuggestion { + span: sugg_sp, + code, + snippet, + }); } else { - err.span_suggestion_hidden(sugg_sp, &msg, code, appl); + missing_trait_item_none.push(errors::MissingTraitItemSuggestionNone { + span: sugg_sp, + code, + snippet, + }) } } - err.emit(); + + tcx.sess.emit_err(errors::MissingTraitItem { + span: tcx.span_of_impl(impl_def_id.to_def_id()).unwrap(), + missing_items_msg, + missing_trait_item_label, + missing_trait_item, + missing_trait_item_none, + }); } fn missing_items_must_implement_one_of_err( @@ -257,19 +249,11 @@ fn missing_items_must_implement_one_of_err( let missing_items_msg = missing_items.iter().map(Ident::to_string).collect::>().join("`, `"); - let mut err = struct_span_err!( - tcx.sess, - impl_span, - E0046, - "not all trait items implemented, missing one of: `{missing_items_msg}`", - ); - err.span_label(impl_span, format!("missing one of `{missing_items_msg}` in implementation")); - - if let Some(annotation_span) = annotation_span { - err.span_note(annotation_span, "required because of this annotation"); - } - - err.emit(); + tcx.sess.emit_err(errors::MissingOneOfTraitItem { + span: impl_span, + note: annotation_span, + missing_items_msg, + }); } fn default_body_is_unstable( @@ -281,25 +265,31 @@ fn default_body_is_unstable( issue: Option, ) { let missing_item_name = tcx.associated_item(item_did).name; - let use_of_unstable_library_feature_note = match reason { - Some(r) => format!("use of unstable library feature '{feature}': {r}"), - None => format!("use of unstable library feature '{feature}'"), + let (mut some_note, mut none_note, mut reason_str) = (false, false, String::new()); + match reason { + Some(r) => { + some_note = true; + reason_str = r.to_string(); + } + None => none_note = true, }; - let mut err = struct_span_err!( - tcx.sess, - impl_span, - E0046, - "not all trait items implemented, missing: `{missing_item_name}`", - ); - err.note(format!("default implementation of `{missing_item_name}` is unstable")); - err.note(use_of_unstable_library_feature_note); + let mut err = tcx.sess.create_err(errors::MissingTraitItemUnstable { + span: impl_span, + some_note, + none_note, + missing_item_name, + feature, + reason: reason_str, + }); + rustc_session::parse::add_feature_diagnostics_for_issue( &mut err, &tcx.sess.parse_sess, feature, rustc_feature::GateIssue::Library(issue), ); + err.emit(); } @@ -488,16 +478,18 @@ fn bad_variant_count<'tcx>(tcx: TyCtxt<'tcx>, adt: ty::AdtDef<'tcx>, sp: Span, d .iter() .map(|variant| tcx.hir().span_if_local(variant.def_id).unwrap()) .collect(); - let msg = format!("needs exactly one variant, but has {}", adt.variants().len(),); - let mut err = struct_span_err!(tcx.sess, sp, E0731, "transparent enum {msg}"); - err.span_label(sp, &msg); + let (mut spans, mut many) = (Vec::new(), None); if let [start @ .., end] = &*variant_spans { - for variant_span in start { - err.span_label(*variant_span, ""); - } - err.span_label(*end, &format!("too many variants in `{}`", tcx.def_path_str(did))); + spans = start.to_vec(); + many = Some(*end); } - err.emit(); + tcx.sess.emit_err(errors::TransparentEnumVariant { + span: sp, + spans, + many, + number: adt.variants().len(), + path: tcx.def_path_str(did), + }); } /// Emit an error when encountering two or more non-zero-sized fields in a transparent @@ -509,21 +501,21 @@ fn bad_non_zero_sized_fields<'tcx>( field_spans: impl Iterator, sp: Span, ) { - let msg = format!("needs at most one non-zero-sized field, but has {field_count}"); - let mut err = struct_span_err!( - tcx.sess, - sp, - E0690, - "{}transparent {} {}", - if adt.is_enum() { "the variant of a " } else { "" }, - adt.descr(), - msg, - ); - err.span_label(sp, &msg); - for sp in field_spans { - err.span_label(sp, "this field is non-zero-sized"); + if adt.is_enum() { + tcx.sess.emit_err(errors::TransparentNonZeroSizedEnum { + span: sp, + spans: field_spans.collect(), + field_count, + desc: adt.descr(), + }); + } else { + tcx.sess.emit_err(errors::TransparentNonZeroSized { + span: sp, + spans: field_spans.collect(), + field_count, + desc: adt.descr(), + }); } - err.emit(); } // FIXME: Consider moving this method to a more fitting place. diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs index b2ebbf993a1cc..c066c39676662 100644 --- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs +++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs @@ -360,7 +360,9 @@ fn check_gat_where_clauses(tcx: TyCtxt<'_>, associated_items: &[hir::TraitItemRe tcx, param_env, item_def_id, - tcx.explicit_item_bounds(item_def_id).to_vec(), + tcx.explicit_item_bounds(item_def_id) + .subst_identity_iter_copied() + .collect::>(), &FxIndexSet::default(), gat_def_id.def_id, gat_generics, @@ -1025,7 +1027,7 @@ fn check_type_defn<'tcx>(tcx: TyCtxt<'tcx>, item: &hir::Item<'tcx>, all_sized: b packed && { let ty = tcx.type_of(variant.fields.raw.last().unwrap().did).subst_identity(); let ty = tcx.erase_regions(ty); - if ty.needs_infer() { + if ty.has_infer() { tcx.sess .delay_span_bug(item.span, &format!("inference variables in {:?}", ty)); // Just treat unresolved type expression as if it needs drop. @@ -1125,7 +1127,7 @@ fn check_associated_type_bounds(wfcx: &WfCheckingCtxt<'_, '_>, item: ty::AssocIt let bounds = wfcx.tcx().explicit_item_bounds(item.def_id); debug!("check_associated_type_bounds: bounds={:?}", bounds); - let wf_obligations = bounds.iter().flat_map(|&(bound, bound_span)| { + let wf_obligations = bounds.subst_identity_iter_copied().flat_map(|(bound, bound_span)| { let normalized_bound = wfcx.normalize(span, None, bound); traits::wf::predicate_obligations( wfcx.infcx, @@ -1290,7 +1292,7 @@ fn check_where_clauses<'tcx>(wfcx: &WfCheckingCtxt<'_, 'tcx>, span: Span, def_id // Ignore dependent defaults -- that is, where the default of one type // parameter includes another (e.g., ``). In those cases, we can't // be sure if it will error or not as user might always specify the other. - if !ty.needs_subst() { + if !ty.has_param() { wfcx.register_wf_obligation( tcx.def_span(param.def_id), Some(WellFormedLoc::Ty(param.def_id.expect_local())), @@ -1306,7 +1308,7 @@ fn check_where_clauses<'tcx>(wfcx: &WfCheckingCtxt<'_, 'tcx>, span: Span, def_id // for `struct Foo` // we should eagerly error. let default_ct = tcx.const_param_default(param.def_id).subst_identity(); - if !default_ct.needs_subst() { + if !default_ct.has_param() { wfcx.register_wf_obligation( tcx.def_span(param.def_id), None, @@ -1340,7 +1342,7 @@ fn check_where_clauses<'tcx>(wfcx: &WfCheckingCtxt<'_, 'tcx>, span: Span, def_id if is_our_default(param) { let default_ty = tcx.type_of(param.def_id).subst_identity(); // ... and it's not a dependent default, ... - if !default_ty.needs_subst() { + if !default_ty.has_param() { // ... then substitute it with the default. return default_ty.into(); } @@ -1353,7 +1355,7 @@ fn check_where_clauses<'tcx>(wfcx: &WfCheckingCtxt<'_, 'tcx>, span: Span, def_id if is_our_default(param) { let default_ct = tcx.const_param_default(param.def_id).subst_identity(); // ... and it's not a dependent default, ... - if !default_ct.needs_subst() { + if !default_ct.has_param() { // ... then substitute it with the default. return default_ct.into(); } @@ -1574,21 +1576,14 @@ impl<'tcx> TypeVisitor> for ImplTraitInTraitFinder<'_, 'tcx> { && let hir::OpaqueTyOrigin::FnReturn(source) | hir::OpaqueTyOrigin::AsyncFn(source) = opaque.origin && source == self.fn_def_id { - let opaque_ty = tcx.fold_regions(unshifted_opaque_ty, |re, depth| { - if let ty::ReLateBound(index, bv) = re.kind() { - if depth != ty::INNERMOST { - return tcx.mk_re_error_with_message( - DUMMY_SP, - "we shouldn't walk non-predicate binders with `impl Trait`...", - ); - } - tcx.mk_re_late_bound(index.shifted_out_to_binder(self.depth), bv) - } else { - re + let opaque_ty = tcx.fold_regions(unshifted_opaque_ty, |re, _depth| { + match re.kind() { + ty::ReEarlyBound(_) | ty::ReFree(_) | ty::ReError(_) => re, + r => bug!("unexpected region: {r:?}"), } }); for (bound, bound_span) in tcx - .bound_explicit_item_bounds(opaque_ty.def_id) + .explicit_item_bounds(opaque_ty.def_id) .subst_iter_copied(tcx, opaque_ty.substs) { let bound = self.wfcx.normalize(bound_span, None, bound); diff --git a/compiler/rustc_hir_analysis/src/coherence/mod.rs b/compiler/rustc_hir_analysis/src/coherence/mod.rs index ac393ee15a684..cd2ec2bef20f9 100644 --- a/compiler/rustc_hir_analysis/src/coherence/mod.rs +++ b/compiler/rustc_hir_analysis/src/coherence/mod.rs @@ -5,6 +5,7 @@ // done by the orphan and overlap modules. Then we build up various // mappings. That mapping code resides here. +use crate::errors; use rustc_errors::{error_code, struct_span_err}; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_middle::ty::query::Providers; @@ -67,13 +68,7 @@ fn enforce_trait_manually_implementable( tcx.trait_def(trait_def_id).specialization_kind { if !tcx.features().specialization && !tcx.features().min_specialization { - tcx.sess - .struct_span_err( - impl_header_span, - "implementing `rustc_specialization_trait` traits is unstable", - ) - .help("add `#![feature(min_specialization)]` to the crate attributes to enable") - .emit(); + tcx.sess.emit_err(errors::SpecializationTrait { span: impl_header_span }); return; } } diff --git a/compiler/rustc_hir_analysis/src/coherence/orphan.rs b/compiler/rustc_hir_analysis/src/coherence/orphan.rs index 47c47de8cedba..89175c0ef7450 100644 --- a/compiler/rustc_hir_analysis/src/coherence/orphan.rs +++ b/compiler/rustc_hir_analysis/src/coherence/orphan.rs @@ -457,7 +457,7 @@ fn emit_newtype_suggestion_for_raw_ptr( ptr_ty: &ty::TypeAndMut<'_>, diag: &mut Diagnostic, ) { - if !self_ty.needs_subst() { + if !self_ty.has_param() { let mut_key = ptr_ty.mutbl.prefix_str(); let msg_sugg = "consider introducing a new wrapper type".to_owned(); let sugg = vec![ diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs index 9fe0c07814ed8..41547dd2a754d 100644 --- a/compiler/rustc_hir_analysis/src/collect.rs +++ b/compiler/rustc_hir_analysis/src/collect.rs @@ -386,8 +386,10 @@ impl<'tcx> AstConv<'tcx> for ItemCtxt<'tcx> { fn ct_infer(&self, ty: Ty<'tcx>, _: Option<&ty::GenericParamDef>, span: Span) -> Const<'tcx> { let ty = self.tcx.fold_regions(ty, |r, _| match *r { - ty::ReErased => self.tcx.lifetimes.re_static, - _ => r, + // This is never reached in practice. If it ever is reached, + // `ReErased` should be changed to `ReStatic`, and any other region + // left alone. + r => bug!("unexpected region: {r:?}"), }); self.tcx().const_error_with_message(ty, span, "bad placeholder constant") } diff --git a/compiler/rustc_hir_analysis/src/collect/item_bounds.rs b/compiler/rustc_hir_analysis/src/collect/item_bounds.rs index 2e56d24638cdb..80d6bc7db9e8f 100644 --- a/compiler/rustc_hir_analysis/src/collect/item_bounds.rs +++ b/compiler/rustc_hir_analysis/src/collect/item_bounds.rs @@ -79,14 +79,14 @@ fn opaque_type_bounds<'tcx>( pub(super) fn explicit_item_bounds( tcx: TyCtxt<'_>, def_id: LocalDefId, -) -> &'_ [(ty::Predicate<'_>, Span)] { +) -> ty::EarlyBinder<&'_ [(ty::Predicate<'_>, Span)]> { match tcx.opt_rpitit_info(def_id.to_def_id()) { // RPITIT's bounds are the same as opaque type bounds, but with // a projection self type. Some(ty::ImplTraitInTraitData::Trait { opaque_def_id, .. }) => { let item = tcx.hir().get_by_def_id(opaque_def_id.expect_local()).expect_item(); let opaque_ty = item.expect_opaque_ty(); - return opaque_type_bounds( + return ty::EarlyBinder(opaque_type_bounds( tcx, opaque_def_id.expect_local(), opaque_ty.bounds, @@ -95,7 +95,7 @@ pub(super) fn explicit_item_bounds( ty::InternalSubsts::identity_for_item(tcx, def_id), ), item.span, - ); + )); } // These should have been fed! Some(ty::ImplTraitInTraitData::Impl { .. }) => unreachable!(), @@ -103,7 +103,7 @@ pub(super) fn explicit_item_bounds( } let hir_id = tcx.hir().local_def_id_to_hir_id(def_id); - match tcx.hir().get(hir_id) { + let bounds = match tcx.hir().get(hir_id) { hir::Node::TraitItem(hir::TraitItem { kind: hir::TraitItemKind::Type(bounds, _), span, @@ -123,16 +123,18 @@ pub(super) fn explicit_item_bounds( opaque_type_bounds(tcx, def_id, bounds, item_ty, *span) } _ => bug!("item_bounds called on {:?}", def_id), - } + }; + ty::EarlyBinder(bounds) } pub(super) fn item_bounds( tcx: TyCtxt<'_>, def_id: DefId, ) -> ty::EarlyBinder<&'_ ty::List>> { - let bounds = tcx.mk_predicates_from_iter(util::elaborate( - tcx, - tcx.explicit_item_bounds(def_id).iter().map(|&(bound, _span)| bound), - )); - ty::EarlyBinder(bounds) + tcx.explicit_item_bounds(def_id).map_bound(|bounds| { + tcx.mk_predicates_from_iter(util::elaborate( + tcx, + bounds.iter().map(|&(bound, _span)| bound), + )) + }) } diff --git a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs index 3cb217335bda0..1c496f867a063 100644 --- a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs +++ b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs @@ -455,13 +455,9 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> { .collect::>(); if !infer_spans.is_empty() { - self.tcx.sess - .struct_span_err( - infer_spans, - "implicit types in closure signatures are forbidden when `for<...>` is present", - ) - .span_label(for_sp, "`for<...>` is here") - .emit(); + self.tcx + .sess + .emit_err(errors::ClosureImplicitHrtb { spans: infer_spans, for_sp }); } } diff --git a/compiler/rustc_hir_analysis/src/errors.rs b/compiler/rustc_hir_analysis/src/errors.rs index 2a3a683489ddd..f82169dee988e 100644 --- a/compiler/rustc_hir_analysis/src/errors.rs +++ b/compiler/rustc_hir_analysis/src/errors.rs @@ -631,3 +631,187 @@ pub(crate) struct SIMDFFIHighlyExperimental { pub span: Span, pub snip: String, } + +#[derive(Diagnostic)] + +pub enum ImplNotMarkedDefault { + #[diag(hir_analysis_impl_not_marked_default, code = "E0520")] + #[note] + Ok { + #[primary_span] + #[label] + span: Span, + #[label(hir_analysis_ok_label)] + ok_label: Span, + ident: Symbol, + }, + #[diag(hir_analysis_impl_not_marked_default_err, code = "E0520")] + #[note] + Err { + #[primary_span] + #[label] + span: Span, + cname: Symbol, + ident: Symbol, + }, +} + +#[derive(Diagnostic)] +#[diag(hir_analysis_missing_trait_item, code = "E0046")] +pub(crate) struct MissingTraitItem { + #[primary_span] + #[label] + pub span: Span, + #[subdiagnostic] + pub missing_trait_item_label: Vec, + #[subdiagnostic] + pub missing_trait_item: Vec, + #[subdiagnostic] + pub missing_trait_item_none: Vec, + pub missing_items_msg: String, +} + +#[derive(Subdiagnostic)] +#[label(hir_analysis_missing_trait_item_label)] +pub(crate) struct MissingTraitItemLabel { + #[primary_span] + pub span: Span, + pub item: Symbol, +} + +#[derive(Subdiagnostic)] +#[suggestion( + hir_analysis_missing_trait_item_suggestion, + style = "tool-only", + applicability = "has-placeholders", + code = "{code}" +)] +pub(crate) struct MissingTraitItemSuggestion { + #[primary_span] + pub span: Span, + pub code: String, + pub snippet: String, +} + +#[derive(Subdiagnostic)] +#[suggestion( + hir_analysis_missing_trait_item_suggestion, + style = "hidden", + applicability = "has-placeholders", + code = "{code}" +)] +pub(crate) struct MissingTraitItemSuggestionNone { + #[primary_span] + pub span: Span, + pub code: String, + pub snippet: String, +} + +#[derive(Diagnostic)] +#[diag(hir_analysis_missing_one_of_trait_item, code = "E0046")] +pub(crate) struct MissingOneOfTraitItem { + #[primary_span] + #[label] + pub span: Span, + #[note] + pub note: Option, + pub missing_items_msg: String, +} + +#[derive(Diagnostic)] +#[diag(hir_analysis_missing_trait_item_unstable, code = "E0046")] +#[note] +pub(crate) struct MissingTraitItemUnstable { + #[primary_span] + pub span: Span, + #[note(hir_analysis_some_note)] + pub some_note: bool, + #[note(hir_analysis_none_note)] + pub none_note: bool, + pub missing_item_name: Symbol, + pub feature: Symbol, + pub reason: String, +} + +#[derive(Diagnostic)] +#[diag(hir_analysis_transparent_enum_variant, code = "E0731")] +pub(crate) struct TransparentEnumVariant { + #[primary_span] + #[label] + pub span: Span, + #[label(hir_analysis_multi_label)] + pub spans: Vec, + #[label(hir_analysis_many_label)] + pub many: Option, + pub number: usize, + pub path: String, +} + +#[derive(Diagnostic)] +#[diag(hir_analysis_transparent_non_zero_sized_enum, code = "E0690")] +pub(crate) struct TransparentNonZeroSizedEnum<'a> { + #[primary_span] + #[label] + pub span: Span, + #[label(hir_analysis_labels)] + pub spans: Vec, + pub field_count: usize, + pub desc: &'a str, +} + +#[derive(Diagnostic)] +#[diag(hir_analysis_transparent_non_zero_sized, code = "E0690")] +pub(crate) struct TransparentNonZeroSized<'a> { + #[primary_span] + #[label] + pub span: Span, + #[label(hir_analysis_labels)] + pub spans: Vec, + pub field_count: usize, + pub desc: &'a str, +} + +#[derive(Diagnostic)] +#[diag(hir_analysis_too_large_static)] +pub(crate) struct TooLargeStatic { + #[primary_span] + pub span: Span, +} + +#[derive(Diagnostic)] +#[diag(hir_analysis_specialization_trait)] +#[help] +pub(crate) struct SpecializationTrait { + #[primary_span] + pub span: Span, +} + +#[derive(Diagnostic)] +#[diag(hir_analysis_closure_implicit_hrtb)] +pub(crate) struct ClosureImplicitHrtb { + #[primary_span] + pub spans: Vec, + #[label] + pub for_sp: Span, +} + +#[derive(Diagnostic)] +#[diag(hir_analysis_const_specialize)] +pub(crate) struct ConstSpecialize { + #[primary_span] + pub span: Span, +} + +#[derive(Diagnostic)] +#[diag(hir_analysis_static_specialize)] +pub(crate) struct StaticSpecialize { + #[primary_span] + pub span: Span, +} + +#[derive(Diagnostic)] +#[diag(hir_analysis_missing_tilde_const)] +pub(crate) struct MissingTildeConst { + #[primary_span] + pub span: Span, +} diff --git a/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs b/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs index eb2fc395223ed..c09457e1d65ec 100644 --- a/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs +++ b/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs @@ -65,8 +65,8 @@ //! cause use after frees with purely safe code in the same way as specializing //! on traits with methods can. -use crate::constrained_generic_params as cgp; use crate::errors::SubstsOnOverriddenImpl; +use crate::{constrained_generic_params as cgp, errors}; use rustc_data_structures::fx::FxHashSet; use rustc_hir as hir; @@ -137,9 +137,7 @@ fn check_constness(tcx: TyCtxt<'_>, impl1_def_id: LocalDefId, impl2_node: Node, if let hir::Constness::Const = impl2_constness { if let hir::Constness::NotConst = impl1_constness { - tcx.sess - .struct_span_err(span, "cannot specialize on const impl with non-const impl") - .emit(); + tcx.sess.emit_err(errors::ConstSpecialize { span }); } } } @@ -293,7 +291,7 @@ fn check_static_lifetimes<'tcx>( span: Span, ) { if tcx.any_free_region_meets(parent_substs, |r| r.is_static()) { - tcx.sess.struct_span_err(span, "cannot specialize on `'static` lifetime").emit(); + tcx.sess.emit_err(errors::StaticSpecialize { span }); } } @@ -368,7 +366,7 @@ fn check_predicates<'tcx>( wf::obligations(infcx, tcx.param_env(impl1_def_id), impl1_def_id, 0, arg, span) .unwrap(); - assert!(!obligations.needs_infer()); + assert!(!obligations.has_infer()); impl2_predicates .extend(traits::elaborate(tcx, obligations).map(|obligation| obligation.predicate)) } @@ -438,7 +436,7 @@ fn trait_predicates_eq<'tcx>( // the one on the base. match (trait_pred2.constness, trait_pred1.constness) { (ty::BoundConstness::ConstIfConst, ty::BoundConstness::NotConst) => { - tcx.sess.struct_span_err(span, "missing `~const` qualifier for specialization").emit(); + tcx.sess.emit_err(errors::MissingTildeConst { span }); } _ => {} } diff --git a/compiler/rustc_hir_analysis/src/variance/mod.rs b/compiler/rustc_hir_analysis/src/variance/mod.rs index 4d240e90b143d..e735b048d7343 100644 --- a/compiler/rustc_hir_analysis/src/variance/mod.rs +++ b/compiler/rustc_hir_analysis/src/variance/mod.rs @@ -153,8 +153,7 @@ fn variance_of_opaque(tcx: TyCtxt<'_>, item_def_id: LocalDefId) -> &[ty::Varianc let mut collector = OpaqueTypeLifetimeCollector { tcx, root_def_id: item_def_id.to_def_id(), variances }; let id_substs = ty::InternalSubsts::identity_for_item(tcx, item_def_id); - for pred in tcx.bound_explicit_item_bounds(item_def_id.to_def_id()).transpose_iter() { - let pred = pred.map_bound(|(pred, _)| *pred).subst(tcx, id_substs); + for (pred, _) in tcx.explicit_item_bounds(item_def_id).subst_iter_copied(tcx, id_substs) { debug!(?pred); // We only ignore opaque type substs if the opaque type is the outermost type. diff --git a/compiler/rustc_hir_typeck/messages.ftl b/compiler/rustc_hir_typeck/messages.ftl index 6d40df7d0ccfa..603ea1440e9ca 100644 --- a/compiler/rustc_hir_typeck/messages.ftl +++ b/compiler/rustc_hir_typeck/messages.ftl @@ -62,3 +62,16 @@ hir_typeck_fru_suggestion = [NONE]{""} *[other] {" "}from `{$expr}` }, separate the last named field with a comma + +hir_typeck_const_select_must_be_const = this argument must be a `const fn` + .help = consult the documentation on `const_eval_select` for more information + +hir_typeck_const_select_must_be_fn = this argument must be a function item + .note = expected a function item, found {$ty} + .help = consult the documentation on `const_eval_select` for more information + +hir_typeck_union_pat_multiple_fields = union patterns should have exactly one field +hir_typeck_union_pat_dotdot = `..` cannot be used in union patterns + +hir_typeck_arg_mismatch_indeterminate = argument type mismatch was detected, but rustc had trouble determining where + .note = we would appreciate a bug report: https://github.com/rust-lang/rust/issues/new diff --git a/compiler/rustc_hir_typeck/src/_match.rs b/compiler/rustc_hir_typeck/src/_match.rs index 6c2ce62722a54..aefde8109a07a 100644 --- a/compiler/rustc_hir_typeck/src/_match.rs +++ b/compiler/rustc_hir_typeck/src/_match.rs @@ -530,7 +530,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { for ty in [first_ty, second_ty] { for (pred, _) in self .tcx - .bound_explicit_item_bounds(rpit_def_id) + .explicit_item_bounds(rpit_def_id) .subst_iter_copied(self.tcx, substs) { let pred = pred.kind().rebind(match pred.kind().skip_binder() { diff --git a/compiler/rustc_hir_typeck/src/closure.rs b/compiler/rustc_hir_typeck/src/closure.rs index 8c2495e1dd8c5..7046269c2de22 100644 --- a/compiler/rustc_hir_typeck/src/closure.rs +++ b/compiler/rustc_hir_typeck/src/closure.rs @@ -172,7 +172,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ty::Alias(ty::Opaque, ty::AliasTy { def_id, substs, .. }) => self .deduce_closure_signature_from_predicates( expected_ty, - self.tcx.bound_explicit_item_bounds(def_id).subst_iter_copied(self.tcx, substs), + self.tcx.explicit_item_bounds(def_id).subst_iter_copied(self.tcx, substs), ), ty::Dynamic(ref object_type, ..) => { let sig = object_type.projection_bounds().find_map(|pb| { @@ -713,13 +713,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } ty::Alias(ty::Opaque, ty::AliasTy { def_id, substs, .. }) => self .tcx - .bound_explicit_item_bounds(def_id) + .explicit_item_bounds(def_id) .subst_iter_copied(self.tcx, substs) .find_map(|(p, s)| get_future_output(p, s))?, ty::Error(_) => return None, ty::Alias(ty::Projection, proj) if self.tcx.is_impl_trait_in_trait(proj.def_id) => self .tcx - .bound_explicit_item_bounds(proj.def_id) + .explicit_item_bounds(proj.def_id) .subst_iter_copied(self.tcx, proj.substs) .find_map(|(p, s)| get_future_output(p, s))?, _ => span_bug!( diff --git a/compiler/rustc_hir_typeck/src/demand.rs b/compiler/rustc_hir_typeck/src/demand.rs index 525acfdaa8124..b8222820cf7a4 100644 --- a/compiler/rustc_hir_typeck/src/demand.rs +++ b/compiler/rustc_hir_typeck/src/demand.rs @@ -1508,6 +1508,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // FIXME(compiler-errors): We can actually do this if the checked_ty is // `steps` layers of boxes, not just one, but this is easier and most likely. || (checked_ty.is_box() && steps == 1) + // We can always deref a binop that takes its arguments by ref. + || matches!( + self.tcx.hir().get_parent(expr.hir_id), + hir::Node::Expr(hir::Expr { kind: hir::ExprKind::Binary(op, ..), .. }) + if !op.node.is_by_value() + ) { let deref_kind = if checked_ty.is_box() { "unboxing the value" diff --git a/compiler/rustc_hir_typeck/src/errors.rs b/compiler/rustc_hir_typeck/src/errors.rs index 5be78416e6128..48c40d216034e 100644 --- a/compiler/rustc_hir_typeck/src/errors.rs +++ b/compiler/rustc_hir_typeck/src/errors.rs @@ -228,3 +228,42 @@ impl HelpUseLatestEdition { } } } + +#[derive(Diagnostic)] +#[diag(hir_typeck_const_select_must_be_const)] +#[help] +pub struct ConstSelectMustBeConst { + #[primary_span] + pub span: Span, +} + +#[derive(Diagnostic)] +#[diag(hir_typeck_const_select_must_be_fn)] +#[note] +#[help] +pub struct ConstSelectMustBeFn<'a> { + #[primary_span] + pub span: Span, + pub ty: Ty<'a>, +} + +#[derive(Diagnostic)] +#[diag(hir_typeck_union_pat_multiple_fields)] +pub struct UnionPatMultipleFields { + #[primary_span] + pub span: Span, +} + +#[derive(Diagnostic)] +#[diag(hir_typeck_union_pat_dotdot)] +pub struct UnionPatDotDot { + #[primary_span] + pub span: Span, +} + +#[derive(Diagnostic)] +#[diag(hir_typeck_arg_mismatch_indeterminate)] +pub struct ArgMismatchIndeterminate { + #[primary_span] + pub span: Span, +} diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs index 955463c14348c..f42c825d9e8b1 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs @@ -2,8 +2,8 @@ use crate::coercion::CoerceMany; use crate::fn_ctxt::arg_matrix::{ArgMatrix, Compatibility, Error, ExpectedIdx, ProvidedIdx}; use crate::gather_locals::Declaration; use crate::method::MethodCallee; -use crate::Expectation::*; use crate::TupleArgumentsFlag::*; +use crate::{errors, Expectation::*}; use crate::{ struct_span_err, BreakableCtxt, Diverges, Expectation, FnCtxt, LocalTy, Needs, RawTy, TupleArgumentsFlag, @@ -283,19 +283,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if idx == 1 && !self.tcx.is_const_fn_raw(*def_id) { self.tcx .sess - .struct_span_err(provided_arg.span, "this argument must be a `const fn`") - .help("consult the documentation on `const_eval_select` for more information") - .emit(); + .emit_err(errors::ConstSelectMustBeConst { span: provided_arg.span }); } } else { - self.tcx - .sess - .struct_span_err(provided_arg.span, "this argument must be a function item") - .note(format!("expected a function item, found {checked_ty}")) - .help( - "consult the documentation on `const_eval_select` for more information", - ) - .emit(); + self.tcx.sess.emit_err(errors::ConstSelectMustBeFn { + span: provided_arg.span, + ty: checked_ty, + }); } } @@ -744,17 +738,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if cfg!(debug_assertions) { span_bug!(error_span, "expected errors from argument matrix"); } else { - tcx.sess - .struct_span_err( - error_span, - "argument type mismatch was detected, \ - but rustc had trouble determining where", - ) - .note( - "we would appreciate a bug report: \ - https://github.com/rust-lang/rust/issues/new", - ) - .emit(); + tcx.sess.emit_err(errors::ArgMismatchIndeterminate { span: error_span }); } return; } diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs index 3ba679df3ed09..73a7bbebb6581 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs @@ -168,7 +168,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ocx.normalize(&ObligationCause::dummy(), self.param_env, fn_sig); if ocx.select_all_or_error().is_empty() { let normalized_fn_sig = self.resolve_vars_if_possible(normalized_fn_sig); - if !normalized_fn_sig.needs_infer() { + if !normalized_fn_sig.has_infer() { return normalized_fn_sig; } } diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs index eef2b5009c82d..82fc1256bba64 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs @@ -1384,7 +1384,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } let item_ty = self.tcx.type_of(item.def_id).subst_identity(); // FIXME(compiler-errors): This check is *so* rudimentary - if item_ty.needs_subst() { + if item_ty.has_param() { return false; } if self.can_coerce(item_ty, expected_ty) { diff --git a/compiler/rustc_hir_typeck/src/generator_interior/drop_ranges/record_consumed_borrow.rs b/compiler/rustc_hir_typeck/src/generator_interior/drop_ranges/record_consumed_borrow.rs index fa3887362d99c..5136d895f2268 100644 --- a/compiler/rustc_hir_typeck/src/generator_interior/drop_ranges/record_consumed_borrow.rs +++ b/compiler/rustc_hir_typeck/src/generator_interior/drop_ranges/record_consumed_borrow.rs @@ -202,7 +202,7 @@ impl<'tcx> expr_use_visitor::Delegate<'tcx> for ExprUseDelegate<'tcx> { // If the type being assigned needs dropped, then the mutation counts as a borrow // since it is essentially doing `Drop::drop(&mut x); x = new_value;`. let ty = self.tcx.erase_regions(assignee_place.place.base_ty); - if ty.needs_infer() { + if ty.has_infer() { self.tcx.sess.delay_span_bug( self.tcx.hir().span(assignee_place.hir_id), &format!("inference variables in {ty}"), diff --git a/compiler/rustc_hir_typeck/src/generator_interior/mod.rs b/compiler/rustc_hir_typeck/src/generator_interior/mod.rs index 8feef332de8a7..915280a5bea02 100644 --- a/compiler/rustc_hir_typeck/src/generator_interior/mod.rs +++ b/compiler/rustc_hir_typeck/src/generator_interior/mod.rs @@ -460,7 +460,7 @@ impl<'a, 'tcx> Visitor<'tcx> for InteriorVisitor<'a, 'tcx> { // Avoid ICEs in needs_drop. let ty = self.fcx.resolve_vars_if_possible(ty); let ty = self.fcx.tcx.erase_regions(ty); - if ty.needs_infer() { + if ty.has_infer() { self.fcx .tcx .sess @@ -571,7 +571,7 @@ fn check_must_not_suspend_ty<'tcx>( // FIXME: support adding the attribute to TAITs ty::Alias(ty::Opaque, ty::AliasTy { def_id: def, .. }) => { let mut has_emitted = false; - for &(predicate, _) in fcx.tcx.explicit_item_bounds(def) { + for &(predicate, _) in fcx.tcx.explicit_item_bounds(def).skip_binder() { // We only look at the `DefId`, so it is safe to skip the binder here. if let ty::PredicateKind::Clause(ty::Clause::Trait(ref poly_trait_predicate)) = predicate.kind().skip_binder() diff --git a/compiler/rustc_hir_typeck/src/method/probe.rs b/compiler/rustc_hir_typeck/src/method/probe.rs index 4fd778910bacb..1a429142e0148 100644 --- a/compiler/rustc_hir_typeck/src/method/probe.rs +++ b/compiler/rustc_hir_typeck/src/method/probe.rs @@ -2032,7 +2032,7 @@ impl<'tcx> Candidate<'tcx> { // means they are safe to put into the // `WhereClausePick`. assert!( - !trait_ref.skip_binder().substs.needs_infer() + !trait_ref.skip_binder().substs.has_infer() && !trait_ref.skip_binder().substs.has_placeholders() ); diff --git a/compiler/rustc_hir_typeck/src/pat.rs b/compiler/rustc_hir_typeck/src/pat.rs index 7160d1c67b251..d69a16d45ae54 100644 --- a/compiler/rustc_hir_typeck/src/pat.rs +++ b/compiler/rustc_hir_typeck/src/pat.rs @@ -1,4 +1,4 @@ -use crate::{FnCtxt, RawTy}; +use crate::{errors, FnCtxt, RawTy}; use rustc_ast as ast; use rustc_data_structures::fx::FxHashMap; use rustc_errors::{ @@ -1410,12 +1410,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // Report an error if an incorrect number of fields was specified. if adt.is_union() { if fields.len() != 1 { - tcx.sess - .struct_span_err(pat.span, "union patterns should have exactly one field") - .emit(); + tcx.sess.emit_err(errors::UnionPatMultipleFields { span: pat.span }); } if has_rest_pat { - tcx.sess.struct_span_err(pat.span, "`..` cannot be used in union patterns").emit(); + tcx.sess.emit_err(errors::UnionPatDotDot { span: pat.span }); } } else if !unmentioned_fields.is_empty() { let accessible_unmentioned_fields: Vec<_> = unmentioned_fields diff --git a/compiler/rustc_hir_typeck/src/writeback.rs b/compiler/rustc_hir_typeck/src/writeback.rs index 9432a5840b276..817918257beb4 100644 --- a/compiler/rustc_hir_typeck/src/writeback.rs +++ b/compiler/rustc_hir_typeck/src/writeback.rs @@ -133,7 +133,7 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> { fn write_ty_to_typeck_results(&mut self, hir_id: hir::HirId, ty: Ty<'tcx>) { debug!("write_ty_to_typeck_results({:?}, {:?})", hir_id, ty); - assert!(!ty.needs_infer() && !ty.has_placeholders() && !ty.has_free_regions()); + assert!(!ty.has_infer() && !ty.has_placeholders() && !ty.has_free_regions()); self.typeck_results.node_types_mut().insert(hir_id, ty); } @@ -508,7 +508,7 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> { fcx_typeck_results.user_provided_types().items().map(|(local_id, c_ty)| { let hir_id = hir::HirId { owner: common_hir_owner, local_id }; - if cfg!(debug_assertions) && c_ty.needs_infer() { + if cfg!(debug_assertions) && c_ty.has_infer() { span_bug!( hir_id.to_span(self.fcx.tcx), "writeback: `{:?}` has inference variables", @@ -527,7 +527,7 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> { self.typeck_results.user_provided_sigs.extend( fcx_typeck_results.user_provided_sigs.items().map(|(&def_id, c_sig)| { - if cfg!(debug_assertions) && c_sig.needs_infer() { + if cfg!(debug_assertions) && c_sig.has_infer() { span_bug!( self.fcx.tcx.def_span(def_id), "writeback: `{:?}` has inference variables", @@ -618,7 +618,7 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> { if let Some(substs) = self.fcx.typeck_results.borrow().node_substs_opt(hir_id) { let substs = self.resolve(substs, &span); debug!("write_substs_to_tcx({:?}, {:?})", hir_id, substs); - assert!(!substs.needs_infer() && !substs.has_placeholders()); + assert!(!substs.has_infer() && !substs.has_placeholders()); self.typeck_results.node_substs_mut().insert(hir_id, substs); } } @@ -693,7 +693,7 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> { { let hir_id = hir::HirId { owner: common_hir_owner, local_id }; - if cfg!(debug_assertions) && container.needs_infer() { + if cfg!(debug_assertions) && container.has_infer() { span_bug!( hir_id.to_span(self.fcx.tcx), "writeback: `{:?}` has inference variables", @@ -711,7 +711,7 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> { { let mut resolver = Resolver::new(self.fcx, span, self.body); let x = x.fold_with(&mut resolver); - if cfg!(debug_assertions) && x.needs_infer() { + if cfg!(debug_assertions) && x.has_infer() { span_bug!(span.to_span(self.fcx.tcx), "writeback: `{:?}` has inference variables", x); } diff --git a/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs b/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs index e6e1bc0393fcd..c29f652034fc0 100644 --- a/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs +++ b/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs @@ -564,12 +564,12 @@ impl<'cx, 'tcx> Canonicalizer<'cx, 'tcx> { let _inside_canonical_ctxt_guard = infcx.set_canonicalization_ctxt(); let needs_canonical_flags = if canonicalize_region_mode.any() { - TypeFlags::NEEDS_INFER | + TypeFlags::HAS_INFER | TypeFlags::HAS_FREE_REGIONS | // `HAS_RE_PLACEHOLDER` implies `HAS_FREE_REGIONS` TypeFlags::HAS_TY_PLACEHOLDER | TypeFlags::HAS_CT_PLACEHOLDER } else { - TypeFlags::NEEDS_INFER + TypeFlags::HAS_INFER | TypeFlags::HAS_RE_PLACEHOLDER | TypeFlags::HAS_TY_PLACEHOLDER | TypeFlags::HAS_CT_PLACEHOLDER @@ -600,7 +600,7 @@ impl<'cx, 'tcx> Canonicalizer<'cx, 'tcx> { // Once we have canonicalized `out_value`, it should not // contain anything that ties it to this inference context // anymore. - debug_assert!(!out_value.needs_infer() && !out_value.has_placeholders()); + debug_assert!(!out_value.has_infer() && !out_value.has_placeholders()); let canonical_variables = tcx.mk_canonical_var_infos(&canonicalizer.universe_canonicalized_variables()); diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs index b0c376a26f614..547f851526f0a 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs @@ -402,7 +402,7 @@ impl<'tcx> InferCtxt<'tcx> { let future_trait = self.tcx.require_lang_item(LangItem::Future, None); let item_def_id = self.tcx.associated_item_def_ids(future_trait)[0]; - self.tcx.bound_explicit_item_bounds(def_id).subst_iter_copied(self.tcx, substs).find_map( + self.tcx.explicit_item_bounds(def_id).subst_iter_copied(self.tcx, substs).find_map( |(predicate, _)| { predicate .kind() diff --git a/compiler/rustc_infer/src/infer/freshen.rs b/compiler/rustc_infer/src/infer/freshen.rs index d89f63e5c53e9..0219167f6e58b 100644 --- a/compiler/rustc_infer/src/infer/freshen.rs +++ b/compiler/rustc_infer/src/infer/freshen.rs @@ -127,7 +127,7 @@ impl<'a, 'tcx> TypeFolder> for TypeFreshener<'a, 'tcx> { #[inline] fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> { - if !t.needs_infer() && !t.has_erasable_regions() { + if !t.has_infer() && !t.has_erasable_regions() { t } else { match *t.kind() { diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index 1cd09cde0fc08..1cfdb791cd6ae 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -1327,7 +1327,7 @@ impl<'tcx> InferCtxt<'tcx> { where T: TypeFoldable>, { - if !value.needs_infer() { + if !value.has_infer() { return value; // Avoid duplicated subst-folding. } let mut r = InferenceLiteralEraser { tcx: self.tcx }; @@ -1365,7 +1365,7 @@ impl<'tcx> InferCtxt<'tcx> { pub fn fully_resolve>>(&self, value: T) -> FixupResult<'tcx, T> { let value = resolve::fully_resolve(self, value); assert!( - value.as_ref().map_or(true, |value| !value.needs_infer()), + value.as_ref().map_or(true, |value| !value.has_infer()), "`{value:?}` is not fully resolved" ); value diff --git a/compiler/rustc_infer/src/infer/opaque_types.rs b/compiler/rustc_infer/src/infer/opaque_types.rs index 680465bdab690..334395945ea96 100644 --- a/compiler/rustc_infer/src/infer/opaque_types.rs +++ b/compiler/rustc_infer/src/infer/opaque_types.rs @@ -540,7 +540,7 @@ impl<'tcx> InferCtxt<'tcx> { .obligations; } - let item_bounds = tcx.bound_explicit_item_bounds(def_id.to_def_id()); + let item_bounds = tcx.explicit_item_bounds(def_id); for (predicate, _) in item_bounds.subst_iter_copied(tcx, substs) { let predicate = predicate.fold_with(&mut BottomUpFolder { diff --git a/compiler/rustc_infer/src/infer/outlives/obligations.rs b/compiler/rustc_infer/src/infer/outlives/obligations.rs index 2f5e2e417a6fd..d3f7eeff9976c 100644 --- a/compiler/rustc_infer/src/infer/outlives/obligations.rs +++ b/compiler/rustc_infer/src/infer/outlives/obligations.rs @@ -347,7 +347,7 @@ where let is_opaque = alias_ty.kind(self.tcx) == ty::Opaque; if approx_env_bounds.is_empty() && trait_bounds.is_empty() - && (alias_ty.needs_infer() || is_opaque) + && (alias_ty.has_infer() || is_opaque) { debug!("no declared bounds"); let opt_variances = is_opaque.then(|| self.tcx.variances_of(alias_ty.def_id)); diff --git a/compiler/rustc_infer/src/infer/resolve.rs b/compiler/rustc_infer/src/infer/resolve.rs index 4f49f4165074f..3c41e8b37838a 100644 --- a/compiler/rustc_infer/src/infer/resolve.rs +++ b/compiler/rustc_infer/src/infer/resolve.rs @@ -213,7 +213,7 @@ impl<'a, 'tcx> FallibleTypeFolder> for FullTypeResolver<'a, 'tcx> { } fn try_fold_ty(&mut self, t: Ty<'tcx>) -> Result, Self::Error> { - if !t.needs_infer() { + if !t.has_infer() { Ok(t) // micro-optimize -- if there is nothing in this type that this fold affects... } else { let t = self.infcx.shallow_resolve(t); @@ -243,7 +243,7 @@ impl<'a, 'tcx> FallibleTypeFolder> for FullTypeResolver<'a, 'tcx> { } fn try_fold_const(&mut self, c: ty::Const<'tcx>) -> Result, Self::Error> { - if !c.needs_infer() { + if !c.has_infer() { Ok(c) // micro-optimize -- if there is nothing in this const that this fold affects... } else { let c = self.infcx.shallow_resolve(c); diff --git a/compiler/rustc_lint/messages.ftl b/compiler/rustc_lint/messages.ftl index 3d1b8f8ed95ac..3c6dbb466db7a 100644 --- a/compiler/rustc_lint/messages.ftl +++ b/compiler/rustc_lint/messages.ftl @@ -99,6 +99,8 @@ lint_diag_out_of_impl = lint_untranslatable_diag = diagnostics should be created using translatable messages +lint_trivial_untranslatable_diag = diagnostic with static strings only + lint_bad_opt_access = {$msg} lint_cstring_ptr = getting the inner pointer of a temporary `CString` diff --git a/compiler/rustc_lint/src/enum_intrinsics_non_enums.rs b/compiler/rustc_lint/src/enum_intrinsics_non_enums.rs index f1ba192f2bcc0..2ce28f3a049e8 100644 --- a/compiler/rustc_lint/src/enum_intrinsics_non_enums.rs +++ b/compiler/rustc_lint/src/enum_intrinsics_non_enums.rs @@ -42,7 +42,7 @@ declare_lint_pass!(EnumIntrinsicsNonEnums => [ENUM_INTRINSICS_NON_ENUMS]); /// Returns `true` if we know for sure that the given type is not an enum. Note that for cases where /// the type is generic, we can't be certain if it will be an enum so we have to assume that it is. fn is_non_enum(t: Ty<'_>) -> bool { - !t.is_enum() && !t.needs_subst() + !t.is_enum() && !t.has_param() } fn enforce_mem_discriminant( diff --git a/compiler/rustc_lint/src/internal.rs b/compiler/rustc_lint/src/internal.rs index 4ac589c2e10f0..595b50c4063ca 100644 --- a/compiler/rustc_lint/src/internal.rs +++ b/compiler/rustc_lint/src/internal.rs @@ -4,6 +4,7 @@ use crate::lints::{ BadOptAccessDiag, DefaultHashTypesDiag, DiagOutOfImpl, LintPassByHand, NonExistentDocKeyword, QueryInstability, TyQualified, TykindDiag, TykindKind, UntranslatableDiag, + UntranslatableDiagnosticTrivial, }; use crate::{EarlyContext, EarlyLintPass, LateContext, LateLintPass, LintContext}; use rustc_ast as ast; @@ -366,7 +367,15 @@ declare_tool_lint! { report_in_external_macro: true } -declare_lint_pass!(Diagnostics => [ UNTRANSLATABLE_DIAGNOSTIC, DIAGNOSTIC_OUTSIDE_OF_IMPL ]); +declare_tool_lint! { + /// The `untranslatable_diagnostic_trivial` lint detects diagnostics created using only static strings. + pub rustc::UNTRANSLATABLE_DIAGNOSTIC_TRIVIAL, + Deny, + "prevent creation of diagnostics which cannot be translated, which use only static strings", + report_in_external_macro: true +} + +declare_lint_pass!(Diagnostics => [ UNTRANSLATABLE_DIAGNOSTIC, DIAGNOSTIC_OUTSIDE_OF_IMPL, UNTRANSLATABLE_DIAGNOSTIC_TRIVIAL ]); impl LateLintPass<'_> for Diagnostics { fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) { @@ -423,6 +432,75 @@ impl LateLintPass<'_> for Diagnostics { } } +impl EarlyLintPass for Diagnostics { + #[allow(unused_must_use)] + fn check_stmt(&mut self, cx: &EarlyContext<'_>, stmt: &ast::Stmt) { + // Looking for a straight chain of method calls from 'struct_span_err' to 'emit'. + let ast::StmtKind::Semi(expr) = &stmt.kind else { + return; + }; + let ast::ExprKind::MethodCall(meth) = &expr.kind else { + return; + }; + if meth.seg.ident.name != sym::emit || !meth.args.is_empty() { + return; + } + let mut segments = vec![]; + let mut cur = &meth.receiver; + let fake = &[].into(); + loop { + match &cur.kind { + ast::ExprKind::Call(func, args) => { + if let ast::ExprKind::Path(_, path) = &func.kind { + segments.push((path.segments.last().unwrap().ident.name, args)) + } + break; + } + ast::ExprKind::MethodCall(method) => { + segments.push((method.seg.ident.name, &method.args)); + cur = &method.receiver; + } + ast::ExprKind::MacCall(mac) => { + segments.push((mac.path.segments.last().unwrap().ident.name, fake)); + break; + } + _ => { + break; + } + } + } + segments.reverse(); + if segments.is_empty() { + return; + } + if segments[0].0.as_str() != "struct_span_err" { + return; + } + if !segments.iter().all(|(name, args)| { + let arg = match name.as_str() { + "struct_span_err" | "span_note" | "span_label" | "span_help" => &args[1], + "note" | "help" => &args[0], + _ => { + return false; + } + }; + if let ast::ExprKind::Lit(lit) = arg.kind + && let ast::token::LitKind::Str = lit.kind { + true + } else { + false + } + }) { + return; + } + cx.emit_spanned_lint( + UNTRANSLATABLE_DIAGNOSTIC_TRIVIAL, + stmt.span, + UntranslatableDiagnosticTrivial, + ); + } +} + declare_tool_lint! { /// The `bad_opt_access` lint detects accessing options by field instead of /// the wrapper function. diff --git a/compiler/rustc_lint/src/lib.rs b/compiler/rustc_lint/src/lib.rs index 76f0725790777..319eb2ea445ed 100644 --- a/compiler/rustc_lint/src/lib.rs +++ b/compiler/rustc_lint/src/lib.rs @@ -518,6 +518,7 @@ fn register_internals(store: &mut LintStore) { store.register_lints(&TyTyKind::get_lints()); store.register_late_pass(|_| Box::new(TyTyKind)); store.register_lints(&Diagnostics::get_lints()); + store.register_early_pass(|| Box::new(Diagnostics)); store.register_late_pass(|_| Box::new(Diagnostics)); store.register_lints(&BadOptAccess::get_lints()); store.register_late_pass(|_| Box::new(BadOptAccess)); diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs index 1d5e02369f528..848f6a9ecb532 100644 --- a/compiler/rustc_lint/src/lints.rs +++ b/compiler/rustc_lint/src/lints.rs @@ -820,6 +820,10 @@ pub struct DiagOutOfImpl; #[diag(lint_untranslatable_diag)] pub struct UntranslatableDiag; +#[derive(LintDiagnostic)] +#[diag(lint_trivial_untranslatable_diag)] +pub struct UntranslatableDiagnosticTrivial; + #[derive(LintDiagnostic)] #[diag(lint_bad_opt_access)] pub struct BadOptAccessDiag<'a> { diff --git a/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs b/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs index f9d43fe220036..15715c8fca039 100644 --- a/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs +++ b/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs @@ -74,7 +74,7 @@ impl<'tcx> LateLintPass<'tcx> for OpaqueHiddenInferredBound { // For every projection predicate in the opaque type's explicit bounds, // check that the type that we're assigning actually satisfies the bounds // of the associated type. - for &(pred, pred_span) in cx.tcx.explicit_item_bounds(def_id) { + for (pred, pred_span) in cx.tcx.explicit_item_bounds(def_id).subst_identity_iter_copied() { // Liberate bound regions in the predicate since we // don't actually care about lifetimes in this check. let predicate = cx.tcx.liberate_late_bound_regions(def_id, pred.kind()); @@ -112,7 +112,7 @@ impl<'tcx> LateLintPass<'tcx> for OpaqueHiddenInferredBound { // with `impl Send: OtherTrait`. for (assoc_pred, assoc_pred_span) in cx .tcx - .bound_explicit_item_bounds(proj.projection_ty.def_id) + .explicit_item_bounds(proj.projection_ty.def_id) .subst_iter_copied(cx.tcx, &proj.projection_ty.substs) { let assoc_pred = assoc_pred.fold_with(proj_replacer); diff --git a/compiler/rustc_lint/src/unused.rs b/compiler/rustc_lint/src/unused.rs index d677d51881e0e..eb175e96997b3 100644 --- a/compiler/rustc_lint/src/unused.rs +++ b/compiler/rustc_lint/src/unused.rs @@ -254,7 +254,7 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults { } ty::Adt(def, _) => is_def_must_use(cx, def.did(), span), ty::Alias(ty::Opaque, ty::AliasTy { def_id: def, .. }) => { - elaborate(cx.tcx, cx.tcx.explicit_item_bounds(def).iter().cloned()) + elaborate(cx.tcx, cx.tcx.explicit_item_bounds(def).subst_identity_iter_copied()) // We only care about self bounds for the impl-trait .filter_only_self() .find_map(|(pred, _span)| { diff --git a/compiler/rustc_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs index 64245a0460d8f..a310cbb80293a 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder.rs @@ -23,7 +23,7 @@ use rustc_middle::mir::interpret::{AllocDecodingSession, AllocDecodingState}; use rustc_middle::ty::codec::TyDecoder; use rustc_middle::ty::fast_reject::SimplifiedType; use rustc_middle::ty::GeneratorDiagnosticData; -use rustc_middle::ty::{self, ParameterizedOverTcx, Ty, TyCtxt, Visibility}; +use rustc_middle::ty::{self, ParameterizedOverTcx, Predicate, Ty, TyCtxt, Visibility}; use rustc_serialize::opaque::MemDecoder; use rustc_serialize::{Decodable, Decoder}; use rustc_session::cstore::{ @@ -373,16 +373,6 @@ impl<'a, 'tcx> TyDecoder for DecodeContext<'a, 'tcx> { self.tcx() } - #[inline] - fn peek_byte(&self) -> u8 { - self.opaque.data[self.opaque.position()] - } - - #[inline] - fn position(&self) -> usize { - self.opaque.position() - } - fn cached_ty_for_shorthand(&mut self, shorthand: usize, or_insert_with: F) -> Ty<'tcx> where F: FnOnce(&mut Self) -> Ty<'tcx>, @@ -404,7 +394,7 @@ impl<'a, 'tcx> TyDecoder for DecodeContext<'a, 'tcx> { where F: FnOnce(&mut Self) -> R, { - let new_opaque = MemDecoder::new(self.opaque.data, pos); + let new_opaque = MemDecoder::new(self.opaque.data(), pos); let old_opaque = mem::replace(&mut self.opaque, new_opaque); let old_state = mem::replace(&mut self.lazy_state, LazyState::NoNode); let r = f(self); @@ -625,17 +615,12 @@ impl<'a, 'tcx> Decodable> for Symbol { SYMBOL_OFFSET => { // read str offset let pos = d.read_usize(); - let old_pos = d.opaque.position(); // move to str offset and read - d.opaque.set_position(pos); - let s = d.read_str(); - let sym = Symbol::intern(s); - - // restore position - d.opaque.set_position(old_pos); - - sym + d.opaque.with_position(pos, |d| { + let s = d.read_str(); + Symbol::intern(s) + }) } SYMBOL_PREINTERNED => { let symbol_index = d.read_u32(); @@ -857,6 +842,20 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { ) } + fn get_explicit_item_bounds( + self, + index: DefIndex, + tcx: TyCtxt<'tcx>, + ) -> ty::EarlyBinder<&'tcx [(Predicate<'tcx>, Span)]> { + let lazy = self.root.tables.explicit_item_bounds.get(self, index); + let output = if lazy.is_default() { + &mut [] + } else { + tcx.arena.alloc_from_iter(lazy.decode((self, tcx))) + }; + ty::EarlyBinder(&*output) + } + fn get_variant(self, kind: &DefKind, index: DefIndex, parent_did: DefId) -> ty::VariantDef { let adt_kind = match kind { DefKind::Variant => ty::AdtKind::Enum, diff --git a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs index 141980912b1d6..4a3b783c63670 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs @@ -203,7 +203,7 @@ impl IntoArgs for (CrateNum, SimplifiedType) { } provide! { tcx, def_id, other, cdata, - explicit_item_bounds => { table_defaulted_array } + explicit_item_bounds => { cdata.get_explicit_item_bounds(def_id.index, tcx) } explicit_predicates_of => { table } generics_of => { table } inferred_outlives_of => { table_defaulted_array } diff --git a/compiler/rustc_metadata/src/rmeta/def_path_hash_map.rs b/compiler/rustc_metadata/src/rmeta/def_path_hash_map.rs index 02cab561b8f61..05402a58701f1 100644 --- a/compiler/rustc_metadata/src/rmeta/def_path_hash_map.rs +++ b/compiler/rustc_metadata/src/rmeta/def_path_hash_map.rs @@ -45,9 +45,6 @@ impl<'a, 'tcx> Encodable> for DefPathHashMapRef<'tcx> { impl<'a, 'tcx> Decodable> for DefPathHashMapRef<'static> { fn decode(d: &mut DecodeContext<'a, 'tcx>) -> DefPathHashMapRef<'static> { - // Import TyDecoder so we can access the DecodeContext::position() method - use crate::rustc_middle::ty::codec::TyDecoder; - let len = d.read_usize(); let pos = d.position(); let o = slice_owned(d.blob().clone(), |blob| &blob[pos..pos + len]); diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index 17a9daee7d038..f5ffdd27cae3f 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -1423,7 +1423,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { fn encode_explicit_item_bounds(&mut self, def_id: DefId) { debug!("EncodeContext::encode_explicit_item_bounds({:?})", def_id); - let bounds = self.tcx.explicit_item_bounds(def_id); + let bounds = self.tcx.explicit_item_bounds(def_id).skip_binder(); record_defaulted_array!(self.tables.explicit_item_bounds[def_id] <- bounds); } diff --git a/compiler/rustc_middle/src/lib.rs b/compiler/rustc_middle/src/lib.rs index 76a8367b2c460..e9172e767e036 100644 --- a/compiler/rustc_middle/src/lib.rs +++ b/compiler/rustc_middle/src/lib.rs @@ -60,6 +60,7 @@ #![feature(const_option)] #![feature(trait_alias)] #![feature(ptr_alignment_type)] +#![feature(macro_metavar_expr)] #![recursion_limit = "512"] #![allow(rustc::potential_query_instability)] diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index 7109ff95b8710..84b5d6b0d0fa1 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -251,7 +251,7 @@ rustc_queries! { /// `key` is the `DefId` of the associated type or opaque type. /// /// Bounds from the parent (e.g. with nested impl trait) are not included. - query explicit_item_bounds(key: DefId) -> &'tcx [(ty::Predicate<'tcx>, Span)] { + query explicit_item_bounds(key: DefId) -> ty::EarlyBinder<&'tcx [(ty::Predicate<'tcx>, Span)]> { desc { |tcx| "finding item bounds for `{}`", tcx.def_path_str(key) } cache_on_disk_if { key.is_local() } separate_provide_extern diff --git a/compiler/rustc_middle/src/ty/codec.rs b/compiler/rustc_middle/src/ty/codec.rs index 5454d406dd128..3793d85c85a41 100644 --- a/compiler/rustc_middle/src/ty/codec.rs +++ b/compiler/rustc_middle/src/ty/codec.rs @@ -530,6 +530,16 @@ macro_rules! implement_ty_decoder { fn read_raw_bytes(&mut self, len: usize) -> &[u8] { self.opaque.read_raw_bytes(len) } + + #[inline] + fn position(&self) -> usize { + self.opaque.position() + } + + #[inline] + fn peek_byte(&self) -> u8 { + self.opaque.peek_byte() + } } } } diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 4a4f6770fc46f..f9bc253ca3a92 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -189,7 +189,7 @@ impl<'tcx> CtxtInterners<'tcx> { #[allow(rustc::usage_of_ty_tykind)] #[inline(never)] fn intern_ty(&self, kind: TyKind<'tcx>, sess: &Session, untracked: &Untracked) -> Ty<'tcx> { - Ty(Interned::new_unchecked( + Ty::from_interned(Interned::new_unchecked( self.type_ .intern(kind, |kind| { let flags = super::flags::FlagComputation::for_kind(&kind); @@ -215,7 +215,7 @@ impl<'tcx> CtxtInterners<'tcx> { ) -> Fingerprint { // It's impossible to hash inference variables (and will ICE), so we don't need to try to cache them. // Without incremental, we rarely stable-hash types, so let's not do it proactively. - if flags.flags.intersects(TypeFlags::NEEDS_INFER) || sess.opts.incremental.is_none() { + if flags.flags.intersects(TypeFlags::HAS_INFER) || sess.opts.incremental.is_none() { Fingerprint::ZERO } else { let mut hasher = StableHasher::new(); @@ -1288,7 +1288,20 @@ macro_rules! nop_list_lift { }; } -nop_lift! {type_; Ty<'a> => Ty<'tcx>} +impl<'a, 'tcx> Lift<'tcx> for Ty<'a> { + type Lifted = Ty<'tcx>; + fn lift_to_tcx(self, tcx: TyCtxt<'tcx>) -> Option { + tcx.interners + .type_ + .contains_pointer_to::>>>( + &InternedInSet(&*self.0.pointer().0), + ) + // SAFETY: `self` is interned and therefore valid + // for the entire lifetime of the `TyCtxt`. + .then(|| unsafe { mem::transmute(self) }) + } +} + nop_lift! {region; Region<'a> => Region<'tcx>} nop_lift! {const_; Const<'a> => Const<'tcx>} nop_lift! {const_allocation; ConstAllocation<'a> => ConstAllocation<'tcx>} @@ -1603,7 +1616,7 @@ impl<'tcx> TyCtxt<'tcx> { let ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }) = ty.kind() else { return false }; let future_trait = self.require_lang_item(LangItem::Future, None); - self.explicit_item_bounds(def_id).iter().any(|(predicate, _)| { + self.explicit_item_bounds(def_id).skip_binder().iter().any(|&(predicate, _)| { let ty::PredicateKind::Clause(ty::Clause::Trait(trait_predicate)) = predicate.kind().skip_binder() else { return false; }; diff --git a/compiler/rustc_middle/src/ty/erase_regions.rs b/compiler/rustc_middle/src/ty/erase_regions.rs index 3837732483244..ad930d1e6b64a 100644 --- a/compiler/rustc_middle/src/ty/erase_regions.rs +++ b/compiler/rustc_middle/src/ty/erase_regions.rs @@ -40,7 +40,7 @@ impl<'tcx> TypeFolder> for RegionEraserVisitor<'tcx> { } fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> { - if ty.needs_infer() { ty.super_fold_with(self) } else { self.tcx.erase_regions_ty(ty) } + if ty.has_infer() { ty.super_fold_with(self) } else { self.tcx.erase_regions_ty(ty) } } fn fold_binder(&mut self, t: ty::Binder<'tcx, T>) -> ty::Binder<'tcx, T> diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 17647d13f9979..1301554fa4f06 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -35,7 +35,7 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap, FxIndexSet}; use rustc_data_structures::intern::Interned; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_data_structures::steal::Steal; -use rustc_data_structures::tagged_ptr::CopyTaggedPtr; +use rustc_data_structures::tagged_ptr::{CopyTaggedPtr, Tag}; use rustc_errors::ErrorGuaranteed; use rustc_hir as hir; use rustc_hir::def::{CtorKind, CtorOf, DefKind, DocLinkResMap, LifetimeRes, Res}; @@ -445,10 +445,71 @@ pub struct CReaderCacheKey { } /// Use this rather than `TyKind`, whenever possible. -#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, HashStable)] +#[derive(Copy, Clone, PartialEq, Eq, Hash, HashStable)] #[rustc_diagnostic_item = "Ty"] #[rustc_pass_by_value] -pub struct Ty<'tcx>(Interned<'tcx, WithCachedTypeInfo>>); +pub struct Ty<'tcx>( + CopyTaggedPtr>>, HotTypeFlags, true>, +); + +impl<'tcx> Ty<'tcx> { + fn from_interned(i: Interned<'tcx, WithCachedTypeInfo>>) -> Self { + let hot_flags = HotTypeFlags::from_flags(i.flags); + let tagged = CopyTaggedPtr::new(i, hot_flags); + Self(tagged) + } +} + +/// A subset of [`TypeFlags`] which are stored directly in the [`Ty`] pointer, +/// as such they are faster to access. +#[derive(Debug, Copy, Clone)] +pub struct HotTypeFlags { + pub has_non_region_infer: bool, +} + +impl HotTypeFlags { + fn from_flags(flags: TypeFlags) -> Self { + Self { + has_non_region_infer: flags.intersects(TypeFlags::HAS_INFER - TypeFlags::HAS_RE_INFER), + } + } + + fn intersects(self, other: Self) -> bool { + let Self { has_non_region_infer: self0 } = self; + let Self { has_non_region_infer: other0 } = other; + + self0 && other0 + } +} + +unsafe impl Tag for HotTypeFlags { + // at most 3 + const BITS: u32 = 1; + + fn into_usize(self) -> usize { + let Self { has_non_region_infer } = self; + has_non_region_infer as usize + } + + unsafe fn from_usize(tag: usize) -> Self { + debug_assert!(tag <= 0b1); + + let has_non_region_infer = tag & 0b1 == 1; + Self { has_non_region_infer } + } +} + +impl PartialOrd for Ty<'_> { + fn partial_cmp(&self, other: &Self) -> Option { + Some(self.cmp(other)) + } +} + +impl Ord for Ty<'_> { + fn cmp(&self, other: &Self) -> std::cmp::Ordering { + self.0.pointer().cmp(&other.0.pointer()) + } +} impl ty::EarlyBoundRegion { /// Does this early bound region have a name? Early bound regions normally @@ -861,6 +922,11 @@ impl<'tcx> PolyTraitPredicate<'tcx> { pub fn is_const_if_const(self) -> bool { self.skip_binder().is_const_if_const() } + + #[inline] + pub fn polarity(self) -> ImplPolarity { + self.skip_binder().polarity + } } /// `A: B` @@ -967,7 +1033,7 @@ impl<'tcx> Term<'tcx> { // and this is just going in the other direction. unsafe { match ptr & TAG_MASK { - TYPE_TAG => TermKind::Ty(Ty(Interned::new_unchecked( + TYPE_TAG => TermKind::Ty(Ty::from_interned(Interned::new_unchecked( &*((ptr & !TAG_MASK) as *const WithCachedTypeInfo>), ))), CONST_TAG => TermKind::Const(ty::Const(Interned::new_unchecked( @@ -1037,9 +1103,13 @@ impl<'tcx> TermKind<'tcx> { fn pack(self) -> Term<'tcx> { let (tag, ptr) = match self { TermKind::Ty(ty) => { + let r: &WithCachedTypeInfo> = ty.0.pointer().0; // Ensure we can use the tag bits. - assert_eq!(mem::align_of_val(&*ty.0.0) & TAG_MASK, 0); - (TYPE_TAG, ty.0.0 as *const WithCachedTypeInfo> as usize) + assert_eq!( + mem::align_of_val::>>(r) & TAG_MASK, + 0 + ); + (TYPE_TAG, r as *const WithCachedTypeInfo> as usize) } TermKind::Const(ct) => { // Ensure we can use the tag bits. @@ -1497,29 +1567,12 @@ struct ParamTag { constness: hir::Constness, } -unsafe impl rustc_data_structures::tagged_ptr::Tag for ParamTag { - const BITS: u32 = 2; - - #[inline] - fn into_usize(self) -> usize { - match self { - Self { reveal: traits::Reveal::UserFacing, constness: hir::Constness::NotConst } => 0, - Self { reveal: traits::Reveal::All, constness: hir::Constness::NotConst } => 1, - Self { reveal: traits::Reveal::UserFacing, constness: hir::Constness::Const } => 2, - Self { reveal: traits::Reveal::All, constness: hir::Constness::Const } => 3, - } - } - - #[inline] - unsafe fn from_usize(ptr: usize) -> Self { - match ptr { - 0 => Self { reveal: traits::Reveal::UserFacing, constness: hir::Constness::NotConst }, - 1 => Self { reveal: traits::Reveal::All, constness: hir::Constness::NotConst }, - 2 => Self { reveal: traits::Reveal::UserFacing, constness: hir::Constness::Const }, - 3 => Self { reveal: traits::Reveal::All, constness: hir::Constness::Const }, - _ => std::hint::unreachable_unchecked(), - } - } +impl_tag! { + impl Tag for ParamTag; + ParamTag { reveal: traits::Reveal::UserFacing, constness: hir::Constness::NotConst }, + ParamTag { reveal: traits::Reveal::All, constness: hir::Constness::NotConst }, + ParamTag { reveal: traits::Reveal::UserFacing, constness: hir::Constness::Const }, + ParamTag { reveal: traits::Reveal::All, constness: hir::Constness::Const }, } impl<'tcx> fmt::Debug for ParamEnv<'tcx> { diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index 4c95d0f841514..1c1432ecd5a05 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -914,7 +914,7 @@ pub trait PrettyPrinter<'tcx>: // Grab the "TraitA + TraitB" from `impl TraitA + TraitB`, // by looking up the projections associated with the def_id. - let bounds = tcx.bound_explicit_item_bounds(def_id); + let bounds = tcx.explicit_item_bounds(def_id); let mut traits = FxIndexMap::default(); let mut fn_traits = FxIndexMap::default(); diff --git a/compiler/rustc_middle/src/ty/structural_impls.rs b/compiler/rustc_middle/src/ty/structural_impls.rs index a2611022406f6..b35b514d795dc 100644 --- a/compiler/rustc_middle/src/ty/structural_impls.rs +++ b/compiler/rustc_middle/src/ty/structural_impls.rs @@ -95,7 +95,7 @@ impl<'tcx> fmt::Debug for ty::FnSig<'tcx> { impl<'tcx> fmt::Debug for ty::ConstVid<'tcx> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "_#{}c", self.index) + write!(f, "?{}c", self.index) } } diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index 29ae42be09643..4b4f8df0b725d 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -5,11 +5,11 @@ use crate::infer::canonical::Canonical; use crate::ty::subst::{GenericArg, InternalSubsts, SubstsRef}; use crate::ty::visit::ValidateBoundVars; -use crate::ty::InferTy::*; use crate::ty::{ self, AdtDef, Discr, Term, Ty, TyCtxt, TypeFlags, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor, }; +use crate::ty::{HotTypeFlags, InferTy::*}; use crate::ty::{List, ParamEnv}; use hir::def::DefKind; use polonius_engine::Atom; @@ -1436,7 +1436,7 @@ pub struct ConstVid<'tcx> { rustc_index::newtype_index! { /// A **region** (lifetime) **v**ariable **ID**. #[derive(HashStable)] - #[debug_format = "'_#{}r"] + #[debug_format = "'?{}"] pub struct RegionVid {} } @@ -1709,12 +1709,17 @@ impl<'tcx> Region<'tcx> { impl<'tcx> Ty<'tcx> { #[inline(always)] pub fn kind(self) -> &'tcx TyKind<'tcx> { - &self.0.0 + &self.0.pointer().0 } #[inline(always)] pub fn flags(self) -> TypeFlags { - self.0.0.flags + self.0.flags + } + + #[inline(always)] + pub fn hot_flags(self) -> HotTypeFlags { + self.0.tag() } #[inline] diff --git a/compiler/rustc_middle/src/ty/subst.rs b/compiler/rustc_middle/src/ty/subst.rs index a439211ca336a..149782f1e80c6 100644 --- a/compiler/rustc_middle/src/ty/subst.rs +++ b/compiler/rustc_middle/src/ty/subst.rs @@ -65,8 +65,13 @@ impl<'tcx> GenericArgKind<'tcx> { } GenericArgKind::Type(ty) => { // Ensure we can use the tag bits. - assert_eq!(mem::align_of_val(&*ty.0.0) & TAG_MASK, 0); - (TYPE_TAG, ty.0.0 as *const WithCachedTypeInfo> as usize) + + let r: &WithCachedTypeInfo> = ty.0.pointer().0; + assert_eq!( + mem::align_of_val::>>(r) & TAG_MASK, + 0 + ); + (TYPE_TAG, r as *const WithCachedTypeInfo> as usize) } GenericArgKind::Const(ct) => { // Ensure we can use the tag bits. @@ -143,7 +148,7 @@ impl<'tcx> GenericArg<'tcx> { REGION_TAG => GenericArgKind::Lifetime(ty::Region(Interned::new_unchecked( &*((ptr & !TAG_MASK) as *const ty::RegionKind<'tcx>), ))), - TYPE_TAG => GenericArgKind::Type(Ty(Interned::new_unchecked( + TYPE_TAG => GenericArgKind::Type(Ty::from_interned(Interned::new_unchecked( &*((ptr & !TAG_MASK) as *const WithCachedTypeInfo>), ))), CONST_TAG => GenericArgKind::Const(ty::Const(Interned::new_unchecked( @@ -612,6 +617,12 @@ where ) -> SubstIter<'s, 'tcx, I> { SubstIter { it: self.0.into_iter(), tcx, substs } } + + /// Similar to [`subst_identity`](EarlyBinder::subst_identity), + /// but on an iterator of `TypeFoldable` values. + pub fn subst_identity_iter(self) -> I::IntoIter { + self.0.into_iter() + } } pub struct SubstIter<'s, 'tcx, I: IntoIterator> { @@ -664,6 +675,12 @@ where ) -> SubstIterCopied<'s, 'tcx, I> { SubstIterCopied { it: self.0.into_iter(), tcx, substs } } + + /// Similar to [`subst_identity`](EarlyBinder::subst_identity), + /// but on an iterator of values that deref to a `TypeFoldable`. + pub fn subst_identity_iter_copied(self) -> impl Iterator::Target> { + self.0.into_iter().map(|v| *v) + } } pub struct SubstIterCopied<'a, 'tcx, I: IntoIterator> { @@ -749,7 +766,7 @@ impl<'tcx, T: TypeFoldable>> ty::EarlyBinder { /// Returns the inner value, but only if it contains no bound vars. pub fn no_bound_vars(self) -> Option { - if !self.0.needs_subst() { Some(self.0) } else { None } + if !self.0.has_param() { Some(self.0) } else { None } } } @@ -817,12 +834,18 @@ impl<'a, 'tcx> TypeFolder> for SubstFolder<'a, 'tcx> { None => region_param_out_of_range(data, self.substs), } } - _ => r, + ty::ReLateBound(..) + | ty::ReFree(_) + | ty::ReStatic + | ty::RePlaceholder(_) + | ty::ReErased + | ty::ReError(_) => r, + ty::ReVar(_) => bug!("unexpected region: {r:?}"), } } fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> { - if !t.needs_subst() { + if !t.has_param() { return t; } diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs index 7127fdbf26a1c..c77985c6bd635 100644 --- a/compiler/rustc_middle/src/ty/util.rs +++ b/compiler/rustc_middle/src/ty/util.rs @@ -701,13 +701,6 @@ impl<'tcx> TyCtxt<'tcx> { if visitor.found_recursion { Err(expanded_type) } else { Ok(expanded_type) } } - pub fn bound_explicit_item_bounds( - self, - def_id: DefId, - ) -> ty::EarlyBinder<&'tcx [(ty::Predicate<'tcx>, rustc_span::Span)]> { - ty::EarlyBinder(self.explicit_item_bounds(def_id)) - } - /// Returns names of captured upvars for closures and generators. /// /// Here are some examples: @@ -1158,7 +1151,7 @@ impl<'tcx> Ty<'tcx> { // context, or *something* like that, but for now just avoid passing inference // variables to queries that can't cope with them. Instead, conservatively // return "true" (may change drop order). - if query_ty.needs_infer() { + if query_ty.has_infer() { return true; } diff --git a/compiler/rustc_middle/src/ty/visit.rs b/compiler/rustc_middle/src/ty/visit.rs index 1b07f52afca92..11918d30588cf 100644 --- a/compiler/rustc_middle/src/ty/visit.rs +++ b/compiler/rustc_middle/src/ty/visit.rs @@ -46,6 +46,12 @@ pub trait TypeVisitableExt<'tcx>: TypeVisitable> { trace!(?self, ?flags, ?res, "has_type_flags"); res } + fn has_hot_type_flags(&self, flags: ty::HotTypeFlags) -> bool { + let res = self.visit_with(&mut HasHotTypeFlagsVisitor { flags }).break_value() + == Some(FoundFlags); + trace!(?self, ?flags, ?res, "has_hot_type_flags"); + res + } fn has_projections(&self) -> bool { self.has_type_flags(TypeFlags::HAS_PROJECTION) } @@ -70,7 +76,7 @@ pub trait TypeVisitableExt<'tcx>: TypeVisitable> { } } fn has_non_region_param(&self) -> bool { - self.has_type_flags(TypeFlags::NEEDS_SUBST - TypeFlags::HAS_RE_PARAM) + self.has_type_flags(TypeFlags::HAS_PARAM - TypeFlags::HAS_RE_PARAM) } fn has_infer_regions(&self) -> bool { self.has_type_flags(TypeFlags::HAS_RE_INFER) @@ -78,11 +84,22 @@ pub trait TypeVisitableExt<'tcx>: TypeVisitable> { fn has_infer_types(&self) -> bool { self.has_type_flags(TypeFlags::HAS_TY_INFER) } + fn has_infer_consts(&self) -> bool { + self.has_type_flags(TypeFlags::HAS_CT_INFER) + } fn has_non_region_infer(&self) -> bool { - self.has_type_flags(TypeFlags::NEEDS_INFER - TypeFlags::HAS_RE_INFER) + let result = self.has_hot_type_flags(ty::HotTypeFlags { has_non_region_infer: true }); + + // Just to be sure hot flags are in sync + debug_assert_eq!( + result, + self.has_type_flags(TypeFlags::HAS_INFER - TypeFlags::HAS_RE_INFER) + ); + + result } - fn needs_infer(&self) -> bool { - self.has_type_flags(TypeFlags::NEEDS_INFER) + fn has_infer(&self) -> bool { + self.has_type_flags(TypeFlags::HAS_INFER) } fn has_placeholders(&self) -> bool { self.has_type_flags( @@ -94,8 +111,8 @@ pub trait TypeVisitableExt<'tcx>: TypeVisitable> { fn has_non_region_placeholders(&self) -> bool { self.has_type_flags(TypeFlags::HAS_TY_PLACEHOLDER | TypeFlags::HAS_CT_PLACEHOLDER) } - fn needs_subst(&self) -> bool { - self.has_type_flags(TypeFlags::NEEDS_SUBST) + fn has_param(&self) -> bool { + self.has_type_flags(TypeFlags::HAS_PARAM) } /// "Free" regions in this context means that it has any region /// that is not (a) erased or (b) late-bound. @@ -530,6 +547,61 @@ impl<'tcx> TypeVisitor> for HasTypeFlagsVisitor { } } +struct HasHotTypeFlagsVisitor { + flags: ty::HotTypeFlags, +} + +impl std::fmt::Debug for HasHotTypeFlagsVisitor { + fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + self.flags.fmt(fmt) + } +} + +impl<'tcx> TypeVisitor> for HasHotTypeFlagsVisitor { + type BreakTy = FoundFlags; + + #[inline] + fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow { + let flags = t.hot_flags(); + if flags.intersects(self.flags) { + ControlFlow::Break(FoundFlags) + } else { + ControlFlow::Continue(()) + } + } + + #[inline] + fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow { + let flags = ty::HotTypeFlags::from_flags(r.type_flags()); + if flags.intersects(self.flags) { + ControlFlow::Break(FoundFlags) + } else { + ControlFlow::Continue(()) + } + } + + #[inline] + fn visit_const(&mut self, c: ty::Const<'tcx>) -> ControlFlow { + let flags = ty::HotTypeFlags::from_flags(FlagComputation::for_const(c)); + trace!(r.flags=?flags); + if flags.intersects(self.flags) { + ControlFlow::Break(FoundFlags) + } else { + ControlFlow::Continue(()) + } + } + + #[inline] + fn visit_predicate(&mut self, predicate: ty::Predicate<'tcx>) -> ControlFlow { + let flags = ty::HotTypeFlags::from_flags(predicate.flags()); + if flags.intersects(self.flags) { + ControlFlow::Break(FoundFlags) + } else { + ControlFlow::Continue(()) + } + } +} + /// Collects all the late-bound regions at the innermost binding level /// into a hash set. struct LateBoundRegionsCollector { diff --git a/compiler/rustc_mir_transform/src/const_prop.rs b/compiler/rustc_mir_transform/src/const_prop.rs index 96bae26e39c4b..880745b8f0eb7 100644 --- a/compiler/rustc_mir_transform/src/const_prop.rs +++ b/compiler/rustc_mir_transform/src/const_prop.rs @@ -18,7 +18,6 @@ use rustc_middle::ty::{self, ConstKind, Instance, ParamEnv, Ty, TyCtxt, TypeVisi use rustc_span::{def_id::DefId, Span, DUMMY_SP}; use rustc_target::abi::{self, Align, HasDataLayout, Size, TargetDataLayout}; use rustc_target::spec::abi::Abi as CallAbi; -use rustc_trait_selection::traits; use crate::MirPass; use rustc_const_eval::interpret::{ @@ -84,42 +83,6 @@ impl<'tcx> MirPass<'tcx> for ConstProp { return; } - // Check if it's even possible to satisfy the 'where' clauses - // for this item. - // This branch will never be taken for any normal function. - // However, it's possible to `#!feature(trivial_bounds)]` to write - // a function with impossible to satisfy clauses, e.g.: - // `fn foo() where String: Copy {}` - // - // We don't usually need to worry about this kind of case, - // since we would get a compilation error if the user tried - // to call it. However, since we can do const propagation - // even without any calls to the function, we need to make - // sure that it even makes sense to try to evaluate the body. - // If there are unsatisfiable where clauses, then all bets are - // off, and we just give up. - // - // We manually filter the predicates, skipping anything that's not - // "global". We are in a potentially generic context - // (e.g. we are evaluating a function without substituting generic - // parameters, so this filtering serves two purposes: - // - // 1. We skip evaluating any predicates that we would - // never be able prove are unsatisfiable (e.g. `` - // 2. We avoid trying to normalize predicates involving generic - // parameters (e.g. `::MyItem`). This can confuse - // the normalization code (leading to cycle errors), since - // it's usually never invoked in this way. - let predicates = tcx - .predicates_of(def_id.to_def_id()) - .predicates - .iter() - .filter_map(|(p, _)| if p.is_global() { Some(*p) } else { None }); - if traits::impossible_predicates(tcx, traits::elaborate(tcx, predicates).collect()) { - trace!("ConstProp skipped for {:?}: found unsatisfiable predicates", def_id); - return; - } - trace!("ConstProp starting for {:?}", def_id); let dummy_body = &Body::new( @@ -428,7 +391,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { /// Returns the value, if any, of evaluating `c`. fn eval_constant(&mut self, c: &Constant<'tcx>) -> Option> { // FIXME we need to revisit this for #67176 - if c.needs_subst() { + if c.has_param() { return None; } @@ -527,7 +490,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { } // FIXME we need to revisit this for #67176 - if rvalue.needs_subst() { + if rvalue.has_param() { return None; } if !rvalue diff --git a/compiler/rustc_mir_transform/src/const_prop_lint.rs b/compiler/rustc_mir_transform/src/const_prop_lint.rs index 3a105a2abaeb9..a4049d08d7b82 100644 --- a/compiler/rustc_mir_transform/src/const_prop_lint.rs +++ b/compiler/rustc_mir_transform/src/const_prop_lint.rs @@ -281,7 +281,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { /// Returns the value, if any, of evaluating `c`. fn eval_constant(&mut self, c: &Constant<'tcx>, location: Location) -> Option> { // FIXME we need to revisit this for #67176 - if c.needs_subst() { + if c.has_param() { return None; } @@ -474,7 +474,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { } // FIXME we need to revisit this for #67176 - if rvalue.needs_subst() { + if rvalue.has_param() { return None; } if !rvalue.ty(self.local_decls(), self.tcx).is_sized(self.tcx, self.param_env) { diff --git a/compiler/rustc_mir_transform/src/coverage/mod.rs b/compiler/rustc_mir_transform/src/coverage/mod.rs index 9b3c06fab50b7..076e714d70370 100644 --- a/compiler/rustc_mir_transform/src/coverage/mod.rs +++ b/compiler/rustc_mir_transform/src/coverage/mod.rs @@ -514,7 +514,7 @@ fn make_code_region( // Extend an empty span by one character so the region will be counted. let CharPos(char_pos) = start_col; if span.hi() == body_span.hi() { - start_col = CharPos(char_pos - 1); + start_col = CharPos(char_pos.saturating_sub(1)); } else { end_col = CharPos(char_pos + 1); } diff --git a/compiler/rustc_mir_transform/src/generator.rs b/compiler/rustc_mir_transform/src/generator.rs index 34a7ee9e264f7..e44dd084b2de5 100644 --- a/compiler/rustc_mir_transform/src/generator.rs +++ b/compiler/rustc_mir_transform/src/generator.rs @@ -1800,7 +1800,7 @@ fn check_must_not_suspend_ty<'tcx>( // FIXME: support adding the attribute to TAITs ty::Alias(ty::Opaque, ty::AliasTy { def_id: def, .. }) => { let mut has_emitted = false; - for &(predicate, _) in tcx.explicit_item_bounds(def) { + for &(predicate, _) in tcx.explicit_item_bounds(def).skip_binder() { // We only look at the `DefId`, so it is safe to skip the binder here. if let ty::PredicateKind::Clause(ty::Clause::Trait(ref poly_trait_predicate)) = predicate.kind().skip_binder() diff --git a/compiler/rustc_mir_transform/src/inline/cycle.rs b/compiler/rustc_mir_transform/src/inline/cycle.rs index 098ce0391fcd2..6046c3876bee0 100644 --- a/compiler/rustc_mir_transform/src/inline/cycle.rs +++ b/compiler/rustc_mir_transform/src/inline/cycle.rs @@ -92,7 +92,7 @@ pub(crate) fn mir_callgraph_reachable<'tcx>( // FIXME: A not fully substituted drop shim can cause ICEs if one attempts to // have its MIR built. Likely oli-obk just screwed up the `ParamEnv`s, so this // needs some more analysis. - if callee.needs_subst() { + if callee.has_param() { continue; } } diff --git a/compiler/rustc_mir_transform/src/lib.rs b/compiler/rustc_mir_transform/src/lib.rs index 1d6cd1c15b7d4..25d7db0ee605a 100644 --- a/compiler/rustc_mir_transform/src/lib.rs +++ b/compiler/rustc_mir_transform/src/lib.rs @@ -30,11 +30,12 @@ use rustc_middle::mir::visit::Visitor as _; use rustc_middle::mir::{ traversal, AnalysisPhase, Body, ClearCrossCrate, ConstQualifs, Constant, LocalDecl, MirPass, MirPhase, Operand, Place, ProjectionElem, Promoted, RuntimePhase, Rvalue, SourceInfo, - Statement, StatementKind, TerminatorKind, + Statement, StatementKind, TerminatorKind, START_BLOCK, }; use rustc_middle::ty::query::Providers; use rustc_middle::ty::{self, TyCtxt, TypeVisitableExt}; use rustc_span::sym; +use rustc_trait_selection::traits; #[macro_use] mod pass_manager; @@ -389,6 +390,50 @@ fn mir_drops_elaborated_and_const_checked(tcx: TyCtxt<'_>, def: LocalDefId) -> & body.tainted_by_errors = Some(error_reported); } + // Check if it's even possible to satisfy the 'where' clauses + // for this item. + // + // This branch will never be taken for any normal function. + // However, it's possible to `#!feature(trivial_bounds)]` to write + // a function with impossible to satisfy clauses, e.g.: + // `fn foo() where String: Copy {}` + // + // We don't usually need to worry about this kind of case, + // since we would get a compilation error if the user tried + // to call it. However, since we optimize even without any + // calls to the function, we need to make sure that it even + // makes sense to try to evaluate the body. + // + // If there are unsatisfiable where clauses, then all bets are + // off, and we just give up. + // + // We manually filter the predicates, skipping anything that's not + // "global". We are in a potentially generic context + // (e.g. we are evaluating a function without substituting generic + // parameters, so this filtering serves two purposes: + // + // 1. We skip evaluating any predicates that we would + // never be able prove are unsatisfiable (e.g. `` + // 2. We avoid trying to normalize predicates involving generic + // parameters (e.g. `::MyItem`). This can confuse + // the normalization code (leading to cycle errors), since + // it's usually never invoked in this way. + let predicates = tcx + .predicates_of(body.source.def_id()) + .predicates + .iter() + .filter_map(|(p, _)| if p.is_global() { Some(*p) } else { None }); + if traits::impossible_predicates(tcx, traits::elaborate(tcx, predicates).collect()) { + trace!("found unsatisfiable predicates for {:?}", body.source); + // Clear the body to only contain a single `unreachable` statement. + let bbs = body.basic_blocks.as_mut(); + bbs.raw.truncate(1); + bbs[START_BLOCK].statements.clear(); + bbs[START_BLOCK].terminator_mut().kind = TerminatorKind::Unreachable; + body.var_debug_info.clear(); + body.local_decls.raw.truncate(body.arg_count + 1); + } + run_analysis_to_runtime_passes(tcx, &mut body); tcx.alloc_steal_mir(body) diff --git a/compiler/rustc_mir_transform/src/lower_intrinsics.rs b/compiler/rustc_mir_transform/src/lower_intrinsics.rs index c7d3f6c9f044c..62b727674c5d1 100644 --- a/compiler/rustc_mir_transform/src/lower_intrinsics.rs +++ b/compiler/rustc_mir_transform/src/lower_intrinsics.rs @@ -192,6 +192,23 @@ impl<'tcx> MirPass<'tcx> for LowerIntrinsics { terminator.kind = TerminatorKind::Goto { target }; } } + sym::offset => { + let target = target.unwrap(); + let Ok([ptr, delta]) = <[_; 2]>::try_from(std::mem::take(args)) else { + span_bug!( + terminator.source_info.span, + "Wrong number of arguments for offset intrinsic", + ); + }; + block.statements.push(Statement { + source_info: terminator.source_info, + kind: StatementKind::Assign(Box::new(( + *destination, + Rvalue::BinaryOp(BinOp::Offset, Box::new((ptr, delta))), + ))), + }); + terminator.kind = TerminatorKind::Goto { target }; + } sym::option_payload_ptr => { if let (Some(target), Some(arg)) = (*target, args[0].place()) { let ty::RawPtr(ty::TypeAndMut { ty: dest_ty, .. }) = diff --git a/compiler/rustc_monomorphize/src/partitioning/default.rs b/compiler/rustc_monomorphize/src/partitioning/default.rs index bd24deb590a71..03183a4066033 100644 --- a/compiler/rustc_monomorphize/src/partitioning/default.rs +++ b/compiler/rustc_monomorphize/src/partitioning/default.rs @@ -305,7 +305,7 @@ fn characteristic_def_id_of_mono_item<'tcx>( // When polymorphization is enabled, methods which do not depend on their generic // parameters, but the self-type of their impl block do will fail to normalize. - if !tcx.sess.opts.unstable_opts.polymorphize || !instance.needs_subst() { + if !tcx.sess.opts.unstable_opts.polymorphize || !instance.has_param() { // This is a method within an impl, find out what the self-type is: let impl_self_ty = tcx.subst_and_normalize_erasing_regions( instance.substs, diff --git a/compiler/rustc_parse/messages.ftl b/compiler/rustc_parse/messages.ftl index f11d0ed0f0109..d45fa90a11b08 100644 --- a/compiler/rustc_parse/messages.ftl +++ b/compiler/rustc_parse/messages.ftl @@ -742,3 +742,33 @@ parse_bad_return_type_notation_output = parse_bad_return_type_notation_dotdot = return type notation uses `()` instead of `(..)` for elided arguments .suggestion = remove the `..` + +parse_bad_assoc_type_bounds = bounds on associated types do not belong here + .label = belongs in `where` clause + +parse_attr_after_generic = trailing attribute after generic parameter + .label = attributes must go before parameters + +parse_attr_without_generics = attribute without generic parameters + .label = attributes are only permitted when preceding parameters + +parse_where_generics = generic parameters on `where` clauses are reserved for future use + .label = currently unsupported + +parse_generics_in_path = unexpected generic arguments in path + +parse_assoc_lifetime = associated lifetimes are not supported + .label = the lifetime is given here + .help = if you meant to specify a trait object, write `dyn Trait + 'lifetime` + +parse_tilde_const_lifetime = `~const` may only modify trait bounds, not lifetime bounds + +parse_maybe_lifetime = `?` may only modify trait bounds, not lifetime bounds + +parse_parenthesized_lifetime = parenthesized lifetime bounds are not supported + .suggestion = remove the parentheses + +parse_const_bounds_missing_tilde = const bounds must start with `~` + .suggestion = add `~` + +parse_underscore_literal_suffix = underscore literal suffix is not allowed diff --git a/compiler/rustc_parse/src/errors.rs b/compiler/rustc_parse/src/errors.rs index 069217165fabe..b0e1189851a1b 100644 --- a/compiler/rustc_parse/src/errors.rs +++ b/compiler/rustc_parse/src/errors.rs @@ -2332,3 +2332,92 @@ pub(crate) struct BadReturnTypeNotationDotDot { #[suggestion(code = "", applicability = "maybe-incorrect")] pub span: Span, } + +#[derive(Diagnostic)] +#[diag(parse_bad_assoc_type_bounds)] +pub(crate) struct BadAssocTypeBounds { + #[primary_span] + #[label] + pub span: Span, +} + +#[derive(Diagnostic)] +#[diag(parse_attr_after_generic)] +pub(crate) struct AttrAfterGeneric { + #[primary_span] + #[label] + pub span: Span, +} + +#[derive(Diagnostic)] +#[diag(parse_attr_without_generics)] +pub(crate) struct AttrWithoutGenerics { + #[primary_span] + #[label] + pub span: Span, +} + +#[derive(Diagnostic)] +#[diag(parse_where_generics)] +pub(crate) struct WhereOnGenerics { + #[primary_span] + #[label] + pub span: Span, +} + +#[derive(Diagnostic)] +#[diag(parse_generics_in_path)] +pub(crate) struct GenericsInPath { + #[primary_span] + pub span: Vec, +} + +#[derive(Diagnostic)] +#[diag(parse_assoc_lifetime)] +#[help] +pub(crate) struct AssocLifetime { + #[primary_span] + pub span: Span, + #[label] + pub lifetime: Span, +} + +#[derive(Diagnostic)] +#[diag(parse_tilde_const_lifetime)] +pub(crate) struct TildeConstLifetime { + #[primary_span] + pub span: Span, +} + +#[derive(Diagnostic)] +#[diag(parse_maybe_lifetime)] +pub(crate) struct MaybeLifetime { + #[primary_span] + pub span: Span, +} + +#[derive(Diagnostic)] +#[diag(parse_parenthesized_lifetime)] +pub(crate) struct ParenthesizedLifetime { + #[primary_span] + pub span: Span, + #[suggestion(style = "short", applicability = "machine-applicable", code = "{snippet}")] + pub sugg: Option, + pub snippet: String, +} + +#[derive(Diagnostic)] +#[diag(parse_const_bounds_missing_tilde)] +pub(crate) struct ConstMissingTilde { + #[primary_span] + pub span: Span, + #[suggestion(code = "~", applicability = "machine-applicable")] + pub start: Span, +} + +#[derive(Diagnostic)] +#[diag(parse_underscore_literal_suffix)] +pub(crate) struct UnderscoreLiteralSuffix { + #[primary_span] + pub span: Span, +} diff --git a/compiler/rustc_parse/src/lexer/mod.rs b/compiler/rustc_parse/src/lexer/mod.rs index ad9b20f9c767a..a4a75fcb96995 100644 --- a/compiler/rustc_parse/src/lexer/mod.rs +++ b/compiler/rustc_parse/src/lexer/mod.rs @@ -209,11 +209,7 @@ impl<'a> StringReader<'a> { if string == "_" { self.sess .span_diagnostic - .struct_span_err( - self.mk_sp(suffix_start, self.pos), - "underscore literal suffix is not allowed", - ) - .emit(); + .emit_err(errors::UnderscoreLiteralSuffix { span: self.mk_sp(suffix_start, self.pos) }); None } else { Some(Symbol::intern(string)) diff --git a/compiler/rustc_parse/src/parser/generics.rs b/compiler/rustc_parse/src/parser/generics.rs index f8ef1307c988e..61a7ae93bfa8b 100644 --- a/compiler/rustc_parse/src/parser/generics.rs +++ b/compiler/rustc_parse/src/parser/generics.rs @@ -1,5 +1,5 @@ use crate::errors::{ - MultipleWhereClauses, UnexpectedDefaultValueForLifetimeInGenericParameters, + self, MultipleWhereClauses, UnexpectedDefaultValueForLifetimeInGenericParameters, UnexpectedSelfInGenericParameters, WhereClauseBeforeTupleStructBody, WhereClauseBeforeTupleStructBodySugg, }; @@ -181,12 +181,9 @@ impl<'a> Parser<'a> { let snapshot = this.create_snapshot_for_diagnostic(); match this.parse_ty_where_predicate() { Ok(where_predicate) => { - this.struct_span_err( - where_predicate.span(), - "bounds on associated types do not belong here", - ) - .span_label(where_predicate.span(), "belongs in `where` clause") - .emit(); + this.sess.emit_err(errors::BadAssocTypeBounds { + span: where_predicate.span(), + }); // FIXME - try to continue parsing other generics? return Ok((None, TrailingToken::None)); } @@ -201,22 +198,11 @@ impl<'a> Parser<'a> { // Check for trailing attributes and stop parsing. if !attrs.is_empty() { if !params.is_empty() { - this.struct_span_err( - attrs[0].span, - "trailing attribute after generic parameter", - ) - .span_label(attrs[0].span, "attributes must go before parameters") - .emit(); + this.sess + .emit_err(errors::AttrAfterGeneric { span: attrs[0].span }); } else { - this.struct_span_err( - attrs[0].span, - "attribute without generic parameters", - ) - .span_label( - attrs[0].span, - "attributes are only permitted when preceding parameters", - ) - .emit(); + this.sess + .emit_err(errors::AttrWithoutGenerics { span: attrs[0].span }); } } return Ok((None, TrailingToken::None)); @@ -304,12 +290,7 @@ impl<'a> Parser<'a> { // change we parse those generics now, but report an error. if self.choose_generics_over_qpath(0) { let generics = self.parse_generics()?; - self.struct_span_err( - generics.span, - "generic parameters on `where` clauses are reserved for future use", - ) - .span_label(generics.span, "currently unsupported") - .emit(); + self.sess.emit_err(errors::WhereOnGenerics { span: generics.span }); } loop { diff --git a/compiler/rustc_parse/src/parser/path.rs b/compiler/rustc_parse/src/parser/path.rs index c25c23d849f04..6cceb47ff8384 100644 --- a/compiler/rustc_parse/src/parser/path.rs +++ b/compiler/rustc_parse/src/parser/path.rs @@ -150,16 +150,13 @@ impl<'a> Parser<'a> { // if style == PathStyle::Mod && path.segments.iter().any(|segment| segment.args.is_some()) { - parser - .struct_span_err( - path.segments - .iter() - .filter_map(|segment| segment.args.as_ref()) - .map(|arg| arg.span()) - .collect::>(), - "unexpected generic arguments in path", - ) - .emit(); + let span = path + .segments + .iter() + .filter_map(|segment| segment.args.as_ref()) + .map(|arg| arg.span()) + .collect::>(); + parser.sess.emit_err(errors::GenericsInPath { span }); } }; @@ -620,10 +617,7 @@ impl<'a> Parser<'a> { c.into() } Some(GenericArg::Lifetime(lt)) => { - self.struct_span_err(span, "associated lifetimes are not supported") - .span_label(lt.ident.span, "the lifetime is given here") - .help("if you meant to specify a trait object, write `dyn Trait + 'lifetime`") - .emit(); + self.sess.emit_err(errors::AssocLifetime { span, lifetime: lt.ident.span }); self.mk_ty(span, ast::TyKind::Err).into() } None => { diff --git a/compiler/rustc_parse/src/parser/ty.rs b/compiler/rustc_parse/src/parser/ty.rs index 400c8dbe9bc6b..f5f6788362ba9 100644 --- a/compiler/rustc_parse/src/parser/ty.rs +++ b/compiler/rustc_parse/src/parser/ty.rs @@ -1,7 +1,7 @@ use super::{Parser, PathStyle, TokenType}; use crate::errors::{ - DynAfterMut, ExpectedFnPathFoundFnKeyword, ExpectedMutOrConstInRawPointerType, + self, DynAfterMut, ExpectedFnPathFoundFnKeyword, ExpectedMutOrConstInRawPointerType, FnPointerCannotBeAsync, FnPointerCannotBeConst, FnPtrWithGenerics, FnPtrWithGenericsSugg, InvalidDynKeyword, LifetimeAfterMut, NeedPlusAfterTraitObjectLifetime, NegativeBoundsNotSupported, NegativeBoundsNotSupportedSugg, NestedCVariadicType, @@ -807,16 +807,11 @@ impl<'a> Parser<'a> { /// Emits an error if any trait bound modifiers were present. fn error_lt_bound_with_modifiers(&self, modifiers: BoundModifiers) { if let Some(span) = modifiers.maybe_const { - self.struct_span_err( - span, - "`~const` may only modify trait bounds, not lifetime bounds", - ) - .emit(); + self.sess.emit_err(errors::TildeConstLifetime { span }); } if let Some(span) = modifiers.maybe { - self.struct_span_err(span, "`?` may only modify trait bounds, not lifetime bounds") - .emit(); + self.sess.emit_err(errors::MaybeLifetime { span }); } } @@ -824,19 +819,14 @@ impl<'a> Parser<'a> { fn recover_paren_lifetime(&mut self, lo: Span, inner_lo: Span) -> PResult<'a, ()> { let inner_span = inner_lo.to(self.prev_token.span); self.expect(&token::CloseDelim(Delimiter::Parenthesis))?; - let mut err = self.struct_span_err( - lo.to(self.prev_token.span), - "parenthesized lifetime bounds are not supported", - ); - if let Ok(snippet) = self.span_to_snippet(inner_span) { - err.span_suggestion_short( - lo.to(self.prev_token.span), - "remove the parentheses", - snippet, - Applicability::MachineApplicable, - ); - } - err.emit(); + let span = lo.to(self.prev_token.span); + let (sugg, snippet) = if let Ok(snippet) = self.span_to_snippet(inner_span) { + (Some(span), snippet) + } else { + (None, String::new()) + }; + + self.sess.emit_err(errors::ParenthesizedLifetime { span, sugg, snippet }); Ok(()) } @@ -857,15 +847,7 @@ impl<'a> Parser<'a> { } else if self.eat_keyword(kw::Const) { let span = self.prev_token.span; self.sess.gated_spans.gate(sym::const_trait_impl, span); - - self.struct_span_err(span, "const bounds must start with `~`") - .span_suggestion( - span.shrink_to_lo(), - "add `~`", - "~", - Applicability::MachineApplicable, - ) - .emit(); + self.sess.emit_err(errors::ConstMissingTilde { span, start: span.shrink_to_lo() }); Some(span) } else { diff --git a/compiler/rustc_passes/messages.ftl b/compiler/rustc_passes/messages.ftl index 055682a1509ef..406801506013b 100644 --- a/compiler/rustc_passes/messages.ftl +++ b/compiler/rustc_passes/messages.ftl @@ -139,7 +139,6 @@ passes_doc_attr_not_crate_level = passes_attr_crate_level = this attribute can only be applied at the crate level .suggestion = to apply to the crate, use an inner attribute - .help = to apply to the crate, use an inner attribute .note = read for more information passes_doc_test_unknown = @@ -724,3 +723,45 @@ passes_skipping_const_checks = skipping const checks passes_invalid_macro_export_arguments = `{$name}` isn't a valid `#[macro_export]` argument passes_invalid_macro_export_arguments_too_many_items = `#[macro_export]` can only take 1 or 0 arguments + +passes_unreachable_due_to_uninhabited = unreachable {$descr} + .label = unreachable {$descr} + .label_orig = any code following this expression is unreachable + .note = this expression has type `{$ty}`, which is uninhabited + +passes_unused_var_maybe_capture_ref = unused variable: `{$name}` + .help = did you mean to capture by reference instead? + +passes_unused_capture_maybe_capture_ref = value captured by `{$name}` is never read + .help = did you mean to capture by reference instead? + +passes_unused_var_remove_field = unused variable: `{$name}` +passes_unused_var_remove_field_suggestion = try removing the field + +passes_unused_var_assigned_only = variable `{$name}` is assigned to, but never used + .note = consider using `_{$name}` instead + +passes_unnecessary_stable_feature = the feature `{$feature}` has been stable since {$since} and no longer requires an attribute to enable + +passes_unnecessary_partial_stable_feature = the feature `{$feature}` has been partially stabilized since {$since} and is succeeded by the feature `{$implies}` + .suggestion = if you are using features which are still unstable, change to using `{$implies}` + .suggestion_remove = if you are using features which are now stable, remove this line + +passes_ineffective_unstable_impl = an `#[unstable]` annotation here has no effect + .note = see issue #55436 for more information + +passes_unused_assign = value assigned to `{$name}` is never read + .help = maybe it is overwritten before being read? + +passes_unused_assign_passed = value passed to `{$name}` is never read + .help = maybe it is overwritten before being read? + +passes_maybe_string_interpolation = you might have meant to use string interpolation in this string literal +passes_string_interpolation_only_works = string interpolation only works in `format!` invocations + +passes_unused_variable_try_prefix = unused variable: `{$name}` + .label = unused variable + .suggestion = if this is intentional, prefix it with an underscore + +passes_unused_variable_try_ignore = unused variable: `{$name}` + .suggestion = try ignoring the field diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index 085a28626ea00..3f28ac26f8617 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -29,7 +29,7 @@ use rustc_session::lint::builtin::{ }; use rustc_session::parse::feature_err; use rustc_span::symbol::{kw, sym, Symbol}; -use rustc_span::{Span, DUMMY_SP}; +use rustc_span::{BytePos, Span, DUMMY_SP}; use rustc_target::spec::abi::Abi; use rustc_trait_selection::infer::{TyCtxtInferExt, ValuePairs}; use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt; @@ -927,30 +927,18 @@ impl CheckAttrVisitor<'_> { hir_id: HirId, ) -> bool { if hir_id != CRATE_HIR_ID { - self.tcx.struct_span_lint_hir( + // insert a bang between `#` and `[...` + let bang_span = attr.span.lo() + BytePos(1); + let sugg = (attr.style == AttrStyle::Outer + && self.tcx.hir().get_parent_item(hir_id) == CRATE_OWNER_ID) + .then_some(errors::AttrCrateLevelOnlySugg { + attr: attr.span.with_lo(bang_span).with_hi(bang_span), + }); + self.tcx.emit_spanned_lint( INVALID_DOC_ATTRIBUTES, hir_id, meta.span(), - fluent::passes_attr_crate_level, - |err| { - if attr.style == AttrStyle::Outer - && self.tcx.hir().get_parent_item(hir_id) == CRATE_OWNER_ID - { - if let Ok(mut src) = self.tcx.sess.source_map().span_to_snippet(attr.span) { - src.insert(1, '!'); - err.span_suggestion_verbose( - attr.span, - fluent::passes_suggestion, - src, - Applicability::MaybeIncorrect, - ); - } else { - err.span_help(attr.span, fluent::passes_help); - } - } - err.note(fluent::passes_note); - err - }, + errors::AttrCrateLevelOnly { sugg }, ); return false; } diff --git a/compiler/rustc_passes/src/errors.rs b/compiler/rustc_passes/src/errors.rs index e8603b3a2f173..99fc69d1bec7b 100644 --- a/compiler/rustc_passes/src/errors.rs +++ b/compiler/rustc_passes/src/errors.rs @@ -6,7 +6,8 @@ use std::{ use crate::fluent_generated as fluent; use rustc_ast::Label; use rustc_errors::{ - error_code, Applicability, DiagnosticSymbolList, ErrorGuaranteed, IntoDiagnostic, MultiSpan, + error_code, AddToDiagnostic, Applicability, Diagnostic, DiagnosticSymbolList, ErrorGuaranteed, + IntoDiagnostic, MultiSpan, }; use rustc_hir::{self as hir, ExprKind, Target}; use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic}; @@ -1555,3 +1556,160 @@ pub struct SkippingConstChecks { #[primary_span] pub span: Span, } + +#[derive(LintDiagnostic)] +#[diag(passes_unreachable_due_to_uninhabited)] +pub struct UnreachableDueToUninhabited<'desc, 'tcx> { + pub descr: &'desc str, + #[label] + pub expr: Span, + #[label(passes_label_orig)] + #[note] + pub orig: Span, + pub ty: Ty<'tcx>, +} + +#[derive(LintDiagnostic)] +#[diag(passes_unused_var_maybe_capture_ref)] +#[help] +pub struct UnusedVarMaybeCaptureRef { + pub name: String, +} + +#[derive(LintDiagnostic)] +#[diag(passes_unused_capture_maybe_capture_ref)] +#[help] +pub struct UnusedCaptureMaybeCaptureRef { + pub name: String, +} + +#[derive(LintDiagnostic)] +#[diag(passes_unused_var_remove_field)] +pub struct UnusedVarRemoveField { + pub name: String, + #[subdiagnostic] + pub sugg: UnusedVarRemoveFieldSugg, +} + +#[derive(Subdiagnostic)] +#[multipart_suggestion( + passes_unused_var_remove_field_suggestion, + applicability = "machine-applicable" +)] +pub struct UnusedVarRemoveFieldSugg { + #[suggestion_part(code = "")] + pub spans: Vec, +} + +#[derive(LintDiagnostic)] +#[diag(passes_unused_var_assigned_only)] +#[note] +pub struct UnusedVarAssignedOnly { + pub name: String, +} + +#[derive(LintDiagnostic)] +#[diag(passes_unnecessary_stable_feature)] +pub struct UnnecessaryStableFeature { + pub feature: Symbol, + pub since: Symbol, +} + +#[derive(LintDiagnostic)] +#[diag(passes_unnecessary_partial_stable_feature)] +pub struct UnnecessaryPartialStableFeature { + #[suggestion(code = "{implies}", applicability = "maybe-incorrect")] + pub span: Span, + #[suggestion(passes_suggestion_remove, code = "", applicability = "maybe-incorrect")] + pub line: Span, + pub feature: Symbol, + pub since: Symbol, + pub implies: Symbol, +} + +#[derive(LintDiagnostic)] +#[diag(passes_ineffective_unstable_impl)] +#[note] +pub struct IneffectiveUnstableImpl; + +#[derive(LintDiagnostic)] +#[diag(passes_unused_assign)] +#[help] +pub struct UnusedAssign { + pub name: String, +} + +#[derive(LintDiagnostic)] +#[diag(passes_unused_assign_passed)] +#[help] +pub struct UnusedAssignPassed { + pub name: String, +} + +#[derive(LintDiagnostic)] +#[diag(passes_unused_variable_try_prefix)] +pub struct UnusedVariableTryPrefix { + #[label] + pub label: Option, + #[subdiagnostic] + pub string_interp: Vec, + #[subdiagnostic] + pub sugg: UnusedVariableTryPrefixSugg, +} + +#[derive(Subdiagnostic)] +#[multipart_suggestion(passes_suggestion, applicability = "machine-applicable")] +pub struct UnusedVariableTryPrefixSugg { + #[suggestion_part(code = "_{name}")] + pub spans: Vec, + pub name: String, +} + +pub struct UnusedVariableStringInterp { + pub lit: Span, + pub lo: Span, + pub hi: Span, +} + +impl AddToDiagnostic for UnusedVariableStringInterp { + fn add_to_diagnostic_with(self, diag: &mut Diagnostic, _: F) { + diag.span_label(self.lit, crate::fluent_generated::passes_maybe_string_interpolation); + diag.multipart_suggestion( + crate::fluent_generated::passes_string_interpolation_only_works, + vec![(self.lo, String::from("format!(")), (self.hi, String::from(")"))], + Applicability::MachineApplicable, + ); + } +} + +#[derive(LintDiagnostic)] +#[diag(passes_unused_variable_try_ignore)] +pub struct UnusedVarTryIgnore { + #[subdiagnostic] + pub sugg: UnusedVarTryIgnoreSugg, +} + +#[derive(Subdiagnostic)] +#[multipart_suggestion(passes_suggestion, applicability = "machine-applicable")] +pub struct UnusedVarTryIgnoreSugg { + #[suggestion_part(code = "{name}: _")] + pub shorthands: Vec, + #[suggestion_part(code = "_")] + pub non_shorthands: Vec, + pub name: String, +} + +#[derive(LintDiagnostic)] +#[diag(passes_attr_crate_level)] +#[note] +pub struct AttrCrateLevelOnly { + #[subdiagnostic] + pub sugg: Option, +} + +#[derive(Subdiagnostic)] +#[suggestion(passes_suggestion, applicability = "maybe-incorrect", code = "!", style = "verbose")] +pub struct AttrCrateLevelOnlySugg { + #[primary_span] + pub attr: Span, +} diff --git a/compiler/rustc_passes/src/lib.rs b/compiler/rustc_passes/src/lib.rs index eca3bae9a1cfd..8b7338e29aa07 100644 --- a/compiler/rustc_passes/src/lib.rs +++ b/compiler/rustc_passes/src/lib.rs @@ -12,6 +12,8 @@ #![feature(min_specialization)] #![feature(try_blocks)] #![recursion_limit = "256"] +#![deny(rustc::untranslatable_diagnostic)] +#![deny(rustc::diagnostic_outside_of_impl)] #[macro_use] extern crate rustc_middle; diff --git a/compiler/rustc_passes/src/liveness.rs b/compiler/rustc_passes/src/liveness.rs index 7d8f6add63282..6758024419d31 100644 --- a/compiler/rustc_passes/src/liveness.rs +++ b/compiler/rustc_passes/src/liveness.rs @@ -81,13 +81,13 @@ //! We generate various special nodes for various, well, special purposes. //! These are described in the `Liveness` struct. +use crate::errors; + use self::LiveNodeKind::*; use self::VarKind::*; use rustc_ast::InlineAsmOptions; use rustc_data_structures::fx::FxIndexMap; -use rustc_errors::Applicability; -use rustc_errors::Diagnostic; use rustc_hir as hir; use rustc_hir::def::*; use rustc_hir::def_id::LocalDefId; @@ -1297,13 +1297,13 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { self.exit_ln } - fn warn_about_unreachable( + fn warn_about_unreachable<'desc>( &mut self, orig_span: Span, orig_ty: Ty<'tcx>, expr_span: Span, expr_id: HirId, - descr: &str, + descr: &'desc str, ) { if !orig_ty.is_never() { // Unreachable code warnings are already emitted during type checking. @@ -1316,22 +1316,15 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { // that we do not emit the same warning twice if the uninhabited type // is indeed `!`. - let msg = format!("unreachable {}", descr); - self.ir.tcx.struct_span_lint_hir( + self.ir.tcx.emit_spanned_lint( lint::builtin::UNREACHABLE_CODE, expr_id, expr_span, - &msg, - |diag| { - diag.span_label(expr_span, &msg) - .span_label(orig_span, "any code following this expression is unreachable") - .span_note( - orig_span, - &format!( - "this expression has type `{}`, which is uninhabited", - orig_ty - ), - ) + errors::UnreachableDueToUninhabited { + expr: expr_span, + orig: orig_span, + descr, + ty: orig_ty, }, ); } @@ -1483,23 +1476,21 @@ impl<'tcx> Liveness<'_, 'tcx> { if self.used_on_entry(entry_ln, var) { if !self.live_on_entry(entry_ln, var) { if let Some(name) = self.should_warn(var) { - self.ir.tcx.struct_span_lint_hir( + self.ir.tcx.emit_spanned_lint( lint::builtin::UNUSED_ASSIGNMENTS, var_hir_id, vec![span], - format!("value captured by `{}` is never read", name), - |lint| lint.help("did you mean to capture by reference instead?"), + errors::UnusedCaptureMaybeCaptureRef { name }, ); } } } else { if let Some(name) = self.should_warn(var) { - self.ir.tcx.struct_span_lint_hir( + self.ir.tcx.emit_spanned_lint( lint::builtin::UNUSED_VARIABLES, var_hir_id, vec![span], - format!("unused variable: `{}`", name), - |lint| lint.help("did you mean to capture by reference instead?"), + errors::UnusedVarMaybeCaptureRef { name }, ); } } @@ -1514,11 +1505,14 @@ impl<'tcx> Liveness<'_, 'tcx> { Some(entry_ln), Some(body), |spans, hir_id, ln, var| { - if !self.live_on_entry(ln, var) { - self.report_unused_assign(hir_id, spans, var, |name| { - format!("value passed to `{}` is never read", name) - }); - } + if !self.live_on_entry(ln, var) + && let Some(name) = self.should_warn(var) { + self.ir.tcx.emit_spanned_lint( + lint::builtin::UNUSED_ASSIGNMENTS, + hir_id, + spans, + errors::UnusedAssignPassed { name }, + ); } }, ); } @@ -1587,39 +1581,35 @@ impl<'tcx> Liveness<'_, 'tcx> { if ln == self.exit_ln { false } else { self.assigned_on_exit(ln, var) }; if is_assigned { - self.ir.tcx.struct_span_lint_hir( + self.ir.tcx.emit_spanned_lint( lint::builtin::UNUSED_VARIABLES, first_hir_id, hir_ids_and_spans .into_iter() .map(|(_, _, ident_span)| ident_span) .collect::>(), - format!("variable `{}` is assigned to, but never used", name), - |lint| lint.note(&format!("consider using `_{}` instead", name)), + errors::UnusedVarAssignedOnly { name }, ) } else if can_remove { - self.ir.tcx.struct_span_lint_hir( + let spans = hir_ids_and_spans + .iter() + .map(|(_, pat_span, _)| { + let span = self + .ir + .tcx + .sess + .source_map() + .span_extend_to_next_char(*pat_span, ',', true); + span.with_hi(BytePos(span.hi().0 + 1)) + }) + .collect(); + self.ir.tcx.emit_spanned_lint( lint::builtin::UNUSED_VARIABLES, first_hir_id, hir_ids_and_spans.iter().map(|(_, pat_span, _)| *pat_span).collect::>(), - format!("unused variable: `{}`", name), - |lint| { - lint.multipart_suggestion( - "try removing the field", - hir_ids_and_spans - .iter() - .map(|(_, pat_span, _)| { - let span = self - .ir - .tcx - .sess - .source_map() - .span_extend_to_next_char(*pat_span, ',', true); - (span.with_hi(BytePos(span.hi().0 + 1)), String::new()) - }) - .collect(), - Applicability::MachineApplicable, - ) + errors::UnusedVarRemoveField { + name, + sugg: errors::UnusedVarRemoveFieldSugg { spans }, }, ); } else { @@ -1633,55 +1623,46 @@ impl<'tcx> Liveness<'_, 'tcx> { // the field" message, and suggest `_` for the non-shorthands. If we only // have non-shorthand, then prefix with an underscore instead. if !shorthands.is_empty() { - let shorthands = shorthands - .into_iter() - .map(|(_, pat_span, _)| (pat_span, format!("{}: _", name))) - .chain( - non_shorthands - .into_iter() - .map(|(_, pat_span, _)| (pat_span, "_".to_string())), - ) - .collect::>(); + let shorthands = + shorthands.into_iter().map(|(_, pat_span, _)| pat_span).collect(); + let non_shorthands = + non_shorthands.into_iter().map(|(_, pat_span, _)| pat_span).collect(); - self.ir.tcx.struct_span_lint_hir( + self.ir.tcx.emit_spanned_lint( lint::builtin::UNUSED_VARIABLES, first_hir_id, hir_ids_and_spans .iter() .map(|(_, pat_span, _)| *pat_span) .collect::>(), - format!("unused variable: `{}`", name), - |lint| { - lint.multipart_suggestion( - "try ignoring the field", + errors::UnusedVarTryIgnore { + sugg: errors::UnusedVarTryIgnoreSugg { shorthands, - Applicability::MachineApplicable, - ) + non_shorthands, + name, + }, }, ); } else { let non_shorthands = non_shorthands .into_iter() - .map(|(_, _, ident_span)| (ident_span, format!("_{}", name))) + .map(|(_, _, ident_span)| ident_span) .collect::>(); - - self.ir.tcx.struct_span_lint_hir( + let suggestions = self.string_interp_suggestions(&name, opt_body); + self.ir.tcx.emit_spanned_lint( lint::builtin::UNUSED_VARIABLES, first_hir_id, hir_ids_and_spans .iter() .map(|(_, _, ident_span)| *ident_span) .collect::>(), - format!("unused variable: `{}`", name), - |lint| { - if self.has_added_lit_match_name_span(&name, opt_body, lint) { - lint.span_label(pat.span, "unused variable"); - } - lint.multipart_suggestion( - "if this is intentional, prefix it with an underscore", - non_shorthands, - Applicability::MachineApplicable, - ) + errors::UnusedVariableTryPrefix { + label: if !suggestions.is_empty() { Some(pat.span) } else { None }, + sugg: errors::UnusedVariableTryPrefixSugg { + spans: non_shorthands, + name, + }, + string_interp: suggestions, }, ); } @@ -1689,65 +1670,40 @@ impl<'tcx> Liveness<'_, 'tcx> { } } - fn has_added_lit_match_name_span( + fn string_interp_suggestions( &self, name: &str, opt_body: Option<&hir::Body<'_>>, - err: &mut Diagnostic, - ) -> bool { - let mut has_litstring = false; - let Some(opt_body) = opt_body else {return false;}; + ) -> Vec { + let mut suggs = Vec::new(); + let Some(opt_body) = opt_body else { return suggs; }; let mut visitor = CollectLitsVisitor { lit_exprs: vec![] }; intravisit::walk_body(&mut visitor, opt_body); for lit_expr in visitor.lit_exprs { let hir::ExprKind::Lit(litx) = &lit_expr.kind else { continue }; let rustc_ast::LitKind::Str(syb, _) = litx.node else{ continue; }; let name_str: &str = syb.as_str(); - let mut name_pa = String::from("{"); - name_pa.push_str(&name); - name_pa.push('}'); + let name_pa = format!("{{{name}}}"); if name_str.contains(&name_pa) { - err.span_label( - lit_expr.span, - "you might have meant to use string interpolation in this string literal", - ); - err.multipart_suggestion( - "string interpolation only works in `format!` invocations", - vec![ - (lit_expr.span.shrink_to_lo(), "format!(".to_string()), - (lit_expr.span.shrink_to_hi(), ")".to_string()), - ], - Applicability::MachineApplicable, - ); - has_litstring = true; + suggs.push(errors::UnusedVariableStringInterp { + lit: lit_expr.span, + lo: lit_expr.span.shrink_to_lo(), + hi: lit_expr.span.shrink_to_hi(), + }); } } - has_litstring + suggs } fn warn_about_dead_assign(&self, spans: Vec, hir_id: HirId, ln: LiveNode, var: Variable) { - if !self.live_on_exit(ln, var) { - self.report_unused_assign(hir_id, spans, var, |name| { - format!("value assigned to `{}` is never read", name) - }); - } - } - - fn report_unused_assign( - &self, - hir_id: HirId, - spans: Vec, - var: Variable, - message: impl Fn(&str) -> String, - ) { - if let Some(name) = self.should_warn(var) { - self.ir.tcx.struct_span_lint_hir( - lint::builtin::UNUSED_ASSIGNMENTS, - hir_id, - spans, - message(&name), - |lint| lint.help("maybe it is overwritten before being read?"), - ) - } + if !self.live_on_exit(ln, var) + && let Some(name) = self.should_warn(var) { + self.ir.tcx.emit_spanned_lint( + lint::builtin::UNUSED_ASSIGNMENTS, + hir_id, + spans, + errors::UnusedAssign { name }, + ); + } } } diff --git a/compiler/rustc_passes/src/stability.rs b/compiler/rustc_passes/src/stability.rs index 4a35c6794663e..9615f283ff423 100644 --- a/compiler/rustc_passes/src/stability.rs +++ b/compiler/rustc_passes/src/stability.rs @@ -7,7 +7,6 @@ use rustc_attr::{ UnstableReason, VERSION_PLACEHOLDER, }; use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap}; -use rustc_errors::Applicability; use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::{LocalDefId, CRATE_DEF_ID}; @@ -759,12 +758,11 @@ impl<'tcx> Visitor<'tcx> for Checker<'tcx> { // do not lint when the trait isn't resolved, since resolution error should // be fixed first if t.path.res != Res::Err && c.fully_stable { - self.tcx.struct_span_lint_hir( + self.tcx.emit_spanned_lint( INEFFECTIVE_UNSTABLE_TRAIT_IMPL, item.hir_id(), span, - "an `#[unstable]` annotation here has no effect", - |lint| lint.note("see issue #55436 for more information") + errors::IneffectiveUnstableImpl, ); } } @@ -1095,29 +1093,16 @@ fn unnecessary_partially_stable_feature_lint( implies: Symbol, since: Symbol, ) { - tcx.struct_span_lint_hir( + tcx.emit_spanned_lint( lint::builtin::STABLE_FEATURES, hir::CRATE_HIR_ID, span, - format!( - "the feature `{feature}` has been partially stabilized since {since} and is succeeded \ - by the feature `{implies}`" - ), - |lint| { - lint.span_suggestion( - span, - &format!( - "if you are using features which are still unstable, change to using `{implies}`" - ), - implies, - Applicability::MaybeIncorrect, - ) - .span_suggestion( - tcx.sess.source_map().span_extend_to_line(span), - "if you are using features which are now stable, remove this line", - "", - Applicability::MaybeIncorrect, - ) + errors::UnnecessaryPartialStableFeature { + span, + line: tcx.sess.source_map().span_extend_to_line(span), + feature, + since, + implies, }, ); } @@ -1131,7 +1116,10 @@ fn unnecessary_stable_feature_lint( if since.as_str() == VERSION_PLACEHOLDER { since = rust_version_symbol(); } - tcx.struct_span_lint_hir(lint::builtin::STABLE_FEATURES, hir::CRATE_HIR_ID, span, format!("the feature `{feature}` has been stable since {since} and no longer requires an attribute to enable"), |lint| { - lint - }); + tcx.emit_spanned_lint( + lint::builtin::STABLE_FEATURES, + hir::CRATE_HIR_ID, + span, + errors::UnnecessaryStableFeature { feature, since }, + ); } diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs index 9567329192d52..c607c7fd5f4a7 100644 --- a/compiler/rustc_privacy/src/lib.rs +++ b/compiler/rustc_privacy/src/lib.rs @@ -269,7 +269,7 @@ where // and are visited by shallow visitors. self.visit_predicates(ty::GenericPredicates { parent: None, - predicates: tcx.explicit_item_bounds(def_id), + predicates: tcx.explicit_item_bounds(def_id).skip_binder(), })?; } } @@ -1784,7 +1784,7 @@ impl SearchInterfaceForPrivateItemsVisitor<'_> { fn bounds(&mut self) -> &mut Self { self.visit_predicates(ty::GenericPredicates { parent: None, - predicates: self.tcx.explicit_item_bounds(self.item_def_id), + predicates: self.tcx.explicit_item_bounds(self.item_def_id).skip_binder(), }); self } diff --git a/compiler/rustc_query_impl/src/on_disk_cache.rs b/compiler/rustc_query_impl/src/on_disk_cache.rs index 91b56660b1541..c0f2d7803d492 100644 --- a/compiler/rustc_query_impl/src/on_disk_cache.rs +++ b/compiler/rustc_query_impl/src/on_disk_cache.rs @@ -169,13 +169,12 @@ impl<'sess> rustc_middle::ty::OnDiskCache<'sess> for OnDiskCache<'sess> { // Decode the *position* of the footer, which can be found in the // last 8 bytes of the file. - decoder.set_position(data.len() - IntEncodedWithFixedSize::ENCODED_SIZE); - let footer_pos = IntEncodedWithFixedSize::decode(&mut decoder).0 as usize; - + let footer_pos = decoder + .with_position(decoder.len() - IntEncodedWithFixedSize::ENCODED_SIZE, |decoder| { + IntEncodedWithFixedSize::decode(decoder).0 as usize + }); // Decode the file footer, which contains all the lookup tables, etc. - decoder.set_position(footer_pos); - - decode_tagged(&mut decoder, TAG_FILE_FOOTER) + decoder.with_position(footer_pos, |decoder| decode_tagged(decoder, TAG_FILE_FOOTER)) }; Self { @@ -522,29 +521,13 @@ impl<'a, 'tcx> CacheDecoder<'a, 'tcx> { } } -trait DecoderWithPosition: Decoder { - fn position(&self) -> usize; -} - -impl<'a> DecoderWithPosition for MemDecoder<'a> { - fn position(&self) -> usize { - self.position() - } -} - -impl<'a, 'tcx> DecoderWithPosition for CacheDecoder<'a, 'tcx> { - fn position(&self) -> usize { - self.opaque.position() - } -} - // Decodes something that was encoded with `encode_tagged()` and verify that the // tag matches and the correct amount of bytes was read. fn decode_tagged(decoder: &mut D, expected_tag: T) -> V where T: Decodable + Eq + std::fmt::Debug, V: Decodable, - D: DecoderWithPosition, + D: Decoder, { let start_pos = decoder.position(); @@ -568,16 +551,6 @@ impl<'a, 'tcx> TyDecoder for CacheDecoder<'a, 'tcx> { self.tcx } - #[inline] - fn position(&self) -> usize { - self.opaque.position() - } - - #[inline] - fn peek_byte(&self) -> u8 { - self.opaque.data[self.opaque.position()] - } - fn cached_ty_for_shorthand(&mut self, shorthand: usize, or_insert_with: F) -> Ty<'tcx> where F: FnOnce(&mut Self) -> Ty<'tcx>, @@ -600,9 +573,9 @@ impl<'a, 'tcx> TyDecoder for CacheDecoder<'a, 'tcx> { where F: FnOnce(&mut Self) -> R, { - debug_assert!(pos < self.opaque.data.len()); + debug_assert!(pos < self.opaque.len()); - let new_opaque = MemDecoder::new(self.opaque.data, pos); + let new_opaque = MemDecoder::new(self.opaque.data(), pos); let old_opaque = mem::replace(&mut self.opaque, new_opaque); let r = f(self); self.opaque = old_opaque; @@ -743,17 +716,12 @@ impl<'a, 'tcx> Decodable> for Symbol { SYMBOL_OFFSET => { // read str offset let pos = d.read_usize(); - let old_pos = d.opaque.position(); // move to str offset and read - d.opaque.set_position(pos); - let s = d.read_str(); - let sym = Symbol::intern(s); - - // restore position - d.opaque.set_position(old_pos); - - sym + d.opaque.with_position(pos, |d| { + let s = d.read_str(); + Symbol::intern(s) + }) } SYMBOL_PREINTERNED => { let symbol_index = d.read_u32(); diff --git a/compiler/rustc_query_system/src/dep_graph/serialized.rs b/compiler/rustc_query_system/src/dep_graph/serialized.rs index 59c1333fb5a46..edddfda624242 100644 --- a/compiler/rustc_query_system/src/dep_graph/serialized.rs +++ b/compiler/rustc_query_system/src/dep_graph/serialized.rs @@ -94,21 +94,19 @@ impl<'a, K: DepKind + Decodable>> Decodable> { #[instrument(level = "debug", skip(d))] fn decode(d: &mut MemDecoder<'a>) -> SerializedDepGraph { - let start_position = d.position(); - // The last 16 bytes are the node count and edge count. debug!("position: {:?}", d.position()); - d.set_position(d.data.len() - 2 * IntEncodedWithFixedSize::ENCODED_SIZE); + let (node_count, edge_count) = + d.with_position(d.len() - 2 * IntEncodedWithFixedSize::ENCODED_SIZE, |d| { + debug!("position: {:?}", d.position()); + let node_count = IntEncodedWithFixedSize::decode(d).0 as usize; + let edge_count = IntEncodedWithFixedSize::decode(d).0 as usize; + (node_count, edge_count) + }); debug!("position: {:?}", d.position()); - let node_count = IntEncodedWithFixedSize::decode(d).0 as usize; - let edge_count = IntEncodedWithFixedSize::decode(d).0 as usize; debug!(?node_count, ?edge_count); - debug!("position: {:?}", d.position()); - d.set_position(start_position); - debug!("position: {:?}", d.position()); - let mut nodes = IndexVec::with_capacity(node_count); let mut fingerprints = IndexVec::with_capacity(node_count); let mut edge_list_indices = IndexVec::with_capacity(node_count); diff --git a/compiler/rustc_resolve/messages.ftl b/compiler/rustc_resolve/messages.ftl index 192badcbc37ea..32409499047cd 100644 --- a/compiler/rustc_resolve/messages.ftl +++ b/compiler/rustc_resolve/messages.ftl @@ -226,3 +226,10 @@ resolve_add_as_non_derive = resolve_proc_macro_same_crate = can't use a procedural macro from the same crate that defines it .help = you can define integration tests in a directory named `tests` + +resolve_imported_crate = `$crate` may not be imported + +resolve_macro_use_extern_crate_self = `#[macro_use]` is not supported on `extern crate self` + +resolve_accessible_unsure = not sure whether the path is accessible or not + .note = the type may have associated items, but we are currently not checking them diff --git a/compiler/rustc_resolve/src/build_reduced_graph.rs b/compiler/rustc_resolve/src/build_reduced_graph.rs index 967c9e22fb26c..3799679cb1eac 100644 --- a/compiler/rustc_resolve/src/build_reduced_graph.rs +++ b/compiler/rustc_resolve/src/build_reduced_graph.rs @@ -9,7 +9,9 @@ use crate::def_collector::collect_definitions; use crate::imports::{Import, ImportKind}; use crate::macros::{MacroRulesBinding, MacroRulesScope, MacroRulesScopeRef}; use crate::Namespace::{self, MacroNS, TypeNS, ValueNS}; -use crate::{Determinacy, ExternPreludeEntry, Finalize, Module, ModuleKind, ModuleOrUniformRoot}; +use crate::{ + errors, Determinacy, ExternPreludeEntry, Finalize, Module, ModuleKind, ModuleOrUniformRoot, +}; use crate::{ MacroData, NameBinding, NameBindingKind, ParentScope, PathResult, PerNS, ResolutionError, }; @@ -523,11 +525,7 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> { ident.name = crate_name; } - self.r - .tcx - .sess - .struct_span_err(item.span, "`$crate` may not be imported") - .emit(); + self.r.tcx.sess.emit_err(errors::CrateImported { span: item.span }); } } @@ -1028,11 +1026,7 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> { self.r .tcx .sess - .struct_span_err( - attr.span, - "`#[macro_use]` is not supported on `extern crate self`", - ) - .emit(); + .emit_err(errors::MacroUseExternCrateSelf { span: attr.span }); } } let ill_formed = |span| { diff --git a/compiler/rustc_resolve/src/errors.rs b/compiler/rustc_resolve/src/errors.rs index 6197af105a965..4f9f1c7e85648 100644 --- a/compiler/rustc_resolve/src/errors.rs +++ b/compiler/rustc_resolve/src/errors.rs @@ -517,3 +517,25 @@ pub(crate) struct ProcMacroSameCrate { #[help] pub(crate) is_test: bool, } + +#[derive(Diagnostic)] +#[diag(resolve_imported_crate)] +pub(crate) struct CrateImported { + #[primary_span] + pub(crate) span: Span, +} + +#[derive(Diagnostic)] +#[diag(resolve_macro_use_extern_crate_self)] +pub(crate) struct MacroUseExternCrateSelf { + #[primary_span] + pub(crate) span: Span, +} + +#[derive(Diagnostic)] +#[diag(resolve_accessible_unsure)] +#[note] +pub(crate) struct CfgAccessibleUnsure { + #[primary_span] + pub(crate) span: Span, +} diff --git a/compiler/rustc_resolve/src/macros.rs b/compiler/rustc_resolve/src/macros.rs index 2211fb56ccda1..b30c1cd226cb6 100644 --- a/compiler/rustc_resolve/src/macros.rs +++ b/compiler/rustc_resolve/src/macros.rs @@ -436,9 +436,7 @@ impl<'a, 'tcx> ResolverExpand for Resolver<'a, 'tcx> { // HACK(Urgau): This shouldn't be necessary PathResult::Failed { is_error_from_last_segment: false, .. } => { self.tcx.sess - .struct_span_err(span, "not sure whether the path is accessible or not") - .note("the type may have associated items, but we are currently not checking them") - .emit(); + .emit_err(errors::CfgAccessibleUnsure { span }); // If we get a partially resolved NonModule in one namespace, we should get the // same result in any other namespaces, so we can return early. diff --git a/compiler/rustc_serialize/src/leb128.rs b/compiler/rustc_serialize/src/leb128.rs index 7dad9aa01fafd..e568b9e6786f9 100644 --- a/compiler/rustc_serialize/src/leb128.rs +++ b/compiler/rustc_serialize/src/leb128.rs @@ -1,3 +1,6 @@ +use crate::opaque::MemDecoder; +use crate::serialize::Decoder; + /// Returns the length of the longest LEB128 encoding for `T`, assuming `T` is an integer type pub const fn max_leb128_len() -> usize { // The longest LEB128 encoding for an integer uses 7 bits per byte. @@ -50,21 +53,19 @@ impl_write_unsigned_leb128!(write_usize_leb128, usize); macro_rules! impl_read_unsigned_leb128 { ($fn_name:ident, $int_ty:ty) => { #[inline] - pub fn $fn_name(slice: &[u8], position: &mut usize) -> $int_ty { + pub fn $fn_name(decoder: &mut MemDecoder<'_>) -> $int_ty { // The first iteration of this loop is unpeeled. This is a // performance win because this code is hot and integer values less // than 128 are very common, typically occurring 50-80% or more of // the time, even for u64 and u128. - let byte = slice[*position]; - *position += 1; + let byte = decoder.read_u8(); if (byte & 0x80) == 0 { return byte as $int_ty; } let mut result = (byte & 0x7F) as $int_ty; let mut shift = 7; loop { - let byte = slice[*position]; - *position += 1; + let byte = decoder.read_u8(); if (byte & 0x80) == 0 { result |= (byte as $int_ty) << shift; return result; @@ -127,14 +128,13 @@ impl_write_signed_leb128!(write_isize_leb128, isize); macro_rules! impl_read_signed_leb128 { ($fn_name:ident, $int_ty:ty) => { #[inline] - pub fn $fn_name(slice: &[u8], position: &mut usize) -> $int_ty { + pub fn $fn_name(decoder: &mut MemDecoder<'_>) -> $int_ty { let mut result = 0; let mut shift = 0; let mut byte; loop { - byte = slice[*position]; - *position += 1; + byte = decoder.read_u8(); result |= <$int_ty>::from(byte & 0x7F) << shift; shift += 7; diff --git a/compiler/rustc_serialize/src/lib.rs b/compiler/rustc_serialize/src/lib.rs index 1f8d2336c4e58..ce8503918b4f2 100644 --- a/compiler/rustc_serialize/src/lib.rs +++ b/compiler/rustc_serialize/src/lib.rs @@ -16,6 +16,7 @@ Core encoding and decoding interfaces. #![feature(maybe_uninit_slice)] #![feature(new_uninit)] #![feature(allocator_api)] +#![feature(ptr_sub_ptr)] #![cfg_attr(test, feature(test))] #![allow(rustc::internal)] #![deny(rustc::untranslatable_diagnostic)] diff --git a/compiler/rustc_serialize/src/opaque.rs b/compiler/rustc_serialize/src/opaque.rs index 53e5c89673652..b7976ea3b1c63 100644 --- a/compiler/rustc_serialize/src/opaque.rs +++ b/compiler/rustc_serialize/src/opaque.rs @@ -2,7 +2,9 @@ use crate::leb128::{self, largest_max_leb128_len}; use crate::serialize::{Decodable, Decoder, Encodable, Encoder}; use std::fs::File; use std::io::{self, Write}; +use std::marker::PhantomData; use std::mem::MaybeUninit; +use std::ops::Range; use std::path::Path; use std::ptr; @@ -510,38 +512,125 @@ impl Encoder for FileEncoder { // Decoder // ----------------------------------------------------------------------------- +// Conceptually, `MemDecoder` wraps a `&[u8]` with a cursor into it that is always valid. +// This is implemented with three pointers, two which represent the original slice and a +// third that is our cursor. +// It is an invariant of this type that start <= current <= end. +// Additionally, the implementation of this type never modifies start and end. pub struct MemDecoder<'a> { - pub data: &'a [u8], - position: usize, + start: *const u8, + current: *const u8, + end: *const u8, + _marker: PhantomData<&'a u8>, } impl<'a> MemDecoder<'a> { #[inline] pub fn new(data: &'a [u8], position: usize) -> MemDecoder<'a> { - MemDecoder { data, position } + let Range { start, end } = data.as_ptr_range(); + MemDecoder { start, current: data[position..].as_ptr(), end, _marker: PhantomData } } #[inline] - pub fn position(&self) -> usize { - self.position + pub fn data(&self) -> &'a [u8] { + // SAFETY: This recovers the original slice, only using members we never modify. + unsafe { std::slice::from_raw_parts(self.start, self.len()) } } #[inline] - pub fn set_position(&mut self, pos: usize) { - self.position = pos + pub fn len(&self) -> usize { + // SAFETY: This recovers the length of the original slice, only using members we never modify. + unsafe { self.end.sub_ptr(self.start) } + } + + #[inline] + pub fn remaining(&self) -> usize { + // SAFETY: This type guarantees current <= end. + unsafe { self.end.sub_ptr(self.current) } + } + + #[cold] + #[inline(never)] + fn decoder_exhausted() -> ! { + panic!("MemDecoder exhausted") } #[inline] - pub fn advance(&mut self, bytes: usize) { - self.position += bytes; + fn read_byte(&mut self) -> u8 { + if self.current == self.end { + Self::decoder_exhausted(); + } + // SAFETY: This type guarantees current <= end, and we just checked current == end. + unsafe { + let byte = *self.current; + self.current = self.current.add(1); + byte + } + } + + #[inline] + fn read_array(&mut self) -> [u8; N] { + self.read_raw_bytes(N).try_into().unwrap() + } + + // The trait method doesn't have a lifetime parameter, and we need a version of this + // that definitely returns a slice based on the underlying storage as opposed to + // the Decoder itself in order to implement read_str efficiently. + #[inline] + fn read_raw_bytes_inherent(&mut self, bytes: usize) -> &'a [u8] { + if bytes > self.remaining() { + Self::decoder_exhausted(); + } + // SAFETY: We just checked if this range is in-bounds above. + unsafe { + let slice = std::slice::from_raw_parts(self.current, bytes); + self.current = self.current.add(bytes); + slice + } + } + + /// While we could manually expose manipulation of the decoder position, + /// all current users of that method would need to reset the position later, + /// incurring the bounds check of set_position twice. + #[inline] + pub fn with_position(&mut self, pos: usize, func: F) -> T + where + F: Fn(&mut MemDecoder<'a>) -> T, + { + struct SetOnDrop<'a, 'guarded> { + decoder: &'guarded mut MemDecoder<'a>, + current: *const u8, + } + impl Drop for SetOnDrop<'_, '_> { + fn drop(&mut self) { + self.decoder.current = self.current; + } + } + + if pos >= self.len() { + Self::decoder_exhausted(); + } + let previous = self.current; + // SAFETY: We just checked if this add is in-bounds above. + unsafe { + self.current = self.start.add(pos); + } + let guard = SetOnDrop { current: previous, decoder: self }; + func(guard.decoder) } } macro_rules! read_leb128 { - ($dec:expr, $fun:ident) => {{ leb128::$fun($dec.data, &mut $dec.position) }}; + ($dec:expr, $fun:ident) => {{ leb128::$fun($dec) }}; } impl<'a> Decoder for MemDecoder<'a> { + #[inline] + fn position(&self) -> usize { + // SAFETY: This type guarantees start <= current + unsafe { self.current.sub_ptr(self.start) } + } + #[inline] fn read_u128(&mut self) -> u128 { read_leb128!(self, read_u128_leb128) @@ -559,17 +648,12 @@ impl<'a> Decoder for MemDecoder<'a> { #[inline] fn read_u16(&mut self) -> u16 { - let bytes = [self.data[self.position], self.data[self.position + 1]]; - let value = u16::from_le_bytes(bytes); - self.position += 2; - value + u16::from_le_bytes(self.read_array()) } #[inline] fn read_u8(&mut self) -> u8 { - let value = self.data[self.position]; - self.position += 1; - value + self.read_byte() } #[inline] @@ -594,17 +678,12 @@ impl<'a> Decoder for MemDecoder<'a> { #[inline] fn read_i16(&mut self) -> i16 { - let bytes = [self.data[self.position], self.data[self.position + 1]]; - let value = i16::from_le_bytes(bytes); - self.position += 2; - value + i16::from_le_bytes(self.read_array()) } #[inline] fn read_i8(&mut self) -> i8 { - let value = self.data[self.position]; - self.position += 1; - value as i8 + self.read_byte() as i8 } #[inline] @@ -625,22 +704,26 @@ impl<'a> Decoder for MemDecoder<'a> { } #[inline] - fn read_str(&mut self) -> &'a str { + fn read_str(&mut self) -> &str { let len = self.read_usize(); - let sentinel = self.data[self.position + len]; - assert!(sentinel == STR_SENTINEL); - let s = unsafe { - std::str::from_utf8_unchecked(&self.data[self.position..self.position + len]) - }; - self.position += len + 1; - s + let bytes = self.read_raw_bytes_inherent(len + 1); + assert!(bytes[len] == STR_SENTINEL); + unsafe { std::str::from_utf8_unchecked(&bytes[..len]) } } #[inline] - fn read_raw_bytes(&mut self, bytes: usize) -> &'a [u8] { - let start = self.position; - self.position += bytes; - &self.data[start..self.position] + fn read_raw_bytes(&mut self, bytes: usize) -> &[u8] { + self.read_raw_bytes_inherent(bytes) + } + + #[inline] + fn peek_byte(&self) -> u8 { + if self.current == self.end { + Self::decoder_exhausted(); + } + // SAFETY: This type guarantees current is inbounds or one-past-the-end, which is end. + // Since we just checked current == end, the current pointer must be inbounds. + unsafe { *self.current } } } diff --git a/compiler/rustc_serialize/src/serialize.rs b/compiler/rustc_serialize/src/serialize.rs index 527abc2372715..a6d9c7b7d4210 100644 --- a/compiler/rustc_serialize/src/serialize.rs +++ b/compiler/rustc_serialize/src/serialize.rs @@ -84,6 +84,8 @@ pub trait Decoder { fn read_char(&mut self) -> char; fn read_str(&mut self) -> &str; fn read_raw_bytes(&mut self, len: usize) -> &[u8]; + fn peek_byte(&self) -> u8; + fn position(&self) -> usize; } /// Trait for types that can be serialized diff --git a/compiler/rustc_serialize/tests/leb128.rs b/compiler/rustc_serialize/tests/leb128.rs index 314c07db981da..7872e7784311a 100644 --- a/compiler/rustc_serialize/tests/leb128.rs +++ b/compiler/rustc_serialize/tests/leb128.rs @@ -3,6 +3,7 @@ use rustc_serialize::leb128::*; use std::mem::MaybeUninit; +use rustc_serialize::Decoder; macro_rules! impl_test_unsigned_leb128 { ($test_name:ident, $write_fn_name:ident, $read_fn_name:ident, $int_ty:ident) => { @@ -28,12 +29,12 @@ macro_rules! impl_test_unsigned_leb128 { stream.extend($write_fn_name(&mut buf, x)); } - let mut position = 0; + let mut decoder = rustc_serialize::opaque::MemDecoder::new(&stream, 0); for &expected in &values { - let actual = $read_fn_name(&stream, &mut position); + let actual = $read_fn_name(&mut decoder); assert_eq!(expected, actual); } - assert_eq!(stream.len(), position); + assert_eq!(stream.len(), decoder.position()); } }; } @@ -74,12 +75,12 @@ macro_rules! impl_test_signed_leb128 { stream.extend($write_fn_name(&mut buf, x)); } - let mut position = 0; + let mut decoder = rustc_serialize::opaque::MemDecoder::new(&stream, 0); for &expected in &values { - let actual = $read_fn_name(&stream, &mut position); + let actual = $read_fn_name(&mut decoder); assert_eq!(expected, actual); } - assert_eq!(stream.len(), position); + assert_eq!(stream.len(), decoder.position()); } }; } diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs index 79eb31bb1050e..51418c01eedb4 100644 --- a/compiler/rustc_session/src/config.rs +++ b/compiler/rustc_session/src/config.rs @@ -1400,7 +1400,8 @@ The default is {DEFAULT_EDITION} and the latest stable edition is {LATEST_STABLE pub fn rustc_short_optgroups() -> Vec { vec![ opt::flag_s("h", "help", "Display this message"), - opt::multi_s("", "cfg", "Configure the compilation environment", "SPEC"), + opt::multi_s("", "cfg", "Configure the compilation environment. + SPEC supports the syntax `NAME[=\"VALUE\"]`.", "SPEC"), opt::multi("", "check-cfg", "Provide list of valid cfg options for checking", "SPEC"), opt::multi_s( "L", diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 70b9088de5064..abf19c30e3deb 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -651,6 +651,7 @@ symbols! { edition_panic, eh_catch_typeinfo, eh_personality, + emit, emit_enum, emit_enum_variant, emit_enum_variant_arg, diff --git a/compiler/rustc_symbol_mangling/src/legacy.rs b/compiler/rustc_symbol_mangling/src/legacy.rs index 6a0ca06f69caa..a3f262905c74f 100644 --- a/compiler/rustc_symbol_mangling/src/legacy.rs +++ b/compiler/rustc_symbol_mangling/src/legacy.rs @@ -108,7 +108,7 @@ fn get_symbol_hash<'tcx>( tcx.def_path_hash(def_id).hash_stable(&mut hcx, &mut hasher); // Include the main item-type. Note that, in this case, the - // assertions about `needs_subst` may not hold, but this item-type + // assertions about `has_param` may not hold, but this item-type // ought to be the same for every reference anyway. assert!(!item_type.has_erasable_regions()); hcx.while_hashing_spans(false, |hcx| { diff --git a/compiler/rustc_target/src/asm/loongarch.rs b/compiler/rustc_target/src/asm/loongarch.rs new file mode 100644 index 0000000000000..7ace1647ded43 --- /dev/null +++ b/compiler/rustc_target/src/asm/loongarch.rs @@ -0,0 +1,131 @@ +use super::{InlineAsmArch, InlineAsmType}; +use rustc_macros::HashStable_Generic; +use rustc_span::Symbol; +use std::fmt; + +def_reg_class! { + LoongArch LoongArchInlineAsmRegClass { + reg, + freg, + } +} + +impl LoongArchInlineAsmRegClass { + pub fn valid_modifiers(self, _arch: super::InlineAsmArch) -> &'static [char] { + &[] + } + + pub fn suggest_class(self, _arch: InlineAsmArch, _ty: InlineAsmType) -> Option { + None + } + + pub fn suggest_modifier( + self, + _arch: InlineAsmArch, + _ty: InlineAsmType, + ) -> Option<(char, &'static str)> { + None + } + + pub fn default_modifier(self, _arch: InlineAsmArch) -> Option<(char, &'static str)> { + None + } + + pub fn supported_types( + self, + arch: InlineAsmArch, + ) -> &'static [(InlineAsmType, Option)] { + match (self, arch) { + (Self::reg, InlineAsmArch::LoongArch64) => types! { _: I8, I16, I32, I64, F32, F64; }, + (Self::reg, _) => types! { _: I8, I16, I32, F32; }, + (Self::freg, _) => types! { _: F32, F64; }, + } + } +} + +// The reserved registers are taken from +def_regs! { + LoongArch LoongArchInlineAsmReg LoongArchInlineAsmRegClass { + r1: reg = ["$r1","$ra"], + r4: reg = ["$r4","$a0"], + r5: reg = ["$r5","$a1"], + r6: reg = ["$r6","$a2"], + r7: reg = ["$r7","$a3"], + r8: reg = ["$r8","$a4"], + r9: reg = ["$r9","$a5"], + r10: reg = ["$r10","$a6"], + r11: reg = ["$r11","$a7"], + r12: reg = ["$r12","$t0"], + r13: reg = ["$r13","$t1"], + r14: reg = ["$r14","$t2"], + r15: reg = ["$r15","$t3"], + r16: reg = ["$r16","$t4"], + r17: reg = ["$r17","$t5"], + r18: reg = ["$r18","$t6"], + r19: reg = ["$r19","$t7"], + r20: reg = ["$r20","$t8"], + r23: reg = ["$r23","$s0"], + r24: reg = ["$r24","$s1"], + r25: reg = ["$r25","$s2"], + r26: reg = ["$r26","$s3"], + r27: reg = ["$r27","$s4"], + r28: reg = ["$r28","$s5"], + r29: reg = ["$r29","$s6"], + r30: reg = ["$r30","$s7"], + f0: freg = ["$f0","$fa0"], + f1: freg = ["$f1","$fa1"], + f2: freg = ["$f2","$fa2"], + f3: freg = ["$f3","$fa3"], + f4: freg = ["$f4","$fa4"], + f5: freg = ["$f5","$fa5"], + f6: freg = ["$f6","$fa6"], + f7: freg = ["$f7","$fa7"], + f8: freg = ["$f8","$ft0"], + f9: freg = ["$f9","$ft1"], + f10: freg = ["$f10","$ft2"], + f11: freg = ["$f11","$ft3"], + f12: freg = ["$f12","$ft4"], + f13: freg = ["$f13","$ft5"], + f14: freg = ["$f14","$ft6"], + f15: freg = ["$f15","$ft7"], + f16: freg = ["$f16","$ft8"], + f17: freg = ["$f17","$ft9"], + f18: freg = ["$f18","$ft10"], + f19: freg = ["$f19","$ft11"], + f20: freg = ["$f20","$ft12"], + f21: freg = ["$f21","$ft13"], + f22: freg = ["$f22","$ft14"], + f23: freg = ["$f23","$ft15"], + f24: freg = ["$f24","$fs0"], + f25: freg = ["$f25","$fs1"], + f26: freg = ["$f26","$fs2"], + f27: freg = ["$f27","$fs3"], + f28: freg = ["$f28","$fs4"], + f29: freg = ["$f29","$fs5"], + f30: freg = ["$f30","$fs6"], + f31: freg = ["$f31","$fs7"], + #error = ["$r0","$zero"] => + "constant zero cannot be used as an operand for inline asm", + #error = ["$r2","$tp"] => + "reserved for TLS", + #error = ["$r3","$sp"] => + "the stack pointer cannot be used as an operand for inline asm", + #error = ["$r21"] => + "reserved by the ABI", + #error = ["$r22","$fp"] => + "the frame pointer cannot be used as an operand for inline asm", + #error = ["$r31","$s8"] => + "$r31 is used internally by LLVM and cannot be used as an operand for inline asm", + } +} + +impl LoongArchInlineAsmReg { + pub fn emit( + self, + out: &mut dyn fmt::Write, + _arch: InlineAsmArch, + _modifier: Option, + ) -> fmt::Result { + out.write_str(self.name()) + } +} diff --git a/compiler/rustc_target/src/asm/mod.rs b/compiler/rustc_target/src/asm/mod.rs index 3f9c850b3524c..266691b2c88c3 100644 --- a/compiler/rustc_target/src/asm/mod.rs +++ b/compiler/rustc_target/src/asm/mod.rs @@ -168,6 +168,7 @@ mod arm; mod avr; mod bpf; mod hexagon; +mod loongarch; mod m68k; mod mips; mod msp430; @@ -184,6 +185,7 @@ pub use arm::{ArmInlineAsmReg, ArmInlineAsmRegClass}; pub use avr::{AvrInlineAsmReg, AvrInlineAsmRegClass}; pub use bpf::{BpfInlineAsmReg, BpfInlineAsmRegClass}; pub use hexagon::{HexagonInlineAsmReg, HexagonInlineAsmRegClass}; +pub use loongarch::{LoongArchInlineAsmReg, LoongArchInlineAsmRegClass}; pub use m68k::{M68kInlineAsmReg, M68kInlineAsmRegClass}; pub use mips::{MipsInlineAsmReg, MipsInlineAsmRegClass}; pub use msp430::{Msp430InlineAsmReg, Msp430InlineAsmRegClass}; @@ -205,6 +207,7 @@ pub enum InlineAsmArch { RiscV64, Nvptx64, Hexagon, + LoongArch64, Mips, Mips64, PowerPC, @@ -234,6 +237,7 @@ impl FromStr for InlineAsmArch { "powerpc" => Ok(Self::PowerPC), "powerpc64" => Ok(Self::PowerPC64), "hexagon" => Ok(Self::Hexagon), + "loongarch64" => Ok(Self::LoongArch64), "mips" => Ok(Self::Mips), "mips64" => Ok(Self::Mips64), "s390x" => Ok(Self::S390x), @@ -259,6 +263,7 @@ pub enum InlineAsmReg { Nvptx(NvptxInlineAsmReg), PowerPC(PowerPCInlineAsmReg), Hexagon(HexagonInlineAsmReg), + LoongArch(LoongArchInlineAsmReg), Mips(MipsInlineAsmReg), S390x(S390xInlineAsmReg), SpirV(SpirVInlineAsmReg), @@ -280,6 +285,7 @@ impl InlineAsmReg { Self::RiscV(r) => r.name(), Self::PowerPC(r) => r.name(), Self::Hexagon(r) => r.name(), + Self::LoongArch(r) => r.name(), Self::Mips(r) => r.name(), Self::S390x(r) => r.name(), Self::Bpf(r) => r.name(), @@ -298,6 +304,7 @@ impl InlineAsmReg { Self::RiscV(r) => InlineAsmRegClass::RiscV(r.reg_class()), Self::PowerPC(r) => InlineAsmRegClass::PowerPC(r.reg_class()), Self::Hexagon(r) => InlineAsmRegClass::Hexagon(r.reg_class()), + Self::LoongArch(r) => InlineAsmRegClass::LoongArch(r.reg_class()), Self::Mips(r) => InlineAsmRegClass::Mips(r.reg_class()), Self::S390x(r) => InlineAsmRegClass::S390x(r.reg_class()), Self::Bpf(r) => InlineAsmRegClass::Bpf(r.reg_class()), @@ -324,6 +331,7 @@ impl InlineAsmReg { Self::PowerPC(PowerPCInlineAsmReg::parse(name)?) } InlineAsmArch::Hexagon => Self::Hexagon(HexagonInlineAsmReg::parse(name)?), + InlineAsmArch::LoongArch64 => Self::LoongArch(LoongArchInlineAsmReg::parse(name)?), InlineAsmArch::Mips | InlineAsmArch::Mips64 => { Self::Mips(MipsInlineAsmReg::parse(name)?) } @@ -354,6 +362,9 @@ impl InlineAsmReg { Self::RiscV(r) => r.validate(arch, reloc_model, target_features, target, is_clobber), Self::PowerPC(r) => r.validate(arch, reloc_model, target_features, target, is_clobber), Self::Hexagon(r) => r.validate(arch, reloc_model, target_features, target, is_clobber), + Self::LoongArch(r) => { + r.validate(arch, reloc_model, target_features, target, is_clobber) + } Self::Mips(r) => r.validate(arch, reloc_model, target_features, target, is_clobber), Self::S390x(r) => r.validate(arch, reloc_model, target_features, target, is_clobber), Self::Bpf(r) => r.validate(arch, reloc_model, target_features, target, is_clobber), @@ -379,6 +390,7 @@ impl InlineAsmReg { Self::RiscV(r) => r.emit(out, arch, modifier), Self::PowerPC(r) => r.emit(out, arch, modifier), Self::Hexagon(r) => r.emit(out, arch, modifier), + Self::LoongArch(r) => r.emit(out, arch, modifier), Self::Mips(r) => r.emit(out, arch, modifier), Self::S390x(r) => r.emit(out, arch, modifier), Self::Bpf(r) => r.emit(out, arch, modifier), @@ -397,6 +409,7 @@ impl InlineAsmReg { Self::RiscV(_) => cb(self), Self::PowerPC(r) => r.overlapping_regs(|r| cb(Self::PowerPC(r))), Self::Hexagon(r) => r.overlapping_regs(|r| cb(Self::Hexagon(r))), + Self::LoongArch(_) => cb(self), Self::Mips(_) => cb(self), Self::S390x(_) => cb(self), Self::Bpf(r) => r.overlapping_regs(|r| cb(Self::Bpf(r))), @@ -418,6 +431,7 @@ pub enum InlineAsmRegClass { Nvptx(NvptxInlineAsmRegClass), PowerPC(PowerPCInlineAsmRegClass), Hexagon(HexagonInlineAsmRegClass), + LoongArch(LoongArchInlineAsmRegClass), Mips(MipsInlineAsmRegClass), S390x(S390xInlineAsmRegClass), SpirV(SpirVInlineAsmRegClass), @@ -440,6 +454,7 @@ impl InlineAsmRegClass { Self::Nvptx(r) => r.name(), Self::PowerPC(r) => r.name(), Self::Hexagon(r) => r.name(), + Self::LoongArch(r) => r.name(), Self::Mips(r) => r.name(), Self::S390x(r) => r.name(), Self::SpirV(r) => r.name(), @@ -464,6 +479,7 @@ impl InlineAsmRegClass { Self::Nvptx(r) => r.suggest_class(arch, ty).map(InlineAsmRegClass::Nvptx), Self::PowerPC(r) => r.suggest_class(arch, ty).map(InlineAsmRegClass::PowerPC), Self::Hexagon(r) => r.suggest_class(arch, ty).map(InlineAsmRegClass::Hexagon), + Self::LoongArch(r) => r.suggest_class(arch, ty).map(InlineAsmRegClass::LoongArch), Self::Mips(r) => r.suggest_class(arch, ty).map(InlineAsmRegClass::Mips), Self::S390x(r) => r.suggest_class(arch, ty).map(InlineAsmRegClass::S390x), Self::SpirV(r) => r.suggest_class(arch, ty).map(InlineAsmRegClass::SpirV), @@ -495,6 +511,7 @@ impl InlineAsmRegClass { Self::Nvptx(r) => r.suggest_modifier(arch, ty), Self::PowerPC(r) => r.suggest_modifier(arch, ty), Self::Hexagon(r) => r.suggest_modifier(arch, ty), + Self::LoongArch(r) => r.suggest_modifier(arch, ty), Self::Mips(r) => r.suggest_modifier(arch, ty), Self::S390x(r) => r.suggest_modifier(arch, ty), Self::SpirV(r) => r.suggest_modifier(arch, ty), @@ -522,6 +539,7 @@ impl InlineAsmRegClass { Self::Nvptx(r) => r.default_modifier(arch), Self::PowerPC(r) => r.default_modifier(arch), Self::Hexagon(r) => r.default_modifier(arch), + Self::LoongArch(r) => r.default_modifier(arch), Self::Mips(r) => r.default_modifier(arch), Self::S390x(r) => r.default_modifier(arch), Self::SpirV(r) => r.default_modifier(arch), @@ -548,6 +566,7 @@ impl InlineAsmRegClass { Self::Nvptx(r) => r.supported_types(arch), Self::PowerPC(r) => r.supported_types(arch), Self::Hexagon(r) => r.supported_types(arch), + Self::LoongArch(r) => r.supported_types(arch), Self::Mips(r) => r.supported_types(arch), Self::S390x(r) => r.supported_types(arch), Self::SpirV(r) => r.supported_types(arch), @@ -575,6 +594,7 @@ impl InlineAsmRegClass { Self::PowerPC(PowerPCInlineAsmRegClass::parse(name)?) } InlineAsmArch::Hexagon => Self::Hexagon(HexagonInlineAsmRegClass::parse(name)?), + InlineAsmArch::LoongArch64 => Self::LoongArch(LoongArchInlineAsmRegClass::parse(name)?), InlineAsmArch::Mips | InlineAsmArch::Mips64 => { Self::Mips(MipsInlineAsmRegClass::parse(name)?) } @@ -601,6 +621,7 @@ impl InlineAsmRegClass { Self::Nvptx(r) => r.valid_modifiers(arch), Self::PowerPC(r) => r.valid_modifiers(arch), Self::Hexagon(r) => r.valid_modifiers(arch), + Self::LoongArch(r) => r.valid_modifiers(arch), Self::Mips(r) => r.valid_modifiers(arch), Self::S390x(r) => r.valid_modifiers(arch), Self::SpirV(r) => r.valid_modifiers(arch), @@ -760,6 +781,11 @@ pub fn allocatable_registers( hexagon::fill_reg_map(arch, reloc_model, target_features, target, &mut map); map } + InlineAsmArch::LoongArch64 => { + let mut map = loongarch::regclass_map(); + loongarch::fill_reg_map(arch, reloc_model, target_features, target, &mut map); + map + } InlineAsmArch::Mips | InlineAsmArch::Mips64 => { let mut map = mips::regclass_map(); mips::fill_reg_map(arch, reloc_model, target_features, target, &mut map); diff --git a/compiler/rustc_trait_selection/src/infer.rs b/compiler/rustc_trait_selection/src/infer.rs index 911cc0b88c406..fcf86da08f469 100644 --- a/compiler/rustc_trait_selection/src/infer.rs +++ b/compiler/rustc_trait_selection/src/infer.rs @@ -41,7 +41,7 @@ impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> { fn type_is_copy_modulo_regions(&self, param_env: ty::ParamEnv<'tcx>, ty: Ty<'tcx>) -> bool { let ty = self.resolve_vars_if_possible(ty); - if !(param_env, ty).needs_infer() { + if !(param_env, ty).has_infer() { return ty.is_copy_modulo_regions(self.tcx, param_env); } diff --git a/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs b/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs index 1a566e87dc8e3..996dc329dcb9b 100644 --- a/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs +++ b/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs @@ -91,14 +91,15 @@ pub(in crate::solve) fn replace_erased_lifetimes_with_bound_vars<'tcx>( ) -> ty::Binder<'tcx, Ty<'tcx>> { debug_assert!(!ty.has_late_bound_regions()); let mut counter = 0; - let ty = tcx.fold_regions(ty, |mut r, current_depth| { - if let ty::ReErased = r.kind() { + let ty = tcx.fold_regions(ty, |r, current_depth| match r.kind() { + ty::ReErased => { let br = ty::BoundRegion { var: ty::BoundVar::from_u32(counter), kind: ty::BrAnon(None) }; counter += 1; - r = tcx.mk_re_late_bound(current_depth, br); + tcx.mk_re_late_bound(current_depth, br) } - r + // All free regions should be erased here. + r => bug!("unexpected region: {r:?}"), }); let bound_vars = tcx.mk_bound_variable_kinds_from_iter( (0..counter).map(|_| ty::BoundVariableKind::Region(ty::BrAnon(None))), diff --git a/compiler/rustc_trait_selection/src/solve/canonicalize.rs b/compiler/rustc_trait_selection/src/solve/canonicalize.rs index 976849696e33a..ff4bff10cc8a3 100644 --- a/compiler/rustc_trait_selection/src/solve/canonicalize.rs +++ b/compiler/rustc_trait_selection/src/solve/canonicalize.rs @@ -69,7 +69,7 @@ impl<'a, 'tcx> Canonicalizer<'a, 'tcx> { }; let value = value.fold_with(&mut canonicalizer); - assert!(!value.needs_infer()); + assert!(!value.has_infer()); assert!(!value.has_placeholders()); let (max_universe, variables) = canonicalizer.finalize(); diff --git a/compiler/rustc_trait_selection/src/solve/trait_goals.rs b/compiler/rustc_trait_selection/src/solve/trait_goals.rs index 8e7097ce4a779..c97473e6241f2 100644 --- a/compiler/rustc_trait_selection/src/solve/trait_goals.rs +++ b/compiler/rustc_trait_selection/src/solve/trait_goals.rs @@ -86,8 +86,9 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> { ) -> QueryResult<'tcx> { if let Some(poly_trait_pred) = assumption.to_opt_poly_trait_pred() && poly_trait_pred.def_id() == goal.predicate.def_id() + && poly_trait_pred.polarity() == goal.predicate.polarity { - // FIXME: Constness and polarity + // FIXME: Constness ecx.probe(|ecx| { let assumption_trait_pred = ecx.instantiate_binder_with_infer(poly_trait_pred); @@ -111,6 +112,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> { ) -> QueryResult<'tcx> { if let Some(poly_trait_pred) = assumption.to_opt_poly_trait_pred() && poly_trait_pred.def_id() == goal.predicate.def_id() + && poly_trait_pred.polarity() == goal.predicate.polarity { // FIXME: Constness and polarity ecx.probe(|ecx| { @@ -147,6 +149,10 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> { ecx: &mut EvalCtxt<'_, 'tcx>, goal: Goal<'tcx, Self>, ) -> QueryResult<'tcx> { + if goal.predicate.polarity != ty::ImplPolarity::Positive { + return Err(NoSolution); + } + if let Some(result) = ecx.disqualify_auto_trait_candidate_due_to_possible_impl(goal) { return result; } @@ -161,6 +167,10 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> { ecx: &mut EvalCtxt<'_, 'tcx>, goal: Goal<'tcx, Self>, ) -> QueryResult<'tcx> { + if goal.predicate.polarity != ty::ImplPolarity::Positive { + return Err(NoSolution); + } + let tcx = ecx.tcx(); ecx.probe(|ecx| { @@ -176,6 +186,10 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> { ecx: &mut EvalCtxt<'_, 'tcx>, goal: Goal<'tcx, Self>, ) -> QueryResult<'tcx> { + if goal.predicate.polarity != ty::ImplPolarity::Positive { + return Err(NoSolution); + } + ecx.probe_and_evaluate_goal_for_constituent_tys( goal, structural_traits::instantiate_constituent_tys_for_sized_trait, @@ -186,6 +200,10 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> { ecx: &mut EvalCtxt<'_, 'tcx>, goal: Goal<'tcx, Self>, ) -> QueryResult<'tcx> { + if goal.predicate.polarity != ty::ImplPolarity::Positive { + return Err(NoSolution); + } + ecx.probe_and_evaluate_goal_for_constituent_tys( goal, structural_traits::instantiate_constituent_tys_for_copy_clone_trait, @@ -196,6 +214,10 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> { ecx: &mut EvalCtxt<'_, 'tcx>, goal: Goal<'tcx, Self>, ) -> QueryResult<'tcx> { + if goal.predicate.polarity != ty::ImplPolarity::Positive { + return Err(NoSolution); + } + if goal.predicate.self_ty().has_non_region_infer() { return ecx.evaluate_added_goals_and_make_canonical_response(Certainty::AMBIGUOUS); } @@ -217,6 +239,10 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> { ecx: &mut EvalCtxt<'_, 'tcx>, goal: Goal<'tcx, Self>, ) -> QueryResult<'tcx> { + if goal.predicate.polarity != ty::ImplPolarity::Positive { + return Err(NoSolution); + } + if let ty::FnPtr(..) = goal.predicate.self_ty().kind() { ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) } else { @@ -229,6 +255,10 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> { goal: Goal<'tcx, Self>, goal_kind: ty::ClosureKind, ) -> QueryResult<'tcx> { + if goal.predicate.polarity != ty::ImplPolarity::Positive { + return Err(NoSolution); + } + let tcx = ecx.tcx(); let tupled_inputs_and_output = match structural_traits::extract_tupled_inputs_and_output_from_callable( @@ -259,6 +289,10 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> { ecx: &mut EvalCtxt<'_, 'tcx>, goal: Goal<'tcx, Self>, ) -> QueryResult<'tcx> { + if goal.predicate.polarity != ty::ImplPolarity::Positive { + return Err(NoSolution); + } + if let ty::Tuple(..) = goal.predicate.self_ty().kind() { ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) } else { @@ -268,8 +302,12 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> { fn consider_builtin_pointee_candidate( ecx: &mut EvalCtxt<'_, 'tcx>, - _goal: Goal<'tcx, Self>, + goal: Goal<'tcx, Self>, ) -> QueryResult<'tcx> { + if goal.predicate.polarity != ty::ImplPolarity::Positive { + return Err(NoSolution); + } + ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) } @@ -277,6 +315,10 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> { ecx: &mut EvalCtxt<'_, 'tcx>, goal: Goal<'tcx, Self>, ) -> QueryResult<'tcx> { + if goal.predicate.polarity != ty::ImplPolarity::Positive { + return Err(NoSolution); + } + let ty::Generator(def_id, _, _) = *goal.predicate.self_ty().kind() else { return Err(NoSolution); }; @@ -297,6 +339,10 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> { ecx: &mut EvalCtxt<'_, 'tcx>, goal: Goal<'tcx, Self>, ) -> QueryResult<'tcx> { + if goal.predicate.polarity != ty::ImplPolarity::Positive { + return Err(NoSolution); + } + let self_ty = goal.predicate.self_ty(); let ty::Generator(def_id, substs, _) = *self_ty.kind() else { return Err(NoSolution); @@ -326,6 +372,10 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> { 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.substs.type_at(1); @@ -447,6 +497,10 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> { ecx: &mut EvalCtxt<'_, 'tcx>, goal: Goal<'tcx, Self>, ) -> Vec> { + if goal.predicate.polarity != ty::ImplPolarity::Positive { + return vec![]; + } + let tcx = ecx.tcx(); let a_ty = goal.predicate.self_ty(); @@ -521,8 +575,12 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> { fn consider_builtin_discriminant_kind_candidate( ecx: &mut EvalCtxt<'_, 'tcx>, - _goal: Goal<'tcx, Self>, + goal: Goal<'tcx, Self>, ) -> QueryResult<'tcx> { + if goal.predicate.polarity != ty::ImplPolarity::Positive { + return Err(NoSolution); + } + // `DiscriminantKind` is automatically implemented for every type. ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) } @@ -531,6 +589,10 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> { ecx: &mut EvalCtxt<'_, 'tcx>, goal: Goal<'tcx, Self>, ) -> QueryResult<'tcx> { + if goal.predicate.polarity != ty::ImplPolarity::Positive { + return Err(NoSolution); + } + if !goal.param_env.is_const() { // `Destruct` is automatically implemented for every type in // non-const environments. @@ -545,6 +607,10 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> { ecx: &mut EvalCtxt<'_, 'tcx>, goal: Goal<'tcx, Self>, ) -> QueryResult<'tcx> { + if goal.predicate.polarity != ty::ImplPolarity::Positive { + return Err(NoSolution); + } + // `rustc_transmute` does not have support for type or const params if goal.has_non_region_placeholders() { return Err(NoSolution); diff --git a/compiler/rustc_trait_selection/src/traits/coherence.rs b/compiler/rustc_trait_selection/src/traits/coherence.rs index 20c2605f219a7..b7690f79933d9 100644 --- a/compiler/rustc_trait_selection/src/traits/coherence.rs +++ b/compiler/rustc_trait_selection/src/traits/coherence.rs @@ -582,7 +582,7 @@ fn orphan_check_trait_ref<'tcx>( trait_ref: ty::TraitRef<'tcx>, in_crate: InCrate, ) -> Result<(), OrphanCheckErr<'tcx>> { - if trait_ref.needs_infer() && trait_ref.needs_subst() { + if trait_ref.has_infer() && trait_ref.has_param() { bug!( "can't orphan check a trait ref with both params and inference variables {:?}", trait_ref diff --git a/compiler/rustc_trait_selection/src/traits/mod.rs b/compiler/rustc_trait_selection/src/traits/mod.rs index 4c9df5d9d0a26..0e8c74a6765ce 100644 --- a/compiler/rustc_trait_selection/src/traits/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/mod.rs @@ -414,7 +414,7 @@ fn subst_and_check_impossible_predicates<'tcx>( predicates.push(ty::Binder::dummy(trait_ref).to_predicate(tcx)); } - predicates.retain(|predicate| !predicate.needs_subst()); + predicates.retain(|predicate| !predicate.has_param()); let result = impossible_predicates(tcx, predicates); debug!("subst_and_check_impossible_predicates(key={:?}) = {:?}", key, result); diff --git a/compiler/rustc_trait_selection/src/traits/object_safety.rs b/compiler/rustc_trait_selection/src/traits/object_safety.rs index b8ad1925e4eaa..73e2efc3b000e 100644 --- a/compiler/rustc_trait_selection/src/traits/object_safety.rs +++ b/compiler/rustc_trait_selection/src/traits/object_safety.rs @@ -297,8 +297,8 @@ fn bounds_reference_self(tcx: TyCtxt<'_>, trait_def_id: DefId) -> SmallVec<[Span tcx.associated_items(trait_def_id) .in_definition_order() .filter(|item| item.kind == ty::AssocKind::Type) - .flat_map(|item| tcx.explicit_item_bounds(item.def_id)) - .filter_map(|pred_span| predicate_references_self(tcx, *pred_span)) + .flat_map(|item| tcx.explicit_item_bounds(item.def_id).subst_identity_iter_copied()) + .filter_map(|pred_span| predicate_references_self(tcx, pred_span)) .collect() } diff --git a/compiler/rustc_trait_selection/src/traits/outlives_bounds.rs b/compiler/rustc_trait_selection/src/traits/outlives_bounds.rs index e01a57ea4fee8..0db8023289127 100644 --- a/compiler/rustc_trait_selection/src/traits/outlives_bounds.rs +++ b/compiler/rustc_trait_selection/src/traits/outlives_bounds.rs @@ -60,7 +60,7 @@ impl<'a, 'tcx: 'a> InferCtxtExt<'a, 'tcx> for InferCtxt<'tcx> { // We may however encounter unconstrained lifetime variables in invalid // code. See #110161 for context. assert!(!ty.has_non_region_infer()); - if ty.needs_infer() { + if ty.has_infer() { self.tcx.sess.delay_span_bug( self.tcx.def_span(body_id), "skipped implied_outlives_bounds due to unconstrained lifetimes", diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index 081e4d7cfa47d..863553670dee2 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -449,7 +449,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { debug!(?stack, ?candidates, "winnowed to {} candidates", candidates.len()); - let needs_infer = stack.obligation.predicate.has_non_region_infer(); + let has_non_region_infer = stack.obligation.predicate.has_non_region_infer(); // If there are STILL multiple candidates, we can further // reduce the list by dropping duplicates -- including @@ -461,7 +461,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { self.candidate_should_be_dropped_in_favor_of( &candidates[i], &candidates[j], - needs_infer, + has_non_region_infer, ) == DropVictim::Yes }); if should_drop_i { @@ -1000,7 +1000,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { ) -> Result { if !self.is_intercrate() && obligation.is_global() - && obligation.param_env.caller_bounds().iter().all(|bound| bound.needs_subst()) + && obligation.param_env.caller_bounds().iter().all(|bound| bound.has_param()) { // If a param env has no global bounds, global obligations do not // depend on its particular value in order to work, so we can clear @@ -1330,7 +1330,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { } if self.can_use_global_caches(param_env) { - if !trait_pred.needs_infer() { + if !trait_pred.has_infer() { debug!(?trait_pred, ?result, "insert_evaluation_cache global"); // This may overwrite the cache with the same value // FIXME: Due to #50507 this overwrites the different values @@ -1516,7 +1516,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // If there are any inference variables in the `ParamEnv`, then we // always use a cache local to this particular scope. Otherwise, we // switch to a global cache. - if param_env.needs_infer() { + if param_env.has_infer() { return false; } @@ -1587,7 +1587,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { return false; } match result { - Ok(Some(SelectionCandidate::ParamCandidate(trait_ref))) => !trait_ref.needs_infer(), + Ok(Some(SelectionCandidate::ParamCandidate(trait_ref))) => !trait_ref.has_infer(), _ => true, } } @@ -1613,8 +1613,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { if self.can_use_global_caches(param_env) { if let Err(Overflow(OverflowError::Canonical)) = candidate { // Don't cache overflow globally; we only produce this in certain modes. - } else if !pred.needs_infer() { - if !candidate.needs_infer() { + } else if !pred.has_infer() { + if !candidate.has_infer() { debug!(?pred, ?candidate, "insert_candidate_cache global"); // This may overwrite the cache with the same value. tcx.selection_cache.insert((param_env, pred), dep_node, candidate); @@ -1724,7 +1724,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { .map(|InferOk { obligations: _, value: () }| { // This method is called within a probe, so we can't have // inference variables and placeholders escape. - if !trait_bound.needs_infer() && !trait_bound.has_placeholders() { + if !trait_bound.has_infer() && !trait_bound.has_placeholders() { Some(trait_bound) } else { None @@ -1840,7 +1840,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> { &mut self, victim: &EvaluatedCandidate<'tcx>, other: &EvaluatedCandidate<'tcx>, - needs_infer: bool, + has_non_region_infer: bool, ) -> DropVictim { if victim.candidate == other.candidate { return DropVictim::Yes; @@ -1956,7 +1956,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> { | (ObjectCandidate(i), ObjectCandidate(j)) => { // Arbitrarily pick the lower numbered candidate for backwards // compatibility reasons. Don't let this affect inference. - DropVictim::drop_if(i < j && !needs_infer) + DropVictim::drop_if(i < j && !has_non_region_infer) } (ObjectCandidate(_), ProjectionCandidate(..)) | (ProjectionCandidate(..), ObjectCandidate(_)) => { @@ -2062,7 +2062,8 @@ impl<'tcx> SelectionContext<'_, 'tcx> { // existence of multiple marker trait impls tells us nothing // about which one should actually apply. DropVictim::drop_if( - !needs_infer && other.evaluation.must_apply_considering_regions(), + !has_non_region_infer + && other.evaluation.must_apply_considering_regions(), ) } None => DropVictim::No, @@ -3006,16 +3007,16 @@ fn bind_generator_hidden_types_above<'tcx>( // Only remap erased regions if we use them. if considering_regions { - ty = tcx.fold_regions(ty, |mut r, current_depth| { - if let ty::ReErased = r.kind() { + ty = tcx.fold_regions(ty, |r, current_depth| match r.kind() { + ty::ReErased => { let br = ty::BoundRegion { var: ty::BoundVar::from_u32(counter), kind: ty::BrAnon(None), }; counter += 1; - r = tcx.mk_re_late_bound(current_depth, br); + tcx.mk_re_late_bound(current_depth, br) } - r + r => bug!("unexpected region: {r:?}"), }) } diff --git a/compiler/rustc_trait_selection/src/traits/vtable.rs b/compiler/rustc_trait_selection/src/traits/vtable.rs index a4e9928f8b2cf..c56e7c7cadd81 100644 --- a/compiler/rustc_trait_selection/src/traits/vtable.rs +++ b/compiler/rustc_trait_selection/src/traits/vtable.rs @@ -353,8 +353,8 @@ pub(crate) fn vtable_trait_upcasting_coercion_new_vptr_slot<'tcx>( ), ) -> Option { let (source, target) = key; - assert!(matches!(&source.kind(), &ty::Dynamic(..)) && !source.needs_infer()); - assert!(matches!(&target.kind(), &ty::Dynamic(..)) && !target.needs_infer()); + assert!(matches!(&source.kind(), &ty::Dynamic(..)) && !source.has_infer()); + assert!(matches!(&target.kind(), &ty::Dynamic(..)) && !target.has_infer()); // this has been typecked-before, so diagnostics is not really needed. let unsize_trait_did = tcx.require_lang_item(LangItem::Unsize, None); diff --git a/compiler/rustc_traits/src/chalk/db.rs b/compiler/rustc_traits/src/chalk/db.rs index 9683e48478edc..c319b2e31c7e6 100644 --- a/compiler/rustc_traits/src/chalk/db.rs +++ b/compiler/rustc_traits/src/chalk/db.rs @@ -50,12 +50,11 @@ impl<'tcx> RustIrDatabase<'tcx> { where ty::Predicate<'tcx>: LowerInto<'tcx, std::option::Option>, { - let bounds = self.interner.tcx.bound_explicit_item_bounds(def_id); - bounds - .0 - .iter() - .map(|(bound, _)| bounds.rebind(*bound).subst(self.interner.tcx, &bound_vars)) - .filter_map(|bound| LowerInto::>::lower_into(bound, self.interner)) + self.interner + .tcx + .explicit_item_bounds(def_id) + .subst_iter_copied(self.interner.tcx, &bound_vars) + .filter_map(|(bound, _)| LowerInto::>::lower_into(bound, self.interner)) .collect() } } @@ -506,15 +505,11 @@ impl<'tcx> chalk_solve::RustIrDatabase> for RustIrDatabase<'t let identity_substs = InternalSubsts::identity_for_item(self.interner.tcx, opaque_ty_id.0); - let explicit_item_bounds = self.interner.tcx.bound_explicit_item_bounds(opaque_ty_id.0); + let explicit_item_bounds = self.interner.tcx.explicit_item_bounds(opaque_ty_id.0); let bounds = explicit_item_bounds - .0 - .iter() + .subst_iter_copied(self.interner.tcx, &bound_vars) .map(|(bound, _)| { - explicit_item_bounds.rebind(*bound).subst(self.interner.tcx, &bound_vars) - }) - .map(|bound| { bound.fold_with(&mut ReplaceOpaqueTyFolder { tcx: self.interner.tcx, opaque_ty_id, diff --git a/compiler/rustc_traits/src/normalize_erasing_regions.rs b/compiler/rustc_traits/src/normalize_erasing_regions.rs index 126a494f34fd6..5da0f16c2bf05 100644 --- a/compiler/rustc_traits/src/normalize_erasing_regions.rs +++ b/compiler/rustc_traits/src/normalize_erasing_regions.rs @@ -47,7 +47,7 @@ fn try_normalize_after_erasing_regions<'tcx, T: TypeFoldable> + Par // us a test case. debug_assert_eq!(normalized_value, resolved_value); let erased = infcx.tcx.erase_regions(resolved_value); - debug_assert!(!erased.needs_infer(), "{erased:?}"); + debug_assert!(!erased.has_infer(), "{erased:?}"); Ok(erased) } Err(NoSolution) => Err(NoSolution), diff --git a/compiler/rustc_ty_utils/src/instance.rs b/compiler/rustc_ty_utils/src/instance.rs index 21cc3c9517e9d..64586a6782b18 100644 --- a/compiler/rustc_ty_utils/src/instance.rs +++ b/compiler/rustc_ty_utils/src/instance.rs @@ -104,8 +104,8 @@ fn resolve_associated_item<'tcx>( "resolving ImplSource::UserDefined: {:?}, {:?}, {:?}, {:?}", param_env, trait_item_id, rcvr_substs, impl_data ); - assert!(!rcvr_substs.needs_infer()); - assert!(!trait_ref.needs_infer()); + assert!(!rcvr_substs.has_infer()); + assert!(!trait_ref.has_infer()); let trait_def_id = tcx.trait_id_of_impl(impl_data.impl_def_id).unwrap(); let trait_def = tcx.trait_def(trait_def_id); diff --git a/compiler/rustc_type_ir/src/codec.rs b/compiler/rustc_type_ir/src/codec.rs index ee249050cc64e..3b638934629b5 100644 --- a/compiler/rustc_type_ir/src/codec.rs +++ b/compiler/rustc_type_ir/src/codec.rs @@ -27,10 +27,13 @@ pub trait TyEncoder: Encoder { const CLEAR_CROSS_CRATE: bool; fn position(&self) -> usize; + fn type_shorthands(&mut self) -> &mut FxHashMap<::Ty, usize>; + fn predicate_shorthands( &mut self, ) -> &mut FxHashMap<::PredicateKind, usize>; + fn encode_alloc_id(&mut self, alloc_id: &::AllocId); } @@ -40,10 +43,6 @@ pub trait TyDecoder: Decoder { fn interner(&self) -> Self::I; - fn peek_byte(&self) -> u8; - - fn position(&self) -> usize; - fn cached_ty_for_shorthand( &mut self, shorthand: usize, diff --git a/compiler/rustc_type_ir/src/lib.rs b/compiler/rustc_type_ir/src/lib.rs index a3c98ae007ede..1e91e26e2afe9 100644 --- a/compiler/rustc_type_ir/src/lib.rs +++ b/compiler/rustc_type_ir/src/lib.rs @@ -179,7 +179,7 @@ bitflags! { /// Does this have `ConstKind::Param`? const HAS_CT_PARAM = 1 << 2; - const NEEDS_SUBST = TypeFlags::HAS_TY_PARAM.bits + const HAS_PARAM = TypeFlags::HAS_TY_PARAM.bits | TypeFlags::HAS_RE_PARAM.bits | TypeFlags::HAS_CT_PARAM.bits; @@ -192,7 +192,7 @@ bitflags! { /// Does this have inference variables? Used to determine whether /// inference is required. - const NEEDS_INFER = TypeFlags::HAS_TY_INFER.bits + const HAS_INFER = TypeFlags::HAS_TY_INFER.bits | TypeFlags::HAS_RE_INFER.bits | TypeFlags::HAS_CT_INFER.bits; @@ -537,7 +537,7 @@ pub struct FloatVarValue(pub FloatTy); rustc_index::newtype_index! { /// A **ty**pe **v**ariable **ID**. - #[debug_format = "_#{}t"] + #[debug_format = "?{}t"] pub struct TyVid {} } @@ -739,13 +739,13 @@ impl fmt::Debug for FloatVarValue { impl fmt::Debug for IntVid { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "_#{}i", self.index) + write!(f, "?{}i", self.index) } } impl fmt::Debug for FloatVid { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "_#{}f", self.index) + write!(f, "?{}f", self.index) } } diff --git a/library/alloc/src/collections/linked_list.rs b/library/alloc/src/collections/linked_list.rs index 1743a155c5abf..0cb7e82beb057 100644 --- a/library/alloc/src/collections/linked_list.rs +++ b/library/alloc/src/collections/linked_list.rs @@ -18,9 +18,10 @@ use core::hash::{Hash, Hasher}; use core::iter::FusedIterator; use core::marker::PhantomData; use core::mem; -use core::ptr::NonNull; +use core::ptr::{NonNull, Unique}; use super::SpecExtend; +use crate::alloc::{Allocator, Global}; use crate::boxed::Box; #[cfg(test)] @@ -47,11 +48,15 @@ mod tests; #[stable(feature = "rust1", since = "1.0.0")] #[cfg_attr(not(test), rustc_diagnostic_item = "LinkedList")] #[rustc_insignificant_dtor] -pub struct LinkedList { +pub struct LinkedList< + T, + #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global, +> { head: Option>>, tail: Option>>, len: usize, - marker: PhantomData>>, + alloc: A, + marker: PhantomData, A>>, } struct Node { @@ -81,6 +86,7 @@ impl fmt::Debug for Iter<'_, T> { head: self.head, tail: self.tail, len: self.len, + alloc: Global, marker: PhantomData, })) .field(&self.len) @@ -117,6 +123,7 @@ impl fmt::Debug for IterMut<'_, T> { head: self.head, tail: self.tail, len: self.len, + alloc: Global, marker: PhantomData, })) .field(&self.len) @@ -132,12 +139,15 @@ impl fmt::Debug for IterMut<'_, T> { /// [`into_iter`]: LinkedList::into_iter #[derive(Clone)] #[stable(feature = "rust1", since = "1.0.0")] -pub struct IntoIter { - list: LinkedList, +pub struct IntoIter< + T, + #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global, +> { + list: LinkedList, } #[stable(feature = "collection_debug", since = "1.17.0")] -impl fmt::Debug for IntoIter { +impl fmt::Debug for IntoIter { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_tuple("IntoIter").field(&self.list).finish() } @@ -148,22 +158,25 @@ impl Node { Node { next: None, prev: None, element } } - fn into_element(self: Box) -> T { + fn into_element(self: Box) -> T { self.element } } // private methods -impl LinkedList { +impl LinkedList { /// Adds the given node to the front of the list. + /// + /// # Safety + /// `node` must point to a valid node that was boxed using the list's allocator. #[inline] - fn push_front_node(&mut self, mut node: Box>) { + unsafe fn push_front_node(&mut self, node: Unique>) { // This method takes care not to create mutable references to whole nodes, // to maintain validity of aliasing pointers into `element`. unsafe { - node.next = self.head; - node.prev = None; - let node = Some(Box::leak(node).into()); + (*node.as_ptr()).next = self.head; + (*node.as_ptr()).prev = None; + let node = Some(NonNull::from(node)); match self.head { None => self.tail = node, @@ -178,11 +191,11 @@ impl LinkedList { /// Removes and returns the node at the front of the list. #[inline] - fn pop_front_node(&mut self) -> Option>> { + fn pop_front_node(&mut self) -> Option, &A>> { // This method takes care not to create mutable references to whole nodes, // to maintain validity of aliasing pointers into `element`. self.head.map(|node| unsafe { - let node = Box::from_raw(node.as_ptr()); + let node = Box::from_raw_in(node.as_ptr(), &self.alloc); self.head = node.next; match self.head { @@ -197,14 +210,17 @@ impl LinkedList { } /// Adds the given node to the back of the list. + /// + /// # Safety + /// `node` must point to a valid node that was boxed using the list's allocator. #[inline] - fn push_back_node(&mut self, mut node: Box>) { + unsafe fn push_back_node(&mut self, node: Unique>) { // This method takes care not to create mutable references to whole nodes, // to maintain validity of aliasing pointers into `element`. unsafe { - node.next = None; - node.prev = self.tail; - let node = Some(Box::leak(node).into()); + (*node.as_ptr()).next = None; + (*node.as_ptr()).prev = self.tail; + let node = Some(NonNull::from(node)); match self.tail { None => self.head = node, @@ -219,11 +235,11 @@ impl LinkedList { /// Removes and returns the node at the back of the list. #[inline] - fn pop_back_node(&mut self) -> Option>> { + fn pop_back_node(&mut self) -> Option, &A>> { // This method takes care not to create mutable references to whole nodes, // to maintain validity of aliasing pointers into `element`. self.tail.map(|node| unsafe { - let node = Box::from_raw(node.as_ptr()); + let node = Box::from_raw_in(node.as_ptr(), &self.alloc); self.tail = node.prev; match self.tail { @@ -321,7 +337,10 @@ impl LinkedList { &mut self, split_node: Option>>, at: usize, - ) -> Self { + ) -> Self + where + A: Clone, + { // The split node is the new head node of the second part if let Some(mut split_node) = split_node { let first_part_head; @@ -342,6 +361,7 @@ impl LinkedList { head: first_part_head, tail: first_part_tail, len: at, + alloc: self.alloc.clone(), marker: PhantomData, }; @@ -351,7 +371,7 @@ impl LinkedList { first_part } else { - mem::replace(self, LinkedList::new()) + mem::replace(self, LinkedList::new_in(self.alloc.clone())) } } @@ -360,7 +380,10 @@ impl LinkedList { &mut self, split_node: Option>>, at: usize, - ) -> Self { + ) -> Self + where + A: Clone, + { // The split node is the new tail node of the first part and owns // the head of the second part. if let Some(mut split_node) = split_node { @@ -382,6 +405,7 @@ impl LinkedList { head: second_part_head, tail: second_part_tail, len: self.len - at, + alloc: self.alloc.clone(), marker: PhantomData, }; @@ -391,7 +415,7 @@ impl LinkedList { second_part } else { - mem::replace(self, LinkedList::new()) + mem::replace(self, LinkedList::new_in(self.alloc.clone())) } } } @@ -420,7 +444,7 @@ impl LinkedList { #[stable(feature = "rust1", since = "1.0.0")] #[must_use] pub const fn new() -> Self { - LinkedList { head: None, tail: None, len: 0, marker: PhantomData } + LinkedList { head: None, tail: None, len: 0, alloc: Global, marker: PhantomData } } /// Moves all elements from `other` to the end of the list. @@ -471,7 +495,26 @@ impl LinkedList { } } } +} +impl LinkedList { + /// Constructs an empty `LinkedList`. + /// + /// # Examples + /// + /// ``` + /// #![feature(allocator_api)] + /// + /// use std::alloc::System; + /// use std::collections::LinkedList; + /// + /// let list: LinkedList = LinkedList::new_in(System); + /// ``` + #[inline] + #[unstable(feature = "allocator_api", issue = "32838")] + pub const fn new_in(alloc: A) -> Self { + LinkedList { head: None, tail: None, len: 0, alloc, marker: PhantomData } + } /// Provides a forward iterator. /// /// # Examples @@ -532,7 +575,7 @@ impl LinkedList { #[inline] #[must_use] #[unstable(feature = "linked_list_cursors", issue = "58533")] - pub fn cursor_front(&self) -> Cursor<'_, T> { + pub fn cursor_front(&self) -> Cursor<'_, T, A> { Cursor { index: 0, current: self.head, list: self } } @@ -542,7 +585,7 @@ impl LinkedList { #[inline] #[must_use] #[unstable(feature = "linked_list_cursors", issue = "58533")] - pub fn cursor_front_mut(&mut self) -> CursorMut<'_, T> { + pub fn cursor_front_mut(&mut self) -> CursorMut<'_, T, A> { CursorMut { index: 0, current: self.head, list: self } } @@ -552,7 +595,7 @@ impl LinkedList { #[inline] #[must_use] #[unstable(feature = "linked_list_cursors", issue = "58533")] - pub fn cursor_back(&self) -> Cursor<'_, T> { + pub fn cursor_back(&self) -> Cursor<'_, T, A> { Cursor { index: self.len.checked_sub(1).unwrap_or(0), current: self.tail, list: self } } @@ -562,7 +605,7 @@ impl LinkedList { #[inline] #[must_use] #[unstable(feature = "linked_list_cursors", issue = "58533")] - pub fn cursor_back_mut(&mut self) -> CursorMut<'_, T> { + pub fn cursor_back_mut(&mut self) -> CursorMut<'_, T, A> { CursorMut { index: self.len.checked_sub(1).unwrap_or(0), current: self.tail, list: self } } @@ -638,7 +681,15 @@ impl LinkedList { #[inline] #[stable(feature = "rust1", since = "1.0.0")] pub fn clear(&mut self) { - *self = Self::new(); + // We need to drop the nodes while keeping self.alloc + // We can do this by moving (head, tail, len) into a new list that borrows self.alloc + drop(LinkedList { + head: self.head.take(), + tail: self.tail.take(), + len: mem::take(&mut self.len), + alloc: &self.alloc, + marker: PhantomData, + }); } /// Returns `true` if the `LinkedList` contains an element equal to the @@ -790,7 +841,12 @@ impl LinkedList { /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn push_front(&mut self, elt: T) { - self.push_front_node(Box::new(Node::new(elt))); + let node = Box::new_in(Node::new(elt), &self.alloc); + let node_ptr = Unique::from(Box::leak(node)); + // SAFETY: node_ptr is a unique pointer to a node we boxed with self.alloc + unsafe { + self.push_front_node(node_ptr); + } } /// Removes the first element and returns it, or `None` if the list is @@ -833,7 +889,12 @@ impl LinkedList { /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn push_back(&mut self, elt: T) { - self.push_back_node(Box::new(Node::new(elt))); + let node = Box::new_in(Node::new(elt), &self.alloc); + let node_ptr = Unique::from(Box::leak(node)); + // SAFETY: node_ptr is a unique pointer to a node we boxed with self.alloc + unsafe { + self.push_back_node(node_ptr); + } } /// Removes the last element from a list and returns it, or `None` if @@ -883,13 +944,16 @@ impl LinkedList { /// assert_eq!(split.pop_front(), None); /// ``` #[stable(feature = "rust1", since = "1.0.0")] - pub fn split_off(&mut self, at: usize) -> LinkedList { + pub fn split_off(&mut self, at: usize) -> LinkedList + where + A: Clone, + { let len = self.len(); assert!(at <= len, "Cannot split off at a nonexistent index"); if at == 0 { - return mem::take(self); + return mem::replace(self, Self::new_in(self.alloc.clone())); } else if at == len { - return Self::new(); + return Self::new_in(self.alloc.clone()); } // Below, we iterate towards the `i-1`th node, either from the start or the end, @@ -987,7 +1051,7 @@ impl LinkedList { /// assert_eq!(odds.into_iter().collect::>(), vec![1, 3, 5, 9, 11, 13, 15]); /// ``` #[unstable(feature = "drain_filter", reason = "recently added", issue = "43244")] - pub fn drain_filter(&mut self, filter: F) -> DrainFilter<'_, T, F> + pub fn drain_filter(&mut self, filter: F) -> DrainFilter<'_, T, F, A> where F: FnMut(&mut T) -> bool, { @@ -1000,11 +1064,11 @@ impl LinkedList { } #[stable(feature = "rust1", since = "1.0.0")] -unsafe impl<#[may_dangle] T> Drop for LinkedList { +unsafe impl<#[may_dangle] T, A: Allocator> Drop for LinkedList { fn drop(&mut self) { - struct DropGuard<'a, T>(&'a mut LinkedList); + struct DropGuard<'a, T, A: Allocator>(&'a mut LinkedList); - impl<'a, T> Drop for DropGuard<'a, T> { + impl<'a, T, A: Allocator> Drop for DropGuard<'a, T, A> { fn drop(&mut self) { // Continue the same loop we do below. This only runs when a destructor has // panicked. If another one panics this will abort. @@ -1012,11 +1076,10 @@ unsafe impl<#[may_dangle] T> Drop for LinkedList { } } - while let Some(node) = self.pop_front_node() { - let guard = DropGuard(self); - drop(node); - mem::forget(guard); - } + // Wrap self so that if a destructor panics, we can try to keep looping + let guard = DropGuard(self); + while guard.0.pop_front_node().is_some() {} + mem::forget(guard); } } @@ -1159,14 +1222,18 @@ impl Default for IterMut<'_, T> { /// /// When created, cursors start at the front of the list, or the "ghost" non-element if the list is empty. #[unstable(feature = "linked_list_cursors", issue = "58533")] -pub struct Cursor<'a, T: 'a> { +pub struct Cursor< + 'a, + T: 'a, + #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global, +> { index: usize, current: Option>>, - list: &'a LinkedList, + list: &'a LinkedList, } #[unstable(feature = "linked_list_cursors", issue = "58533")] -impl Clone for Cursor<'_, T> { +impl Clone for Cursor<'_, T, A> { fn clone(&self) -> Self { let Cursor { index, current, list } = *self; Cursor { index, current, list } @@ -1174,7 +1241,7 @@ impl Clone for Cursor<'_, T> { } #[unstable(feature = "linked_list_cursors", issue = "58533")] -impl fmt::Debug for Cursor<'_, T> { +impl fmt::Debug for Cursor<'_, T, A> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_tuple("Cursor").field(&self.list).field(&self.index()).finish() } @@ -1191,20 +1258,24 @@ impl fmt::Debug for Cursor<'_, T> { /// To accommodate this, there is a "ghost" non-element that yields `None` between the head and /// tail of the list. #[unstable(feature = "linked_list_cursors", issue = "58533")] -pub struct CursorMut<'a, T: 'a> { +pub struct CursorMut< + 'a, + T: 'a, + #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global, +> { index: usize, current: Option>>, - list: &'a mut LinkedList, + list: &'a mut LinkedList, } #[unstable(feature = "linked_list_cursors", issue = "58533")] -impl fmt::Debug for CursorMut<'_, T> { +impl fmt::Debug for CursorMut<'_, T, A> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_tuple("CursorMut").field(&self.list).field(&self.index()).finish() } } -impl<'a, T> Cursor<'a, T> { +impl<'a, T, A: Allocator> Cursor<'a, T, A> { /// Returns the cursor position index within the `LinkedList`. /// /// This returns `None` if the cursor is currently pointing to the @@ -1321,7 +1392,7 @@ impl<'a, T> Cursor<'a, T> { } } -impl<'a, T> CursorMut<'a, T> { +impl<'a, T, A: Allocator> CursorMut<'a, T, A> { /// Returns the cursor position index within the `LinkedList`. /// /// This returns `None` if the cursor is currently pointing to the @@ -1426,7 +1497,7 @@ impl<'a, T> CursorMut<'a, T> { /// `CursorMut` is frozen for the lifetime of the `Cursor`. #[must_use] #[unstable(feature = "linked_list_cursors", issue = "58533")] - pub fn as_cursor(&self) -> Cursor<'_, T> { + pub fn as_cursor(&self) -> Cursor<'_, T, A> { Cursor { list: self.list, current: self.current, index: self.index } } } @@ -1434,6 +1505,51 @@ impl<'a, T> CursorMut<'a, T> { // Now the list editing operations impl<'a, T> CursorMut<'a, T> { + /// Inserts the elements from the given `LinkedList` after the current one. + /// + /// If the cursor is pointing at the "ghost" non-element then the new elements are + /// inserted at the start of the `LinkedList`. + #[unstable(feature = "linked_list_cursors", issue = "58533")] + pub fn splice_after(&mut self, list: LinkedList) { + unsafe { + let (splice_head, splice_tail, splice_len) = match list.detach_all_nodes() { + Some(parts) => parts, + _ => return, + }; + let node_next = match self.current { + None => self.list.head, + Some(node) => node.as_ref().next, + }; + self.list.splice_nodes(self.current, node_next, splice_head, splice_tail, splice_len); + if self.current.is_none() { + // The "ghost" non-element's index has changed. + self.index = self.list.len; + } + } + } + + /// Inserts the elements from the given `LinkedList` before the current one. + /// + /// If the cursor is pointing at the "ghost" non-element then the new elements are + /// inserted at the end of the `LinkedList`. + #[unstable(feature = "linked_list_cursors", issue = "58533")] + pub fn splice_before(&mut self, list: LinkedList) { + unsafe { + let (splice_head, splice_tail, splice_len) = match list.detach_all_nodes() { + Some(parts) => parts, + _ => return, + }; + let node_prev = match self.current { + None => self.list.tail, + Some(node) => node.as_ref().prev, + }; + self.list.splice_nodes(node_prev, self.current, splice_head, splice_tail, splice_len); + self.index += splice_len; + } + } +} + +impl<'a, T, A: Allocator> CursorMut<'a, T, A> { /// Inserts a new element into the `LinkedList` after the current one. /// /// If the cursor is pointing at the "ghost" non-element then the new element is @@ -1441,7 +1557,7 @@ impl<'a, T> CursorMut<'a, T> { #[unstable(feature = "linked_list_cursors", issue = "58533")] pub fn insert_after(&mut self, item: T) { unsafe { - let spliced_node = Box::leak(Box::new(Node::new(item))).into(); + let spliced_node = Box::leak(Box::new_in(Node::new(item), &self.list.alloc)).into(); let node_next = match self.current { None => self.list.head, Some(node) => node.as_ref().next, @@ -1461,7 +1577,7 @@ impl<'a, T> CursorMut<'a, T> { #[unstable(feature = "linked_list_cursors", issue = "58533")] pub fn insert_before(&mut self, item: T) { unsafe { - let spliced_node = Box::leak(Box::new(Node::new(item))).into(); + let spliced_node = Box::leak(Box::new_in(Node::new(item), &self.list.alloc)).into(); let node_prev = match self.current { None => self.list.tail, Some(node) => node.as_ref().prev, @@ -1497,7 +1613,10 @@ impl<'a, T> CursorMut<'a, T> { /// If the cursor is currently pointing to the "ghost" non-element then no element /// is removed and `None` is returned. #[unstable(feature = "linked_list_cursors", issue = "58533")] - pub fn remove_current_as_list(&mut self) -> Option> { + pub fn remove_current_as_list(&mut self) -> Option> + where + A: Clone, + { let mut unlinked_node = self.current?; unsafe { self.current = unlinked_node.as_ref().next; @@ -1509,54 +1628,12 @@ impl<'a, T> CursorMut<'a, T> { head: Some(unlinked_node), tail: Some(unlinked_node), len: 1, + alloc: self.list.alloc.clone(), marker: PhantomData, }) } } - /// Inserts the elements from the given `LinkedList` after the current one. - /// - /// If the cursor is pointing at the "ghost" non-element then the new elements are - /// inserted at the start of the `LinkedList`. - #[unstable(feature = "linked_list_cursors", issue = "58533")] - pub fn splice_after(&mut self, list: LinkedList) { - unsafe { - let (splice_head, splice_tail, splice_len) = match list.detach_all_nodes() { - Some(parts) => parts, - _ => return, - }; - let node_next = match self.current { - None => self.list.head, - Some(node) => node.as_ref().next, - }; - self.list.splice_nodes(self.current, node_next, splice_head, splice_tail, splice_len); - if self.current.is_none() { - // The "ghost" non-element's index has changed. - self.index = self.list.len; - } - } - } - - /// Inserts the elements from the given `LinkedList` before the current one. - /// - /// If the cursor is pointing at the "ghost" non-element then the new elements are - /// inserted at the end of the `LinkedList`. - #[unstable(feature = "linked_list_cursors", issue = "58533")] - pub fn splice_before(&mut self, list: LinkedList) { - unsafe { - let (splice_head, splice_tail, splice_len) = match list.detach_all_nodes() { - Some(parts) => parts, - _ => return, - }; - let node_prev = match self.current { - None => self.list.tail, - Some(node) => node.as_ref().prev, - }; - self.list.splice_nodes(node_prev, self.current, splice_head, splice_tail, splice_len); - self.index += splice_len; - } - } - /// Splits the list into two after the current element. This will return a /// new list consisting of everything after the cursor, with the original /// list retaining everything before. @@ -1564,7 +1641,10 @@ impl<'a, T> CursorMut<'a, T> { /// If the cursor is pointing at the "ghost" non-element then the entire contents /// of the `LinkedList` are moved. #[unstable(feature = "linked_list_cursors", issue = "58533")] - pub fn split_after(&mut self) -> LinkedList { + pub fn split_after(&mut self) -> LinkedList + where + A: Clone, + { let split_off_idx = if self.index == self.list.len { 0 } else { self.index + 1 }; if self.index == self.list.len { // The "ghost" non-element's index has changed to 0. @@ -1580,7 +1660,10 @@ impl<'a, T> CursorMut<'a, T> { /// If the cursor is pointing at the "ghost" non-element then the entire contents /// of the `LinkedList` are moved. #[unstable(feature = "linked_list_cursors", issue = "58533")] - pub fn split_before(&mut self) -> LinkedList { + pub fn split_before(&mut self) -> LinkedList + where + A: Clone, + { let split_off_idx = self.index; self.index = 0; unsafe { self.list.split_off_before_node(self.current, split_off_idx) } @@ -1722,11 +1805,15 @@ impl<'a, T> CursorMut<'a, T> { /// An iterator produced by calling `drain_filter` on LinkedList. #[unstable(feature = "drain_filter", reason = "recently added", issue = "43244")] -pub struct DrainFilter<'a, T: 'a, F: 'a> -where +pub struct DrainFilter< + 'a, + T: 'a, + F: 'a, + #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global, +> where F: FnMut(&mut T) -> bool, { - list: &'a mut LinkedList, + list: &'a mut LinkedList, it: Option>>, pred: F, idx: usize, @@ -1734,7 +1821,7 @@ where } #[unstable(feature = "drain_filter", reason = "recently added", issue = "43244")] -impl Iterator for DrainFilter<'_, T, F> +impl Iterator for DrainFilter<'_, T, F, A> where F: FnMut(&mut T) -> bool, { @@ -1763,16 +1850,16 @@ where } #[unstable(feature = "drain_filter", reason = "recently added", issue = "43244")] -impl Drop for DrainFilter<'_, T, F> +impl Drop for DrainFilter<'_, T, F, A> where F: FnMut(&mut T) -> bool, { fn drop(&mut self) { - struct DropGuard<'r, 'a, T, F>(&'r mut DrainFilter<'a, T, F>) + struct DropGuard<'r, 'a, T, F, A: Allocator>(&'r mut DrainFilter<'a, T, F, A>) where F: FnMut(&mut T) -> bool; - impl<'r, 'a, T, F> Drop for DropGuard<'r, 'a, T, F> + impl<'r, 'a, T, F, A: Allocator> Drop for DropGuard<'r, 'a, T, F, A> where F: FnMut(&mut T) -> bool, { @@ -1800,7 +1887,7 @@ where } #[stable(feature = "rust1", since = "1.0.0")] -impl Iterator for IntoIter { +impl Iterator for IntoIter { type Item = T; #[inline] @@ -1815,7 +1902,7 @@ impl Iterator for IntoIter { } #[stable(feature = "rust1", since = "1.0.0")] -impl DoubleEndedIterator for IntoIter { +impl DoubleEndedIterator for IntoIter { #[inline] fn next_back(&mut self) -> Option { self.list.pop_back() @@ -1823,10 +1910,10 @@ impl DoubleEndedIterator for IntoIter { } #[stable(feature = "rust1", since = "1.0.0")] -impl ExactSizeIterator for IntoIter {} +impl ExactSizeIterator for IntoIter {} #[stable(feature = "fused", since = "1.26.0")] -impl FusedIterator for IntoIter {} +impl FusedIterator for IntoIter {} #[stable(feature = "default_iters", since = "CURRENT_RUSTC_VERSION")] impl Default for IntoIter { @@ -1852,19 +1939,19 @@ impl FromIterator for LinkedList { } #[stable(feature = "rust1", since = "1.0.0")] -impl IntoIterator for LinkedList { +impl IntoIterator for LinkedList { type Item = T; - type IntoIter = IntoIter; + type IntoIter = IntoIter; /// Consumes the list into an iterator yielding elements by value. #[inline] - fn into_iter(self) -> IntoIter { + fn into_iter(self) -> IntoIter { IntoIter { list: self } } } #[stable(feature = "rust1", since = "1.0.0")] -impl<'a, T> IntoIterator for &'a LinkedList { +impl<'a, T, A: Allocator> IntoIterator for &'a LinkedList { type Item = &'a T; type IntoIter = Iter<'a, T>; @@ -1874,7 +1961,7 @@ impl<'a, T> IntoIterator for &'a LinkedList { } #[stable(feature = "rust1", since = "1.0.0")] -impl<'a, T> IntoIterator for &'a mut LinkedList { +impl<'a, T, A: Allocator> IntoIterator for &'a mut LinkedList { type Item = &'a mut T; type IntoIter = IterMut<'a, T>; @@ -1884,7 +1971,7 @@ impl<'a, T> IntoIterator for &'a mut LinkedList { } #[stable(feature = "rust1", since = "1.0.0")] -impl Extend for LinkedList { +impl Extend for LinkedList { fn extend>(&mut self, iter: I) { >::spec_extend(self, iter); } @@ -1895,7 +1982,7 @@ impl Extend for LinkedList { } } -impl SpecExtend for LinkedList { +impl SpecExtend for LinkedList { default fn spec_extend(&mut self, iter: I) { iter.into_iter().for_each(move |elt| self.push_back(elt)); } @@ -1908,7 +1995,7 @@ impl SpecExtend> for LinkedList { } #[stable(feature = "extend_ref", since = "1.2.0")] -impl<'a, T: 'a + Copy> Extend<&'a T> for LinkedList { +impl<'a, T: 'a + Copy, A: Allocator> Extend<&'a T> for LinkedList { fn extend>(&mut self, iter: I) { self.extend(iter.into_iter().cloned()); } @@ -1920,7 +2007,7 @@ impl<'a, T: 'a + Copy> Extend<&'a T> for LinkedList { } #[stable(feature = "rust1", since = "1.0.0")] -impl PartialEq for LinkedList { +impl PartialEq for LinkedList { fn eq(&self, other: &Self) -> bool { self.len() == other.len() && self.iter().eq(other) } @@ -1931,17 +2018,17 @@ impl PartialEq for LinkedList { } #[stable(feature = "rust1", since = "1.0.0")] -impl Eq for LinkedList {} +impl Eq for LinkedList {} #[stable(feature = "rust1", since = "1.0.0")] -impl PartialOrd for LinkedList { +impl PartialOrd for LinkedList { fn partial_cmp(&self, other: &Self) -> Option { self.iter().partial_cmp(other) } } #[stable(feature = "rust1", since = "1.0.0")] -impl Ord for LinkedList { +impl Ord for LinkedList { #[inline] fn cmp(&self, other: &Self) -> Ordering { self.iter().cmp(other) @@ -1949,9 +2036,11 @@ impl Ord for LinkedList { } #[stable(feature = "rust1", since = "1.0.0")] -impl Clone for LinkedList { +impl Clone for LinkedList { fn clone(&self) -> Self { - self.iter().cloned().collect() + let mut list = Self::new_in(self.alloc.clone()); + list.extend(self.iter().cloned()); + list } fn clone_from(&mut self, other: &Self) { @@ -1969,14 +2058,14 @@ impl Clone for LinkedList { } #[stable(feature = "rust1", since = "1.0.0")] -impl fmt::Debug for LinkedList { +impl fmt::Debug for LinkedList { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_list().entries(self).finish() } } #[stable(feature = "rust1", since = "1.0.0")] -impl Hash for LinkedList { +impl Hash for LinkedList { fn hash(&self, state: &mut H) { state.write_length_prefix(self.len()); for elt in self { @@ -2016,10 +2105,10 @@ fn assert_covariance() { } #[stable(feature = "rust1", since = "1.0.0")] -unsafe impl Send for LinkedList {} +unsafe impl Send for LinkedList {} #[stable(feature = "rust1", since = "1.0.0")] -unsafe impl Sync for LinkedList {} +unsafe impl Sync for LinkedList {} #[stable(feature = "rust1", since = "1.0.0")] unsafe impl Send for Iter<'_, T> {} @@ -2034,13 +2123,13 @@ unsafe impl Send for IterMut<'_, T> {} unsafe impl Sync for IterMut<'_, T> {} #[unstable(feature = "linked_list_cursors", issue = "58533")] -unsafe impl Send for Cursor<'_, T> {} +unsafe impl Send for Cursor<'_, T, A> {} #[unstable(feature = "linked_list_cursors", issue = "58533")] -unsafe impl Sync for Cursor<'_, T> {} +unsafe impl Sync for Cursor<'_, T, A> {} #[unstable(feature = "linked_list_cursors", issue = "58533")] -unsafe impl Send for CursorMut<'_, T> {} +unsafe impl Send for CursorMut<'_, T, A> {} #[unstable(feature = "linked_list_cursors", issue = "58533")] -unsafe impl Sync for CursorMut<'_, T> {} +unsafe impl Sync for CursorMut<'_, T, A> {} diff --git a/library/alloc/src/collections/vec_deque/spec_from_iter.rs b/library/alloc/src/collections/vec_deque/spec_from_iter.rs index 7650492ebdad1..2708c7fe10259 100644 --- a/library/alloc/src/collections/vec_deque/spec_from_iter.rs +++ b/library/alloc/src/collections/vec_deque/spec_from_iter.rs @@ -12,7 +12,7 @@ where default fn spec_from_iter(iterator: I) -> Self { // Since converting is O(1) now, just re-use the `Vec` logic for // anything where we can't do something extra-special for `VecDeque`, - // especially as that could save us some monomorphiziation work + // especially as that could save us some monomorphization work // if one uses the same iterators (like slice ones) with both. crate::vec::Vec::from_iter(iterator).into() } diff --git a/library/alloc/src/str.rs b/library/alloc/src/str.rs index b87ef59f64a3b..8497740990443 100644 --- a/library/alloc/src/str.rs +++ b/library/alloc/src/str.rs @@ -404,12 +404,12 @@ impl str { // See https://www.unicode.org/versions/Unicode7.0.0/ch03.pdf#G33992 // for the definition of `Final_Sigma`. debug_assert!('Σ'.len_utf8() == 2); - let is_word_final = case_ignoreable_then_cased(from[..i].chars().rev()) - && !case_ignoreable_then_cased(from[i + 2..].chars()); + let is_word_final = case_ignorable_then_cased(from[..i].chars().rev()) + && !case_ignorable_then_cased(from[i + 2..].chars()); to.push_str(if is_word_final { "ς" } else { "σ" }); } - fn case_ignoreable_then_cased>(iter: I) -> bool { + fn case_ignorable_then_cased>(iter: I) -> bool { use core::unicode::{Case_Ignorable, Cased}; match iter.skip_while(|&c| Case_Ignorable(c)).next() { Some(c) => Cased(c), diff --git a/library/alloc/src/task.rs b/library/alloc/src/task.rs index 9d8e309a978d9..5d9772b878b03 100644 --- a/library/alloc/src/task.rs +++ b/library/alloc/src/task.rs @@ -39,6 +39,7 @@ use crate::sync::Arc; /// use std::sync::Arc; /// use std::task::{Context, Poll, Wake}; /// use std::thread::{self, Thread}; +/// use core::pin::pin; /// /// /// A waker that wakes up the current thread when called. /// struct ThreadWaker(Thread); @@ -52,7 +53,7 @@ use crate::sync::Arc; /// /// Run a future to completion on the current thread. /// fn block_on(fut: impl Future) -> T { /// // Pin the future so it can be polled. -/// let mut fut = Box::pin(fut); +/// let mut fut = pin!(fut); /// /// // Create a new context to be passed to the future. /// let t = thread::current(); diff --git a/library/alloc/src/vec/in_place_collect.rs b/library/alloc/src/vec/in_place_collect.rs index 87d61deb1eb2f..2f1ee8b03533d 100644 --- a/library/alloc/src/vec/in_place_collect.rs +++ b/library/alloc/src/vec/in_place_collect.rs @@ -201,7 +201,7 @@ where // // Note: This access to the source wouldn't be allowed by the TrustedRandomIteratorNoCoerce // contract (used by SpecInPlaceCollect below). But see the "O(1) collect" section in the - // module documenttation why this is ok anyway. + // module documentation why this is ok anyway. let dst_guard = InPlaceDstBufDrop { ptr: dst_buf, len, cap }; src.forget_allocation_drop_remaining(); mem::forget(dst_guard); diff --git a/library/alloc/tests/slice.rs b/library/alloc/tests/slice.rs index 0693beb48c402..9aa5575ca938b 100644 --- a/library/alloc/tests/slice.rs +++ b/library/alloc/tests/slice.rs @@ -705,7 +705,7 @@ fn test_move_rev_iterator() { } #[test] -fn test_splitator() { +fn test_split_iterator() { let xs = &[1, 2, 3, 4, 5]; let splits: &[&[_]] = &[&[1], &[3], &[5]]; @@ -725,7 +725,7 @@ fn test_splitator() { } #[test] -fn test_splitator_inclusive() { +fn test_split_iterator_inclusive() { let xs = &[1, 2, 3, 4, 5]; let splits: &[&[_]] = &[&[1, 2], &[3, 4], &[5]]; @@ -745,7 +745,7 @@ fn test_splitator_inclusive() { } #[test] -fn test_splitator_inclusive_reverse() { +fn test_split_iterator_inclusive_reverse() { let xs = &[1, 2, 3, 4, 5]; let splits: &[&[_]] = &[&[5], &[3, 4], &[1, 2]]; @@ -765,7 +765,7 @@ fn test_splitator_inclusive_reverse() { } #[test] -fn test_splitator_mut_inclusive() { +fn test_split_iterator_mut_inclusive() { let xs = &mut [1, 2, 3, 4, 5]; let splits: &[&[_]] = &[&[1, 2], &[3, 4], &[5]]; @@ -785,7 +785,7 @@ fn test_splitator_mut_inclusive() { } #[test] -fn test_splitator_mut_inclusive_reverse() { +fn test_split_iterator_mut_inclusive_reverse() { let xs = &mut [1, 2, 3, 4, 5]; let splits: &[&[_]] = &[&[5], &[3, 4], &[1, 2]]; @@ -805,7 +805,7 @@ fn test_splitator_mut_inclusive_reverse() { } #[test] -fn test_splitnator() { +fn test_splitn_iterator() { let xs = &[1, 2, 3, 4, 5]; let splits: &[&[_]] = &[&[1, 2, 3, 4, 5]]; @@ -821,7 +821,7 @@ fn test_splitnator() { } #[test] -fn test_splitnator_mut() { +fn test_splitn_iterator_mut() { let xs = &mut [1, 2, 3, 4, 5]; let splits: &[&mut [_]] = &[&mut [1, 2, 3, 4, 5]]; @@ -837,7 +837,7 @@ fn test_splitnator_mut() { } #[test] -fn test_rsplitator() { +fn test_rsplit_iterator() { let xs = &[1, 2, 3, 4, 5]; let splits: &[&[_]] = &[&[5], &[3], &[1]]; @@ -855,7 +855,7 @@ fn test_rsplitator() { } #[test] -fn test_rsplitnator() { +fn test_rsplitn_iterator() { let xs = &[1, 2, 3, 4, 5]; let splits: &[&[_]] = &[&[1, 2, 3, 4, 5]]; @@ -932,7 +932,7 @@ fn test_split_iterators_size_hint() { } #[test] -fn test_windowsator() { +fn test_windows_iterator() { let v = &[1, 2, 3, 4]; let wins: &[&[_]] = &[&[1, 2], &[2, 3], &[3, 4]]; @@ -948,13 +948,13 @@ fn test_windowsator() { #[test] #[should_panic] -fn test_windowsator_0() { +fn test_windows_iterator_0() { let v = &[1, 2, 3, 4]; let _it = v.windows(0); } #[test] -fn test_chunksator() { +fn test_chunks_iterator() { let v = &[1, 2, 3, 4, 5]; assert_eq!(v.chunks(2).len(), 3); @@ -972,13 +972,13 @@ fn test_chunksator() { #[test] #[should_panic] -fn test_chunksator_0() { +fn test_chunks_iterator_0() { let v = &[1, 2, 3, 4]; let _it = v.chunks(0); } #[test] -fn test_chunks_exactator() { +fn test_chunks_exact_iterator() { let v = &[1, 2, 3, 4, 5]; assert_eq!(v.chunks_exact(2).len(), 2); @@ -996,13 +996,13 @@ fn test_chunks_exactator() { #[test] #[should_panic] -fn test_chunks_exactator_0() { +fn test_chunks_exact_iterator_0() { let v = &[1, 2, 3, 4]; let _it = v.chunks_exact(0); } #[test] -fn test_rchunksator() { +fn test_rchunks_iterator() { let v = &[1, 2, 3, 4, 5]; assert_eq!(v.rchunks(2).len(), 3); @@ -1020,13 +1020,13 @@ fn test_rchunksator() { #[test] #[should_panic] -fn test_rchunksator_0() { +fn test_rchunks_iterator_0() { let v = &[1, 2, 3, 4]; let _it = v.rchunks(0); } #[test] -fn test_rchunks_exactator() { +fn test_rchunks_exact_iterator() { let v = &[1, 2, 3, 4, 5]; assert_eq!(v.rchunks_exact(2).len(), 2); @@ -1044,7 +1044,7 @@ fn test_rchunks_exactator() { #[test] #[should_panic] -fn test_rchunks_exactator_0() { +fn test_rchunks_exact_iterator_0() { let v = &[1, 2, 3, 4]; let _it = v.rchunks_exact(0); } @@ -1219,7 +1219,7 @@ fn test_ends_with() { } #[test] -fn test_mut_splitator() { +fn test_mut_split_iterator() { let mut xs = [0, 1, 0, 2, 3, 0, 0, 4, 5, 0]; assert_eq!(xs.split_mut(|x| *x == 0).count(), 6); for slice in xs.split_mut(|x| *x == 0) { @@ -1235,7 +1235,7 @@ fn test_mut_splitator() { } #[test] -fn test_mut_splitator_rev() { +fn test_mut_split_iterator_rev() { let mut xs = [1, 2, 0, 3, 4, 0, 0, 5, 6, 0]; for slice in xs.split_mut(|x| *x == 0).rev().take(4) { slice.reverse(); diff --git a/library/alloc/tests/vec.rs b/library/alloc/tests/vec.rs index 3ee16f04e92f5..cc4c1f1272865 100644 --- a/library/alloc/tests/vec.rs +++ b/library/alloc/tests/vec.rs @@ -2470,7 +2470,7 @@ fn test_vec_dedup_panicking() { // Regression test for issue #82533 #[test] -fn test_extend_from_within_panicing_clone() { +fn test_extend_from_within_panicking_clone() { struct Panic<'dc> { drop_count: &'dc AtomicU32, aaaaa: bool, diff --git a/library/core/src/ffi/mod.rs b/library/core/src/ffi/mod.rs index c4f554c8c6bf9..146e8d3d22a47 100644 --- a/library/core/src/ffi/mod.rs +++ b/library/core/src/ffi/mod.rs @@ -143,7 +143,10 @@ mod c_char_definition { target_arch = "powerpc" ) ), - all(target_os = "fuchsia", target_arch = "aarch64"), + all( + target_os = "fuchsia", + any(target_arch = "aarch64", target_arch = "riscv64") + ), all(target_os = "nto", target_arch = "aarch64"), target_os = "horizon" ))] { diff --git a/library/core/src/fmt/builders.rs b/library/core/src/fmt/builders.rs index 7da49b04aaae9..d1c6b67b27881 100644 --- a/library/core/src/fmt/builders.rs +++ b/library/core/src/fmt/builders.rs @@ -109,14 +109,14 @@ impl<'a, 'b: 'a> DebugStruct<'a, 'b> { /// .field("bar", &self.bar) // We add `bar` field. /// .field("another", &self.another) // We add `another` field. /// // We even add a field which doesn't exist (because why not?). - /// .field("not_existing_field", &1) + /// .field("nonexistent_field", &1) /// .finish() // We're good to go! /// } /// } /// /// assert_eq!( /// format!("{:?}", Bar { bar: 10, another: "Hello World".to_string() }), - /// "Bar { bar: 10, another: \"Hello World\", not_existing_field: 1 }", + /// "Bar { bar: 10, another: \"Hello World\", nonexistent_field: 1 }", /// ); /// ``` #[stable(feature = "debug_builders", since = "1.2.0")] diff --git a/library/core/src/hint.rs b/library/core/src/hint.rs index f6698589ccd92..75c104ce2fad0 100644 --- a/library/core/src/hint.rs +++ b/library/core/src/hint.rs @@ -217,17 +217,14 @@ pub fn spin_loop() { /// Note however, that `black_box` is only (and can only be) provided on a "best-effort" basis. The /// extent to which it can block optimisations may vary depending upon the platform and code-gen /// backend used. Programs cannot rely on `black_box` for *correctness*, beyond it behaving as the -/// identity function. +/// identity function. As such, it **must not be relied upon to control critical program behavior.** +/// This _immediately_ precludes any direct use of this function for cryptographic or security +/// purposes. /// /// [`std::convert::identity`]: crate::convert::identity /// /// # When is this useful? /// -/// First and foremost: `black_box` does _not_ guarantee any exact behavior and, in some cases, may -/// do nothing at all. As such, it **must not be relied upon to control critical program behavior.** -/// This _immediately_ precludes any direct use of this function for cryptographic or security -/// purposes. -/// /// While not suitable in those mission-critical cases, `black_box`'s functionality can generally be /// relied upon for benchmarking, and should be used there. It will try to ensure that the /// compiler doesn't optimize away part of the intended test code based on context. For diff --git a/library/core/src/intrinsics.rs b/library/core/src/intrinsics.rs index 39edfd8265b41..741f20cf4c715 100644 --- a/library/core/src/intrinsics.rs +++ b/library/core/src/intrinsics.rs @@ -2474,7 +2474,7 @@ extern "rust-intrinsic" { /// This macro should be called as `assert_unsafe_precondition!([Generics](name: Type) => Expression)` /// where the names specified will be moved into the macro as captured variables, and defines an item /// to call `const_eval_select` on. The tokens inside the square brackets are used to denote generics -/// for the function declaractions and can be omitted if there is no generics. +/// for the function declarations and can be omitted if there is no generics. /// /// # Safety /// @@ -2733,7 +2733,7 @@ pub const unsafe fn copy(src: *const T, dst: *mut T, count: usize) { // SAFETY: the safety contract for `copy` must be upheld by the caller. unsafe { assert_unsafe_precondition!( - "ptr::copy requires that both pointer arguments are aligned aligned and non-null", + "ptr::copy requires that both pointer arguments are aligned and non-null", [T](src: *const T, dst: *mut T) => is_aligned_and_not_null(src) && is_aligned_and_not_null(dst) ); diff --git a/library/core/src/iter/adapters/flatten.rs b/library/core/src/iter/adapters/flatten.rs index e0308e3360f45..7217e8f2a8ef6 100644 --- a/library/core/src/iter/adapters/flatten.rs +++ b/library/core/src/iter/adapters/flatten.rs @@ -136,26 +136,12 @@ where } #[unstable(feature = "trusted_len", issue = "37572")] -unsafe impl TrustedLen for FlatMap +unsafe impl TrustedLen for FlatMap where - I: TrustedLen, - F: FnMut(I::Item) -> [T; N], -{ -} - -#[unstable(feature = "trusted_len", issue = "37572")] -unsafe impl<'a, T, I, F, const N: usize> TrustedLen for FlatMap -where - I: TrustedLen, - F: FnMut(I::Item) -> &'a [T; N], -{ -} - -#[unstable(feature = "trusted_len", issue = "37572")] -unsafe impl<'a, T, I, F, const N: usize> TrustedLen for FlatMap -where - I: TrustedLen, - F: FnMut(I::Item) -> &'a mut [T; N], + I: Iterator, + U: IntoIterator, + F: FnMut(I::Item) -> U, + FlattenCompat, ::IntoIter>: TrustedLen, { } @@ -298,8 +284,8 @@ where #[unstable(feature = "trusted_len", issue = "37572")] unsafe impl TrustedLen for Flatten where - I: TrustedLen, - ::Item: TrustedConstSize, + I: Iterator, + FlattenCompat::IntoIter>: TrustedLen, { } @@ -660,6 +646,27 @@ where } } +unsafe impl TrustedLen + for FlattenCompat::IntoIter> +where + I: TrustedLen, +{ +} + +unsafe impl<'a, const N: usize, I, T> TrustedLen + for FlattenCompat::IntoIter> +where + I: TrustedLen, +{ +} + +unsafe impl<'a, const N: usize, I, T> TrustedLen + for FlattenCompat::IntoIter> +where + I: TrustedLen, +{ +} + trait ConstSizeIntoIterator: IntoIterator { // FIXME(#31844): convert to an associated const once specialization supports that fn size() -> Option; @@ -696,19 +703,6 @@ impl ConstSizeIntoIterator for &mut [T; N] { } } -#[doc(hidden)] -#[unstable(feature = "std_internals", issue = "none")] -// FIXME(#20400): Instead of this helper trait there should be multiple impl TrustedLen for Flatten<> -// blocks with different bounds on Iterator::Item but the compiler erroneously considers them overlapping -pub unsafe trait TrustedConstSize: IntoIterator {} - -#[unstable(feature = "std_internals", issue = "none")] -unsafe impl TrustedConstSize for [T; N] {} -#[unstable(feature = "std_internals", issue = "none")] -unsafe impl TrustedConstSize for &'_ [T; N] {} -#[unstable(feature = "std_internals", issue = "none")] -unsafe impl TrustedConstSize for &'_ mut [T; N] {} - #[inline] fn and_then_or_clear(opt: &mut Option, f: impl FnOnce(&mut T) -> Option) -> Option { let x = f(opt.as_mut()?); diff --git a/library/core/src/macros/panic.md b/library/core/src/macros/panic.md index 98fb7e9e41d7a..8b549e187ba81 100644 --- a/library/core/src/macros/panic.md +++ b/library/core/src/macros/panic.md @@ -42,7 +42,7 @@ the successful result of some computation, `Ok(T)`, or error types that represent an anticipated runtime failure mode of that computation, `Err(E)`. `Result` is used alongside user defined types which represent the various anticipated runtime failure modes that the associated computation could -encounter. `Result` must be propagated manually, often with the the help of the +encounter. `Result` must be propagated manually, often with the help of the `?` operator and `Try` trait, and they must be reported manually, often with the help of the `Error` trait. diff --git a/library/core/src/ptr/const_ptr.rs b/library/core/src/ptr/const_ptr.rs index 603bd88733393..6b18f5f5a40d1 100644 --- a/library/core/src/ptr/const_ptr.rs +++ b/library/core/src/ptr/const_ptr.rs @@ -264,7 +264,7 @@ impl *const T { let dest_addr = addr as isize; let offset = dest_addr.wrapping_sub(self_addr); - // This is the canonical desugarring of this operation + // This is the canonical desugaring of this operation self.wrapping_byte_offset(offset) } diff --git a/library/core/src/ptr/mod.rs b/library/core/src/ptr/mod.rs index 555d58fad8440..675bc8245d8d8 100644 --- a/library/core/src/ptr/mod.rs +++ b/library/core/src/ptr/mod.rs @@ -2126,7 +2126,7 @@ mod new_fn_ptr_impl { /// assert_eq!(unsafe { raw_f2.read_unaligned() }, 2); /// ``` /// -/// See [`addr_of_mut`] for how to create a pointer to unininitialized data. +/// See [`addr_of_mut`] for how to create a pointer to uninitialized data. /// Doing that with `addr_of` would not make much sense since one could only /// read the data, and that would be Undefined Behavior. #[stable(feature = "raw_ref_macros", since = "1.51.0")] diff --git a/library/core/src/ptr/mut_ptr.rs b/library/core/src/ptr/mut_ptr.rs index 24b66c549a6e4..7b0fd02eb9f8b 100644 --- a/library/core/src/ptr/mut_ptr.rs +++ b/library/core/src/ptr/mut_ptr.rs @@ -270,7 +270,7 @@ impl *mut T { let dest_addr = addr as isize; let offset = dest_addr.wrapping_sub(self_addr); - // This is the canonical desugarring of this operation + // This is the canonical desugaring of this operation self.wrapping_byte_offset(offset) } diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs index d12809357a890..33a468a6bca57 100644 --- a/library/core/src/slice/mod.rs +++ b/library/core/src/slice/mod.rs @@ -4451,7 +4451,7 @@ impl SlicePattern for [T; N] { /// This will do `binomial(N + 1, 2) = N * (N + 1) / 2 = 0, 1, 3, 6, 10, ..` /// comparison operations. fn get_many_check_valid(indices: &[usize; N], len: usize) -> bool { - // NB: The optimzer should inline the loops into a sequence + // NB: The optimizer should inline the loops into a sequence // of instructions without additional branching. let mut valid = true; for (i, &idx) in indices.iter().enumerate() { diff --git a/library/core/src/slice/sort.rs b/library/core/src/slice/sort.rs index 07fd96f929586..e6e3b55efa9ae 100644 --- a/library/core/src/slice/sort.rs +++ b/library/core/src/slice/sort.rs @@ -1456,7 +1456,6 @@ pub struct TimSortRun { /// Takes a range as denoted by start and end, that is already sorted and extends it to the right if /// necessary with sorts optimized for smaller ranges such as insertion sort. -#[cfg(not(no_global_oom_handling))] fn provide_sorted_batch(v: &mut [T], start: usize, mut end: usize, is_less: &mut F) -> usize where F: FnMut(&T, &T) -> bool, diff --git a/library/core/tests/asserting.rs b/library/core/tests/asserting.rs index 4b626ba6f2d5d..1d9670886eb3d 100644 --- a/library/core/tests/asserting.rs +++ b/library/core/tests/asserting.rs @@ -24,7 +24,7 @@ struct NoCopyNoDebug; struct NoDebug; test!( - capture_with_non_copyable_and_non_debugabble_elem_has_correct_params, + capture_with_non_copyable_and_non_debuggable_elem_has_correct_params, NoCopyNoDebug, None, "N/A" @@ -32,6 +32,6 @@ test!( test!(capture_with_non_copyable_elem_has_correct_params, NoCopy, None, "N/A"); -test!(capture_with_non_debugabble_elem_has_correct_params, NoDebug, None, "N/A"); +test!(capture_with_non_debuggable_elem_has_correct_params, NoDebug, None, "N/A"); -test!(capture_with_copyable_and_debugabble_elem_has_correct_params, 1i32, Some(1i32), "1"); +test!(capture_with_copyable_and_debuggable_elem_has_correct_params, 1i32, Some(1i32), "1"); diff --git a/library/core/tests/lazy.rs b/library/core/tests/lazy.rs index e2f526d155e87..7f7f1f0058801 100644 --- a/library/core/tests/lazy.rs +++ b/library/core/tests/lazy.rs @@ -10,7 +10,7 @@ fn once_cell() { c.get_or_init(|| 92); assert_eq!(c.get(), Some(&92)); - c.get_or_init(|| panic!("Kabom!")); + c.get_or_init(|| panic!("Kaboom!")); assert_eq!(c.get(), Some(&92)); } diff --git a/library/core/tests/num/mod.rs b/library/core/tests/num/mod.rs index c79e909e41db8..3e1f848ccfec2 100644 --- a/library/core/tests/num/mod.rs +++ b/library/core/tests/num/mod.rs @@ -170,7 +170,7 @@ fn test_can_not_overflow() { for base in 2..=36 { let num = (<$t>::MAX as u128) + 1; - // Calcutate the string length for the smallest overflowing number: + // Calculate the string length for the smallest overflowing number: let max_len_string = format_radix(num, base as u128); // Ensure that string length is deemed to potentially overflow: assert!(can_overflow::<$t>(base, &max_len_string)); diff --git a/library/std/Cargo.toml b/library/std/Cargo.toml index f2fda64a1ee72..72a5b4773306e 100644 --- a/library/std/Cargo.toml +++ b/library/std/Cargo.toml @@ -15,7 +15,7 @@ cfg-if = { version = "1.0", features = ['rustc-dep-of-std'] } panic_unwind = { path = "../panic_unwind", optional = true } panic_abort = { path = "../panic_abort" } core = { path = "../core" } -libc = { version = "0.2.140", default-features = false, features = ['rustc-dep-of-std'] } +libc = { version = "0.2.142", default-features = false, features = ['rustc-dep-of-std'] } compiler_builtins = { version = "0.1.91" } profiler_builtins = { path = "../profiler_builtins", optional = true } unwind = { path = "../unwind" } diff --git a/library/std/src/fs.rs b/library/std/src/fs.rs index 55580b23a6249..42a68496fc491 100644 --- a/library/std/src/fs.rs +++ b/library/std/src/fs.rs @@ -2515,9 +2515,10 @@ impl AsInnerMut for DirBuilder { /// This function will traverse symbolic links to query information about the /// destination file. In case of broken symbolic links this will return `Ok(false)`. /// -/// As opposed to the [`Path::exists`] method, this one doesn't silently ignore errors -/// unrelated to the path not existing. (E.g. it will return `Err(_)` in case of permission -/// denied on some of the parent directories.) +/// As opposed to the [`Path::exists`] method, this will only return `Ok(true)` or `Ok(false)` +/// if the path was _verified_ to exist or not exist. If its existence can neither be confirmed +/// nor denied, an `Err(_)` will be propagated instead. This can be the case if e.g. listing +/// permission is denied on one of the parent directories. /// /// Note that while this avoids some pitfalls of the `exists()` method, it still can not /// prevent time-of-check to time-of-use (TOCTOU) bugs. You should only use it in scenarios diff --git a/library/std/src/io/buffered/tests.rs b/library/std/src/io/buffered/tests.rs index 4c1b7d57684dd..35a5291a34769 100644 --- a/library/std/src/io/buffered/tests.rs +++ b/library/std/src/io/buffered/tests.rs @@ -831,9 +831,9 @@ fn partial_line_buffered_after_line_write() { assert_eq!(&writer.get_ref().buffer, b"Line 1\nLine 2\nLine 3"); } -/// Test that, given a partial line that exceeds the length of -/// LineBuffer's buffer (that is, without a trailing newline), that that -/// line is written to the inner writer +/// Test that for calls to LineBuffer::write where the passed bytes do not contain +/// a newline and on their own are greater in length than the internal buffer, the +/// passed bytes are immediately written to the inner writer. #[test] fn long_line_flushed() { let writer = ProgrammableSink::default(); @@ -844,9 +844,10 @@ fn long_line_flushed() { } /// Test that, given a very long partial line *after* successfully -/// flushing a complete line, that that line is buffered unconditionally, -/// and no additional writes take place. This assures the property that -/// `write` should make at-most-one attempt to write new data. +/// flushing a complete line, the very long partial line is buffered +/// unconditionally, and no additional writes take place. This assures +/// the property that `write` should make at-most-one attempt to write +/// new data. #[test] fn line_long_tail_not_flushed() { let writer = ProgrammableSink::default(); diff --git a/library/std/src/io/readbuf/tests.rs b/library/std/src/io/readbuf/tests.rs index cc1b423f2dd0d..89a2f6b2271bd 100644 --- a/library/std/src/io/readbuf/tests.rs +++ b/library/std/src/io/readbuf/tests.rs @@ -36,7 +36,7 @@ fn initialize_unfilled() { } #[test] -fn addvance_filled() { +fn advance_filled() { let buf: &mut [_] = &mut [0; 16]; let mut rbuf: BorrowedBuf<'_> = buf.into(); diff --git a/library/std/src/keyword_docs.rs b/library/std/src/keyword_docs.rs index 43842bee992a7..be6dc7768af94 100644 --- a/library/std/src/keyword_docs.rs +++ b/library/std/src/keyword_docs.rs @@ -1925,7 +1925,7 @@ mod type_keyword {} /// `unsafe_op_in_unsafe_fn` lint can be enabled to warn against that and require explicit unsafe /// blocks even inside `unsafe fn`. /// -/// See the [Rustnomicon] and the [Reference] for more information. +/// See the [Rustonomicon] and the [Reference] for more information. /// /// # Examples /// @@ -2129,7 +2129,7 @@ mod type_keyword {} /// [`impl`]: keyword.impl.html /// [raw pointers]: ../reference/types/pointer.html /// [memory safety]: ../book/ch19-01-unsafe-rust.html -/// [Rustnomicon]: ../nomicon/index.html +/// [Rustonomicon]: ../nomicon/index.html /// [nomicon-soundness]: ../nomicon/safe-unsafe-meaning.html /// [soundness]: https://rust-lang.github.io/unsafe-code-guidelines/glossary.html#soundness-of-code--of-a-library /// [Reference]: ../reference/unsafety.html diff --git a/library/std/src/os/fuchsia/raw.rs b/library/std/src/os/fuchsia/raw.rs index ea6b94f2f13c4..cb570beb8a1e7 100644 --- a/library/std/src/os/fuchsia/raw.rs +++ b/library/std/src/os/fuchsia/raw.rs @@ -286,3 +286,9 @@ mod arch { pub __unused: [c_long; 3], } } + +#[cfg(target_arch = "riscv64")] +mod arch { + #[stable(feature = "raw_ext", since = "1.1.0")] + pub use libc::{blkcnt_t, blksize_t, ino_t, nlink_t, off_t, stat, time_t}; +} diff --git a/library/std/src/os/windows/io/handle.rs b/library/std/src/os/windows/io/handle.rs index f6622874625fc..11948cecad853 100644 --- a/library/std/src/os/windows/io/handle.rs +++ b/library/std/src/os/windows/io/handle.rs @@ -450,7 +450,7 @@ impl AsHandle for OwnedHandle { #[inline] fn as_handle(&self) -> BorrowedHandle<'_> { // Safety: `OwnedHandle` and `BorrowedHandle` have the same validity - // invariants, and the `BorrowdHandle` is bounded by the lifetime + // invariants, and the `BorrowedHandle` is bounded by the lifetime // of `&self`. unsafe { BorrowedHandle::borrow_raw(self.as_raw_handle()) } } diff --git a/library/std/src/os/windows/io/socket.rs b/library/std/src/os/windows/io/socket.rs index 5c1634084a055..b6bd0f9e12bd4 100644 --- a/library/std/src/os/windows/io/socket.rs +++ b/library/std/src/os/windows/io/socket.rs @@ -260,7 +260,7 @@ impl AsSocket for OwnedSocket { #[inline] fn as_socket(&self) -> BorrowedSocket<'_> { // Safety: `OwnedSocket` and `BorrowedSocket` have the same validity - // invariants, and the `BorrowdSocket` is bounded by the lifetime + // invariants, and the `BorrowedSocket` is bounded by the lifetime // of `&self`. unsafe { BorrowedSocket::borrow_raw(self.as_raw_socket()) } } diff --git a/library/std/src/path.rs b/library/std/src/path.rs index 8014ba992eaf8..e5abd02a1bc53 100644 --- a/library/std/src/path.rs +++ b/library/std/src/path.rs @@ -2844,9 +2844,11 @@ impl Path { /// This function will traverse symbolic links to query information about the /// destination file. In case of broken symbolic links this will return `Ok(false)`. /// - /// As opposed to the [`exists()`] method, this one doesn't silently ignore errors - /// unrelated to the path not existing. (E.g. it will return `Err(_)` in case of permission - /// denied on some of the parent directories.) + /// [`Path::exists()`] only checks whether or not a path was both found and readable. By + /// contrast, `try_exists` will return `Ok(true)` or `Ok(false)`, respectively, if the path + /// was _verified_ to exist or not exist. If its existence can neither be confirmed nor + /// denied, it will propagate an `Err(_)` instead. This can be the case if e.g. listing + /// permission is denied on one of the parent directories. /// /// Note that while this avoids some pitfalls of the `exists()` method, it still can not /// prevent time-of-check to time-of-use (TOCTOU) bugs. You should only use it in scenarios diff --git a/library/std/src/sync/once_lock/tests.rs b/library/std/src/sync/once_lock/tests.rs index 46695225b9f5a..d5d32e73d8880 100644 --- a/library/std/src/sync/once_lock/tests.rs +++ b/library/std/src/sync/once_lock/tests.rs @@ -24,7 +24,7 @@ fn sync_once_cell() { assert_eq!(ONCE_CELL.get(), Some(&92)); }); - ONCE_CELL.get_or_init(|| panic!("Kabom!")); + ONCE_CELL.get_or_init(|| panic!("Kaboom!")); assert_eq!(ONCE_CELL.get(), Some(&92)); } diff --git a/library/std/src/sync/remutex.rs b/library/std/src/sync/remutex.rs index 519ec2c32bd5d..0ced48d10b7c6 100644 --- a/library/std/src/sync/remutex.rs +++ b/library/std/src/sync/remutex.rs @@ -7,7 +7,7 @@ use crate::panic::{RefUnwindSafe, UnwindSafe}; use crate::sync::atomic::{AtomicUsize, Ordering::Relaxed}; use crate::sys::locks as sys; -/// A re-entrant mutual exclusion +/// A reentrant mutual exclusion /// /// This mutex will block *other* threads waiting for the lock to become /// available. The thread which has already locked the mutex can lock it diff --git a/library/std/src/sys/common/thread_local/fast_local.rs b/library/std/src/sys/common/thread_local/fast_local.rs index e229eb16aa139..914e017f7ffaf 100644 --- a/library/std/src/sys/common/thread_local/fast_local.rs +++ b/library/std/src/sys/common/thread_local/fast_local.rs @@ -1,13 +1,14 @@ +use super::lazy::LazyKeyInner; +use crate::cell::Cell; +use crate::sys::thread_local_dtor::register_dtor; +use crate::{fmt, mem, panic}; + #[doc(hidden)] -#[macro_export] -#[allow_internal_unstable( - thread_local_internals, - cfg_target_thread_local, - thread_local, - libstd_thread_internals -)] +#[allow_internal_unstable(thread_local_internals, cfg_target_thread_local, thread_local)] #[allow_internal_unsafe] -macro_rules! __thread_local_inner { +#[unstable(feature = "thread_local_internals", issue = "none")] +#[rustc_macro_transparency = "semitransparent"] +pub macro thread_local_inner { // used to generate the `LocalKey` value for const-initialized thread locals (@key $t:ty, const $init:expr) => {{ #[cfg_attr(not(bootstrap), inline)] @@ -49,7 +50,7 @@ macro_rules! __thread_local_inner { // 0 == we haven't registered a destructor, so do // so now. 0 => { - $crate::thread::__LocalKeyInner::<$t>::register_dtor( + $crate::thread::local_impl::Key::<$t>::register_dtor( $crate::ptr::addr_of_mut!(VAL) as *mut $crate::primitive::u8, destroy, ); @@ -69,7 +70,7 @@ macro_rules! __thread_local_inner { unsafe { $crate::thread::LocalKey::new(__getit) } - }}; + }}, // used to generate the `LocalKey` value for `thread_local!` (@key $t:ty, $init:expr) => { @@ -82,8 +83,8 @@ macro_rules! __thread_local_inner { init: $crate::option::Option<&mut $crate::option::Option<$t>>, ) -> $crate::option::Option<&'static $t> { #[thread_local] - static __KEY: $crate::thread::__LocalKeyInner<$t> = - $crate::thread::__LocalKeyInner::<$t>::new(); + 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. @@ -107,148 +108,140 @@ macro_rules! __thread_local_inner { $crate::thread::LocalKey::new(__getit) } } - }; + }, ($(#[$attr:meta])* $vis:vis $name:ident, $t:ty, $($init:tt)*) => { $(#[$attr])* $vis const $name: $crate::thread::LocalKey<$t> = - $crate::__thread_local_inner!(@key $t, $($init)*); - } + $crate::thread::local_impl::thread_local_inner!(@key $t, $($init)*); + }, } -#[doc(hidden)] -pub mod fast { - use super::super::lazy::LazyKeyInner; - use crate::cell::Cell; - use crate::sys::thread_local_dtor::register_dtor; - use crate::{fmt, mem, panic}; - - #[derive(Copy, Clone)] - enum DtorState { - Unregistered, - Registered, - RunningOrHasRun, - } +#[derive(Copy, Clone)] +enum DtorState { + Unregistered, + Registered, + RunningOrHasRun, +} - // This data structure has been carefully constructed so that the fast path - // only contains one branch on x86. That optimization is necessary to avoid - // duplicated tls lookups on OSX. +// This data structure has been carefully constructed so that the fast path +// only contains one branch on x86. That optimization is necessary to avoid +// duplicated tls lookups on OSX. +// +// LLVM issue: https://bugs.llvm.org/show_bug.cgi?id=41722 +pub struct Key { + // If `LazyKeyInner::get` returns `None`, that indicates either: + // * The value has never been initialized + // * The value is being recursively initialized + // * The value has already been destroyed or is being destroyed + // To determine which kind of `None`, check `dtor_state`. // - // LLVM issue: https://bugs.llvm.org/show_bug.cgi?id=41722 - pub struct Key { - // If `LazyKeyInner::get` returns `None`, that indicates either: - // * The value has never been initialized - // * The value is being recursively initialized - // * The value has already been destroyed or is being destroyed - // To determine which kind of `None`, check `dtor_state`. - // - // This is very optimizer friendly for the fast path - initialized but - // not yet dropped. - inner: LazyKeyInner, + // This is very optimizer friendly for the fast path - initialized but + // not yet dropped. + inner: LazyKeyInner, - // Metadata to keep track of the state of the destructor. Remember that - // this variable is thread-local, not global. - dtor_state: Cell, - } + // Metadata to keep track of the state of the destructor. Remember that + // this variable is thread-local, not global. + dtor_state: Cell, +} - impl fmt::Debug for Key { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_struct("Key").finish_non_exhaustive() - } +impl fmt::Debug for Key { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("Key").finish_non_exhaustive() } +} - impl Key { - pub const fn new() -> Key { - Key { inner: LazyKeyInner::new(), dtor_state: Cell::new(DtorState::Unregistered) } - } +impl Key { + pub const fn new() -> Key { + Key { inner: LazyKeyInner::new(), dtor_state: Cell::new(DtorState::Unregistered) } + } - // note that this is just a publicly-callable function only for the - // const-initialized form of thread locals, basically a way to call the - // free `register_dtor` function defined elsewhere in std. - pub unsafe fn register_dtor(a: *mut u8, dtor: unsafe extern "C" fn(*mut u8)) { - unsafe { - register_dtor(a, dtor); - } + // note that this is just a publicly-callable function only for the + // const-initialized form of thread locals, basically a way to call the + // free `register_dtor` function defined elsewhere in std. + pub unsafe fn register_dtor(a: *mut u8, dtor: unsafe extern "C" fn(*mut u8)) { + unsafe { + register_dtor(a, dtor); } + } - pub unsafe fn get T>(&self, init: F) -> Option<&'static T> { - // SAFETY: See the definitions of `LazyKeyInner::get` and - // `try_initialize` for more information. - // - // The caller must ensure no mutable references are ever active to - // the inner cell or the inner T when this is called. - // The `try_initialize` is dependant on the passed `init` function - // for this. - unsafe { - match self.inner.get() { - Some(val) => Some(val), - None => self.try_initialize(init), - } + pub unsafe fn get T>(&self, init: F) -> Option<&'static T> { + // SAFETY: See the definitions of `LazyKeyInner::get` and + // `try_initialize` for more information. + // + // The caller must ensure no mutable references are ever active to + // the inner cell or the inner T when this is called. + // The `try_initialize` is dependant on the passed `init` function + // for this. + unsafe { + match self.inner.get() { + Some(val) => Some(val), + None => self.try_initialize(init), } } + } - // `try_initialize` is only called once per fast thread local variable, - // except in corner cases where thread_local dtors reference other - // thread_local's, or it is being recursively initialized. - // - // Macos: Inlining this function can cause two `tlv_get_addr` calls to - // be performed for every call to `Key::get`. - // LLVM issue: https://bugs.llvm.org/show_bug.cgi?id=41722 - #[inline(never)] - unsafe fn try_initialize T>(&self, init: F) -> Option<&'static T> { + // `try_initialize` is only called once per fast thread local variable, + // except in corner cases where thread_local dtors reference other + // thread_local's, or it is being recursively initialized. + // + // Macos: Inlining this function can cause two `tlv_get_addr` calls to + // be performed for every call to `Key::get`. + // LLVM issue: https://bugs.llvm.org/show_bug.cgi?id=41722 + #[inline(never)] + unsafe fn try_initialize T>(&self, init: F) -> Option<&'static T> { + // SAFETY: See comment above (this function doc). + if !mem::needs_drop::() || unsafe { self.try_register_dtor() } { // SAFETY: See comment above (this function doc). - if !mem::needs_drop::() || unsafe { self.try_register_dtor() } { - // SAFETY: See comment above (this function doc). - Some(unsafe { self.inner.initialize(init) }) - } else { - None - } + Some(unsafe { self.inner.initialize(init) }) + } else { + None } + } - // `try_register_dtor` is only called once per fast thread local - // variable, except in corner cases where thread_local dtors reference - // other thread_local's, or it is being recursively initialized. - unsafe fn try_register_dtor(&self) -> bool { - match self.dtor_state.get() { - DtorState::Unregistered => { - // SAFETY: dtor registration happens before initialization. - // Passing `self` as a pointer while using `destroy_value` - // is safe because the function will build a pointer to a - // Key, which is the type of self and so find the correct - // size. - unsafe { register_dtor(self as *const _ as *mut u8, destroy_value::) }; - self.dtor_state.set(DtorState::Registered); - true - } - DtorState::Registered => { - // recursively initialized - true - } - DtorState::RunningOrHasRun => false, + // `try_register_dtor` is only called once per fast thread local + // variable, except in corner cases where thread_local dtors reference + // other thread_local's, or it is being recursively initialized. + unsafe fn try_register_dtor(&self) -> bool { + match self.dtor_state.get() { + DtorState::Unregistered => { + // SAFETY: dtor registration happens before initialization. + // Passing `self` as a pointer while using `destroy_value` + // is safe because the function will build a pointer to a + // Key, which is the type of self and so find the correct + // size. + unsafe { register_dtor(self as *const _ as *mut u8, destroy_value::) }; + self.dtor_state.set(DtorState::Registered); + true } + DtorState::Registered => { + // recursively initialized + true + } + DtorState::RunningOrHasRun => false, } } +} - unsafe extern "C" fn destroy_value(ptr: *mut u8) { - let ptr = ptr as *mut Key; +unsafe extern "C" fn destroy_value(ptr: *mut u8) { + let ptr = ptr as *mut Key; - // SAFETY: - // - // The pointer `ptr` has been built just above and comes from - // `try_register_dtor` where it is originally a Key coming from `self`, - // making it non-NUL and of the correct type. - // - // Right before we run the user destructor be sure to set the - // `Option` to `None`, and `dtor_state` to `RunningOrHasRun`. This - // causes future calls to `get` to run `try_initialize_drop` again, - // which will now fail, and return `None`. - // - // Wrap the call in a catch to ensure unwinding is caught in the event - // a panic takes place in a destructor. - if let Err(_) = panic::catch_unwind(panic::AssertUnwindSafe(|| unsafe { - let value = (*ptr).inner.take(); - (*ptr).dtor_state.set(DtorState::RunningOrHasRun); - drop(value); - })) { - rtabort!("thread local panicked on drop"); - } + // SAFETY: + // + // The pointer `ptr` has been built just above and comes from + // `try_register_dtor` where it is originally a Key coming from `self`, + // making it non-NUL and of the correct type. + // + // Right before we run the user destructor be sure to set the + // `Option` to `None`, and `dtor_state` to `RunningOrHasRun`. This + // causes future calls to `get` to run `try_initialize_drop` again, + // which will now fail, and return `None`. + // + // Wrap the call in a catch to ensure unwinding is caught in the event + // a panic takes place in a destructor. + if let Err(_) = panic::catch_unwind(panic::AssertUnwindSafe(|| unsafe { + let value = (*ptr).inner.take(); + (*ptr).dtor_state.set(DtorState::RunningOrHasRun); + drop(value); + })) { + rtabort!("thread local panicked on drop"); } } diff --git a/library/std/src/sys/common/thread_local/mod.rs b/library/std/src/sys/common/thread_local/mod.rs index 1fee84a04349c..a7528c06c9de2 100644 --- a/library/std/src/sys/common/thread_local/mod.rs +++ b/library/std/src/sys/common/thread_local/mod.rs @@ -1,35 +1,24 @@ -//! The following module declarations are outside cfg_if because the internal -//! `__thread_local_internal` macro does not seem to be exported properly when using cfg_if #![unstable(feature = "thread_local_internals", reason = "should not be necessary", issue = "none")] -#[cfg(all(target_thread_local, not(all(target_family = "wasm", not(target_feature = "atomics")))))] -mod fast_local; -#[cfg(all( - not(target_thread_local), - not(all(target_family = "wasm", not(target_feature = "atomics"))) -))] -mod os_local; -#[cfg(all(target_family = "wasm", not(target_feature = "atomics")))] -mod static_local; - -#[cfg(not(test))] cfg_if::cfg_if! { if #[cfg(all(target_family = "wasm", not(target_feature = "atomics")))] { #[doc(hidden)] - pub use static_local::statik::Key; - } else if #[cfg(all(target_thread_local, not(all(target_family = "wasm", not(target_feature = "atomics")))))] { + mod static_local; + #[doc(hidden)] + pub use static_local::{Key, thread_local_inner}; + } else if #[cfg(all(target_thread_local))] { + #[doc(hidden)] + mod fast_local; #[doc(hidden)] - pub use fast_local::fast::Key; - } else if #[cfg(all(not(target_thread_local), not(all(target_family = "wasm", not(target_feature = "atomics")))))] { + pub use fast_local::{Key, thread_local_inner}; + } else { #[doc(hidden)] - pub use os_local::os::Key; + mod os_local; + #[doc(hidden)] + pub use os_local::{Key, thread_local_inner}; } } -#[doc(hidden)] -#[cfg(test)] -pub use realstd::thread::__LocalKeyInner as Key; - mod lazy { use crate::cell::UnsafeCell; use crate::hint; 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 1442a397e767e..e9516f9983f2a 100644 --- a/library/std/src/sys/common/thread_local/os_local.rs +++ b/library/std/src/sys/common/thread_local/os_local.rs @@ -1,13 +1,14 @@ +use super::lazy::LazyKeyInner; +use crate::cell::Cell; +use crate::sys_common::thread_local_key::StaticKey as OsStaticKey; +use crate::{fmt, marker, panic, ptr}; + #[doc(hidden)] -#[macro_export] -#[allow_internal_unstable( - thread_local_internals, - cfg_target_thread_local, - thread_local, - libstd_thread_internals -)] +#[allow_internal_unstable(thread_local_internals)] #[allow_internal_unsafe] -macro_rules! __thread_local_inner { +#[unstable(feature = "thread_local_internals", issue = "none")] +#[rustc_macro_transparency = "semitransparent"] +pub macro thread_local_inner { // used to generate the `LocalKey` value for const-initialized thread locals (@key $t:ty, const $init:expr) => {{ #[cfg_attr(not(bootstrap), inline)] @@ -21,8 +22,8 @@ macro_rules! __thread_local_inner { // same implementation as below for os thread locals. #[inline] const fn __init() -> $t { INIT_EXPR } - static __KEY: $crate::thread::__LocalKeyInner<$t> = - $crate::thread::__LocalKeyInner::new(); + static __KEY: $crate::thread::local_impl::Key<$t> = + $crate::thread::local_impl::Key::new(); #[allow(unused_unsafe)] unsafe { __KEY.get(move || { @@ -41,7 +42,7 @@ macro_rules! __thread_local_inner { unsafe { $crate::thread::LocalKey::new(__getit) } - }}; + }}, // used to generate the `LocalKey` value for `thread_local!` (@key $t:ty, $init:expr) => { @@ -55,8 +56,8 @@ macro_rules! __thread_local_inner { unsafe fn __getit( init: $crate::option::Option<&mut $crate::option::Option<$t>>, ) -> $crate::option::Option<&'static $t> { - static __KEY: $crate::thread::__LocalKeyInner<$t> = - $crate::thread::__LocalKeyInner::new(); + 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. @@ -80,118 +81,110 @@ macro_rules! __thread_local_inner { $crate::thread::LocalKey::new(__getit) } } - }; + }, ($(#[$attr:meta])* $vis:vis $name:ident, $t:ty, $($init:tt)*) => { $(#[$attr])* $vis const $name: $crate::thread::LocalKey<$t> = - $crate::__thread_local_inner!(@key $t, $($init)*); - } + $crate::thread::local_impl::thread_local_inner!(@key $t, $($init)*); + }, } -#[doc(hidden)] -pub mod os { - use super::super::lazy::LazyKeyInner; - use crate::cell::Cell; - use crate::sys_common::thread_local_key::StaticKey as OsStaticKey; - use crate::{fmt, marker, panic, ptr}; - - /// Use a regular global static to store this key; the state provided will then be - /// thread-local. - pub struct Key { - // OS-TLS key that we'll use to key off. - os: OsStaticKey, - marker: marker::PhantomData>, - } +/// Use a regular global static to store this key; the state provided will then be +/// thread-local. +pub struct Key { + // OS-TLS key that we'll use to key off. + os: OsStaticKey, + marker: marker::PhantomData>, +} - impl fmt::Debug for Key { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_struct("Key").finish_non_exhaustive() - } +impl fmt::Debug for Key { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("Key").finish_non_exhaustive() } +} - unsafe impl Sync for Key {} +unsafe impl Sync for Key {} - struct Value { - inner: LazyKeyInner, - key: &'static Key, +struct Value { + inner: LazyKeyInner, + key: &'static Key, +} + +impl Key { + #[rustc_const_unstable(feature = "thread_local_internals", issue = "none")] + pub const fn new() -> Key { + Key { os: OsStaticKey::new(Some(destroy_value::)), marker: marker::PhantomData } } - impl Key { - #[rustc_const_unstable(feature = "thread_local_internals", issue = "none")] - pub const fn new() -> Key { - Key { os: OsStaticKey::new(Some(destroy_value::)), marker: marker::PhantomData } + /// It is a requirement for the caller to ensure that no mutable + /// reference is active when this method is called. + pub unsafe fn get(&'static self, init: impl FnOnce() -> T) -> Option<&'static T> { + // SAFETY: See the documentation for this method. + let ptr = unsafe { self.os.get() as *mut Value }; + if ptr.addr() > 1 { + // SAFETY: the check ensured the pointer is safe (its destructor + // is not running) + it is coming from a trusted source (self). + if let Some(ref value) = unsafe { (*ptr).inner.get() } { + return Some(value); + } } + // SAFETY: At this point we are sure we have no value and so + // initializing (or trying to) is safe. + unsafe { self.try_initialize(init) } + } - /// It is a requirement for the caller to ensure that no mutable - /// reference is active when this method is called. - pub unsafe fn get(&'static self, init: impl FnOnce() -> T) -> Option<&'static T> { - // SAFETY: See the documentation for this method. - let ptr = unsafe { self.os.get() as *mut Value }; - if ptr.addr() > 1 { - // SAFETY: the check ensured the pointer is safe (its destructor - // is not running) + it is coming from a trusted source (self). - if let Some(ref value) = unsafe { (*ptr).inner.get() } { - return Some(value); - } - } - // SAFETY: At this point we are sure we have no value and so - // initializing (or trying to) is safe. - unsafe { self.try_initialize(init) } + // `try_initialize` is only called once per os thread local variable, + // except in corner cases where thread_local dtors reference other + // thread_local's, or it is being recursively initialized. + unsafe fn try_initialize(&'static self, init: impl FnOnce() -> T) -> Option<&'static T> { + // SAFETY: No mutable references are ever handed out meaning getting + // the value is ok. + let ptr = unsafe { self.os.get() as *mut Value }; + if ptr.addr() == 1 { + // destructor is running + return None; } - // `try_initialize` is only called once per os thread local variable, - // except in corner cases where thread_local dtors reference other - // thread_local's, or it is being recursively initialized. - unsafe fn try_initialize(&'static self, init: impl FnOnce() -> T) -> Option<&'static T> { - // SAFETY: No mutable references are ever handed out meaning getting - // the value is ok. - let ptr = unsafe { self.os.get() as *mut Value }; - if ptr.addr() == 1 { - // destructor is running - return None; + let ptr = if ptr.is_null() { + // If the lookup returned null, we haven't initialized our own + // local copy, so do that now. + let ptr = Box::into_raw(Box::new(Value { inner: LazyKeyInner::new(), key: self })); + // SAFETY: At this point we are sure there is no value inside + // ptr so setting it will not affect anyone else. + unsafe { + self.os.set(ptr as *mut u8); } - - let ptr = if ptr.is_null() { - // If the lookup returned null, we haven't initialized our own - // local copy, so do that now. - let ptr = Box::into_raw(Box::new(Value { inner: LazyKeyInner::new(), key: self })); - // SAFETY: At this point we are sure there is no value inside - // ptr so setting it will not affect anyone else. - unsafe { - self.os.set(ptr as *mut u8); - } - ptr - } else { - // recursive initialization - ptr - }; - - // SAFETY: ptr has been ensured as non-NUL just above an so can be - // dereferenced safely. - unsafe { Some((*ptr).inner.initialize(init)) } - } + ptr + } else { + // recursive initialization + ptr + }; + + // SAFETY: ptr has been ensured as non-NUL just above an so can be + // dereferenced safely. + unsafe { Some((*ptr).inner.initialize(init)) } } +} - unsafe extern "C" fn destroy_value(ptr: *mut u8) { - // SAFETY: - // - // The OS TLS ensures that this key contains a null value when this - // destructor starts to run. We set it back to a sentinel value of 1 to - // ensure that any future calls to `get` for this thread will return - // `None`. - // - // Note that to prevent an infinite loop we reset it back to null right - // before we return from the destructor ourselves. - // - // Wrap the call in a catch to ensure unwinding is caught in the event - // a panic takes place in a destructor. - if let Err(_) = panic::catch_unwind(|| unsafe { - let ptr = Box::from_raw(ptr as *mut Value); - let key = ptr.key; - key.os.set(ptr::invalid_mut(1)); - drop(ptr); - key.os.set(ptr::null_mut()); - }) { - rtabort!("thread local panicked on drop"); - } +unsafe extern "C" fn destroy_value(ptr: *mut u8) { + // SAFETY: + // + // The OS TLS ensures that this key contains a null value when this + // destructor starts to run. We set it back to a sentinel value of 1 to + // ensure that any future calls to `get` for this thread will return + // `None`. + // + // Note that to prevent an infinite loop we reset it back to null right + // before we return from the destructor ourselves. + // + // Wrap the call in a catch to ensure unwinding is caught in the event + // a panic takes place in a destructor. + if let Err(_) = panic::catch_unwind(|| unsafe { + let ptr = Box::from_raw(ptr as *mut Value); + let key = ptr.key; + key.os.set(ptr::invalid_mut(1)); + drop(ptr); + key.os.set(ptr::null_mut()); + }) { + rtabort!("thread local panicked on drop"); } } 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 ec4f2a12b7ee4..80322a978646b 100644 --- a/library/std/src/sys/common/thread_local/static_local.rs +++ b/library/std/src/sys/common/thread_local/static_local.rs @@ -1,13 +1,12 @@ +use super::lazy::LazyKeyInner; +use crate::fmt; + #[doc(hidden)] -#[macro_export] -#[allow_internal_unstable( - thread_local_internals, - cfg_target_thread_local, - thread_local, - libstd_thread_internals -)] +#[allow_internal_unstable(thread_local_internals)] #[allow_internal_unsafe] -macro_rules! __thread_local_inner { +#[unstable(feature = "thread_local_internals", issue = "none")] +#[rustc_macro_transparency = "semitransparent"] +pub macro thread_local_inner { // used to generate the `LocalKey` value for const-initialized thread locals (@key $t:ty, const $init:expr) => {{ #[inline] // see comments below @@ -30,7 +29,7 @@ macro_rules! __thread_local_inner { unsafe { $crate::thread::LocalKey::new(__getit) } - }}; + }}, // used to generate the `LocalKey` value for `thread_local!` (@key $t:ty, $init:expr) => { @@ -41,8 +40,8 @@ macro_rules! __thread_local_inner { unsafe fn __getit( init: $crate::option::Option<&mut $crate::option::Option<$t>>, ) -> $crate::option::Option<&'static $t> { - static __KEY: $crate::thread::__LocalKeyInner<$t> = - $crate::thread::__LocalKeyInner::new(); + 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. @@ -66,50 +65,45 @@ macro_rules! __thread_local_inner { $crate::thread::LocalKey::new(__getit) } } - }; + }, ($(#[$attr:meta])* $vis:vis $name:ident, $t:ty, $($init:tt)*) => { $(#[$attr])* $vis const $name: $crate::thread::LocalKey<$t> = - $crate::__thread_local_inner!(@key $t, $($init)*); - } + $crate::thread::local_impl::thread_local_inner!(@key $t, $($init)*); + }, } /// On some targets like wasm there's no threads, so no need to generate /// thread locals and we can instead just use plain statics! -#[doc(hidden)] -pub mod statik { - use super::super::lazy::LazyKeyInner; - use crate::fmt; - pub struct Key { - inner: LazyKeyInner, - } +pub struct Key { + inner: LazyKeyInner, +} - unsafe impl Sync for Key {} +unsafe impl Sync for Key {} - impl fmt::Debug for Key { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_struct("Key").finish_non_exhaustive() - } +impl fmt::Debug for Key { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("Key").finish_non_exhaustive() } +} - impl Key { - pub const fn new() -> Key { - Key { inner: LazyKeyInner::new() } - } +impl Key { + pub const fn new() -> Key { + Key { inner: LazyKeyInner::new() } + } - pub unsafe fn get(&self, init: impl FnOnce() -> T) -> Option<&'static T> { - // SAFETY: The caller must ensure no reference is ever handed out to - // the inner cell nor mutable reference to the Option inside said - // cell. This make it safe to hand a reference, though the lifetime - // of 'static is itself unsafe, making the get method unsafe. - let value = unsafe { - match self.inner.get() { - Some(ref value) => value, - None => self.inner.initialize(init), - } - }; + pub unsafe fn get(&self, init: impl FnOnce() -> T) -> Option<&'static T> { + // SAFETY: The caller must ensure no reference is ever handed out to + // the inner cell nor mutable reference to the Option inside said + // cell. This make it safe to hand a reference, though the lifetime + // of 'static is itself unsafe, making the get method unsafe. + let value = unsafe { + match self.inner.get() { + Some(ref value) => value, + None => self.inner.initialize(init), + } + }; - Some(value) - } + Some(value) } } diff --git a/library/std/src/sys/sgx/abi/entry.S b/library/std/src/sys/sgx/abi/entry.S index f61bcf06f0815..ca79d1d796e9a 100644 --- a/library/std/src/sys/sgx/abi/entry.S +++ b/library/std/src/sys/sgx/abi/entry.S @@ -58,7 +58,7 @@ IMAGE_BASE: globvar DEBUG 1 /* The base address (relative to enclave start) of the enclave text section */ globvar TEXT_BASE 8 - /* The size in bytes of enclacve text section */ + /* The size in bytes of enclave text section */ globvar TEXT_SIZE 8 /* The base address (relative to enclave start) of the enclave .eh_frame_hdr section */ globvar EH_FRM_HDR_OFFSET 8 @@ -66,7 +66,7 @@ IMAGE_BASE: globvar EH_FRM_HDR_LEN 8 /* The base address (relative to enclave start) of the enclave .eh_frame section */ globvar EH_FRM_OFFSET 8 - /* The size in bytes of enclacve .eh_frame section */ + /* The size in bytes of enclave .eh_frame section */ globvar EH_FRM_LEN 8 .org .Lxsave_clear+512 diff --git a/library/std/src/sys/unix/process/process_unix.rs b/library/std/src/sys/unix/process/process_unix.rs index ceaff59668460..612d43fe20414 100644 --- a/library/std/src/sys/unix/process/process_unix.rs +++ b/library/std/src/sys/unix/process/process_unix.rs @@ -735,7 +735,7 @@ impl ExitStatus { // true on all actual versions of Unix, is widely assumed, and is specified in SuS // https://pubs.opengroup.org/onlinepubs/9699919799/functions/wait.html. If it is not // true for a platform pretending to be Unix, the tests (our doctests, and also - // procsss_unix/tests.rs) will spot it. `ExitStatusError::code` assumes this too. + // process_unix/tests.rs) will spot it. `ExitStatusError::code` assumes this too. match NonZero_c_int::try_from(self.0) { /* was nonzero */ Ok(failure) => Err(ExitStatusError(failure)), /* was zero, couldn't convert */ Err(_) => Ok(()), diff --git a/library/std/src/sys/unix/process/process_vxworks.rs b/library/std/src/sys/unix/process/process_vxworks.rs index 569a4b149125d..c40e7ada03cbd 100644 --- a/library/std/src/sys/unix/process/process_vxworks.rs +++ b/library/std/src/sys/unix/process/process_vxworks.rs @@ -199,7 +199,7 @@ impl ExitStatus { // true on all actual versions of Unix, is widely assumed, and is specified in SuS // https://pubs.opengroup.org/onlinepubs/9699919799/functions/wait.html. If it is not // true for a platform pretending to be Unix, the tests (our doctests, and also - // procsss_unix/tests.rs) will spot it. `ExitStatusError::code` assumes this too. + // process_unix/tests.rs) will spot it. `ExitStatusError::code` assumes this too. match NonZero_c_int::try_from(self.0) { Ok(failure) => Err(ExitStatusError(failure)), Err(_) => Ok(()), diff --git a/library/std/src/sys/wasi/mod.rs b/library/std/src/sys/wasi/mod.rs index 1dc3f2b20266d..c468ae395fc8d 100644 --- a/library/std/src/sys/wasi/mod.rs +++ b/library/std/src/sys/wasi/mod.rs @@ -32,8 +32,6 @@ pub mod io; #[path = "../unsupported/locks/mod.rs"] pub mod locks; pub mod net; -#[path = "../unsupported/once.rs"] -pub mod once; pub mod os; #[path = "../unix/os_str.rs"] pub mod os_str; @@ -51,6 +49,13 @@ pub mod thread_local_dtor; pub mod thread_local_key; pub mod time; +cfg_if::cfg_if! { + if #[cfg(not(target_feature = "atomics"))] { + #[path = "../unsupported/once.rs"] + pub mod once; + } +} + #[path = "../unsupported/common.rs"] #[deny(unsafe_op_in_unsafe_fn)] #[allow(unused)] diff --git a/library/std/src/thread/local.rs b/library/std/src/thread/local.rs index 7fdf03acc14d9..fa08fdc16530b 100644 --- a/library/std/src/thread/local.rs +++ b/library/std/src/thread/local.rs @@ -153,23 +153,23 @@ macro_rules! thread_local { () => {}; ($(#[$attr:meta])* $vis:vis static $name:ident: $t:ty = const { $init:expr }; $($rest:tt)*) => ( - $crate::__thread_local_inner!($(#[$attr])* $vis $name, $t, const $init); + $crate::thread::local_impl::thread_local_inner!($(#[$attr])* $vis $name, $t, const $init); $crate::thread_local!($($rest)*); ); ($(#[$attr:meta])* $vis:vis static $name:ident: $t:ty = const { $init:expr }) => ( - $crate::__thread_local_inner!($(#[$attr])* $vis $name, $t, const $init); + $crate::thread::local_impl::thread_local_inner!($(#[$attr])* $vis $name, $t, const $init); ); // process multiple declarations ($(#[$attr:meta])* $vis:vis static $name:ident: $t:ty = $init:expr; $($rest:tt)*) => ( - $crate::__thread_local_inner!($(#[$attr])* $vis $name, $t, $init); + $crate::thread::local_impl::thread_local_inner!($(#[$attr])* $vis $name, $t, $init); $crate::thread_local!($($rest)*); ); // handle a single declaration ($(#[$attr:meta])* $vis:vis static $name:ident: $t:ty = $init:expr) => ( - $crate::__thread_local_inner!($(#[$attr])* $vis $name, $t, $init); + $crate::thread::local_impl::thread_local_inner!($(#[$attr])* $vis $name, $t, $init); ); } diff --git a/library/std/src/thread/mod.rs b/library/std/src/thread/mod.rs index 13b845b25c92d..9cdc17a287c96 100644 --- a/library/std/src/thread/mod.rs +++ b/library/std/src/thread/mod.rs @@ -204,9 +204,12 @@ pub use self::local::{AccessError, LocalKey}; // by the elf linker. "static" is for single-threaded platforms where a global // static is sufficient. +// Implementation details used by the thread_local!{} macro. #[doc(hidden)] -#[unstable(feature = "libstd_thread_internals", issue = "none")] -pub use crate::sys::common::thread_local::Key as __LocalKeyInner; +#[unstable(feature = "thread_local_internals", issue = "none")] +pub mod local_impl { + pub use crate::sys::common::thread_local::{thread_local_inner, Key}; +} //////////////////////////////////////////////////////////////////////////////// // Builder @@ -494,7 +497,7 @@ impl Builder { MaybeDangling(mem::MaybeUninit::new(x)) } fn into_inner(self) -> T { - // SAFETY: we are always initiailized. + // SAFETY: we are always initialized. let ret = unsafe { self.0.assume_init_read() }; // Make sure we don't drop. mem::forget(self); @@ -503,7 +506,7 @@ impl Builder { } impl Drop for MaybeDangling { fn drop(&mut self) { - // SAFETY: we are always initiailized. + // SAFETY: we are always initialized. unsafe { self.0.assume_init_drop() }; } } diff --git a/src/ci/docker/host-x86_64/dist-x86_64-linux/build-gcc.sh b/src/ci/docker/host-x86_64/dist-x86_64-linux/build-gcc.sh index 41ca1385c75d1..6da3f89220e23 100755 --- a/src/ci/docker/host-x86_64/dist-x86_64-linux/build-gcc.sh +++ b/src/ci/docker/host-x86_64/dist-x86_64-linux/build-gcc.sh @@ -22,8 +22,7 @@ cd gcc-$GCC # latter host is presented to `wget`! Therefore, we choose to download from the insecure HTTP server # instead here. # -# FIXME: use HTTPS (see https://github.com/rust-lang/rust/pull/86586#issuecomment-868355356) -sed -i'' 's|ftp://gcc\.gnu\.org/|http://gcc.gnu.org/|g' ./contrib/download_prerequisites +sed -i'' 's|ftp://gcc\.gnu\.org/|https://gcc.gnu.org/|g' ./contrib/download_prerequisites ./contrib/download_prerequisites mkdir ../gcc-build diff --git a/src/ci/github-actions/ci.yml b/src/ci/github-actions/ci.yml index 8c7798aad8bdf..8409b9ca56993 100644 --- a/src/ci/github-actions/ci.yml +++ b/src/ci/github-actions/ci.yml @@ -82,7 +82,7 @@ x--expand-yaml-anchors--remove: <<: *base-job - &job-macos-xl - os: macos-12-xl + os: macos-latest # We use the standard runner for now <<: *base-job - &job-windows-8c diff --git a/src/doc/rustdoc/src/SUMMARY.md b/src/doc/rustdoc/src/SUMMARY.md index 747cc629ba44b..b512135d92770 100644 --- a/src/doc/rustdoc/src/SUMMARY.md +++ b/src/doc/rustdoc/src/SUMMARY.md @@ -3,6 +3,7 @@ - [What is rustdoc?](what-is-rustdoc.md) - [Command-line arguments](command-line-arguments.md) - [How to read rustdoc output](how-to-read-rustdoc.md) + - [In-doc settings](read-documentation/in-doc-settings.md) - [How to write documentation](how-to-write-documentation.md) - [What to include (and exclude)](write-documentation/what-to-include.md) - [The `#[doc]` attribute](write-documentation/the-doc-attribute.md) diff --git a/src/doc/rustdoc/src/how-to-read-rustdoc.md b/src/doc/rustdoc/src/how-to-read-rustdoc.md index 56342f65d9998..ccd77fb17e938 100644 --- a/src/doc/rustdoc/src/how-to-read-rustdoc.md +++ b/src/doc/rustdoc/src/how-to-read-rustdoc.md @@ -43,7 +43,7 @@ including automatic and blanket implementations that `rustdoc` knows about. Subheadings, variants, fields, and many other things in this documentation are anchors and can be clicked on and deep-linked to, which is a great way to communicate exactly what you're talking about. -The typograpical character "§" appears next to lines with anchors on them +The typographical character "§" appears next to lines with anchors on them when hovered or given keyboard focus. ## The Navigation Bar @@ -68,7 +68,7 @@ Typing in the search bar instantly searches the available documentation for the string entered with a fuzzy matching algorithm that is tolerant of minor typos. -By default, the search results give are "In Names", +By default, the search results given are "In Names", meaning that the fuzzy match is made against the names of items. Matching names are shown on the left, and the first few words of their descriptions are given on the right. @@ -105,11 +105,6 @@ will match these queries: But it *does not* match `Result` or `Result>`. -### Changing displayed theme - -You can change the displayed theme by opening the settings menu (the gear -icon in the upper right) and then pick a new one from there. - ### Shortcuts Pressing `S` while focused elsewhere on the page will move focus to the diff --git a/src/doc/rustdoc/src/images/collapsed-long-item.png b/src/doc/rustdoc/src/images/collapsed-long-item.png new file mode 100644 index 0000000000000..c382870c64a65 Binary files /dev/null and b/src/doc/rustdoc/src/images/collapsed-long-item.png differ diff --git a/src/doc/rustdoc/src/images/collapsed-trait-impls.png b/src/doc/rustdoc/src/images/collapsed-trait-impls.png new file mode 100644 index 0000000000000..f685656e09a9c Binary files /dev/null and b/src/doc/rustdoc/src/images/collapsed-trait-impls.png differ diff --git a/src/doc/rustdoc/src/read-documentation/in-doc-settings.md b/src/doc/rustdoc/src/read-documentation/in-doc-settings.md new file mode 100644 index 0000000000000..12928a4f36926 --- /dev/null +++ b/src/doc/rustdoc/src/read-documentation/in-doc-settings.md @@ -0,0 +1,64 @@ +# Rustdoc in-doc settings + +Rustdoc's HTML output includes a settings menu, and this chapter describes what +each setting in this menu does. + +It can be accessed by clicking on the gear button +() in the upper right. + +## Changing displayed theme + +It is possible to change the theme. If you pick the "system preference", you +will be able to see two new sub-menus: "Preferred light theme" and "Preferred +dark theme". It means that if your system preference is set to "light", then +rustdoc will use the theme you selected in "Preferred light theme". + +## Auto-hide item contents for large items + +If the type definition contains more than 12 items, and this setting is enabled, +it'll collapse them by default. You can see them by clicking on the `[+]` button +to expand them. + +A good example of this setting in use can be seen in the +[`Iterator`](https://doc.rust-lang.org/stable/std/iter/trait.Iterator.html) doc +page: + +![Collapsed long item](../images/collapsed-long-item.png) + +## Auto-hide item methods' documentation + +If enabled, this setting will collapse all trait implementations blocks. It is +convenient if you just want an overview of all the methods available. You can +still see a method's documentation by expanding it. + +## Auto-hide trait implementation documentation + +If enabled, this setting will collapse all trait implementations blocks (you can +see them in the "Trait Implementations" section). It is convenient if you just +want an overview of all the trait implemented on a type. You can still see +a trait implementation's associated items by expanding it. + +Example: + +![Collapsed trait implementations](../images/collapsed-trait-impls.png) + +## Directly go to item in search if there is only one result + +If this setting is enabled, you will directly be taken to the result page if +your search only returned one element. Useful if you know exactly what you're +looking for and want to be taken there directly and not waste time selecting the +only search result. + +## Show line numbers on code examples + +If enabled, this setting will add line numbers to the code examples in the +documentation. It provides a visual aide for the code reading. + +## Disable keyboard shortcuts + +If this setting is enabled, the keyboard shortcuts will be disabled. It's useful +in case some of these shortcuts are already used by a web extension you're +using. + +To see the full list of the rustdoc keyboard shortcuts, you can open the help +menu (the button with the question mark on the left of the setting menu button). diff --git a/src/doc/rustdoc/src/references.md b/src/doc/rustdoc/src/references.md index 45cf4e88eef6b..2e0cb1c0af4cd 100644 --- a/src/doc/rustdoc/src/references.md +++ b/src/doc/rustdoc/src/references.md @@ -13,15 +13,15 @@ If you know of other great resources, please submit a pull request! ## Community - [API Guidelines] -- [Github tagged RFCs] -- [Github tagged issues] +- [GitHub tagged RFCs] +- [GitHub tagged issues] - [RFC (stalled) front page styleguide] - [Guide on how to write documentation for a Rust crate] [API Guidelines]: https://rust-lang.github.io/api-guidelines/documentation.html -[Github tagged RFCs]: https://github.com/rust-lang/rfcs/issues?q=label%3AT-rustdoc -[Github tagged issues]: https://github.com/rust-lang/rust/issues?q=is%3Aissue+is%3Aopen+label%3AT-rustdoc +[GitHub tagged RFCs]: https://github.com/rust-lang/rfcs/issues?q=label%3AT-rustdoc +[GitHub tagged issues]: https://github.com/rust-lang/rust/issues?q=is%3Aissue+is%3Aopen+label%3AT-rustdoc [Guide on how to write documentation for a Rust crate]: https://blog.guillaume-gomez.fr/articles/2020-03-12+Guide+on+how+to+write+documentation+for+a+Rust+crate [Learn Rust]: https://doc.rust-lang.org/book/ch14-02-publishing-to-crates-io.html#making-useful-documentation-comments [RFC 1574: More API Documentation Conventions]: https://rust-lang.github.io/rfcs/1574-more-api-documentation-conventions.html diff --git a/src/doc/style-guide/src/statements.md b/src/doc/style-guide/src/statements.md index 4ab1c36f97652..671e6d31a5775 100644 --- a/src/doc/style-guide/src/statements.md +++ b/src/doc/style-guide/src/statements.md @@ -138,18 +138,31 @@ Otherwise, the `else` keyword and opening brace should be placed on the next lin For example: ```rust -let Some(x) = abcdef() - .foo( - "abc", - some_really_really_really_long_ident, - "ident", - "123456", - ) - .bar() - .baz() - .qux("fffffffffffffffff") -else { - foo_bar() +fn main() { + let Some(x) = abcdef() + .foo( + "abc", + some_really_really_really_long_ident, + "ident", + "123456", + ) + .bar() + .baz() + .qux("fffffffffffffffff") + else { + return + }; + + let Some(x) = some_really_really_really_really_really_really_really_really_really_long_name + else { + return; + }; + + let Some(aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa) = + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb + else { + return; + }; } ``` diff --git a/src/doc/unstable-book/src/language-features/asm-experimental-arch.md b/src/doc/unstable-book/src/language-features/asm-experimental-arch.md index 1f52ab75010e6..1874baa0c385a 100644 --- a/src/doc/unstable-book/src/language-features/asm-experimental-arch.md +++ b/src/doc/unstable-book/src/language-features/asm-experimental-arch.md @@ -17,6 +17,7 @@ This feature tracks `asm!` and `global_asm!` support for the following architect - AVR - MSP430 - M68k +- LoongArch ## Register classes @@ -45,6 +46,8 @@ This feature tracks `asm!` and `global_asm!` support for the following architect | M68k | `reg` | `d[0-7]`, `a[0-7]` | `r` | | M68k | `reg_data` | `d[0-7]` | `d` | | M68k | `reg_addr` | `a[0-3]` | `a` | +| LoongArch | `reg` | `$r1`, `$r[4-20]`, `$r[23,30]` | `r` | +| LoongArch | `freg` | `$f[0-31]` | `f` | > **Notes**: > - NVPTX doesn't have a fixed register set, so named registers are not supported. @@ -76,6 +79,8 @@ This feature tracks `asm!` and `global_asm!` support for the following architect | MSP430 | `reg` | None | `i8`, `i16` | | M68k | `reg`, `reg_addr` | None | `i16`, `i32` | | M68k | `reg_data` | None | `i8`, `i16`, `i32` | +| LoongArch64 | `reg` | None | `i8`, `i16`, `i32`, `i64`, `f32`, `f64` | +| LoongArch64 | `freg` | None | `f32`, `f64` | ## Register aliases @@ -97,6 +102,10 @@ This feature tracks `asm!` and `global_asm!` support for the following architect | M68k | `a5` | `bp` | | M68k | `a6` | `fp` | | M68k | `a7` | `sp`, `usp`, `ssp`, `isp` | +| LoongArch | `$r0` | `zero` | +| LoongArch | `$r2` | `tp` | +| LoongArch | `$r3` | `sp` | +| LoongArch | `$r22` | `fp` | > **Notes**: > - TI does not mandate a frame pointer for MSP430, but toolchains are allowed @@ -107,7 +116,7 @@ This feature tracks `asm!` and `global_asm!` support for the following architect | Architecture | Unsupported register | Reason | | ------------ | --------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | All | `sp` | The stack pointer must be restored to its original value at the end of an asm code block. | -| All | `fr` (Hexagon), `$fp` (MIPS), `Y` (AVR), `r4` (MSP430), `a6` (M68k) | The frame pointer cannot be used as an input or output. | +| All | `fr` (Hexagon), `$fp` (MIPS), `Y` (AVR), `r4` (MSP430), `a6` (M68k), `$fp` (LoongArch) | The frame pointer cannot be used as an input or output. | | All | `r19` (Hexagon) | This is used internally by LLVM as a "base pointer" for functions with complex stack frames. | | MIPS | `$0` or `$zero` | This is a constant zero register which can't be modified. | | MIPS | `$1` or `$at` | Reserved for assembler. | @@ -118,6 +127,10 @@ This feature tracks `asm!` and `global_asm!` support for the following architect | AVR | `r0`, `r1`, `r1r0` | Due to an issue in LLVM, the `r0` and `r1` registers cannot be used as inputs or outputs. If modified, they must be restored to their original values before the end of the block. | |MSP430 | `r0`, `r2`, `r3` | These are the program counter, status register, and constant generator respectively. Neither the status register nor constant generator can be written to. | | M68k | `a4`, `a5` | Used internally by LLVM for the base pointer and global base pointer. | +| LoongArch | `$r0` or `$zero` | This is a constant zero register which can't be modified. | +| LoongArch | `$r2` or `$tp` | This is reserved for TLS. | +| LoongArch | `$r21` | This is reserved by the ABI. | +| LoongArch | `$r31` or `$s8` | This is used internally by LLVM. | ## Template modifiers @@ -132,6 +145,8 @@ This feature tracks `asm!` and `global_asm!` support for the following architect | PowerPC | `reg` | None | `0` | None | | PowerPC | `reg_nonzero` | None | `3` | `b` | | PowerPC | `freg` | None | `0` | None | +| LoongArch | `reg` | None | `$r2` | None | +| LoongArch | `freg` | None | `$f0` | None | # Flags covered by `preserves_flags` diff --git a/src/doc/unstable-book/src/library-features/libstd-thread-internals.md b/src/doc/unstable-book/src/library-features/libstd-thread-internals.md deleted file mode 100644 index b682d12e7cdd1..0000000000000 --- a/src/doc/unstable-book/src/library-features/libstd-thread-internals.md +++ /dev/null @@ -1,5 +0,0 @@ -# `libstd_thread_internals` - -This feature is internal to the Rust compiler and is not intended for general use. - ------------------------- diff --git a/src/librustdoc/clean/auto_trait.rs b/src/librustdoc/clean/auto_trait.rs index eeee12a431065..1b622905e1adb 100644 --- a/src/librustdoc/clean/auto_trait.rs +++ b/src/librustdoc/clean/auto_trait.rs @@ -741,8 +741,10 @@ impl<'a, 'tcx> TypeFolder> for RegionReplacer<'a, 'tcx> { fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> { match *r { + // These are the regions that can be seen in the AST. ty::ReVar(vid) => self.vid_to_region.get(&vid).cloned().unwrap_or(r), - _ => r, + ty::ReEarlyBound(_) | ty::ReStatic | ty::ReLateBound(..) | ty::ReError(_) => r, + r => bug!("unexpected region: {r:?}"), } } } diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 04379c2bca97d..c992a5388d199 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -422,8 +422,8 @@ fn clean_projection<'tcx>( let bounds = cx .tcx .explicit_item_bounds(ty.skip_binder().def_id) - .iter() - .map(|(bound, _)| EarlyBinder(*bound).subst(cx.tcx, ty.skip_binder().substs)) + .subst_iter_copied(cx.tcx, ty.skip_binder().substs) + .map(|(pred, _)| pred) .collect::>(); return clean_middle_opaque_bounds(cx, bounds); } @@ -1315,10 +1315,11 @@ pub(crate) fn clean_middle_assoc_item<'tcx>( } if let ty::TraitContainer = assoc_item.container { - let bounds = tcx.explicit_item_bounds(assoc_item.def_id); + let bounds = + tcx.explicit_item_bounds(assoc_item.def_id).subst_identity_iter_copied(); let predicates = tcx.explicit_predicates_of(assoc_item.def_id).predicates; let predicates = - tcx.arena.alloc_from_iter(bounds.into_iter().chain(predicates).copied()); + tcx.arena.alloc_from_iter(bounds.chain(predicates.iter().copied())); let mut generics = clean_ty_generics( cx, tcx.generics_of(assoc_item.def_id), @@ -1845,8 +1846,8 @@ pub(crate) fn clean_middle_ty<'tcx>( let bounds = cx .tcx .explicit_item_bounds(def_id) - .iter() - .map(|(bound, _)| EarlyBinder(*bound).subst(cx.tcx, substs)) + .subst_iter_copied(cx.tcx, substs) + .map(|(bound, _)| bound) .collect::>(); clean_middle_opaque_bounds(cx, bounds) } diff --git a/src/librustdoc/doctest.rs b/src/librustdoc/doctest.rs index daf10e5b88a83..d71098ad89da0 100644 --- a/src/librustdoc/doctest.rs +++ b/src/librustdoc/doctest.rs @@ -679,6 +679,10 @@ pub(crate) fn make_test( // parse the source, but only has false positives, not false // negatives. if s.contains(crate_name) { + // rustdoc implicitly inserts an `extern crate` item for the own crate + // which may be unused, so we need to allow the lint. + prog.push_str(&format!("#[allow(unused_extern_crates)]\n")); + prog.push_str(&format!("extern crate r#{crate_name};\n")); line_offset += 1; } diff --git a/src/librustdoc/doctest/tests.rs b/src/librustdoc/doctest/tests.rs index 360d2259ea3d2..a30fe28f94f99 100644 --- a/src/librustdoc/doctest/tests.rs +++ b/src/librustdoc/doctest/tests.rs @@ -38,6 +38,7 @@ fn make_test_crate_name() { let input = "use asdf::qwop; assert_eq!(2+2, 4);"; let expected = "#![allow(unused)] +#[allow(unused_extern_crates)] extern crate r#asdf; fn main() { use asdf::qwop; @@ -128,6 +129,7 @@ fn make_test_opts_attrs() { let input = "use asdf::qwop; assert_eq!(2+2, 4);"; let expected = "#![feature(sick_rad)] +#[allow(unused_extern_crates)] extern crate r#asdf; fn main() { use asdf::qwop; @@ -141,6 +143,7 @@ assert_eq!(2+2, 4); opts.attrs.push("feature(hella_dope)".to_string()); let expected = "#![feature(sick_rad)] #![feature(hella_dope)] +#[allow(unused_extern_crates)] extern crate r#asdf; fn main() { use asdf::qwop; @@ -236,6 +239,7 @@ assert_eq!(asdf::foo, 4);"; let expected = "#![allow(unused)] extern crate hella_qwop; +#[allow(unused_extern_crates)] extern crate r#asdf; fn main() { assert_eq!(asdf::foo, 4); diff --git a/src/librustdoc/json/mod.rs b/src/librustdoc/json/mod.rs index d6da6e0993894..9392dd4d08825 100644 --- a/src/librustdoc/json/mod.rs +++ b/src/librustdoc/json/mod.rs @@ -279,7 +279,10 @@ impl<'tcx> FormatRenderer<'tcx> for JsonRenderer<'tcx> { p.push(output.index.get(&output.root).unwrap().name.clone().unwrap()); p.set_extension("json"); let mut file = BufWriter::new(try_err!(File::create(&p), p)); - serde_json::ser::to_writer(&mut file, &output).unwrap(); + self.tcx + .sess + .time("rustdoc_json_serialization", || serde_json::ser::to_writer(&mut file, &output)) + .unwrap(); try_err!(file.flush(), p); Ok(()) diff --git a/src/tools/cargo b/src/tools/cargo index de80432f04da6..9e586fbd8b931 160000 --- a/src/tools/cargo +++ b/src/tools/cargo @@ -1 +1 @@ -Subproject commit de80432f04da61d98dcbbc1572598071718ccfd2 +Subproject commit 9e586fbd8b931494067144623b76c37d213b1ab6 diff --git a/src/tools/clippy/clippy_lints/src/future_not_send.rs b/src/tools/clippy/clippy_lints/src/future_not_send.rs index ed0bd58c770c7..ff838c2d56e43 100644 --- a/src/tools/clippy/clippy_lints/src/future_not_send.rs +++ b/src/tools/clippy/clippy_lints/src/future_not_send.rs @@ -4,7 +4,7 @@ use rustc_hir::intravisit::FnKind; use rustc_hir::{Body, FnDecl}; use rustc_infer::infer::TyCtxtInferExt; use rustc_lint::{LateContext, LateLintPass}; -use rustc_middle::ty::{self, AliasTy, Clause, EarlyBinder, PredicateKind}; +use rustc_middle::ty::{self, AliasTy, Clause, PredicateKind}; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::def_id::LocalDefId; use rustc_span::{sym, Span}; @@ -66,8 +66,7 @@ impl<'tcx> LateLintPass<'tcx> for FutureNotSend { if let ty::Alias(ty::Opaque, AliasTy { def_id, substs, .. }) = *ret_ty.kind() { let preds = cx.tcx.explicit_item_bounds(def_id); let mut is_future = false; - for &(p, _span) in preds { - let p = EarlyBinder(p).subst(cx.tcx, substs); + for (p, _span) in preds.subst_iter_copied(cx.tcx, substs) { if let Some(trait_pred) = p.to_opt_poly_trait_pred() { if Some(trait_pred.skip_binder().trait_ref.def_id) == cx.tcx.lang_items().future_trait() { is_future = true; diff --git a/src/tools/clippy/clippy_utils/src/ty.rs b/src/tools/clippy/clippy_utils/src/ty.rs index 8b996c188161d..a65720116440e 100644 --- a/src/tools/clippy/clippy_utils/src/ty.rs +++ b/src/tools/clippy/clippy_utils/src/ty.rs @@ -90,7 +90,7 @@ pub fn contains_ty_adt_constructor_opaque<'tcx>(cx: &LateContext<'tcx>, ty: Ty<' return false; } - for &(predicate, _span) in cx.tcx.explicit_item_bounds(def_id) { + for (predicate, _span) in cx.tcx.explicit_item_bounds(def_id).subst_identity_iter_copied() { match predicate.kind().skip_binder() { // For `impl Trait`, it will register a predicate of `T: Trait`, so we go through // and check substituions to find `U`. @@ -226,7 +226,7 @@ pub fn implements_trait_with_env<'tcx>( ty_params: impl IntoIterator>>, ) -> bool { // Clippy shouldn't have infer types - assert!(!ty.needs_infer()); + assert!(!ty.has_infer()); let ty = tcx.erase_regions(ty); if ty.has_escaping_bound_vars() { @@ -267,7 +267,7 @@ pub fn is_must_use_ty<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool { }, ty::Tuple(substs) => substs.iter().any(|ty| is_must_use_ty(cx, ty)), ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }) => { - for (predicate, _) in cx.tcx.explicit_item_bounds(*def_id) { + for (predicate, _) in cx.tcx.explicit_item_bounds(def_id).skip_binder() { if let ty::PredicateKind::Clause(ty::Clause::Trait(trait_predicate)) = predicate.kind().skip_binder() { if cx.tcx.has_attr(trait_predicate.trait_ref.def_id, sym::must_use) { return true; @@ -743,7 +743,7 @@ fn sig_for_projection<'tcx>(cx: &LateContext<'tcx>, ty: AliasTy<'tcx>) -> Option for (pred, _) in cx .tcx - .bound_explicit_item_bounds(ty.def_id) + .explicit_item_bounds(ty.def_id) .subst_iter_copied(cx.tcx, ty.substs) { match pred.kind().skip_binder() { diff --git a/src/tools/tidy/src/style.rs b/src/tools/tidy/src/style.rs index a2012db903a18..5f388ee47bbdb 100644 --- a/src/tools/tidy/src/style.rs +++ b/src/tools/tidy/src/style.rs @@ -385,10 +385,12 @@ pub fn check(path: &Path, bad: &mut bool) { } if filename != "style.rs" { if trimmed.contains("TODO") { - err("TODO is deprecated; use FIXME") + err( + "TODO is used for tasks that should be done before merging a PR; If you want to leave a message in the codebase use FIXME", + ) } if trimmed.contains("//") && trimmed.contains(" XXX") { - err("XXX is deprecated; use FIXME") + err("Instead of XXX use FIXME") } if any_problematic_line { for s in problematic_consts_strings.iter() { diff --git a/tests/assembly/asm/loongarch-type.rs b/tests/assembly/asm/loongarch-type.rs new file mode 100644 index 0000000000000..4e296f3ade58b --- /dev/null +++ b/tests/assembly/asm/loongarch-type.rs @@ -0,0 +1,196 @@ +// min-llvm-version: 16.0 +// assembly-output: emit-asm +// compile-flags: --target loongarch64-unknown-linux-gnu +// needs-llvm-components: loongarch + +#![feature(no_core, lang_items, rustc_attrs, asm_experimental_arch)] +#![crate_type = "rlib"] +#![no_core] +#![allow(asm_sub_register, non_camel_case_types)] + +#[rustc_builtin_macro] +macro_rules! asm { + () => {}; +} +#[rustc_builtin_macro] +macro_rules! concat { + () => {}; +} +#[rustc_builtin_macro] +macro_rules! stringify { + () => {}; +} + +#[lang = "sized"] +trait Sized {} +#[lang = "copy"] +trait Copy {} + +type ptr = *const i32; + +impl Copy for i8 {} +impl Copy for i16 {} +impl Copy for i32 {} +impl Copy for i64 {} +impl Copy for f32 {} +impl Copy for f64 {} +impl Copy for ptr {} +extern "C" { + fn extern_func(); + static extern_static: u8; +} + +// Hack to avoid function merging +extern "Rust" { + fn dont_merge(s: &str); +} + +// CHECK-LABEL: sym_fn: +// CHECK: #APP +// CHECK: pcalau12i $t0, %got_pc_hi20(extern_func) +// CHECK: ld.d $t0, $t0, %got_pc_lo12(extern_func) +// CHECK: #NO_APP +#[no_mangle] +pub unsafe fn sym_fn() { + asm!("la.got $r12, {}", sym extern_func); +} + +// CHECK-LABEL: sym_static: +// CHECK: #APP +// CHECK: pcalau12i $t0, %got_pc_hi20(extern_static) +// CHECK: ld.d $t0, $t0, %got_pc_lo12(extern_static) +// CHECK: #NO_APP +#[no_mangle] +pub unsafe fn sym_static() { + asm!("la.got $r12, {}", sym extern_static); +} + +macro_rules! check { ($func:ident, $ty:ty, $class:ident, $mov:literal) => { + #[no_mangle] + pub unsafe fn $func(x: $ty) -> $ty { + dont_merge(stringify!($func)); + + let y; + asm!(concat!($mov," {}, {}"), out($class) y, in($class) x); + y + } +};} + +macro_rules! check_reg { ($func:ident, $ty:ty, $reg:tt, $mov:literal) => { + #[no_mangle] + pub unsafe fn $func(x: $ty) -> $ty { + dont_merge(stringify!($func)); + + let y; + asm!(concat!($mov, " ", $reg, ", ", $reg), lateout($reg) y, in($reg) x); + y + } +};} + +// CHECK-LABEL: reg_i8: +// CHECK: #APP +// CHECK: move ${{[a-z0-9]+}}, ${{[a-z0-9]+}} +// CHECK: #NO_APP +check!(reg_i8, i8, reg, "move"); + +// CHECK-LABEL: reg_i16: +// CHECK: #APP +// CHECK: move ${{[a-z0-9]+}}, ${{[a-z0-9]+}} +// CHECK: #NO_APP +check!(reg_i16, i16, reg, "move"); + +// CHECK-LABEL: reg_i32: +// CHECK: #APP +// CHECK: move ${{[a-z0-9]+}}, ${{[a-z0-9]+}} +// CHECK: #NO_APP +check!(reg_i32, i32, reg, "move"); + +// CHECK-LABEL: reg_f32: +// CHECK: #APP +// CHECK: move ${{[a-z0-9]+}}, ${{[a-z0-9]+}} +// CHECK: #NO_APP +check!(reg_f32, f32, reg, "move"); + +// CHECK-LABEL: reg_i64: +// CHECK: #APP +// CHECK: move ${{[a-z0-9]+}}, ${{[a-z0-9]+}} +// CHECK: #NO_APP +check!(reg_i64, i64, reg, "move"); + +// CHECK-LABEL: reg_f64: +// CHECK: #APP +// CHECK: move ${{[a-z0-9]+}}, ${{[a-z0-9]+}} +// CHECK: #NO_APP +check!(reg_f64, f64, reg, "move"); + +// CHECK-LABEL: reg_ptr: +// CHECK: #APP +// CHECK: move ${{[a-z0-9]+}}, ${{[a-z0-9]+}} +// CHECK: #NO_APP +check!(reg_ptr, ptr, reg, "move"); + +// CHECK-LABEL: freg_f32: +// CHECK: #APP +// CHECK: fmov.s $f{{[a-z0-9]+}}, $f{{[a-z0-9]+}} +// CHECK: #NO_APP +check!(freg_f32, f32, freg, "fmov.s"); + +// CHECK-LABEL: freg_f64: +// CHECK: #APP +// CHECK: fmov.d $f{{[a-z0-9]+}}, $f{{[a-z0-9]+}} +// CHECK: #NO_APP +check!(freg_f64, f64, freg, "fmov.d"); + +// CHECK-LABEL: r4_i8: +// CHECK: #APP +// CHECK: move $a0, $a0 +// CHECK: #NO_APP +check_reg!(r4_i8, i8, "$r4", "move"); + +// CHECK-LABEL: r4_i16: +// CHECK: #APP +// CHECK: move $a0, $a0 +// CHECK: #NO_APP +check_reg!(r4_i16, i16, "$r4", "move"); + +// CHECK-LABEL: r4_i32: +// CHECK: #APP +// CHECK: move $a0, $a0 +// CHECK: #NO_APP +check_reg!(r4_i32, i32, "$r4", "move"); + +// CHECK-LABEL: r4_f32: +// CHECK: #APP +// CHECK: move $a0, $a0 +// CHECK: #NO_APP +check_reg!(r4_f32, f32, "$r4", "move"); + +// CHECK-LABEL: r4_i64: +// CHECK: #APP +// CHECK: move $a0, $a0 +// CHECK: #NO_APP +check_reg!(r4_i64, i64, "$r4", "move"); + +// CHECK-LABEL: r4_f64: +// CHECK: #APP +// CHECK: move $a0, $a0 +// CHECK: #NO_APP +check_reg!(r4_f64, f64, "$r4", "move"); + +// CHECK-LABEL: r4_ptr: +// CHECK: #APP +// CHECK: move $a0, $a0 +// CHECK: #NO_APP +check_reg!(r4_ptr, ptr, "$r4", "move"); + +// CHECK-LABEL: f0_f32: +// CHECK: #APP +// CHECK: fmov.s $f{{[a-z0-9]+}}, $f{{[a-z0-9]+}} +// CHECK: #NO_APP +check_reg!(f0_f32, f32, "$f0", "fmov.s"); + +// CHECK-LABEL: f0_f64: +// CHECK: #APP +// CHECK: fmov.d $f{{[a-z0-9]+}}, $f{{[a-z0-9]+}} +// CHECK: #NO_APP +check_reg!(f0_f64, f64, "$f0", "fmov.d"); diff --git a/tests/debuginfo/pretty-std.rs b/tests/debuginfo/pretty-std.rs index 7bb2810c2b213..c7df7dc3cb3b7 100644 --- a/tests/debuginfo/pretty-std.rs +++ b/tests/debuginfo/pretty-std.rs @@ -130,8 +130,8 @@ // cdb-check: [+0x000] __0 : "IAMA optional string!" [Type: alloc::string::String] // cdb-command: dx linkedlist -// cdb-check:linkedlist : { len=0x2 } [Type: alloc::collections::linked_list::LinkedList] -// cdb-check: [] [Type: alloc::collections::linked_list::LinkedList] +// cdb-check:linkedlist : { len=0x2 } [Type: alloc::collections::linked_list::LinkedList] +// cdb-check: [] [Type: alloc::collections::linked_list::LinkedList] // cdb-check: [0x0] : 128 [Type: int] // cdb-check: [0x1] : 42 [Type: int] diff --git a/tests/debuginfo/thread.rs b/tests/debuginfo/thread.rs index 388d50c5cdc43..e7e83c7aacd47 100644 --- a/tests/debuginfo/thread.rs +++ b/tests/debuginfo/thread.rs @@ -1,4 +1,4 @@ -// Testing the the display of JoinHandle and Thread in cdb. +// Testing the display of JoinHandle and Thread in cdb. // cdb-only // min-cdb-version: 10.0.18317.1001 diff --git a/tests/mir-opt/building/async_await.b-{closure#0}.generator_resume.0.mir b/tests/mir-opt/building/async_await.b-{closure#0}.generator_resume.0.mir index 7cce3415fa1b7..9bced25a5957d 100644 --- a/tests/mir-opt/building/async_await.b-{closure#0}.generator_resume.0.mir +++ b/tests/mir-opt/building/async_await.b-{closure#0}.generator_resume.0.mir @@ -12,7 +12,7 @@ _1: GeneratorSavedTy { ty: impl std::future::Future, source_info: SourceInfo { - span: $DIR/async_await.rs:16:8: 16:14 (#11), + span: $DIR/async_await.rs:16:8: 16:14 (#10), scope: scope[0], }, ignore_for_traits: false, diff --git a/tests/mir-opt/lower_intrinsics.ptr_offset.LowerIntrinsics.diff b/tests/mir-opt/lower_intrinsics.ptr_offset.LowerIntrinsics.diff new file mode 100644 index 0000000000000..f342bf30d02ac --- /dev/null +++ b/tests/mir-opt/lower_intrinsics.ptr_offset.LowerIntrinsics.diff @@ -0,0 +1,30 @@ +- // MIR for `ptr_offset` before LowerIntrinsics ++ // MIR for `ptr_offset` after LowerIntrinsics + + fn ptr_offset(_1: *const i32, _2: isize) -> *const i32 { + debug p => _1; // in scope 0 at $DIR/lower_intrinsics.rs:+0:26: +0:27 + debug d => _2; // in scope 0 at $DIR/lower_intrinsics.rs:+0:41: +0:42 + let mut _0: *const i32; // return place in scope 0 at $DIR/lower_intrinsics.rs:+0:54: +0:64 + let mut _3: *const i32; // in scope 0 at $DIR/lower_intrinsics.rs:+1:30: +1:31 + let mut _4: isize; // in scope 0 at $DIR/lower_intrinsics.rs:+1:33: +1:34 + + bb0: { + StorageLive(_3); // scope 0 at $DIR/lower_intrinsics.rs:+1:30: +1:31 + _3 = _1; // scope 0 at $DIR/lower_intrinsics.rs:+1:30: +1:31 + StorageLive(_4); // scope 0 at $DIR/lower_intrinsics.rs:+1:33: +1:34 + _4 = _2; // scope 0 at $DIR/lower_intrinsics.rs:+1:33: +1:34 +- _0 = offset::(move _3, move _4) -> [return: bb1, unwind unreachable]; // scope 0 at $DIR/lower_intrinsics.rs:+1:5: +1:35 +- // mir::Constant +- // + span: $DIR/lower_intrinsics.rs:140:5: 140:29 +- // + literal: Const { ty: unsafe extern "rust-intrinsic" fn(*const i32, isize) -> *const i32 {offset::}, val: Value() } ++ _0 = Offset(move _3, move _4); // scope 0 at $DIR/lower_intrinsics.rs:+1:5: +1:35 ++ goto -> bb1; // scope 0 at $DIR/lower_intrinsics.rs:+1:5: +1:35 + } + + bb1: { + StorageDead(_4); // scope 0 at $DIR/lower_intrinsics.rs:+1:34: +1:35 + StorageDead(_3); // scope 0 at $DIR/lower_intrinsics.rs:+1:34: +1:35 + return; // scope 0 at $DIR/lower_intrinsics.rs:+2:2: +2:2 + } + } + diff --git a/tests/mir-opt/lower_intrinsics.rs b/tests/mir-opt/lower_intrinsics.rs index 33fef930ad34b..ad690f803c424 100644 --- a/tests/mir-opt/lower_intrinsics.rs +++ b/tests/mir-opt/lower_intrinsics.rs @@ -134,3 +134,8 @@ pub fn option_payload(o: &Option, p: &Option) { let _y = core::intrinsics::option_payload_ptr(p); } } + +// EMIT_MIR lower_intrinsics.ptr_offset.LowerIntrinsics.diff +pub unsafe fn ptr_offset(p: *const i32, d: isize) -> *const i32 { + core::intrinsics::offset(p, d) +} diff --git a/tests/mir-opt/nll/named_lifetimes_basic.use_x.nll.0.mir b/tests/mir-opt/nll/named_lifetimes_basic.use_x.nll.0.mir index 6cd6d8b77959e..be5baf6ee3923 100644 --- a/tests/mir-opt/nll/named_lifetimes_basic.use_x.nll.0.mir +++ b/tests/mir-opt/nll/named_lifetimes_basic.use_x.nll.0.mir @@ -1,39 +1,39 @@ // MIR for `use_x` 0 nll | Free Region Mapping -| '_#0r | Global | ['_#2r, '_#1r, '_#0r, '_#4r, '_#3r] -| '_#1r | Local | ['_#1r, '_#4r] -| '_#2r | Local | ['_#2r, '_#1r, '_#4r] -| '_#3r | Local | ['_#4r, '_#3r] -| '_#4r | Local | ['_#4r] +| '?0 | Global | ['?2, '?1, '?0, '?4, '?3] +| '?1 | Local | ['?1, '?4] +| '?2 | Local | ['?2, '?1, '?4] +| '?3 | Local | ['?4, '?3] +| '?4 | Local | ['?4] | | Inferred Region Values -| '_#0r | U0 | {bb0[0..=1], '_#0r, '_#1r, '_#2r, '_#3r, '_#4r} -| '_#1r | U0 | {bb0[0..=1], '_#1r} -| '_#2r | U0 | {bb0[0..=1], '_#2r} -| '_#3r | U0 | {bb0[0..=1], '_#3r} -| '_#4r | U0 | {bb0[0..=1], '_#4r} -| '_#5r | U0 | {bb0[0..=1], '_#1r} -| '_#6r | U0 | {bb0[0..=1], '_#2r} -| '_#7r | U0 | {bb0[0..=1], '_#1r} -| '_#8r | U0 | {bb0[0..=1], '_#3r} +| '?0 | U0 | {bb0[0..=1], '?0, '?1, '?2, '?3, '?4} +| '?1 | U0 | {bb0[0..=1], '?1} +| '?2 | U0 | {bb0[0..=1], '?2} +| '?3 | U0 | {bb0[0..=1], '?3} +| '?4 | U0 | {bb0[0..=1], '?4} +| '?5 | U0 | {bb0[0..=1], '?1} +| '?6 | U0 | {bb0[0..=1], '?2} +| '?7 | U0 | {bb0[0..=1], '?1} +| '?8 | U0 | {bb0[0..=1], '?3} | | Inference Constraints -| '_#0r live at {bb0[0..=1]} -| '_#1r live at {bb0[0..=1]} -| '_#2r live at {bb0[0..=1]} -| '_#3r live at {bb0[0..=1]} -| '_#4r live at {bb0[0..=1]} -| '_#1r: '_#5r due to BoringNoLocation at All($DIR/named_lifetimes_basic.rs:12:26: 12:27) ($DIR/named_lifetimes_basic.rs:12:26: 12:27 (#0) -| '_#1r: '_#7r due to BoringNoLocation at All($DIR/named_lifetimes_basic.rs:12:54: 12:55) ($DIR/named_lifetimes_basic.rs:12:54: 12:55 (#0) -| '_#2r: '_#6r due to BoringNoLocation at All($DIR/named_lifetimes_basic.rs:12:42: 12:43) ($DIR/named_lifetimes_basic.rs:12:42: 12:43 (#0) -| '_#3r: '_#8r due to BoringNoLocation at All($DIR/named_lifetimes_basic.rs:12:66: 12:67) ($DIR/named_lifetimes_basic.rs:12:66: 12:67 (#0) -| '_#5r: '_#1r due to BoringNoLocation at All($DIR/named_lifetimes_basic.rs:12:26: 12:27) ($DIR/named_lifetimes_basic.rs:12:26: 12:27 (#0) -| '_#6r: '_#2r due to BoringNoLocation at All($DIR/named_lifetimes_basic.rs:12:42: 12:43) ($DIR/named_lifetimes_basic.rs:12:42: 12:43 (#0) -| '_#7r: '_#1r due to BoringNoLocation at All($DIR/named_lifetimes_basic.rs:12:54: 12:55) ($DIR/named_lifetimes_basic.rs:12:54: 12:55 (#0) -| '_#8r: '_#3r due to BoringNoLocation at All($DIR/named_lifetimes_basic.rs:12:66: 12:67) ($DIR/named_lifetimes_basic.rs:12:66: 12:67 (#0) +| '?0 live at {bb0[0..=1]} +| '?1 live at {bb0[0..=1]} +| '?2 live at {bb0[0..=1]} +| '?3 live at {bb0[0..=1]} +| '?4 live at {bb0[0..=1]} +| '?1: '?5 due to BoringNoLocation at All($DIR/named_lifetimes_basic.rs:12:26: 12:27) ($DIR/named_lifetimes_basic.rs:12:26: 12:27 (#0) +| '?1: '?7 due to BoringNoLocation at All($DIR/named_lifetimes_basic.rs:12:54: 12:55) ($DIR/named_lifetimes_basic.rs:12:54: 12:55 (#0) +| '?2: '?6 due to BoringNoLocation at All($DIR/named_lifetimes_basic.rs:12:42: 12:43) ($DIR/named_lifetimes_basic.rs:12:42: 12:43 (#0) +| '?3: '?8 due to BoringNoLocation at All($DIR/named_lifetimes_basic.rs:12:66: 12:67) ($DIR/named_lifetimes_basic.rs:12:66: 12:67 (#0) +| '?5: '?1 due to BoringNoLocation at All($DIR/named_lifetimes_basic.rs:12:26: 12:27) ($DIR/named_lifetimes_basic.rs:12:26: 12:27 (#0) +| '?6: '?2 due to BoringNoLocation at All($DIR/named_lifetimes_basic.rs:12:42: 12:43) ($DIR/named_lifetimes_basic.rs:12:42: 12:43 (#0) +| '?7: '?1 due to BoringNoLocation at All($DIR/named_lifetimes_basic.rs:12:54: 12:55) ($DIR/named_lifetimes_basic.rs:12:54: 12:55 (#0) +| '?8: '?3 due to BoringNoLocation at All($DIR/named_lifetimes_basic.rs:12:66: 12:67) ($DIR/named_lifetimes_basic.rs:12:66: 12:67 (#0) | -fn use_x(_1: &'_#5r mut i32, _2: &'_#6r u32, _3: &'_#7r u32, _4: &'_#8r u32) -> bool { +fn use_x(_1: &'?5 mut i32, _2: &'?6 u32, _3: &'?7 u32, _4: &'?8 u32) -> bool { debug w => _1; // in scope 0 at $DIR/named_lifetimes_basic.rs:+0:26: +0:27 debug x => _2; // in scope 0 at $DIR/named_lifetimes_basic.rs:+0:42: +0:43 debug y => _3; // in scope 0 at $DIR/named_lifetimes_basic.rs:+0:54: +0:55 diff --git a/tests/mir-opt/nll/region_subtyping_basic.main.nll.0.32bit.mir b/tests/mir-opt/nll/region_subtyping_basic.main.nll.0.32bit.mir index 798e45df8ca76..71bdfcc5c4991 100644 --- a/tests/mir-opt/nll/region_subtyping_basic.main.nll.0.32bit.mir +++ b/tests/mir-opt/nll/region_subtyping_basic.main.nll.0.32bit.mir @@ -1,24 +1,24 @@ // MIR for `main` 0 nll | Free Region Mapping -| '_#0r | Global | ['_#0r, '_#1r] -| '_#1r | Local | ['_#1r] +| '?0 | Global | ['?0, '?1] +| '?1 | Local | ['?1] | | Inferred Region Values -| '_#0r | U0 | {bb0[0..=8], bb1[0..=7], bb2[0..=3], bb3[0..=3], bb4[0..=1], bb5[0..=2], bb6[0..=5], bb7[0], '_#0r, '_#1r} -| '_#1r | U0 | {bb0[0..=8], bb1[0..=7], bb2[0..=3], bb3[0..=3], bb4[0..=1], bb5[0..=2], bb6[0..=5], bb7[0], '_#1r} -| '_#2r | U0 | {bb1[0..=7], bb2[0..=2]} -| '_#3r | U0 | {bb1[1..=7], bb2[0..=2]} -| '_#4r | U0 | {bb1[4..=7], bb2[0..=2]} +| '?0 | U0 | {bb0[0..=8], bb1[0..=7], bb2[0..=3], bb3[0..=3], bb4[0..=1], bb5[0..=2], bb6[0..=5], bb7[0], '?0, '?1} +| '?1 | U0 | {bb0[0..=8], bb1[0..=7], bb2[0..=3], bb3[0..=3], bb4[0..=1], bb5[0..=2], bb6[0..=5], bb7[0], '?1} +| '?2 | U0 | {bb1[0..=7], bb2[0..=2]} +| '?3 | U0 | {bb1[1..=7], bb2[0..=2]} +| '?4 | U0 | {bb1[4..=7], bb2[0..=2]} | | Inference Constraints -| '_#0r live at {bb0[0..=8], bb1[0..=7], bb2[0..=3], bb3[0..=3], bb4[0..=1], bb5[0..=2], bb6[0..=5], bb7[0]} -| '_#1r live at {bb0[0..=8], bb1[0..=7], bb2[0..=3], bb3[0..=3], bb4[0..=1], bb5[0..=2], bb6[0..=5], bb7[0]} -| '_#2r live at {bb1[0]} -| '_#3r live at {bb1[1..=3]} -| '_#4r live at {bb1[4..=7], bb2[0..=2]} -| '_#2r: '_#3r due to Assignment at Single(bb1[0]) ($DIR/region_subtyping_basic.rs:18:13: 18:18 (#0) -| '_#3r: '_#4r due to Assignment at Single(bb1[3]) ($DIR/region_subtyping_basic.rs:19:13: 19:14 (#0) +| '?0 live at {bb0[0..=8], bb1[0..=7], bb2[0..=3], bb3[0..=3], bb4[0..=1], bb5[0..=2], bb6[0..=5], bb7[0]} +| '?1 live at {bb0[0..=8], bb1[0..=7], bb2[0..=3], bb3[0..=3], bb4[0..=1], bb5[0..=2], bb6[0..=5], bb7[0]} +| '?2 live at {bb1[0]} +| '?3 live at {bb1[1..=3]} +| '?4 live at {bb1[4..=7], bb2[0..=2]} +| '?2: '?3 due to Assignment at Single(bb1[0]) ($DIR/region_subtyping_basic.rs:18:13: 18:18 (#0) +| '?3: '?4 due to Assignment at Single(bb1[3]) ($DIR/region_subtyping_basic.rs:19:13: 19:14 (#0) | fn main() -> () { let mut _0: (); // return place in scope 0 at $DIR/region_subtyping_basic.rs:+0:11: +0:11 @@ -32,10 +32,10 @@ fn main() -> () { let _10: bool; // in scope 0 at $DIR/region_subtyping_basic.rs:+7:9: +7:18 scope 1 { debug v => _1; // in scope 1 at $DIR/region_subtyping_basic.rs:+1:9: +1:14 - let _2: &'_#3r usize; // in scope 1 at $DIR/region_subtyping_basic.rs:+2:9: +2:10 + let _2: &'?3 usize; // in scope 1 at $DIR/region_subtyping_basic.rs:+2:9: +2:10 scope 2 { debug p => _2; // in scope 2 at $DIR/region_subtyping_basic.rs:+2:9: +2:10 - let _6: &'_#4r usize; // in scope 2 at $DIR/region_subtyping_basic.rs:+3:9: +3:10 + let _6: &'?4 usize; // in scope 2 at $DIR/region_subtyping_basic.rs:+3:9: +3:10 scope 3 { debug q => _6; // in scope 3 at $DIR/region_subtyping_basic.rs:+3:9: +3:10 } @@ -55,7 +55,7 @@ fn main() -> () { } bb1: { - _2 = &'_#2r _1[_3]; // bb1[0]: scope 1 at $DIR/region_subtyping_basic.rs:+2:13: +2:18 + _2 = &'?2 _1[_3]; // bb1[0]: scope 1 at $DIR/region_subtyping_basic.rs:+2:13: +2:18 FakeRead(ForLet(None), _2); // bb1[1]: scope 1 at $DIR/region_subtyping_basic.rs:+2:9: +2:10 StorageLive(_6); // bb1[2]: scope 2 at $DIR/region_subtyping_basic.rs:+3:9: +3:10 _6 = _2; // bb1[3]: scope 2 at $DIR/region_subtyping_basic.rs:+3:13: +3:14 diff --git a/tests/mir-opt/nll/region_subtyping_basic.main.nll.0.64bit.mir b/tests/mir-opt/nll/region_subtyping_basic.main.nll.0.64bit.mir index 4767bfc76ed9d..9fa8609b751a2 100644 --- a/tests/mir-opt/nll/region_subtyping_basic.main.nll.0.64bit.mir +++ b/tests/mir-opt/nll/region_subtyping_basic.main.nll.0.64bit.mir @@ -1,24 +1,24 @@ // MIR for `main` 0 nll | Free Region Mapping -| '_#0r | Global | ['_#0r, '_#1r] -| '_#1r | Local | ['_#1r] +| '?0 | Global | ['?0, '?1] +| '?1 | Local | ['?1] | | Inferred Region Values -| '_#0r | U0 | {bb0[0..=8], bb1[0..=7], bb2[0..=3], bb3[0..=3], bb4[0..=1], bb5[0..=2], bb6[0..=5], bb7[0], '_#0r, '_#1r} -| '_#1r | U0 | {bb0[0..=8], bb1[0..=7], bb2[0..=3], bb3[0..=3], bb4[0..=1], bb5[0..=2], bb6[0..=5], bb7[0], '_#1r} -| '_#2r | U0 | {bb1[0..=7], bb2[0..=2]} -| '_#3r | U0 | {bb1[1..=7], bb2[0..=2]} -| '_#4r | U0 | {bb1[4..=7], bb2[0..=2]} +| '?0 | U0 | {bb0[0..=8], bb1[0..=7], bb2[0..=3], bb3[0..=3], bb4[0..=1], bb5[0..=2], bb6[0..=5], bb7[0], '?0, '?1} +| '?1 | U0 | {bb0[0..=8], bb1[0..=7], bb2[0..=3], bb3[0..=3], bb4[0..=1], bb5[0..=2], bb6[0..=5], bb7[0], '?1} +| '?2 | U0 | {bb1[0..=7], bb2[0..=2]} +| '?3 | U0 | {bb1[1..=7], bb2[0..=2]} +| '?4 | U0 | {bb1[4..=7], bb2[0..=2]} | | Inference Constraints -| '_#0r live at {bb0[0..=8], bb1[0..=7], bb2[0..=3], bb3[0..=3], bb4[0..=1], bb5[0..=2], bb6[0..=5], bb7[0]} -| '_#1r live at {bb0[0..=8], bb1[0..=7], bb2[0..=3], bb3[0..=3], bb4[0..=1], bb5[0..=2], bb6[0..=5], bb7[0]} -| '_#2r live at {bb1[0]} -| '_#3r live at {bb1[1..=3]} -| '_#4r live at {bb1[4..=7], bb2[0..=2]} -| '_#2r: '_#3r due to Assignment at Single(bb1[0]) ($DIR/region_subtyping_basic.rs:18:13: 18:18 (#0) -| '_#3r: '_#4r due to Assignment at Single(bb1[3]) ($DIR/region_subtyping_basic.rs:19:13: 19:14 (#0) +| '?0 live at {bb0[0..=8], bb1[0..=7], bb2[0..=3], bb3[0..=3], bb4[0..=1], bb5[0..=2], bb6[0..=5], bb7[0]} +| '?1 live at {bb0[0..=8], bb1[0..=7], bb2[0..=3], bb3[0..=3], bb4[0..=1], bb5[0..=2], bb6[0..=5], bb7[0]} +| '?2 live at {bb1[0]} +| '?3 live at {bb1[1..=3]} +| '?4 live at {bb1[4..=7], bb2[0..=2]} +| '?2: '?3 due to Assignment at Single(bb1[0]) ($DIR/region_subtyping_basic.rs:18:13: 18:18 (#0) +| '?3: '?4 due to Assignment at Single(bb1[3]) ($DIR/region_subtyping_basic.rs:19:13: 19:14 (#0) | fn main() -> () { let mut _0: (); // return place in scope 0 at $DIR/region_subtyping_basic.rs:+0:11: +0:11 @@ -32,10 +32,10 @@ fn main() -> () { let _10: bool; // in scope 0 at $DIR/region_subtyping_basic.rs:+7:9: +7:18 scope 1 { debug v => _1; // in scope 1 at $DIR/region_subtyping_basic.rs:+1:9: +1:14 - let _2: &'_#3r usize; // in scope 1 at $DIR/region_subtyping_basic.rs:+2:9: +2:10 + let _2: &'?3 usize; // in scope 1 at $DIR/region_subtyping_basic.rs:+2:9: +2:10 scope 2 { debug p => _2; // in scope 2 at $DIR/region_subtyping_basic.rs:+2:9: +2:10 - let _6: &'_#4r usize; // in scope 2 at $DIR/region_subtyping_basic.rs:+3:9: +3:10 + let _6: &'?4 usize; // in scope 2 at $DIR/region_subtyping_basic.rs:+3:9: +3:10 scope 3 { debug q => _6; // in scope 3 at $DIR/region_subtyping_basic.rs:+3:9: +3:10 } @@ -55,7 +55,7 @@ fn main() -> () { } bb1: { - _2 = &'_#2r _1[_3]; // bb1[0]: scope 1 at $DIR/region_subtyping_basic.rs:+2:13: +2:18 + _2 = &'?2 _1[_3]; // bb1[0]: scope 1 at $DIR/region_subtyping_basic.rs:+2:13: +2:18 FakeRead(ForLet(None), _2); // bb1[1]: scope 1 at $DIR/region_subtyping_basic.rs:+2:9: +2:10 StorageLive(_6); // bb1[2]: scope 2 at $DIR/region_subtyping_basic.rs:+3:9: +3:10 _6 = _2; // bb1[3]: scope 2 at $DIR/region_subtyping_basic.rs:+3:13: +3:14 diff --git a/tests/mir-opt/storage_ranges.main.nll.0.mir b/tests/mir-opt/storage_ranges.main.nll.0.mir index 8e10e70f192d2..5bb1a7bf0c937 100644 --- a/tests/mir-opt/storage_ranges.main.nll.0.mir +++ b/tests/mir-opt/storage_ranges.main.nll.0.mir @@ -1,21 +1,21 @@ // MIR for `main` 0 nll | Free Region Mapping -| '_#0r | Global | ['_#0r, '_#1r] -| '_#1r | Local | ['_#1r] +| '?0 | Global | ['?0, '?1] +| '?1 | Local | ['?1] | | Inferred Region Values -| '_#0r | U0 | {bb0[0..=22], '_#0r, '_#1r} -| '_#1r | U0 | {bb0[0..=22], '_#1r} -| '_#2r | U0 | {bb0[10..=11]} -| '_#3r | U0 | {bb0[11]} +| '?0 | U0 | {bb0[0..=22], '?0, '?1} +| '?1 | U0 | {bb0[0..=22], '?1} +| '?2 | U0 | {bb0[10..=11]} +| '?3 | U0 | {bb0[11]} | | Inference Constraints -| '_#0r live at {bb0[0..=22]} -| '_#1r live at {bb0[0..=22]} -| '_#2r live at {bb0[10]} -| '_#3r live at {bb0[11]} -| '_#2r: '_#3r due to Assignment at Single(bb0[10]) ($DIR/storage_ranges.rs:6:17: 6:25 (#0) +| '?0 live at {bb0[0..=22]} +| '?1 live at {bb0[0..=22]} +| '?2 live at {bb0[10]} +| '?3 live at {bb0[11]} +| '?2: '?3 due to Assignment at Single(bb0[10]) ($DIR/storage_ranges.rs:6:17: 6:25 (#0) | fn main() -> () { let mut _0: (); // return place in scope 0 at $DIR/storage_ranges.rs:+0:11: +0:11 diff --git a/tests/rustdoc-json/reexport/auxiliary/enum_with_discriminant.rs b/tests/rustdoc-json/reexport/auxiliary/enum_with_discriminant.rs new file mode 100644 index 0000000000000..4fa26204be917 --- /dev/null +++ b/tests/rustdoc-json/reexport/auxiliary/enum_with_discriminant.rs @@ -0,0 +1,6 @@ +//! Should not be inlined + +/// Should not be inlined +pub enum O { + L = -1, +} diff --git a/tests/rustdoc-json/reexport/doc_inline_external_crate.rs b/tests/rustdoc-json/reexport/doc_inline_external_crate.rs new file mode 100644 index 0000000000000..40b681d7dbbef --- /dev/null +++ b/tests/rustdoc-json/reexport/doc_inline_external_crate.rs @@ -0,0 +1,10 @@ +// Regression Test for https://github.com/rust-lang/rust/issues/110138 +// aux-build: enum_with_discriminant.rs + +#[doc(inline)] +pub extern crate enum_with_discriminant; + +// @!has '$.index[*][?(@.docs == "Should not be inlined")]' +// @is '$.index[*][?(@.name == "enum_with_discriminant")].kind' '"extern_crate"' +// @set enum_with_discriminant = '$.index[*][?(@.name == "enum_with_discriminant")].id' +// @is '$.index[*][?(@.name == "doc_inline_external_crate")].inner.items[*]' $enum_with_discriminant diff --git a/tests/rustdoc-json/reexport/extern_crate_glob.rs b/tests/rustdoc-json/reexport/extern_crate_glob.rs new file mode 100644 index 0000000000000..8efb94fd3f17a --- /dev/null +++ b/tests/rustdoc-json/reexport/extern_crate_glob.rs @@ -0,0 +1,10 @@ +// aux-build: enum_with_discriminant.rs + +extern crate enum_with_discriminant; + +#[doc(inline)] +pub use enum_with_discriminant::*; + +// @!has '$.index[*][?(@.docs == "Should not be inlined")]' +// @set use = '$.index[*][?(@.inner.name == "enum_with_discriminant")].id' +// @is '$.index[*][?(@.name == "extern_crate_glob")].inner.items[*]' $use diff --git a/tests/rustdoc-ui/doc_cfg_hide.stderr b/tests/rustdoc-ui/doc_cfg_hide.stderr index 03623368cd047..b7e8870fdf548 100644 --- a/tests/rustdoc-ui/doc_cfg_hide.stderr +++ b/tests/rustdoc-ui/doc_cfg_hide.stderr @@ -16,7 +16,7 @@ LL | #![deny(warnings)] help: to apply to the crate, use an inner attribute | LL | #![doc(cfg_hide(doc))] - | ~~~~~~~~~~~~~~~~~~~~~~ + | + error: `#[doc(cfg_hide(...)]` takes a list of attributes --> $DIR/doc_cfg_hide.rs:4:8 diff --git a/tests/rustdoc-ui/intra-doc/auxiliary/inner-crate-enum.rs b/tests/rustdoc-ui/intra-doc/auxiliary/inner-crate-enum.rs deleted file mode 100644 index 6c48f5aa01f98..0000000000000 --- a/tests/rustdoc-ui/intra-doc/auxiliary/inner-crate-enum.rs +++ /dev/null @@ -1,3 +0,0 @@ -pub enum O { - L = -1, -} diff --git a/tests/rustdoc-ui/intra-doc/inline-external-enum.rs b/tests/rustdoc-ui/intra-doc/inline-external-enum.rs deleted file mode 100644 index 363dd7f64c225..0000000000000 --- a/tests/rustdoc-ui/intra-doc/inline-external-enum.rs +++ /dev/null @@ -1,8 +0,0 @@ -// check-pass -// aux-build: inner-crate-enum.rs -// compile-flags:-Z unstable-options --output-format json - -#[doc(inline)] -pub extern crate inner_crate_enum; - -fn main() {} diff --git a/tests/rustdoc-ui/invalid-doc-attr.rs b/tests/rustdoc-ui/invalid-doc-attr.rs index de004b41e27bc..c231e43b35caf 100644 --- a/tests/rustdoc-ui/invalid-doc-attr.rs +++ b/tests/rustdoc-ui/invalid-doc-attr.rs @@ -5,7 +5,7 @@ //~^ 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(test(no_crate_inject))] +//~| SUGGESTION ! #[doc(inline)] //~^ ERROR can only be applied to a `use` item //~| WARN is being phased out diff --git a/tests/rustdoc-ui/invalid-doc-attr.stderr b/tests/rustdoc-ui/invalid-doc-attr.stderr index 3c66e587b470d..b23b8ded8674b 100644 --- a/tests/rustdoc-ui/invalid-doc-attr.stderr +++ b/tests/rustdoc-ui/invalid-doc-attr.stderr @@ -16,7 +16,7 @@ LL | #![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 diff --git a/tests/rustdoc/playground-arg.rs b/tests/rustdoc/playground-arg.rs index f3811fe0b0ad1..2542ed657c1a7 100644 --- a/tests/rustdoc/playground-arg.rs +++ b/tests/rustdoc/playground-arg.rs @@ -10,4 +10,4 @@ pub fn dummy() {} // ensure that `extern crate foo;` was inserted into code snips automatically: -// @matches foo/index.html '//a[@class="test-arrow"][@href="https://example.com/?code=%23!%5Ballow(unused)%5D%0Aextern+crate+r%23foo;%0Afn+main()+%7B%0Ause+foo::dummy;%0Adummy();%0A%7D&edition=2015"]' "Run" +// @matches foo/index.html '//a[@class="test-arrow"][@href="https://example.com/?code=%23!%5Ballow(unused)%5D%0A%23%5Ballow(unused_extern_crates)%5D%0Aextern+crate+r%23foo;%0Afn+main()+%7B%0Ause+foo::dummy;%0Adummy();%0A%7D&edition=2015"]' "Run" diff --git a/tests/ui/associated-inherent-types/const-generics.rs b/tests/ui/associated-inherent-types/const-generics.rs new file mode 100644 index 0000000000000..5b7c00bccba70 --- /dev/null +++ b/tests/ui/associated-inherent-types/const-generics.rs @@ -0,0 +1,23 @@ +// Regression test for issue #109759. +// check-pass + +#![feature(inherent_associated_types)] +#![allow(incomplete_features)] + +struct Foo; + +struct Bar([(); X]); + +impl Bar { + pub fn new() -> Self { + Self([(); X]) + } +} + +impl Foo { + type Bar = Bar; +} + +fn main() { + let _ = Foo::Bar::<10>::new(); +} diff --git a/tests/ui/associated-inherent-types/generic-const-exprs.rs b/tests/ui/associated-inherent-types/generic-const-exprs.rs new file mode 100644 index 0000000000000..a4ac0ecfa4cf9 --- /dev/null +++ b/tests/ui/associated-inherent-types/generic-const-exprs.rs @@ -0,0 +1,28 @@ +// check-pass + +#![feature(inherent_associated_types, generic_const_exprs)] +#![allow(incomplete_features)] + +struct Parent; + +impl Parent { + type Mapping = Store<{ O + I }> + where + [(); O + I]: + ; +} + +struct Store; + +impl Store { + const REIFIED: usize = N; + + fn reify() -> usize { + N + } +} + +fn main() { + let _ = Parent::<2>::Mapping::<{ 12 * 2 }>::REIFIED; + let _ = Parent::<1>::Mapping::<{ 2 * 5 }>::reify(); +} diff --git a/tests/ui/associated-types/substs-ppaux.verbose.stderr b/tests/ui/associated-types/substs-ppaux.verbose.stderr index e4f6ba573ca40..ad67899e6da08 100644 --- a/tests/ui/associated-types/substs-ppaux.verbose.stderr +++ b/tests/ui/associated-types/substs-ppaux.verbose.stderr @@ -77,7 +77,7 @@ LL | >::bar; | ^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time | = help: the trait `Sized` is not implemented for `str` -note: required for `str` to implement `Foo<'_#0r, '_#1r, u8>` +note: required for `str` to implement `Foo<'?0, '?1, u8>` --> $DIR/substs-ppaux.rs:11:17 | LL | impl<'a,'b,T,S> Foo<'a, 'b, S> for T {} diff --git a/tests/ui/attributes/invalid-doc-attr.rs b/tests/ui/attributes/invalid-doc-attr.rs index de004b41e27bc..c231e43b35caf 100644 --- a/tests/ui/attributes/invalid-doc-attr.rs +++ b/tests/ui/attributes/invalid-doc-attr.rs @@ -5,7 +5,7 @@ //~^ 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(test(no_crate_inject))] +//~| SUGGESTION ! #[doc(inline)] //~^ ERROR can only be applied to a `use` item //~| WARN is being phased out diff --git a/tests/ui/attributes/invalid-doc-attr.stderr b/tests/ui/attributes/invalid-doc-attr.stderr index 3c66e587b470d..b23b8ded8674b 100644 --- a/tests/ui/attributes/invalid-doc-attr.stderr +++ b/tests/ui/attributes/invalid-doc-attr.stderr @@ -16,7 +16,7 @@ LL | #![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 diff --git a/tests/ui/closures/binder/nested-closures-regions.stderr b/tests/ui/closures/binder/nested-closures-regions.stderr index b385e0ed6e0a5..381aadb1564cc 100644 --- a/tests/ui/closures/binder/nested-closures-regions.stderr +++ b/tests/ui/closures/binder/nested-closures-regions.stderr @@ -9,11 +9,11 @@ LL | for<'a> || -> () { for<'c> |_: &'a ()| -> () {}; }; extern "rust-call" fn((&(),)), (), ] - = note: late-bound region is '_#4r - = note: late-bound region is '_#2r + = note: late-bound region is '?4 + = note: late-bound region is '?2 = note: number of external vids: 3 - = note: where '_#1r: '_#2r - = note: where '_#2r: '_#1r + = note: where '?1: '?2 + = note: where '?2: '?1 note: no external requirements --> $DIR/nested-closures-regions.rs:8:5 @@ -26,7 +26,7 @@ LL | for<'a> || -> () { for<'c> |_: &'a ()| -> () {}; }; extern "rust-call" fn(()), (), ] - = note: late-bound region is '_#2r + = note: late-bound region is '?2 note: no external requirements --> $DIR/nested-closures-regions.rs:7:1 diff --git a/tests/ui/closures/print/closure-print-generic-trim-off-verbose-2.stderr b/tests/ui/closures/print/closure-print-generic-trim-off-verbose-2.stderr index ff89dd340349b..381bb0c084a22 100644 --- a/tests/ui/closures/print/closure-print-generic-trim-off-verbose-2.stderr +++ b/tests/ui/closures/print/closure-print-generic-trim-off-verbose-2.stderr @@ -9,7 +9,7 @@ LL | let c1 : () = c; | expected due to this | = note: expected unit type `()` - found closure `[mod1::f::{closure#0} closure_substs=(unavailable) substs=[T, _#16t, extern "rust-call" fn(()), _#15t]]` + found closure `[mod1::f::{closure#0} closure_substs=(unavailable) substs=[T, ?16t, extern "rust-call" fn(()), ?15t]]` help: use parentheses to call this closure | LL | let c1 : () = c(); diff --git a/tests/ui/closures/print/closure-print-generic-verbose-1.stderr b/tests/ui/closures/print/closure-print-generic-verbose-1.stderr index 3ab7c66d11f2f..9a1f18fa8550d 100644 --- a/tests/ui/closures/print/closure-print-generic-verbose-1.stderr +++ b/tests/ui/closures/print/closure-print-generic-verbose-1.stderr @@ -2,7 +2,7 @@ error[E0382]: use of moved value: `c` --> $DIR/closure-print-generic-verbose-1.rs:17:5 | LL | let c = to_fn_once(move|| { - | - move occurs because `c` has type `[f::{closure#0} closure_kind_ty=i32 closure_sig_as_fn_ptr_ty=extern "rust-call" fn(()) upvar_tys=(Foo<&'_#9r str>, T)]`, which does not implement the `Copy` trait + | - move occurs because `c` has type `[f::{closure#0} closure_kind_ty=i32 closure_sig_as_fn_ptr_ty=extern "rust-call" fn(()) upvar_tys=(Foo<&'?9 str>, T)]`, which does not implement the `Copy` trait ... LL | c(); | --- `c` moved due to this call diff --git a/tests/ui/closures/print/closure-print-generic-verbose-2.stderr b/tests/ui/closures/print/closure-print-generic-verbose-2.stderr index 5bbf84f963d7e..2a4d16c48dc2e 100644 --- a/tests/ui/closures/print/closure-print-generic-verbose-2.stderr +++ b/tests/ui/closures/print/closure-print-generic-verbose-2.stderr @@ -9,7 +9,7 @@ LL | let c1 : () = c; | expected due to this | = note: expected unit type `()` - found closure `[f::{closure#0} closure_substs=(unavailable) substs=[T, _#16t, extern "rust-call" fn(()), _#15t]]` + found closure `[f::{closure#0} closure_substs=(unavailable) substs=[T, ?16t, extern "rust-call" fn(()), ?15t]]` help: use parentheses to call this closure | LL | let c1 : () = c(); diff --git a/tests/ui/closures/print/closure-print-verbose.stderr b/tests/ui/closures/print/closure-print-verbose.stderr index 083717b333408..9e219435e5ce0 100644 --- a/tests/ui/closures/print/closure-print-verbose.stderr +++ b/tests/ui/closures/print/closure-print-verbose.stderr @@ -7,7 +7,7 @@ LL | let foo: fn(u8) -> u8 = |v: u8| { a += v; a }; | expected due to this | = note: expected fn pointer `fn(u8) -> u8` - found closure `[main::{closure#0} closure_substs=(unavailable) substs=[i8, extern "rust-call" fn((u8,)) -> u8, _#6t]]` + found closure `[main::{closure#0} closure_substs=(unavailable) substs=[i8, extern "rust-call" fn((u8,)) -> u8, ?6t]]` note: closures can only be coerced to `fn` types if they do not capture any variables --> $DIR/closure-print-verbose.rs:10:39 | diff --git a/tests/ui/const-generics/occurs-check/unused-substs-2.rs b/tests/ui/const-generics/occurs-check/unused-substs-2.rs index 9b1212694f5ba..84e24d1a3f5f9 100644 --- a/tests/ui/const-generics/occurs-check/unused-substs-2.rs +++ b/tests/ui/const-generics/occurs-check/unused-substs-2.rs @@ -1,9 +1,9 @@ #![feature(generic_const_exprs)] #![allow(incomplete_features)] -// The goal is to get an unevaluated const `ct` with a `Ty::Infer(TyVar(_#1t)` subst. +// The goal is to get an unevaluated const `ct` with a `Ty::Infer(TyVar(?1t)` subst. // -// If we are then able to infer `ty::Infer(TyVar(_#1t) := Ty` we introduced an +// If we are then able to infer `ty::Infer(TyVar(?1t) := Ty` we introduced an // artificial inference cycle. struct Foo; @@ -20,8 +20,8 @@ impl Bind for Foo<{ 6 + 1 }> { fn main() { let (mut t, foo) = Foo::bind(); - // `t` is `ty::Infer(TyVar(_#1t))` - // `foo` contains `ty::Infer(TyVar(_#1t))` in its substs + // `t` is `ty::Infer(TyVar(?1t))` + // `foo` contains `ty::Infer(TyVar(?1t))` in its substs t = foo; //~^ ERROR mismatched types //~| NOTE cyclic type diff --git a/tests/ui/const-generics/occurs-check/unused-substs-3.rs b/tests/ui/const-generics/occurs-check/unused-substs-3.rs index d5aeab47e62b0..6db18d587d3e2 100644 --- a/tests/ui/const-generics/occurs-check/unused-substs-3.rs +++ b/tests/ui/const-generics/occurs-check/unused-substs-3.rs @@ -1,9 +1,9 @@ #![feature(generic_const_exprs)] #![allow(incomplete_features)] -// The goal is to get an unevaluated const `ct` with a `Ty::Infer(TyVar(_#1t)` subst. +// The goal is to get an unevaluated const `ct` with a `Ty::Infer(TyVar(?1t)` subst. // -// If we are then able to infer `ty::Infer(TyVar(_#1t) := Ty` we introduced an +// If we are then able to infer `ty::Infer(TyVar(?1t) := Ty` we introduced an // artificial inference cycle. fn bind() -> (T, [u8; 6 + 1]) { todo!() @@ -11,8 +11,8 @@ fn bind() -> (T, [u8; 6 + 1]) { fn main() { let (mut t, foo) = bind(); - // `t` is `ty::Infer(TyVar(_#1t))` - // `foo` contains `ty::Infer(TyVar(_#1t))` in its substs + // `t` is `ty::Infer(TyVar(?1t))` + // `foo` contains `ty::Infer(TyVar(?1t))` in its substs t = foo; //~^ ERROR mismatched types //~| NOTE cyclic type diff --git a/tests/ui/generator/issue-57084.rs b/tests/ui/generator/issue-57084.rs index 2a5c3dd0570f9..fbed78ff28047 100644 --- a/tests/ui/generator/issue-57084.rs +++ b/tests/ui/generator/issue-57084.rs @@ -1,5 +1,5 @@ // This issue reproduces an ICE on compile (E.g. fails on 2018-12-19 nightly). -// "cannot relate bound region: ReLateBound(DebruijnIndex(1), BrAnon(1)) <= '_#1r" +// "cannot relate bound region: ReLateBound(DebruijnIndex(1), BrAnon(1)) <= '?1" // run-pass // edition:2018 #![feature(generators,generator_trait)] diff --git a/tests/ui/generic-associated-types/self-outlives-lint.rs b/tests/ui/generic-associated-types/self-outlives-lint.rs index 673891fc3d1b4..0ea81b5aecb9e 100644 --- a/tests/ui/generic-associated-types/self-outlives-lint.rs +++ b/tests/ui/generic-associated-types/self-outlives-lint.rs @@ -189,7 +189,7 @@ trait MultipleMethods { } // We would normally require `Self: 'a`, but we can prove that `Self: 'static` -// because of the the bounds on the trait, so the bound is proven +// because of the bounds on the trait, so the bound is proven trait Trait: 'static { type Assoc<'a>; fn make_assoc(_: &u32) -> Self::Assoc<'_>; diff --git a/tests/ui/impl-trait/wf-eval-order.rs b/tests/ui/impl-trait/wf-eval-order.rs index c7d6bb870962a..8638fc2e77578 100644 --- a/tests/ui/impl-trait/wf-eval-order.rs +++ b/tests/ui/impl-trait/wf-eval-order.rs @@ -31,9 +31,9 @@ fn main() { // // - `wf(typeof(x))` because we use a projection candidate. // - `::V: Clone` because that's a bound on the trait. - // - `::V` normalizes to `_#1` where `::U == _#1` + // - `::V` normalizes to `?1t` where `::U == ?1t` // - // This all works if we evaluate `::U == _#1` before + // This all works if we evaluate `::U == ?1t` before // `::V`, but we previously had the opposite order. let x = hide(X(0)); } diff --git a/tests/ui/inference/deref-suggestion.rs b/tests/ui/inference/deref-suggestion.rs index 0d8e7289dc8a2..dc39cc9dbffb0 100644 --- a/tests/ui/inference/deref-suggestion.rs +++ b/tests/ui/inference/deref-suggestion.rs @@ -72,4 +72,13 @@ fn main() { } else { &0 }; + + #[derive(PartialEq, Eq)] + struct Foo; + let foo = Foo; + let bar = &Foo; + + if foo == bar { + //~^ ERROR mismatched types + } } diff --git a/tests/ui/inference/deref-suggestion.stderr b/tests/ui/inference/deref-suggestion.stderr index 1626032ae997d..6f5aacacfc1f1 100644 --- a/tests/ui/inference/deref-suggestion.stderr +++ b/tests/ui/inference/deref-suggestion.stderr @@ -175,6 +175,19 @@ LL | || }; | |_____`if` and `else` have incompatible types | expected `i32`, found `&{integer}` -error: aborting due to 13 previous errors +error[E0308]: mismatched types + --> $DIR/deref-suggestion.rs:81:15 + | +LL | if foo == bar { + | --- ^^^ expected `Foo`, found `&Foo` + | | + | expected because this is `Foo` + | +help: consider dereferencing the borrow + | +LL | if foo == *bar { + | + + +error: aborting due to 14 previous errors For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/inference/issue-70082.rs b/tests/ui/inference/issue-70082.rs new file mode 100644 index 0000000000000..d54d0a1a48a2d --- /dev/null +++ b/tests/ui/inference/issue-70082.rs @@ -0,0 +1,10 @@ +fn main() { + // this closure is fine, and should not get any error annotations + let em = |v: f64| -> f64 { v }; + + let x: f64 = em(1i16.into()); + + let y: f64 = 0.01f64 * 1i16.into(); + //~^ ERROR type annotations needed + //~| HELP try using a fully qualified path +} diff --git a/tests/ui/inference/issue-70082.stderr b/tests/ui/inference/issue-70082.stderr new file mode 100644 index 0000000000000..47229a5fee14d --- /dev/null +++ b/tests/ui/inference/issue-70082.stderr @@ -0,0 +1,17 @@ +error[E0284]: type annotations needed + --> $DIR/issue-70082.rs:7:33 + | +LL | let y: f64 = 0.01f64 * 1i16.into(); + | - ^^^^ + | | + | type must be known at this point + | + = note: cannot satisfy `>::Output == f64` +help: try using a fully qualified path to specify the expected types + | +LL | let y: f64 = 0.01f64 * >::into(1i16); + | +++++++++++++++++++++++ ~ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0284`. diff --git a/tests/ui/macros/macro-local-data-key-priv.stderr b/tests/ui/macros/macro-local-data-key-priv.stderr index fb8cab2794bc6..0f412bc86fb31 100644 --- a/tests/ui/macros/macro-local-data-key-priv.stderr +++ b/tests/ui/macros/macro-local-data-key-priv.stderr @@ -9,7 +9,7 @@ note: the constant `baz` is defined here | LL | thread_local!(static baz: f64 = 0.0); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - = note: this error originates in the macro `$crate::__thread_local_inner` which comes from the expansion of the macro `thread_local` (in Nightly builds, run with -Z macro-backtrace for more info) + = note: this error originates in the macro `$crate::thread::local_impl::thread_local_inner` which comes from the expansion of the macro `thread_local` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to previous error diff --git a/tests/ui/methods/method-not-found-generic-arg-elision.rs b/tests/ui/methods/method-not-found-generic-arg-elision.rs index 799ced5e9c460..538eeadae0836 100644 --- a/tests/ui/methods/method-not-found-generic-arg-elision.rs +++ b/tests/ui/methods/method-not-found-generic-arg-elision.rs @@ -83,8 +83,8 @@ fn main() { //~^ ERROR no method named `distance` found for struct `Point let d = point_i32.other(); //~^ ERROR no method named `other` found for struct `Point - let v = vec![1_i32, 2, 3]; - v.iter().map(|x| x * x).extend(std::iter::once(100)); + let v = vec![1, 2, 3]; + v.iter().map(Box::new(|x| x * x) as Box i32>).extend(std::iter::once(100)); //~^ ERROR no method named `extend` found for struct `Map let wrapper = Wrapper(true); wrapper.method(); diff --git a/tests/ui/methods/method-not-found-generic-arg-elision.stderr b/tests/ui/methods/method-not-found-generic-arg-elision.stderr index f3db56d1d5391..b97688d3868b8 100644 --- a/tests/ui/methods/method-not-found-generic-arg-elision.stderr +++ b/tests/ui/methods/method-not-found-generic-arg-elision.stderr @@ -20,10 +20,10 @@ LL | let d = point_i32.other(); | ^^^^^ method not found in `Point` error[E0599]: no method named `extend` found for struct `Map` in the current scope - --> $DIR/method-not-found-generic-arg-elision.rs:87:29 + --> $DIR/method-not-found-generic-arg-elision.rs:87:67 | -LL | v.iter().map(|x| x * x).extend(std::iter::once(100)); - | ^^^^^^ method not found in `Map, [closure@method-not-found-generic-arg-elision.rs:87:18]>` +LL | v.iter().map(Box::new(|x| x * x) as Box i32>).extend(std::iter::once(100)); + | ^^^^^^ method not found in `Map, Box i32>>` error[E0599]: no method named `method` found for struct `Wrapper` in the current scope --> $DIR/method-not-found-generic-arg-elision.rs:90:13 diff --git a/tests/ui/nll/closure-requirements/escape-argument-callee.stderr b/tests/ui/nll/closure-requirements/escape-argument-callee.stderr index c0d95ddaa0796..61233fd84077c 100644 --- a/tests/ui/nll/closure-requirements/escape-argument-callee.stderr +++ b/tests/ui/nll/closure-requirements/escape-argument-callee.stderr @@ -17,7 +17,7 @@ LL | let mut closure = expect_sig(|p, y| *p = y); | - - ^^^^^^ assignment requires that `'1` must outlive `'2` | | | | | has type `&'1 i32` - | has type `&'_#2r mut &'2 i32` + | has type `&'?2 mut &'2 i32` note: no external requirements --> $DIR/escape-argument-callee.rs:20:1 diff --git a/tests/ui/nll/closure-requirements/escape-upvar-nested.stderr b/tests/ui/nll/closure-requirements/escape-upvar-nested.stderr index 4fbd5eb19a56c..c00a31ef8e15a 100644 --- a/tests/ui/nll/closure-requirements/escape-upvar-nested.stderr +++ b/tests/ui/nll/closure-requirements/escape-upvar-nested.stderr @@ -7,10 +7,10 @@ LL | let mut closure1 = || p = &y; = note: defining type: test::{closure#0}::{closure#0} with closure substs [ i16, extern "rust-call" fn(()), - (&'_#1r mut &'_#2r i32, &'_#3r i32), + (&'?1 mut &'?2 i32, &'?3 i32), ] = note: number of external vids: 4 - = note: where '_#3r: '_#2r + = note: where '?3: '?2 note: external requirements --> $DIR/escape-upvar-nested.rs:20:27 @@ -21,10 +21,10 @@ LL | let mut closure = || { = note: defining type: test::{closure#0} with closure substs [ i16, extern "rust-call" fn(()), - (&'_#1r mut &'_#2r i32, &'_#3r i32), + (&'?1 mut &'?2 i32, &'?3 i32), ] = note: number of external vids: 4 - = note: where '_#3r: '_#2r + = note: where '?3: '?2 note: no external requirements --> $DIR/escape-upvar-nested.rs:13:1 diff --git a/tests/ui/nll/closure-requirements/escape-upvar-ref.stderr b/tests/ui/nll/closure-requirements/escape-upvar-ref.stderr index bc1ceac5bf01e..2d67e6e7d722a 100644 --- a/tests/ui/nll/closure-requirements/escape-upvar-ref.stderr +++ b/tests/ui/nll/closure-requirements/escape-upvar-ref.stderr @@ -7,10 +7,10 @@ LL | let mut closure = || p = &y; = note: defining type: test::{closure#0} with closure substs [ i16, extern "rust-call" fn(()), - (&'_#1r mut &'_#2r i32, &'_#3r i32), + (&'?1 mut &'?2 i32, &'?3 i32), ] = note: number of external vids: 4 - = note: where '_#3r: '_#2r + = note: where '?3: '?2 note: no external requirements --> $DIR/escape-upvar-ref.rs:17:1 diff --git a/tests/ui/nll/closure-requirements/propagate-approximated-fail-no-postdom.stderr b/tests/ui/nll/closure-requirements/propagate-approximated-fail-no-postdom.stderr index 5a7b12732df68..ba42576d40346 100644 --- a/tests/ui/nll/closure-requirements/propagate-approximated-fail-no-postdom.stderr +++ b/tests/ui/nll/closure-requirements/propagate-approximated-fail-no-postdom.stderr @@ -6,20 +6,20 @@ LL | |_outlives1, _outlives2, _outlives3, x, y| { | = note: defining type: supply::{closure#0} with closure substs [ i16, - for extern "rust-call" fn((std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon(None) }) u32>, std::cell::Cell<&'_#2r &ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon(None) }) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon(None) }) &'_#3r u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon(None) }) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon(None) }) u32>)), + for extern "rust-call" fn((std::cell::Cell<&'?1 &ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon(None) }) u32>, std::cell::Cell<&'?2 &ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon(None) }) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon(None) }) &'?3 u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon(None) }) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon(None) }) u32>)), (), ] - = note: late-bound region is '_#4r - = note: late-bound region is '_#5r - = note: late-bound region is '_#6r + = note: late-bound region is '?4 + = note: late-bound region is '?5 + = note: late-bound region is '?6 error: lifetime may not live long enough --> $DIR/propagate-approximated-fail-no-postdom.rs:46:13 | LL | |_outlives1, _outlives2, _outlives3, x, y| { - | ---------- ---------- has type `Cell<&'2 &'_#3r u32>` + | ---------- ---------- has type `Cell<&'2 &'?3 u32>` | | - | has type `Cell<&'_#1r &'1 u32>` + | has type `Cell<&'?1 &'1 u32>` ... LL | demand_y(x, y, p) | ^^^^^^^^^^^^^^^^^ argument requires that `'1` must outlive `'2` diff --git a/tests/ui/nll/closure-requirements/propagate-approximated-ref.stderr b/tests/ui/nll/closure-requirements/propagate-approximated-ref.stderr index db2ecc779ef96..9dd6e02081faf 100644 --- a/tests/ui/nll/closure-requirements/propagate-approximated-ref.stderr +++ b/tests/ui/nll/closure-requirements/propagate-approximated-ref.stderr @@ -6,13 +6,13 @@ LL | establish_relationships(&cell_a, &cell_b, |_outlives1, _outlives2, x, y | = note: defining type: supply::{closure#0} with closure substs [ i16, - for extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon(None) }) std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon(None) }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 2, kind: BrAnon(None) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 3, kind: BrAnon(None) }) &'_#2r u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 4, kind: BrAnon(None) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon(None) }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 5, kind: BrAnon(None) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 3, kind: BrAnon(None) }) u32>)), + for extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon(None) }) std::cell::Cell<&'?1 &ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon(None) }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 2, kind: BrAnon(None) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 3, kind: BrAnon(None) }) &'?2 u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 4, kind: BrAnon(None) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon(None) }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 5, kind: BrAnon(None) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 3, kind: BrAnon(None) }) u32>)), (), ] - = note: late-bound region is '_#3r - = note: late-bound region is '_#4r + = note: late-bound region is '?3 + = note: late-bound region is '?4 = note: number of external vids: 5 - = note: where '_#1r: '_#2r + = note: where '?1: '?2 note: no external requirements --> $DIR/propagate-approximated-ref.rs:42:1 diff --git a/tests/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-comparing-against-free.stderr b/tests/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-comparing-against-free.stderr index 1d9dafbe55f69..e2f5576d3953f 100644 --- a/tests/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-comparing-against-free.stderr +++ b/tests/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-comparing-against-free.stderr @@ -6,7 +6,7 @@ LL | foo(cell, |cell_a, cell_x| { | = note: defining type: case1::{closure#0} with closure substs [ i32, - for extern "rust-call" fn((std::cell::Cell<&'_#1r u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon(None) }) u32>)), + for extern "rust-call" fn((std::cell::Cell<&'?1 u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon(None) }) u32>)), (), ] @@ -36,11 +36,11 @@ LL | foo(cell, |cell_a, cell_x| { | = note: defining type: case2::{closure#0} with closure substs [ i32, - for extern "rust-call" fn((std::cell::Cell<&'_#1r u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon(None) }) u32>)), + for extern "rust-call" fn((std::cell::Cell<&'?1 u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon(None) }) u32>)), (), ] = note: number of external vids: 2 - = note: where '_#1r: '_#0r + = note: where '?1: '?0 note: no external requirements --> $DIR/propagate-approximated-shorter-to-static-comparing-against-free.rs:28:1 diff --git a/tests/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-no-bound.stderr b/tests/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-no-bound.stderr index 85f7fe35c0aa8..383fb471ad3af 100644 --- a/tests/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-no-bound.stderr +++ b/tests/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-no-bound.stderr @@ -6,13 +6,13 @@ LL | establish_relationships(&cell_a, &cell_b, |_outlives, x, y| { | = note: defining type: supply::{closure#0} with closure substs [ i16, - for extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon(None) }) std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon(None) }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 2, kind: BrAnon(None) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon(None) }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 3, kind: BrAnon(None) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 4, kind: BrAnon(None) }) u32>)), + for extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon(None) }) std::cell::Cell<&'?1 &ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon(None) }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 2, kind: BrAnon(None) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon(None) }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 3, kind: BrAnon(None) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 4, kind: BrAnon(None) }) u32>)), (), ] - = note: late-bound region is '_#2r - = note: late-bound region is '_#3r + = note: late-bound region is '?2 + = note: late-bound region is '?3 = note: number of external vids: 4 - = note: where '_#1r: '_#0r + = note: where '?1: '?0 note: no external requirements --> $DIR/propagate-approximated-shorter-to-static-no-bound.rs:31:1 @@ -40,7 +40,7 @@ LL | | }); | |______`cell_a` escapes the function body here | argument requires that `'a` must outlive `'static` | - = note: requirement occurs because of the type `Cell<&'_#9r u32>`, which makes the generic argument `&'_#9r u32` invariant + = note: requirement occurs because of the type `Cell<&'?9 u32>`, which makes the generic argument `&'?9 u32` invariant = note: the struct `Cell` is invariant over the parameter `T` = help: see for more information about variance diff --git a/tests/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-wrong-bound.stderr b/tests/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-wrong-bound.stderr index 7194843e203fb..ac346c0b110ae 100644 --- a/tests/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-wrong-bound.stderr +++ b/tests/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-wrong-bound.stderr @@ -6,13 +6,13 @@ LL | establish_relationships(&cell_a, &cell_b, |_outlives1, _outlives2, x, y | = note: defining type: supply::{closure#0} with closure substs [ i16, - for extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon(None) }) std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon(None) }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 2, kind: BrAnon(None) }) std::cell::Cell<&'_#2r &ReLateBound(DebruijnIndex(0), BoundRegion { var: 3, kind: BrAnon(None) }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 4, kind: BrAnon(None) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon(None) }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 5, kind: BrAnon(None) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 3, kind: BrAnon(None) }) u32>)), + for extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon(None) }) std::cell::Cell<&'?1 &ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon(None) }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 2, kind: BrAnon(None) }) std::cell::Cell<&'?2 &ReLateBound(DebruijnIndex(0), BoundRegion { var: 3, kind: BrAnon(None) }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 4, kind: BrAnon(None) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon(None) }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 5, kind: BrAnon(None) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 3, kind: BrAnon(None) }) u32>)), (), ] - = note: late-bound region is '_#3r - = note: late-bound region is '_#4r + = note: late-bound region is '?3 + = note: late-bound region is '?4 = note: number of external vids: 5 - = note: where '_#1r: '_#0r + = note: where '?1: '?0 note: no external requirements --> $DIR/propagate-approximated-shorter-to-static-wrong-bound.rs:34:1 @@ -40,7 +40,7 @@ LL | | }); | |______`cell_a` escapes the function body here | argument requires that `'a` must outlive `'static` | - = note: requirement occurs because of the type `Cell<&'_#10r u32>`, which makes the generic argument `&'_#10r u32` invariant + = note: requirement occurs because of the type `Cell<&'?10 u32>`, which makes the generic argument `&'?10 u32` invariant = note: the struct `Cell` is invariant over the parameter `T` = help: see for more information about variance diff --git a/tests/ui/nll/closure-requirements/propagate-approximated-val.stderr b/tests/ui/nll/closure-requirements/propagate-approximated-val.stderr index 71f8a1c67c679..b217ae19773ab 100644 --- a/tests/ui/nll/closure-requirements/propagate-approximated-val.stderr +++ b/tests/ui/nll/closure-requirements/propagate-approximated-val.stderr @@ -6,13 +6,13 @@ LL | establish_relationships(cell_a, cell_b, |outlives1, outlives2, x, y| { | = note: defining type: test::{closure#0} with closure substs [ i16, - for extern "rust-call" fn((std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon(None) }) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon(None) }) &'_#2r u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon(None) }) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon(None) }) u32>)), + for extern "rust-call" fn((std::cell::Cell<&'?1 &ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon(None) }) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon(None) }) &'?2 u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon(None) }) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon(None) }) u32>)), (), ] - = note: late-bound region is '_#3r - = note: late-bound region is '_#4r + = note: late-bound region is '?3 + = note: late-bound region is '?4 = note: number of external vids: 5 - = note: where '_#1r: '_#2r + = note: where '?1: '?2 note: no external requirements --> $DIR/propagate-approximated-val.rs:35:1 diff --git a/tests/ui/nll/closure-requirements/propagate-despite-same-free-region.stderr b/tests/ui/nll/closure-requirements/propagate-despite-same-free-region.stderr index e1cb97b1c7d90..f31478b6d1cfb 100644 --- a/tests/ui/nll/closure-requirements/propagate-despite-same-free-region.stderr +++ b/tests/ui/nll/closure-requirements/propagate-despite-same-free-region.stderr @@ -6,12 +6,12 @@ LL | |_outlives1, _outlives2, x, y| { | = note: defining type: supply::{closure#0} with closure substs [ i16, - for extern "rust-call" fn((std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon(None) }) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon(None) }) &'_#2r u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon(None) }) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon(None) }) u32>)), + for extern "rust-call" fn((std::cell::Cell<&'?1 &ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon(None) }) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon(None) }) &'?2 u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon(None) }) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon(None) }) u32>)), (), ] - = note: late-bound region is '_#3r + = note: late-bound region is '?3 = note: number of external vids: 4 - = note: where '_#1r: '_#2r + = note: where '?1: '?2 note: no external requirements --> $DIR/propagate-despite-same-free-region.rs:39:1 diff --git a/tests/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-no-bounds.stderr b/tests/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-no-bounds.stderr index b66e8391c0136..1509ade87fa09 100644 --- a/tests/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-no-bounds.stderr +++ b/tests/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-no-bounds.stderr @@ -6,19 +6,19 @@ LL | establish_relationships(&cell_a, &cell_b, |_outlives, x, y| { | = note: defining type: supply::{closure#0} with closure substs [ i16, - for extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon(None) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon(None) }) &'_#1r u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 2, kind: BrAnon(None) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 3, kind: BrAnon(None) }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 4, kind: BrAnon(None) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon(None) }) u32>)), + for extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon(None) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon(None) }) &'?1 u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 2, kind: BrAnon(None) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 3, kind: BrAnon(None) }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 4, kind: BrAnon(None) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon(None) }) u32>)), (), ] - = note: late-bound region is '_#2r - = note: late-bound region is '_#3r + = note: late-bound region is '?2 + = note: late-bound region is '?3 error: lifetime may not live long enough --> $DIR/propagate-fail-to-approximate-longer-no-bounds.rs:37:9 | LL | establish_relationships(&cell_a, &cell_b, |_outlives, x, y| { - | --------- - has type `&'_#7r Cell<&'1 u32>` + | --------- - has type `&'?7 Cell<&'1 u32>` | | - | has type `&'_#5r Cell<&'2 &'_#1r u32>` + | has type `&'?5 Cell<&'2 &'?1 u32>` LL | // Only works if 'x: 'y: LL | demand_y(x, y, x.get()) | ^^^^^^^^^^^^^^^^^^^^^^^ argument requires that `'1` must outlive `'2` diff --git a/tests/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-wrong-bounds.stderr b/tests/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-wrong-bounds.stderr index 49641fd06fdb4..c85a9872e212d 100644 --- a/tests/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-wrong-bounds.stderr +++ b/tests/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-wrong-bounds.stderr @@ -6,19 +6,19 @@ LL | establish_relationships(&cell_a, &cell_b, |_outlives1, _outlives2, x, y | = note: defining type: supply::{closure#0} with closure substs [ i16, - for extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon(None) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon(None) }) &'_#1r u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 2, kind: BrAnon(None) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 3, kind: BrAnon(None) }) &'_#2r u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 4, kind: BrAnon(None) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon(None) }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 5, kind: BrAnon(None) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 3, kind: BrAnon(None) }) u32>)), + for extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon(None) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon(None) }) &'?1 u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 2, kind: BrAnon(None) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 3, kind: BrAnon(None) }) &'?2 u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 4, kind: BrAnon(None) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon(None) }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 5, kind: BrAnon(None) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 3, kind: BrAnon(None) }) u32>)), (), ] - = note: late-bound region is '_#3r - = note: late-bound region is '_#4r + = note: late-bound region is '?3 + = note: late-bound region is '?4 error: lifetime may not live long enough --> $DIR/propagate-fail-to-approximate-longer-wrong-bounds.rs:41:9 | LL | establish_relationships(&cell_a, &cell_b, |_outlives1, _outlives2, x, y| { - | ---------- ---------- has type `&'_#8r Cell<&'2 &'_#2r u32>` + | ---------- ---------- has type `&'?8 Cell<&'2 &'?2 u32>` | | - | has type `&'_#6r Cell<&'1 &'_#1r u32>` + | has type `&'?6 Cell<&'1 &'?1 u32>` LL | // Only works if 'x: 'y: LL | demand_y(x, y, x.get()) | ^^^^^^^^^^^^^^^^^^^^^^^ argument requires that `'1` must outlive `'2` diff --git a/tests/ui/nll/closure-requirements/propagate-from-trait-match.stderr b/tests/ui/nll/closure-requirements/propagate-from-trait-match.stderr index 038a5e11f88ce..05e274ab22032 100644 --- a/tests/ui/nll/closure-requirements/propagate-from-trait-match.stderr +++ b/tests/ui/nll/closure-requirements/propagate-from-trait-match.stderr @@ -4,13 +4,13 @@ note: external requirements LL | establish_relationships(value, |value| { | ^^^^^^^ | - = note: defining type: supply::<'_#1r, T>::{closure#0} with closure substs [ + = note: defining type: supply::<'?1, T>::{closure#0} with closure substs [ i32, extern "rust-call" fn((T,)), (), ] = note: number of external vids: 2 - = note: where T: '_#1r + = note: where T: '?1 note: no external requirements --> $DIR/propagate-from-trait-match.rs:28:1 @@ -20,7 +20,7 @@ LL | | where LL | | T: Trait<'a>, | |_________________^ | - = note: defining type: supply::<'_#1r, T> + = note: defining type: supply::<'?1, T> error[E0309]: the parameter type `T` may not live long enough --> $DIR/propagate-from-trait-match.rs:43:9 diff --git a/tests/ui/nll/member-constraints/min-choice.rs b/tests/ui/nll/member-constraints/min-choice.rs index 14b4dae7abfde..f4aca69e19fd9 100644 --- a/tests/ui/nll/member-constraints/min-choice.rs +++ b/tests/ui/nll/member-constraints/min-choice.rs @@ -1,5 +1,5 @@ -// Assuming that the hidden type in these tests is `&'_#15r u8`, -// we have a member constraint: `'_#15r member ['static, 'a, 'b, 'c]`. +// Assuming that the hidden type in these tests is `&'?15 u8`, +// we have a member constraint: `'?15 member ['static, 'a, 'b, 'c]`. // // Make sure we pick up the minimum non-ambiguous region among them. // We will have to exclude `['b, 'c]` because they're incomparable, diff --git a/tests/ui/nll/member-constraints/nested-impl-trait-fail.rs b/tests/ui/nll/member-constraints/nested-impl-trait-fail.rs index 66ff828a84f7c..ceb417f84f3df 100644 --- a/tests/ui/nll/member-constraints/nested-impl-trait-fail.rs +++ b/tests/ui/nll/member-constraints/nested-impl-trait-fail.rs @@ -5,9 +5,9 @@ trait Cap<'a> {} impl Cap<'_> for T {} -// Assuming the hidden type is `[&'_#15r u8; 1]`, we have two distinct member constraints: -// - '_#15r member ['static, 'a, 'b] // from outer impl-trait -// - '_#15r member ['static, 'a, 'b] // from inner impl-trait +// Assuming the hidden type is `[&'?15 u8; 1]`, we have two distinct member constraints: +// - '?15 member ['static, 'a, 'b] // from outer impl-trait +// - '?15 member ['static, 'a, 'b] // from inner impl-trait // To satisfy both we can choose 'a or 'b, so it's a failure due to ambiguity. fn fail_early_bound<'s, 'a, 'b>(a: &'s u8) -> impl IntoIterator + Cap<'b>> where diff --git a/tests/ui/nll/member-constraints/nested-impl-trait-pass.rs b/tests/ui/nll/member-constraints/nested-impl-trait-pass.rs index 15540cb460e7a..4be0f02acf2a2 100644 --- a/tests/ui/nll/member-constraints/nested-impl-trait-pass.rs +++ b/tests/ui/nll/member-constraints/nested-impl-trait-pass.rs @@ -5,9 +5,9 @@ trait Cap<'a> {} impl Cap<'_> for T {} -// Assuming the hidden type is `[&'_#15r u8; 1]`, we have two distinct member constraints: -// - '_#15r member ['static, 'a, 'b] // from outer impl-trait -// - '_#15r member ['static, 'a] // from inner impl-trait +// Assuming the hidden type is `[&'?15 u8; 1]`, we have two distinct member constraints: +// - '?15 member ['static, 'a, 'b] // from outer impl-trait +// - '?15 member ['static, 'a] // from inner impl-trait // To satisfy both we can only choose 'a. fn pass_early_bound<'s, 'a, 'b>(a: &'s u8) -> impl IntoIterator> + Cap<'b> where diff --git a/tests/ui/nll/ty-outlives/projection-no-regions-closure.stderr b/tests/ui/nll/ty-outlives/projection-no-regions-closure.stderr index 4933b93486831..4eefb180ee506 100644 --- a/tests/ui/nll/ty-outlives/projection-no-regions-closure.stderr +++ b/tests/ui/nll/ty-outlives/projection-no-regions-closure.stderr @@ -4,13 +4,13 @@ note: external requirements LL | with_signature(x, |mut y| Box::new(y.next())) | ^^^^^^^ | - = note: defining type: no_region::<'_#1r, T>::{closure#0} with closure substs [ + = note: defining type: no_region::<'?1, T>::{closure#0} with closure substs [ i32, - extern "rust-call" fn((std::boxed::Box,)) -> std::boxed::Box<(dyn Anything + '_#2r)>, + extern "rust-call" fn((std::boxed::Box,)) -> std::boxed::Box<(dyn Anything + '?2)>, (), ] = note: number of external vids: 3 - = note: where ::Item: '_#2r + = note: where ::Item: '?2 note: no external requirements --> $DIR/projection-no-regions-closure.rs:21:1 @@ -20,7 +20,7 @@ LL | | where LL | | T: Iterator, | |________________^ | - = note: defining type: no_region::<'_#1r, T> + = note: defining type: no_region::<'?1, T> error[E0309]: the associated type `::Item` may not live long enough --> $DIR/projection-no-regions-closure.rs:25:31 @@ -37,13 +37,13 @@ note: external requirements LL | with_signature(x, |mut y| Box::new(y.next())) | ^^^^^^^ | - = note: defining type: correct_region::<'_#1r, T>::{closure#0} with closure substs [ + = note: defining type: correct_region::<'?1, T>::{closure#0} with closure substs [ i32, - extern "rust-call" fn((std::boxed::Box,)) -> std::boxed::Box<(dyn Anything + '_#2r)>, + extern "rust-call" fn((std::boxed::Box,)) -> std::boxed::Box<(dyn Anything + '?2)>, (), ] = note: number of external vids: 3 - = note: where ::Item: '_#2r + = note: where ::Item: '?2 note: no external requirements --> $DIR/projection-no-regions-closure.rs:30:1 @@ -53,7 +53,7 @@ LL | | where LL | | T: 'a + Iterator, | |_____________________^ | - = note: defining type: correct_region::<'_#1r, T> + = note: defining type: correct_region::<'?1, T> note: external requirements --> $DIR/projection-no-regions-closure.rs:42:23 @@ -61,13 +61,13 @@ note: external requirements LL | with_signature(x, |mut y| Box::new(y.next())) | ^^^^^^^ | - = note: defining type: wrong_region::<'_#1r, '_#2r, T>::{closure#0} with closure substs [ + = note: defining type: wrong_region::<'?1, '?2, T>::{closure#0} with closure substs [ i32, - extern "rust-call" fn((std::boxed::Box,)) -> std::boxed::Box<(dyn Anything + '_#3r)>, + extern "rust-call" fn((std::boxed::Box,)) -> std::boxed::Box<(dyn Anything + '?3)>, (), ] = note: number of external vids: 4 - = note: where ::Item: '_#3r + = note: where ::Item: '?3 note: no external requirements --> $DIR/projection-no-regions-closure.rs:38:1 @@ -77,7 +77,7 @@ LL | | where LL | | T: 'b + Iterator, | |_____________________^ | - = note: defining type: wrong_region::<'_#1r, '_#2r, T> + = note: defining type: wrong_region::<'?1, '?2, T> error[E0309]: the associated type `::Item` may not live long enough --> $DIR/projection-no-regions-closure.rs:42:31 @@ -94,13 +94,13 @@ note: external requirements LL | with_signature(x, |mut y| Box::new(y.next())) | ^^^^^^^ | - = note: defining type: outlives_region::<'_#1r, '_#2r, T>::{closure#0} with closure substs [ + = note: defining type: outlives_region::<'?1, '?2, T>::{closure#0} with closure substs [ i32, - extern "rust-call" fn((std::boxed::Box,)) -> std::boxed::Box<(dyn Anything + '_#3r)>, + extern "rust-call" fn((std::boxed::Box,)) -> std::boxed::Box<(dyn Anything + '?3)>, (), ] = note: number of external vids: 4 - = note: where ::Item: '_#3r + = note: where ::Item: '?3 note: no external requirements --> $DIR/projection-no-regions-closure.rs:47:1 @@ -111,7 +111,7 @@ LL | | T: 'b + Iterator, LL | | 'b: 'a, | |___________^ | - = note: defining type: outlives_region::<'_#1r, '_#2r, T> + = note: defining type: outlives_region::<'?1, '?2, T> error: aborting due to 2 previous errors diff --git a/tests/ui/nll/ty-outlives/projection-one-region-closure.stderr b/tests/ui/nll/ty-outlives/projection-one-region-closure.stderr index 11ada59c06639..986c2bd2182b4 100644 --- a/tests/ui/nll/ty-outlives/projection-one-region-closure.stderr +++ b/tests/ui/nll/ty-outlives/projection-one-region-closure.stderr @@ -4,15 +4,15 @@ note: external requirements LL | with_signature(cell, t, |cell, t| require(cell, t)); | ^^^^^^^^^ | - = note: defining type: no_relationships_late::<'_#1r, T>::{closure#0} with closure substs [ + = note: defining type: no_relationships_late::<'?1, T>::{closure#0} with closure substs [ i32, - extern "rust-call" fn((std::cell::Cell<&'_#2r ()>, T)), + extern "rust-call" fn((std::cell::Cell<&'?2 ()>, T)), (), ] - = note: late-bound region is '_#3r + = note: late-bound region is '?3 = note: number of external vids: 4 - = note: where T: '_#2r - = note: where '_#1r: '_#2r + = note: where T: '?2 + = note: where '?1: '?2 note: no external requirements --> $DIR/projection-one-region-closure.rs:41:1 @@ -22,7 +22,7 @@ LL | | where LL | | T: Anything<'b>, | |____________________^ | - = note: defining type: no_relationships_late::<'_#1r, T> + = note: defining type: no_relationships_late::<'?1, T> error[E0309]: the parameter type `T` may not live long enough --> $DIR/projection-one-region-closure.rs:45:39 @@ -54,14 +54,14 @@ note: external requirements LL | with_signature(cell, t, |cell, t| require(cell, t)); | ^^^^^^^^^ | - = note: defining type: no_relationships_early::<'_#1r, '_#2r, T>::{closure#0} with closure substs [ + = note: defining type: no_relationships_early::<'?1, '?2, T>::{closure#0} with closure substs [ i32, - extern "rust-call" fn((std::cell::Cell<&'_#3r ()>, T)), + extern "rust-call" fn((std::cell::Cell<&'?3 ()>, T)), (), ] = note: number of external vids: 4 - = note: where T: '_#3r - = note: where '_#2r: '_#3r + = note: where T: '?3 + = note: where '?2: '?3 note: no external requirements --> $DIR/projection-one-region-closure.rs:51:1 @@ -72,7 +72,7 @@ LL | | T: Anything<'b>, LL | | 'a: 'a, | |___________^ | - = note: defining type: no_relationships_early::<'_#1r, '_#2r, T> + = note: defining type: no_relationships_early::<'?1, '?2, T> error[E0309]: the parameter type `T` may not live long enough --> $DIR/projection-one-region-closure.rs:56:39 @@ -104,13 +104,13 @@ note: external requirements LL | with_signature(cell, t, |cell, t| require(cell, t)); | ^^^^^^^^^ | - = note: defining type: projection_outlives::<'_#1r, '_#2r, T>::{closure#0} with closure substs [ + = note: defining type: projection_outlives::<'?1, '?2, T>::{closure#0} with closure substs [ i32, - extern "rust-call" fn((std::cell::Cell<&'_#3r ()>, T)), + extern "rust-call" fn((std::cell::Cell<&'?3 ()>, T)), (), ] = note: number of external vids: 4 - = note: where >::AssocType: '_#3r + = note: where >::AssocType: '?3 note: no external requirements --> $DIR/projection-one-region-closure.rs:62:1 @@ -121,7 +121,7 @@ LL | | T: Anything<'b>, LL | | T::AssocType: 'a, | |_____________________^ | - = note: defining type: projection_outlives::<'_#1r, '_#2r, T> + = note: defining type: projection_outlives::<'?1, '?2, T> note: external requirements --> $DIR/projection-one-region-closure.rs:80:29 @@ -129,14 +129,14 @@ note: external requirements LL | with_signature(cell, t, |cell, t| require(cell, t)); | ^^^^^^^^^ | - = note: defining type: elements_outlive::<'_#1r, '_#2r, T>::{closure#0} with closure substs [ + = note: defining type: elements_outlive::<'?1, '?2, T>::{closure#0} with closure substs [ i32, - extern "rust-call" fn((std::cell::Cell<&'_#3r ()>, T)), + extern "rust-call" fn((std::cell::Cell<&'?3 ()>, T)), (), ] = note: number of external vids: 4 - = note: where T: '_#3r - = note: where '_#2r: '_#3r + = note: where T: '?3 + = note: where '?2: '?3 note: no external requirements --> $DIR/projection-one-region-closure.rs:74:1 @@ -148,7 +148,7 @@ LL | | T: 'a, LL | | 'b: 'a, | |___________^ | - = note: defining type: elements_outlive::<'_#1r, '_#2r, T> + = note: defining type: elements_outlive::<'?1, '?2, T> error: aborting due to 4 previous errors diff --git a/tests/ui/nll/ty-outlives/projection-one-region-trait-bound-closure.stderr b/tests/ui/nll/ty-outlives/projection-one-region-trait-bound-closure.stderr index 47d4f2e46c62b..25cc60d814159 100644 --- a/tests/ui/nll/ty-outlives/projection-one-region-trait-bound-closure.stderr +++ b/tests/ui/nll/ty-outlives/projection-one-region-trait-bound-closure.stderr @@ -4,14 +4,14 @@ note: external requirements LL | with_signature(cell, t, |cell, t| require(cell, t)); | ^^^^^^^^^ | - = note: defining type: no_relationships_late::<'_#1r, T>::{closure#0} with closure substs [ + = note: defining type: no_relationships_late::<'?1, T>::{closure#0} with closure substs [ i32, - extern "rust-call" fn((std::cell::Cell<&'_#2r ()>, T)), + extern "rust-call" fn((std::cell::Cell<&'?2 ()>, T)), (), ] - = note: late-bound region is '_#3r + = note: late-bound region is '?3 = note: number of external vids: 4 - = note: where '_#1r: '_#2r + = note: where '?1: '?2 note: no external requirements --> $DIR/projection-one-region-trait-bound-closure.rs:33:1 @@ -21,7 +21,7 @@ LL | | where LL | | T: Anything<'b>, | |____________________^ | - = note: defining type: no_relationships_late::<'_#1r, T> + = note: defining type: no_relationships_late::<'?1, T> error: lifetime may not live long enough --> $DIR/projection-one-region-trait-bound-closure.rs:37:39 @@ -42,13 +42,13 @@ note: external requirements LL | with_signature(cell, t, |cell, t| require(cell, t)); | ^^^^^^^^^ | - = note: defining type: no_relationships_early::<'_#1r, '_#2r, T>::{closure#0} with closure substs [ + = note: defining type: no_relationships_early::<'?1, '?2, T>::{closure#0} with closure substs [ i32, - extern "rust-call" fn((std::cell::Cell<&'_#3r ()>, T)), + extern "rust-call" fn((std::cell::Cell<&'?3 ()>, T)), (), ] = note: number of external vids: 4 - = note: where '_#2r: '_#3r + = note: where '?2: '?3 note: no external requirements --> $DIR/projection-one-region-trait-bound-closure.rs:42:1 @@ -59,7 +59,7 @@ LL | | T: Anything<'b>, LL | | 'a: 'a, | |___________^ | - = note: defining type: no_relationships_early::<'_#1r, '_#2r, T> + = note: defining type: no_relationships_early::<'?1, '?2, T> error: lifetime may not live long enough --> $DIR/projection-one-region-trait-bound-closure.rs:47:39 @@ -80,13 +80,13 @@ note: external requirements LL | with_signature(cell, t, |cell, t| require(cell, t)); | ^^^^^^^^^ | - = note: defining type: projection_outlives::<'_#1r, '_#2r, T>::{closure#0} with closure substs [ + = note: defining type: projection_outlives::<'?1, '?2, T>::{closure#0} with closure substs [ i32, - extern "rust-call" fn((std::cell::Cell<&'_#3r ()>, T)), + extern "rust-call" fn((std::cell::Cell<&'?3 ()>, T)), (), ] = note: number of external vids: 4 - = note: where >::AssocType: '_#3r + = note: where >::AssocType: '?3 note: no external requirements --> $DIR/projection-one-region-trait-bound-closure.rs:52:1 @@ -97,7 +97,7 @@ LL | | T: Anything<'b>, LL | | T::AssocType: 'a, | |_____________________^ | - = note: defining type: projection_outlives::<'_#1r, '_#2r, T> + = note: defining type: projection_outlives::<'?1, '?2, T> note: external requirements --> $DIR/projection-one-region-trait-bound-closure.rs:69:29 @@ -105,13 +105,13 @@ note: external requirements LL | with_signature(cell, t, |cell, t| require(cell, t)); | ^^^^^^^^^ | - = note: defining type: elements_outlive::<'_#1r, '_#2r, T>::{closure#0} with closure substs [ + = note: defining type: elements_outlive::<'?1, '?2, T>::{closure#0} with closure substs [ i32, - extern "rust-call" fn((std::cell::Cell<&'_#3r ()>, T)), + extern "rust-call" fn((std::cell::Cell<&'?3 ()>, T)), (), ] = note: number of external vids: 4 - = note: where '_#2r: '_#3r + = note: where '?2: '?3 note: no external requirements --> $DIR/projection-one-region-trait-bound-closure.rs:64:1 @@ -122,7 +122,7 @@ LL | | T: Anything<'b>, LL | | 'b: 'a, | |___________^ | - = note: defining type: elements_outlive::<'_#1r, '_#2r, T> + = note: defining type: elements_outlive::<'?1, '?2, T> note: external requirements --> $DIR/projection-one-region-trait-bound-closure.rs:81:29 @@ -130,13 +130,13 @@ note: external requirements LL | with_signature(cell, t, |cell, t| require(cell, t)); | ^^^^^^^^^ | - = note: defining type: one_region::<'_#1r, T>::{closure#0} with closure substs [ + = note: defining type: one_region::<'?1, T>::{closure#0} with closure substs [ i32, - extern "rust-call" fn((std::cell::Cell<&'_#2r ()>, T)), + extern "rust-call" fn((std::cell::Cell<&'?2 ()>, T)), (), ] = note: number of external vids: 3 - = note: where '_#1r: '_#2r + = note: where '?1: '?2 note: no external requirements --> $DIR/projection-one-region-trait-bound-closure.rs:73:1 @@ -146,7 +146,7 @@ LL | | where LL | | T: Anything<'a>, | |____________________^ | - = note: defining type: one_region::<'_#1r, T> + = note: defining type: one_region::<'?1, T> error: aborting due to 2 previous errors diff --git a/tests/ui/nll/ty-outlives/projection-one-region-trait-bound-static-closure.stderr b/tests/ui/nll/ty-outlives/projection-one-region-trait-bound-static-closure.stderr index b27186b053735..5a092d7b8497a 100644 --- a/tests/ui/nll/ty-outlives/projection-one-region-trait-bound-static-closure.stderr +++ b/tests/ui/nll/ty-outlives/projection-one-region-trait-bound-static-closure.stderr @@ -4,12 +4,12 @@ note: no external requirements LL | with_signature(cell, t, |cell, t| require(cell, t)); | ^^^^^^^^^ | - = note: defining type: no_relationships_late::<'_#1r, T>::{closure#0} with closure substs [ + = note: defining type: no_relationships_late::<'?1, T>::{closure#0} with closure substs [ i32, - extern "rust-call" fn((std::cell::Cell<&'_#2r ()>, T)), + extern "rust-call" fn((std::cell::Cell<&'?2 ()>, T)), (), ] - = note: late-bound region is '_#3r + = note: late-bound region is '?3 note: no external requirements --> $DIR/projection-one-region-trait-bound-static-closure.rs:32:1 @@ -19,7 +19,7 @@ LL | | where LL | | T: Anything<'b>, | |____________________^ | - = note: defining type: no_relationships_late::<'_#1r, T> + = note: defining type: no_relationships_late::<'?1, T> note: no external requirements --> $DIR/projection-one-region-trait-bound-static-closure.rs:45:29 @@ -27,9 +27,9 @@ note: no external requirements LL | with_signature(cell, t, |cell, t| require(cell, t)); | ^^^^^^^^^ | - = note: defining type: no_relationships_early::<'_#1r, '_#2r, T>::{closure#0} with closure substs [ + = note: defining type: no_relationships_early::<'?1, '?2, T>::{closure#0} with closure substs [ i32, - extern "rust-call" fn((std::cell::Cell<&'_#3r ()>, T)), + extern "rust-call" fn((std::cell::Cell<&'?3 ()>, T)), (), ] @@ -42,7 +42,7 @@ LL | | T: Anything<'b>, LL | | 'a: 'a, | |___________^ | - = note: defining type: no_relationships_early::<'_#1r, '_#2r, T> + = note: defining type: no_relationships_early::<'?1, '?2, T> note: no external requirements --> $DIR/projection-one-region-trait-bound-static-closure.rs:64:29 @@ -50,9 +50,9 @@ note: no external requirements LL | with_signature(cell, t, |cell, t| require(cell, t)); | ^^^^^^^^^ | - = note: defining type: projection_outlives::<'_#1r, '_#2r, T>::{closure#0} with closure substs [ + = note: defining type: projection_outlives::<'?1, '?2, T>::{closure#0} with closure substs [ i32, - extern "rust-call" fn((std::cell::Cell<&'_#3r ()>, T)), + extern "rust-call" fn((std::cell::Cell<&'?3 ()>, T)), (), ] @@ -65,7 +65,7 @@ LL | | T: Anything<'b>, LL | | T::AssocType: 'a, | |_____________________^ | - = note: defining type: projection_outlives::<'_#1r, '_#2r, T> + = note: defining type: projection_outlives::<'?1, '?2, T> note: no external requirements --> $DIR/projection-one-region-trait-bound-static-closure.rs:73:29 @@ -73,9 +73,9 @@ note: no external requirements LL | with_signature(cell, t, |cell, t| require(cell, t)); | ^^^^^^^^^ | - = note: defining type: elements_outlive::<'_#1r, '_#2r, T>::{closure#0} with closure substs [ + = note: defining type: elements_outlive::<'?1, '?2, T>::{closure#0} with closure substs [ i32, - extern "rust-call" fn((std::cell::Cell<&'_#3r ()>, T)), + extern "rust-call" fn((std::cell::Cell<&'?3 ()>, T)), (), ] @@ -88,7 +88,7 @@ LL | | T: Anything<'b>, LL | | 'b: 'a, | |___________^ | - = note: defining type: elements_outlive::<'_#1r, '_#2r, T> + = note: defining type: elements_outlive::<'?1, '?2, T> note: no external requirements --> $DIR/projection-one-region-trait-bound-static-closure.rs:85:29 @@ -96,9 +96,9 @@ note: no external requirements LL | with_signature(cell, t, |cell, t| require(cell, t)); | ^^^^^^^^^ | - = note: defining type: one_region::<'_#1r, T>::{closure#0} with closure substs [ + = note: defining type: one_region::<'?1, T>::{closure#0} with closure substs [ i32, - extern "rust-call" fn((std::cell::Cell<&'_#2r ()>, T)), + extern "rust-call" fn((std::cell::Cell<&'?2 ()>, T)), (), ] @@ -110,5 +110,5 @@ LL | | where LL | | T: Anything<'a>, | |____________________^ | - = note: defining type: one_region::<'_#1r, T> + = note: defining type: one_region::<'?1, T> diff --git a/tests/ui/nll/ty-outlives/projection-two-region-trait-bound-closure.stderr b/tests/ui/nll/ty-outlives/projection-two-region-trait-bound-closure.stderr index 530dd86819dc3..51283aa88289f 100644 --- a/tests/ui/nll/ty-outlives/projection-two-region-trait-bound-closure.stderr +++ b/tests/ui/nll/ty-outlives/projection-two-region-trait-bound-closure.stderr @@ -4,14 +4,14 @@ note: external requirements LL | with_signature(cell, t, |cell, t| require(cell, t)); | ^^^^^^^^^ | - = note: defining type: no_relationships_late::<'_#1r, '_#2r, T>::{closure#0} with closure substs [ + = note: defining type: no_relationships_late::<'?1, '?2, T>::{closure#0} with closure substs [ i32, - extern "rust-call" fn((std::cell::Cell<&'_#3r ()>, T)), + extern "rust-call" fn((std::cell::Cell<&'?3 ()>, T)), (), ] - = note: late-bound region is '_#4r + = note: late-bound region is '?4 = note: number of external vids: 5 - = note: where >::AssocType: '_#3r + = note: where >::AssocType: '?3 note: no external requirements --> $DIR/projection-two-region-trait-bound-closure.rs:34:1 @@ -21,16 +21,16 @@ LL | | where LL | | T: Anything<'b, 'c>, | |________________________^ | - = note: defining type: no_relationships_late::<'_#1r, '_#2r, T> + = note: defining type: no_relationships_late::<'?1, '?2, T> -error[E0309]: the associated type `>::AssocType` may not live long enough +error[E0309]: the associated type `>::AssocType` may not live long enough --> $DIR/projection-two-region-trait-bound-closure.rs:38:39 | LL | with_signature(cell, t, |cell, t| require(cell, t)); | ^^^^^^^^^^^^^^^^ | - = help: consider adding an explicit lifetime bound `>::AssocType: 'a`... - = note: ...so that the type `>::AssocType` will meet its required lifetime bounds + = help: consider adding an explicit lifetime bound `>::AssocType: 'a`... + = note: ...so that the type `>::AssocType` will meet its required lifetime bounds note: external requirements --> $DIR/projection-two-region-trait-bound-closure.rs:48:29 @@ -38,13 +38,13 @@ note: external requirements LL | with_signature(cell, t, |cell, t| require(cell, t)); | ^^^^^^^^^ | - = note: defining type: no_relationships_early::<'_#1r, '_#2r, '_#3r, T>::{closure#0} with closure substs [ + = note: defining type: no_relationships_early::<'?1, '?2, '?3, T>::{closure#0} with closure substs [ i32, - extern "rust-call" fn((std::cell::Cell<&'_#4r ()>, T)), + extern "rust-call" fn((std::cell::Cell<&'?4 ()>, T)), (), ] = note: number of external vids: 5 - = note: where >::AssocType: '_#4r + = note: where >::AssocType: '?4 note: no external requirements --> $DIR/projection-two-region-trait-bound-closure.rs:43:1 @@ -55,16 +55,16 @@ LL | | T: Anything<'b, 'c>, LL | | 'a: 'a, | |___________^ | - = note: defining type: no_relationships_early::<'_#1r, '_#2r, '_#3r, T> + = note: defining type: no_relationships_early::<'?1, '?2, '?3, T> -error[E0309]: the associated type `>::AssocType` may not live long enough +error[E0309]: the associated type `>::AssocType` may not live long enough --> $DIR/projection-two-region-trait-bound-closure.rs:48:39 | LL | with_signature(cell, t, |cell, t| require(cell, t)); | ^^^^^^^^^^^^^^^^ | - = help: consider adding an explicit lifetime bound `>::AssocType: 'a`... - = note: ...so that the type `>::AssocType` will meet its required lifetime bounds + = help: consider adding an explicit lifetime bound `>::AssocType: 'a`... + = note: ...so that the type `>::AssocType` will meet its required lifetime bounds note: external requirements --> $DIR/projection-two-region-trait-bound-closure.rs:61:29 @@ -72,13 +72,13 @@ note: external requirements LL | with_signature(cell, t, |cell, t| require(cell, t)); | ^^^^^^^^^ | - = note: defining type: projection_outlives::<'_#1r, '_#2r, '_#3r, T>::{closure#0} with closure substs [ + = note: defining type: projection_outlives::<'?1, '?2, '?3, T>::{closure#0} with closure substs [ i32, - extern "rust-call" fn((std::cell::Cell<&'_#4r ()>, T)), + extern "rust-call" fn((std::cell::Cell<&'?4 ()>, T)), (), ] = note: number of external vids: 5 - = note: where >::AssocType: '_#4r + = note: where >::AssocType: '?4 note: no external requirements --> $DIR/projection-two-region-trait-bound-closure.rs:53:1 @@ -89,7 +89,7 @@ LL | | T: Anything<'b, 'c>, LL | | T::AssocType: 'a, | |_____________________^ | - = note: defining type: projection_outlives::<'_#1r, '_#2r, '_#3r, T> + = note: defining type: projection_outlives::<'?1, '?2, '?3, T> note: external requirements --> $DIR/projection-two-region-trait-bound-closure.rs:70:29 @@ -97,13 +97,13 @@ note: external requirements LL | with_signature(cell, t, |cell, t| require(cell, t)); | ^^^^^^^^^ | - = note: defining type: elements_outlive1::<'_#1r, '_#2r, '_#3r, T>::{closure#0} with closure substs [ + = note: defining type: elements_outlive1::<'?1, '?2, '?3, T>::{closure#0} with closure substs [ i32, - extern "rust-call" fn((std::cell::Cell<&'_#4r ()>, T)), + extern "rust-call" fn((std::cell::Cell<&'?4 ()>, T)), (), ] = note: number of external vids: 5 - = note: where >::AssocType: '_#4r + = note: where >::AssocType: '?4 note: no external requirements --> $DIR/projection-two-region-trait-bound-closure.rs:65:1 @@ -114,7 +114,7 @@ LL | | T: Anything<'b, 'c>, LL | | 'b: 'a, | |___________^ | - = note: defining type: elements_outlive1::<'_#1r, '_#2r, '_#3r, T> + = note: defining type: elements_outlive1::<'?1, '?2, '?3, T> note: external requirements --> $DIR/projection-two-region-trait-bound-closure.rs:79:29 @@ -122,13 +122,13 @@ note: external requirements LL | with_signature(cell, t, |cell, t| require(cell, t)); | ^^^^^^^^^ | - = note: defining type: elements_outlive2::<'_#1r, '_#2r, '_#3r, T>::{closure#0} with closure substs [ + = note: defining type: elements_outlive2::<'?1, '?2, '?3, T>::{closure#0} with closure substs [ i32, - extern "rust-call" fn((std::cell::Cell<&'_#4r ()>, T)), + extern "rust-call" fn((std::cell::Cell<&'?4 ()>, T)), (), ] = note: number of external vids: 5 - = note: where >::AssocType: '_#4r + = note: where >::AssocType: '?4 note: no external requirements --> $DIR/projection-two-region-trait-bound-closure.rs:74:1 @@ -139,7 +139,7 @@ LL | | T: Anything<'b, 'c>, LL | | 'c: 'a, | |___________^ | - = note: defining type: elements_outlive2::<'_#1r, '_#2r, '_#3r, T> + = note: defining type: elements_outlive2::<'?1, '?2, '?3, T> note: external requirements --> $DIR/projection-two-region-trait-bound-closure.rs:87:29 @@ -147,14 +147,14 @@ note: external requirements LL | with_signature(cell, t, |cell, t| require(cell, t)); | ^^^^^^^^^ | - = note: defining type: two_regions::<'_#1r, T>::{closure#0} with closure substs [ + = note: defining type: two_regions::<'?1, T>::{closure#0} with closure substs [ i32, - extern "rust-call" fn((std::cell::Cell<&'_#2r ()>, T)), + extern "rust-call" fn((std::cell::Cell<&'?2 ()>, T)), (), ] - = note: late-bound region is '_#3r + = note: late-bound region is '?3 = note: number of external vids: 4 - = note: where >::AssocType: '_#2r + = note: where >::AssocType: '?2 note: no external requirements --> $DIR/projection-two-region-trait-bound-closure.rs:83:1 @@ -164,7 +164,7 @@ LL | | where LL | | T: Anything<'b, 'b>, | |________________________^ | - = note: defining type: two_regions::<'_#1r, T> + = note: defining type: two_regions::<'?1, T> error: lifetime may not live long enough --> $DIR/projection-two-region-trait-bound-closure.rs:87:5 @@ -178,7 +178,7 @@ LL | with_signature(cell, t, |cell, t| require(cell, t)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ argument requires that `'b` must outlive `'a` | = help: consider adding the following bound: `'b: 'a` - = note: requirement occurs because of the type `Cell<&'_#8r ()>`, which makes the generic argument `&'_#8r ()` invariant + = note: requirement occurs because of the type `Cell<&'?8 ()>`, which makes the generic argument `&'?8 ()` invariant = note: the struct `Cell` is invariant over the parameter `T` = help: see for more information about variance @@ -188,13 +188,13 @@ note: external requirements LL | with_signature(cell, t, |cell, t| require(cell, t)); | ^^^^^^^^^ | - = note: defining type: two_regions_outlive::<'_#1r, '_#2r, T>::{closure#0} with closure substs [ + = note: defining type: two_regions_outlive::<'?1, '?2, T>::{closure#0} with closure substs [ i32, - extern "rust-call" fn((std::cell::Cell<&'_#3r ()>, T)), + extern "rust-call" fn((std::cell::Cell<&'?3 ()>, T)), (), ] = note: number of external vids: 4 - = note: where >::AssocType: '_#3r + = note: where >::AssocType: '?3 note: no external requirements --> $DIR/projection-two-region-trait-bound-closure.rs:92:1 @@ -205,7 +205,7 @@ LL | | T: Anything<'b, 'b>, LL | | 'b: 'a, | |___________^ | - = note: defining type: two_regions_outlive::<'_#1r, '_#2r, T> + = note: defining type: two_regions_outlive::<'?1, '?2, T> note: external requirements --> $DIR/projection-two-region-trait-bound-closure.rs:109:29 @@ -213,13 +213,13 @@ note: external requirements LL | with_signature(cell, t, |cell, t| require(cell, t)); | ^^^^^^^^^ | - = note: defining type: one_region::<'_#1r, T>::{closure#0} with closure substs [ + = note: defining type: one_region::<'?1, T>::{closure#0} with closure substs [ i32, - extern "rust-call" fn((std::cell::Cell<&'_#2r ()>, T)), + extern "rust-call" fn((std::cell::Cell<&'?2 ()>, T)), (), ] = note: number of external vids: 3 - = note: where >::AssocType: '_#2r + = note: where >::AssocType: '?2 note: no external requirements --> $DIR/projection-two-region-trait-bound-closure.rs:101:1 @@ -229,7 +229,7 @@ LL | | where LL | | T: Anything<'a, 'a>, | |________________________^ | - = note: defining type: one_region::<'_#1r, T> + = note: defining type: one_region::<'?1, T> error: aborting due to 3 previous errors diff --git a/tests/ui/nll/ty-outlives/ty-param-closure-approximate-lower-bound.stderr b/tests/ui/nll/ty-outlives/ty-param-closure-approximate-lower-bound.stderr index 2c4a0597554a3..04616f9b7028b 100644 --- a/tests/ui/nll/ty-outlives/ty-param-closure-approximate-lower-bound.stderr +++ b/tests/ui/nll/ty-outlives/ty-param-closure-approximate-lower-bound.stderr @@ -6,11 +6,11 @@ LL | twice(cell, value, |a, b| invoke(a, b)); | = note: defining type: generic::::{closure#0} with closure substs [ i16, - for extern "rust-call" fn((std::option::Option>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon(None) }) T)), + for extern "rust-call" fn((std::option::Option>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon(None) }) T)), (), ] = note: number of external vids: 2 - = note: where T: '_#1r + = note: where T: '?1 note: no external requirements --> $DIR/ty-param-closure-approximate-lower-bound.rs:22:1 @@ -28,12 +28,12 @@ LL | twice(cell, value, |a, b| invoke(a, b)); | = note: defining type: generic_fail::::{closure#0} with closure substs [ i16, - for extern "rust-call" fn((std::option::Option>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon(None) }) T)), + for extern "rust-call" fn((std::option::Option>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon(None) }) T)), (), ] - = note: late-bound region is '_#2r + = note: late-bound region is '?2 = note: number of external vids: 3 - = note: where T: '_#1r + = note: where T: '?1 note: no external requirements --> $DIR/ty-param-closure-approximate-lower-bound.rs:28:1 diff --git a/tests/ui/nll/ty-outlives/ty-param-closure-outlives-from-return-type.rs b/tests/ui/nll/ty-outlives/ty-param-closure-outlives-from-return-type.rs index 4343c3aee53f3..72b18c1673259 100644 --- a/tests/ui/nll/ty-outlives/ty-param-closure-outlives-from-return-type.rs +++ b/tests/ui/nll/ty-outlives/ty-param-closure-outlives-from-return-type.rs @@ -19,8 +19,8 @@ where // Here, the closure winds up being required to prove that `T: // 'a`. In principle, it could know that, except that it is // type-checked in a fully generic way, and hence it winds up with - // a propagated requirement that `T: '_#2`, where `'_#2` appears - // in the return type. The caller makes the mapping from `'_#2` to + // a propagated requirement that `T: '?2`, where `'?2` appears + // in the return type. The caller makes the mapping from `'?2` to // `'a` (and subsequently reports an error). with_signature(x, |y| y) diff --git a/tests/ui/nll/ty-outlives/ty-param-closure-outlives-from-return-type.stderr b/tests/ui/nll/ty-outlives/ty-param-closure-outlives-from-return-type.stderr index 35979c8bf5171..d580774ff8cbf 100644 --- a/tests/ui/nll/ty-outlives/ty-param-closure-outlives-from-return-type.stderr +++ b/tests/ui/nll/ty-outlives/ty-param-closure-outlives-from-return-type.stderr @@ -4,13 +4,13 @@ note: external requirements LL | with_signature(x, |y| y) | ^^^ | - = note: defining type: no_region::<'_#1r, T>::{closure#0} with closure substs [ + = note: defining type: no_region::<'?1, T>::{closure#0} with closure substs [ i32, - extern "rust-call" fn((std::boxed::Box,)) -> std::boxed::Box<(dyn std::fmt::Debug + '_#2r)>, + extern "rust-call" fn((std::boxed::Box,)) -> std::boxed::Box<(dyn std::fmt::Debug + '?2)>, (), ] = note: number of external vids: 3 - = note: where T: '_#2r + = note: where T: '?2 note: no external requirements --> $DIR/ty-param-closure-outlives-from-return-type.rs:15:1 @@ -20,7 +20,7 @@ LL | | where LL | | T: Debug, | |_____________^ | - = note: defining type: no_region::<'_#1r, T> + = note: defining type: no_region::<'?1, T> error[E0309]: the parameter type `T` may not live long enough --> $DIR/ty-param-closure-outlives-from-return-type.rs:26:27 diff --git a/tests/ui/nll/ty-outlives/ty-param-closure-outlives-from-where-clause.stderr b/tests/ui/nll/ty-outlives/ty-param-closure-outlives-from-where-clause.stderr index 4c97db58c6c3d..3d4c11a3c547a 100644 --- a/tests/ui/nll/ty-outlives/ty-param-closure-outlives-from-where-clause.stderr +++ b/tests/ui/nll/ty-outlives/ty-param-closure-outlives-from-where-clause.stderr @@ -6,12 +6,12 @@ LL | with_signature(a, b, |x, y| { | = note: defining type: no_region::::{closure#0} with closure substs [ i32, - extern "rust-call" fn((std::cell::Cell<&'_#1r ()>, T)), + extern "rust-call" fn((std::cell::Cell<&'?1 ()>, T)), (), ] - = note: late-bound region is '_#2r + = note: late-bound region is '?2 = note: number of external vids: 3 - = note: where T: '_#1r + = note: where T: '?1 note: no external requirements --> $DIR/ty-param-closure-outlives-from-where-clause.rs:26:1 @@ -38,13 +38,13 @@ note: external requirements LL | with_signature(a, b, |x, y| { | ^^^^^^ | - = note: defining type: correct_region::<'_#1r, T>::{closure#0} with closure substs [ + = note: defining type: correct_region::<'?1, T>::{closure#0} with closure substs [ i32, - extern "rust-call" fn((std::cell::Cell<&'_#2r ()>, T)), + extern "rust-call" fn((std::cell::Cell<&'?2 ()>, T)), (), ] = note: number of external vids: 3 - = note: where T: '_#2r + = note: where T: '?2 note: no external requirements --> $DIR/ty-param-closure-outlives-from-where-clause.rs:38:1 @@ -54,7 +54,7 @@ LL | | where LL | | T: 'a, | |__________^ | - = note: defining type: correct_region::<'_#1r, T> + = note: defining type: correct_region::<'?1, T> note: external requirements --> $DIR/ty-param-closure-outlives-from-where-clause.rs:63:26 @@ -62,14 +62,14 @@ note: external requirements LL | with_signature(a, b, |x, y| { | ^^^^^^ | - = note: defining type: wrong_region::<'_#1r, T>::{closure#0} with closure substs [ + = note: defining type: wrong_region::<'?1, T>::{closure#0} with closure substs [ i32, - extern "rust-call" fn((std::cell::Cell<&'_#2r ()>, T)), + extern "rust-call" fn((std::cell::Cell<&'?2 ()>, T)), (), ] - = note: late-bound region is '_#3r + = note: late-bound region is '?3 = note: number of external vids: 4 - = note: where T: '_#2r + = note: where T: '?2 note: no external requirements --> $DIR/ty-param-closure-outlives-from-where-clause.rs:59:1 @@ -79,7 +79,7 @@ LL | | where LL | | T: 'b, | |__________^ | - = note: defining type: wrong_region::<'_#1r, T> + = note: defining type: wrong_region::<'?1, T> error[E0309]: the parameter type `T` may not live long enough --> $DIR/ty-param-closure-outlives-from-where-clause.rs:65:9 @@ -98,13 +98,13 @@ note: external requirements LL | with_signature(a, b, |x, y| { | ^^^^^^ | - = note: defining type: outlives_region::<'_#1r, '_#2r, T>::{closure#0} with closure substs [ + = note: defining type: outlives_region::<'?1, '?2, T>::{closure#0} with closure substs [ i32, - extern "rust-call" fn((std::cell::Cell<&'_#3r ()>, T)), + extern "rust-call" fn((std::cell::Cell<&'?3 ()>, T)), (), ] = note: number of external vids: 4 - = note: where T: '_#3r + = note: where T: '?3 note: no external requirements --> $DIR/ty-param-closure-outlives-from-where-clause.rs:71:1 @@ -115,7 +115,7 @@ LL | | T: 'b, LL | | 'b: 'a, | |___________^ | - = note: defining type: outlives_region::<'_#1r, '_#2r, T> + = note: defining type: outlives_region::<'?1, '?2, T> error: aborting due to 2 previous errors diff --git a/tests/ui/process/process-sigpipe.rs b/tests/ui/process/process-sigpipe.rs index 7ae14c6b84d2f..4f4db11911594 100644 --- a/tests/ui/process/process-sigpipe.rs +++ b/tests/ui/process/process-sigpipe.rs @@ -8,14 +8,14 @@ // libstd ignores SIGPIPE, and other libraries may set signal masks. // Make sure that these behaviors don't get inherited to children // spawned via std::process, since they're needed for traditional UNIX -// filter behavior. This test checks that `yes | head` terminates +// filter behavior. +// This test checks that `while echo y ; do : ; done | head` terminates // (instead of running forever), and that it does not print an error // message about a broken pipe. // ignore-emscripten no threads support // ignore-vxworks no 'sh' // ignore-fuchsia no 'sh' -// ignore-nto no 'yes' use std::process; use std::thread; @@ -27,7 +27,11 @@ fn main() { thread::sleep_ms(5000); process::exit(1); }); - let output = process::Command::new("sh").arg("-c").arg("yes | head").output().unwrap(); + let output = process::Command::new("sh") + .arg("-c") + .arg("while echo y ; do : ; done | head") + .output() + .unwrap(); assert!(output.status.success()); assert!(output.stderr.len() == 0); } diff --git a/tests/ui/repr/repr-transparent.stderr b/tests/ui/repr/repr-transparent.stderr index f1c570b952356..cb1e233777656 100644 --- a/tests/ui/repr/repr-transparent.stderr +++ b/tests/ui/repr/repr-transparent.stderr @@ -58,7 +58,7 @@ error[E0731]: transparent enum needs exactly one variant, but has 2 LL | enum MultipleVariants { | ^^^^^^^^^^^^^^^^^^^^^ needs exactly one variant, but has 2 LL | Foo(String), - | --- + | --- variant here LL | Bar, | --- too many variants in `MultipleVariants` diff --git a/tests/ui/repr/transparent-enum-too-many-variants.stderr b/tests/ui/repr/transparent-enum-too-many-variants.stderr index fb44757efaf13..1a500257f48c5 100644 --- a/tests/ui/repr/transparent-enum-too-many-variants.stderr +++ b/tests/ui/repr/transparent-enum-too-many-variants.stderr @@ -5,6 +5,8 @@ LL | enum Foo { | ^^^^^^^^ needs exactly one variant, but has 2 LL | A(u8), B(u8), | - - too many variants in `Foo` + | | + | variant here error: aborting due to previous error diff --git a/tests/ui/threads-sendsync/issue-43733-2.rs b/tests/ui/threads-sendsync/issue-43733-2.rs index 8f7a9c0837510..e9653dbe5c222 100644 --- a/tests/ui/threads-sendsync/issue-43733-2.rs +++ b/tests/ui/threads-sendsync/issue-43733-2.rs @@ -21,7 +21,7 @@ impl Key { } #[cfg(target_thread_local)] -use std::thread::__LocalKeyInner as Key; +use std::thread::local_impl::Key; static __KEY: Key<()> = Key::new(); //~^ ERROR `UnsafeCell>` cannot be shared between threads diff --git a/tests/ui/threads-sendsync/issue-43733.mir.stderr b/tests/ui/threads-sendsync/issue-43733.mir.stderr index 1e21a6b37a991..ff83e16add9ef 100644 --- a/tests/ui/threads-sendsync/issue-43733.mir.stderr +++ b/tests/ui/threads-sendsync/issue-43733.mir.stderr @@ -1,5 +1,5 @@ error[E0133]: call to unsafe function is unsafe and requires unsafe function or block - --> $DIR/issue-43733.rs:21:5 + --> $DIR/issue-43733.rs:19:5 | LL | __KEY.get(Default::default) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ call to unsafe function @@ -7,7 +7,7 @@ LL | __KEY.get(Default::default) = note: consult the function's documentation for information on how to avoid undefined behavior error[E0133]: call to unsafe function is unsafe and requires unsafe function or block - --> $DIR/issue-43733.rs:26:42 + --> $DIR/issue-43733.rs:24:42 | LL | static FOO: std::thread::LocalKey = std::thread::LocalKey::new(__getit); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ call to unsafe function diff --git a/tests/ui/threads-sendsync/issue-43733.rs b/tests/ui/threads-sendsync/issue-43733.rs index 0eadef3e3e8cb..cac745f1e12f3 100644 --- a/tests/ui/threads-sendsync/issue-43733.rs +++ b/tests/ui/threads-sendsync/issue-43733.rs @@ -1,8 +1,6 @@ // ignore-wasm32 // revisions: mir thir // [thir]compile-flags: -Z thir-unsafeck -// normalize-stderr-test: "__LocalKeyInner::::get" -> "$$LOCALKEYINNER::::get" -// normalize-stderr-test: "__LocalKeyInner::::get" -> "$$LOCALKEYINNER::::get" #![feature(thread_local)] #![feature(cfg_target_thread_local, thread_local_internals)] @@ -12,15 +10,15 @@ type Foo = std::cell::RefCell; #[cfg(target_thread_local)] #[thread_local] -static __KEY: std::thread::__LocalKeyInner = std::thread::__LocalKeyInner::new(); +static __KEY: std::thread::local_impl::Key = std::thread::local_impl::Key::new(); #[cfg(not(target_thread_local))] -static __KEY: std::thread::__LocalKeyInner = std::thread::__LocalKeyInner::new(); +static __KEY: std::thread::local_impl::Key = std::thread::local_impl::Key::new(); fn __getit(_: Option<&mut Option>>) -> std::option::Option<&'static Foo> { __KEY.get(Default::default) //[mir]~^ ERROR call to unsafe function is unsafe - //[thir]~^^ ERROR call to unsafe function `__ + //[thir]~^^ ERROR call to unsafe function `Key::::get` } static FOO: std::thread::LocalKey = std::thread::LocalKey::new(__getit); diff --git a/tests/ui/threads-sendsync/issue-43733.thir.stderr b/tests/ui/threads-sendsync/issue-43733.thir.stderr index ea7ff4080486d..94ec724044c7a 100644 --- a/tests/ui/threads-sendsync/issue-43733.thir.stderr +++ b/tests/ui/threads-sendsync/issue-43733.thir.stderr @@ -1,5 +1,5 @@ -error[E0133]: call to unsafe function `$LOCALKEYINNER::::get` is unsafe and requires unsafe function or block - --> $DIR/issue-43733.rs:21:5 +error[E0133]: call to unsafe function `Key::::get` is unsafe and requires unsafe function or block + --> $DIR/issue-43733.rs:19:5 | LL | __KEY.get(Default::default) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ call to unsafe function @@ -7,7 +7,7 @@ LL | __KEY.get(Default::default) = note: consult the function's documentation for information on how to avoid undefined behavior error[E0133]: call to unsafe function `LocalKey::::new` is unsafe and requires unsafe function or block - --> $DIR/issue-43733.rs:26:42 + --> $DIR/issue-43733.rs:24:42 | LL | static FOO: std::thread::LocalKey = std::thread::LocalKey::new(__getit); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ call to unsafe function diff --git a/tests/ui/traits/infer-from-object-issue-26952.rs b/tests/ui/traits/infer-from-object-issue-26952.rs index ed258dbb24c3f..9544b4f2088ea 100644 --- a/tests/ui/traits/infer-from-object-issue-26952.rs +++ b/tests/ui/traits/infer-from-object-issue-26952.rs @@ -1,8 +1,8 @@ // run-pass #![allow(dead_code)] #![allow(unused_variables)] -// Test that when we match a trait reference like `Foo: Foo<_#0t>`, -// we unify with `_#0t` with `A`. In this code, if we failed to do +// Test that when we match a trait reference like `Foo: Foo`, +// we unify with `?0t` with `A`. In this code, if we failed to do // that, then you get an unconstrained type-variable in `call`. // // Also serves as a regression test for issue #26952, though the test diff --git a/tests/ui/traits/new-solver/int-var-alias-eq.rs b/tests/ui/traits/new-solver/int-var-alias-eq.rs index 2da387db4a99f..790197e2d97f5 100644 --- a/tests/ui/traits/new-solver/int-var-alias-eq.rs +++ b/tests/ui/traits/new-solver/int-var-alias-eq.rs @@ -1,7 +1,7 @@ // check-pass // compile-flags: -Ztrait-solver=next -// HIR typeck ends up equating `<_#0i as Add>::Output == _#0i`. +// HIR typeck ends up equating `::Output == ?0i`. // Want to make sure that we emit an alias-eq goal for this, // instead of treating it as a type error and bailing. diff --git a/tests/ui/traits/new-solver/negative-coherence-bounds.rs b/tests/ui/traits/new-solver/negative-coherence-bounds.rs new file mode 100644 index 0000000000000..5436b02c3ded2 --- /dev/null +++ b/tests/ui/traits/new-solver/negative-coherence-bounds.rs @@ -0,0 +1,40 @@ +// check-pass + +// This test verifies that negative trait predicate cannot be satisfied from a +// positive param-env candidate. + +// Negative coherence is one of the only places where we actually construct and +// evaluate negative predicates. Specifically, when verifying whether the first +// and second impls below overlap, we do not want to consider them disjoint, +// otherwise the second impl would be missing an associated type `type Item` +// which is provided by the first impl that it is specializing. + +#![feature(specialization)] +//~^ WARN the feature `specialization` is incomplete +#![feature(with_negative_coherence)] + +trait BoxIter { + type Item; + + fn last(self) -> Option; +} + +impl BoxIter for Box { + type Item = I::Item; + + default fn last(self) -> Option { + todo!() + } +} + +// When checking that this impl does/doesn't overlap the one above, we evaluate +// a negative version of all of the where-clause predicates of the impl below. +// For `I: !Iterator`, we should make sure that the param-env clause `I: Iterator` +// from above doesn't satisfy this predicate. +impl BoxIter for Box { + fn last(self) -> Option { + (*self).last() + } +} + +fn main() {} diff --git a/tests/ui/traits/new-solver/negative-coherence-bounds.stderr b/tests/ui/traits/new-solver/negative-coherence-bounds.stderr new file mode 100644 index 0000000000000..4127f51f56da2 --- /dev/null +++ b/tests/ui/traits/new-solver/negative-coherence-bounds.stderr @@ -0,0 +1,12 @@ +warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/negative-coherence-bounds.rs:12:12 + | +LL | #![feature(specialization)] + | ^^^^^^^^^^^^^^ + | + = note: see issue #31844 for more information + = help: consider using `min_specialization` instead, which is more stable and complete + = note: `#[warn(incomplete_features)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/traits/new-solver/two-projection-param-candidates-are-ambiguous.rs b/tests/ui/traits/new-solver/two-projection-param-candidates-are-ambiguous.rs index cde2059ca9b91..3c7fc0d813d0d 100644 --- a/tests/ui/traits/new-solver/two-projection-param-candidates-are-ambiguous.rs +++ b/tests/ui/traits/new-solver/two-projection-param-candidates-are-ambiguous.rs @@ -1,7 +1,7 @@ // compile-flags: -Ztrait-solver=next // When we're solving `::Assoc = i32`, we actually first solve -// `::Assoc = _#1t`, then unify `_#1t` with `i32`. That goal +// `::Assoc = ?1t`, then unify `?1t` with `i32`. That goal // with the inference variable is ambiguous when there are >1 param-env // candidates. diff --git a/tests/ui/type-alias-impl-trait/closure_parent_substs.rs b/tests/ui/type-alias-impl-trait/closure_parent_substs.rs index 475f4724ff28f..3ff20d99ad886 100644 --- a/tests/ui/type-alias-impl-trait/closure_parent_substs.rs +++ b/tests/ui/type-alias-impl-trait/closure_parent_substs.rs @@ -12,7 +12,7 @@ // Basic test mod test1 { - // Hidden type = Closure['_#0r] + // Hidden type = Closure['?0] type Opaque = impl Sized; fn define<'a: 'a>() -> Opaque { @@ -24,8 +24,8 @@ mod test1 { mod test2 { trait Trait {} - // Hidden type = Closure['a, '_#0r, '_#1r] - // Constraints = [('_#0r: 'a), ('a: '_#1r)] + // Hidden type = Closure['a, '?0, '?1] + // Constraints = [('?0: 'a), ('a: '?1)] type Opaque<'a> where &'a (): Trait, @@ -45,8 +45,8 @@ mod test2 { mod test3 { trait Trait {} - // Hidden type = Closure['a, 'b, '_#0r] - // Constraints = [('_#0r: 'a), ('_#0r: 'b)] + // Hidden type = Closure['a, 'b, '?0] + // Constraints = [('?0: 'a), ('?0: 'b)] type Opaque<'a, 'b> where (&'a (), &'b ()): Trait,