diff options
186 files changed, 2444 insertions, 1371 deletions
diff --git a/Cargo.lock b/Cargo.lock index 897a4f6adfb..8d707067bb9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -8,31 +8,29 @@ version = "0.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f4fa78e18c64fce05e902adecd7a5eed15a5e0a3439f7b0e169f0252214865e3" dependencies = [ - "compiler_builtins", "gimli 0.27.3", - "rustc-std-workspace-alloc", - "rustc-std-workspace-core", ] [[package]] -name = "adler" -version = "1.0.2" +name = "addr2line" +version = "0.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" +checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" dependencies = [ "compiler_builtins", + "gimli 0.28.0", + "rustc-std-workspace-alloc", "rustc-std-workspace-core", ] [[package]] -name = "ahash" -version = "0.7.6" +name = "adler" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fcb51a0695d8f838b1ee009b3fbf66bda078cd64590202a864a8f3e8c4315c47" +checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" dependencies = [ - "getrandom", - "once_cell", - "version_check", + "compiler_builtins", + "rustc-std-workspace-core", ] [[package]] @@ -178,11 +176,11 @@ dependencies = [ [[package]] name = "ar_archive_writer" -version = "0.1.4" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74cfb39880a59e122232cb5fb06b20b4382d58c12fa9747d16f846d38a7b094c" +checksum = "9792d37ca5173d7e7f4fe453739a0671d0557915a030a383d6b866476bbc3e71" dependencies = [ - "object", + "object 0.32.0", ] [[package]] @@ -252,12 +250,12 @@ version = "0.3.68" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4319208da049c43661739c5fade2ba182f09d1dc2299b32298d3a31692b17e12" dependencies = [ - "addr2line", + "addr2line 0.20.0", "cc", "cfg-if", "libc", "miniz_oxide", - "object", + "object 0.31.1", "rustc-demangle", ] @@ -1159,9 +1157,9 @@ dependencies = [ [[package]] name = "fallible-iterator" -version = "0.2.0" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4443176a9f2c162692bd3d352d745ef9413eec5782a80d8fd6f8a1ac692a07f7" +checksum = "2acce4a10f12dc2fb14a218589d4f1f62ef011b2d0cc4b3cb1bba8e94da14649" [[package]] name = "fastrand" @@ -1439,24 +1437,22 @@ dependencies = [ [[package]] name = "gimli" -version = "0.26.2" +version = "0.27.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22030e2c5a68ec659fde1e949a745124b48e6fa8b045b7ed5bd1fe4ccc5c4e5d" -dependencies = [ - "fallible-iterator", - "indexmap 1.9.3", - "stable_deref_trait", -] +checksum = "b6c80984affa11d98d1b88b66ac8853f143217b399d3c74116778ff8fdb4ed2e" [[package]] name = "gimli" -version = "0.27.3" +version = "0.28.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6c80984affa11d98d1b88b66ac8853f143217b399d3c74116778ff8fdb4ed2e" +checksum = "6fb8d784f27acf97159b40fc4db5ecd8aa23b9ad5ef69cdd136d3bc80665f0c0" dependencies = [ "compiler_builtins", + "fallible-iterator", + "indexmap 2.0.0", "rustc-std-workspace-alloc", "rustc-std-workspace-core", + "stable_deref_trait", ] [[package]] @@ -1525,18 +1521,6 @@ name = "hashbrown" version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" -dependencies = [ - "ahash 0.7.6", -] - -[[package]] -name = "hashbrown" -version = "0.13.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43a3c133739dddd0d2990f9a4bdf8eb4b21ef50e4851ca85ab661199821d510e" -dependencies = [ - "ahash 0.8.3", -] [[package]] name = "hashbrown" @@ -1544,6 +1528,7 @@ version = "0.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2c6201b9ff9fd90a5a3bac2e56a830d0caa509576f0e503818ee82c181b3437a" dependencies = [ + "ahash", "allocator-api2", "compiler_builtins", "rustc-std-workspace-alloc", @@ -2450,11 +2435,20 @@ version = "0.31.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8bda667d9f2b5051b8833f59f3bf748b28ef54f850f4fcb389a252aa383866d1" dependencies = [ + "memchr", +] + +[[package]] +name = "object" +version = "0.32.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77ac5bbd07aea88c60a577a1ce218075ffd59208b2d7ca97adf9bfc5aeb21ebe" +dependencies = [ "compiler_builtins", "crc32fast", "flate2", - "hashbrown 0.13.2", - "indexmap 1.9.3", + "hashbrown 0.14.0", + "indexmap 2.0.0", "memchr", "rustc-std-workspace-alloc", "rustc-std-workspace-core", @@ -3362,7 +3356,7 @@ dependencies = [ "cstr", "libc", "measureme", - "object", + "object 0.32.0", "rustc-demangle", "rustc_ast", "rustc_attr", @@ -3398,7 +3392,7 @@ dependencies = [ "itertools", "jobserver", "libc", - "object", + "object 0.32.0", "pathdiff", "regex", "rustc_arena", @@ -4332,7 +4326,7 @@ name = "rustc_target" version = "0.0.0" dependencies = [ "bitflags 1.3.2", - "object", + "object 0.32.0", "rustc_abi", "rustc_data_structures", "rustc_feature", @@ -4587,12 +4581,12 @@ checksum = "4f3208ce4d8448b3f3e7d168a73f5e0c43a61e32930de3bceeccedb388b6bf06" [[package]] name = "ruzstd" -version = "0.3.1" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a15e661f0f9dac21f3494fe5d23a6338c0ac116a2d22c2b63010acd89467ffe" +checksum = "ac3ffab8f9715a0d455df4bbb9d21e91135aab3cd3ca187af0cd0c3c3f868fdc" dependencies = [ "byteorder", - "thiserror", + "thiserror-core", "twox-hash", ] @@ -4861,7 +4855,7 @@ checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" name = "std" version = "0.0.0" dependencies = [ - "addr2line", + "addr2line 0.21.0", "alloc", "cfg-if", "compiler_builtins", @@ -4872,7 +4866,7 @@ dependencies = [ "hermit-abi 0.3.2", "libc", "miniz_oxide", - "object", + "object 0.32.0", "panic_abort", "panic_unwind", "profiler_builtins", @@ -5140,6 +5134,26 @@ dependencies = [ ] [[package]] +name = "thiserror-core" +version = "1.0.38" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d97345f6437bb2004cd58819d8a9ef8e36cdd7661c2abc4bbde0a7c40d9f497" +dependencies = [ + "thiserror-core-impl", +] + +[[package]] +name = "thiserror-core-impl" +version = "1.0.38" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "10ac1c5050e43014d16b2f94d0d2ce79e65ffdd8b38d8048f9c8f6a8a6da62ac" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] name = "thiserror-impl" version = "1.0.40" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -5152,13 +5166,13 @@ dependencies = [ [[package]] name = "thorin-dwp" -version = "0.6.0" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "98c040e1340b889d4180c64e1d787efa9c32cb1617757e101480b61238b0d927" +checksum = "4db52ee8fec06e119b692ef3dd2c4cf621a99204c1b8c47407870ed050305b9b" dependencies = [ - "gimli 0.26.2", - "hashbrown 0.12.3", - "object", + "gimli 0.28.0", + "hashbrown 0.14.0", + "object 0.32.0", "tracing", ] diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 89775bdee26..4a47de1280c 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -2495,35 +2495,31 @@ impl<'hir> GenericArgsCtor<'hir> { let id = lcx.next_node_id(); let hir_id = lcx.next_id(); + + let Some(host_param_id) = lcx.host_param_id else { + lcx.tcx + .sess + .delay_span_bug(span, "no host param id for call in const yet no errors reported"); + return; + }; + let body = lcx.lower_body(|lcx| { - ( - &[], - match constness { - ast::Const::Yes(_) => { - let hir_id = lcx.next_id(); - let res = - Res::Def(DefKind::ConstParam, lcx.host_param_id.unwrap().to_def_id()); - let expr_kind = hir::ExprKind::Path(hir::QPath::Resolved( - None, - lcx.arena.alloc(hir::Path { - span, - res, - segments: arena_vec![lcx; hir::PathSegment::new(Ident { - name: sym::host, - span, - }, hir_id, res)], - }), - )); - lcx.expr(span, expr_kind) - } - ast::Const::No => lcx.expr( + (&[], { + let hir_id = lcx.next_id(); + let res = Res::Def(DefKind::ConstParam, host_param_id.to_def_id()); + let expr_kind = hir::ExprKind::Path(hir::QPath::Resolved( + None, + lcx.arena.alloc(hir::Path { span, - hir::ExprKind::Lit( - lcx.arena.alloc(hir::Lit { span, node: ast::LitKind::Bool(true) }), - ), - ), - }, - ) + res, + segments: arena_vec![lcx; hir::PathSegment::new(Ident { + name: sym::host, + span, + }, hir_id, res)], + }), + )); + lcx.expr(span, expr_kind) + }) }); let attr_id = lcx.tcx.sess.parse_sess.attr_id_generator.mk_attr_id(); diff --git a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs index 68dddd65acb..4da7b602571 100644 --- a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs +++ b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs @@ -371,40 +371,27 @@ fn check_opaque_type_parameter_valid( span: Span, ) -> Result<(), ErrorGuaranteed> { let opaque_ty_hir = tcx.hir().expect_item(opaque_type_key.def_id); - match opaque_ty_hir.expect_opaque_ty().origin { - // No need to check return position impl trait (RPIT) - // because for type and const parameters they are correct - // by construction: we convert - // - // fn foo<P0..Pn>() -> impl Trait - // - // into - // - // type Foo<P0...Pn> - // fn foo<P0..Pn>() -> Foo<P0...Pn>. - // - // For lifetime parameters we convert - // - // fn foo<'l0..'ln>() -> impl Trait<'l0..'lm> - // - // into - // - // type foo::<'p0..'pn>::Foo<'q0..'qm> - // fn foo<l0..'ln>() -> foo::<'static..'static>::Foo<'l0..'lm>. - // - // which would error here on all of the `'static` args. - OpaqueTyOrigin::FnReturn(..) | OpaqueTyOrigin::AsyncFn(..) => return Ok(()), - // Check these - OpaqueTyOrigin::TyAlias { .. } => {} - } + let is_ty_alias = match opaque_ty_hir.expect_opaque_ty().origin { + OpaqueTyOrigin::TyAlias { .. } => true, + OpaqueTyOrigin::AsyncFn(..) | OpaqueTyOrigin::FnReturn(..) => false, + }; + let opaque_generics = tcx.generics_of(opaque_type_key.def_id); let mut seen_params: FxIndexMap<_, Vec<_>> = FxIndexMap::default(); for (i, arg) in opaque_type_key.args.iter().enumerate() { + if let Err(guar) = arg.error_reported() { + return Err(guar); + } + let arg_is_param = match arg.unpack() { GenericArgKind::Type(ty) => matches!(ty.kind(), ty::Param(_)), - GenericArgKind::Lifetime(lt) => { + GenericArgKind::Lifetime(lt) if is_ty_alias => { matches!(*lt, ty::ReEarlyBound(_) | ty::ReFree(_)) } + // FIXME(#113916): we can't currently check for unique lifetime params, + // see that issue for more. We will also have to ignore unused lifetime + // params for RPIT, but that's comparatively trivial ✨ + GenericArgKind::Lifetime(_) => continue, GenericArgKind::Const(ct) => matches!(ct.kind(), ty::ConstKind::Param(_)), }; diff --git a/compiler/rustc_codegen_gcc/example/alloc_system.rs b/compiler/rustc_codegen_gcc/example/alloc_system.rs index e756b347e89..3deef419f42 100644 --- a/compiler/rustc_codegen_gcc/example/alloc_system.rs +++ b/compiler/rustc_codegen_gcc/example/alloc_system.rs @@ -12,6 +12,7 @@ target_arch = "mips", target_arch = "mips32r6", target_arch = "powerpc", + target_arch = "csky" target_arch = "powerpc64"))] const MIN_ALIGN: usize = 8; #[cfg(any(target_arch = "x86_64", diff --git a/compiler/rustc_codegen_gcc/src/asm.rs b/compiler/rustc_codegen_gcc/src/asm.rs index 4c3b7f5036c..0482a85f5f3 100644 --- a/compiler/rustc_codegen_gcc/src/asm.rs +++ b/compiler/rustc_codegen_gcc/src/asm.rs @@ -597,6 +597,8 @@ fn reg_to_gcc(reg: InlineAsmRegOrRegClass) -> ConstraintOrRegister { InlineAsmRegClass::M68k(M68kInlineAsmRegClass::reg) => "r", InlineAsmRegClass::M68k(M68kInlineAsmRegClass::reg_addr) => "a", InlineAsmRegClass::M68k(M68kInlineAsmRegClass::reg_data) => "d", + InlineAsmRegClass::CSKY(CSKYInlineAsmRegClass::reg) => "r", + InlineAsmRegClass::CSKY(CSKYInlineAsmRegClass::freg) => "f", InlineAsmRegClass::Mips(MipsInlineAsmRegClass::reg) => "d", // more specific than "r" InlineAsmRegClass::Mips(MipsInlineAsmRegClass::freg) => "f", InlineAsmRegClass::Msp430(Msp430InlineAsmRegClass::reg) => "r", @@ -673,6 +675,8 @@ fn dummy_output_type<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, reg: InlineAsmRegCl InlineAsmRegClass::M68k(M68kInlineAsmRegClass::reg) => cx.type_i32(), InlineAsmRegClass::M68k(M68kInlineAsmRegClass::reg_addr) => cx.type_i32(), InlineAsmRegClass::M68k(M68kInlineAsmRegClass::reg_data) => cx.type_i32(), + InlineAsmRegClass::CSKY(CSKYInlineAsmRegClass::reg) => cx.type_i32(), + InlineAsmRegClass::CSKY(CSKYInlineAsmRegClass::freg) => cx.type_f32(), InlineAsmRegClass::Mips(MipsInlineAsmRegClass::reg) => cx.type_i32(), InlineAsmRegClass::Mips(MipsInlineAsmRegClass::freg) => cx.type_f32(), InlineAsmRegClass::Msp430(_) => unimplemented!(), @@ -860,6 +864,7 @@ fn modifier_to_gcc(arch: InlineAsmArch, reg: InlineAsmRegClass, modifier: Option InlineAsmRegClass::S390x(_) => None, InlineAsmRegClass::Msp430(_) => None, InlineAsmRegClass::M68k(_) => None, + InlineAsmRegClass::CSKY(_) => None, InlineAsmRegClass::SpirV(SpirVInlineAsmRegClass::reg) => { bug!("LLVM backend does not support SPIR-V") } diff --git a/compiler/rustc_codegen_llvm/Cargo.toml b/compiler/rustc_codegen_llvm/Cargo.toml index ad51f2d0958..be09820d08d 100644 --- a/compiler/rustc_codegen_llvm/Cargo.toml +++ b/compiler/rustc_codegen_llvm/Cargo.toml @@ -11,7 +11,7 @@ bitflags = "1.0" cstr = "0.2" libc = "0.2" measureme = "10.0.0" -object = { version = "0.31.1", default-features = false, features = [ +object = { version = "0.32.0", default-features = false, features = [ "std", "read", ] } diff --git a/compiler/rustc_codegen_llvm/src/asm.rs b/compiler/rustc_codegen_llvm/src/asm.rs index 2a6ad1be763..ca9fd76a997 100644 --- a/compiler/rustc_codegen_llvm/src/asm.rs +++ b/compiler/rustc_codegen_llvm/src/asm.rs @@ -261,6 +261,7 @@ impl<'ll, 'tcx> AsmBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> { InlineAsmArch::M68k => { constraints.push("~{ccr}".to_string()); } + InlineAsmArch::CSKY => {} } } if !options.contains(InlineAsmOptions::NOMEM) { @@ -693,6 +694,8 @@ fn reg_to_llvm(reg: InlineAsmRegOrRegClass, layout: Option<&TyAndLayout<'_>>) -> InlineAsmRegClass::M68k(M68kInlineAsmRegClass::reg) => "r", InlineAsmRegClass::M68k(M68kInlineAsmRegClass::reg_addr) => "a", InlineAsmRegClass::M68k(M68kInlineAsmRegClass::reg_data) => "d", + InlineAsmRegClass::CSKY(CSKYInlineAsmRegClass::reg) => "r", + InlineAsmRegClass::CSKY(CSKYInlineAsmRegClass::freg) => "f", InlineAsmRegClass::SpirV(SpirVInlineAsmRegClass::reg) => { bug!("LLVM backend does not support SPIR-V") } @@ -792,6 +795,7 @@ fn modifier_to_llvm( bug!("LLVM backend does not support SPIR-V") } InlineAsmRegClass::M68k(_) => None, + InlineAsmRegClass::CSKY(_) => None, InlineAsmRegClass::Err => unreachable!(), } } @@ -868,6 +872,8 @@ fn dummy_output_type<'ll>(cx: &CodegenCx<'ll, '_>, reg: InlineAsmRegClass) -> &' InlineAsmRegClass::M68k(M68kInlineAsmRegClass::reg) => cx.type_i32(), InlineAsmRegClass::M68k(M68kInlineAsmRegClass::reg_addr) => cx.type_i32(), InlineAsmRegClass::M68k(M68kInlineAsmRegClass::reg_data) => cx.type_i32(), + InlineAsmRegClass::CSKY(CSKYInlineAsmRegClass::reg) => cx.type_i32(), + InlineAsmRegClass::CSKY(CSKYInlineAsmRegClass::freg) => cx.type_f32(), InlineAsmRegClass::SpirV(SpirVInlineAsmRegClass::reg) => { bug!("LLVM backend does not support SPIR-V") } diff --git a/compiler/rustc_codegen_ssa/Cargo.toml b/compiler/rustc_codegen_ssa/Cargo.toml index 8f383f68bcd..34d0e2d1df6 100644 --- a/compiler/rustc_codegen_ssa/Cargo.toml +++ b/compiler/rustc_codegen_ssa/Cargo.toml @@ -4,14 +4,14 @@ version = "0.0.0" edition = "2021" [dependencies] -ar_archive_writer = "0.1.3" +ar_archive_writer = "0.1.5" bitflags = "1.2.1" cc = "1.0.69" itertools = "0.10.1" tracing = "0.1" jobserver = "0.1.22" tempfile = "3.2" -thorin-dwp = "0.6" +thorin-dwp = "0.7" pathdiff = "0.2.0" serde_json = "1.0.59" smallvec = { version = "1.8.1", features = ["union", "may_dangle"] } @@ -42,7 +42,7 @@ rustc_session = { path = "../rustc_session" } libc = "0.2.50" [dependencies.object] -version = "0.31.1" +version = "0.32.0" default-features = false features = ["read_core", "elf", "macho", "pe", "xcoff", "unaligned", "archive", "write"] diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index bb65c3c81d9..a7ac728c59b 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -2991,25 +2991,10 @@ fn add_lld_args(cmd: &mut dyn Linker, sess: &Session, flavor: LinkerFlavor) { return; } - let self_contained_linker = sess.opts.cg.link_self_contained.linker(); - - // FIXME: some targets default to using `lld`, but users can only override the linker on the CLI - // and cannot yet select the precise linker flavor to opt out of that. See for example issue - // #113597 for the `thumbv6m-none-eabi` target: a driver is used, and its default linker - // conflicts with the target's flavor, causing unexpected arguments being passed. - // - // Until the new `LinkerFlavor`-like CLI options are stabilized, we only adopt MCP510's behavior - // if its dedicated unstable CLI flags are used, to keep the current sub-optimal stable - // behavior. - let using_mcp510 = - self_contained_linker || sess.opts.cg.linker_flavor.is_some_and(|f| f.is_unstable()); - if !using_mcp510 && !unstable_use_lld { - return; - } - // 1. Implement the "self-contained" part of this feature by adding rustc distribution // directories to the tool's search path. - if self_contained_linker || unstable_use_lld { + let self_contained_linker = sess.opts.cg.link_self_contained.linker() || unstable_use_lld; + if self_contained_linker { for path in sess.get_tools_search_paths(false) { cmd.arg({ let mut arg = OsString::from("-B"); diff --git a/compiler/rustc_codegen_ssa/src/back/metadata.rs b/compiler/rustc_codegen_ssa/src/back/metadata.rs index 5c7df29444b..0be84c9fa83 100644 --- a/compiler/rustc_codegen_ssa/src/back/metadata.rs +++ b/compiler/rustc_codegen_ssa/src/back/metadata.rs @@ -209,6 +209,7 @@ pub(crate) fn create_object_file(sess: &Session) -> Option<write::Object<'static "hexagon" => Architecture::Hexagon, "bpf" => Architecture::Bpf, "loongarch64" => Architecture::LoongArch64, + "csky" => Architecture::Csky, // Unsupported architecture. _ => return None, }; @@ -307,6 +308,13 @@ pub(crate) fn create_object_file(sess: &Session) -> Option<write::Object<'static // the appropriate EF_AVR_ARCH flag. ef_avr_arch(&sess.target.options.cpu) } + Architecture::Csky => { + let e_flags = match sess.target.options.abi.as_ref() { + "abiv2" => elf::EF_CSKY_ABIV2, + _ => elf::EF_CSKY_ABIV1, + }; + e_flags + } _ => 0, }; // adapted from LLVM's `MCELFObjectTargetWriter::getOSABI` diff --git a/compiler/rustc_codegen_ssa/src/target_features.rs b/compiler/rustc_codegen_ssa/src/target_features.rs index c370ba9be56..baf6b19d3f9 100644 --- a/compiler/rustc_codegen_ssa/src/target_features.rs +++ b/compiler/rustc_codegen_ssa/src/target_features.rs @@ -296,6 +296,52 @@ const WASM_ALLOWED_FEATURES: &[(&str, Option<Symbol>)] = &[ const BPF_ALLOWED_FEATURES: &[(&str, Option<Symbol>)] = &[("alu32", Some(sym::bpf_target_feature))]; +const CSKY_ALLOWED_FEATURES: &[(&str, Option<Symbol>)] = &[ + // tidy-alphabetical-start + ("10e60", Some(sym::csky_target_feature)), + ("2e3", Some(sym::csky_target_feature)), + ("3e3r1", Some(sym::csky_target_feature)), + ("3e3r2", Some(sym::csky_target_feature)), + ("3e3r3", Some(sym::csky_target_feature)), + ("3e7", Some(sym::csky_target_feature)), + ("7e10", Some(sym::csky_target_feature)), + ("cache", Some(sym::csky_target_feature)), + ("doloop", Some(sym::csky_target_feature)), + ("dsp1e2", Some(sym::csky_target_feature)), + ("dspe60", Some(sym::csky_target_feature)), + ("e1", Some(sym::csky_target_feature)), + ("e2", Some(sym::csky_target_feature)), + ("edsp", Some(sym::csky_target_feature)), + ("elrw", Some(sym::csky_target_feature)), + ("float1e2", Some(sym::csky_target_feature)), + ("float1e3", Some(sym::csky_target_feature)), + ("float3e4", Some(sym::csky_target_feature)), + ("float7e60", Some(sym::csky_target_feature)), + ("floate1", Some(sym::csky_target_feature)), + ("hard-tp", Some(sym::csky_target_feature)), + ("high-registers", Some(sym::csky_target_feature)), + ("hwdiv", Some(sym::csky_target_feature)), + ("mp", Some(sym::csky_target_feature)), + ("mp1e2", Some(sym::csky_target_feature)), + ("nvic", Some(sym::csky_target_feature)), + ("trust", Some(sym::csky_target_feature)), + ("vdsp2e60f", Some(sym::csky_target_feature)), + ("vdspv1", Some(sym::csky_target_feature)), + ("vdspv2", Some(sym::csky_target_feature)), + // tidy-alphabetical-end + //fpu + // tidy-alphabetical-start + ("fdivdu", Some(sym::csky_target_feature)), + ("fpuv2_df", Some(sym::csky_target_feature)), + ("fpuv2_sf", Some(sym::csky_target_feature)), + ("fpuv3_df", Some(sym::csky_target_feature)), + ("fpuv3_hf", Some(sym::csky_target_feature)), + ("fpuv3_hi", Some(sym::csky_target_feature)), + ("fpuv3_sf", Some(sym::csky_target_feature)), + ("hard-float", Some(sym::csky_target_feature)), + ("hard-float-abi", Some(sym::csky_target_feature)), + // tidy-alphabetical-end +]; /// When rustdoc is running, provide a list of all known features so that all their respective /// primitives may be documented. /// @@ -311,6 +357,7 @@ pub fn all_known_features() -> impl Iterator<Item = (&'static str, Option<Symbol .chain(RISCV_ALLOWED_FEATURES.iter()) .chain(WASM_ALLOWED_FEATURES.iter()) .chain(BPF_ALLOWED_FEATURES.iter()) + .chain(CSKY_ALLOWED_FEATURES) .cloned() } @@ -325,6 +372,7 @@ pub fn supported_target_features(sess: &Session) -> &'static [(&'static str, Opt "riscv32" | "riscv64" => RISCV_ALLOWED_FEATURES, "wasm32" | "wasm64" => WASM_ALLOWED_FEATURES, "bpf" => BPF_ALLOWED_FEATURES, + "csky" => CSKY_ALLOWED_FEATURES, _ => &[], } } @@ -396,6 +444,7 @@ pub fn from_target_feature( Some(sym::ermsb_target_feature) => rust_features.ermsb_target_feature, Some(sym::bpf_target_feature) => rust_features.bpf_target_feature, Some(sym::aarch64_ver_target_feature) => rust_features.aarch64_ver_target_feature, + Some(sym::csky_target_feature) => rust_features.csky_target_feature, Some(name) => bug!("unknown target feature gate {}", name), None => true, }; diff --git a/compiler/rustc_const_eval/src/transform/check_consts/check.rs b/compiler/rustc_const_eval/src/transform/check_consts/check.rs index b077c10907e..fae047bff9e 100644 --- a/compiler/rustc_const_eval/src/transform/check_consts/check.rs +++ b/compiler/rustc_const_eval/src/transform/check_consts/check.rs @@ -772,7 +772,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> { }; match implsrc { - Ok(Some(ImplSource::Param(ty::BoundConstness::ConstIfConst, _))) => { + Ok(Some(ImplSource::Param(_))) if tcx.features().effects => { debug!( "const_trait_impl: provided {:?} via where-clause in {:?}", trait_ref, param_env diff --git a/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs b/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs index 8293bdfd969..b1b2859ef9d 100644 --- a/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs +++ b/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs @@ -174,8 +174,7 @@ impl Qualif for NeedsNonConstDrop { if !matches!( impl_src, - ImplSource::Builtin(BuiltinImplSource::Misc, _) - | ImplSource::Param(ty::BoundConstness::ConstIfConst, _) + ImplSource::Builtin(BuiltinImplSource::Misc, _) | ImplSource::Param(_) ) { // If our const destruct candidate is not ConstDestruct or implied by the param env, // then it's bad diff --git a/compiler/rustc_feature/src/active.rs b/compiler/rustc_feature/src/active.rs index 898f5fd3b70..953ea1bf523 100644 --- a/compiler/rustc_feature/src/active.rs +++ b/compiler/rustc_feature/src/active.rs @@ -282,6 +282,7 @@ declare_features! ( (active, arm_target_feature, "1.27.0", Some(44839), None), (active, avx512_target_feature, "1.27.0", Some(44839), None), (active, bpf_target_feature, "1.54.0", Some(44839), None), + (active, csky_target_feature, "CURRENT_RUSTC_VERSION", Some(44839), None), (active, ermsb_target_feature, "1.49.0", Some(44839), None), (active, hexagon_target_feature, "1.27.0", Some(44839), None), (active, mips_target_feature, "1.27.0", Some(44839), None), diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs index 8a5099804ed..46e8cf81bc1 100644 --- a/compiler/rustc_hir_analysis/src/check/check.rs +++ b/compiler/rustc_hir_analysis/src/check/check.rs @@ -8,7 +8,7 @@ use rustc_attr as attr; use rustc_errors::{Applicability, ErrorGuaranteed, MultiSpan}; use rustc_hir as hir; use rustc_hir::def::{CtorKind, DefKind, Res}; -use rustc_hir::def_id::{DefId, LocalDefId, CRATE_DEF_ID}; +use rustc_hir::def_id::{DefId, LocalDefId, LocalModDefId}; use rustc_hir::intravisit::Visitor; use rustc_hir::{ItemKind, Node, PathSegment}; use rustc_infer::infer::opaque_types::ConstrainOpaqueTypeRegionVisitor; @@ -1443,12 +1443,12 @@ pub(super) fn check_type_params_are_used<'tcx>( } } -pub(super) fn check_mod_item_types(tcx: TyCtxt<'_>, module_def_id: LocalDefId) { +pub(super) fn check_mod_item_types(tcx: TyCtxt<'_>, module_def_id: LocalModDefId) { let module = tcx.hir_module_items(module_def_id); for id in module.items() { check_item_type(tcx, id); } - if module_def_id == CRATE_DEF_ID { + if module_def_id == LocalModDefId::CRATE_DEF_ID { super::entry::check_for_entry_fn(tcx); } } 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 044fb405e32..ad02ca252c4 100644 --- a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs +++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs @@ -308,6 +308,15 @@ fn compare_method_predicate_entailment<'tcx>( } if check_implied_wf == CheckImpliedWfMode::Check && !(impl_sig, trait_sig).references_error() { + // Select obligations to make progress on inference before processing + // the wf obligation below. + // FIXME(-Ztrait-solver=next): Not needed when the hack below is removed. + let errors = ocx.select_where_possible(); + if !errors.is_empty() { + let reported = infcx.err_ctxt().report_fulfillment_errors(&errors); + return Err(reported); + } + // See #108544. Annoying, we can end up in cases where, because of winnowing, // we pick param env candidates over a more general impl, leading to more // stricter lifetime requirements than we would otherwise need. This can @@ -378,7 +387,7 @@ fn compare_method_predicate_entailment<'tcx>( // lifetime parameters. let outlives_env = OutlivesEnvironment::with_bounds( param_env, - infcx.implied_bounds_tys(param_env, impl_m_def_id, wf_tys.clone()), + infcx.implied_bounds_tys(param_env, impl_m_def_id, wf_tys), ); let errors = infcx.resolve_regions(&outlives_env); if !errors.is_empty() { diff --git a/compiler/rustc_hir_analysis/src/check/intrinsicck.rs b/compiler/rustc_hir_analysis/src/check/intrinsicck.rs index b0dd5e5787d..945953edd5a 100644 --- a/compiler/rustc_hir_analysis/src/check/intrinsicck.rs +++ b/compiler/rustc_hir_analysis/src/check/intrinsicck.rs @@ -68,7 +68,7 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> { let asm_ty = match *ty.kind() { // `!` is allowed for input but not for output (issue #87802) ty::Never if is_input => return None, - ty::Error(_) => return None, + _ if ty.references_error() => return None, ty::Int(IntTy::I8) | ty::Uint(UintTy::U8) => Some(InlineAsmType::I8), ty::Int(IntTy::I16) | ty::Uint(UintTy::U16) => Some(InlineAsmType::I16), ty::Int(IntTy::I32) | ty::Uint(UintTy::U32) => Some(InlineAsmType::I32), diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs index 16d4d099c7e..f5beefc47f3 100644 --- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs +++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs @@ -5,7 +5,7 @@ use rustc_ast as ast; use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexSet}; use rustc_errors::{pluralize, struct_span_err, Applicability, DiagnosticBuilder, ErrorGuaranteed}; use rustc_hir as hir; -use rustc_hir::def_id::{DefId, LocalDefId}; +use rustc_hir::def_id::{DefId, LocalDefId, LocalModDefId}; use rustc_hir::lang_items::LangItem; use rustc_hir::ItemKind; use rustc_infer::infer::outlives::env::{OutlivesEnvironment, RegionBoundPairs}; @@ -1854,7 +1854,7 @@ impl<'tcx> WfCheckingCtxt<'_, 'tcx> { } } -fn check_mod_type_wf(tcx: TyCtxt<'_>, module: LocalDefId) { +fn check_mod_type_wf(tcx: TyCtxt<'_>, module: LocalModDefId) { let items = tcx.hir_module_items(module); items.par_items(|item| tcx.ensure().check_well_formed(item.owner_id)); items.par_impl_items(|item| tcx.ensure().check_well_formed(item.owner_id)); diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs index 02a5d28b1e2..7b9f61d7ab2 100644 --- a/compiler/rustc_hir_analysis/src/collect.rs +++ b/compiler/rustc_hir_analysis/src/collect.rs @@ -22,7 +22,7 @@ use rustc_data_structures::captures::Captures; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_errors::{Applicability, DiagnosticBuilder, ErrorGuaranteed, StashKey}; use rustc_hir as hir; -use rustc_hir::def_id::{DefId, LocalDefId}; +use rustc_hir::def_id::{DefId, LocalDefId, LocalModDefId}; use rustc_hir::intravisit::{self, Visitor}; use rustc_hir::{GenericParamKind, Node}; use rustc_infer::infer::{InferCtxt, TyCtxtInferExt}; @@ -48,7 +48,7 @@ mod type_of; /////////////////////////////////////////////////////////////////////////// // Main entry point -fn collect_mod_item_types(tcx: TyCtxt<'_>, module_def_id: LocalDefId) { +fn collect_mod_item_types(tcx: TyCtxt<'_>, module_def_id: LocalModDefId) { tcx.hir().visit_item_likes_in_module(module_def_id, &mut CollectItemTypesVisitor { tcx }); } diff --git a/compiler/rustc_hir_analysis/src/constrained_generic_params.rs b/compiler/rustc_hir_analysis/src/constrained_generic_params.rs index 35882ad352b..5591fa6f2a5 100644 --- a/compiler/rustc_hir_analysis/src/constrained_generic_params.rs +++ b/compiler/rustc_hir_analysis/src/constrained_generic_params.rs @@ -59,7 +59,7 @@ struct ParameterCollector { impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for ParameterCollector { fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> { match *t.kind() { - ty::Alias(ty::Projection | ty::Inherent, ..) if !self.include_nonconstraining => { + ty::Alias(..) if !self.include_nonconstraining => { // projections are not injective return ControlFlow::Continue(()); } diff --git a/compiler/rustc_hir_analysis/src/impl_wf_check.rs b/compiler/rustc_hir_analysis/src/impl_wf_check.rs index 4f705eaf10a..788121f7a30 100644 --- a/compiler/rustc_hir_analysis/src/impl_wf_check.rs +++ b/compiler/rustc_hir_analysis/src/impl_wf_check.rs @@ -14,7 +14,7 @@ use min_specialization::check_min_specialization; use rustc_data_structures::fx::FxHashSet; use rustc_errors::struct_span_err; use rustc_hir::def::DefKind; -use rustc_hir::def_id::LocalDefId; +use rustc_hir::def_id::{LocalDefId, LocalModDefId}; use rustc_middle::query::Providers; use rustc_middle::ty::{self, TyCtxt, TypeVisitableExt}; use rustc_span::{Span, Symbol}; @@ -51,7 +51,7 @@ mod min_specialization; /// impl<'a> Trait<Foo> for Bar { type X = &'a i32; } /// // ^ 'a is unused and appears in assoc type, error /// ``` -fn check_mod_impl_wf(tcx: TyCtxt<'_>, module_def_id: LocalDefId) { +fn check_mod_impl_wf(tcx: TyCtxt<'_>, module_def_id: LocalModDefId) { let min_specialization = tcx.features().min_specialization; let module = tcx.hir_module_items(module_def_id); for id in module.items() { diff --git a/compiler/rustc_incremental/src/persist/load.rs b/compiler/rustc_incremental/src/persist/load.rs index bb479b5bdcc..8d67f692568 100644 --- a/compiler/rustc_incremental/src/persist/load.rs +++ b/compiler/rustc_incremental/src/persist/load.rs @@ -3,7 +3,7 @@ use crate::errors; use rustc_data_structures::memmap::Mmap; use rustc_data_structures::unord::UnordMap; -use rustc_middle::dep_graph::{SerializedDepGraph, WorkProduct, WorkProductId}; +use rustc_middle::dep_graph::{SerializedDepGraph, WorkProductMap}; use rustc_middle::query::on_disk_cache::OnDiskCache; use rustc_serialize::opaque::MemDecoder; use rustc_serialize::Decodable; @@ -16,8 +16,6 @@ use super::file_format; use super::fs::*; use super::work_product; -type WorkProductMap = UnordMap<WorkProductId, WorkProduct>; - #[derive(Debug)] /// Represents the result of an attempt to load incremental compilation data. pub enum LoadResult<T> { diff --git a/compiler/rustc_incremental/src/persist/save.rs b/compiler/rustc_incremental/src/persist/save.rs index bfaa52f9c81..0cfaf583774 100644 --- a/compiler/rustc_incremental/src/persist/save.rs +++ b/compiler/rustc_incremental/src/persist/save.rs @@ -1,7 +1,9 @@ use crate::errors; use rustc_data_structures::fx::FxIndexMap; use rustc_data_structures::sync::join; -use rustc_middle::dep_graph::{DepGraph, SerializedDepGraph, WorkProduct, WorkProductId}; +use rustc_middle::dep_graph::{ + DepGraph, SerializedDepGraph, WorkProduct, WorkProductId, WorkProductMap, +}; use rustc_middle::ty::TyCtxt; use rustc_serialize::opaque::{FileEncodeResult, FileEncoder}; use rustc_serialize::Encodable as RustcEncodable; @@ -101,7 +103,7 @@ pub fn save_work_product_index( // deleted during invalidation. Some object files don't change their // content, they are just not needed anymore. let previous_work_products = dep_graph.previous_work_products(); - for (id, wp) in previous_work_products.iter() { + for (id, wp) in previous_work_products.to_sorted_stable_ord().iter() { if !new_work_products.contains_key(id) { work_product::delete_workproduct_files(sess, wp); debug_assert!( @@ -146,7 +148,7 @@ fn encode_query_cache(tcx: TyCtxt<'_>, encoder: FileEncoder) -> FileEncodeResult pub fn build_dep_graph( sess: &Session, prev_graph: SerializedDepGraph, - prev_work_products: FxIndexMap<WorkProductId, WorkProduct>, + prev_work_products: WorkProductMap, ) -> Option<DepGraph> { if sess.opts.incremental.is_none() { // No incremental compilation. diff --git a/compiler/rustc_interface/src/queries.rs b/compiler/rustc_interface/src/queries.rs index 5d38cf770a2..fc71c6c7e9a 100644 --- a/compiler/rustc_interface/src/queries.rs +++ b/compiler/rustc_interface/src/queries.rs @@ -5,7 +5,6 @@ use crate::{passes, util}; use rustc_ast as ast; use rustc_codegen_ssa::traits::CodegenBackend; use rustc_codegen_ssa::CodegenResults; -use rustc_data_structures::fx::FxIndexMap; use rustc_data_structures::steal::Steal; use rustc_data_structures::svh::Svh; use rustc_data_structures::sync::{AppendOnlyIndexVec, Lrc, OnceCell, RwLock, WorkerLocal}; @@ -86,9 +85,6 @@ pub struct Queries<'tcx> { parse: Query<ast::Crate>, pre_configure: Query<(ast::Crate, ast::AttrVec)>, - crate_name: Query<Symbol>, - crate_types: Query<Vec<CrateType>>, - stable_crate_id: Query<StableCrateId>, // This just points to what's in `gcx_cell`. gcx: Query<&'tcx GlobalCtxt<'tcx>>, } @@ -102,9 +98,6 @@ impl<'tcx> Queries<'tcx> { hir_arena: WorkerLocal::new(|_| rustc_hir::Arena::default()), parse: Default::default(), pre_configure: Default::default(), - crate_name: Default::default(), - crate_types: Default::default(), - stable_crate_id: Default::default(), gcx: Default::default(), } } @@ -138,39 +131,12 @@ impl<'tcx> Queries<'tcx> { }) } - fn crate_name(&self) -> Result<QueryResult<'_, Symbol>> { - self.crate_name.compute(|| { - let pre_configure_result = self.pre_configure()?; - let (_, pre_configured_attrs) = &*pre_configure_result.borrow(); - // parse `#[crate_name]` even if `--crate-name` was passed, to make sure it matches. - Ok(find_crate_name(self.session(), pre_configured_attrs)) - }) - } - - fn crate_types(&self) -> Result<QueryResult<'_, Vec<CrateType>>> { - self.crate_types.compute(|| { - let pre_configure_result = self.pre_configure()?; - let (_, pre_configured_attrs) = &*pre_configure_result.borrow(); - Ok(util::collect_crate_types(&self.session(), &pre_configured_attrs)) - }) - } - - fn stable_crate_id(&self) -> Result<QueryResult<'_, StableCrateId>> { - self.stable_crate_id.compute(|| { - let sess = self.session(); - Ok(StableCrateId::new( - *self.crate_name()?.borrow(), - self.crate_types()?.borrow().contains(&CrateType::Executable), - sess.opts.cg.metadata.clone(), - sess.cfg_version, - )) - }) - } - - fn dep_graph_future(&self) -> Result<Option<DepGraphFuture>> { + fn dep_graph_future( + &self, + crate_name: Symbol, + stable_crate_id: StableCrateId, + ) -> Result<Option<DepGraphFuture>> { let sess = self.session(); - let crate_name = *self.crate_name()?.borrow(); - let stable_crate_id = *self.stable_crate_id()?.borrow(); // `load_dep_graph` can only be called after `prepare_session_directory`. rustc_incremental::prepare_session_directory(sess, crate_name, stable_crate_id)?; @@ -195,15 +161,8 @@ impl<'tcx> Queries<'tcx> { dep_graph_future .and_then(|future| { let sess = self.session(); - let (prev_graph, mut prev_work_products) = + let (prev_graph, prev_work_products) = sess.time("blocked_on_dep_graph_loading", || future.open().open(sess)); - // Convert from UnordMap to FxIndexMap by sorting - let prev_work_product_ids = - prev_work_products.items().map(|x| *x.0).into_sorted_stable_ord(); - let prev_work_products = prev_work_product_ids - .into_iter() - .map(|x| (x, prev_work_products.remove(&x).unwrap())) - .collect::<FxIndexMap<_, _>>(); rustc_incremental::build_dep_graph(sess, prev_graph, prev_work_products) }) .unwrap_or_else(DepGraph::new_disabled) @@ -211,23 +170,33 @@ impl<'tcx> Queries<'tcx> { pub fn global_ctxt(&'tcx self) -> Result<QueryResult<'_, &'tcx GlobalCtxt<'tcx>>> { self.gcx.compute(|| { + let sess = self.session(); + let (krate, pre_configured_attrs) = self.pre_configure()?.steal(); + + // parse `#[crate_name]` even if `--crate-name` was passed, to make sure it matches. + let crate_name = find_crate_name(sess, &pre_configured_attrs); + let crate_types = util::collect_crate_types(sess, &pre_configured_attrs); + let stable_crate_id = StableCrateId::new( + crate_name, + crate_types.contains(&CrateType::Executable), + sess.opts.cg.metadata.clone(), + sess.cfg_version, + ); + // Compute the dependency graph (in the background). We want to do this as early as // possible, to give the DepGraph maximum time to load before `dep_graph` is called. - let dep_graph_future = self.dep_graph_future()?; - - let crate_name = self.crate_name()?.steal(); - let crate_types = self.crate_types()?.steal(); - let stable_crate_id = self.stable_crate_id()?.steal(); - let (krate, pre_configured_attrs) = self.pre_configure()?.steal(); + let dep_graph_future = self.dep_graph_future(crate_name, stable_crate_id)?; - let sess = self.session(); let lint_store = Lrc::new(passes::create_lint_store( sess, &*self.codegen_backend().metadata_loader(), self.compiler.register_lints.as_deref(), &pre_configured_attrs, )); - let cstore = RwLock::new(Box::new(CStore::new(stable_crate_id)) as _); + let cstore = RwLock::new(Box::new(CStore::new( + self.codegen_backend().metadata_loader(), + stable_crate_id, + )) as _); let definitions = RwLock::new(Definitions::new(stable_crate_id)); let source_span = AppendOnlyIndexVec::new(); let _id = source_span.push(krate.spans.inner_span); @@ -255,9 +224,6 @@ impl<'tcx> Queries<'tcx> { tcx.arena.alloc(rustc_expand::config::features(sess, &pre_configured_attrs)), ); feed.crate_for_resolver(tcx.arena.alloc(Steal::new((krate, pre_configured_attrs)))); - feed.metadata_loader( - tcx.arena.alloc(Steal::new(self.codegen_backend().metadata_loader())), - ); }); Ok(qcx) }) diff --git a/compiler/rustc_lint/src/late.rs b/compiler/rustc_lint/src/late.rs index 3331dbad4a9..73af51d9e90 100644 --- a/compiler/rustc_lint/src/late.rs +++ b/compiler/rustc_lint/src/late.rs @@ -19,7 +19,7 @@ use rustc_ast as ast; use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_data_structures::sync::join; use rustc_hir as hir; -use rustc_hir::def_id::LocalDefId; +use rustc_hir::def_id::{LocalDefId, LocalModDefId}; use rustc_hir::intravisit as hir_visit; use rustc_hir::intravisit::Visitor; use rustc_middle::hir::nested_filter; @@ -338,7 +338,7 @@ crate::late_lint_methods!(impl_late_lint_pass, []); pub fn late_lint_mod<'tcx, T: LateLintPass<'tcx> + 'tcx>( tcx: TyCtxt<'tcx>, - module_def_id: LocalDefId, + module_def_id: LocalModDefId, builtin_lints: T, ) { let context = LateContext { @@ -369,7 +369,7 @@ pub fn late_lint_mod<'tcx, T: LateLintPass<'tcx> + 'tcx>( fn late_lint_mod_inner<'tcx, T: LateLintPass<'tcx>>( tcx: TyCtxt<'tcx>, - module_def_id: LocalDefId, + module_def_id: LocalModDefId, context: LateContext<'tcx>, pass: T, ) { diff --git a/compiler/rustc_lint/src/lib.rs b/compiler/rustc_lint/src/lib.rs index 42378951af3..585b10e79e4 100644 --- a/compiler/rustc_lint/src/lib.rs +++ b/compiler/rustc_lint/src/lib.rs @@ -90,7 +90,7 @@ use rustc_ast as ast; use rustc_errors::{DiagnosticMessage, SubdiagnosticMessage}; use rustc_fluent_macro::fluent_messages; use rustc_hir as hir; -use rustc_hir::def_id::LocalDefId; +use rustc_hir::def_id::{LocalDefId, LocalModDefId}; use rustc_middle::query::Providers; use rustc_middle::ty::TyCtxt; use rustc_session::lint::builtin::{ @@ -145,7 +145,7 @@ pub fn provide(providers: &mut Providers) { *providers = Providers { lint_mod, ..*providers }; } -fn lint_mod(tcx: TyCtxt<'_>, module_def_id: LocalDefId) { +fn lint_mod(tcx: TyCtxt<'_>, module_def_id: LocalModDefId) { late_lint_mod(tcx, module_def_id, BuiltinCombinedModuleLateLintPass::new()); } diff --git a/compiler/rustc_lint/src/unused.rs b/compiler/rustc_lint/src/unused.rs index 3db6b302790..6041f80753b 100644 --- a/compiler/rustc_lint/src/unused.rs +++ b/compiler/rustc_lint/src/unused.rs @@ -666,6 +666,24 @@ trait UnusedDelimLint { if !followed_by_block { return false; } + + // Check if we need parens for `match &( Struct { feild: }) {}`. + { + let mut innermost = inner; + loop { + innermost = match &innermost.kind { + ExprKind::AddrOf(_, _, expr) => expr, + _ => { + if parser::contains_exterior_struct_lit(&innermost) { + return true; + } else { + break; + } + } + } + } + } + let mut innermost = inner; loop { innermost = match &innermost.kind { diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs index 3747e562cec..96c31a90da8 100644 --- a/compiler/rustc_lint_defs/src/builtin.rs +++ b/compiler/rustc_lint_defs/src/builtin.rs @@ -3366,6 +3366,7 @@ declare_lint_pass! { BYTE_SLICE_IN_PACKED_STRUCT_WITH_DERIVE, CENUM_IMPL_DROP_CAST, COHERENCE_LEAK_CHECK, + COINDUCTIVE_OVERLAP_IN_COHERENCE, CONFLICTING_REPR_HINTS, CONST_EVALUATABLE_UNCHECKED, CONST_ITEM_MUTATION, @@ -4423,6 +4424,44 @@ declare_lint! { } declare_lint! { + /// The `coinductive_overlap_in_coherence` lint detects impls which are currently + /// considered not overlapping, but may be considered to overlap if support for + /// coinduction is added to the trait solver. + /// + /// ### Example + /// + /// ```rust,compile_fail + /// #![deny(coinductive_overlap_in_coherence)] + /// + /// trait CyclicTrait {} + /// impl<T: CyclicTrait> CyclicTrait for T {} + /// + /// trait Trait {} + /// impl<T: CyclicTrait> Trait for T {} + /// // conflicting impl with the above + /// impl Trait for u8 {} + /// ``` + /// + /// {{produces}} + /// + /// ### Explanation + /// + /// We have two choices for impl which satisfy `u8: Trait`: the blanket impl + /// for generic `T`, and the direct impl for `u8`. These two impls nominally + /// overlap, since we can infer `T = u8` in the former impl, but since the where + /// clause `u8: CyclicTrait` would end up resulting in a cycle (since it depends + /// on itself), the blanket impl is not considered to hold for `u8`. This will + /// change in a future release. + pub COINDUCTIVE_OVERLAP_IN_COHERENCE, + Warn, + "impls that are not considered to overlap may be considered to \ + overlap in the future", + @future_incompatible = FutureIncompatibleInfo { + reference: "issue #114040 <https://github.com/rust-lang/rust/issues/114040>", + }; +} + +declare_lint! { /// The `unknown_diagnostic_attributes` lint detects unrecognized diagnostic attributes. /// /// ### Example diff --git a/compiler/rustc_llvm/build.rs b/compiler/rustc_llvm/build.rs index aa1121d6bb3..4302b161833 100644 --- a/compiler/rustc_llvm/build.rs +++ b/compiler/rustc_llvm/build.rs @@ -12,6 +12,7 @@ const OPTIONAL_COMPONENTS: &[&str] = &[ "avr", "loongarch", "m68k", + "csky", "mips", "powerpc", "systemz", diff --git a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp index b3371dbe834..b566ea496de 100644 --- a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp +++ b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp @@ -105,6 +105,12 @@ extern "C" void LLVMTimeTraceProfilerFinish(const char* FileName) { #define SUBTARGET_M68K #endif +#ifdef LLVM_COMPONENT_CSKY +#define SUBTARGET_CSKY SUBTARGET(CSKY) +#else +#define SUBTARGET_CSKY +#endif + #ifdef LLVM_COMPONENT_MIPS #define SUBTARGET_MIPS SUBTARGET(Mips) #else @@ -159,6 +165,7 @@ extern "C" void LLVMTimeTraceProfilerFinish(const char* FileName) { SUBTARGET_AARCH64 \ SUBTARGET_AVR \ SUBTARGET_M68K \ + SUBTARGET_CSKY \ SUBTARGET_MIPS \ SUBTARGET_PPC \ SUBTARGET_SYSTEMZ \ diff --git a/compiler/rustc_llvm/src/lib.rs b/compiler/rustc_llvm/src/lib.rs index a49ded4fd7b..eb70961503d 100644 --- a/compiler/rustc_llvm/src/lib.rs +++ b/compiler/rustc_llvm/src/lib.rs @@ -103,6 +103,14 @@ pub fn initialize_available_targets() { LLVMInitializeM68kAsmParser ); init_target!( + llvm_component = "csky", + LLVMInitializeCSKYTargetInfo, + LLVMInitializeCSKYTarget, + LLVMInitializeCSKYTargetMC, + LLVMInitializeCSKYAsmPrinter, + LLVMInitializeCSKYAsmParser + ); + init_target!( llvm_component = "loongarch", LLVMInitializeLoongArchTargetInfo, LLVMInitializeLoongArchTarget, diff --git a/compiler/rustc_metadata/src/creader.rs b/compiler/rustc_metadata/src/creader.rs index 3c76f9a8e52..fce80ab37dd 100644 --- a/compiler/rustc_metadata/src/creader.rs +++ b/compiler/rustc_metadata/src/creader.rs @@ -15,8 +15,9 @@ use rustc_hir::definitions::Definitions; use rustc_index::IndexVec; use rustc_middle::ty::TyCtxt; use rustc_session::config::{self, CrateType, ExternLocation}; -use rustc_session::cstore::ExternCrateSource; -use rustc_session::cstore::{CrateDepKind, CrateSource, ExternCrate}; +use rustc_session::cstore::{ + CrateDepKind, CrateSource, ExternCrate, ExternCrateSource, MetadataLoaderDyn, +}; use rustc_session::lint; use rustc_session::output::validate_crate_name; use rustc_session::search_paths::PathKind; @@ -33,6 +34,8 @@ use std::time::Duration; use std::{cmp, env, iter}; pub struct CStore { + metadata_loader: Box<MetadataLoaderDyn>, + metas: IndexVec<CrateNum, Option<Box<CrateMetadata>>>, injected_panic_runtime: Option<CrateNum>, /// This crate needs an allocator and either provides it itself, or finds it in a dependency. @@ -261,10 +264,14 @@ impl CStore { } } - pub fn new(local_stable_crate_id: StableCrateId) -> CStore { + pub fn new( + metadata_loader: Box<MetadataLoaderDyn>, + local_stable_crate_id: StableCrateId, + ) -> CStore { let mut stable_crate_ids = StableCrateIdMap::default(); stable_crate_ids.insert(local_stable_crate_id, LOCAL_CRATE); CStore { + metadata_loader, // We add an empty entry for LOCAL_CRATE (which maps to zero) in // order to make array indices in `metas` match with the // corresponding `CrateNum`. This first entry will always remain @@ -538,10 +545,9 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> { (LoadResult::Previous(cnum), None) } else { info!("falling back to a load"); - let metadata_loader = self.tcx.metadata_loader(()).borrow(); let mut locator = CrateLocator::new( self.sess, - &**metadata_loader, + &*self.cstore.metadata_loader, name, // The all loop is because `--crate-type=rlib --crate-type=rlib` is // legal and produces both inside this type. diff --git a/compiler/rustc_middle/src/arena.rs b/compiler/rustc_middle/src/arena.rs index b056ae420ab..952c796f52e 100644 --- a/compiler/rustc_middle/src/arena.rs +++ b/compiler/rustc_middle/src/arena.rs @@ -40,7 +40,6 @@ macro_rules! arena_types { rustc_data_structures::sync::Lrc<rustc_ast::Crate>, )>, [] output_filenames: std::sync::Arc<rustc_session::config::OutputFilenames>, - [] metadata_loader: rustc_data_structures::steal::Steal<Box<rustc_session::cstore::MetadataLoaderDyn>>, [] crate_for_resolver: rustc_data_structures::steal::Steal<(rustc_ast::Crate, rustc_ast::AttrVec)>, [] resolutions: rustc_middle::ty::ResolverGlobalCtxt, [decode] unsafety_check_result: rustc_middle::mir::UnsafetyCheckResult, diff --git a/compiler/rustc_middle/src/dep_graph/dep_node.rs b/compiler/rustc_middle/src/dep_graph/dep_node.rs index 06251bccc98..04c09d33400 100644 --- a/compiler/rustc_middle/src/dep_graph/dep_node.rs +++ b/compiler/rustc_middle/src/dep_graph/dep_node.rs @@ -60,7 +60,7 @@ use crate::mir::mono::MonoItem; use crate::ty::TyCtxt; use rustc_data_structures::fingerprint::Fingerprint; -use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, LOCAL_CRATE}; +use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, LocalModDefId, ModDefId, LOCAL_CRATE}; use rustc_hir::definitions::DefPathHash; use rustc_hir::{HirId, ItemLocalId, OwnerId}; use rustc_query_system::dep_graph::FingerprintStyle; @@ -387,3 +387,53 @@ impl<'tcx> DepNodeParams<TyCtxt<'tcx>> for HirId { } } } + +macro_rules! impl_for_typed_def_id { + ($Name:ident, $LocalName:ident) => { + impl<'tcx> DepNodeParams<TyCtxt<'tcx>> for $Name { + #[inline(always)] + fn fingerprint_style() -> FingerprintStyle { + FingerprintStyle::DefPathHash + } + + #[inline(always)] + fn to_fingerprint(&self, tcx: TyCtxt<'tcx>) -> Fingerprint { + self.to_def_id().to_fingerprint(tcx) + } + + #[inline(always)] + fn to_debug_str(&self, tcx: TyCtxt<'tcx>) -> String { + self.to_def_id().to_debug_str(tcx) + } + + #[inline(always)] + fn recover(tcx: TyCtxt<'tcx>, dep_node: &DepNode) -> Option<Self> { + DefId::recover(tcx, dep_node).map($Name::new_unchecked) + } + } + + impl<'tcx> DepNodeParams<TyCtxt<'tcx>> for $LocalName { + #[inline(always)] + fn fingerprint_style() -> FingerprintStyle { + FingerprintStyle::DefPathHash + } + + #[inline(always)] + fn to_fingerprint(&self, tcx: TyCtxt<'tcx>) -> Fingerprint { + self.to_def_id().to_fingerprint(tcx) + } + + #[inline(always)] + fn to_debug_str(&self, tcx: TyCtxt<'tcx>) -> String { + self.to_def_id().to_debug_str(tcx) + } + + #[inline(always)] + fn recover(tcx: TyCtxt<'tcx>, dep_node: &DepNode) -> Option<Self> { + LocalDefId::recover(tcx, dep_node).map($LocalName::new_unchecked) + } + } + }; +} + +impl_for_typed_def_id! { ModDefId, LocalModDefId } diff --git a/compiler/rustc_middle/src/dep_graph/mod.rs b/compiler/rustc_middle/src/dep_graph/mod.rs index 3ad9b0d79e7..f79ce08b8ae 100644 --- a/compiler/rustc_middle/src/dep_graph/mod.rs +++ b/compiler/rustc_middle/src/dep_graph/mod.rs @@ -8,7 +8,7 @@ mod dep_node; pub use rustc_query_system::dep_graph::{ debug::DepNodeFilter, hash_result, DepContext, DepNodeColor, DepNodeIndex, - SerializedDepNodeIndex, WorkProduct, WorkProductId, + SerializedDepNodeIndex, WorkProduct, WorkProductId, WorkProductMap, }; pub use dep_node::{label_strs, DepKind, DepNode, DepNodeExt}; diff --git a/compiler/rustc_middle/src/hir/map/mod.rs b/compiler/rustc_middle/src/hir/map/mod.rs index 224f897492b..467962b39bb 100644 --- a/compiler/rustc_middle/src/hir/map/mod.rs +++ b/compiler/rustc_middle/src/hir/map/mod.rs @@ -8,7 +8,7 @@ use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_data_structures::svh::Svh; use rustc_data_structures::sync::{par_for_each_in, DynSend, DynSync}; use rustc_hir::def::{DefKind, Res}; -use rustc_hir::def_id::{DefId, LocalDefId, CRATE_DEF_ID, LOCAL_CRATE}; +use rustc_hir::def_id::{DefId, LocalDefId, LocalModDefId, LOCAL_CRATE}; use rustc_hir::definitions::{DefKey, DefPath, DefPathData, DefPathHash}; use rustc_hir::intravisit::{self, Visitor}; use rustc_hir::*; @@ -148,7 +148,7 @@ impl<'hir> Map<'hir> { } #[inline] - pub fn module_items(self, module: LocalDefId) -> impl Iterator<Item = ItemId> + 'hir { + pub fn module_items(self, module: LocalModDefId) -> impl Iterator<Item = ItemId> + 'hir { self.tcx.hir_module_items(module).items() } @@ -169,8 +169,8 @@ impl<'hir> Map<'hir> { } #[inline] - pub fn local_def_id_to_hir_id(self, def_id: LocalDefId) -> HirId { - self.tcx.local_def_id_to_hir_id(def_id) + pub fn local_def_id_to_hir_id(self, def_id: impl Into<LocalDefId>) -> HirId { + self.tcx.local_def_id_to_hir_id(def_id.into()) } /// Do not call this function directly. The query should be called. @@ -529,8 +529,8 @@ impl<'hir> Map<'hir> { self.krate_attrs().iter().any(|attr| attr.has_name(sym::rustc_coherence_is_core)) } - pub fn get_module(self, module: LocalDefId) -> (&'hir Mod<'hir>, Span, HirId) { - let hir_id = HirId::make_owner(module); + pub fn get_module(self, module: LocalModDefId) -> (&'hir Mod<'hir>, Span, HirId) { + let hir_id = HirId::make_owner(module.to_local_def_id()); match self.tcx.hir_owner(hir_id.owner).map(|o| o.node) { Some(OwnerNode::Item(&Item { span, kind: ItemKind::Mod(ref m), .. })) => { (m, span, hir_id) @@ -542,7 +542,7 @@ impl<'hir> Map<'hir> { /// Walks the contents of the local crate. See also `visit_all_item_likes_in_crate`. pub fn walk_toplevel_module(self, visitor: &mut impl Visitor<'hir>) { - let (top_mod, span, hir_id) = self.get_module(CRATE_DEF_ID); + let (top_mod, span, hir_id) = self.get_module(LocalModDefId::CRATE_DEF_ID); visitor.visit_mod(top_mod, span, hir_id); } @@ -595,7 +595,7 @@ impl<'hir> Map<'hir> { /// This method is the equivalent of `visit_all_item_likes_in_crate` but restricted to /// item-likes in a single module. - pub fn visit_item_likes_in_module<V>(self, module: LocalDefId, visitor: &mut V) + pub fn visit_item_likes_in_module<V>(self, module: LocalModDefId, visitor: &mut V) where V: Visitor<'hir>, { @@ -618,17 +618,19 @@ impl<'hir> Map<'hir> { } } - pub fn for_each_module(self, mut f: impl FnMut(LocalDefId)) { + pub fn for_each_module(self, mut f: impl FnMut(LocalModDefId)) { let crate_items = self.tcx.hir_crate_items(()); for module in crate_items.submodules.iter() { - f(module.def_id) + f(LocalModDefId::new_unchecked(module.def_id)) } } #[inline] - pub fn par_for_each_module(self, f: impl Fn(LocalDefId) + DynSend + DynSync) { + pub fn par_for_each_module(self, f: impl Fn(LocalModDefId) + DynSend + DynSync) { let crate_items = self.tcx.hir_crate_items(()); - par_for_each_in(&crate_items.submodules[..], |module| f(module.def_id)) + par_for_each_in(&crate_items.submodules[..], |module| { + f(LocalModDefId::new_unchecked(module.def_id)) + }) } /// Returns an iterator for the nodes in the ancestor tree of the `current_id` @@ -1324,7 +1326,7 @@ fn hir_id_to_string(map: Map<'_>, id: HirId) -> String { } } -pub(super) fn hir_module_items(tcx: TyCtxt<'_>, module_id: LocalDefId) -> ModuleItems { +pub(super) fn hir_module_items(tcx: TyCtxt<'_>, module_id: LocalModDefId) -> ModuleItems { let mut collector = ItemCollector::new(tcx, false); let (hir_mod, span, hir_id) = tcx.hir().get_module(module_id); diff --git a/compiler/rustc_middle/src/hir/mod.rs b/compiler/rustc_middle/src/hir/mod.rs index 06b25556c82..e8fd469e1fb 100644 --- a/compiler/rustc_middle/src/hir/mod.rs +++ b/compiler/rustc_middle/src/hir/mod.rs @@ -11,7 +11,7 @@ use crate::ty::{EarlyBinder, ImplSubject, TyCtxt}; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_data_structures::sync::{par_for_each_in, DynSend, DynSync}; use rustc_hir::def::DefKind; -use rustc_hir::def_id::{DefId, LocalDefId}; +use rustc_hir::def_id::{DefId, LocalDefId, LocalModDefId}; use rustc_hir::*; use rustc_query_system::ich::StableHashingContext; use rustc_span::{ExpnId, DUMMY_SP}; @@ -101,22 +101,22 @@ impl<'tcx> TyCtxt<'tcx> { map::Map { tcx: self } } - pub fn parent_module(self, id: HirId) -> LocalDefId { + pub fn parent_module(self, id: HirId) -> LocalModDefId { if !id.is_owner() && self.def_kind(id.owner) == DefKind::Mod { - id.owner.def_id + LocalModDefId::new_unchecked(id.owner.def_id) } else { self.parent_module_from_def_id(id.owner.def_id) } } - pub fn parent_module_from_def_id(self, mut id: LocalDefId) -> LocalDefId { + pub fn parent_module_from_def_id(self, mut id: LocalDefId) -> LocalModDefId { while let Some(parent) = self.opt_local_parent(id) { id = parent; if self.def_kind(id) == DefKind::Mod { break; } } - id + LocalModDefId::new_unchecked(id) } pub fn impl_subject(self, def_id: DefId) -> EarlyBinder<ImplSubject<'tcx>> { diff --git a/compiler/rustc_middle/src/query/erase.rs b/compiler/rustc_middle/src/query/erase.rs index 2c481745d98..348f79ed6a8 100644 --- a/compiler/rustc_middle/src/query/erase.rs +++ b/compiler/rustc_middle/src/query/erase.rs @@ -235,6 +235,7 @@ trivial! { rustc_hir::def_id::DefId, rustc_hir::def_id::DefIndex, rustc_hir::def_id::LocalDefId, + rustc_hir::def_id::LocalModDefId, rustc_hir::def::DefKind, rustc_hir::Defaultness, rustc_hir::definitions::DefKey, diff --git a/compiler/rustc_middle/src/query/keys.rs b/compiler/rustc_middle/src/query/keys.rs index a8aec3096d5..01bdc4c9904 100644 --- a/compiler/rustc_middle/src/query/keys.rs +++ b/compiler/rustc_middle/src/query/keys.rs @@ -8,7 +8,7 @@ use crate::ty::fast_reject::SimplifiedType; use crate::ty::layout::{TyAndLayout, ValidityRequirement}; use crate::ty::{self, Ty, TyCtxt}; use crate::ty::{GenericArg, GenericArgsRef}; -use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, LOCAL_CRATE}; +use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, LocalModDefId, ModDefId, LOCAL_CRATE}; use rustc_hir::hir_id::{HirId, OwnerId}; use rustc_query_system::query::{DefaultCacheSelector, SingleCacheSelector, VecCacheSelector}; use rustc_span::symbol::{Ident, Symbol}; @@ -175,6 +175,41 @@ impl AsLocalKey for DefId { } } +impl Key for LocalModDefId { + type CacheSelector = DefaultCacheSelector<Self>; + + fn default_span(&self, tcx: TyCtxt<'_>) -> Span { + tcx.def_span(*self) + } + + #[inline(always)] + fn key_as_def_id(&self) -> Option<DefId> { + Some(self.to_def_id()) + } +} + +impl Key for ModDefId { + type CacheSelector = DefaultCacheSelector<Self>; + + fn default_span(&self, tcx: TyCtxt<'_>) -> Span { + tcx.def_span(*self) + } + + #[inline(always)] + fn key_as_def_id(&self) -> Option<DefId> { + Some(self.to_def_id()) + } +} + +impl AsLocalKey for ModDefId { + type LocalKey = LocalModDefId; + + #[inline(always)] + fn as_local_key(&self) -> Option<Self::LocalKey> { + self.as_local() + } +} + impl Key for SimplifiedType { type CacheSelector = DefaultCacheSelector<Self>; diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index 52a18c99edb..e289ddab120 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -67,7 +67,7 @@ use rustc_errors::ErrorGuaranteed; use rustc_hir as hir; use rustc_hir::def::{DefKind, DocLinkResMap}; use rustc_hir::def_id::{ - CrateNum, DefId, DefIdMap, DefIdSet, LocalDefId, LocalDefIdMap, LocalDefIdSet, + CrateNum, DefId, DefIdMap, DefIdSet, LocalDefId, LocalDefIdMap, LocalDefIdSet, LocalModDefId, }; use rustc_hir::lang_items::{LangItem, LanguageItems}; use rustc_hir::{Crate, ItemLocalId, TraitCandidate}; @@ -167,7 +167,7 @@ rustc_queries! { /// /// This can be conveniently accessed by `tcx.hir().visit_item_likes_in_module`. /// Avoid calling this query directly. - query hir_module_items(key: LocalDefId) -> &'tcx rustc_middle::hir::ModuleItems { + query hir_module_items(key: LocalModDefId) -> &'tcx rustc_middle::hir::ModuleItems { arena_cache desc { |tcx| "getting HIR module items in `{}`", tcx.def_path_str(key) } cache_on_disk_if { true } @@ -896,7 +896,7 @@ rustc_queries! { } /// Performs lint checking for the module. - query lint_mod(key: LocalDefId) -> () { + query lint_mod(key: LocalModDefId) -> () { desc { |tcx| "linting {}", describe_as_module(key, tcx) } } @@ -905,35 +905,35 @@ rustc_queries! { } /// Checks the attributes in the module. - query check_mod_attrs(key: LocalDefId) -> () { + query check_mod_attrs(key: LocalModDefId) -> () { desc { |tcx| "checking attributes in {}", describe_as_module(key, tcx) } } /// Checks for uses of unstable APIs in the module. - query check_mod_unstable_api_usage(key: LocalDefId) -> () { + query check_mod_unstable_api_usage(key: LocalModDefId) -> () { desc { |tcx| "checking for unstable API usage in {}", describe_as_module(key, tcx) } } /// Checks the const bodies in the module for illegal operations (e.g. `if` or `loop`). - query check_mod_const_bodies(key: LocalDefId) -> () { + query check_mod_const_bodies(key: LocalModDefId) -> () { desc { |tcx| "checking consts in {}", describe_as_module(key, tcx) } } /// Checks the loops in the module. - query check_mod_loops(key: LocalDefId) -> () { + query check_mod_loops(key: LocalModDefId) -> () { desc { |tcx| "checking loops in {}", describe_as_module(key, tcx) } } - query check_mod_naked_functions(key: LocalDefId) -> () { + query check_mod_naked_functions(key: LocalModDefId) -> () { desc { |tcx| "checking naked functions in {}", describe_as_module(key, tcx) } } - query check_mod_item_types(key: LocalDefId) -> () { + query check_mod_item_types(key: LocalModDefId) -> () { desc { |tcx| "checking item types in {}", describe_as_module(key, tcx) } } - query check_mod_privacy(key: LocalDefId) -> () { - desc { |tcx| "checking privacy in {}", describe_as_module(key, tcx) } + query check_mod_privacy(key: LocalModDefId) -> () { + desc { |tcx| "checking privacy in {}", describe_as_module(key.to_local_def_id(), tcx) } } query check_liveness(key: LocalDefId) { @@ -952,19 +952,19 @@ rustc_queries! { desc { "finding live symbols in crate" } } - query check_mod_deathness(key: LocalDefId) -> () { + query check_mod_deathness(key: LocalModDefId) -> () { desc { |tcx| "checking deathness of variables in {}", describe_as_module(key, tcx) } } - query check_mod_impl_wf(key: LocalDefId) -> () { + query check_mod_impl_wf(key: LocalModDefId) -> () { desc { |tcx| "checking that impls are well-formed in {}", describe_as_module(key, tcx) } } - query check_mod_type_wf(key: LocalDefId) -> () { + query check_mod_type_wf(key: LocalModDefId) -> () { desc { |tcx| "checking that types are well-formed in {}", describe_as_module(key, tcx) } } - query collect_mod_item_types(key: LocalDefId) -> () { + query collect_mod_item_types(key: LocalModDefId) -> () { desc { |tcx| "collecting item types in {}", describe_as_module(key, tcx) } } @@ -2096,12 +2096,6 @@ rustc_queries! { desc { "looking up enabled feature gates" } } - query metadata_loader((): ()) -> &'tcx Steal<Box<rustc_session::cstore::MetadataLoaderDyn>> { - feedable - no_hash - desc { "raw operations for metadata file access" } - } - query crate_for_resolver((): ()) -> &'tcx Steal<(rustc_ast::Crate, rustc_ast::AttrVec)> { feedable no_hash diff --git a/compiler/rustc_middle/src/query/plumbing.rs b/compiler/rustc_middle/src/query/plumbing.rs index 97edfc2fca2..a1aac284621 100644 --- a/compiler/rustc_middle/src/query/plumbing.rs +++ b/compiler/rustc_middle/src/query/plumbing.rs @@ -545,6 +545,7 @@ macro_rules! define_feedable { mod sealed { use super::{DefId, LocalDefId, OwnerId}; + use rustc_hir::def_id::{LocalModDefId, ModDefId}; /// An analogue of the `Into` trait that's intended only for query parameters. /// @@ -588,6 +589,27 @@ mod sealed { self.to_def_id() } } + + impl IntoQueryParam<DefId> for ModDefId { + #[inline(always)] + fn into_query_param(self) -> DefId { + self.to_def_id() + } + } + + impl IntoQueryParam<DefId> for LocalModDefId { + #[inline(always)] + fn into_query_param(self) -> DefId { + self.to_def_id() + } + } + + impl IntoQueryParam<LocalDefId> for LocalModDefId { + #[inline(always)] + fn into_query_param(self) -> LocalDefId { + self.into() + } + } } pub use sealed::IntoQueryParam; diff --git a/compiler/rustc_middle/src/traits/mod.rs b/compiler/rustc_middle/src/traits/mod.rs index 85116555fc0..2d655041c32 100644 --- a/compiler/rustc_middle/src/traits/mod.rs +++ b/compiler/rustc_middle/src/traits/mod.rs @@ -649,7 +649,7 @@ pub enum ImplSource<'tcx, N> { /// for some type parameter. The `Vec<N>` represents the /// obligations incurred from normalizing the where-clause (if /// any). - Param(ty::BoundConstness, Vec<N>), + Param(Vec<N>), /// Successful resolution for a builtin impl. Builtin(BuiltinImplSource, Vec<N>), @@ -659,21 +659,21 @@ impl<'tcx, N> ImplSource<'tcx, N> { pub fn nested_obligations(self) -> Vec<N> { match self { ImplSource::UserDefined(i) => i.nested, - ImplSource::Param(_, n) | ImplSource::Builtin(_, n) => n, + ImplSource::Param(n) | ImplSource::Builtin(_, n) => n, } } pub fn borrow_nested_obligations(&self) -> &[N] { match self { ImplSource::UserDefined(i) => &i.nested, - ImplSource::Param(_, n) | ImplSource::Builtin(_, n) => &n, + ImplSource::Param(n) | ImplSource::Builtin(_, n) => &n, } } pub fn borrow_nested_obligations_mut(&mut self) -> &mut [N] { match self { ImplSource::UserDefined(i) => &mut i.nested, - ImplSource::Param(_, n) | ImplSource::Builtin(_, n) => n, + ImplSource::Param(n) | ImplSource::Builtin(_, n) => n, } } @@ -687,7 +687,7 @@ impl<'tcx, N> ImplSource<'tcx, N> { args: i.args, nested: i.nested.into_iter().map(f).collect(), }), - ImplSource::Param(ct, n) => ImplSource::Param(ct, n.into_iter().map(f).collect()), + ImplSource::Param(n) => ImplSource::Param(n.into_iter().map(f).collect()), ImplSource::Builtin(source, n) => { ImplSource::Builtin(source, n.into_iter().map(f).collect()) } diff --git a/compiler/rustc_middle/src/traits/select.rs b/compiler/rustc_middle/src/traits/select.rs index a90d58f5fc1..ffae3579889 100644 --- a/compiler/rustc_middle/src/traits/select.rs +++ b/compiler/rustc_middle/src/traits/select.rs @@ -127,6 +127,7 @@ pub enum SelectionCandidate<'tcx> { /// an applicable bound in the trait definition. The `usize` is an index /// into the list returned by `tcx.item_bounds`. The constness is the /// constness of the bound in the trait. + // FIXME(effects) do we need this constness ProjectionCandidate(usize, ty::BoundConstness), /// Implementation of a `Fn`-family trait by one of the anonymous types diff --git a/compiler/rustc_middle/src/traits/structural_impls.rs b/compiler/rustc_middle/src/traits/structural_impls.rs index d7dc429f53b..ec450cf5590 100644 --- a/compiler/rustc_middle/src/traits/structural_impls.rs +++ b/compiler/rustc_middle/src/traits/structural_impls.rs @@ -13,8 +13,8 @@ impl<'tcx, N: fmt::Debug> fmt::Debug for traits::ImplSource<'tcx, N> { write!(f, "Builtin({source:?}, {d:?})") } - super::ImplSource::Param(ct, n) => { - write!(f, "ImplSourceParamData({n:?}, {ct:?})") + super::ImplSource::Param(n) => { + write!(f, "ImplSourceParamData({n:?})") } } } diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 48aa25dba6d..1274f427e4f 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -238,7 +238,7 @@ pub struct ImplHeader<'tcx> { pub impl_def_id: DefId, pub self_ty: Ty<'tcx>, pub trait_ref: Option<TraitRef<'tcx>>, - pub predicates: Vec<Predicate<'tcx>>, + pub predicates: Vec<(Predicate<'tcx>, Span)>, } #[derive(Copy, Clone, PartialEq, Eq, Debug, TypeFoldable, TypeVisitable)] @@ -355,8 +355,8 @@ impl TyCtxt<'_> { #[inline] #[track_caller] - pub fn local_parent(self, id: LocalDefId) -> LocalDefId { - self.parent(id.to_def_id()).expect_local() + pub fn local_parent(self, id: impl Into<LocalDefId>) -> LocalDefId { + self.parent(id.into().to_def_id()).expect_local() } pub fn is_descendant_of(self, mut descendant: DefId, ancestor: DefId) -> bool { diff --git a/compiler/rustc_middle/src/ty/print/mod.rs b/compiler/rustc_middle/src/ty/print/mod.rs index 83a75d0c6b9..05871d0bc39 100644 --- a/compiler/rustc_middle/src/ty/print/mod.rs +++ b/compiler/rustc_middle/src/ty/print/mod.rs @@ -329,7 +329,8 @@ impl<'tcx, P: Printer<'tcx>> Print<'tcx, P> for ty::Const<'tcx> { } // This is only used by query descriptions -pub fn describe_as_module(def_id: LocalDefId, tcx: TyCtxt<'_>) -> String { +pub fn describe_as_module(def_id: impl Into<LocalDefId>, tcx: TyCtxt<'_>) -> String { + let def_id = def_id.into(); if def_id.is_top_level_module() { "top-level module".to_string() } else { diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index bb6513363c9..ac0c88468fa 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -11,7 +11,7 @@ use rustc_data_structures::fx::{FxHashMap, FxIndexMap}; use rustc_data_structures::sso::SsoHashSet; use rustc_hir as hir; use rustc_hir::def::{self, CtorKind, DefKind, Namespace}; -use rustc_hir::def_id::{DefId, DefIdSet, CRATE_DEF_ID, LOCAL_CRATE}; +use rustc_hir::def_id::{DefId, DefIdSet, ModDefId, CRATE_DEF_ID, LOCAL_CRATE}; use rustc_hir::definitions::{DefKey, DefPathData, DefPathDataName, DisambiguatedDefPathData}; use rustc_hir::LangItem; use rustc_session::config::TrimmedDefPaths; @@ -326,7 +326,8 @@ pub trait PrettyPrinter<'tcx>: { this .tcx() - .module_children(visible_parent) + // FIXME(typed_def_id): Further propagate ModDefId + .module_children(ModDefId::new_unchecked(*visible_parent)) .iter() .filter(|child| child.res.opt_def_id() == Some(def_id)) .find(|child| child.vis.is_public() && child.ident.name != kw::Underscore) @@ -551,7 +552,8 @@ pub trait PrettyPrinter<'tcx>: // that's public and whose identifier isn't `_`. let reexport = self .tcx() - .module_children(visible_parent) + // FIXME(typed_def_id): Further propagate ModDefId + .module_children(ModDefId::new_unchecked(visible_parent)) .iter() .filter(|child| child.res.opt_def_id() == Some(def_id)) .find(|child| child.vis.is_public() && child.ident.name != kw::Underscore) diff --git a/compiler/rustc_mir_build/src/thir/cx/expr.rs b/compiler/rustc_mir_build/src/thir/cx/expr.rs index 994ac8a3286..a96d837b3ad 100644 --- a/compiler/rustc_mir_build/src/thir/cx/expr.rs +++ b/compiler/rustc_mir_build/src/thir/cx/expr.rs @@ -445,7 +445,6 @@ impl<'tcx> Cx<'tcx> { let rhs = self.mirror_expr(rhs); self.overloaded_operator(expr, Box::new([lhs, rhs])) } else { - // FIXME overflow match op.node { hir::BinOpKind::And => ExprKind::LogicalOp { op: LogicalOp::And, diff --git a/compiler/rustc_parse/src/lexer/mod.rs b/compiler/rustc_parse/src/lexer/mod.rs index 1931ee5e528..a375a1d69cd 100644 --- a/compiler/rustc_parse/src/lexer/mod.rs +++ b/compiler/rustc_parse/src/lexer/mod.rs @@ -74,7 +74,6 @@ pub(crate) fn parse_token_trees<'a>( // because the delimiter mismatch is more likely to be the root cause of error let mut buffer = Vec::with_capacity(1); - // Not using `emit_unclosed_delims` to use `db.buffer` for unmatched in unmatched_delims { if let Some(err) = make_unclosed_delims_error(unmatched, &sess) { err.buffer(&mut buffer); diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs index c5b46b809b1..ce4d4a60551 100644 --- a/compiler/rustc_parse/src/parser/mod.rs +++ b/compiler/rustc_parse/src/parser/mod.rs @@ -29,7 +29,6 @@ use rustc_ast::{Async, AttrArgs, AttrArgsEq, Expr, ExprKind, Mutability, StrLit} use rustc_ast::{HasAttrs, HasTokens, Unsafe, Visibility, VisibilityKind}; use rustc_ast_pretty::pprust; use rustc_data_structures::fx::FxHashMap; -use rustc_data_structures::sync::Ordering; use rustc_errors::PResult; use rustc_errors::{ Applicability, DiagnosticBuilder, ErrorGuaranteed, FatalError, IntoDiagnostic, MultiSpan, @@ -1455,18 +1454,6 @@ pub(crate) fn make_unclosed_delims_error( Some(err) } -pub fn emit_unclosed_delims(unclosed_delims: &mut Vec<UnmatchedDelim>, sess: &ParseSess) { - let _ = sess.reached_eof.fetch_or( - unclosed_delims.iter().any(|unmatched_delim| unmatched_delim.found_delim.is_none()), - Ordering::Relaxed, - ); - for unmatched in unclosed_delims.drain(..) { - if let Some(mut e) = make_unclosed_delims_error(unmatched, sess) { - e.emit(); - } - } -} - /// A helper struct used when building an `AttrTokenStream` from /// a `LazyAttrTokenStream`. Both delimiter and non-delimited tokens /// are stored as `FlatToken::Token`. A vector of `FlatToken`s diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index 4f9b362e237..197b335bdec 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -10,7 +10,7 @@ use rustc_data_structures::fx::FxHashMap; use rustc_errors::{Applicability, IntoDiagnosticArg, MultiSpan}; use rustc_feature::{AttributeDuplicates, AttributeType, BuiltinAttribute, BUILTIN_ATTRIBUTE_MAP}; use rustc_hir as hir; -use rustc_hir::def_id::LocalDefId; +use rustc_hir::def_id::LocalModDefId; use rustc_hir::intravisit::{self, Visitor}; use rustc_hir::{ self, FnSig, ForeignItem, HirId, Item, ItemKind, TraitItem, CRATE_HIR_ID, CRATE_OWNER_ID, @@ -2465,10 +2465,10 @@ fn check_non_exported_macro_for_invalid_attrs(tcx: TyCtxt<'_>, item: &Item<'_>) } } -fn check_mod_attrs(tcx: TyCtxt<'_>, module_def_id: LocalDefId) { +fn check_mod_attrs(tcx: TyCtxt<'_>, module_def_id: LocalModDefId) { let check_attr_visitor = &mut CheckAttrVisitor { tcx, abort: Cell::new(false) }; tcx.hir().visit_item_likes_in_module(module_def_id, check_attr_visitor); - if module_def_id.is_top_level_module() { + if module_def_id.to_local_def_id().is_top_level_module() { check_attr_visitor.check_attributes(CRATE_HIR_ID, DUMMY_SP, Target::Mod, None); check_invalid_crate_level_attr(tcx, tcx.hir().krate_attrs()); } diff --git a/compiler/rustc_passes/src/check_const.rs b/compiler/rustc_passes/src/check_const.rs index e70817d7b7c..495eb615ed8 100644 --- a/compiler/rustc_passes/src/check_const.rs +++ b/compiler/rustc_passes/src/check_const.rs @@ -9,7 +9,7 @@ use rustc_attr as attr; use rustc_hir as hir; -use rustc_hir::def_id::LocalDefId; +use rustc_hir::def_id::{LocalDefId, LocalModDefId}; use rustc_hir::intravisit::{self, Visitor}; use rustc_middle::hir::nested_filter; use rustc_middle::query::Providers; @@ -55,7 +55,7 @@ impl NonConstExpr { } } -fn check_mod_const_bodies(tcx: TyCtxt<'_>, module_def_id: LocalDefId) { +fn check_mod_const_bodies(tcx: TyCtxt<'_>, module_def_id: LocalModDefId) { let mut vis = CheckConstVisitor::new(tcx); tcx.hir().visit_item_likes_in_module(module_def_id, &mut vis); } diff --git a/compiler/rustc_passes/src/dead.rs b/compiler/rustc_passes/src/dead.rs index 2936c8fac7d..d1c3bcf3839 100644 --- a/compiler/rustc_passes/src/dead.rs +++ b/compiler/rustc_passes/src/dead.rs @@ -8,7 +8,7 @@ use rustc_data_structures::unord::UnordSet; use rustc_errors::MultiSpan; use rustc_hir as hir; use rustc_hir::def::{CtorOf, DefKind, Res}; -use rustc_hir::def_id::{DefId, LocalDefId}; +use rustc_hir::def_id::{DefId, LocalDefId, LocalModDefId}; use rustc_hir::intravisit::{self, Visitor}; use rustc_hir::{Node, PatKind, TyKind}; use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags; @@ -944,7 +944,7 @@ impl<'tcx> DeadVisitor<'tcx> { } } -fn check_mod_deathness(tcx: TyCtxt<'_>, module: LocalDefId) { +fn check_mod_deathness(tcx: TyCtxt<'_>, module: LocalModDefId) { let (live_symbols, ignored_derived_traits) = tcx.live_symbols_and_ignored_derived_traits(()); let mut visitor = DeadVisitor { tcx, live_symbols, ignored_derived_traits }; @@ -969,7 +969,7 @@ fn check_mod_deathness(tcx: TyCtxt<'_>, module: LocalDefId) { if !live_symbols.contains(&item.owner_id.def_id) { let parent = tcx.local_parent(item.owner_id.def_id); - if parent != module && !live_symbols.contains(&parent) { + if parent != module.to_local_def_id() && !live_symbols.contains(&parent) { // We already have diagnosed something. continue; } diff --git a/compiler/rustc_passes/src/entry.rs b/compiler/rustc_passes/src/entry.rs index 6a29159e917..4f71704b885 100644 --- a/compiler/rustc_passes/src/entry.rs +++ b/compiler/rustc_passes/src/entry.rs @@ -187,12 +187,6 @@ fn sigpipe(tcx: TyCtxt<'_>, def_id: DefId) -> u8 { fn no_main_err(tcx: TyCtxt<'_>, visitor: &EntryContext<'_>) { let sp = tcx.def_span(CRATE_DEF_ID); - if tcx.sess.parse_sess.reached_eof.load(rustc_data_structures::sync::Ordering::Relaxed) { - // There's an unclosed brace that made the parser reach `Eof`, we shouldn't complain about - // the missing `fn main()` then as it might have been hidden inside an unclosed block. - tcx.sess.delay_span_bug(sp, "`main` not found, but expected unclosed brace error"); - return; - } // There is no main function. let mut has_filename = true; diff --git a/compiler/rustc_passes/src/loops.rs b/compiler/rustc_passes/src/loops.rs index 7c64df6a50e..0aaf85086e4 100644 --- a/compiler/rustc_passes/src/loops.rs +++ b/compiler/rustc_passes/src/loops.rs @@ -1,7 +1,7 @@ use Context::*; use rustc_hir as hir; -use rustc_hir::def_id::LocalDefId; +use rustc_hir::def_id::LocalModDefId; use rustc_hir::intravisit::{self, Visitor}; use rustc_hir::{Destination, Movability, Node}; use rustc_middle::hir::map::Map; @@ -34,7 +34,7 @@ struct CheckLoopVisitor<'a, 'hir> { cx: Context, } -fn check_mod_loops(tcx: TyCtxt<'_>, module_def_id: LocalDefId) { +fn check_mod_loops(tcx: TyCtxt<'_>, module_def_id: LocalModDefId) { tcx.hir().visit_item_likes_in_module( module_def_id, &mut CheckLoopVisitor { sess: &tcx.sess, hir_map: tcx.hir(), cx: Normal }, diff --git a/compiler/rustc_passes/src/naked_functions.rs b/compiler/rustc_passes/src/naked_functions.rs index 769b389009b..7f36c59ad98 100644 --- a/compiler/rustc_passes/src/naked_functions.rs +++ b/compiler/rustc_passes/src/naked_functions.rs @@ -3,7 +3,7 @@ use rustc_ast::InlineAsmOptions; use rustc_hir as hir; use rustc_hir::def::DefKind; -use rustc_hir::def_id::LocalDefId; +use rustc_hir::def_id::{LocalDefId, LocalModDefId}; use rustc_hir::intravisit::Visitor; use rustc_hir::{ExprKind, InlineAsmOperand, StmtKind}; use rustc_middle::query::Providers; @@ -23,7 +23,7 @@ pub(crate) fn provide(providers: &mut Providers) { *providers = Providers { check_mod_naked_functions, ..*providers }; } -fn check_mod_naked_functions(tcx: TyCtxt<'_>, module_def_id: LocalDefId) { +fn check_mod_naked_functions(tcx: TyCtxt<'_>, module_def_id: LocalModDefId) { let items = tcx.hir_module_items(module_def_id); for def_id in items.definitions() { if !matches!(tcx.def_kind(def_id), DefKind::Fn | DefKind::AssocFn) { diff --git a/compiler/rustc_passes/src/stability.rs b/compiler/rustc_passes/src/stability.rs index bd2336410b9..9c265e8ec11 100644 --- a/compiler/rustc_passes/src/stability.rs +++ b/compiler/rustc_passes/src/stability.rs @@ -9,7 +9,7 @@ use rustc_attr::{ use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap}; use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; -use rustc_hir::def_id::{LocalDefId, CRATE_DEF_ID}; +use rustc_hir::def_id::{LocalDefId, LocalModDefId, CRATE_DEF_ID}; use rustc_hir::hir_id::CRATE_HIR_ID; use rustc_hir::intravisit::{self, Visitor}; use rustc_hir::{FieldDef, Item, ItemKind, TraitRef, Ty, TyKind, Variant}; @@ -682,7 +682,7 @@ fn stability_index(tcx: TyCtxt<'_>, (): ()) -> Index { /// Cross-references the feature names of unstable APIs with enabled /// features and possibly prints errors. -fn check_mod_unstable_api_usage(tcx: TyCtxt<'_>, module_def_id: LocalDefId) { +fn check_mod_unstable_api_usage(tcx: TyCtxt<'_>, module_def_id: LocalModDefId) { tcx.hir().visit_item_likes_in_module(module_def_id, &mut Checker { tcx }); } diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs index 30a4235d371..0eb344ba690 100644 --- a/compiler/rustc_privacy/src/lib.rs +++ b/compiler/rustc_privacy/src/lib.rs @@ -20,7 +20,7 @@ use rustc_errors::{DiagnosticMessage, SubdiagnosticMessage}; use rustc_fluent_macro::fluent_messages; use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; -use rustc_hir::def_id::{DefId, LocalDefId, CRATE_DEF_ID}; +use rustc_hir::def_id::{DefId, LocalDefId, LocalModDefId, CRATE_DEF_ID}; use rustc_hir::intravisit::{self, Visitor}; use rustc_hir::{AssocItemKind, ForeignItemKind, HirIdSet, ItemId, Node, PatKind}; use rustc_middle::bug; @@ -382,8 +382,9 @@ impl VisibilityLike for EffectiveVisibility { ) -> Self { let effective_vis = find.effective_visibilities.effective_vis(def_id).copied().unwrap_or_else(|| { - let private_vis = - ty::Visibility::Restricted(find.tcx.parent_module_from_def_id(def_id)); + let private_vis = ty::Visibility::Restricted( + find.tcx.parent_module_from_def_id(def_id).to_local_def_id(), + ); EffectiveVisibility::from_vis(private_vis) }); @@ -412,7 +413,7 @@ struct EmbargoVisitor<'tcx> { /// pub macro m() { /// n::p::f() /// } - macro_reachable: FxHashSet<(LocalDefId, LocalDefId)>, + macro_reachable: FxHashSet<(LocalModDefId, LocalModDefId)>, /// Preliminary pass for marking all underlying types of `impl Trait`s as reachable. impl_trait_pass: bool, /// Has something changed in the level map? @@ -449,7 +450,9 @@ impl<'tcx> EmbargoVisitor<'tcx> { max_vis: Option<ty::Visibility>, level: Level, ) { - let private_vis = ty::Visibility::Restricted(self.tcx.parent_module_from_def_id(def_id)); + // FIXME(typed_def_id): Make `Visibility::Restricted` use a `LocalModDefId` by default. + let private_vis = + ty::Visibility::Restricted(self.tcx.parent_module_from_def_id(def_id).into()); if max_vis != Some(private_vis) { self.changed |= self.effective_visibilities.update( def_id, @@ -508,6 +511,8 @@ impl<'tcx> EmbargoVisitor<'tcx> { // The macro's parent doesn't correspond to a `mod`, return early (#63164, #65252). return; } + // FIXME(typed_def_id): Introduce checked constructors that check def_kind. + let macro_module_def_id = LocalModDefId::new_unchecked(macro_module_def_id); if self.effective_visibilities.public_at_level(local_def_id).is_none() { return; @@ -519,10 +524,10 @@ impl<'tcx> EmbargoVisitor<'tcx> { loop { let changed_reachability = self.update_macro_reachable(module_def_id, macro_module_def_id, macro_ev); - if changed_reachability || module_def_id == CRATE_DEF_ID { + if changed_reachability || module_def_id == LocalModDefId::CRATE_DEF_ID { break; } - module_def_id = self.tcx.local_parent(module_def_id); + module_def_id = LocalModDefId::new_unchecked(self.tcx.local_parent(module_def_id)); } } @@ -530,8 +535,8 @@ impl<'tcx> EmbargoVisitor<'tcx> { /// module. Returns `true` if the level has changed. fn update_macro_reachable( &mut self, - module_def_id: LocalDefId, - defining_mod: LocalDefId, + module_def_id: LocalModDefId, + defining_mod: LocalModDefId, macro_ev: EffectiveVisibility, ) -> bool { if self.macro_reachable.insert((module_def_id, defining_mod)) { @@ -544,8 +549,8 @@ impl<'tcx> EmbargoVisitor<'tcx> { fn update_macro_reachable_mod( &mut self, - module_def_id: LocalDefId, - defining_mod: LocalDefId, + module_def_id: LocalModDefId, + defining_mod: LocalModDefId, macro_ev: EffectiveVisibility, ) { let module = self.tcx.hir().get_module(module_def_id).0; @@ -560,7 +565,7 @@ impl<'tcx> EmbargoVisitor<'tcx> { macro_ev, ); } - for child in self.tcx.module_children_local(module_def_id) { + for child in self.tcx.module_children_local(module_def_id.to_local_def_id()) { // FIXME: Use module children for the logic above too. if !child.reexport_chain.is_empty() && child.vis.is_accessible_from(defining_mod, self.tcx) @@ -577,7 +582,7 @@ impl<'tcx> EmbargoVisitor<'tcx> { def_id: LocalDefId, def_kind: DefKind, vis: ty::Visibility, - module: LocalDefId, + module: LocalModDefId, macro_ev: EffectiveVisibility, ) { self.update(def_id, macro_ev, Level::Reachable); @@ -608,7 +613,11 @@ impl<'tcx> EmbargoVisitor<'tcx> { // the module, however may be reachable. DefKind::Mod => { if vis.is_accessible_from(module, self.tcx) { - self.update_macro_reachable(def_id, module, macro_ev); + self.update_macro_reachable( + LocalModDefId::new_unchecked(def_id), + module, + macro_ev, + ); } } @@ -892,7 +901,7 @@ fn vis_to_string<'tcx>(def_id: LocalDefId, vis: ty::Visibility, tcx: TyCtxt<'tcx ty::Visibility::Restricted(restricted_id) => { if restricted_id.is_top_level_module() { "pub(crate)".to_string() - } else if restricted_id == tcx.parent_module_from_def_id(def_id) { + } else if restricted_id == tcx.parent_module_from_def_id(def_id).to_local_def_id() { "pub(self)".to_string() } else { format!("pub({})", tcx.item_name(restricted_id.to_def_id())) @@ -1800,7 +1809,7 @@ impl SearchInterfaceForPrivateItemsVisitor<'_> { let vis_descr = match vis { ty::Visibility::Public => "public", ty::Visibility::Restricted(vis_def_id) => { - if vis_def_id == self.tcx.parent_module(hir_id) { + if vis_def_id == self.tcx.parent_module(hir_id).to_local_def_id() { "private" } else if vis_def_id.is_top_level_module() { "crate-private" @@ -2196,7 +2205,7 @@ fn local_visibility(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Visibility { kind: hir::ItemKind::Use(_, hir::UseKind::ListStem) | hir::ItemKind::OpaqueTy(..), .. - }) => ty::Visibility::Restricted(tcx.parent_module(hir_id)), + }) => ty::Visibility::Restricted(tcx.parent_module(hir_id).to_local_def_id()), // Visibilities of trait impl items are inherited from their traits // and are not filled in resolve. Node::ImplItem(impl_item) => { @@ -2224,18 +2233,25 @@ fn local_visibility(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Visibility { } } -fn check_mod_privacy(tcx: TyCtxt<'_>, module_def_id: LocalDefId) { +fn check_mod_privacy(tcx: TyCtxt<'_>, module_def_id: LocalModDefId) { // Check privacy of names not checked in previous compilation stages. - let mut visitor = - NamePrivacyVisitor { tcx, maybe_typeck_results: None, current_item: module_def_id }; + let mut visitor = NamePrivacyVisitor { + tcx, + maybe_typeck_results: None, + current_item: module_def_id.to_local_def_id(), + }; let (module, span, hir_id) = tcx.hir().get_module(module_def_id); intravisit::walk_mod(&mut visitor, module, hir_id); // Check privacy of explicitly written types and traits as well as // inferred types of expressions and patterns. - let mut visitor = - TypePrivacyVisitor { tcx, maybe_typeck_results: None, current_item: module_def_id, span }; + let mut visitor = TypePrivacyVisitor { + tcx, + maybe_typeck_results: None, + current_item: module_def_id.to_local_def_id(), + span, + }; intravisit::walk_mod(&mut visitor, module, hir_id); } diff --git a/compiler/rustc_query_system/src/dep_graph/graph.rs b/compiler/rustc_query_system/src/dep_graph/graph.rs index 3803f7eca0a..30422ea1102 100644 --- a/compiler/rustc_query_system/src/dep_graph/graph.rs +++ b/compiler/rustc_query_system/src/dep_graph/graph.rs @@ -1,5 +1,5 @@ use rustc_data_structures::fingerprint::Fingerprint; -use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap}; +use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::profiling::{EventId, QueryInvocationId, SelfProfilerRef}; use rustc_data_structures::sharded::{self, Sharded}; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; @@ -93,7 +93,7 @@ pub struct DepGraphData<K: DepKind> { /// things available to us. If we find that they are not dirty, we /// load the path to the file storing those work-products here into /// this map. We can later look for and extract that data. - previous_work_products: FxIndexMap<WorkProductId, WorkProduct>, + previous_work_products: WorkProductMap, dep_node_debug: Lock<FxHashMap<DepNode<K>, String>>, @@ -116,7 +116,7 @@ impl<K: DepKind> DepGraph<K> { pub fn new( profiler: &SelfProfilerRef, prev_graph: SerializedDepGraph<K>, - prev_work_products: FxIndexMap<WorkProductId, WorkProduct>, + prev_work_products: WorkProductMap, encoder: FileEncoder, record_graph: bool, record_stats: bool, @@ -688,7 +688,7 @@ impl<K: DepKind> DepGraph<K> { /// Access the map of work-products created during the cached run. Only /// used during saving of the dep-graph. - pub fn previous_work_products(&self) -> &FxIndexMap<WorkProductId, WorkProduct> { + pub fn previous_work_products(&self) -> &WorkProductMap { &self.data.as_ref().unwrap().previous_work_products } @@ -1051,6 +1051,8 @@ pub struct WorkProduct { pub saved_files: UnordMap<String, String>, } +pub type WorkProductMap = UnordMap<WorkProductId, WorkProduct>; + // Index type for `DepNodeData`'s edges. rustc_index::newtype_index! { struct EdgeIndex {} diff --git a/compiler/rustc_query_system/src/dep_graph/mod.rs b/compiler/rustc_query_system/src/dep_graph/mod.rs index 40e7131987f..0fd9e35d6dc 100644 --- a/compiler/rustc_query_system/src/dep_graph/mod.rs +++ b/compiler/rustc_query_system/src/dep_graph/mod.rs @@ -7,7 +7,7 @@ mod serialized; pub use dep_node::{DepKindStruct, DepNode, DepNodeParams, WorkProductId}; pub use graph::{ hash_result, DepGraph, DepGraphData, DepNodeColor, DepNodeIndex, TaskDeps, TaskDepsRef, - WorkProduct, + WorkProduct, WorkProductMap, }; pub use query::DepGraphQuery; pub use serialized::{SerializedDepGraph, SerializedDepNodeIndex}; diff --git a/compiler/rustc_session/src/parse.rs b/compiler/rustc_session/src/parse.rs index bca49981668..1cf63e9b7ba 100644 --- a/compiler/rustc_session/src/parse.rs +++ b/compiler/rustc_session/src/parse.rs @@ -8,7 +8,7 @@ use crate::lint::{ }; use rustc_ast::node_id::NodeId; use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexSet}; -use rustc_data_structures::sync::{AppendOnlyVec, AtomicBool, Lock, Lrc}; +use rustc_data_structures::sync::{AppendOnlyVec, Lock, Lrc}; use rustc_errors::{emitter::SilentEmitter, Handler}; use rustc_errors::{ fallback_fluent_bundle, Diagnostic, DiagnosticBuilder, DiagnosticId, DiagnosticMessage, @@ -204,8 +204,6 @@ pub struct ParseSess { pub ambiguous_block_expr_parse: Lock<FxHashMap<Span, Span>>, pub gated_spans: GatedSpans, pub symbol_gallery: SymbolGallery, - /// The parser has reached `Eof` due to an unclosed brace. Used to silence unnecessary errors. - pub reached_eof: AtomicBool, /// Environment variables accessed during the build and their values when they exist. pub env_depinfo: Lock<FxHashSet<(Symbol, Option<Symbol>)>>, /// File paths accessed during the build. @@ -242,7 +240,6 @@ impl ParseSess { ambiguous_block_expr_parse: Lock::new(FxHashMap::default()), gated_spans: GatedSpans::default(), symbol_gallery: SymbolGallery::default(), - reached_eof: AtomicBool::new(false), env_depinfo: Default::default(), file_depinfo: Default::default(), assume_incomplete_release: false, diff --git a/compiler/rustc_smir/src/rustc_smir/mod.rs b/compiler/rustc_smir/src/rustc_smir/mod.rs index bc12422e7d7..06b37008ebe 100644 --- a/compiler/rustc_smir/src/rustc_smir/mod.rs +++ b/compiler/rustc_smir/src/rustc_smir/mod.rs @@ -10,7 +10,7 @@ use crate::rustc_internal::{self, opaque}; use crate::stable_mir::mir::{CopyNonOverlapping, UserTypeProjection, VariantIdx}; use crate::stable_mir::ty::{ - allocation_filter, new_allocation, FloatTy, IntTy, Movability, RigidTy, TyKind, UintTy, + allocation_filter, new_allocation, Const, FloatTy, IntTy, Movability, RigidTy, TyKind, UintTy, }; use crate::stable_mir::{self, Context}; use rustc_hir as hir; @@ -187,7 +187,11 @@ impl<'tcx> Stable<'tcx> for mir::Rvalue<'tcx> { use mir::Rvalue::*; match self { Use(op) => stable_mir::mir::Rvalue::Use(op.stable(tables)), - Repeat(op, len) => stable_mir::mir::Rvalue::Repeat(op.stable(tables), opaque(len)), + Repeat(op, len) => { + let cnst = ConstantKind::from_const(*len, tables.tcx); + let len = Const { literal: cnst.stable(tables) }; + stable_mir::mir::Rvalue::Repeat(op.stable(tables), len) + } Ref(region, kind, place) => stable_mir::mir::Rvalue::Ref( opaque(region), kind.stable(tables), @@ -372,7 +376,11 @@ impl<'tcx> Stable<'tcx> for ty::TermKind<'tcx> { use stable_mir::ty::TermKind; match self { ty::TermKind::Ty(ty) => TermKind::Type(tables.intern_ty(*ty)), - ty::TermKind::Const(const_) => TermKind::Const(opaque(const_)), + ty::TermKind::Const(cnst) => { + let cnst = ConstantKind::from_const(*cnst, tables.tcx); + let cnst = Const { literal: cnst.stable(tables) }; + TermKind::Const(cnst) + } } } } @@ -829,7 +837,10 @@ impl<'tcx> Stable<'tcx> for ty::GenericArgKind<'tcx> { match self { ty::GenericArgKind::Lifetime(region) => GenericArgKind::Lifetime(opaque(region)), ty::GenericArgKind::Type(ty) => GenericArgKind::Type(tables.intern_ty(*ty)), - ty::GenericArgKind::Const(const_) => GenericArgKind::Const(opaque(&const_)), + ty::GenericArgKind::Const(cnst) => { + let cnst = ConstantKind::from_const(*cnst, tables.tcx); + GenericArgKind::Const(stable_mir::ty::Const { literal: cnst.stable(tables) }) + } } } } @@ -1035,7 +1046,9 @@ impl<'tcx> Stable<'tcx> for Ty<'tcx> { } ty::Str => TyKind::RigidTy(RigidTy::Str), ty::Array(ty, constant) => { - TyKind::RigidTy(RigidTy::Array(tables.intern_ty(*ty), opaque(constant))) + let cnst = ConstantKind::from_const(*constant, tables.tcx); + let cnst = stable_mir::ty::Const { literal: cnst.stable(tables) }; + TyKind::RigidTy(RigidTy::Array(tables.intern_ty(*ty), cnst)) } ty::Slice(ty) => TyKind::RigidTy(RigidTy::Slice(tables.intern_ty(*ty))), ty::RawPtr(ty::TypeAndMut { ty, mutbl }) => { diff --git a/compiler/rustc_smir/src/stable_mir/ty.rs b/compiler/rustc_smir/src/stable_mir/ty.rs index 875d5ae70da..f8ff6741208 100644 --- a/compiler/rustc_smir/src/stable_mir/ty.rs +++ b/compiler/rustc_smir/src/stable_mir/ty.rs @@ -15,7 +15,11 @@ impl Ty { } } -pub(crate) type Const = Opaque; +#[derive(Debug, Clone)] +pub struct Const { + pub literal: ConstantKind, +} + type Ident = Opaque; pub(crate) type Region = Opaque; type Span = Opaque; diff --git a/compiler/rustc_span/src/def_id.rs b/compiler/rustc_span/src/def_id.rs index f65a6aa4fb2..595babc26ae 100644 --- a/compiler/rustc_span/src/def_id.rs +++ b/compiler/rustc_span/src/def_id.rs @@ -28,10 +28,16 @@ impl CrateNum { CrateNum::from_usize(x) } + // FIXME(typed_def_id): Replace this with `as_mod_def_id`. #[inline] pub fn as_def_id(self) -> DefId { DefId { krate: self, index: CRATE_DEF_INDEX } } + + #[inline] + pub fn as_mod_def_id(self) -> ModDefId { + ModDefId::new_unchecked(DefId { krate: self, index: CRATE_DEF_INDEX }) + } } impl fmt::Display for CrateNum { @@ -485,3 +491,92 @@ impl<CTX: HashStableContext> ToStableHashKey<CTX> for CrateNum { self.as_def_id().to_stable_hash_key(hcx) } } + +macro_rules! typed_def_id { + ($Name:ident, $LocalName:ident) => { + #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Encodable, Decodable, HashStable_Generic)] + pub struct $Name(DefId); + + impl $Name { + pub const fn new_unchecked(def_id: DefId) -> Self { + Self(def_id) + } + + pub fn to_def_id(self) -> DefId { + self.into() + } + + pub fn is_local(self) -> bool { + self.0.is_local() + } + + pub fn as_local(self) -> Option<$LocalName> { + self.0.as_local().map($LocalName::new_unchecked) + } + } + + impl From<$LocalName> for $Name { + fn from(local: $LocalName) -> Self { + Self(local.0.to_def_id()) + } + } + + impl From<$Name> for DefId { + fn from(typed: $Name) -> Self { + typed.0 + } + } + + #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Encodable, Decodable, HashStable_Generic)] + pub struct $LocalName(LocalDefId); + + impl !Ord for $LocalName {} + impl !PartialOrd for $LocalName {} + + impl $LocalName { + pub const fn new_unchecked(def_id: LocalDefId) -> Self { + Self(def_id) + } + + pub fn to_def_id(self) -> DefId { + self.0.into() + } + + pub fn to_local_def_id(self) -> LocalDefId { + self.0 + } + } + + impl From<$LocalName> for LocalDefId { + fn from(typed: $LocalName) -> Self { + typed.0 + } + } + + impl From<$LocalName> for DefId { + fn from(typed: $LocalName) -> Self { + typed.0.into() + } + } + }; +} + +// N.B.: when adding new typed `DefId`s update the corresponding trait impls in +// `rustc_middle::dep_graph::def_node` for `DepNodeParams`. +typed_def_id! { ModDefId, LocalModDefId } + +impl LocalModDefId { + pub const CRATE_DEF_ID: Self = Self::new_unchecked(CRATE_DEF_ID); +} + +impl ModDefId { + pub fn is_top_level_module(self) -> bool { + self.0.is_top_level_module() + } +} + +impl LocalModDefId { + pub fn is_top_level_module(self) -> bool { + self.0.is_top_level_module() + } +} diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 745a3590720..a0daebf5baa 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -574,6 +574,7 @@ symbols! { crate_type, crate_visibility_modifier, crt_dash_static: "crt-static", + csky_target_feature, cstring_type, ctlz, ctlz_nonzero, diff --git a/compiler/rustc_target/Cargo.toml b/compiler/rustc_target/Cargo.toml index a71e2e8cc57..393e59e8b00 100644 --- a/compiler/rustc_target/Cargo.toml +++ b/compiler/rustc_target/Cargo.toml @@ -16,6 +16,6 @@ rustc_serialize = { path = "../rustc_serialize" } rustc_span = { path = "../rustc_span" } [dependencies.object] -version = "0.31.1" +version = "0.32.0" default-features = false features = ["elf"] diff --git a/compiler/rustc_target/src/abi/call/csky.rs b/compiler/rustc_target/src/abi/call/csky.rs new file mode 100644 index 00000000000..bbe95fa20ac --- /dev/null +++ b/compiler/rustc_target/src/abi/call/csky.rs @@ -0,0 +1,31 @@ +// See https://github.com/llvm/llvm-project/blob/d85b94bf0080dcd780656c0f5e6342800720eba9/llvm/lib/Target/CSKY/CSKYCallingConv.td +use crate::abi::call::{ArgAbi, FnAbi}; + +fn classify_ret<Ty>(ret: &mut ArgAbi<'_, Ty>) { + if ret.layout.is_aggregate() || ret.layout.size.bits() > 64 { + ret.make_indirect(); + } else { + ret.extend_integer_width_to(32); + } +} + +fn classify_arg<Ty>(arg: &mut ArgAbi<'_, Ty>) { + if arg.layout.is_aggregate() || arg.layout.size.bits() > 64 { + arg.make_indirect(); + } else { + arg.extend_integer_width_to(32); + } +} + +pub fn compute_abi_info<Ty>(fn_abi: &mut FnAbi<'_, Ty>) { + if !fn_abi.ret.is_ignore() { + classify_ret(&mut fn_abi.ret); + } + + for arg in fn_abi.args.iter_mut() { + if arg.is_ignore() { + continue; + } + classify_arg(arg); + } +} diff --git a/compiler/rustc_target/src/abi/call/mod.rs b/compiler/rustc_target/src/abi/call/mod.rs index e4989bdfbcd..8fab13d5d5d 100644 --- a/compiler/rustc_target/src/abi/call/mod.rs +++ b/compiler/rustc_target/src/abi/call/mod.rs @@ -9,6 +9,7 @@ mod amdgpu; mod arm; mod avr; mod bpf; +mod csky; mod hexagon; mod loongarch; mod m68k; @@ -712,6 +713,7 @@ impl<'a, Ty> FnAbi<'a, Ty> { "avr" => avr::compute_abi_info(self), "loongarch64" => loongarch::compute_abi_info(cx, self), "m68k" => m68k::compute_abi_info(self), + "csky" => csky::compute_abi_info(self), "mips" | "mips32r6" => mips::compute_abi_info(cx, self), "mips64" | "mips64r6" => mips64::compute_abi_info(cx, self), "powerpc" => powerpc::compute_abi_info(self), diff --git a/compiler/rustc_target/src/asm/csky.rs b/compiler/rustc_target/src/asm/csky.rs new file mode 100644 index 00000000000..6f0e7f79949 --- /dev/null +++ b/compiler/rustc_target/src/asm/csky.rs @@ -0,0 +1,128 @@ +use super::{InlineAsmArch, InlineAsmType}; +use rustc_macros::HashStable_Generic; +use rustc_span::Symbol; +use std::fmt; + +def_reg_class! { + CSKY CSKYInlineAsmRegClass { + reg, + freg, + } +} + +impl CSKYInlineAsmRegClass { + pub fn valid_modifiers(self, _arch: super::InlineAsmArch) -> &'static [char] { + &[] + } + + pub fn suggest_class(self, _arch: InlineAsmArch, _ty: InlineAsmType) -> Option<Self> { + 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<Symbol>)] { + match self { + Self::reg => types! { _: I8, I16, I32; }, + Self::freg => types! { _: F32; }, + } + } +} + +// The reserved registers are taken from <https://github.com/llvm/llvm-project/blob/main/llvm/lib/Target/CSKY/CSKYRegisterInfo.cpp#79> +def_regs! { + CSKY CSKYInlineAsmReg CSKYInlineAsmRegClass { + r0: reg = ["r0","a0"], + r1: reg = ["r1","a1"], + r2: reg = ["r2","a2"], + r3: reg = ["r3","a3"], + r4: reg = ["r4","l0"], + r5: reg = ["r5","l1"], + r6: reg = ["r6","l2"], + r9: reg = ["r9","l5"],// feature e2 + r10: reg = ["r10","l6"],// feature e2 + r11: reg = ["r11","l7"],// feature e2 + r12: reg = ["r12","t0"],// feature e2 + r13: reg = ["r13","t1"],// feature e2 + r16: reg = ["r16","l8"],// feature high-register + r17: reg = ["r17","l9"],// feature high-register + r18: reg = ["r18","t2"],// feature high-register + r19: reg = ["r19","t3"],// feature high-register + r20: reg = ["r20","t4"],// feature high-register + r21: reg = ["r21","t5"],// feature high-register + r22: reg = ["r22","t6"],// feature high-register + r23: reg = ["r23","t7", "fp"],// feature high-register + r24: reg = ["r24","t8", "sop"],// feature high-register + r25: reg = ["r25","t9","tp", "bsp"],// feature high-register + f0: freg = ["fr0","vr0"], + f1: freg = ["fr1","vr1"], + f2: freg = ["fr2","vr2"], + f3: freg = ["fr3","vr3"], + f4: freg = ["fr4","vr4"], + f5: freg = ["fr5","vr5"], + f6: freg = ["fr6","vr6"], + f7: freg = ["fr7","vr7"], + f8: freg = ["fr8","vr8"], + f9: freg = ["fr9","vr9"], + f10: freg = ["fr10","vr10"], + f11: freg = ["fr11","vr11"], + f12: freg = ["fr12","vr12"], + f13: freg = ["fr13","vr13"], + f14: freg = ["fr14","vr14"], + f15: freg = ["fr15","vr15"], + f16: freg = ["fr16","vr16"], + f17: freg = ["fr17","vr17"], + f18: freg = ["fr18","vr18"], + f19: freg = ["fr19","vr19"], + f20: freg = ["fr20","vr20"], + f21: freg = ["fr21","vr21"], + f22: freg = ["fr22","vr22"], + f23: freg = ["fr23","vr23"], + f24: freg = ["fr24","vr24"], + f25: freg = ["fr25","vr25"], + f26: freg = ["fr26","vr26"], + f27: freg = ["fr27","vr27"], + f28: freg = ["fr28","vr28"], + f29: freg = ["fr29","vr29"], + f30: freg = ["fr30","vr30"], + f31: freg = ["fr31","vr31"], + #error = ["r7", "l3"] => + "the base pointer cannot be used as an operand for inline asm", + #error = ["r8","l4"] => + "the frame pointer cannot be used as an operand for inline asm", + #error = ["r14","sp"] => + "the stack pointer cannot be used as an operand for inline asm", + #error = ["r15","lr"] => + "the link register cannot be used as an operand for inline asm", + #error = ["r31","tls"] => + "reserver for tls", + #error = ["r28", "gb", "rgb", "rdb"] => + "the global pointer cannot be used as an operand for inline asm", + #error = ["r26","r27","r29","tb", "rtb", "r30","svbr"] => + "reserved by the ABI", + } +} + +impl CSKYInlineAsmReg { + pub fn emit( + self, + out: &mut dyn fmt::Write, + _arch: InlineAsmArch, + _modifier: Option<char>, + ) -> 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 7c27732079b..a11884bea26 100644 --- a/compiler/rustc_target/src/asm/mod.rs +++ b/compiler/rustc_target/src/asm/mod.rs @@ -167,6 +167,7 @@ mod aarch64; mod arm; mod avr; mod bpf; +mod csky; mod hexagon; mod loongarch; mod m68k; @@ -184,6 +185,7 @@ pub use aarch64::{AArch64InlineAsmReg, AArch64InlineAsmRegClass}; pub use arm::{ArmInlineAsmReg, ArmInlineAsmRegClass}; pub use avr::{AvrInlineAsmReg, AvrInlineAsmRegClass}; pub use bpf::{BpfInlineAsmReg, BpfInlineAsmRegClass}; +pub use csky::{CSKYInlineAsmReg, CSKYInlineAsmRegClass}; pub use hexagon::{HexagonInlineAsmReg, HexagonInlineAsmRegClass}; pub use loongarch::{LoongArchInlineAsmReg, LoongArchInlineAsmRegClass}; pub use m68k::{M68kInlineAsmReg, M68kInlineAsmRegClass}; @@ -220,6 +222,7 @@ pub enum InlineAsmArch { Avr, Msp430, M68k, + CSKY, } impl FromStr for InlineAsmArch { @@ -248,6 +251,7 @@ impl FromStr for InlineAsmArch { "avr" => Ok(Self::Avr), "msp430" => Ok(Self::Msp430), "m68k" => Ok(Self::M68k), + "csky" => Ok(Self::CSKY), _ => Err(()), } } @@ -272,6 +276,7 @@ pub enum InlineAsmReg { Avr(AvrInlineAsmReg), Msp430(Msp430InlineAsmReg), M68k(M68kInlineAsmReg), + CSKY(CSKYInlineAsmReg), // Placeholder for invalid register constraints for the current target Err, } @@ -292,6 +297,7 @@ impl InlineAsmReg { Self::Avr(r) => r.name(), Self::Msp430(r) => r.name(), Self::M68k(r) => r.name(), + Self::CSKY(r) => r.name(), Self::Err => "<reg>", } } @@ -311,6 +317,7 @@ impl InlineAsmReg { Self::Avr(r) => InlineAsmRegClass::Avr(r.reg_class()), Self::Msp430(r) => InlineAsmRegClass::Msp430(r.reg_class()), Self::M68k(r) => InlineAsmRegClass::M68k(r.reg_class()), + Self::CSKY(r) => InlineAsmRegClass::CSKY(r.reg_class()), Self::Err => InlineAsmRegClass::Err, } } @@ -344,6 +351,7 @@ impl InlineAsmReg { InlineAsmArch::Avr => Self::Avr(AvrInlineAsmReg::parse(name)?), InlineAsmArch::Msp430 => Self::Msp430(Msp430InlineAsmReg::parse(name)?), InlineAsmArch::M68k => Self::M68k(M68kInlineAsmReg::parse(name)?), + InlineAsmArch::CSKY => Self::CSKY(CSKYInlineAsmReg::parse(name)?), }) } @@ -371,6 +379,7 @@ impl InlineAsmReg { Self::Avr(r) => r.validate(arch, reloc_model, target_features, target, is_clobber), Self::Msp430(r) => r.validate(arch, reloc_model, target_features, target, is_clobber), Self::M68k(r) => r.validate(arch, reloc_model, target_features, target, is_clobber), + Self::CSKY(r) => r.validate(arch, reloc_model, target_features, target, is_clobber), Self::Err => unreachable!(), } } @@ -397,6 +406,7 @@ impl InlineAsmReg { Self::Avr(r) => r.emit(out, arch, modifier), Self::Msp430(r) => r.emit(out, arch, modifier), Self::M68k(r) => r.emit(out, arch, modifier), + Self::CSKY(r) => r.emit(out, arch, modifier), Self::Err => unreachable!("Use of InlineAsmReg::Err"), } } @@ -416,6 +426,7 @@ impl InlineAsmReg { Self::Avr(r) => r.overlapping_regs(|r| cb(Self::Avr(r))), Self::Msp430(_) => cb(self), Self::M68k(_) => cb(self), + Self::CSKY(_) => cb(self), Self::Err => unreachable!("Use of InlineAsmReg::Err"), } } @@ -440,6 +451,7 @@ pub enum InlineAsmRegClass { Avr(AvrInlineAsmRegClass), Msp430(Msp430InlineAsmRegClass), M68k(M68kInlineAsmRegClass), + CSKY(CSKYInlineAsmRegClass), // Placeholder for invalid register constraints for the current target Err, } @@ -463,6 +475,7 @@ impl InlineAsmRegClass { Self::Avr(r) => r.name(), Self::Msp430(r) => r.name(), Self::M68k(r) => r.name(), + Self::CSKY(r) => r.name(), Self::Err => rustc_span::symbol::sym::reg, } } @@ -488,6 +501,7 @@ impl InlineAsmRegClass { Self::Avr(r) => r.suggest_class(arch, ty).map(InlineAsmRegClass::Avr), Self::Msp430(r) => r.suggest_class(arch, ty).map(InlineAsmRegClass::Msp430), Self::M68k(r) => r.suggest_class(arch, ty).map(InlineAsmRegClass::M68k), + Self::CSKY(r) => r.suggest_class(arch, ty).map(InlineAsmRegClass::CSKY), Self::Err => unreachable!("Use of InlineAsmRegClass::Err"), } } @@ -520,6 +534,7 @@ impl InlineAsmRegClass { Self::Avr(r) => r.suggest_modifier(arch, ty), Self::Msp430(r) => r.suggest_modifier(arch, ty), Self::M68k(r) => r.suggest_modifier(arch, ty), + Self::CSKY(r) => r.suggest_modifier(arch, ty), Self::Err => unreachable!("Use of InlineAsmRegClass::Err"), } } @@ -548,6 +563,7 @@ impl InlineAsmRegClass { Self::Avr(r) => r.default_modifier(arch), Self::Msp430(r) => r.default_modifier(arch), Self::M68k(r) => r.default_modifier(arch), + Self::CSKY(r) => r.default_modifier(arch), Self::Err => unreachable!("Use of InlineAsmRegClass::Err"), } } @@ -575,6 +591,7 @@ impl InlineAsmRegClass { Self::Avr(r) => r.supported_types(arch), Self::Msp430(r) => r.supported_types(arch), Self::M68k(r) => r.supported_types(arch), + Self::CSKY(r) => r.supported_types(arch), Self::Err => unreachable!("Use of InlineAsmRegClass::Err"), } } @@ -607,6 +624,7 @@ impl InlineAsmRegClass { InlineAsmArch::Avr => Self::Avr(AvrInlineAsmRegClass::parse(name)?), InlineAsmArch::Msp430 => Self::Msp430(Msp430InlineAsmRegClass::parse(name)?), InlineAsmArch::M68k => Self::M68k(M68kInlineAsmRegClass::parse(name)?), + InlineAsmArch::CSKY => Self::CSKY(CSKYInlineAsmRegClass::parse(name)?), }) } @@ -630,6 +648,7 @@ impl InlineAsmRegClass { Self::Avr(r) => r.valid_modifiers(arch), Self::Msp430(r) => r.valid_modifiers(arch), Self::M68k(r) => r.valid_modifiers(arch), + Self::CSKY(r) => r.valid_modifiers(arch), Self::Err => unreachable!("Use of InlineAsmRegClass::Err"), } } @@ -826,6 +845,11 @@ pub fn allocatable_registers( m68k::fill_reg_map(arch, reloc_model, target_features, target, &mut map); map } + InlineAsmArch::CSKY => { + let mut map = csky::regclass_map(); + csky::fill_reg_map(arch, reloc_model, target_features, target, &mut map); + map + } } } diff --git a/compiler/rustc_target/src/spec/csky_unknown_linux_gnuabiv2.rs b/compiler/rustc_target/src/spec/csky_unknown_linux_gnuabiv2.rs new file mode 100644 index 00000000000..7d03dd26f5d --- /dev/null +++ b/compiler/rustc_target/src/spec/csky_unknown_linux_gnuabiv2.rs @@ -0,0 +1,20 @@ +use crate::spec::{Cc, LinkerFlavor, Lld, Target, TargetOptions}; + +// This target is for glibc Linux on Csky + +pub fn target() -> Target { + Target { + //https://github.com/llvm/llvm-project/blob/8b76aea8d8b1b71f6220bc2845abc749f18a19b7/clang/lib/Basic/Targets/CSKY.h + llvm_target: "csky-unknown-linux-gnuabiv2".into(), + pointer_width: 32, + data_layout: "e-m:e-S32-p:32:32-i32:32:32-i64:32:32-f32:32:32-f64:32:32-v64:32:32-v128:32:32-a:0:32-Fi32-n32".into(), + arch: "csky".into(), + options: TargetOptions { + abi: "abiv2".into(), + features: "+2e3,+3e7,+7e10,+cache,+dsp1e2,+dspe60,+e1,+e2,+edsp,+elrw,+hard-tp,+high-registers,+hwdiv,+mp,+mp1e2,+nvic,+trust".into(), + late_link_args_static: TargetOptions::link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-l:libatomic.a"]), + max_atomic_width: Some(32), + ..super::linux_gnu_base::opts() + }, + } +} diff --git a/compiler/rustc_target/src/spec/loongarch64_unknown_none.rs b/compiler/rustc_target/src/spec/loongarch64_unknown_none.rs index 209d481d6f8..dbc96d68eae 100644 --- a/compiler/rustc_target/src/spec/loongarch64_unknown_none.rs +++ b/compiler/rustc_target/src/spec/loongarch64_unknown_none.rs @@ -10,7 +10,8 @@ pub fn target() -> Target { options: TargetOptions { cpu: "generic".into(), features: "+f,+d".into(), - linker_flavor: LinkerFlavor::Gnu(Cc::No, Lld::No), + linker_flavor: LinkerFlavor::Gnu(Cc::No, Lld::Yes), + linker: Some("rust-lld".into()), llvm_abiname: "lp64d".into(), max_atomic_width: Some(64), relocation_model: RelocModel::Static, diff --git a/compiler/rustc_target/src/spec/loongarch64_unknown_none_softfloat.rs b/compiler/rustc_target/src/spec/loongarch64_unknown_none_softfloat.rs index f444a7f24bb..c4d5c7bc44c 100644 --- a/compiler/rustc_target/src/spec/loongarch64_unknown_none_softfloat.rs +++ b/compiler/rustc_target/src/spec/loongarch64_unknown_none_softfloat.rs @@ -11,7 +11,8 @@ pub fn target() -> Target { cpu: "generic".into(), features: "-f,-d".into(), abi: "softfloat".into(), - linker_flavor: LinkerFlavor::Gnu(Cc::No, Lld::No), + linker_flavor: LinkerFlavor::Gnu(Cc::No, Lld::Yes), + linker: Some("rust-lld".into()), llvm_abiname: "lp64s".into(), max_atomic_width: Some(64), relocation_model: RelocModel::Static, diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs index 1871239d7de..af2b96ccb51 100644 --- a/compiler/rustc_target/src/spec/mod.rs +++ b/compiler/rustc_target/src/spec/mod.rs @@ -338,7 +338,7 @@ impl LinkerFlavor { || stem == "clang++" || stem.ends_with("-clang++") { - (Some(Cc::Yes), None) + (Some(Cc::Yes), Some(Lld::No)) } else if stem == "wasm-ld" || stem.ends_with("-wasm-ld") || stem == "ld.lld" @@ -1246,6 +1246,7 @@ supported_targets! { ("i586-unknown-linux-gnu", i586_unknown_linux_gnu), ("loongarch64-unknown-linux-gnu", loongarch64_unknown_linux_gnu), ("m68k-unknown-linux-gnu", m68k_unknown_linux_gnu), + ("csky-unknown-linux-gnuabiv2", csky_unknown_linux_gnuabiv2), ("mips-unknown-linux-gnu", mips_unknown_linux_gnu), ("mips64-unknown-linux-gnuabi64", mips64_unknown_linux_gnuabi64), ("mips64el-unknown-linux-gnuabi64", mips64el_unknown_linux_gnuabi64), diff --git a/compiler/rustc_trait_selection/src/solve/assembly/mod.rs b/compiler/rustc_trait_selection/src/solve/assembly/mod.rs index 44c50b086bd..36194f973b5 100644 --- a/compiler/rustc_trait_selection/src/solve/assembly/mod.rs +++ b/compiler/rustc_trait_selection/src/solve/assembly/mod.rs @@ -849,6 +849,11 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { ty::Dynamic(bounds, ..) => bounds, }; + // Do not consider built-in object impls for non-object-safe types. + if bounds.principal_def_id().is_some_and(|def_id| !tcx.check_is_object_safe(def_id)) { + return; + } + // Consider all of the auto-trait and projection bounds, which don't // need to be recorded as a `BuiltinImplSource::Object` since they don't // really have a vtable base... diff --git a/compiler/rustc_trait_selection/src/solve/eval_ctxt/select.rs b/compiler/rustc_trait_selection/src/solve/eval_ctxt/select.rs index ca4a4c9510c..42d7a587cac 100644 --- a/compiler/rustc_trait_selection/src/solve/eval_ctxt/select.rs +++ b/compiler/rustc_trait_selection/src/solve/eval_ctxt/select.rs @@ -123,7 +123,7 @@ impl<'tcx> InferCtxtSelectExt<'tcx> for InferCtxt<'tcx> { // It's fine not to do anything to rematch these, since there are no // nested obligations. (Certainty::Yes, CandidateSource::ParamEnv(_) | CandidateSource::AliasBound) => { - Ok(Some(ImplSource::Param(ty::BoundConstness::NotConst, nested_obligations))) + Ok(Some(ImplSource::Param(nested_obligations))) } (Certainty::Maybe(_), _) => Ok(None), diff --git a/compiler/rustc_trait_selection/src/solve/trait_goals.rs b/compiler/rustc_trait_selection/src/solve/trait_goals.rs index 639400f0927..8685f3100a8 100644 --- a/compiler/rustc_trait_selection/src/solve/trait_goals.rs +++ b/compiler/rustc_trait_selection/src/solve/trait_goals.rs @@ -597,16 +597,18 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { self.walk_vtable( a_principal.with_self_ty(tcx, a_ty), |ecx, new_a_principal, _, vtable_vptr_slot| { - if let Ok(resp) = ecx.consider_builtin_upcast_to_principal( - goal, - a_data, - a_region, - b_data, - b_region, - Some(new_a_principal.map_bound(|trait_ref| { - ty::ExistentialTraitRef::erase_self_ty(tcx, trait_ref) - })), - ) { + if let Ok(resp) = ecx.probe_candidate("dyn upcast").enter(|ecx| { + ecx.consider_builtin_upcast_to_principal( + goal, + a_data, + a_region, + b_data, + b_region, + Some(new_a_principal.map_bound(|trait_ref| { + ty::ExistentialTraitRef::erase_self_ty(tcx, trait_ref) + })), + ) + }) { responses .push((resp, BuiltinImplSource::TraitUpcasting { vtable_vptr_slot })); } diff --git a/compiler/rustc_trait_selection/src/traits/coherence.rs b/compiler/rustc_trait_selection/src/traits/coherence.rs index e56af586ed8..5746781ae35 100644 --- a/compiler/rustc_trait_selection/src/traits/coherence.rs +++ b/compiler/rustc_trait_selection/src/traits/coherence.rs @@ -7,7 +7,7 @@ use crate::infer::outlives::env::OutlivesEnvironment; use crate::infer::InferOk; use crate::traits::outlives_bounds::InferCtxtExt as _; -use crate::traits::select::IntercrateAmbiguityCause; +use crate::traits::select::{IntercrateAmbiguityCause, TreatInductiveCycleAs}; use crate::traits::util::impl_subject_and_oblig; use crate::traits::SkipLeakCheck; use crate::traits::{ @@ -24,6 +24,7 @@ use rustc_middle::traits::DefiningAnchor; use rustc_middle::ty::fast_reject::{DeepRejectCtxt, TreatParams}; use rustc_middle::ty::visit::{TypeVisitable, TypeVisitableExt}; use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitor}; +use rustc_session::lint::builtin::COINDUCTIVE_OVERLAP_IN_COHERENCE; use rustc_span::symbol::sym; use rustc_span::DUMMY_SP; use std::fmt::Debug; @@ -151,14 +152,16 @@ fn with_fresh_ty_vars<'cx, 'tcx>( .predicates_of(impl_def_id) .instantiate(tcx, impl_args) .iter() - .map(|(c, _)| c.as_predicate()) + .map(|(c, s)| (c.as_predicate(), s)) .collect(), }; - let InferOk { value: mut header, obligations } = - selcx.infcx.at(&ObligationCause::dummy(), param_env).normalize(header); + let InferOk { value: mut header, obligations } = selcx + .infcx + .at(&ObligationCause::dummy_with_span(tcx.def_span(impl_def_id)), param_env) + .normalize(header); - header.predicates.extend(obligations.into_iter().map(|o| o.predicate)); + header.predicates.extend(obligations.into_iter().map(|o| (o.predicate, o.cause.span))); header } @@ -207,16 +210,76 @@ fn overlap<'tcx>( let equate_obligations = equate_impl_headers(selcx.infcx, &impl1_header, &impl2_header)?; debug!("overlap: unification check succeeded"); - if overlap_mode.use_implicit_negative() - && impl_intersection_has_impossible_obligation( - selcx, - param_env, - &impl1_header, - impl2_header, - equate_obligations, - ) - { - return None; + if overlap_mode.use_implicit_negative() { + for mode in [TreatInductiveCycleAs::Ambig, TreatInductiveCycleAs::Recur] { + if let Some(failing_obligation) = selcx.with_treat_inductive_cycle_as(mode, |selcx| { + impl_intersection_has_impossible_obligation( + selcx, + param_env, + &impl1_header, + &impl2_header, + &equate_obligations, + ) + }) { + if matches!(mode, TreatInductiveCycleAs::Recur) { + let first_local_impl = impl1_header + .impl_def_id + .as_local() + .or(impl2_header.impl_def_id.as_local()) + .expect("expected one of the impls to be local"); + infcx.tcx.struct_span_lint_hir( + COINDUCTIVE_OVERLAP_IN_COHERENCE, + infcx.tcx.local_def_id_to_hir_id(first_local_impl), + infcx.tcx.def_span(first_local_impl), + format!( + "implementations {} will conflict in the future", + match impl1_header.trait_ref { + Some(trait_ref) => { + let trait_ref = infcx.resolve_vars_if_possible(trait_ref); + format!( + "of `{}` for `{}`", + trait_ref.print_only_trait_path(), + trait_ref.self_ty() + ) + } + None => format!( + "for `{}`", + infcx.resolve_vars_if_possible(impl1_header.self_ty) + ), + }, + ), + |lint| { + lint.note( + "impls that are not considered to overlap may be considered to \ + overlap in the future", + ) + .span_label( + infcx.tcx.def_span(impl1_header.impl_def_id), + "the first impl is here", + ) + .span_label( + infcx.tcx.def_span(impl2_header.impl_def_id), + "the second impl is here", + ); + if !failing_obligation.cause.span.is_dummy() { + lint.span_label( + failing_obligation.cause.span, + format!( + "`{}` may be considered to hold in future releases, \ + causing the impls to overlap", + infcx + .resolve_vars_if_possible(failing_obligation.predicate) + ), + ); + } + lint + }, + ); + } + + return None; + } + } } // We toggle the `leak_check` by using `skip_leak_check` when constructing the @@ -284,40 +347,30 @@ fn impl_intersection_has_impossible_obligation<'cx, 'tcx>( selcx: &mut SelectionContext<'cx, 'tcx>, param_env: ty::ParamEnv<'tcx>, impl1_header: &ty::ImplHeader<'tcx>, - impl2_header: ty::ImplHeader<'tcx>, - obligations: PredicateObligations<'tcx>, -) -> bool { + impl2_header: &ty::ImplHeader<'tcx>, + obligations: &PredicateObligations<'tcx>, +) -> Option<PredicateObligation<'tcx>> { let infcx = selcx.infcx; - let obligation_guaranteed_to_fail = move |obligation: &PredicateObligation<'tcx>| { - if infcx.next_trait_solver() { - infcx.evaluate_obligation(obligation).map_or(false, |result| !result.may_apply()) - } else { - // We use `evaluate_root_obligation` to correctly track - // intercrate ambiguity clauses. We do not need this in the - // new solver. - selcx.evaluate_root_obligation(obligation).map_or( - false, // Overflow has occurred, and treat the obligation as possibly holding. - |result| !result.may_apply(), - ) - } - }; - - let opt_failing_obligation = [&impl1_header.predicates, &impl2_header.predicates] + [&impl1_header.predicates, &impl2_header.predicates] .into_iter() .flatten() - .map(|&predicate| { - Obligation::new(infcx.tcx, ObligationCause::dummy(), param_env, predicate) + .map(|&(predicate, span)| { + Obligation::new(infcx.tcx, ObligationCause::dummy_with_span(span), param_env, predicate) + }) + .chain(obligations.into_iter().cloned()) + .find(|obligation: &PredicateObligation<'tcx>| { + if infcx.next_trait_solver() { + infcx.evaluate_obligation(obligation).map_or(false, |result| !result.may_apply()) + } else { + // We use `evaluate_root_obligation` to correctly track intercrate + // ambiguity clauses. We cannot use this in the new solver. + selcx.evaluate_root_obligation(obligation).map_or( + false, // Overflow has occurred, and treat the obligation as possibly holding. + |result| !result.may_apply(), + ) + } }) - .chain(obligations) - .find(obligation_guaranteed_to_fail); - - if let Some(failing_obligation) = opt_failing_obligation { - debug!("overlap: obligation unsatisfiable {:?}", failing_obligation); - true - } else { - false - } } /// Check if both impls can be satisfied by a common type by considering whether diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs index 71a82baeec6..88d03003309 100644 --- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs +++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs @@ -59,8 +59,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { ParamCandidate(param) => { let obligations = self.confirm_param_candidate(obligation, param.map_bound(|t| t.trait_ref)); - // FIXME(effects) - ImplSource::Param(ty::BoundConstness::NotConst, obligations) + ImplSource::Param(obligations) } ImplCandidate(impl_def_id) => { @@ -72,9 +71,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { ImplSource::Builtin(BuiltinImplSource::Misc, data) } - ProjectionCandidate(idx, constness) => { + ProjectionCandidate(idx, _) => { let obligations = self.confirm_projection_candidate(obligation, idx)?; - ImplSource::Param(constness, obligations) + ImplSource::Param(obligations) } ObjectCandidate(idx) => self.confirm_object_candidate(obligation, idx)?, diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index 2bd2b081157..19385e2d7f2 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -118,6 +118,8 @@ pub struct SelectionContext<'cx, 'tcx> { /// policy. In essence, canonicalized queries need their errors propagated /// rather than immediately reported because we do not have accurate spans. query_mode: TraitQueryMode, + + treat_inductive_cycle: TreatInductiveCycleAs, } // A stack that walks back up the stack frame. @@ -198,6 +200,27 @@ enum BuiltinImplConditions<'tcx> { Ambiguous, } +#[derive(Copy, Clone)] +pub enum TreatInductiveCycleAs { + /// This is the previous behavior, where `Recur` represents an inductive + /// cycle that is known not to hold. This is not forwards-compatible with + /// coinduction, and will be deprecated. This is the default behavior + /// of the old trait solver due to back-compat reasons. + Recur, + /// This is the behavior of the new trait solver, where inductive cycles + /// are treated as ambiguous and possibly holding. + Ambig, +} + +impl From<TreatInductiveCycleAs> for EvaluationResult { + fn from(treat: TreatInductiveCycleAs) -> EvaluationResult { + match treat { + TreatInductiveCycleAs::Ambig => EvaluatedToUnknown, + TreatInductiveCycleAs::Recur => EvaluatedToRecur, + } + } +} + impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { pub fn new(infcx: &'cx InferCtxt<'tcx>) -> SelectionContext<'cx, 'tcx> { SelectionContext { @@ -205,9 +228,26 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { freshener: infcx.freshener(), intercrate_ambiguity_causes: None, query_mode: TraitQueryMode::Standard, + treat_inductive_cycle: TreatInductiveCycleAs::Recur, } } + // Sets the `TreatInductiveCycleAs` mode temporarily in the selection context + pub fn with_treat_inductive_cycle_as<T>( + &mut self, + treat_inductive_cycle: TreatInductiveCycleAs, + f: impl FnOnce(&mut Self) -> T, + ) -> T { + // Should be executed in a context where caching is disabled, + // otherwise the cache is poisoned with the temporary result. + assert!(self.is_intercrate()); + let treat_inductive_cycle = + std::mem::replace(&mut self.treat_inductive_cycle, treat_inductive_cycle); + let value = f(self); + self.treat_inductive_cycle = treat_inductive_cycle; + value + } + pub fn with_query_mode( infcx: &'cx InferCtxt<'tcx>, query_mode: TraitQueryMode, @@ -719,7 +759,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { stack.update_reached_depth(stack_arg.1); return Ok(EvaluatedToOk); } else { - return Ok(EvaluatedToRecur); + return Ok(self.treat_inductive_cycle.into()); } } return Ok(EvaluatedToOk); @@ -837,7 +877,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { } } ProjectAndUnifyResult::FailedNormalization => Ok(EvaluatedToAmbig), - ProjectAndUnifyResult::Recursive => Ok(EvaluatedToRecur), + ProjectAndUnifyResult::Recursive => Ok(self.treat_inductive_cycle.into()), ProjectAndUnifyResult::MismatchedProjectionTypes(_) => Ok(EvaluatedToErr), } } @@ -1151,7 +1191,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { Some(EvaluatedToOk) } else { debug!("evaluate_stack --> recursive, inductive"); - Some(EvaluatedToRecur) + Some(self.treat_inductive_cycle.into()) } } else { None diff --git a/config.example.toml b/config.example.toml index fc5de5f9537..5c4bee87553 100644 --- a/config.example.toml +++ b/config.example.toml @@ -94,7 +94,7 @@ changelog-seen = 2 # the same format as above, but since these targets are experimental, they are # not built by default and the experimental Rust compilation targets that depend # on them will not work unless the user opts in to building them. -#experimental-targets = "AVR;M68k" +#experimental-targets = "AVR;M68k;CSKY" # Cap the number of parallel linker invocations when compiling LLVM. # This can be useful when building LLVM with debug info, which significantly diff --git a/library/alloc/src/lib.rs b/library/alloc/src/lib.rs index 80681a7a7cf..cb8691aac13 100644 --- a/library/alloc/src/lib.rs +++ b/library/alloc/src/lib.rs @@ -138,7 +138,6 @@ #![feature(maybe_uninit_uninit_array_transpose)] #![feature(pattern)] #![feature(pointer_byte_offsets)] -#![feature(provide_any)] #![feature(ptr_internals)] #![feature(ptr_metadata)] #![feature(ptr_sub_ptr)] diff --git a/library/alloc/src/sync.rs b/library/alloc/src/sync.rs index 6c701225a84..e2a2fe932ab 100644 --- a/library/alloc/src/sync.rs +++ b/library/alloc/src/sync.rs @@ -3575,7 +3575,7 @@ impl<T: core::error::Error + ?Sized> core::error::Error for Arc<T> { core::error::Error::source(&**self) } - fn provide<'a>(&'a self, req: &mut core::any::Demand<'a>) { + fn provide<'a>(&'a self, req: &mut core::error::Request<'a>) { core::error::Error::provide(&**self, req); } } diff --git a/library/core/src/any.rs b/library/core/src/any.rs index 277c2f76a08..8f5404d9713 100644 --- a/library/core/src/any.rs +++ b/library/core/src/any.rs @@ -83,72 +83,6 @@ //! } //! ``` //! -//! # `Provider` and `Demand` -//! -//! `Provider` and the associated APIs support generic, type-driven access to data, and a mechanism -//! for implementers to provide such data. The key parts of the interface are the `Provider` -//! trait for objects which can provide data, and the [`request_value`] and [`request_ref`] -//! functions for requesting data from an object which implements `Provider`. Generally, end users -//! should not call `request_*` directly, they are helper functions for intermediate implementers -//! to use to implement a user-facing interface. This is purely for the sake of ergonomics, there is -//! no safety concern here; intermediate implementers can typically support methods rather than -//! free functions and use more specific names. -//! -//! Typically, a data provider is a trait object of a trait which extends `Provider`. A user will -//! request data from a trait object by specifying the type of the data. -//! -//! ## Data flow -//! -//! * A user requests an object of a specific type, which is delegated to `request_value` or -//! `request_ref` -//! * `request_*` creates a `Demand` object and passes it to `Provider::provide` -//! * The data provider's implementation of `Provider::provide` tries providing values of -//! different types using `Demand::provide_*`. If the type matches the type requested by -//! the user, the value will be stored in the `Demand` object. -//! * `request_*` unpacks the `Demand` object and returns any stored value to the user. -//! -//! ## Examples -//! -//! ``` -//! # #![feature(provide_any)] -//! use std::any::{Provider, Demand, request_ref}; -//! -//! // Definition of MyTrait, a data provider. -//! trait MyTrait: Provider { -//! // ... -//! } -//! -//! // Methods on `MyTrait` trait objects. -//! impl dyn MyTrait + '_ { -//! /// Get a reference to a field of the implementing struct. -//! pub fn get_context_by_ref<T: ?Sized + 'static>(&self) -> Option<&T> { -//! request_ref::<T>(self) -//! } -//! } -//! -//! // Downstream implementation of `MyTrait` and `Provider`. -//! # struct SomeConcreteType { some_string: String } -//! impl MyTrait for SomeConcreteType { -//! // ... -//! } -//! -//! impl Provider for SomeConcreteType { -//! fn provide<'a>(&'a self, demand: &mut Demand<'a>) { -//! // Provide a string reference. We could provide multiple values with -//! // different types here. -//! demand.provide_ref::<String>(&self.some_string); -//! } -//! } -//! -//! // Downstream usage of `MyTrait`. -//! fn use_my_trait(obj: &dyn MyTrait) { -//! // Request a &String from obj. -//! let _ = obj.get_context_by_ref::<String>().unwrap(); -//! } -//! ``` -//! -//! In this example, if the concrete type of `obj` in `use_my_trait` is `SomeConcreteType`, then -//! the `get_context_by_ref` call will return a reference to `obj.some_string` with type `&String`. #![stable(feature = "rust1", since = "1.0.0")] @@ -798,524 +732,3 @@ pub const fn type_name<T: ?Sized>() -> &'static str { pub const fn type_name_of_val<T: ?Sized>(_val: &T) -> &'static str { type_name::<T>() } - -/////////////////////////////////////////////////////////////////////////////// -// Provider trait -/////////////////////////////////////////////////////////////////////////////// - -/// Trait implemented by a type which can dynamically provide values based on type. -#[unstable(feature = "provide_any", issue = "96024")] -pub trait Provider { - /// Data providers should implement this method to provide *all* values they are able to - /// provide by using `demand`. - /// - /// Note that the `provide_*` methods on `Demand` have short-circuit semantics: if an earlier - /// method has successfully provided a value, then later methods will not get an opportunity to - /// provide. - /// - /// # Examples - /// - /// Provides a reference to a field with type `String` as a `&str`, and a value of - /// type `i32`. - /// - /// ```rust - /// # #![feature(provide_any)] - /// use std::any::{Provider, Demand}; - /// # struct SomeConcreteType { field: String, num_field: i32 } - /// - /// impl Provider for SomeConcreteType { - /// fn provide<'a>(&'a self, demand: &mut Demand<'a>) { - /// demand.provide_ref::<str>(&self.field) - /// .provide_value::<i32>(self.num_field); - /// } - /// } - /// ``` - #[unstable(feature = "provide_any", issue = "96024")] - fn provide<'a>(&'a self, demand: &mut Demand<'a>); -} - -/// Request a value from the `Provider`. -/// -/// # Examples -/// -/// Get a string value from a provider. -/// -/// ```rust -/// # #![feature(provide_any)] -/// use std::any::{Provider, request_value}; -/// -/// fn get_string(provider: &impl Provider) -> String { -/// request_value::<String>(provider).unwrap() -/// } -/// ``` -#[unstable(feature = "provide_any", issue = "96024")] -pub fn request_value<'a, T>(provider: &'a (impl Provider + ?Sized)) -> Option<T> -where - T: 'static, -{ - request_by_type_tag::<'a, tags::Value<T>>(provider) -} - -/// Request a reference from the `Provider`. -/// -/// # Examples -/// -/// Get a string reference from a provider. -/// -/// ```rust -/// # #![feature(provide_any)] -/// use std::any::{Provider, request_ref}; -/// -/// fn get_str(provider: &impl Provider) -> &str { -/// request_ref::<str>(provider).unwrap() -/// } -/// ``` -#[unstable(feature = "provide_any", issue = "96024")] -pub fn request_ref<'a, T>(provider: &'a (impl Provider + ?Sized)) -> Option<&'a T> -where - T: 'static + ?Sized, -{ - request_by_type_tag::<'a, tags::Ref<tags::MaybeSizedValue<T>>>(provider) -} - -/// Request a specific value by tag from the `Provider`. -fn request_by_type_tag<'a, I>(provider: &'a (impl Provider + ?Sized)) -> Option<I::Reified> -where - I: tags::Type<'a>, -{ - let mut tagged = TaggedOption::<'a, I>(None); - provider.provide(tagged.as_demand()); - tagged.0 -} - -/////////////////////////////////////////////////////////////////////////////// -// Demand and its methods -/////////////////////////////////////////////////////////////////////////////// - -/// A helper object for providing data by type. -/// -/// A data provider provides values by calling this type's provide methods. -#[unstable(feature = "provide_any", issue = "96024")] -#[cfg_attr(not(doc), repr(transparent))] // work around https://github.com/rust-lang/rust/issues/90435 -pub struct Demand<'a>(dyn Erased<'a> + 'a); - -impl<'a> Demand<'a> { - /// Create a new `&mut Demand` from a `&mut dyn Erased` trait object. - fn new<'b>(erased: &'b mut (dyn Erased<'a> + 'a)) -> &'b mut Demand<'a> { - // SAFETY: transmuting `&mut (dyn Erased<'a> + 'a)` to `&mut Demand<'a>` is safe since - // `Demand` is repr(transparent). - unsafe { &mut *(erased as *mut dyn Erased<'a> as *mut Demand<'a>) } - } - - /// Provide a value or other type with only static lifetimes. - /// - /// # Examples - /// - /// Provides an `u8`. - /// - /// ```rust - /// #![feature(provide_any)] - /// - /// use std::any::{Provider, Demand}; - /// # struct SomeConcreteType { field: u8 } - /// - /// impl Provider for SomeConcreteType { - /// fn provide<'a>(&'a self, demand: &mut Demand<'a>) { - /// demand.provide_value::<u8>(self.field); - /// } - /// } - /// ``` - #[unstable(feature = "provide_any", issue = "96024")] - pub fn provide_value<T>(&mut self, value: T) -> &mut Self - where - T: 'static, - { - self.provide::<tags::Value<T>>(value) - } - - /// Provide a value or other type with only static lifetimes computed using a closure. - /// - /// # Examples - /// - /// Provides a `String` by cloning. - /// - /// ```rust - /// #![feature(provide_any)] - /// - /// use std::any::{Provider, Demand}; - /// # struct SomeConcreteType { field: String } - /// - /// impl Provider for SomeConcreteType { - /// fn provide<'a>(&'a self, demand: &mut Demand<'a>) { - /// demand.provide_value_with::<String>(|| self.field.clone()); - /// } - /// } - /// ``` - #[unstable(feature = "provide_any", issue = "96024")] - pub fn provide_value_with<T>(&mut self, fulfil: impl FnOnce() -> T) -> &mut Self - where - T: 'static, - { - self.provide_with::<tags::Value<T>>(fulfil) - } - - /// Provide a reference. The referee type must be bounded by `'static`, - /// but may be unsized. - /// - /// # Examples - /// - /// Provides a reference to a field as a `&str`. - /// - /// ```rust - /// #![feature(provide_any)] - /// - /// use std::any::{Provider, Demand}; - /// # struct SomeConcreteType { field: String } - /// - /// impl Provider for SomeConcreteType { - /// fn provide<'a>(&'a self, demand: &mut Demand<'a>) { - /// demand.provide_ref::<str>(&self.field); - /// } - /// } - /// ``` - #[unstable(feature = "provide_any", issue = "96024")] - pub fn provide_ref<T: ?Sized + 'static>(&mut self, value: &'a T) -> &mut Self { - self.provide::<tags::Ref<tags::MaybeSizedValue<T>>>(value) - } - - /// Provide a reference computed using a closure. The referee type - /// must be bounded by `'static`, but may be unsized. - /// - /// # Examples - /// - /// Provides a reference to a field as a `&str`. - /// - /// ```rust - /// #![feature(provide_any)] - /// - /// use std::any::{Provider, Demand}; - /// # struct SomeConcreteType { business: String, party: String } - /// # fn today_is_a_weekday() -> bool { true } - /// - /// impl Provider for SomeConcreteType { - /// fn provide<'a>(&'a self, demand: &mut Demand<'a>) { - /// demand.provide_ref_with::<str>(|| { - /// if today_is_a_weekday() { - /// &self.business - /// } else { - /// &self.party - /// } - /// }); - /// } - /// } - /// ``` - #[unstable(feature = "provide_any", issue = "96024")] - pub fn provide_ref_with<T: ?Sized + 'static>( - &mut self, - fulfil: impl FnOnce() -> &'a T, - ) -> &mut Self { - self.provide_with::<tags::Ref<tags::MaybeSizedValue<T>>>(fulfil) - } - - /// Provide a value with the given `Type` tag. - fn provide<I>(&mut self, value: I::Reified) -> &mut Self - where - I: tags::Type<'a>, - { - if let Some(res @ TaggedOption(None)) = self.0.downcast_mut::<I>() { - res.0 = Some(value); - } - self - } - - /// Provide a value with the given `Type` tag, using a closure to prevent unnecessary work. - fn provide_with<I>(&mut self, fulfil: impl FnOnce() -> I::Reified) -> &mut Self - where - I: tags::Type<'a>, - { - if let Some(res @ TaggedOption(None)) = self.0.downcast_mut::<I>() { - res.0 = Some(fulfil()); - } - self - } - - /// Check if the `Demand` would be satisfied if provided with a - /// value of the specified type. If the type does not match or has - /// already been provided, returns false. - /// - /// # Examples - /// - /// Check if an `u8` still needs to be provided and then provides - /// it. - /// - /// ```rust - /// #![feature(provide_any)] - /// - /// use std::any::{Provider, Demand}; - /// - /// struct Parent(Option<u8>); - /// - /// impl Provider for Parent { - /// fn provide<'a>(&'a self, demand: &mut Demand<'a>) { - /// if let Some(v) = self.0 { - /// demand.provide_value::<u8>(v); - /// } - /// } - /// } - /// - /// struct Child { - /// parent: Parent, - /// } - /// - /// impl Child { - /// // Pretend that this takes a lot of resources to evaluate. - /// fn an_expensive_computation(&self) -> Option<u8> { - /// Some(99) - /// } - /// } - /// - /// impl Provider for Child { - /// fn provide<'a>(&'a self, demand: &mut Demand<'a>) { - /// // In general, we don't know if this call will provide - /// // an `u8` value or not... - /// self.parent.provide(demand); - /// - /// // ...so we check to see if the `u8` is needed before - /// // we run our expensive computation. - /// if demand.would_be_satisfied_by_value_of::<u8>() { - /// if let Some(v) = self.an_expensive_computation() { - /// demand.provide_value::<u8>(v); - /// } - /// } - /// - /// // The demand will be satisfied now, regardless of if - /// // the parent provided the value or we did. - /// assert!(!demand.would_be_satisfied_by_value_of::<u8>()); - /// } - /// } - /// - /// let parent = Parent(Some(42)); - /// let child = Child { parent }; - /// assert_eq!(Some(42), std::any::request_value::<u8>(&child)); - /// - /// let parent = Parent(None); - /// let child = Child { parent }; - /// assert_eq!(Some(99), std::any::request_value::<u8>(&child)); - /// ``` - #[unstable(feature = "provide_any", issue = "96024")] - pub fn would_be_satisfied_by_value_of<T>(&self) -> bool - where - T: 'static, - { - self.would_be_satisfied_by::<tags::Value<T>>() - } - - /// Check if the `Demand` would be satisfied if provided with a - /// reference to a value of the specified type. If the type does - /// not match or has already been provided, returns false. - /// - /// # Examples - /// - /// Check if a `&str` still needs to be provided and then provides - /// it. - /// - /// ```rust - /// #![feature(provide_any)] - /// - /// use std::any::{Provider, Demand}; - /// - /// struct Parent(Option<String>); - /// - /// impl Provider for Parent { - /// fn provide<'a>(&'a self, demand: &mut Demand<'a>) { - /// if let Some(v) = &self.0 { - /// demand.provide_ref::<str>(v); - /// } - /// } - /// } - /// - /// struct Child { - /// parent: Parent, - /// name: String, - /// } - /// - /// impl Child { - /// // Pretend that this takes a lot of resources to evaluate. - /// fn an_expensive_computation(&self) -> Option<&str> { - /// Some(&self.name) - /// } - /// } - /// - /// impl Provider for Child { - /// fn provide<'a>(&'a self, demand: &mut Demand<'a>) { - /// // In general, we don't know if this call will provide - /// // a `str` reference or not... - /// self.parent.provide(demand); - /// - /// // ...so we check to see if the `&str` is needed before - /// // we run our expensive computation. - /// if demand.would_be_satisfied_by_ref_of::<str>() { - /// if let Some(v) = self.an_expensive_computation() { - /// demand.provide_ref::<str>(v); - /// } - /// } - /// - /// // The demand will be satisfied now, regardless of if - /// // the parent provided the reference or we did. - /// assert!(!demand.would_be_satisfied_by_ref_of::<str>()); - /// } - /// } - /// - /// let parent = Parent(Some("parent".into())); - /// let child = Child { parent, name: "child".into() }; - /// assert_eq!(Some("parent"), std::any::request_ref::<str>(&child)); - /// - /// let parent = Parent(None); - /// let child = Child { parent, name: "child".into() }; - /// assert_eq!(Some("child"), std::any::request_ref::<str>(&child)); - /// ``` - #[unstable(feature = "provide_any", issue = "96024")] - pub fn would_be_satisfied_by_ref_of<T>(&self) -> bool - where - T: ?Sized + 'static, - { - self.would_be_satisfied_by::<tags::Ref<tags::MaybeSizedValue<T>>>() - } - - fn would_be_satisfied_by<I>(&self) -> bool - where - I: tags::Type<'a>, - { - matches!(self.0.downcast::<I>(), Some(TaggedOption(None))) - } -} - -#[unstable(feature = "provide_any", issue = "96024")] -impl<'a> fmt::Debug for Demand<'a> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_struct("Demand").finish_non_exhaustive() - } -} - -/////////////////////////////////////////////////////////////////////////////// -// Type tags -/////////////////////////////////////////////////////////////////////////////// - -mod tags { - //! Type tags are used to identify a type using a separate value. This module includes type tags - //! for some very common types. - //! - //! Currently type tags are not exposed to the user. But in the future, if you want to use the - //! Provider API with more complex types (typically those including lifetime parameters), you - //! will need to write your own tags. - - use crate::marker::PhantomData; - - /// This trait is implemented by specific tag types in order to allow - /// describing a type which can be requested for a given lifetime `'a`. - /// - /// A few example implementations for type-driven tags can be found in this - /// module, although crates may also implement their own tags for more - /// complex types with internal lifetimes. - pub trait Type<'a>: Sized + 'static { - /// The type of values which may be tagged by this tag for the given - /// lifetime. - type Reified: 'a; - } - - /// Similar to the [`Type`] trait, but represents a type which may be unsized (i.e., has a - /// `?Sized` bound). E.g., `str`. - pub trait MaybeSizedType<'a>: Sized + 'static { - type Reified: 'a + ?Sized; - } - - impl<'a, T: Type<'a>> MaybeSizedType<'a> for T { - type Reified = T::Reified; - } - - /// Type-based tag for types bounded by `'static`, i.e., with no borrowed elements. - #[derive(Debug)] - pub struct Value<T: 'static>(PhantomData<T>); - - impl<'a, T: 'static> Type<'a> for Value<T> { - type Reified = T; - } - - /// Type-based tag similar to [`Value`] but which may be unsized (i.e., has a `?Sized` bound). - #[derive(Debug)] - pub struct MaybeSizedValue<T: ?Sized + 'static>(PhantomData<T>); - - impl<'a, T: ?Sized + 'static> MaybeSizedType<'a> for MaybeSizedValue<T> { - type Reified = T; - } - - /// Type-based tag for reference types (`&'a T`, where T is represented by - /// `<I as MaybeSizedType<'a>>::Reified`. - #[derive(Debug)] - pub struct Ref<I>(PhantomData<I>); - - impl<'a, I: MaybeSizedType<'a>> Type<'a> for Ref<I> { - type Reified = &'a I::Reified; - } -} - -/// An `Option` with a type tag `I`. -/// -/// Since this struct implements `Erased`, the type can be erased to make a dynamically typed -/// option. The type can be checked dynamically using `Erased::tag_id` and since this is statically -/// checked for the concrete type, there is some degree of type safety. -#[repr(transparent)] -struct TaggedOption<'a, I: tags::Type<'a>>(Option<I::Reified>); - -impl<'a, I: tags::Type<'a>> TaggedOption<'a, I> { - fn as_demand(&mut self) -> &mut Demand<'a> { - Demand::new(self as &mut (dyn Erased<'a> + 'a)) - } -} - -/// Represents a type-erased but identifiable object. -/// -/// This trait is exclusively implemented by the `TaggedOption` type. -unsafe trait Erased<'a>: 'a { - /// The `TypeId` of the erased type. - fn tag_id(&self) -> TypeId; -} - -unsafe impl<'a, I: tags::Type<'a>> Erased<'a> for TaggedOption<'a, I> { - fn tag_id(&self) -> TypeId { - TypeId::of::<I>() - } -} - -#[unstable(feature = "provide_any", issue = "96024")] -impl<'a> dyn Erased<'a> + 'a { - /// Returns some reference to the dynamic value if it is tagged with `I`, - /// or `None` otherwise. - #[inline] - fn downcast<I>(&self) -> Option<&TaggedOption<'a, I>> - where - I: tags::Type<'a>, - { - if self.tag_id() == TypeId::of::<I>() { - // SAFETY: Just checked whether we're pointing to an I. - Some(unsafe { &*(self as *const Self).cast::<TaggedOption<'a, I>>() }) - } else { - None - } - } - - /// Returns some mutable reference to the dynamic value if it is tagged with `I`, - /// or `None` otherwise. - #[inline] - fn downcast_mut<I>(&mut self) -> Option<&mut TaggedOption<'a, I>> - where - I: tags::Type<'a>, - { - if self.tag_id() == TypeId::of::<I>() { - // SAFETY: Just checked whether we're pointing to an I. - Some(unsafe { &mut *(self as *mut Self).cast::<TaggedOption<'a, I>>() }) - } else { - None - } - } -} diff --git a/library/core/src/error.rs b/library/core/src/error.rs index 11cb0827578..c32a54b77ef 100644 --- a/library/core/src/error.rs +++ b/library/core/src/error.rs @@ -4,8 +4,8 @@ #[cfg(test)] mod tests; -use crate::any::{Demand, Provider, TypeId}; -use crate::fmt::{Debug, Display}; +use crate::any::TypeId; +use crate::fmt::{Debug, Display, Formatter, Result}; /// `Error` is a trait representing the basic expectations for error values, /// i.e., values of type `E` in [`Result<T, E>`]. @@ -123,16 +123,20 @@ pub trait Error: Debug + Display { /// Provides type based access to context intended for error reports. /// - /// Used in conjunction with [`Demand::provide_value`] and [`Demand::provide_ref`] to extract + /// Used in conjunction with [`Request::provide_value`] and [`Request::provide_ref`] to extract /// references to member variables from `dyn Error` trait objects. /// /// # Example /// /// ```rust - /// #![feature(provide_any)] /// #![feature(error_generic_member_access)] /// use core::fmt; - /// use core::any::Demand; + /// use core::error::{request_ref, Request}; + /// + /// #[derive(Debug)] + /// enum MyLittleTeaPot { + /// Empty, + /// } /// /// #[derive(Debug)] /// struct MyBacktrace { @@ -147,21 +151,7 @@ pub trait Error: Debug + Display { /// } /// /// #[derive(Debug)] - /// struct SourceError { - /// // ... - /// } - /// - /// impl fmt::Display for SourceError { - /// fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - /// write!(f, "Example Source Error") - /// } - /// } - /// - /// impl std::error::Error for SourceError {} - /// - /// #[derive(Debug)] /// struct Error { - /// source: SourceError, /// backtrace: MyBacktrace, /// } /// @@ -172,38 +162,26 @@ pub trait Error: Debug + Display { /// } /// /// impl std::error::Error for Error { - /// fn provide<'a>(&'a self, demand: &mut Demand<'a>) { - /// demand - /// .provide_ref::<MyBacktrace>(&self.backtrace) - /// .provide_ref::<dyn std::error::Error + 'static>(&self.source); + /// fn provide<'a>(&'a self, request: &mut Request<'a>) { + /// request + /// .provide_ref::<MyBacktrace>(&self.backtrace); /// } /// } /// /// fn main() { /// let backtrace = MyBacktrace::new(); - /// let source = SourceError {}; - /// let error = Error { source, backtrace }; + /// let error = Error { backtrace }; /// let dyn_error = &error as &dyn std::error::Error; - /// let backtrace_ref = dyn_error.request_ref::<MyBacktrace>().unwrap(); + /// let backtrace_ref = request_ref::<MyBacktrace>(dyn_error).unwrap(); /// /// assert!(core::ptr::eq(&error.backtrace, backtrace_ref)); + /// assert!(request_ref::<MyLittleTeaPot>(dyn_error).is_none()); /// } /// ``` #[unstable(feature = "error_generic_member_access", issue = "99301")] #[allow(unused_variables)] - fn provide<'a>(&'a self, demand: &mut Demand<'a>) {} -} - -#[unstable(feature = "error_generic_member_access", issue = "99301")] -impl<E> Provider for E -where - E: Error + ?Sized, -{ - fn provide<'a>(&'a self, demand: &mut Demand<'a>) { - self.provide(demand) - } + fn provide<'a>(&'a self, request: &mut Request<'a>) {} } - mod private { // This is a hack to prevent `type_id` from being overridden by `Error` // implementations, since that can enable unsound downcasting. @@ -215,20 +193,6 @@ mod private { #[unstable(feature = "never_type", issue = "35121")] impl Error for ! {} -impl<'a> dyn Error + 'a { - /// Request a reference of type `T` as context about this error. - #[unstable(feature = "error_generic_member_access", issue = "99301")] - pub fn request_ref<T: ?Sized + 'static>(&'a self) -> Option<&'a T> { - core::any::request_ref(self) - } - - /// Request a value of type `T` as context about this error. - #[unstable(feature = "error_generic_member_access", issue = "99301")] - pub fn request_value<T: 'static>(&'a self) -> Option<T> { - core::any::request_value(self) - } -} - // Copied from `any.rs`. impl dyn Error + 'static { /// Returns `true` if the inner type is the same as `T`. @@ -293,18 +257,6 @@ impl dyn Error + 'static + Send { pub fn downcast_mut<T: Error + 'static>(&mut self) -> Option<&mut T> { <dyn Error + 'static>::downcast_mut::<T>(self) } - - /// Request a reference of type `T` as context about this error. - #[unstable(feature = "error_generic_member_access", issue = "99301")] - pub fn request_ref<T: ?Sized + 'static>(&self) -> Option<&T> { - <dyn Error>::request_ref(self) - } - - /// Request a value of type `T` as context about this error. - #[unstable(feature = "error_generic_member_access", issue = "99301")] - pub fn request_value<T: 'static>(&self) -> Option<T> { - <dyn Error>::request_value(self) - } } impl dyn Error + 'static + Send + Sync { @@ -328,18 +280,6 @@ impl dyn Error + 'static + Send + Sync { pub fn downcast_mut<T: Error + 'static>(&mut self) -> Option<&mut T> { <dyn Error + 'static>::downcast_mut::<T>(self) } - - /// Request a reference of type `T` as context about this error. - #[unstable(feature = "error_generic_member_access", issue = "99301")] - pub fn request_ref<T: ?Sized + 'static>(&self) -> Option<&T> { - <dyn Error>::request_ref(self) - } - - /// Request a value of type `T` as context about this error. - #[unstable(feature = "error_generic_member_access", issue = "99301")] - pub fn request_value<T: 'static>(&self) -> Option<T> { - <dyn Error>::request_value(self) - } } impl dyn Error { @@ -412,6 +352,645 @@ impl dyn Error { } } +/// Request a value of type `T` from the given `impl Error`. +/// +/// # Examples +/// +/// Get a string value from an error. +/// +/// ```rust +/// # #![feature(error_generic_member_access)] +/// use std::error::Error; +/// use core::error::request_value; +/// +/// fn get_string(err: &impl Error) -> String { +/// request_value::<String>(err).unwrap() +/// } +/// ``` +#[unstable(feature = "error_generic_member_access", issue = "99301")] +pub fn request_value<'a, T>(err: &'a (impl Error + ?Sized)) -> Option<T> +where + T: 'static, +{ + request_by_type_tag::<'a, tags::Value<T>>(err) +} + +/// Request a reference of type `T` from the given `impl Error`. +/// +/// # Examples +/// +/// Get a string reference from an error. +/// +/// ```rust +/// # #![feature(error_generic_member_access)] +/// use core::error::Error; +/// use core::error::request_ref; +/// +/// fn get_str(err: &impl Error) -> &str { +/// request_ref::<str>(err).unwrap() +/// } +/// ``` +#[unstable(feature = "error_generic_member_access", issue = "99301")] +pub fn request_ref<'a, T>(err: &'a (impl Error + ?Sized)) -> Option<&'a T> +where + T: 'static + ?Sized, +{ + request_by_type_tag::<'a, tags::Ref<tags::MaybeSizedValue<T>>>(err) +} + +/// Request a specific value by tag from the `Error`. +fn request_by_type_tag<'a, I>(err: &'a (impl Error + ?Sized)) -> Option<I::Reified> +where + I: tags::Type<'a>, +{ + let mut tagged = TaggedOption::<'a, I>(None); + err.provide(tagged.as_request()); + tagged.0 +} + +/////////////////////////////////////////////////////////////////////////////// +// Request and its methods +/////////////////////////////////////////////////////////////////////////////// + +/// `Request` supports generic, type-driven access to data. It's use is currently restricted to the +/// standard library in cases where trait authors wish to allow trait implementors to share generic +/// information across trait boundaries. The motivating and prototypical use case is +/// `core::error::Error` which would otherwise require a method per concrete type (eg. +/// `std::backtrace::Backtrace` instance that implementors want to expose to users). +/// +/// # Data flow +/// +/// To describe the intended data flow for Request objects, let's consider two conceptual users +/// separated by API boundaries: +/// +/// * Consumer - the consumer requests objects using a Request instance; eg a crate that offers +/// fancy `Error`/`Result` reporting to users wants to request a Backtrace from a given `dyn Error`. +/// +/// * Producer - the producer provides objects when requested via Request; eg. a library with an +/// an `Error` implementation that automatically captures backtraces at the time instances are +/// created. +/// +/// The consumer only needs to know where to submit their request and are expected to handle the +/// request not being fulfilled by the use of `Option<T>` in the responses offered by the producer. +/// +/// * A Producer initializes the value of one of its fields of a specific type. (or is otherwise +/// prepared to generate a value requested). eg, `backtrace::Backtrace` or +/// `std::backtrace::Backtrace` +/// * A Consumer requests an object of a specific type (say `std::backtrace::Backtrace). In the case +/// of a `dyn Error` trait object (the Producer), there are methods called `request_ref` and +/// `request_value` are available to simplify obtaining an ``Option<T>`` for a given type. * The +/// Producer, when requested, populates the given Request object which is given as a mutable +/// reference. +/// * The Consumer extracts a value or reference to the requested type from the `Request` object +/// wrapped in an `Option<T>`; in the case of `dyn Error` the aforementioned `request_ref` and ` +/// request_value` methods mean that `dyn Error` users don't have to deal with the `Request` type at +/// all (but `Error` implementors do). The `None` case of the `Option` suggests only that the +/// Producer cannot currently offer an instance of the requested type, not it can't or never will. +/// +/// # Examples +/// +/// The best way to demonstrate this is using an example implementation of `Error`'s `provide` trait +/// method: +/// +/// ``` +/// #![feature(error_generic_member_access)] +/// use core::fmt; +/// use core::error::Request; +/// use core::error::request_ref; +/// +/// #[derive(Debug)] +/// enum MyLittleTeaPot { +/// Empty, +/// } +/// +/// #[derive(Debug)] +/// struct MyBacktrace { +/// // ... +/// } +/// +/// impl MyBacktrace { +/// fn new() -> MyBacktrace { +/// // ... +/// # MyBacktrace {} +/// } +/// } +/// +/// #[derive(Debug)] +/// struct Error { +/// backtrace: MyBacktrace, +/// } +/// +/// impl fmt::Display for Error { +/// fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { +/// write!(f, "Example Error") +/// } +/// } +/// +/// impl std::error::Error for Error { +/// fn provide<'a>(&'a self, request: &mut Request<'a>) { +/// request +/// .provide_ref::<MyBacktrace>(&self.backtrace); +/// } +/// } +/// +/// fn main() { +/// let backtrace = MyBacktrace::new(); +/// let error = Error { backtrace }; +/// let dyn_error = &error as &dyn std::error::Error; +/// let backtrace_ref = request_ref::<MyBacktrace>(dyn_error).unwrap(); +/// +/// assert!(core::ptr::eq(&error.backtrace, backtrace_ref)); +/// assert!(request_ref::<MyLittleTeaPot>(dyn_error).is_none()); +/// } +/// ``` +/// +#[unstable(feature = "error_generic_member_access", issue = "99301")] +#[cfg_attr(not(doc), repr(transparent))] // work around https://github.com/rust-lang/rust/issues/90435 +pub struct Request<'a>(dyn Erased<'a> + 'a); + +impl<'a> Request<'a> { + /// Create a new `&mut Request` from a `&mut dyn Erased` trait object. + fn new<'b>(erased: &'b mut (dyn Erased<'a> + 'a)) -> &'b mut Request<'a> { + // SAFETY: transmuting `&mut (dyn Erased<'a> + 'a)` to `&mut Request<'a>` is safe since + // `Request` is repr(transparent). + unsafe { &mut *(erased as *mut dyn Erased<'a> as *mut Request<'a>) } + } + + /// Provide a value or other type with only static lifetimes. + /// + /// # Examples + /// + /// Provides an `u8`. + /// + /// ```rust + /// #![feature(error_generic_member_access)] + /// + /// use core::error::Request; + /// + /// #[derive(Debug)] + /// struct SomeConcreteType { field: u8 } + /// + /// impl std::fmt::Display for SomeConcreteType { + /// fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + /// write!(f, "{} failed", self.field) + /// } + /// } + /// + /// impl std::error::Error for SomeConcreteType { + /// fn provide<'a>(&'a self, request: &mut Request<'a>) { + /// request.provide_value::<u8>(self.field); + /// } + /// } + /// ``` + #[unstable(feature = "error_generic_member_access", issue = "99301")] + pub fn provide_value<T>(&mut self, value: T) -> &mut Self + where + T: 'static, + { + self.provide::<tags::Value<T>>(value) + } + + /// Provide a value or other type with only static lifetimes computed using a closure. + /// + /// # Examples + /// + /// Provides a `String` by cloning. + /// + /// ```rust + /// #![feature(error_generic_member_access)] + /// + /// use core::error::Request; + /// + /// #[derive(Debug)] + /// struct SomeConcreteType { field: String } + /// + /// impl std::fmt::Display for SomeConcreteType { + /// fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + /// write!(f, "{} failed", self.field) + /// } + /// } + /// + /// impl std::error::Error for SomeConcreteType { + /// fn provide<'a>(&'a self, request: &mut Request<'a>) { + /// request.provide_value_with::<String>(|| self.field.clone()); + /// } + /// } + /// ``` + #[unstable(feature = "error_generic_member_access", issue = "99301")] + pub fn provide_value_with<T>(&mut self, fulfil: impl FnOnce() -> T) -> &mut Self + where + T: 'static, + { + self.provide_with::<tags::Value<T>>(fulfil) + } + + /// Provide a reference. The referee type must be bounded by `'static`, + /// but may be unsized. + /// + /// # Examples + /// + /// Provides a reference to a field as a `&str`. + /// + /// ```rust + /// #![feature(error_generic_member_access)] + /// + /// use core::error::Request; + /// + /// #[derive(Debug)] + /// struct SomeConcreteType { field: String } + /// + /// impl std::fmt::Display for SomeConcreteType { + /// fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + /// write!(f, "{} failed", self.field) + /// } + /// } + /// + /// impl std::error::Error for SomeConcreteType { + /// fn provide<'a>(&'a self, request: &mut Request<'a>) { + /// request.provide_ref::<str>(&self.field); + /// } + /// } + /// ``` + #[unstable(feature = "error_generic_member_access", issue = "99301")] + pub fn provide_ref<T: ?Sized + 'static>(&mut self, value: &'a T) -> &mut Self { + self.provide::<tags::Ref<tags::MaybeSizedValue<T>>>(value) + } + + /// Provide a reference computed using a closure. The referee type + /// must be bounded by `'static`, but may be unsized. + /// + /// # Examples + /// + /// Provides a reference to a field as a `&str`. + /// + /// ```rust + /// #![feature(error_generic_member_access)] + /// + /// use core::error::Request; + /// + /// #[derive(Debug)] + /// struct SomeConcreteType { business: String, party: String } + /// fn today_is_a_weekday() -> bool { true } + /// + /// impl std::fmt::Display for SomeConcreteType { + /// fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + /// write!(f, "{} failed", self.business) + /// } + /// } + /// + /// impl std::error::Error for SomeConcreteType { + /// fn provide<'a>(&'a self, request: &mut Request<'a>) { + /// request.provide_ref_with::<str>(|| { + /// if today_is_a_weekday() { + /// &self.business + /// } else { + /// &self.party + /// } + /// }); + /// } + /// } + /// ``` + #[unstable(feature = "error_generic_member_access", issue = "99301")] + pub fn provide_ref_with<T: ?Sized + 'static>( + &mut self, + fulfil: impl FnOnce() -> &'a T, + ) -> &mut Self { + self.provide_with::<tags::Ref<tags::MaybeSizedValue<T>>>(fulfil) + } + + /// Provide a value with the given `Type` tag. + fn provide<I>(&mut self, value: I::Reified) -> &mut Self + where + I: tags::Type<'a>, + { + if let Some(res @ TaggedOption(None)) = self.0.downcast_mut::<I>() { + res.0 = Some(value); + } + self + } + + /// Provide a value with the given `Type` tag, using a closure to prevent unnecessary work. + fn provide_with<I>(&mut self, fulfil: impl FnOnce() -> I::Reified) -> &mut Self + where + I: tags::Type<'a>, + { + if let Some(res @ TaggedOption(None)) = self.0.downcast_mut::<I>() { + res.0 = Some(fulfil()); + } + self + } + + /// Check if the `Request` would be satisfied if provided with a + /// value of the specified type. If the type does not match or has + /// already been provided, returns false. + /// + /// # Examples + /// + /// Check if an `u8` still needs to be provided and then provides + /// it. + /// + /// ```rust + /// #![feature(error_generic_member_access)] + /// + /// use core::error::Request; + /// use core::error::request_value; + /// + /// #[derive(Debug)] + /// struct Parent(Option<u8>); + /// + /// impl std::fmt::Display for Parent { + /// fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + /// write!(f, "a parent failed") + /// } + /// } + /// + /// impl std::error::Error for Parent { + /// fn provide<'a>(&'a self, request: &mut Request<'a>) { + /// if let Some(v) = self.0 { + /// request.provide_value::<u8>(v); + /// } + /// } + /// } + /// + /// #[derive(Debug)] + /// struct Child { + /// parent: Parent, + /// } + /// + /// impl Child { + /// // Pretend that this takes a lot of resources to evaluate. + /// fn an_expensive_computation(&self) -> Option<u8> { + /// Some(99) + /// } + /// } + /// + /// impl std::fmt::Display for Child { + /// fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + /// write!(f, "child failed: \n because of parent: {}", self.parent) + /// } + /// } + /// + /// impl std::error::Error for Child { + /// fn provide<'a>(&'a self, request: &mut Request<'a>) { + /// // In general, we don't know if this call will provide + /// // an `u8` value or not... + /// self.parent.provide(request); + /// + /// // ...so we check to see if the `u8` is needed before + /// // we run our expensive computation. + /// if request.would_be_satisfied_by_value_of::<u8>() { + /// if let Some(v) = self.an_expensive_computation() { + /// request.provide_value::<u8>(v); + /// } + /// } + /// + /// // The request will be satisfied now, regardless of if + /// // the parent provided the value or we did. + /// assert!(!request.would_be_satisfied_by_value_of::<u8>()); + /// } + /// } + /// + /// let parent = Parent(Some(42)); + /// let child = Child { parent }; + /// assert_eq!(Some(42), request_value::<u8>(&child)); + /// + /// let parent = Parent(None); + /// let child = Child { parent }; + /// assert_eq!(Some(99), request_value::<u8>(&child)); + /// + /// ``` + #[unstable(feature = "error_generic_member_access", issue = "99301")] + pub fn would_be_satisfied_by_value_of<T>(&self) -> bool + where + T: 'static, + { + self.would_be_satisfied_by::<tags::Value<T>>() + } + + /// Check if the `Request` would be satisfied if provided with a + /// reference to a value of the specified type. If the type does + /// not match or has already been provided, returns false. + /// + /// # Examples + /// + /// Check if a `&str` still needs to be provided and then provides + /// it. + /// + /// ```rust + /// #![feature(error_generic_member_access)] + /// + /// use core::error::Request; + /// use core::error::request_ref; + /// + /// #[derive(Debug)] + /// struct Parent(Option<String>); + /// + /// impl std::fmt::Display for Parent { + /// fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + /// write!(f, "a parent failed") + /// } + /// } + /// + /// impl std::error::Error for Parent { + /// fn provide<'a>(&'a self, request: &mut Request<'a>) { + /// if let Some(v) = &self.0 { + /// request.provide_ref::<str>(v); + /// } + /// } + /// } + /// + /// #[derive(Debug)] + /// struct Child { + /// parent: Parent, + /// name: String, + /// } + /// + /// impl Child { + /// // Pretend that this takes a lot of resources to evaluate. + /// fn an_expensive_computation(&self) -> Option<&str> { + /// Some(&self.name) + /// } + /// } + /// + /// impl std::fmt::Display for Child { + /// fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + /// write!(f, "{} failed: \n {}", self.name, self.parent) + /// } + /// } + /// + /// impl std::error::Error for Child { + /// fn provide<'a>(&'a self, request: &mut Request<'a>) { + /// // In general, we don't know if this call will provide + /// // a `str` reference or not... + /// self.parent.provide(request); + /// + /// // ...so we check to see if the `&str` is needed before + /// // we run our expensive computation. + /// if request.would_be_satisfied_by_ref_of::<str>() { + /// if let Some(v) = self.an_expensive_computation() { + /// request.provide_ref::<str>(v); + /// } + /// } + /// + /// // The request will be satisfied now, regardless of if + /// // the parent provided the reference or we did. + /// assert!(!request.would_be_satisfied_by_ref_of::<str>()); + /// } + /// } + /// + /// let parent = Parent(Some("parent".into())); + /// let child = Child { parent, name: "child".into() }; + /// assert_eq!(Some("parent"), request_ref::<str>(&child)); + /// + /// let parent = Parent(None); + /// let child = Child { parent, name: "child".into() }; + /// assert_eq!(Some("child"), request_ref::<str>(&child)); + /// ``` + #[unstable(feature = "error_generic_member_access", issue = "99301")] + pub fn would_be_satisfied_by_ref_of<T>(&self) -> bool + where + T: ?Sized + 'static, + { + self.would_be_satisfied_by::<tags::Ref<tags::MaybeSizedValue<T>>>() + } + + fn would_be_satisfied_by<I>(&self) -> bool + where + I: tags::Type<'a>, + { + matches!(self.0.downcast::<I>(), Some(TaggedOption(None))) + } +} + +#[unstable(feature = "error_generic_member_access", issue = "99301")] +impl<'a> Debug for Request<'a> { + fn fmt(&self, f: &mut Formatter<'_>) -> Result { + f.debug_struct("Request").finish_non_exhaustive() + } +} + +/////////////////////////////////////////////////////////////////////////////// +// Type tags +/////////////////////////////////////////////////////////////////////////////// + +pub(crate) mod tags { + //! Type tags are used to identify a type using a separate value. This module includes type tags + //! for some very common types. + //! + //! Currently type tags are not exposed to the user. But in the future, if you want to use the + //! Request API with more complex types (typically those including lifetime parameters), you + //! will need to write your own tags. + + use crate::marker::PhantomData; + + /// This trait is implemented by specific tag types in order to allow + /// describing a type which can be requested for a given lifetime `'a`. + /// + /// A few example implementations for type-driven tags can be found in this + /// module, although crates may also implement their own tags for more + /// complex types with internal lifetimes. + pub(crate) trait Type<'a>: Sized + 'static { + /// The type of values which may be tagged by this tag for the given + /// lifetime. + type Reified: 'a; + } + + /// Similar to the [`Type`] trait, but represents a type which may be unsized (i.e., has a + /// `?Sized` bound). E.g., `str`. + pub(crate) trait MaybeSizedType<'a>: Sized + 'static { + type Reified: 'a + ?Sized; + } + + impl<'a, T: Type<'a>> MaybeSizedType<'a> for T { + type Reified = T::Reified; + } + + /// Type-based tag for types bounded by `'static`, i.e., with no borrowed elements. + #[derive(Debug)] + pub(crate) struct Value<T: 'static>(PhantomData<T>); + + impl<'a, T: 'static> Type<'a> for Value<T> { + type Reified = T; + } + + /// Type-based tag similar to [`Value`] but which may be unsized (i.e., has a `?Sized` bound). + #[derive(Debug)] + pub(crate) struct MaybeSizedValue<T: ?Sized + 'static>(PhantomData<T>); + + impl<'a, T: ?Sized + 'static> MaybeSizedType<'a> for MaybeSizedValue<T> { + type Reified = T; + } + + /// Type-based tag for reference types (`&'a T`, where T is represented by + /// `<I as MaybeSizedType<'a>>::Reified`. + #[derive(Debug)] + pub(crate) struct Ref<I>(PhantomData<I>); + + impl<'a, I: MaybeSizedType<'a>> Type<'a> for Ref<I> { + type Reified = &'a I::Reified; + } +} + +/// An `Option` with a type tag `I`. +/// +/// Since this struct implements `Erased`, the type can be erased to make a dynamically typed +/// option. The type can be checked dynamically using `Erased::tag_id` and since this is statically +/// checked for the concrete type, there is some degree of type safety. +#[repr(transparent)] +pub(crate) struct TaggedOption<'a, I: tags::Type<'a>>(pub Option<I::Reified>); + +impl<'a, I: tags::Type<'a>> TaggedOption<'a, I> { + pub(crate) fn as_request(&mut self) -> &mut Request<'a> { + Request::new(self as &mut (dyn Erased<'a> + 'a)) + } +} + +/// Represents a type-erased but identifiable object. +/// +/// This trait is exclusively implemented by the `TaggedOption` type. +unsafe trait Erased<'a>: 'a { + /// The `TypeId` of the erased type. + fn tag_id(&self) -> TypeId; +} + +unsafe impl<'a, I: tags::Type<'a>> Erased<'a> for TaggedOption<'a, I> { + fn tag_id(&self) -> TypeId { + TypeId::of::<I>() + } +} + +impl<'a> dyn Erased<'a> + 'a { + /// Returns some reference to the dynamic value if it is tagged with `I`, + /// or `None` otherwise. + #[inline] + fn downcast<I>(&self) -> Option<&TaggedOption<'a, I>> + where + I: tags::Type<'a>, + { + if self.tag_id() == TypeId::of::<I>() { + // SAFETY: Just checked whether we're pointing to an I. + Some(unsafe { &*(self as *const Self).cast::<TaggedOption<'a, I>>() }) + } else { + None + } + } + + /// Returns some mutable reference to the dynamic value if it is tagged with `I`, + /// or `None` otherwise. + #[inline] + fn downcast_mut<I>(&mut self) -> Option<&mut TaggedOption<'a, I>> + where + I: tags::Type<'a>, + { + if self.tag_id() == TypeId::of::<I>() { + // SAFETY: Just checked whether we're pointing to an I. + Some(unsafe { &mut *(self as *mut Self).cast::<TaggedOption<'a, I>>() }) + } else { + None + } + } +} + /// An iterator over an [`Error`] and its sources. /// /// If you want to omit the initial error and only process @@ -449,8 +1028,8 @@ impl<'a, T: Error + ?Sized> Error for &'a T { Error::source(&**self) } - fn provide<'b>(&'b self, demand: &mut Demand<'b>) { - Error::provide(&**self, demand); + fn provide<'b>(&'b self, request: &mut Request<'b>) { + Error::provide(&**self, request); } } diff --git a/library/core/src/ffi/c_str.rs b/library/core/src/ffi/c_str.rs index b59ec12790d..4082b208c12 100644 --- a/library/core/src/ffi/c_str.rs +++ b/library/core/src/ffi/c_str.rs @@ -82,12 +82,12 @@ use crate::str; #[stable(feature = "core_c_str", since = "1.64.0")] #[rustc_has_incoherent_inherent_impls] #[lang = "CStr"] -// FIXME: // `fn from` in `impl From<&CStr> for Box<CStr>` current implementation relies // on `CStr` being layout-compatible with `[u8]`. -// When attribute privacy is implemented, `CStr` should be annotated as `#[repr(transparent)]`. -// Anyway, `CStr` representation and layout are considered implementation detail, are -// not documented and must not be relied upon. +// However, `CStr` layout is considered an implementation detail and must not be relied upon. We +// want `repr(transparent)` but we don't want it to show up in rustdoc, so we hide it under +// `cfg(doc)`. This is an ad-hoc implementation of attribute privacy. +#[cfg_attr(not(doc), repr(transparent))] pub struct CStr { // FIXME: this should not be represented with a DST slice but rather with // just a raw `c_char` along with some form of marker to make diff --git a/library/core/src/ffi/mod.rs b/library/core/src/ffi/mod.rs index 3fcd5e7c1cb..b2c9a0800c9 100644 --- a/library/core/src/ffi/mod.rs +++ b/library/core/src/ffi/mod.rs @@ -110,7 +110,8 @@ mod c_char_definition { target_arch = "powerpc64", target_arch = "s390x", target_arch = "riscv64", - target_arch = "riscv32" + target_arch = "riscv32", + target_arch = "csky" ) ), all(target_os = "android", any(target_arch = "aarch64", target_arch = "arm")), diff --git a/library/core/tests/any.rs b/library/core/tests/any.rs index a8f6b7ebb92..8d2d31b6431 100644 --- a/library/core/tests/any.rs +++ b/library/core/tests/any.rs @@ -147,65 +147,3 @@ fn dyn_type_name() { std::any::type_name::<dyn Foo<Bar = i32> + Send + Sync>() ); } - -// Test the `Provider` API. - -struct SomeConcreteType { - some_string: String, -} - -impl Provider for SomeConcreteType { - fn provide<'a>(&'a self, demand: &mut Demand<'a>) { - demand - .provide_ref::<String>(&self.some_string) - .provide_ref::<str>(&self.some_string) - .provide_value_with::<String>(|| "bye".to_owned()); - } -} - -// Test the provide and request mechanisms with a by-reference trait object. -#[test] -fn test_provider() { - let obj: &dyn Provider = &SomeConcreteType { some_string: "hello".to_owned() }; - - assert_eq!(&**request_ref::<String>(obj).unwrap(), "hello"); - assert_eq!(&*request_value::<String>(obj).unwrap(), "bye"); - assert_eq!(request_value::<u8>(obj), None); -} - -// Test the provide and request mechanisms with a boxed trait object. -#[test] -fn test_provider_boxed() { - let obj: Box<dyn Provider> = Box::new(SomeConcreteType { some_string: "hello".to_owned() }); - - assert_eq!(&**request_ref::<String>(&*obj).unwrap(), "hello"); - assert_eq!(&*request_value::<String>(&*obj).unwrap(), "bye"); - assert_eq!(request_value::<u8>(&*obj), None); -} - -// Test the provide and request mechanisms with a concrete object. -#[test] -fn test_provider_concrete() { - let obj = SomeConcreteType { some_string: "hello".to_owned() }; - - assert_eq!(&**request_ref::<String>(&obj).unwrap(), "hello"); - assert_eq!(&*request_value::<String>(&obj).unwrap(), "bye"); - assert_eq!(request_value::<u8>(&obj), None); -} - -trait OtherTrait: Provider {} - -impl OtherTrait for SomeConcreteType {} - -impl dyn OtherTrait { - fn get_ref<T: 'static + ?Sized>(&self) -> Option<&T> { - request_ref::<T>(self) - } -} - -// Test the provide and request mechanisms via an intermediate trait. -#[test] -fn test_provider_intermediate() { - let obj: &dyn OtherTrait = &SomeConcreteType { some_string: "hello".to_owned() }; - assert_eq!(obj.get_ref::<str>().unwrap(), "hello"); -} diff --git a/library/core/tests/error.rs b/library/core/tests/error.rs new file mode 100644 index 00000000000..cb7cb5441d1 --- /dev/null +++ b/library/core/tests/error.rs @@ -0,0 +1,66 @@ +use core::error::{request_value, request_ref, Request}; + +// Test the `Request` API. +#[derive(Debug)] +struct SomeConcreteType { + some_string: String, +} + +impl std::fmt::Display for SomeConcreteType { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "A") + } +} + +impl std::error::Error for SomeConcreteType { + fn provide<'a>(&'a self, request: &mut Request<'a>) { + request + .provide_ref::<String>(&self.some_string) + .provide_ref::<str>(&self.some_string) + .provide_value_with::<String>(|| "bye".to_owned()); + } +} + +// Test the Error.provide and request mechanisms with a by-reference trait object. +#[test] +fn test_error_generic_member_access() { + let obj = &SomeConcreteType { some_string: "hello".to_owned() }; + + assert_eq!(request_ref::<String>(&*obj).unwrap(), "hello"); + assert_eq!(request_value::<String>(&*obj).unwrap(), "bye"); + assert_eq!(request_value::<u8>(&obj), None); +} + +// Test the Error.provide and request mechanisms with a by-reference trait object. +#[test] +fn test_request_constructor() { + let obj: &dyn std::error::Error = &SomeConcreteType { some_string: "hello".to_owned() }; + + assert_eq!(request_ref::<String>(&*obj).unwrap(), "hello"); + assert_eq!(request_value::<String>(&*obj).unwrap(), "bye"); + assert_eq!(request_value::<u8>(&obj), None); +} + +// Test the Error.provide and request mechanisms with a boxed trait object. +#[test] +fn test_error_generic_member_access_boxed() { + let obj: Box<dyn std::error::Error> = + Box::new(SomeConcreteType { some_string: "hello".to_owned() }); + + assert_eq!(request_ref::<String>(&*obj).unwrap(), "hello"); + assert_eq!(request_value::<String>(&*obj).unwrap(), "bye"); + + // NOTE: Box<E> only implements Error when E: Error + Sized, which means we can't pass a + // Box<dyn Error> to request_value. + //assert_eq!(request_value::<String>(&obj).unwrap(), "bye"); +} + +// Test the Error.provide and request mechanisms with a concrete object. +#[test] +fn test_error_generic_member_access_concrete() { + let obj = SomeConcreteType { some_string: "hello".to_owned() }; + + assert_eq!(request_ref::<String>(&obj).unwrap(), "hello"); + assert_eq!(request_value::<String>(&obj).unwrap(), "bye"); + assert_eq!(request_value::<u8>(&obj), None); +} diff --git a/library/core/tests/lib.rs b/library/core/tests/lib.rs index d849561bb21..7a6def37a55 100644 --- a/library/core/tests/lib.rs +++ b/library/core/tests/lib.rs @@ -105,7 +105,9 @@ #![feature(const_slice_from_ref)] #![feature(waker_getters)] #![feature(slice_flatten)] -#![feature(provide_any)] +#![feature(error_generic_member_access)] +#![feature(error_in_core)] +#![feature(trait_upcasting)] #![feature(utf8_chunks)] #![feature(is_ascii_octdigit)] #![feature(get_many_mut)] diff --git a/library/std/Cargo.toml b/library/std/Cargo.toml index 5b213555394..33c9c6e63c1 100644 --- a/library/std/Cargo.toml +++ b/library/std/Cargo.toml @@ -29,8 +29,8 @@ rustc-demangle = { version = "0.1.21", features = ['rustc-dep-of-std'] } [target.'cfg(not(all(windows, target_env = "msvc", not(target_vendor = "uwp"))))'.dependencies] miniz_oxide = { version = "0.7.0", optional = true, default-features = false } -addr2line = { version = "0.20.0", optional = true, default-features = false } -object = { version = "0.31.1", default-features = false, optional = true, features = ['read_core', 'elf', 'macho', 'pe', 'unaligned', 'archive'] } +addr2line = { version = "0.21.0", optional = true, default-features = false } +object = { version = "0.32.0", default-features = false, optional = true, features = ['read_core', 'elf', 'macho', 'pe', 'unaligned', 'archive'] } [dev-dependencies] rand = { version = "0.8.5", default-features = false, features = ["alloc"] } diff --git a/library/std/src/env.rs b/library/std/src/env.rs index f3122c2931d..f67f6034d34 100644 --- a/library/std/src/env.rs +++ b/library/std/src/env.rs @@ -894,6 +894,7 @@ pub mod consts { /// - aarch64 /// - loongarch64 /// - m68k + /// - csky /// - mips /// - mips64 /// - powerpc diff --git a/library/std/src/error.rs b/library/std/src/error.rs index ee5eddebfaf..7bc3af1793e 100644 --- a/library/std/src/error.rs +++ b/library/std/src/error.rs @@ -9,6 +9,8 @@ use crate::fmt::{self, Write}; #[stable(feature = "rust1", since = "1.0.0")] pub use core::error::Error; +#[unstable(feature = "error_generic_member_access", issue = "99301")] +pub use core::error::{request_ref, Request}; mod private { // This is a hack to prevent `type_id` from being overridden by `Error` @@ -371,11 +373,10 @@ impl<E> Report<E> { /// /// ```rust /// #![feature(error_reporter)] - /// #![feature(provide_any)] /// #![feature(error_generic_member_access)] /// # use std::error::Error; /// # use std::fmt; - /// use std::any::Demand; + /// use std::error::Request; /// use std::error::Report; /// use std::backtrace::Backtrace; /// @@ -405,8 +406,8 @@ impl<E> Report<E> { /// } /// /// impl Error for SuperErrorSideKick { - /// fn provide<'a>(&'a self, demand: &mut Demand<'a>) { - /// demand.provide_ref::<Backtrace>(&self.backtrace); + /// fn provide<'a>(&'a self, request: &mut Request<'a>) { + /// request.provide_ref::<Backtrace>(&self.backtrace); /// } /// } /// @@ -459,11 +460,11 @@ where fn backtrace(&self) -> Option<&Backtrace> { // have to grab the backtrace on the first error directly since that error may not be // 'static - let backtrace = (&self.error as &dyn Error).request_ref(); + let backtrace = request_ref(&self.error); let backtrace = backtrace.or_else(|| { self.error .source() - .map(|source| source.sources().find_map(|source| source.request_ref())) + .map(|source| source.sources().find_map(|source| request_ref(source))) .flatten() }); backtrace diff --git a/library/std/src/error/tests.rs b/library/std/src/error/tests.rs index ee999bd65c3..ed070a26b0c 100644 --- a/library/std/src/error/tests.rs +++ b/library/std/src/error/tests.rs @@ -1,6 +1,6 @@ use super::Error; use crate::fmt; -use core::any::Demand; +use core::error::Request; #[derive(Debug, PartialEq)] struct A; @@ -199,7 +199,7 @@ where self.source.as_deref() } - fn provide<'a>(&'a self, req: &mut Demand<'a>) { + fn provide<'a>(&'a self, req: &mut Request<'a>) { self.backtrace.as_ref().map(|bt| req.provide_ref::<Backtrace>(bt)); } } diff --git a/library/std/src/ffi/os_str.rs b/library/std/src/ffi/os_str.rs index 67e58fd1b86..43cecb19b14 100644 --- a/library/std/src/ffi/os_str.rs +++ b/library/std/src/ffi/os_str.rs @@ -110,12 +110,12 @@ impl crate::sealed::Sealed for OsString {} /// [conversions]: super#conversions #[cfg_attr(not(test), rustc_diagnostic_item = "OsStr")] #[stable(feature = "rust1", since = "1.0.0")] -// FIXME: // `OsStr::from_inner` current implementation relies // on `OsStr` being layout-compatible with `Slice`. -// When attribute privacy is implemented, `OsStr` should be annotated as `#[repr(transparent)]`. -// Anyway, `OsStr` representation and layout are considered implementation details, are -// not documented and must not be relied upon. +// However, `OsStr` layout is considered an implementation detail and must not be relied upon. We +// want `repr(transparent)` but we don't want it to show up in rustdoc, so we hide it under +// `cfg(doc)`. This is an ad-hoc implementation of attribute privacy. +#[cfg_attr(not(doc), repr(transparent))] pub struct OsStr { inner: Slice, } diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index 6f58e5a0f05..c07aa5cd91f 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -306,7 +306,6 @@ #![feature(pointer_is_aligned)] #![feature(portable_simd)] #![feature(prelude_2024)] -#![feature(provide_any)] #![feature(ptr_as_uninit)] #![feature(raw_os_nonzero)] #![feature(round_ties_even)] diff --git a/library/std/src/os/l4re/raw.rs b/library/std/src/os/l4re/raw.rs index b3f7439f8cd..12c0293285a 100644 --- a/library/std/src/os/l4re/raw.rs +++ b/library/std/src/os/l4re/raw.rs @@ -27,6 +27,7 @@ pub use self::arch::{blkcnt_t, blksize_t, ino_t, nlink_t, off_t, stat, time_t}; #[cfg(any( target_arch = "x86", target_arch = "m68k", + target_arch = "csky", target_arch = "powerpc", target_arch = "sparc", target_arch = "arm", diff --git a/library/std/src/os/linux/raw.rs b/library/std/src/os/linux/raw.rs index 7c55e92502f..a568f9b26ba 100644 --- a/library/std/src/os/linux/raw.rs +++ b/library/std/src/os/linux/raw.rs @@ -27,6 +27,7 @@ pub use self::arch::{blkcnt_t, blksize_t, ino_t, nlink_t, off_t, stat, time_t}; #[cfg(any( target_arch = "x86", target_arch = "m68k", + target_arch = "csky", target_arch = "powerpc", target_arch = "sparc", target_arch = "arm", diff --git a/library/std/src/path.rs b/library/std/src/path.rs index 99f7a60f8ab..5842c096f1a 100644 --- a/library/std/src/path.rs +++ b/library/std/src/path.rs @@ -1158,12 +1158,12 @@ impl FusedIterator for Ancestors<'_> {} /// Which method works best depends on what kind of situation you're in. #[cfg_attr(not(test), rustc_diagnostic_item = "PathBuf")] #[stable(feature = "rust1", since = "1.0.0")] -// FIXME: // `PathBuf::as_mut_vec` current implementation relies // on `PathBuf` being layout-compatible with `Vec<u8>`. -// When attribute privacy is implemented, `PathBuf` should be annotated as `#[repr(transparent)]`. -// Anyway, `PathBuf` representation and layout are considered implementation detail, are -// not documented and must not be relied upon. +// However, `PathBuf` layout is considered an implementation detail and must not be relied upon. We +// want `repr(transparent)` but we don't want it to show up in rustdoc, so we hide it under +// `cfg(doc)`. This is an ad-hoc implementation of attribute privacy. +#[cfg_attr(not(doc), repr(transparent))] pub struct PathBuf { inner: OsString, } @@ -1983,12 +1983,12 @@ impl AsRef<OsStr> for PathBuf { /// ``` #[cfg_attr(not(test), rustc_diagnostic_item = "Path")] #[stable(feature = "rust1", since = "1.0.0")] -// FIXME: // `Path::new` current implementation relies // on `Path` being layout-compatible with `OsStr`. -// When attribute privacy is implemented, `Path` should be annotated as `#[repr(transparent)]`. -// Anyway, `Path` representation and layout are considered implementation detail, are -// not documented and must not be relied upon. +// However, `Path` layout is considered an implementation detail and must not be relied upon. We +// want `repr(transparent)` but we don't want it to show up in rustdoc, so we hide it under +// `cfg(doc)`. This is an ad-hoc implementation of attribute privacy. +#[cfg_attr(not(doc), repr(transparent))] pub struct Path { inner: OsStr, } diff --git a/library/std/src/sys/common/alloc.rs b/library/std/src/sys/common/alloc.rs index 3ccea3ce0e3..d58aa6c27b8 100644 --- a/library/std/src/sys/common/alloc.rs +++ b/library/std/src/sys/common/alloc.rs @@ -8,6 +8,7 @@ use crate::ptr; target_arch = "x86", target_arch = "arm", target_arch = "m68k", + target_arch = "csky", target_arch = "mips", target_arch = "mips32r6", target_arch = "powerpc", diff --git a/library/std/src/sys/personality/gcc.rs b/library/std/src/sys/personality/gcc.rs index dc9636ac8c9..e477a0cd7ab 100644 --- a/library/std/src/sys/personality/gcc.rs +++ b/library/std/src/sys/personality/gcc.rs @@ -67,6 +67,9 @@ const UNWIND_DATA_REG: (i32, i32) = (0, 1); // D0, D1 ))] const UNWIND_DATA_REG: (i32, i32) = (4, 5); // A0, A1 +#[cfg(target_arch = "csky")] +const UNWIND_DATA_REG: (i32, i32) = (0, 1); // R0, R1 + #[cfg(any(target_arch = "powerpc", target_arch = "powerpc64"))] const UNWIND_DATA_REG: (i32, i32) = (3, 4); // R3, R4 / X3, X4 diff --git a/library/std/src/sys/wasi/fd.rs b/library/std/src/sys/wasi/fd.rs index 1b50c2ea6dd..d7295a799da 100644 --- a/library/std/src/sys/wasi/fd.rs +++ b/library/std/src/sys/wasi/fd.rs @@ -16,14 +16,20 @@ pub struct WasiFd { fn iovec<'a>(a: &'a mut [IoSliceMut<'_>]) -> &'a [wasi::Iovec] { assert_eq!(mem::size_of::<IoSliceMut<'_>>(), mem::size_of::<wasi::Iovec>()); assert_eq!(mem::align_of::<IoSliceMut<'_>>(), mem::align_of::<wasi::Iovec>()); - // SAFETY: `IoSliceMut` and `IoVec` have exactly the same memory layout + // SAFETY: `IoSliceMut` and `IoVec` have exactly the same memory layout. + // We decorate our `IoSliceMut` with `repr(transparent)` (see `io.rs`), and + // `crate::io::IoSliceMut` is a `repr(transparent)` wrapper around our type, so this is + // guaranteed. unsafe { mem::transmute(a) } } fn ciovec<'a>(a: &'a [IoSlice<'_>]) -> &'a [wasi::Ciovec] { assert_eq!(mem::size_of::<IoSlice<'_>>(), mem::size_of::<wasi::Ciovec>()); assert_eq!(mem::align_of::<IoSlice<'_>>(), mem::align_of::<wasi::Ciovec>()); - // SAFETY: `IoSlice` and `CIoVec` have exactly the same memory layout + // SAFETY: `IoSlice` and `CIoVec` have exactly the same memory layout. + // We decorate our `IoSlice` with `repr(transparent)` (see `io.rs`), and + // `crate::io::IoSlice` is a `repr(transparent)` wrapper around our type, so this is + // guaranteed. unsafe { mem::transmute(a) } } diff --git a/library/std/src/sys_common/wtf8.rs b/library/std/src/sys_common/wtf8.rs index 195d175cc9b..67db5ebd89c 100644 --- a/library/std/src/sys_common/wtf8.rs +++ b/library/std/src/sys_common/wtf8.rs @@ -459,6 +459,7 @@ impl Wtf8Buf { /// Converts this `Wtf8Buf` into a boxed `Wtf8`. #[inline] pub fn into_box(self) -> Box<Wtf8> { + // SAFETY: relies on `Wtf8` being `repr(transparent)`. unsafe { mem::transmute(self.bytes.into_boxed_slice()) } } @@ -511,6 +512,7 @@ impl Extend<CodePoint> for Wtf8Buf { /// Similar to `&str`, but can additionally contain surrogate code points /// if they’re not in a surrogate pair. #[derive(Eq, Ord, PartialEq, PartialOrd)] +#[repr(transparent)] pub struct Wtf8 { bytes: [u8], } diff --git a/library/unwind/src/libunwind.rs b/library/unwind/src/libunwind.rs index 521da6c4589..a2bfa8e96dd 100644 --- a/library/unwind/src/libunwind.rs +++ b/library/unwind/src/libunwind.rs @@ -54,6 +54,9 @@ pub const unwinder_private_data_size: usize = 2; #[cfg(any(target_arch = "mips", target_arch = "mips32r6"))] pub const unwinder_private_data_size: usize = 2; +#[cfg(target_arch = "csky")] +pub const unwinder_private_data_size: usize = 2; + #[cfg(any(target_arch = "mips64", target_arch = "mips64r6"))] pub const unwinder_private_data_size: usize = 2; diff --git a/src/bootstrap/Cargo.lock b/src/bootstrap/Cargo.lock index 66d97a2a0d0..ecb58a0e9a5 100644 --- a/src/bootstrap/Cargo.lock +++ b/src/bootstrap/Cargo.lock @@ -479,9 +479,9 @@ dependencies = [ [[package]] name = "object" -version = "0.31.1" +version = "0.32.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8bda667d9f2b5051b8833f59f3bf748b28ef54f850f4fcb389a252aa383866d1" +checksum = "77ac5bbd07aea88c60a577a1ce218075ffd59208b2d7ca97adf9bfc5aeb21ebe" dependencies = [ "memchr", ] diff --git a/src/bootstrap/Cargo.toml b/src/bootstrap/Cargo.toml index 85eb543e48e..74b9a23fa4e 100644 --- a/src/bootstrap/Cargo.toml +++ b/src/bootstrap/Cargo.toml @@ -36,7 +36,7 @@ filetime = "0.2" cc = "1.0.69" libc = "0.2" hex = "0.4" -object = { version = "0.31.1", default-features = false, features = ["archive", "coff", "read_core", "unaligned"] } +object = { version = "0.32.0", default-features = false, features = ["archive", "coff", "read_core", "unaligned"] } serde = "1.0.137" # Directly use serde_derive rather than through the derive feature of serde to allow building both # in parallel and to allow serde_json and toml to start building as soon as serde has been built. diff --git a/src/bootstrap/bootstrap.py b/src/bootstrap/bootstrap.py index 70079106689..f44a05a6b28 100644 --- a/src/bootstrap/bootstrap.py +++ b/src/bootstrap/bootstrap.py @@ -332,6 +332,7 @@ def default_build_triple(verbose): 'i786': 'i686', 'loongarch64': 'loongarch64', 'm68k': 'm68k', + 'csky': 'csky', 'powerpc': 'powerpc', 'powerpc64': 'powerpc64', 'powerpc64le': 'powerpc64le', diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs index e3a9434a164..4396bbc51a3 100644 --- a/src/bootstrap/lib.rs +++ b/src/bootstrap/lib.rs @@ -138,7 +138,7 @@ const EXTRA_CHECK_CFGS: &[(Option<Mode>, &'static str, Option<&[&'static str]>)] ( Some(Mode::Std), "target_arch", - Some(&["asmjs", "spirv", "nvptx", "xtensa", "mips32r6", "mips64r6"]), + Some(&["asmjs", "spirv", "nvptx", "xtensa", "mips32r6", "mips64r6", "csky"]), ), /* Extra names used by dependencies */ // FIXME: Used by serde_json, but we should not be triggering on external dependencies. diff --git a/src/bootstrap/llvm.rs b/src/bootstrap/llvm.rs index 4943f93fa9a..c841cb34036 100644 --- a/src/bootstrap/llvm.rs +++ b/src/bootstrap/llvm.rs @@ -299,7 +299,7 @@ impl Step for Llvm { let llvm_exp_targets = match builder.config.llvm_experimental_targets { Some(ref s) => s, - None => "AVR;M68k", + None => "AVR;M68k;CSKY", }; let assertions = if builder.config.llvm_assertions { "ON" } else { "OFF" }; @@ -374,12 +374,12 @@ impl Step for Llvm { cfg.define("LLVM_LINK_LLVM_DYLIB", "ON"); } - if target.starts_with("riscv") + if (target.starts_with("riscv") || target.starts_with("csky")) && !target.contains("freebsd") && !target.contains("openbsd") && !target.contains("netbsd") { - // RISC-V GCC erroneously requires linking against + // RISC-V and CSKY GCC erroneously requires linking against // `libatomic` when using 1-byte and 2-byte C++ // atomics but the LLVM build system check cannot // detect this. Therefore it is set manually here. diff --git a/src/doc/book b/src/doc/book -Subproject 668c64760b5c7ea654facb4ba5fe9faddfda27c +Subproject 72187f5cd0beaaa9c6f584156bcd88f921871e8 diff --git a/src/doc/embedded-book b/src/doc/embedded-book -Subproject 1e5556dd1b864109985d5871616ae6b9164bcea +Subproject 99ad2847b865e96d8ae7b333d3ee96963557e62 diff --git a/src/doc/nomicon b/src/doc/nomicon -Subproject 302b995bcb24b70fd883980fd174738c3a10b70 +Subproject 388750b081c0893c275044d37203f97709e058b diff --git a/src/doc/reference b/src/doc/reference -Subproject 9cd5c5a6ccbd4c07c65ab5c69a53286280308c9 +Subproject d43038932adeb16ada80e206d4c073d85129810 diff --git a/src/doc/rustc-dev-guide b/src/doc/rustc-dev-guide -Subproject 24eebb6df96d037aad285e4f7793bd0393a6687 +Subproject b123ab4754127d822ffb38349ce0fbf561f1b2f diff --git a/src/doc/rustc/src/SUMMARY.md b/src/doc/rustc/src/SUMMARY.md index 817abbfaf26..94605e2a217 100644 --- a/src/doc/rustc/src/SUMMARY.md +++ b/src/doc/rustc/src/SUMMARY.md @@ -32,6 +32,7 @@ - [\*-esp-espidf](platform-support/esp-idf.md) - [\*-unknown-fuchsia](platform-support/fuchsia.md) - [\*-kmc-solid_\*](platform-support/kmc-solid.md) + - [csky-unknown-linux-gnuabiv2](platform-support/csky-unknown-linux-gnuabiv2.md) - [loongarch\*-unknown-linux-\*](platform-support/loongarch-linux.md) - [loongarch\*-unknown-none\*](platform-support/loongarch-none.md) - [m68k-unknown-linux-gnu](platform-support/m68k-unknown-linux-gnu.md) diff --git a/src/doc/rustc/src/platform-support.md b/src/doc/rustc/src/platform-support.md index 393719e7115..371ee378d1a 100644 --- a/src/doc/rustc/src/platform-support.md +++ b/src/doc/rustc/src/platform-support.md @@ -259,6 +259,7 @@ target | std | host | notes `avr-unknown-gnu-atmega328` | * | | AVR. Requires `-Z build-std=core` `bpfeb-unknown-none` | * | | BPF (big endian) `bpfel-unknown-none` | * | | BPF (little endian) +`csky-unknown-linux-gnuabiv2` | ✓ | | C-SKY abiv2 Linux(little endian) `hexagon-unknown-linux-musl` | ? | | `i386-apple-ios` | ✓ | | 32-bit x86 iOS [`i586-pc-nto-qnx700`](platform-support/nto-qnx.md) | * | | 32-bit x86 QNX Neutrino 7.0 RTOS | diff --git a/src/doc/rustc/src/platform-support/csky-unknown-linux-gnuabiv2.md b/src/doc/rustc/src/platform-support/csky-unknown-linux-gnuabiv2.md new file mode 100644 index 00000000000..e73598be0d9 --- /dev/null +++ b/src/doc/rustc/src/platform-support/csky-unknown-linux-gnuabiv2.md @@ -0,0 +1,70 @@ +# `csky-unknown-linux-gnuabiv2` + +**Tier: 3** + +This target supports [C-SKY](https://github.com/c-sky) CPUs with `abi` v2 and `glibc`. + +https://c-sky.github.io/ +https://gitlab.com/c-sky/ + +## Target maintainers + +* [@Dirreke](https://github.com/Dirreke) + +## Requirements + + +## Building the target + +### Get a C toolchain + +Compiling rust for this target has been tested on `x86_64` linux hosts. Other host types have not been tested, but may work, if you can find a suitable cross compilation toolchain for them. + +If you don't already have a suitable toolchain, you can download from [here](https://occ-oss-prod.oss-cn-hangzhou.aliyuncs.com/resource/1356021/1619528643136/csky-linux-gnuabiv2-tools-x86_64-glibc-linux-4.9.56-20210423.tar.gz), and unpack it into a directory. + +### Configure rust + +The target can be built by enabling it for a `rustc` build, by placing the following in `config.toml`: + +```toml +[build] +target = ["x86_64-unknown-linux-gnu", "csky-unknown-linux-gnuabiv2"] +stage = 2 + +[target.csky-unknown-linux-gnuabiv2] +# ADJUST THIS PATH TO POINT AT YOUR TOOLCHAIN +cc = "${TOOLCHAIN_PATH}/bin/csky-linux-gnuabiv2-gcc" + +### Build + +```sh +# in rust dir +./x.py build --stage 2 +``` + +## Building and Running Rust programs + +To test cross-compiled binaries on a `x86_64` system, you can use the `qemu-cskyv2`. This avoids having a full emulated ARM system by doing dynamic binary translation and dynamic system call translation. It lets you run CSKY programs directly on your `x86_64` kernel. It's very convenient! + +To use: + +* Install `qemu-cskyv2` (If you don't already have a qemu, you can download from [here](https://occ-oss-prod.oss-cn-hangzhou.aliyuncs.com/resource//1689324918932/xuantie-qemu-x86_64-Ubuntu-18.04-20230714-0202.tar.gz"), and unpack it into a directory.) +* Link your built toolchain via: + * `rustup toolchain link stage2 ${RUST}/build/x86_64-unknown-linux-gnu/stage2` +* Create a test program + +```sh +cargo new hello_world +cd hello_world +``` + +* Build and run + +```sh +CARGO_TARGET_CSKY_UNKNOWN_LINUX_GNUABIV2_RUNNER=${QEMU_PATH}/bin/qemu-cskyv2 -L ${TOOLCHAIN_PATH}/csky-linux-gnuabiv2/libc \ +CARGO_TARGET_CSKY_UNKNOWN_LINUX_GNUABIV2_LINKER=${TOOLCHAIN_PATH}/bin/csky-linux-gnuabiv2-gcc \ +RUSTFLAGS="-C target-features=+crt-static" \ +cargo +stage2 run --target csky-unknown-linux-gnuabiv2 +``` + +Attention: The dynamic-linked program may nor be run by `qemu-cskyv2` but can be run on the target. 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 c634dc50d6d..968c9bb4ebb 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 +- CSKY - s390x ## Register classes @@ -46,6 +47,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` | +| CSKY | `reg` | `r[0-31]` | `r` | +| CSKY | `freg` | `f[0-31]` | `f` | | s390x | `reg` | `r[0-10]`, `r[12-14]` | `r` | | s390x | `freg` | `f[0-15]` | `f` | @@ -79,6 +82,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` | +| CSKY | `reg` | None | `i8`, `i16`, `i32` | +| CSKY | `freg` | None | `f32`, | | s390x | `reg` | None | `i8`, `i16`, `i32`, `i64` | | s390x | `freg` | None | `f32`, `f64` | @@ -102,6 +107,17 @@ This feature tracks `asm!` and `global_asm!` support for the following architect | M68k | `a5` | `bp` | | M68k | `a6` | `fp` | | M68k | `a7` | `sp`, `usp`, `ssp`, `isp` | +| CSKY | `r[0-3]` | `a[0-3]` | +| CSKY | `r[4-11]` | `l[0-7]` | +| CSKY | `r[12-13]` | `t[0-1]` | +| CSKY | `r14` | `sp` | +| CSKY | `r15` | `lr` | +| CSKY | `r[16-17]` | `l[8-9]` | +| CSKY | `r[18-25]` | `t[2-9]` | +| CSKY | `r28` | `rgb` | +| CSKY | `r29` | `rtb` | +| CSKY | `r30` | `svbr` | +| CSKY | `r31` | `tls` | > **Notes**: > - TI does not mandate a frame pointer for MSP430, but toolchains are allowed @@ -123,6 +139,13 @@ 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. | +| CSKY | `r7`, `r28` | Used internally by LLVM for the base pointer and global base pointer. | +| CSKY | `r8` | Used internally by LLVM for the frame pointer. | +| CSKY | `r14` | Used internally by LLVM for the stack pointer. | +| CSKY | `r15` | This is the link register. | +| CSKY | `r[26-30]` | Reserved by its ABI. | +| CSKY | `r31` | This is the TLS register. | + ## Template modifiers @@ -139,6 +162,8 @@ This feature tracks `asm!` and `global_asm!` support for the following architect | PowerPC | `freg` | None | `0` | None | | s390x | `reg` | None | `%r0` | None | | s390x | `freg` | None | `%f0` | None | +| CSKY | `reg` | None | `r0` | None | +| CSKY | `freg` | None | `f0` | None | # Flags covered by `preserves_flags` diff --git a/src/librustdoc/clean/cfg.rs b/src/librustdoc/clean/cfg.rs index 83886dd42aa..7652f27e51c 100644 --- a/src/librustdoc/clean/cfg.rs +++ b/src/librustdoc/clean/cfg.rs @@ -519,6 +519,7 @@ impl<'a> fmt::Display for Display<'a> { "asmjs" => "JavaScript", "loongarch64" => "LoongArch LA64", "m68k" => "M68k", + "csky" => "CSKY", "mips" => "MIPS", "mips32r6" => "MIPS Release 6", "mips64" => "MIPS-64", diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index 389bac0f09d..2456e8818eb 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -9,7 +9,7 @@ use rustc_ast as ast; use rustc_data_structures::fx::FxHashSet; use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; -use rustc_hir::def_id::{DefId, DefIdSet, LocalDefId}; +use rustc_hir::def_id::{DefId, DefIdSet, LocalModDefId}; use rustc_hir::Mutability; use rustc_metadata::creader::{CStore, LoadedMacro}; use rustc_middle::ty::fast_reject::SimplifiedType; @@ -138,7 +138,7 @@ pub(crate) fn try_inline( pub(crate) fn try_inline_glob( cx: &mut DocContext<'_>, res: Res, - current_mod: LocalDefId, + current_mod: LocalModDefId, visited: &mut DefIdSet, inlined_names: &mut FxHashSet<(ItemType, Symbol)>, import: &hir::Item<'_>, @@ -154,7 +154,7 @@ pub(crate) fn try_inline_glob( // reexported by the glob, e.g. because they are shadowed by something else. let reexports = cx .tcx - .module_children_local(current_mod) + .module_children_local(current_mod.to_local_def_id()) .iter() .filter(|child| !child.reexport_chain.is_empty()) .filter_map(|child| child.res.opt_def_id()) diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index b6ba4c853d4..624f1620f2c 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -1551,7 +1551,7 @@ fn first_non_private<'tcx>( } [parent, leaf] if parent.ident.name == kw::Super => { let parent_mod = cx.tcx.parent_module(hir_id); - if let Some(super_parent) = cx.tcx.opt_local_parent(parent_mod) { + if let Some(super_parent) = cx.tcx.opt_local_parent(parent_mod.to_local_def_id()) { (super_parent, leaf.ident) } else { // If we can't find the parent of the parent, then the parent is already the crate. @@ -2828,7 +2828,7 @@ fn clean_use_statement_inner<'tcx>( // The parent of the module in which this import resides. This // is the same as `current_mod` if that's already the top // level module. - let parent_mod = cx.tcx.parent_module_from_def_id(current_mod); + let parent_mod = cx.tcx.parent_module_from_def_id(current_mod.to_local_def_id()); // This checks if the import can be seen from a higher level module. // In other words, it checks if the visibility is the equivalent of diff --git a/src/tools/build-manifest/src/main.rs b/src/tools/build-manifest/src/main.rs index 88f8770029e..778609da062 100644 --- a/src/tools/build-manifest/src/main.rs +++ b/src/tools/build-manifest/src/main.rs @@ -100,6 +100,7 @@ static TARGETS: &[&str] = &[ "i686-unknown-uefi", "loongarch64-unknown-linux-gnu", "m68k-unknown-linux-gnu", + "csky-unknown-linux-gnuabiv2", "mips-unknown-linux-gnu", "mips-unknown-linux-musl", "mips64-unknown-linux-gnuabi64", diff --git a/src/tools/cargo b/src/tools/cargo -Subproject 7e9de3f4ec3708f500bec142317895b96131e47 +Subproject 7c3904d6c3ed54e8a413023519b55a536ad44d5 diff --git a/src/tools/clippy/clippy_utils/src/lib.rs b/src/tools/clippy/clippy_utils/src/lib.rs index 171b7faf219..b77a2f1d0cd 100644 --- a/src/tools/clippy/clippy_utils/src/lib.rs +++ b/src/tools/clippy/clippy_utils/src/lib.rs @@ -83,7 +83,7 @@ use rustc_ast::Attribute; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::unhash::UnhashMap; use rustc_hir::def::{DefKind, Res}; -use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, LOCAL_CRATE}; +use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, LocalModDefId, LOCAL_CRATE}; use rustc_hir::hir_id::{HirIdMap, HirIdSet}; use rustc_hir::intravisit::{walk_expr, FnKind, Visitor}; use rustc_hir::LangItem::{OptionNone, OptionSome, ResultErr, ResultOk}; @@ -2370,11 +2370,11 @@ pub fn is_hir_ty_cfg_dependant(cx: &LateContext<'_>, ty: &hir::Ty<'_>) -> bool { false } -static TEST_ITEM_NAMES_CACHE: OnceLock<Mutex<FxHashMap<LocalDefId, Vec<Symbol>>>> = OnceLock::new(); +static TEST_ITEM_NAMES_CACHE: OnceLock<Mutex<FxHashMap<LocalModDefId, Vec<Symbol>>>> = OnceLock::new(); -fn with_test_item_names(tcx: TyCtxt<'_>, module: LocalDefId, f: impl Fn(&[Symbol]) -> bool) -> bool { +fn with_test_item_names(tcx: TyCtxt<'_>, module: LocalModDefId, f: impl Fn(&[Symbol]) -> bool) -> bool { let cache = TEST_ITEM_NAMES_CACHE.get_or_init(|| Mutex::new(FxHashMap::default())); - let mut map: MutexGuard<'_, FxHashMap<LocalDefId, Vec<Symbol>>> = cache.lock().unwrap(); + let mut map: MutexGuard<'_, FxHashMap<LocalModDefId, Vec<Symbol>>> = cache.lock().unwrap(); let value = map.entry(module); match value { Entry::Occupied(entry) => f(entry.get()), diff --git a/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs b/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs index 4c695cb9b6e..139e31bc528 100644 --- a/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs +++ b/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs @@ -415,7 +415,7 @@ fn is_ty_const_destruct<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, body: &Body<'tcx> if !matches!( impl_src, - ImplSource::Builtin(BuiltinImplSource::Misc, _) | ImplSource::Param(ty::BoundConstness::ConstIfConst, _) + ImplSource::Builtin(BuiltinImplSource::Misc, _) | ImplSource::Param(_) ) { return false; } diff --git a/src/tools/rust-analyzer/Cargo.lock b/src/tools/rust-analyzer/Cargo.lock index f8806794979..a2b263cf2d8 100644 --- a/src/tools/rust-analyzer/Cargo.lock +++ b/src/tools/rust-analyzer/Cargo.lock @@ -1196,9 +1196,9 @@ dependencies = [ [[package]] name = "object" -version = "0.31.1" +version = "0.32.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8bda667d9f2b5051b8833f59f3bf748b28ef54f850f4fcb389a252aa383866d1" +checksum = "77ac5bbd07aea88c60a577a1ce218075ffd59208b2d7ca97adf9bfc5aeb21ebe" dependencies = [ "memchr", ] @@ -1337,7 +1337,7 @@ name = "proc-macro-api" version = "0.0.0" dependencies = [ "memmap2", - "object 0.31.1", + "object 0.32.0", "paths", "profile", "serde", @@ -1357,7 +1357,7 @@ dependencies = [ "libloading", "mbe", "memmap2", - "object 0.31.1", + "object 0.32.0", "paths", "proc-macro-api", "proc-macro-test", diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/completions/attribute/cfg.rs b/src/tools/rust-analyzer/crates/ide-completion/src/completions/attribute/cfg.rs index 19bfd294b25..62bdb6ee688 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/completions/attribute/cfg.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/completions/attribute/cfg.rs @@ -42,10 +42,11 @@ pub(crate) fn complete_cfg(acc: &mut Completions, ctx: &CompletionContext<'_>) { }; } -const KNOWN_ARCH: [&str; 19] = [ +const KNOWN_ARCH: [&str; 20] = [ "aarch64", "arm", "avr", + "csky", "hexagon", "mips", "mips64", diff --git a/src/tools/rust-analyzer/crates/proc-macro-api/Cargo.toml b/src/tools/rust-analyzer/crates/proc-macro-api/Cargo.toml index 4e39167136b..4229f289130 100644 --- a/src/tools/rust-analyzer/crates/proc-macro-api/Cargo.toml +++ b/src/tools/rust-analyzer/crates/proc-macro-api/Cargo.toml @@ -12,7 +12,7 @@ rust-version.workspace = true doctest = false [dependencies] -object = { version = "0.31.0", default-features = false, features = [ +object = { version = "0.32.0", default-features = false, features = [ "std", "read_core", "elf", diff --git a/src/tools/rust-analyzer/crates/proc-macro-srv/Cargo.toml b/src/tools/rust-analyzer/crates/proc-macro-srv/Cargo.toml index ecc6aaa0ac7..99993f16e27 100644 --- a/src/tools/rust-analyzer/crates/proc-macro-srv/Cargo.toml +++ b/src/tools/rust-analyzer/crates/proc-macro-srv/Cargo.toml @@ -12,7 +12,7 @@ rust-version.workspace = true doctest = false [dependencies] -object = { version = "0.31.0", default-features = false, features = [ +object = { version = "0.32.0", default-features = false, features = [ "std", "read_core", "elf", diff --git a/src/tools/tidy/src/deps.rs b/src/tools/tidy/src/deps.rs index a9ab696cdf4..410852b6a31 100644 --- a/src/tools/tidy/src/deps.rs +++ b/src/tools/tidy/src/deps.rs @@ -258,6 +258,8 @@ const PERMITTED_RUSTC_DEPENDENCIES: &[&str] = &[ "termize", "thin-vec", "thiserror", + "thiserror-core", + "thiserror-core-impl", "thiserror-impl", "thorin-dwp", "thread_local", diff --git a/tests/codegen/method-declaration.rs b/tests/codegen/method-declaration.rs new file mode 100644 index 00000000000..4ae332b0107 --- /dev/null +++ b/tests/codegen/method-declaration.rs @@ -0,0 +1,26 @@ +// compile-flags: -g -Cno-prepopulate-passes + +// Verify that we added a declaration for a method. + +// CHECK: define{{.*}}@method{{.*}} !dbg ![[METHOD_DEF_DBG:[0-9]+]] +// CHECK: define{{.*}}@function{{.*}} !dbg ![[FUNC_DEF_DBG:[0-9]+]] + +#![crate_type = "lib"] + +// CHECK-DAG: ![[FOO_DBG:[0-9]+]] = !DICompositeType(tag: {{.*}} name: "Foo", {{.*}} identifier: +pub struct Foo; + +impl Foo { + // CHECK-DAG: ![[METHOD_DEF_DBG]] = distinct !DISubprogram(name: "method"{{.*}}, scope: ![[FOO_DBG]]{{.*}}DISPFlagDefinition{{.*}}, declaration: ![[METHOD_DECL_DBG:[0-9]+]] + // CHECK-DAG: ![[METHOD_DECL_DBG]] = !DISubprogram(name: "method"{{.*}}, scope: ![[FOO_DBG]] + #[no_mangle] + pub fn method() {} +} + +// CHECK: ![[FUNC_DEF_DBG]] = distinct !DISubprogram(name: "function" +// CHECK-NOT: declaration +// CHECK-SAME: DISPFlagDefinition +// CHECK-NOT: declaration +// CHECK-SAME: ) +#[no_mangle] +pub fn function() {} diff --git a/tests/ui/asm/issue-113788.rs b/tests/ui/asm/issue-113788.rs new file mode 100644 index 00000000000..903b444767f --- /dev/null +++ b/tests/ui/asm/issue-113788.rs @@ -0,0 +1,7 @@ +// test that "error: arguments for inline assembly must be copyable" doesn't show up in this code +// needs-asm-support +// only-x86_64 +fn main() { + let peb: *const PEB; //~ ERROR cannot find type `PEB` in this scope [E0412] + unsafe { std::arch::asm!("mov {0}, fs:[0x30]", out(reg) peb); } +} diff --git a/tests/ui/asm/issue-113788.stderr b/tests/ui/asm/issue-113788.stderr new file mode 100644 index 00000000000..f8e65b6f538 --- /dev/null +++ b/tests/ui/asm/issue-113788.stderr @@ -0,0 +1,9 @@ +error[E0412]: cannot find type `PEB` in this scope + --> $DIR/issue-113788.rs:5:21 + | +LL | let peb: *const PEB; + | ^^^ not found in this scope + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0412`. diff --git a/tests/ui/check-cfg/compact-values.stderr b/tests/ui/check-cfg/compact-values.stderr index 5f8dbbdb05c..b7269a652ea 100644 --- a/tests/ui/check-cfg/compact-values.stderr +++ b/tests/ui/check-cfg/compact-values.stderr @@ -4,7 +4,7 @@ warning: unexpected `cfg` condition value LL | #[cfg(target(os = "linux", arch = "X"))] | ^^^^^^^^^^ | - = note: expected values for `target_arch` are: `aarch64`, `arm`, `avr`, `bpf`, `hexagon`, `loongarch64`, `m68k`, `mips`, `mips32r6`, `mips64`, `mips64r6`, `msp430`, `nvptx64`, `powerpc`, `powerpc64`, `riscv32`, `riscv64`, `s390x`, `sparc`, `sparc64`, `wasm32`, `wasm64`, `x86`, `x86_64` + = note: expected values for `target_arch` are: `aarch64`, `arm`, `avr`, `bpf`, `csky`, `hexagon`, `loongarch64`, `m68k`, `mips`, `mips32r6`, `mips64`, `mips64r6`, `msp430`, `nvptx64`, `powerpc`, `powerpc64`, `riscv32`, `riscv64`, `s390x`, `sparc`, `sparc64`, `wasm32`, `wasm64`, `x86`, `x86_64` = note: `#[warn(unexpected_cfgs)]` on by default warning: 1 warning emitted diff --git a/tests/ui/coherence/warn-when-cycle-is-error-in-coherence.rs b/tests/ui/coherence/warn-when-cycle-is-error-in-coherence.rs new file mode 100644 index 00000000000..01f7d6ce901 --- /dev/null +++ b/tests/ui/coherence/warn-when-cycle-is-error-in-coherence.rs @@ -0,0 +1,35 @@ +#![deny(coinductive_overlap_in_coherence)] + +use std::borrow::Borrow; +use std::cmp::Ordering; +use std::marker::PhantomData; + +#[derive(PartialEq, Default)] +pub(crate) struct Interval<T>(PhantomData<T>); + +// This impl overlaps with the `derive` unless we reject the nested +// `Interval<?1>: PartialOrd<Interval<?1>>` candidate which results +// in a - currently inductive - cycle. +impl<T, Q> PartialEq<Q> for Interval<T> +//~^ ERROR implementations of `PartialEq<Interval<_>>` for `Interval<_>` will conflict in the future +//~| WARN this was previously accepted by the compiler but is being phased out +where + T: Borrow<Q>, + Q: ?Sized + PartialOrd, +{ + fn eq(&self, _: &Q) -> bool { + true + } +} + +impl<T, Q> PartialOrd<Q> for Interval<T> +where + T: Borrow<Q>, + Q: ?Sized + PartialOrd, +{ + fn partial_cmp(&self, _: &Q) -> Option<Ordering> { + None + } +} + +fn main() {} diff --git a/tests/ui/coherence/warn-when-cycle-is-error-in-coherence.stderr b/tests/ui/coherence/warn-when-cycle-is-error-in-coherence.stderr new file mode 100644 index 00000000000..f315ba82130 --- /dev/null +++ b/tests/ui/coherence/warn-when-cycle-is-error-in-coherence.stderr @@ -0,0 +1,23 @@ +error: implementations of `PartialEq<Interval<_>>` for `Interval<_>` will conflict in the future + --> $DIR/warn-when-cycle-is-error-in-coherence.rs:13:1 + | +LL | #[derive(PartialEq, Default)] + | --------- the second impl is here +... +LL | impl<T, Q> PartialEq<Q> for Interval<T> + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the first impl is here +... +LL | Q: ?Sized + PartialOrd, + | ---------- `Interval<_>: PartialOrd` may be considered to hold in future releases, causing the impls to overlap + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #114040 <https://github.com/rust-lang/rust/issues/114040> + = note: impls that are not considered to overlap may be considered to overlap in the future +note: the lint level is defined here + --> $DIR/warn-when-cycle-is-error-in-coherence.rs:1:9 + | +LL | #![deny(coinductive_overlap_in_coherence)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/impl-trait/issue-99073-2.rs b/tests/ui/impl-trait/issue-99073-2.rs index 14ac688806b..37ea211bec3 100644 --- a/tests/ui/impl-trait/issue-99073-2.rs +++ b/tests/ui/impl-trait/issue-99073-2.rs @@ -8,6 +8,7 @@ fn test<T: Display>(t: T, recurse: bool) -> impl Display { let f = || { let i: u32 = test::<i32>(-1, false); //~^ ERROR concrete type differs from previous defining opaque type use + //~| ERROR expected generic type parameter, found `i32` println!("{i}"); }; if recurse { diff --git a/tests/ui/impl-trait/issue-99073-2.stderr b/tests/ui/impl-trait/issue-99073-2.stderr index 913bc8f5674..06b2b84569f 100644 --- a/tests/ui/impl-trait/issue-99073-2.stderr +++ b/tests/ui/impl-trait/issue-99073-2.stderr @@ -1,3 +1,12 @@ +error[E0792]: expected generic type parameter, found `i32` + --> $DIR/issue-99073-2.rs:9:22 + | +LL | fn test<T: Display>(t: T, recurse: bool) -> impl Display { + | - this generic parameter must be used with a generic type parameter +LL | let f = || { +LL | let i: u32 = test::<i32>(-1, false); + | ^^^^^^^^^^^^^^^^^^^^^^ + error: concrete type differs from previous defining opaque type use --> $DIR/issue-99073-2.rs:9:22 | @@ -5,10 +14,11 @@ LL | let i: u32 = test::<i32>(-1, false); | ^^^^^^^^^^^^^^^^^^^^^^ expected `T`, got `u32` | note: previous use here - --> $DIR/issue-99073-2.rs:16:5 + --> $DIR/issue-99073-2.rs:7:45 | -LL | t - | ^ +LL | fn test<T: Display>(t: T, recurse: bool) -> impl Display { + | ^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 2 previous errors +For more information about this error, try `rustc --explain E0792`. diff --git a/tests/ui/impl-trait/issue-99073.rs b/tests/ui/impl-trait/issue-99073.rs index 7798e247df0..b4ef3e66f96 100644 --- a/tests/ui/impl-trait/issue-99073.rs +++ b/tests/ui/impl-trait/issue-99073.rs @@ -5,4 +5,5 @@ fn main() { fn fix<F: Fn(G), G: Fn()>(f: F) -> impl Fn() { move || f(fix(&f)) //~^ ERROR concrete type differs from previous defining opaque type use + //~| ERROR expected generic type parameter, found `&F` } diff --git a/tests/ui/impl-trait/issue-99073.stderr b/tests/ui/impl-trait/issue-99073.stderr index 54636795349..a8400080e5a 100644 --- a/tests/ui/impl-trait/issue-99073.stderr +++ b/tests/ui/impl-trait/issue-99073.stderr @@ -1,14 +1,23 @@ -error: concrete type differs from previous defining opaque type use +error[E0792]: expected generic type parameter, found `&F` --> $DIR/issue-99073.rs:6:11 | +LL | fn fix<F: Fn(G), G: Fn()>(f: F) -> impl Fn() { + | - this generic parameter must be used with a generic type parameter +LL | move || f(fix(&f)) + | ^^^^^^^^^^ + +error: concrete type differs from previous defining opaque type use + --> $DIR/issue-99073.rs:6:13 + | LL | move || f(fix(&f)) - | ^^^^^^^^^^ expected `[closure@$DIR/issue-99073.rs:6:3: 6:10]`, got `G` + | ^^^^^^^ expected `[closure@$DIR/issue-99073.rs:6:3: 6:10]`, got `G` | note: previous use here - --> $DIR/issue-99073.rs:6:3 + --> $DIR/issue-99073.rs:5:36 | -LL | move || f(fix(&f)) - | ^^^^^^^^^^^^^^^^^^ +LL | fn fix<F: Fn(G), G: Fn()>(f: F) -> impl Fn() { + | ^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 2 previous errors +For more information about this error, try `rustc --explain E0792`. diff --git a/tests/ui/impl-trait/rpit/equal-lifetime-params-ok.rs b/tests/ui/impl-trait/rpit/equal-lifetime-params-ok.rs new file mode 100644 index 00000000000..6207381c745 --- /dev/null +++ b/tests/ui/impl-trait/rpit/equal-lifetime-params-ok.rs @@ -0,0 +1,19 @@ +// check-pass + +// related to #113916, check that using RPITs in functions with lifetime params +// which are constrained to be equal compiles. + +trait Trait<'a, 'b> {} +impl Trait<'_, '_> for () {} +fn pass<'a: 'b, 'b: 'a>() -> impl Trait<'a, 'b> { + (|| {})() +} + +struct Foo<'a>(&'a ()); +impl<'a> Foo<'a> { + fn bar<'b: 'a>(&'b self) -> impl Trait<'a, 'b> { + let _: &'a &'b &'a (); + } +} + +fn main() {} diff --git a/tests/ui/impl-trait/rpit/non-defining-use.rs b/tests/ui/impl-trait/rpit/non-defining-use.rs new file mode 100644 index 00000000000..255a8929a87 --- /dev/null +++ b/tests/ui/impl-trait/rpit/non-defining-use.rs @@ -0,0 +1,14 @@ +// Regression test for #111935 that non-defining uses of RPIT result in errors +#![allow(unconditional_recursion)] +fn foo<T>() -> impl Sized { + let _: () = foo::<u8>(); //~ ERROR expected generic type parameter, found `u8` +} + +fn bar<T>(val: T) -> impl Sized { + let _: u8 = bar(0u8); + //~^ ERROR concrete type differs from previous defining opaque type use + //~| ERROR expected generic type parameter, found `u8` + val +} + +fn main() {} diff --git a/tests/ui/impl-trait/rpit/non-defining-use.stderr b/tests/ui/impl-trait/rpit/non-defining-use.stderr new file mode 100644 index 00000000000..19987d47672 --- /dev/null +++ b/tests/ui/impl-trait/rpit/non-defining-use.stderr @@ -0,0 +1,31 @@ +error[E0792]: expected generic type parameter, found `u8` + --> $DIR/non-defining-use.rs:4:12 + | +LL | fn foo<T>() -> impl Sized { + | - this generic parameter must be used with a generic type parameter +LL | let _: () = foo::<u8>(); + | ^^ + +error[E0792]: expected generic type parameter, found `u8` + --> $DIR/non-defining-use.rs:8:12 + | +LL | fn bar<T>(val: T) -> impl Sized { + | - this generic parameter must be used with a generic type parameter +LL | let _: u8 = bar(0u8); + | ^^ + +error: concrete type differs from previous defining opaque type use + --> $DIR/non-defining-use.rs:8:17 + | +LL | let _: u8 = bar(0u8); + | ^^^^^^^^ expected `T`, got `u8` + | +note: previous use here + --> $DIR/non-defining-use.rs:7:22 + | +LL | fn bar<T>(val: T) -> impl Sized { + | ^^^^^^^^^^ + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0792`. diff --git a/tests/ui/implied-bounds/implied-bounds-entailment-wf-vars-issue-114783-1.rs b/tests/ui/implied-bounds/implied-bounds-entailment-wf-vars-issue-114783-1.rs new file mode 100644 index 00000000000..9b793642d07 --- /dev/null +++ b/tests/ui/implied-bounds/implied-bounds-entailment-wf-vars-issue-114783-1.rs @@ -0,0 +1,26 @@ +// check-pass + +pub trait Foo { + type Error: Error; + + fn foo(&self, stream: &<Self::Error as Error>::Span); +} + +pub struct Wrapper<Inner>(Inner); + +impl<E: Error, Inner> Foo for Wrapper<Inner> +where + Inner: Foo<Error = E>, +{ + type Error = E; + + fn foo(&self, stream: &<Self::Error as Error>::Span) { + todo!() + } +} + +pub trait Error { + type Span; +} + +fn main() {} diff --git a/tests/ui/implied-bounds/implied-bounds-entailment-wf-vars-issue-114783-2.rs b/tests/ui/implied-bounds/implied-bounds-entailment-wf-vars-issue-114783-2.rs new file mode 100644 index 00000000000..86b10a56c9d --- /dev/null +++ b/tests/ui/implied-bounds/implied-bounds-entailment-wf-vars-issue-114783-2.rs @@ -0,0 +1,26 @@ +// check-pass + +trait AsBufferView { + type Device; +} + +trait Error { + type Span; +} + +trait Foo { + type Error: Error; + fn foo(&self) -> &<Self::Error as Error>::Span; +} + +impl<D: Error, VBuf0> Foo for VBuf0 +where + VBuf0: AsBufferView<Device = D>, +{ + type Error = D; + fn foo(&self) -> &<Self::Error as Error>::Span { + todo!() + } +} + +fn main() {} diff --git a/tests/ui/lint/lint-struct-necessary.rs b/tests/ui/lint/lint-struct-necessary.rs new file mode 100644 index 00000000000..8bc3c12054a --- /dev/null +++ b/tests/ui/lint/lint-struct-necessary.rs @@ -0,0 +1,31 @@ +#![allow(dead_code)] +#![deny(unused_parens)] + +enum State { + Waiting { start_at: u64 } +} +struct Foo {} + +fn main() { + let e = &mut State::Waiting { start_at: 0u64 }; + match (&mut State::Waiting { start_at: 0u64 }) { + _ => {} + } + + match (e) { + //~^ ERROR unnecessary parentheses around `match` scrutinee expression + _ => {} + } + + match &(State::Waiting { start_at: 0u64 }) { + _ => {} + } + + match (State::Waiting { start_at: 0u64 }) { + _ => {} + } + + match (&&Foo {}) { + _ => {} + } +} diff --git a/tests/ui/lint/lint-struct-necessary.stderr b/tests/ui/lint/lint-struct-necessary.stderr new file mode 100644 index 00000000000..eb65a9e98c6 --- /dev/null +++ b/tests/ui/lint/lint-struct-necessary.stderr @@ -0,0 +1,19 @@ +error: unnecessary parentheses around `match` scrutinee expression + --> $DIR/lint-struct-necessary.rs:15:11 + | +LL | match (e) { + | ^ ^ + | +note: the lint level is defined here + --> $DIR/lint-struct-necessary.rs:2:9 + | +LL | #![deny(unused_parens)] + | ^^^^^^^^^^^^^ +help: remove these parentheses + | +LL - match (e) { +LL + match e { + | + +error: aborting due to previous error + diff --git a/tests/ui/lint/unknown-lints/allow-in-other-module.rs b/tests/ui/lint/unknown-lints/allow-in-other-module.rs new file mode 100644 index 00000000000..20bf0d7af03 --- /dev/null +++ b/tests/ui/lint/unknown-lints/allow-in-other-module.rs @@ -0,0 +1,26 @@ +// check-pass + +// Tests that the unknown_lints lint doesn't fire for an unknown lint loaded from a separate file. +// The key part is that the stderr output should be empty. +// Reported in https://github.com/rust-lang/rust/issues/84936 +// Fixed incidentally by https://github.com/rust-lang/rust/pull/97266 + +// This `allow` should apply to submodules, whether they are inline or loaded from a file. +#![allow(unknown_lints)] +#![allow(dead_code)] +// no warning +#![allow(not_a_real_lint)] + +mod other; + +// no warning +#[allow(not_a_real_lint)] +fn m() {} + +mod mm { + // no warning + #[allow(not_a_real_lint)] + fn m() {} +} + +fn main() {} diff --git a/tests/ui/lint/unknown-lints/other.rs b/tests/ui/lint/unknown-lints/other.rs new file mode 100644 index 00000000000..a5111c00a3e --- /dev/null +++ b/tests/ui/lint/unknown-lints/other.rs @@ -0,0 +1,10 @@ +// ignore-test + +// Companion to allow-in-other-module.rs + +// This should not warn. +#![allow(not_a_real_lint)] + +// This should not warn, either. +#[allow(not_a_real_lint)] +fn m() {} diff --git a/tests/ui/rfcs/rfc-2027-object-safe-for-dispatch/manual-self-impl-for-unsafe-obj.rs b/tests/ui/rfcs/rfc-2027-object-safe-for-dispatch/manual-self-impl-for-unsafe-obj.rs index 721890db4fb..c27e8c4b019 100644 --- a/tests/ui/rfcs/rfc-2027-object-safe-for-dispatch/manual-self-impl-for-unsafe-obj.rs +++ b/tests/ui/rfcs/rfc-2027-object-safe-for-dispatch/manual-self-impl-for-unsafe-obj.rs @@ -1,5 +1,7 @@ // Check that we can manually implement an object-unsafe trait for its trait object. +// revisions: current next +//[next] compile-flags: -Ztrait-solver=next // run-pass #![feature(object_safe_for_dispatch)] diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/assoc-type-const-bound-usage.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/assoc-type-const-bound-usage.rs index a70ef31fed1..f41c1051fce 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/assoc-type-const-bound-usage.rs +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/assoc-type-const-bound-usage.rs @@ -1,6 +1,6 @@ // known-bug: #110395 // FIXME check-pass -#![feature(const_trait_impl)] +#![feature(const_trait_impl, effects)] #[const_trait] trait Foo { diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/assoc-type-const-bound-usage.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/assoc-type-const-bound-usage.stderr index 6d7980a9736..4fcfe9d4769 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/assoc-type-const-bound-usage.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/assoc-type-const-bound-usage.stderr @@ -1,11 +1,14 @@ -error[E0015]: cannot call non-const fn `<<T as Foo>::Assoc as Foo>::foo` in constant functions +error[E0277]: the trait bound `T: Foo` is not satisfied --> $DIR/assoc-type-const-bound-usage.rs:12:5 | LL | <T as Foo>::Assoc::foo(); - | ^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `T` | - = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants +help: consider further restricting this bound + | +LL | const fn foo<T: ~const Foo + Foo>() { + | +++++ error: aborting due to previous error -For more information about this error, try `rustc --explain E0015`. +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/call-generic-method-fail.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/call-generic-method-fail.rs index fe1abbf4207..53778b3af3d 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/call-generic-method-fail.rs +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/call-generic-method-fail.rs @@ -1,5 +1,6 @@ -// known-bug: #110395 -#![feature(const_trait_impl)] +// FIXME(effects) +// check-pass +#![feature(const_trait_impl, effects)] pub const fn equals_self<T: PartialEq>(t: &T) -> bool { *t == *t diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/call-generic-method-fail.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/call-generic-method-fail.stderr deleted file mode 100644 index d50100d033e..00000000000 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/call-generic-method-fail.stderr +++ /dev/null @@ -1,15 +0,0 @@ -error[E0015]: cannot call non-const operator in constant functions - --> $DIR/call-generic-method-fail.rs:5:5 - | -LL | *t == *t - | ^^^^^^^^ - | - = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants -help: consider further restricting this bound - | -LL | pub const fn equals_self<T: PartialEq + ~const std::cmp::PartialEq>(t: &T) -> bool { - | ++++++++++++++++++++++++++++ - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0015`. diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/specialization/const-default-const-specialized.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/specialization/const-default-const-specialized.rs index 307d5a37bb0..b6cb24d15fe 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/specialization/const-default-const-specialized.rs +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/specialization/const-default-const-specialized.rs @@ -1,10 +1,9 @@ // Tests that a const default trait impl can be specialized by another const // trait impl and that the specializing impl will be used during const-eval. -// known-bug: #110395 -// FIXME run-pass +// run-pass -#![feature(const_trait_impl)] +#![feature(const_trait_impl, effects)] #![feature(min_specialization)] #[const_trait] diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/specialization/const-default-const-specialized.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/specialization/const-default-const-specialized.stderr deleted file mode 100644 index 6dad82b03b5..00000000000 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/specialization/const-default-const-specialized.stderr +++ /dev/null @@ -1,11 +0,0 @@ -error[E0015]: cannot call non-const fn `<T as Value>::value` in constant functions - --> $DIR/const-default-const-specialized.rs:16:5 - | -LL | T::value() - | ^^^^^^^^^^ - | - = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0015`. diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/specialization/non-const-default-const-specialized.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/specialization/non-const-default-const-specialized.rs index f1fbbb512e3..84c7926f415 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/specialization/non-const-default-const-specialized.rs +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/specialization/non-const-default-const-specialized.rs @@ -3,7 +3,7 @@ // known-bug: #110395 // FIXME run-pass -#![feature(const_trait_impl)] +#![feature(const_trait_impl, effects)] #![feature(min_specialization)] #[const_trait] diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/specialization/non-const-default-const-specialized.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/specialization/non-const-default-const-specialized.stderr index 5ba4f2d52c5..4734cee7f9a 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/specialization/non-const-default-const-specialized.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/specialization/non-const-default-const-specialized.stderr @@ -1,11 +1,12 @@ -error[E0015]: cannot call non-const fn `<T as Value>::value` in constant functions - --> $DIR/non-const-default-const-specialized.rs:15:5 +error[E0119]: conflicting implementations of trait `Value` for type `FortyTwo` + --> $DIR/non-const-default-const-specialized.rs:27:1 | -LL | T::value() - | ^^^^^^^^^^ - | - = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants +LL | impl<T> Value for T { + | ------------------- first implementation here +... +LL | impl const Value for FortyTwo { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `FortyTwo` error: aborting due to previous error -For more information about this error, try `rustc --explain E0015`. +For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits.rs index 79cba548fd5..92becf7c4af 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits.rs +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits.rs @@ -1,6 +1,5 @@ -// known-bug: #110395 -// FIXME check-pass -#![feature(const_trait_impl)] +// check-pass +#![feature(const_trait_impl, effects)] #[const_trait] trait Foo { diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits.stderr deleted file mode 100644 index 03d7b0549a6..00000000000 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits.stderr +++ /dev/null @@ -1,11 +0,0 @@ -error[E0015]: cannot call non-const fn `<T as Foo>::a` in constant functions - --> $DIR/super-traits.rs:21:7 - | -LL | t.a(); - | ^^^ - | - = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0015`. diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/tilde-const-and-const-params.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/tilde-const-and-const-params.rs index 7338fb245b3..89d74cecfdb 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/tilde-const-and-const-params.rs +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/tilde-const-and-const-params.rs @@ -1,4 +1,4 @@ -#![feature(const_trait_impl)] +#![feature(const_trait_impl, effects)] #![feature(generic_arg_infer)] #![feature(generic_const_exprs)] #![allow(incomplete_features)] @@ -6,9 +6,10 @@ struct Foo<const N: usize>; impl<const N: usize> Foo<N> { - fn add<A: ~const Add42>(self) -> Foo<{ A::add(N) }> { - Foo - } + fn add<A: ~const Add42>(self) -> Foo<{ A::add(N) }> { + //~^ ERROR mismatched types + Foo + } } #[const_trait] @@ -24,7 +25,7 @@ impl const Add42 for () { fn bar<A: ~const Add42, const N: usize>(_: Foo<N>) -> Foo<{ A::add(N) }> { //~^ ERROR `~const` is not allowed here - //~| ERROR cannot call + //~| ERROR mismatched types Foo } diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/tilde-const-and-const-params.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/tilde-const-and-const-params.stderr index 2a17ee3f372..ec5d21d33c6 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/tilde-const-and-const-params.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/tilde-const-and-const-params.stderr @@ -1,23 +1,33 @@ error: `~const` is not allowed here - --> $DIR/tilde-const-and-const-params.rs:25:11 + --> $DIR/tilde-const-and-const-params.rs:26:11 | LL | fn bar<A: ~const Add42, const N: usize>(_: Foo<N>) -> Foo<{ A::add(N) }> { | ^^^^^^^^^^^^ | note: this function is not `const`, so it cannot have `~const` trait bounds - --> $DIR/tilde-const-and-const-params.rs:25:4 + --> $DIR/tilde-const-and-const-params.rs:26:4 | LL | fn bar<A: ~const Add42, const N: usize>(_: Foo<N>) -> Foo<{ A::add(N) }> { | ^^^ -error[E0015]: cannot call non-const fn `<A as Add42>::add` in constants - --> $DIR/tilde-const-and-const-params.rs:25:61 +error[E0308]: mismatched types + --> $DIR/tilde-const-and-const-params.rs:26:61 | LL | fn bar<A: ~const Add42, const N: usize>(_: Foo<N>) -> Foo<{ A::add(N) }> { - | ^^^^^^^^^ + | ^^^^^^^^^ expected `false`, found `true` | - = note: calls in constants are limited to constant functions, tuple structs and tuple variants + = note: expected constant `false` + found constant `true` -error: aborting due to 2 previous errors +error[E0308]: mismatched types + --> $DIR/tilde-const-and-const-params.rs:9:44 + | +LL | fn add<A: ~const Add42>(self) -> Foo<{ A::add(N) }> { + | ^^^^^^^^^ expected `false`, found `true` + | + = note: expected constant `false` + found constant `true` + +error: aborting due to 3 previous errors -For more information about this error, try `rustc --explain E0015`. +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/tilde_const_on_impl_bound.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/tilde_const_on_impl_bound.rs index 411f4b2f68c..fbdc3a4f370 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/tilde_const_on_impl_bound.rs +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/tilde_const_on_impl_bound.rs @@ -1,6 +1,6 @@ // known-bug: #110395 // FIXME check-pass -#![feature(const_trait_impl)] +#![feature(const_trait_impl, effects)] #[const_trait] trait Foo { diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/tilde_const_on_impl_bound.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/tilde_const_on_impl_bound.stderr index 4b852b65b0c..f77672f3e71 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/tilde_const_on_impl_bound.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/tilde_const_on_impl_bound.stderr @@ -1,11 +1,12 @@ -error[E0015]: cannot call non-const fn `<T as Foo>::foo` in constant functions - --> $DIR/tilde_const_on_impl_bound.rs:14:16 +error[E0308]: mismatched types + --> $DIR/tilde_const_on_impl_bound.rs:14:9 | LL | self.0.foo() - | ^^^^^ + | ^^^^^^^^^^^^ expected `host`, found `true` | - = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants + = note: expected constant `host` + found constant `true` error: aborting due to previous error -For more information about this error, try `rustc --explain E0015`. +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/trait-where-clause-const.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/trait-where-clause-const.rs index 47f7806e453..94be3ff46ac 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/trait-where-clause-const.rs +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/trait-where-clause-const.rs @@ -4,7 +4,7 @@ // test is not enough. // known-bug: #110395 // FIXME check-pass -#![feature(const_trait_impl)] +#![feature(const_trait_impl, effects)] #[const_trait] trait Bar {} diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/trait-where-clause-const.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/trait-where-clause-const.stderr index 54537231b61..e8d0eec020f 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/trait-where-clause-const.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/trait-where-clause-const.stderr @@ -1,51 +1,35 @@ -error[E0015]: cannot call non-const fn `<T as Foo>::a` in constant functions - --> $DIR/trait-where-clause-const.rs:20:5 - | -LL | T::a(); - | ^^^^^^ - | - = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants - -error[E0015]: cannot call non-const fn `<T as Foo>::b` in constant functions +error[E0277]: the trait bound `T: ~const Bar` is not satisfied --> $DIR/trait-where-clause-const.rs:21:5 | LL | T::b(); - | ^^^^^^ - | - = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants - -error[E0015]: cannot call non-const fn `<T as Foo>::c::<T>` in constant functions - --> $DIR/trait-where-clause-const.rs:23:5 - | -LL | T::c::<T>(); - | ^^^^^^^^^^^ + | ^^^^ the trait `Bar` is not implemented for `T` | - = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants - -error[E0015]: cannot call non-const fn `<T as Foo>::a` in constant functions - --> $DIR/trait-where-clause-const.rs:28:5 +note: required by a bound in `Foo::b` + --> $DIR/trait-where-clause-const.rs:15:24 | -LL | T::a(); - | ^^^^^^ +LL | fn b() where Self: ~const Bar; + | ^^^^^^^^^^ required by this bound in `Foo::b` +help: consider further restricting this bound | - = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants +LL | const fn test1<T: ~const Foo + Bar + Bar>() { + | +++++ -error[E0015]: cannot call non-const fn `<T as Foo>::b` in constant functions - --> $DIR/trait-where-clause-const.rs:29:5 +error[E0277]: the trait bound `T: ~const Bar` is not satisfied + --> $DIR/trait-where-clause-const.rs:23:12 | -LL | T::b(); - | ^^^^^^ +LL | T::c::<T>(); + | ^ the trait `Bar` is not implemented for `T` | - = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants - -error[E0015]: cannot call non-const fn `<T as Foo>::c::<T>` in constant functions - --> $DIR/trait-where-clause-const.rs:30:5 +note: required by a bound in `Foo::c` + --> $DIR/trait-where-clause-const.rs:16:13 | -LL | T::c::<T>(); - | ^^^^^^^^^^^ +LL | fn c<T: ~const Bar>(); + | ^^^^^^^^^^ required by this bound in `Foo::c` +help: consider further restricting this bound | - = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants +LL | const fn test1<T: ~const Foo + Bar + Bar>() { + | +++++ -error: aborting due to 6 previous errors +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0015`. +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/trait-where-clause-run.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/trait-where-clause-run.rs index 6e1074035b7..5439f859a03 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/trait-where-clause-run.rs +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/trait-where-clause-run.rs @@ -1,5 +1,4 @@ -// known-bug: #110395 -// FIXME run-pass +// run-pass #![feature(const_trait_impl, effects)] diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/trait-where-clause-run.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/trait-where-clause-run.stderr deleted file mode 100644 index b353c622b55..00000000000 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/trait-where-clause-run.stderr +++ /dev/null @@ -1,11 +0,0 @@ -error[E0015]: cannot call non-const fn `<Self as Bar>::bar` in constant functions - --> $DIR/trait-where-clause-run.rs:14:9 - | -LL | <Self as Bar>::bar() * 6 - | ^^^^^^^^^^^^^^^^^^^^ - | - = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0015`. diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/trait-where-clause-self-referential.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/trait-where-clause-self-referential.rs index 32ebe03435d..c578813b846 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/trait-where-clause-self-referential.rs +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/trait-where-clause-self-referential.rs @@ -1,7 +1,6 @@ -// known-bug: #110395 -// FIXME check-pass +// check-pass -#![feature(const_trait_impl)] +#![feature(const_trait_impl, effects)] #[const_trait] trait Foo { diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/trait-where-clause-self-referential.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/trait-where-clause-self-referential.stderr deleted file mode 100644 index 7356fbd9267..00000000000 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/trait-where-clause-self-referential.stderr +++ /dev/null @@ -1,11 +0,0 @@ -error[E0015]: cannot call non-const fn `<T as Foo>::bar` in constant functions - --> $DIR/trait-where-clause-self-referential.rs:22:5 - | -LL | T::bar(); - | ^^^^^^^^ - | - = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0015`. diff --git a/tests/ui/std/slice-from-array-issue-113238.rs b/tests/ui/std/slice-from-array-issue-113238.rs new file mode 100644 index 00000000000..e9e1bfb8db3 --- /dev/null +++ b/tests/ui/std/slice-from-array-issue-113238.rs @@ -0,0 +1,9 @@ +// check-pass + +// This intends to use the unsizing coercion from array to slice, but it only +// works if we resolve `<&[u8]>::from` as the reflexive `From<T> for T`. In +// #113238, we found that gimli had added its own `From<EndianSlice> for &[u8]` +// that affected all `std/backtrace` users. +fn main() { + let _ = <&[u8]>::from(&[]); +} diff --git a/tests/ui/suggestions/issue-71394-no-from-impl.stderr b/tests/ui/suggestions/issue-71394-no-from-impl.stderr index 004f1c1622b..80be252a0a5 100644 --- a/tests/ui/suggestions/issue-71394-no-from-impl.stderr +++ b/tests/ui/suggestions/issue-71394-no-from-impl.stderr @@ -13,7 +13,7 @@ LL | let _: &[i8] = data.into(); <[T; 4] as From<(T, T, T, T)>> <[T; 5] as From<(T, T, T, T, T)>> <[T; 6] as From<(T, T, T, T, T, T)>> - and 7 others + and 6 others = note: required for `&[u8]` to implement `Into<&[i8]>` error: aborting due to previous error diff --git a/tests/ui/target-feature/gate.rs b/tests/ui/target-feature/gate.rs index 3ebd2dbceaa..782444417a8 100644 --- a/tests/ui/target-feature/gate.rs +++ b/tests/ui/target-feature/gate.rs @@ -17,6 +17,7 @@ // gate-test-ermsb_target_feature // gate-test-bpf_target_feature // gate-test-aarch64_ver_target_feature +// gate-test-csky_target_feature #[target_feature(enable = "avx512bw")] //~^ ERROR: currently unstable diff --git a/tests/ui/target-feature/gate.stderr b/tests/ui/target-feature/gate.stderr index 896212e42fc..f56efb3bb83 100644 --- a/tests/ui/target-feature/gate.stderr +++ b/tests/ui/target-feature/gate.stderr @@ -1,5 +1,5 @@ error[E0658]: the target feature `avx512bw` is currently unstable - --> $DIR/gate.rs:21:18 + --> $DIR/gate.rs:22:18 | LL | #[target_feature(enable = "avx512bw")] | ^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/traits/issue-105231.rs b/tests/ui/traits/issue-105231.rs index 74c7afd6b9e..bb2b13664ba 100644 --- a/tests/ui/traits/issue-105231.rs +++ b/tests/ui/traits/issue-105231.rs @@ -1,9 +1,9 @@ -//~ ERROR overflow evaluating the requirement `A<A<A<A<A<A<A<...>>>>>>>: Send` struct A<T>(B<T>); //~^ ERROR recursive types `A` and `B` have infinite size struct B<T>(A<A<T>>); trait Foo {} impl<T> Foo for T where T: Send {} +//~^ ERROR overflow evaluating the requirement `A<A<A<A<A<A<A<...>>>>>>>: Send` impl Foo for B<u8> {} fn main() {} diff --git a/tests/ui/traits/issue-105231.stderr b/tests/ui/traits/issue-105231.stderr index fe20c47c57a..76a71067353 100644 --- a/tests/ui/traits/issue-105231.stderr +++ b/tests/ui/traits/issue-105231.stderr @@ -1,5 +1,5 @@ error[E0072]: recursive types `A` and `B` have infinite size - --> $DIR/issue-105231.rs:2:1 + --> $DIR/issue-105231.rs:1:1 | LL | struct A<T>(B<T>); | ^^^^^^^^^^^ ---- recursive without indirection @@ -15,10 +15,14 @@ LL ~ struct B<T>(Box<A<A<T>>>); | error[E0275]: overflow evaluating the requirement `A<A<A<A<A<A<A<...>>>>>>>: Send` + --> $DIR/issue-105231.rs:5:28 + | +LL | impl<T> Foo for T where T: Send {} + | ^^^^ | = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`issue_105231`) note: required because it appears within the type `B<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<A<u8>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>` - --> $DIR/issue-105231.rs:4:8 + --> $DIR/issue-105231.rs:3:8 | LL | struct B<T>(A<A<T>>); | ^ diff --git a/tests/ui/traits/solver-cycles/cycle-via-builtin-auto-trait-impl.rs b/tests/ui/traits/solver-cycles/cycle-via-builtin-auto-trait-impl.rs index d37943b929a..206ab07898b 100644 --- a/tests/ui/traits/solver-cycles/cycle-via-builtin-auto-trait-impl.rs +++ b/tests/ui/traits/solver-cycles/cycle-via-builtin-auto-trait-impl.rs @@ -1,4 +1,3 @@ -//~ ERROR overflow // A regression test for #111729 checking that we correctly // track recursion depth for obligations returned by confirmation. use std::panic::RefUnwindSafe; @@ -15,6 +14,7 @@ struct RootDatabase { } impl<T: RefUnwindSafe> Database for T { + //~^ ERROR overflow type Storage = SalsaStorage; } impl Database for RootDatabase { diff --git a/tests/ui/traits/solver-cycles/cycle-via-builtin-auto-trait-impl.stderr b/tests/ui/traits/solver-cycles/cycle-via-builtin-auto-trait-impl.stderr index 8f9ce3ef1e9..4123a8199a0 100644 --- a/tests/ui/traits/solver-cycles/cycle-via-builtin-auto-trait-impl.stderr +++ b/tests/ui/traits/solver-cycles/cycle-via-builtin-auto-trait-impl.stderr @@ -1,13 +1,17 @@ error[E0275]: overflow evaluating the requirement `Runtime<RootDatabase>: RefUnwindSafe` + --> $DIR/cycle-via-builtin-auto-trait-impl.rs:16:9 + | +LL | impl<T: RefUnwindSafe> Database for T { + | ^^^^^^^^^^^^^ | = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`cycle_via_builtin_auto_trait_impl`) note: required because it appears within the type `RootDatabase` - --> $DIR/cycle-via-builtin-auto-trait-impl.rs:13:8 + --> $DIR/cycle-via-builtin-auto-trait-impl.rs:12:8 | LL | struct RootDatabase { | ^^^^^^^^^^^^ note: required for `RootDatabase` to implement `Database` - --> $DIR/cycle-via-builtin-auto-trait-impl.rs:17:24 + --> $DIR/cycle-via-builtin-auto-trait-impl.rs:16:24 | LL | impl<T: RefUnwindSafe> Database for T { | ------------- ^^^^^^^^ ^ diff --git a/tests/ui/traits/trait-upcasting/type-checking-test-1.stderr b/tests/ui/traits/trait-upcasting/type-checking-test-1.current.stderr index 82b4e9bd72a..d48d9b89d1d 100644 --- a/tests/ui/traits/trait-upcasting/type-checking-test-1.stderr +++ b/tests/ui/traits/trait-upcasting/type-checking-test-1.current.stderr @@ -1,5 +1,5 @@ error[E0605]: non-primitive cast: `&dyn Foo` as `&dyn Bar<_>` - --> $DIR/type-checking-test-1.rs:16:13 + --> $DIR/type-checking-test-1.rs:19:13 | LL | let _ = x as &dyn Bar<_>; // Ambiguous | ^^^^^^^^^^^^^^^^ invalid cast @@ -10,7 +10,7 @@ LL | let _ = &x as &dyn Bar<_>; // Ambiguous | + error[E0277]: the trait bound `&dyn Foo: Bar<_>` is not satisfied - --> $DIR/type-checking-test-1.rs:16:13 + --> $DIR/type-checking-test-1.rs:19:13 | LL | let _ = x as &dyn Bar<_>; // Ambiguous | ^ the trait `Bar<_>` is not implemented for `&dyn Foo` diff --git a/tests/ui/traits/trait-upcasting/type-checking-test-1.next.stderr b/tests/ui/traits/trait-upcasting/type-checking-test-1.next.stderr new file mode 100644 index 00000000000..b612005fcb0 --- /dev/null +++ b/tests/ui/traits/trait-upcasting/type-checking-test-1.next.stderr @@ -0,0 +1,9 @@ +error[E0605]: non-primitive cast: `&dyn Foo` as `&dyn Bar<_>` + --> $DIR/type-checking-test-1.rs:19:13 + | +LL | let _ = x as &dyn Bar<_>; // Ambiguous + | ^^^^^^^^^^^^^^^^ an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0605`. diff --git a/tests/ui/traits/trait-upcasting/type-checking-test-1.rs b/tests/ui/traits/trait-upcasting/type-checking-test-1.rs index 6bc9f4a75d3..7c7beec0809 100644 --- a/tests/ui/traits/trait-upcasting/type-checking-test-1.rs +++ b/tests/ui/traits/trait-upcasting/type-checking-test-1.rs @@ -1,3 +1,6 @@ +// revisions: current next +//[next] compile-flags: -Ztrait-solver=next + #![feature(trait_upcasting)] trait Foo: Bar<i32> + Bar<u32> {} @@ -15,7 +18,7 @@ fn test_specific(x: &dyn Foo) { fn test_unknown_version(x: &dyn Foo) { let _ = x as &dyn Bar<_>; // Ambiguous //~^ ERROR non-primitive cast - //~^^ ERROR the trait bound `&dyn Foo: Bar<_>` is not satisfied + //[current]~^^ ERROR the trait bound `&dyn Foo: Bar<_>` is not satisfied } fn test_infer_version(x: &dyn Foo) { diff --git a/tests/ui/type-alias-impl-trait/coherence.rs b/tests/ui/type-alias-impl-trait/coherence.rs index 077a31494a9..1700c800e31 100644 --- a/tests/ui/type-alias-impl-trait/coherence.rs +++ b/tests/ui/type-alias-impl-trait/coherence.rs @@ -11,7 +11,7 @@ fn use_alias<T>(val: T) -> AliasOfForeignType<T> { foreign_crate::ForeignType(val) } -impl<T> foreign_crate::ForeignTrait for AliasOfForeignType<T> {} +impl foreign_crate::ForeignTrait for AliasOfForeignType<()> {} //~^ ERROR only traits defined in the current crate can be implemented for arbitrary types fn main() {} diff --git a/tests/ui/type-alias-impl-trait/coherence.stderr b/tests/ui/type-alias-impl-trait/coherence.stderr index c923eb08ab3..36bbb985ef0 100644 --- a/tests/ui/type-alias-impl-trait/coherence.stderr +++ b/tests/ui/type-alias-impl-trait/coherence.stderr @@ -1,10 +1,10 @@ error[E0117]: only traits defined in the current crate can be implemented for arbitrary types --> $DIR/coherence.rs:14:1 | -LL | impl<T> foreign_crate::ForeignTrait for AliasOfForeignType<T> {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--------------------- - | | | - | | `AliasOfForeignType<T>` is not defined in the current crate +LL | impl foreign_crate::ForeignTrait for AliasOfForeignType<()> {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---------------------- + | | | + | | `AliasOfForeignType<()>` is not defined in the current crate | impl doesn't use only types from inside the current crate | = note: define and implement a trait or new type instead diff --git a/tests/ui/type-alias-impl-trait/coherence_generalization.rs b/tests/ui/type-alias-impl-trait/coherence_generalization.rs index 679b2b0f188..1ec8877eaeb 100644 --- a/tests/ui/type-alias-impl-trait/coherence_generalization.rs +++ b/tests/ui/type-alias-impl-trait/coherence_generalization.rs @@ -2,6 +2,7 @@ // FIXME(type_alias_impl_trait): What does this test? This needs a comment // explaining what we're worried about here. + #![feature(type_alias_impl_trait)] trait Trait {} type Opaque<T> = impl Sized; @@ -9,7 +10,7 @@ fn foo<T>() -> Opaque<T> { () } -impl<T, V> Trait for (T, V, V, u32) {} -impl<U, V> Trait for (Opaque<U>, V, i32, V) {} +impl<T, U, V> Trait for (T, U, V, V, u32) {} +impl<U, V> Trait for (Opaque<U>, U, V, i32, V) {} fn main() {} diff --git a/tests/ui/type-alias-impl-trait/unconstrained-impl-param.rs b/tests/ui/type-alias-impl-trait/unconstrained-impl-param.rs new file mode 100644 index 00000000000..b3510067047 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/unconstrained-impl-param.rs @@ -0,0 +1,25 @@ +#![feature(type_alias_impl_trait)] + +use std::fmt::Display; + +type Opaque<X> = impl Sized + 'static; +fn define<X>() -> Opaque<X> {} + +trait Trait { + type Assoc: Display; +} +impl<'a> Trait for Opaque<&'a str> { + //~^ ERROR the lifetime parameter `'a` is not constrained by the impl trait, self type, or predicates + type Assoc = &'a str; +} + +// ======= Exploit ======= + +fn extend<T: Trait + 'static>(s: T::Assoc) -> Box<dyn Display> { + Box::new(s) +} + +fn main() { + let val = extend::<Opaque<&'_ str>>(&String::from("blah blah blah")); + println!("{}", val); +} diff --git a/tests/ui/type-alias-impl-trait/unconstrained-impl-param.stderr b/tests/ui/type-alias-impl-trait/unconstrained-impl-param.stderr new file mode 100644 index 00000000000..65139307f8e --- /dev/null +++ b/tests/ui/type-alias-impl-trait/unconstrained-impl-param.stderr @@ -0,0 +1,9 @@ +error[E0207]: the lifetime parameter `'a` is not constrained by the impl trait, self type, or predicates + --> $DIR/unconstrained-impl-param.rs:11:6 + | +LL | impl<'a> Trait for Opaque<&'a str> { + | ^^ unconstrained lifetime parameter + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0207`. |
