From 9a819ab8f7f69b5461d0a9a7f8b57f976de1ae2e Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 5 Nov 2023 16:58:47 +0100 Subject: [PATCH 01/12] static mut: allow reference to arbitrary types, not just slices and arrays --- .../src/transform/check_consts/check.rs | 40 ++++++++----------- .../check-static-mut-slices.rs | 15 ------- tests/ui/consts/const-address-of-mut.rs | 2 - tests/ui/consts/const-address-of-mut.stderr | 14 +------ .../mutable_references_err.32bit.stderr | 10 ----- .../mutable_references_err.64bit.stderr | 10 ----- tests/ui/consts/static-mut-refs.rs | 24 +++++++++++ .../consts/static_mut_containing_mut_ref2.rs | 2 +- ...tatic_mut_containing_mut_ref2.stock.stderr | 6 +-- 9 files changed, 46 insertions(+), 77 deletions(-) delete mode 100644 tests/ui/array-slice-vec/check-static-mut-slices.rs create mode 100644 tests/ui/consts/static-mut-refs.rs 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 89c65d9232586..b5ea6c90e0c51 100644 --- a/compiler/rustc_const_eval/src/transform/check_consts/check.rs +++ b/compiler/rustc_const_eval/src/transform/check_consts/check.rs @@ -476,35 +476,27 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> { } } - Rvalue::Ref(_, BorrowKind::Mut { .. }, place) => { - let ty = place.ty(self.body, self.tcx).ty; - let is_allowed = match ty.kind() { - // Inside a `static mut`, `&mut [...]` is allowed. - ty::Array(..) | ty::Slice(_) - if self.const_kind() == hir::ConstContext::Static(hir::Mutability::Mut) => - { - true - } - - // FIXME(ecstaticmorse): We could allow `&mut []` inside a const context given - // that this is merely a ZST and it is already eligible for promotion. - // This may require an RFC? - /* - ty::Array(_, len) if len.try_eval_target_usize(cx.tcx, cx.param_env) == Some(0) - => true, - */ - _ => false, - }; + Rvalue::Ref(_, BorrowKind::Mut { .. }, place) + | Rvalue::AddressOf(Mutability::Mut, place) => { + // Inside mutable statics, we allow arbitrary mutable references. + // We've allowed `static mut FOO = &mut [elements];` for a long time (the exact + // reasons why are lost to history), and there is no reason to restrict that to + // arrays and slices. + let is_allowed = + self.const_kind() == hir::ConstContext::Static(hir::Mutability::Mut); if !is_allowed { - self.check_mut_borrow(place.local, hir::BorrowKind::Ref) + self.check_mut_borrow( + place.local, + if matches!(rvalue, Rvalue::Ref(..)) { + hir::BorrowKind::Ref + } else { + hir::BorrowKind::Raw + }, + ); } } - Rvalue::AddressOf(Mutability::Mut, place) => { - self.check_mut_borrow(place.local, hir::BorrowKind::Raw) - } - Rvalue::Ref(_, BorrowKind::Shared | BorrowKind::Fake, place) | Rvalue::AddressOf(Mutability::Not, place) => { let borrowed_place_has_mut_interior = qualifs::in_place::( diff --git a/tests/ui/array-slice-vec/check-static-mut-slices.rs b/tests/ui/array-slice-vec/check-static-mut-slices.rs deleted file mode 100644 index b89c634036e31..0000000000000 --- a/tests/ui/array-slice-vec/check-static-mut-slices.rs +++ /dev/null @@ -1,15 +0,0 @@ -// run-pass -#![allow(dead_code)] - -// Checks that mutable static items can have mutable slices - - -static mut TEST: &'static mut [isize] = &mut [1]; -static mut EMPTY: &'static mut [isize] = &mut []; - -pub fn main() { - unsafe { - TEST[0] += 1; - assert_eq!(TEST[0], 2); - } -} diff --git a/tests/ui/consts/const-address-of-mut.rs b/tests/ui/consts/const-address-of-mut.rs index 5f0c76d628555..0018bf18e419b 100644 --- a/tests/ui/consts/const-address-of-mut.rs +++ b/tests/ui/consts/const-address-of-mut.rs @@ -4,8 +4,6 @@ const A: () = { let mut x = 2; &raw mut x; }; //~ mutable pointer static B: () = { let mut x = 2; &raw mut x; }; //~ mutable pointer -static mut C: () = { let mut x = 2; &raw mut x; }; //~ mutable pointer - const fn foo() { let mut x = 0; let y = &raw mut x; //~ mutable pointer diff --git a/tests/ui/consts/const-address-of-mut.stderr b/tests/ui/consts/const-address-of-mut.stderr index 1b371fcee984b..95a91ff463f69 100644 --- a/tests/ui/consts/const-address-of-mut.stderr +++ b/tests/ui/consts/const-address-of-mut.stderr @@ -18,18 +18,8 @@ LL | static B: () = { let mut x = 2; &raw mut x; }; = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0658]: raw mutable pointers are not allowed in statics - --> $DIR/const-address-of-mut.rs:7:37 - | -LL | static mut C: () = { let mut x = 2; &raw mut x; }; - | ^^^^^^^^^^ - | - = note: see issue #57349 for more information - = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - error[E0658]: raw mutable pointers are not allowed in constant functions - --> $DIR/const-address-of-mut.rs:11:13 + --> $DIR/const-address-of-mut.rs:9:13 | LL | let y = &raw mut x; | ^^^^^^^^^^ @@ -38,6 +28,6 @@ LL | let y = &raw mut x; = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error: aborting due to 4 previous errors +error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/consts/miri_unleashed/mutable_references_err.32bit.stderr b/tests/ui/consts/miri_unleashed/mutable_references_err.32bit.stderr index 2df80020fdc91..4793466a98784 100644 --- a/tests/ui/consts/miri_unleashed/mutable_references_err.32bit.stderr +++ b/tests/ui/consts/miri_unleashed/mutable_references_err.32bit.stderr @@ -133,11 +133,6 @@ help: skipping check for `const_mut_refs` feature | LL | static mut MUT_TO_READONLY: &mut i32 = unsafe { &mut *(&READONLY as *const _ as *mut _) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -help: skipping check that does not even have a feature gate - --> $DIR/mutable_references_err.rs:40:49 - | -LL | static mut MUT_TO_READONLY: &mut i32 = unsafe { &mut *(&READONLY as *const _ as *mut _) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: skipping check that does not even have a feature gate --> $DIR/mutable_references_err.rs:47:44 | @@ -148,11 +143,6 @@ help: skipping check that does not even have a feature gate | LL | const POINTS_TO_MUTABLE1: &i32 = unsafe { &MUTABLE }; | ^^^^^^^ -help: skipping check that does not even have a feature gate - --> $DIR/mutable_references_err.rs:50:36 - | -LL | static mut MUTABLE_REF: &mut i32 = &mut 42; - | ^^^^^^^ help: skipping check that does not even have a feature gate --> $DIR/mutable_references_err.rs:51:45 | diff --git a/tests/ui/consts/miri_unleashed/mutable_references_err.64bit.stderr b/tests/ui/consts/miri_unleashed/mutable_references_err.64bit.stderr index 3ff6811ea61fb..f5f7b605c9416 100644 --- a/tests/ui/consts/miri_unleashed/mutable_references_err.64bit.stderr +++ b/tests/ui/consts/miri_unleashed/mutable_references_err.64bit.stderr @@ -133,11 +133,6 @@ help: skipping check for `const_mut_refs` feature | LL | static mut MUT_TO_READONLY: &mut i32 = unsafe { &mut *(&READONLY as *const _ as *mut _) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -help: skipping check that does not even have a feature gate - --> $DIR/mutable_references_err.rs:40:49 - | -LL | static mut MUT_TO_READONLY: &mut i32 = unsafe { &mut *(&READONLY as *const _ as *mut _) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: skipping check that does not even have a feature gate --> $DIR/mutable_references_err.rs:47:44 | @@ -148,11 +143,6 @@ help: skipping check that does not even have a feature gate | LL | const POINTS_TO_MUTABLE1: &i32 = unsafe { &MUTABLE }; | ^^^^^^^ -help: skipping check that does not even have a feature gate - --> $DIR/mutable_references_err.rs:50:36 - | -LL | static mut MUTABLE_REF: &mut i32 = &mut 42; - | ^^^^^^^ help: skipping check that does not even have a feature gate --> $DIR/mutable_references_err.rs:51:45 | diff --git a/tests/ui/consts/static-mut-refs.rs b/tests/ui/consts/static-mut-refs.rs new file mode 100644 index 0000000000000..ff865da5aa861 --- /dev/null +++ b/tests/ui/consts/static-mut-refs.rs @@ -0,0 +1,24 @@ +// run-pass +#![allow(dead_code)] + +// Checks that mutable static items can have mutable slices and other references + + +static mut TEST: &'static mut [isize] = &mut [1]; +static mut EMPTY: &'static mut [isize] = &mut []; +static mut INT: &'static mut isize = &mut 1; + +// And the same for raw pointers. + +static mut TEST_RAW: *mut [isize] = &mut [1isize] as *mut _; +static mut EMPTY_RAW: *mut [isize] = &mut [] as *mut _; +static mut INT_RAW: *mut isize = &mut 1isize as *mut _; + +pub fn main() { + unsafe { + TEST[0] += 1; + assert_eq!(TEST[0], 2); + *INT_RAW += 1; + assert_eq!(*INT_RAW, 2); + } +} diff --git a/tests/ui/consts/static_mut_containing_mut_ref2.rs b/tests/ui/consts/static_mut_containing_mut_ref2.rs index fa79a78eab424..b71f1122cd00c 100644 --- a/tests/ui/consts/static_mut_containing_mut_ref2.rs +++ b/tests/ui/consts/static_mut_containing_mut_ref2.rs @@ -7,7 +7,7 @@ static mut STDERR_BUFFER_SPACE: u8 = 0; pub static mut STDERR_BUFFER: () = unsafe { *(&mut STDERR_BUFFER_SPACE) = 42; //[mut_refs]~^ ERROR could not evaluate static initializer - //[stock]~^^ ERROR mutable references are not allowed in statics + //[stock]~^^ ERROR mutation through a reference is not allowed in statics //[mut_refs]~^^^ WARN mutable reference of mutable static is discouraged [static_mut_ref] //[stock]~^^^^ WARN mutable reference of mutable static is discouraged [static_mut_ref] }; diff --git a/tests/ui/consts/static_mut_containing_mut_ref2.stock.stderr b/tests/ui/consts/static_mut_containing_mut_ref2.stock.stderr index e9fe82d2f87a6..aea5b8a33b54c 100644 --- a/tests/ui/consts/static_mut_containing_mut_ref2.stock.stderr +++ b/tests/ui/consts/static_mut_containing_mut_ref2.stock.stderr @@ -13,11 +13,11 @@ help: mutable references are dangerous since if there's any other pointer or ref LL | *addr_of_mut!(STDERR_BUFFER_SPACE) = 42; | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -error[E0658]: mutable references are not allowed in statics - --> $DIR/static_mut_containing_mut_ref2.rs:8:6 +error[E0658]: mutation through a reference is not allowed in statics + --> $DIR/static_mut_containing_mut_ref2.rs:8:5 | LL | *(&mut STDERR_BUFFER_SPACE) = 42; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: see issue #57349 for more information = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable From c94bbb24db36726a2931ae9df114581b2e76f283 Mon Sep 17 00:00:00 2001 From: LegionMammal978 Date: Thu, 8 Feb 2024 22:59:36 -0500 Subject: [PATCH 02/12] Clarify that atomic and regular integers can differ in alignment The documentation for atomic integers says that they have the "same in-memory representation" as their underlying integers. This might be misconstrued as implying that they have the same layout. Therefore, clarify that atomic integers' alignment is equal to their size. --- library/core/src/sync/atomic.rs | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/library/core/src/sync/atomic.rs b/library/core/src/sync/atomic.rs index ad8c70c6a3ca3..d9654973b84ed 100644 --- a/library/core/src/sync/atomic.rs +++ b/library/core/src/sync/atomic.rs @@ -2119,7 +2119,16 @@ macro_rules! atomic_int { /// This type has the same in-memory representation as the underlying /// integer type, [` #[doc = $s_int_type] - /// `]. For more about the differences between atomic types and + /// `]. + #[doc = if_not_8_bit! { + $int_type, + concat!( + "However, the alignment of this type is always equal to its ", + "size, even on targets where [`", $s_int_type, "`] has a ", + "lesser alignment." + ) + }] + /// For more about the differences between atomic types and /// non-atomic types as well as information about the portability of /// this type, please see the [module-level documentation]. /// From 74481b39d5b9329f94b90fa065ddd0c32856855b Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Fri, 2 Feb 2024 13:26:18 -0800 Subject: [PATCH 03/12] wasm: Store rlib metadata in wasm object files The goal of this commit is to remove warnings using LLVM tip-of-tree `wasm-ld`. In llvm/llvm-project#78658 the `wasm-ld` LLD driver no longer looks at archive indices and instead looks at all the objects in archives. Previously `lib.rmeta` files were simply raw rustc metadata bytes, not wasm objects, meaning that `wasm-ld` would emit a warning indicating so. WebAssembly targets previously passed `--fatal-warnings` to `wasm-ld` by default which meant that if Rust were to update to LLVM 18 then all wasm targets would not work. This immediate blocker was resolved in rust-lang/rust#120278 which removed `--fatal-warnings` which enabled a theoretical update to LLVM 18 for wasm targets. This current state is ok-enough for now because rustc squashes all linker output by default if it doesn't fail. This means, for example, that rustc squashes all the linker warnings coming out of `wasm-ld` about `lib.rmeta` files with LLVM 18. This again isn't a pressing issue because the information is all hidden, but it runs the risk of being annoying if another linker error were to happen and then the output would have all these unrelated warnings that couldn't be fixed. Thus, this PR comes into the picture. The goal of this PR is to resolve these warnings by using the WebAssembly object file format on wasm targets instead of using raw rustc metadata. When I first implemented the rlib-in-objects scheme in #84449 I remember either concluding that `wasm-ld` would either include the metadata in the output or I thought we didn't have to do anything there at all. I think I was wrong on both counts as `wasm-ld` does not include the metadata in the final output unless the object is referenced and we do actually need to do something to resolve these warnings. This PR updates the object file format containing rustc metadata on WebAssembly targets to be an actual WebAssembly file. This enables the `wasm` feature of the `object` crate to be able to read the custom section in the same manner as other platforms, but currently `object` doesn't support writing wasm object files so a handwritten encoder is used instead. The only caveat I know of with this is that if `wasm-ld` does indeed look at the object file then the metadata will be included in the final output. I believe the only thing that could cause that at this time is `--whole-archive` which I don't think is passed for rlibs. I would clarify that I'm not 100% certain about this, however. --- Cargo.lock | 11 +++ compiler/rustc_codegen_ssa/Cargo.toml | 2 +- .../rustc_codegen_ssa/src/back/metadata.rs | 88 ++++++++++++++----- src/tools/tidy/src/deps.rs | 17 ++++ 4 files changed, 97 insertions(+), 21 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 29c8c7ef00404..c28479b64d70e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2608,6 +2608,7 @@ dependencies = [ "rustc-std-workspace-alloc", "rustc-std-workspace-core", "ruzstd", + "wasmparser", ] [[package]] @@ -6035,6 +6036,16 @@ version = "0.2.87" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ca6ad05a4870b2bf5fe995117d3728437bd27d7cd5f06f13c17443ef369775a1" +[[package]] +name = "wasmparser" +version = "0.118.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95ee9723b928e735d53000dec9eae7b07a60e490c85ab54abb66659fc61bfcd9" +dependencies = [ + "indexmap", + "semver", +] + [[package]] name = "web-sys" version = "0.3.61" diff --git a/compiler/rustc_codegen_ssa/Cargo.toml b/compiler/rustc_codegen_ssa/Cargo.toml index 7d2f5bb193a39..335a6f244f9b5 100644 --- a/compiler/rustc_codegen_ssa/Cargo.toml +++ b/compiler/rustc_codegen_ssa/Cargo.toml @@ -48,7 +48,7 @@ libc = "0.2.50" [dependencies.object] version = "0.32.1" default-features = false -features = ["read_core", "elf", "macho", "pe", "xcoff", "unaligned", "archive", "write"] +features = ["read_core", "elf", "macho", "pe", "xcoff", "unaligned", "archive", "write", "wasm"] [target.'cfg(windows)'.dependencies.windows] version = "0.48.0" diff --git a/compiler/rustc_codegen_ssa/src/back/metadata.rs b/compiler/rustc_codegen_ssa/src/back/metadata.rs index b683e1b45a8d1..8e76e47cfefca 100644 --- a/compiler/rustc_codegen_ssa/src/back/metadata.rs +++ b/compiler/rustc_codegen_ssa/src/back/metadata.rs @@ -15,6 +15,7 @@ use rustc_data_structures::owned_slice::{try_slice_owned, OwnedSlice}; use rustc_metadata::creader::MetadataLoader; use rustc_metadata::fs::METADATA_FILENAME; use rustc_metadata::EncodedMetadata; +use rustc_serialize::leb128; use rustc_session::Session; use rustc_span::sym; use rustc_target::abi::Endian; @@ -420,10 +421,9 @@ pub enum MetadataPosition { /// it's not in an allowlist of otherwise well known dwarf section names to /// go into the final artifact. /// -/// * WebAssembly - we actually don't have any container format for this -/// target. WebAssembly doesn't support the `dylib` crate type anyway so -/// there's no need for us to support this at this time. Consequently the -/// metadata bytes are simply stored as-is into an rlib. +/// * WebAssembly - this uses wasm files themselves as the object file format +/// so an empty file with no linking metadata but a single custom section is +/// created holding our metadata. /// /// * COFF - Windows-like targets create an object with a section that has /// the `IMAGE_SCN_LNK_REMOVE` flag set which ensures that if the linker @@ -438,22 +438,13 @@ pub fn create_wrapper_file( data: &[u8], ) -> (Vec, MetadataPosition) { let Some(mut file) = create_object_file(sess) else { - // This is used to handle all "other" targets. This includes targets - // in two categories: - // - // * Some targets don't have support in the `object` crate just yet - // to write an object file. These targets are likely to get filled - // out over time. - // - // * Targets like WebAssembly don't support dylibs, so the purpose - // of putting metadata in object files, to support linking rlibs - // into dylibs, is moot. - // - // In both of these cases it means that linking into dylibs will - // not be supported by rustc. This doesn't matter for targets like - // WebAssembly and for targets not supported by the `object` crate - // yet it means that work will need to be done in the `object` crate - // to add a case above. + if sess.target.is_like_wasm { + return (create_metadata_file_for_wasm(data, §ion_name), MetadataPosition::First); + } + + // Targets using this branch don't have support implemented here yet or + // they're not yet implemented in the `object` crate and will likely + // fill out this module over time. return (data.to_vec(), MetadataPosition::Last); }; let section = if file.format() == BinaryFormat::Xcoff { @@ -532,6 +523,9 @@ pub fn create_compressed_metadata_file( packed_metadata.extend(metadata.raw_data()); let Some(mut file) = create_object_file(sess) else { + if sess.target.is_like_wasm { + return create_metadata_file_for_wasm(&packed_metadata, b".rustc"); + } return packed_metadata.to_vec(); }; if file.format() == BinaryFormat::Xcoff { @@ -624,3 +618,57 @@ pub fn create_compressed_metadata_file_for_xcoff( file.append_section_data(section, data, 1); file.write().unwrap() } + +/// Creates a simple WebAssembly object file, which is itself a wasm module, +/// that contains a custom section of the name `section_name` with contents +/// `data`. +/// +/// NB: the `object` crate does not yet have support for writing the the wasm +/// object file format. The format is simple enough that for now an extra crate +/// from crates.io (such as `wasm-encoder`). The file format is: +/// +/// * 4-byte header "\0asm" +/// * 4-byte version number - 1u32 in little-endian format +/// * concatenated sections, which for this object is always "custom sections" +/// +/// Custom sections are then defined by: +/// * 1-byte section identifier - 0 for a custom section +/// * leb-encoded section length (size of the contents beneath this bullet) +/// * leb-encoded custom section name length +/// * custom section name +/// * section contents +/// +/// One custom section, `linking`, is added here in accordance with +/// +/// which is required to inform LLD that this is an object file but it should +/// otherwise basically ignore it if it otherwise looks at it. The linking +/// section currently is defined by a single version byte (2) and then further +/// sections, but we have no more sections, so it's just the byte "2". +/// +/// The next custom section is the one we're interested in. +pub fn create_metadata_file_for_wasm(data: &[u8], section_name: &[u8]) -> Vec { + let mut bytes = b"\0asm\x01\0\0\0".to_vec(); + + let mut append_custom_section = |section_name: &[u8], data: &[u8]| { + let mut section_name_len = [0; leb128::max_leb128_len::()]; + let off = leb128::write_usize_leb128(&mut section_name_len, section_name.len()); + let section_name_len = §ion_name_len[..off]; + + let mut section_len = [0; leb128::max_leb128_len::()]; + let off = leb128::write_usize_leb128( + &mut section_len, + data.len() + section_name_len.len() + section_name.len(), + ); + let section_len = §ion_len[..off]; + + bytes.push(0u8); + bytes.extend_from_slice(section_len); + bytes.extend_from_slice(section_name_len); + bytes.extend_from_slice(section_name); + bytes.extend_from_slice(data); + }; + + append_custom_section(b"linking", &[2]); + append_custom_section(section_name, data); + bytes +} diff --git a/src/tools/tidy/src/deps.rs b/src/tools/tidy/src/deps.rs index acb70328ba210..64d72ca960842 100644 --- a/src/tools/tidy/src/deps.rs +++ b/src/tools/tidy/src/deps.rs @@ -90,6 +90,7 @@ const EXCEPTIONS: ExceptionList = &[ ("ryu", "Apache-2.0 OR BSL-1.0"), // BSL is not acceptble, but we use it under Apache-2.0 // cargo/... (because of serde) ("self_cell", "Apache-2.0"), // rustc (fluent translations) ("snap", "BSD-3-Clause"), // rustc + ("wasmparser", "Apache-2.0 WITH LLVM-exception"), // rustc // tidy-alphabetical-end ]; @@ -375,6 +376,7 @@ const PERMITTED_RUSTC_DEPENDENCIES: &[&str] = &[ "valuable", "version_check", "wasi", + "wasmparser", "winapi", "winapi-i686-pc-windows-gnu", "winapi-util", @@ -559,6 +561,21 @@ fn check_runtime_license_exceptions( if pkg.name == "fortanix-sgx-abi" && pkg.license.as_deref() == Some("MPL-2.0") { continue; } + + // This exception is due to the fact that the feature set of the + // `object` crate is different between rustc and libstd. In the + // standard library only a conservative set of features are enabled + // which notably does not include the `wasm` feature which pulls in + // this dependency. In the compiler, however, the `wasm` feature is + // enabled. This exception is intended to be here so long as the + // `EXCEPTIONS` below contains `wasmparser`, but once that goes away + // this can be removed. + if pkg.name == "wasmparser" + && pkg.license.as_deref() == Some("Apache-2.0 WITH LLVM-exception") + { + continue; + } + tidy_error!(bad, "invalid license `{}` in `{}`", license, pkg.id); } } From 4f3348dbda1062b7d60fc0d2b10b7564c4d6aba1 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Fri, 9 Feb 2024 13:48:58 -0600 Subject: [PATCH 04/12] Update src/tools/tidy/src/deps.rs Co-authored-by: bjorn3 <17426603+bjorn3@users.noreply.github.com> --- src/tools/tidy/src/deps.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/tidy/src/deps.rs b/src/tools/tidy/src/deps.rs index 64d72ca960842..e2c165aff7d29 100644 --- a/src/tools/tidy/src/deps.rs +++ b/src/tools/tidy/src/deps.rs @@ -568,7 +568,7 @@ fn check_runtime_license_exceptions( // which notably does not include the `wasm` feature which pulls in // this dependency. In the compiler, however, the `wasm` feature is // enabled. This exception is intended to be here so long as the - // `EXCEPTIONS` below contains `wasmparser`, but once that goes away + // `EXCEPTIONS` above contains `wasmparser`, but once that goes away // this can be removed. if pkg.name == "wasmparser" && pkg.license.as_deref() == Some("Apache-2.0 WITH LLVM-exception") From bb60ded24b6e4a8dfbcf8533b58c1a35b87bbb8b Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Sat, 10 Feb 2024 09:11:34 +1100 Subject: [PATCH 05/12] Loosen an assertion to account for stashed errors. The meaning of this assertion changed in #120828 when the meaning of `has_errors` changed to exclude stashed errors. Evidently the new meaning is too restrictive. Fixes #120856. --- .../rustc_hir_analysis/src/check/check.rs | 3 ++- tests/ui/typeck/issue-120856.rs | 5 +++++ tests/ui/typeck/issue-120856.stderr | 21 +++++++++++++++++++ 3 files changed, 28 insertions(+), 1 deletion(-) create mode 100644 tests/ui/typeck/issue-120856.rs create mode 100644 tests/ui/typeck/issue-120856.stderr diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs index 50809a571b8dc..7250dc81faf8b 100644 --- a/compiler/rustc_hir_analysis/src/check/check.rs +++ b/compiler/rustc_hir_analysis/src/check/check.rs @@ -1283,7 +1283,8 @@ fn check_type_alias_type_params_are_used<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalD let ty = tcx.type_of(def_id).instantiate_identity(); if ty.references_error() { // If there is already another error, do not emit an error for not using a type parameter. - assert!(tcx.dcx().has_errors().is_some()); + // Without the `stashed_err_count` part this can fail (#120856). + assert!(tcx.dcx().has_errors().is_some() || tcx.dcx().stashed_err_count() > 0); return; } diff --git a/tests/ui/typeck/issue-120856.rs b/tests/ui/typeck/issue-120856.rs new file mode 100644 index 0000000000000..e435a0f9d8e89 --- /dev/null +++ b/tests/ui/typeck/issue-120856.rs @@ -0,0 +1,5 @@ +pub type Archived = ::Archived; +//~^ ERROR failed to resolve: use of undeclared crate or module `m` +//~| ERROR failed to resolve: use of undeclared crate or module `n` + +fn main() {} diff --git a/tests/ui/typeck/issue-120856.stderr b/tests/ui/typeck/issue-120856.stderr new file mode 100644 index 0000000000000..1fc8b20047355 --- /dev/null +++ b/tests/ui/typeck/issue-120856.stderr @@ -0,0 +1,21 @@ +error[E0433]: failed to resolve: use of undeclared crate or module `n` + --> $DIR/issue-120856.rs:1:37 + | +LL | pub type Archived = ::Archived; + | ^ + | | + | use of undeclared crate or module `n` + | help: a trait with a similar name exists: `Fn` + +error[E0433]: failed to resolve: use of undeclared crate or module `m` + --> $DIR/issue-120856.rs:1:25 + | +LL | pub type Archived = ::Archived; + | ^ + | | + | use of undeclared crate or module `m` + | help: a type parameter with a similar name exists: `T` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0433`. From 3d4a9f504780dd8f9ba4e7921cce8d8517c20aa6 Mon Sep 17 00:00:00 2001 From: Ben Kimock Date: Fri, 9 Feb 2024 20:22:15 -0500 Subject: [PATCH 06/12] Turn the "no saved object file in work product" ICE into a translatable fatal error --- compiler/rustc_codegen_ssa/messages.ftl | 2 ++ compiler/rustc_codegen_ssa/src/back/write.rs | 4 +++- compiler/rustc_codegen_ssa/src/errors.rs | 6 ++++++ 3 files changed, 11 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_codegen_ssa/messages.ftl b/compiler/rustc_codegen_ssa/messages.ftl index a80f6a1add099..fa7719d89716e 100644 --- a/compiler/rustc_codegen_ssa/messages.ftl +++ b/compiler/rustc_codegen_ssa/messages.ftl @@ -190,6 +190,8 @@ codegen_ssa_no_module_named = codegen_ssa_no_natvis_directory = error enumerating natvis directory: {$error} +codegen_ssa_no_saved_object_file = cached cgu {$cgu_name} should have an object file, but doesn't + codegen_ssa_processing_dymutil_failed = processing debug info with `dsymutil` failed: {$status} .note = {$output} diff --git a/compiler/rustc_codegen_ssa/src/back/write.rs b/compiler/rustc_codegen_ssa/src/back/write.rs index 9b24339d2551f..a63642d76b976 100644 --- a/compiler/rustc_codegen_ssa/src/back/write.rs +++ b/compiler/rustc_codegen_ssa/src/back/write.rs @@ -913,7 +913,9 @@ fn execute_copy_from_cache_work_item( let object = load_from_incr_comp_dir( cgcx.output_filenames.temp_path(OutputType::Object, Some(&module.name)), - module.source.saved_files.get("o").expect("no saved object file in work product"), + module.source.saved_files.get("o").unwrap_or_else(|| { + cgcx.create_dcx().emit_fatal(errors::NoSavedObjectFile { cgu_name: &module.name }) + }), ); let dwarf_object = module.source.saved_files.get("dwo").as_ref().and_then(|saved_dwarf_object_file| { diff --git a/compiler/rustc_codegen_ssa/src/errors.rs b/compiler/rustc_codegen_ssa/src/errors.rs index 06ea5b9e8f4ab..3d7903b5efb09 100644 --- a/compiler/rustc_codegen_ssa/src/errors.rs +++ b/compiler/rustc_codegen_ssa/src/errors.rs @@ -121,6 +121,12 @@ pub struct NoNatvisDirectory { pub error: Error, } +#[derive(Diagnostic)] +#[diag(codegen_ssa_no_saved_object_file)] +pub struct NoSavedObjectFile<'a> { + pub cgu_name: &'a str, +} + #[derive(Diagnostic)] #[diag(codegen_ssa_copy_path_buf)] pub struct CopyPathBuf { From cf1096eb72e93eeaaed2c8117d68b5798928330b Mon Sep 17 00:00:00 2001 From: Zalathar Date: Sat, 10 Feb 2024 00:40:14 +1100 Subject: [PATCH 07/12] Remove unnecessary `#![feature(min_specialization)]` --- compiler/rustc_codegen_llvm/src/lib.rs | 1 - compiler/rustc_lint/src/lib.rs | 1 - compiler/rustc_lint_defs/src/lib.rs | 2 -- compiler/rustc_passes/src/lib.rs | 1 - 4 files changed, 5 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/lib.rs b/compiler/rustc_codegen_llvm/src/lib.rs index de96bf477adb7..e688e84db61a5 100644 --- a/compiler/rustc_codegen_llvm/src/lib.rs +++ b/compiler/rustc_codegen_llvm/src/lib.rs @@ -13,7 +13,6 @@ #![feature(hash_raw_entry)] #![feature(iter_intersperse)] #![feature(let_chains)] -#![feature(min_specialization)] #![feature(impl_trait_in_assoc_type)] #[macro_use] diff --git a/compiler/rustc_lint/src/lib.rs b/compiler/rustc_lint/src/lib.rs index 5c2a422a2b7c0..5f769e9ad8a5b 100644 --- a/compiler/rustc_lint/src/lib.rs +++ b/compiler/rustc_lint/src/lib.rs @@ -35,7 +35,6 @@ #![feature(iter_order_by)] #![feature(let_chains)] #![feature(trait_upcasting)] -#![feature(min_specialization)] #![feature(rustc_attrs)] #![allow(internal_features)] diff --git a/compiler/rustc_lint_defs/src/lib.rs b/compiler/rustc_lint_defs/src/lib.rs index 8b7e82d2113f8..7ed78a2ffc809 100644 --- a/compiler/rustc_lint_defs/src/lib.rs +++ b/compiler/rustc_lint_defs/src/lib.rs @@ -1,5 +1,3 @@ -#![feature(min_specialization)] - #[macro_use] extern crate rustc_macros; diff --git a/compiler/rustc_passes/src/lib.rs b/compiler/rustc_passes/src/lib.rs index 064af5aec35aa..e795537e84ad7 100644 --- a/compiler/rustc_passes/src/lib.rs +++ b/compiler/rustc_passes/src/lib.rs @@ -10,7 +10,6 @@ #![allow(internal_features)] #![feature(let_chains)] #![feature(map_try_insert)] -#![feature(min_specialization)] #![feature(try_blocks)] #[macro_use] From 973bbfbd23df736dd3a257e42c6cd7e3fe5b0281 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Tue, 6 Feb 2024 19:35:57 +0000 Subject: [PATCH 08/12] No more associated type bounds in dyn trait --- compiler/rustc_ast_lowering/messages.ftl | 6 +- compiler/rustc_ast_lowering/src/errors.rs | 5 +- compiler/rustc_ast_lowering/src/lib.rs | 59 ++------------- .../assoc-type-eq-with-dyn-atb-fail.rs | 2 +- .../assoc-type-eq-with-dyn-atb-fail.stderr | 9 +-- .../bad-universal-in-dyn-in-where-clause.rs | 2 +- ...ad-universal-in-dyn-in-where-clause.stderr | 2 +- .../bad-universal-in-impl-sig.rs | 2 +- .../bad-universal-in-impl-sig.stderr | 2 +- tests/ui/associated-type-bounds/duplicate.rs | 7 -- .../associated-type-bounds/duplicate.stderr | 26 +------ .../dyn-impl-trait-type.rs | 66 ----------------- .../dyn-rpit-and-let.rs | 73 ------------------- tests/ui/associated-type-bounds/elision.rs | 4 +- .../ui/associated-type-bounds/elision.stderr | 15 +--- .../ui/associated-type-bounds/fn-dyn-apit.rs | 61 ---------------- tests/ui/associated-type-bounds/inside-adt.rs | 18 ++--- .../associated-type-bounds/inside-adt.stderr | 18 ++--- .../ui/associated-type-bounds/issue-104916.rs | 2 +- .../issue-104916.stderr | 2 +- .../feature-gate-associated_type_bounds.rs | 11 --- ...feature-gate-associated_type_bounds.stderr | 36 ++------- 22 files changed, 55 insertions(+), 373 deletions(-) delete mode 100644 tests/ui/associated-type-bounds/dyn-impl-trait-type.rs delete mode 100644 tests/ui/associated-type-bounds/dyn-rpit-and-let.rs delete mode 100644 tests/ui/associated-type-bounds/fn-dyn-apit.rs diff --git a/compiler/rustc_ast_lowering/messages.ftl b/compiler/rustc_ast_lowering/messages.ftl index 37e45379ba9a2..9c151ec80eefe 100644 --- a/compiler/rustc_ast_lowering/messages.ftl +++ b/compiler/rustc_ast_lowering/messages.ftl @@ -8,6 +8,9 @@ ast_lowering_arbitrary_expression_in_pattern = ast_lowering_argument = argument +ast_lowering_assoc_ty_binding_in_dyn = + associated type bounds are not allowed in `dyn` types + ast_lowering_assoc_ty_parentheses = parenthesized generic arguments cannot be used in associated type constraints @@ -100,9 +103,6 @@ ast_lowering_match_arm_with_no_body = `match` arm with no body .suggestion = add a body after the pattern -ast_lowering_misplaced_assoc_ty_binding = - associated type bounds are only allowed in where clauses and function signatures, not in {$position} - ast_lowering_misplaced_double_dot = `..` patterns are not allowed here .note = only allowed in tuple, tuple struct, and slice patterns diff --git a/compiler/rustc_ast_lowering/src/errors.rs b/compiler/rustc_ast_lowering/src/errors.rs index 6225358569573..fba8ea206f140 100644 --- a/compiler/rustc_ast_lowering/src/errors.rs +++ b/compiler/rustc_ast_lowering/src/errors.rs @@ -94,11 +94,10 @@ pub struct MisplacedImplTrait<'a> { } #[derive(Diagnostic)] -#[diag(ast_lowering_misplaced_assoc_ty_binding)] -pub struct MisplacedAssocTyBinding<'a> { +#[diag(ast_lowering_assoc_ty_binding_in_dyn)] +pub struct MisplacedAssocTyBinding { #[primary_span] pub span: Span, - pub position: DiagnosticArgFromDisplay<'a>, } #[derive(Diagnostic, Clone, Copy)] diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 4ef9c7607be5e..48cc301219a87 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -1085,33 +1085,13 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } AssocConstraintKind::Bound { bounds } => { enum DesugarKind { - ImplTrait, - Error(ImplTraitPosition), + Error, Bound, } // Piggy-back on the `impl Trait` context to figure out the correct behavior. let desugar_kind = match itctx { - // in an argument, RPIT, or TAIT, if we are within a dyn type: - // - // fn foo(x: dyn Iterator) - // - // then desugar to: - // - // fn foo(x: dyn Iterator) - // - // This is because dyn traits must have all of their associated types specified. - ImplTraitContext::ReturnPositionOpaqueTy { .. } - | ImplTraitContext::TypeAliasesOpaqueTy { .. } - | ImplTraitContext::Universal - if self.is_in_dyn_type => - { - DesugarKind::ImplTrait - } - - ImplTraitContext::Disallowed(position) if self.is_in_dyn_type => { - DesugarKind::Error(position) - } + _ if self.is_in_dyn_type => DesugarKind::Error, // We are in the parameter position, but not within a dyn type: // @@ -1124,32 +1104,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { }; match desugar_kind { - DesugarKind::ImplTrait => { - // Desugar `AssocTy: Bounds` into `AssocTy = impl Bounds`. We do this by - // constructing the HIR for `impl bounds...` and then lowering that. - - let impl_trait_node_id = self.next_node_id(); - // Shift `impl Trait` lifetime captures from the associated type bound's - // node id to the opaque node id, so that the opaque can actually use - // these lifetime bounds. - self.resolver - .remap_extra_lifetime_params(constraint.id, impl_trait_node_id); - - self.with_dyn_type_scope(false, |this| { - let node_id = this.next_node_id(); - let ty = this.lower_ty( - &Ty { - id: node_id, - kind: TyKind::ImplTrait(impl_trait_node_id, bounds.clone()), - span: this.lower_span(constraint.span), - tokens: None, - }, - itctx, - ); - - hir::TypeBindingKind::Equality { term: ty.into() } - }) - } DesugarKind::Bound => { // Desugar `AssocTy: Bounds` into a type binding where the // later desugars into a trait predicate. @@ -1157,11 +1111,10 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { hir::TypeBindingKind::Constraint { bounds } } - DesugarKind::Error(position) => { - let guar = self.dcx().emit_err(errors::MisplacedAssocTyBinding { - span: constraint.span, - position: DiagnosticArgFromDisplay(&position), - }); + DesugarKind::Error => { + let guar = self + .dcx() + .emit_err(errors::MisplacedAssocTyBinding { span: constraint.span }); let err_ty = &*self.arena.alloc(self.ty(constraint.span, hir::TyKind::Err(guar))); hir::TypeBindingKind::Equality { term: err_ty.into() } diff --git a/tests/ui/associated-type-bounds/assoc-type-eq-with-dyn-atb-fail.rs b/tests/ui/associated-type-bounds/assoc-type-eq-with-dyn-atb-fail.rs index 4c36289f47b85..8a580e191869b 100644 --- a/tests/ui/associated-type-bounds/assoc-type-eq-with-dyn-atb-fail.rs +++ b/tests/ui/associated-type-bounds/assoc-type-eq-with-dyn-atb-fail.rs @@ -28,9 +28,9 @@ impl Bar for AssocNoCopy { impl Thing for AssocNoCopy { type Out = Box>; + //~^ ERROR associated type bounds are not allowed in `dyn` types fn func() -> Self::Out { - //~^ ERROR the trait bound `String: Copy` is not satisfied Box::new(AssocNoCopy) } } diff --git a/tests/ui/associated-type-bounds/assoc-type-eq-with-dyn-atb-fail.stderr b/tests/ui/associated-type-bounds/assoc-type-eq-with-dyn-atb-fail.stderr index 7942992874da5..2d38bbd8c923e 100644 --- a/tests/ui/associated-type-bounds/assoc-type-eq-with-dyn-atb-fail.stderr +++ b/tests/ui/associated-type-bounds/assoc-type-eq-with-dyn-atb-fail.stderr @@ -1,9 +1,8 @@ -error[E0277]: the trait bound `String: Copy` is not satisfied - --> $DIR/assoc-type-eq-with-dyn-atb-fail.rs:32:18 +error: associated type bounds are not allowed in `dyn` types + --> $DIR/assoc-type-eq-with-dyn-atb-fail.rs:30:28 | -LL | fn func() -> Self::Out { - | ^^^^^^^^^ the trait `Copy` is not implemented for `String` +LL | type Out = Box>; + | ^^^^^^^^^^^ error: aborting due to 1 previous error -For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/associated-type-bounds/bad-universal-in-dyn-in-where-clause.rs b/tests/ui/associated-type-bounds/bad-universal-in-dyn-in-where-clause.rs index 8cab1f66c2709..81c8fe829f978 100644 --- a/tests/ui/associated-type-bounds/bad-universal-in-dyn-in-where-clause.rs +++ b/tests/ui/associated-type-bounds/bad-universal-in-dyn-in-where-clause.rs @@ -7,7 +7,7 @@ trait B { fn f() where dyn for<'j> B:, - //~^ ERROR associated type bounds are only allowed in where clauses and function signatures + //~^ ERROR associated type bounds are not allowed in `dyn` types { } diff --git a/tests/ui/associated-type-bounds/bad-universal-in-dyn-in-where-clause.stderr b/tests/ui/associated-type-bounds/bad-universal-in-dyn-in-where-clause.stderr index fe300a7de427b..7d9870c72d481 100644 --- a/tests/ui/associated-type-bounds/bad-universal-in-dyn-in-where-clause.stderr +++ b/tests/ui/associated-type-bounds/bad-universal-in-dyn-in-where-clause.stderr @@ -1,4 +1,4 @@ -error: associated type bounds are only allowed in where clauses and function signatures, not in bounds +error: associated type bounds are not allowed in `dyn` types --> $DIR/bad-universal-in-dyn-in-where-clause.rs:9:19 | LL | dyn for<'j> B:, diff --git a/tests/ui/associated-type-bounds/bad-universal-in-impl-sig.rs b/tests/ui/associated-type-bounds/bad-universal-in-impl-sig.rs index 1d5d181efcc01..f465123f34c8b 100644 --- a/tests/ui/associated-type-bounds/bad-universal-in-impl-sig.rs +++ b/tests/ui/associated-type-bounds/bad-universal-in-impl-sig.rs @@ -8,6 +8,6 @@ trait Trait2 {} // It's not possible to insert a universal `impl Trait` here! impl dyn Trait {} -//~^ ERROR associated type bounds are only allowed in where clauses and function signatures +//~^ ERROR associated type bounds are not allowed in `dyn` types fn main() {} diff --git a/tests/ui/associated-type-bounds/bad-universal-in-impl-sig.stderr b/tests/ui/associated-type-bounds/bad-universal-in-impl-sig.stderr index 7bdb2c5a7c292..8855bd9c31230 100644 --- a/tests/ui/associated-type-bounds/bad-universal-in-impl-sig.stderr +++ b/tests/ui/associated-type-bounds/bad-universal-in-impl-sig.stderr @@ -1,4 +1,4 @@ -error: associated type bounds are only allowed in where clauses and function signatures, not in impl headers +error: associated type bounds are not allowed in `dyn` types --> $DIR/bad-universal-in-impl-sig.rs:10:16 | LL | impl dyn Trait {} diff --git a/tests/ui/associated-type-bounds/duplicate.rs b/tests/ui/associated-type-bounds/duplicate.rs index 036f8ede1b3b7..54c8cd3fde0d7 100644 --- a/tests/ui/associated-type-bounds/duplicate.rs +++ b/tests/ui/associated-type-bounds/duplicate.rs @@ -261,11 +261,4 @@ trait TRA3 { //~^ ERROR the value of the associated type `Item` in trait `Iterator` is already specified [E0719] } -type TADyn1 = dyn Iterator; -//~^ ERROR the value of the associated type `Item` in trait `Iterator` is already specified [E0719] -type TADyn2 = Box>; -//~^ ERROR the value of the associated type `Item` in trait `Iterator` is already specified [E0719] -type TADyn3 = dyn Iterator; -//~^ ERROR the value of the associated type `Item` in trait `Iterator` is already specified [E0719] - fn main() {} diff --git a/tests/ui/associated-type-bounds/duplicate.stderr b/tests/ui/associated-type-bounds/duplicate.stderr index bf6aab96dc726..9816d11a40a8b 100644 --- a/tests/ui/associated-type-bounds/duplicate.stderr +++ b/tests/ui/associated-type-bounds/duplicate.stderr @@ -6,30 +6,6 @@ LL | struct SI1> { | | | `Item` bound here first -error[E0719]: the value of the associated type `Item` in trait `Iterator` is already specified - --> $DIR/duplicate.rs:264:40 - | -LL | type TADyn1 = dyn Iterator; - | ---------- ^^^^^^^^^^ re-bound here - | | - | `Item` bound here first - -error[E0719]: the value of the associated type `Item` in trait `Iterator` is already specified - --> $DIR/duplicate.rs:266:44 - | -LL | type TADyn2 = Box>; - | ---------- ^^^^^^^^^^ re-bound here - | | - | `Item` bound here first - -error[E0719]: the value of the associated type `Item` in trait `Iterator` is already specified - --> $DIR/duplicate.rs:268:43 - | -LL | type TADyn3 = dyn Iterator; - | ------------- ^^^^^^^^^^^^^ re-bound here - | | - | `Item` bound here first - error[E0719]: the value of the associated type `Item` in trait `Iterator` is already specified --> $DIR/duplicate.rs:11:36 | @@ -631,7 +607,7 @@ LL | Self: Iterator, | = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -error: aborting due to 75 previous errors +error: aborting due to 72 previous errors Some errors have detailed explanations: E0282, E0719. For more information about an error, try `rustc --explain E0282`. diff --git a/tests/ui/associated-type-bounds/dyn-impl-trait-type.rs b/tests/ui/associated-type-bounds/dyn-impl-trait-type.rs deleted file mode 100644 index 079c44b3a598d..0000000000000 --- a/tests/ui/associated-type-bounds/dyn-impl-trait-type.rs +++ /dev/null @@ -1,66 +0,0 @@ -// run-pass - -#![feature(associated_type_bounds)] - -use std::ops::Add; - -trait Tr1 { type As1; fn mk(&self) -> Self::As1; } -trait Tr2<'a> { fn tr2(self) -> &'a Self; } //~ WARN method `tr2` is never used - -fn assert_copy(x: T) { let _x = x; let _x = x; } -fn assert_static(_: T) {} -fn assert_forall_tr2 Tr2<'a>>(_: T) {} - -struct S1; -#[derive(Copy, Clone)] -struct S2; -impl Tr1 for S1 { type As1 = S2; fn mk(&self) -> Self::As1 { S2 } } - -type Et1 = Box>; -fn def_et1() -> Et1 { Box::new(S1) } -pub fn use_et1() { assert_copy(def_et1().mk()); } - -type Et2 = Box>; -fn def_et2() -> Et2 { Box::new(S1) } -pub fn use_et2() { assert_static(def_et2().mk()); } - -type Et3 = Box>>>>; -fn def_et3() -> Et3 { - struct A; - impl Tr1 for A { - type As1 = core::ops::Range; - fn mk(&self) -> Self::As1 { 0..10 } - } - Box::new(A) -} -pub fn use_et3() { - let _0 = def_et3().mk().clone(); - let mut s = 0u8; - for _1 in _0 { - let _2 = _1 + 1u8; - s += _2.into(); - } - assert_eq!(s, (0..10).map(|x| x + 1).sum()); -} - -type Et4 = Box Tr2<'a>>>; -fn def_et4() -> Et4 { - #[derive(Copy, Clone)] - struct A; - impl Tr1 for A { - type As1 = A; - fn mk(&self) -> A { A } - } - impl<'a> Tr2<'a> for A { - fn tr2(self) -> &'a Self { &A } - } - Box::new(A) -} -pub fn use_et4() { assert_forall_tr2(def_et4().mk()); } - -fn main() { - use_et1(); - use_et2(); - use_et3(); - use_et4(); -} diff --git a/tests/ui/associated-type-bounds/dyn-rpit-and-let.rs b/tests/ui/associated-type-bounds/dyn-rpit-and-let.rs deleted file mode 100644 index 49e5e72f225e2..0000000000000 --- a/tests/ui/associated-type-bounds/dyn-rpit-and-let.rs +++ /dev/null @@ -1,73 +0,0 @@ -// run-pass - -// FIXME: uncomment let binding types below when `impl_trait_in_bindings` feature is fixed. - -#![feature(associated_type_bounds)] - -use std::ops::Add; - -trait Tr1 { type As1; fn mk(&self) -> Self::As1; } -trait Tr2<'a> { fn tr2(self) -> &'a Self; } //~ WARN method `tr2` is never used - -fn assert_copy(x: T) { let _x = x; let _x = x; } -fn assert_static(_: T) {} -fn assert_forall_tr2 Tr2<'a>>(_: T) {} - -struct S1; -#[derive(Copy, Clone)] -struct S2; -impl Tr1 for S1 { type As1 = S2; fn mk(&self) -> Self::As1 { S2 } } - -fn def_et1() -> Box> { - let x /* : Box> */ = Box::new(S1); - x -} -pub fn use_et1() { assert_copy(def_et1().mk()); } - -fn def_et2() -> Box> { - let x /* : Box> */ = Box::new(S1); - x -} -pub fn use_et2() { assert_static(def_et2().mk()); } - -fn def_et3() -> Box>>>> { - struct A; - impl Tr1 for A { - type As1 = core::ops::Range; - fn mk(&self) -> Self::As1 { 0..10 } - } - let x /* : Box>>>> */ - = Box::new(A); - x -} -pub fn use_et3() { - let _0 = def_et3().mk().clone(); - let mut s = 0u8; - for _1 in _0 { - let _2 = _1 + 1u8; - s += _2.into(); - } - assert_eq!(s, (0..10).map(|x| x + 1).sum()); -} - -fn def_et4() -> Box Tr2<'a>>> { - #[derive(Copy, Clone)] - struct A; - impl Tr1 for A { - type As1 = A; - fn mk(&self) -> A { A } - } - impl<'a> Tr2<'a> for A { - fn tr2(self) -> &'a Self { &A } - } - let x /* : Box Tr2<'a>>> */ = Box::new(A); - x -} -pub fn use_et4() { assert_forall_tr2(def_et4().mk()); } - -fn main() { - use_et1(); - use_et2(); - use_et3(); - use_et4(); -} diff --git a/tests/ui/associated-type-bounds/elision.rs b/tests/ui/associated-type-bounds/elision.rs index d00def571666b..5d7ed940ac69b 100644 --- a/tests/ui/associated-type-bounds/elision.rs +++ b/tests/ui/associated-type-bounds/elision.rs @@ -3,7 +3,7 @@ // The same thing should happen for constraints in dyn trait. fn f(x: &mut dyn Iterator>) -> Option<&'_ ()> { x.next() } -//~^ ERROR missing lifetime specifier -//~| ERROR mismatched types +//~^ ERROR associated type bounds are not allowed in `dyn` types +//~| ERROR missing lifetime specifier fn main() {} diff --git a/tests/ui/associated-type-bounds/elision.stderr b/tests/ui/associated-type-bounds/elision.stderr index a29e32a784fe4..70302d25b2b45 100644 --- a/tests/ui/associated-type-bounds/elision.stderr +++ b/tests/ui/associated-type-bounds/elision.stderr @@ -10,19 +10,12 @@ help: consider introducing a named lifetime parameter LL | fn f<'a>(x: &'a mut dyn Iterator>) -> Option<&'a ()> { x.next() } | ++++ ++ ~~ ~~ -error[E0308]: mismatched types - --> $DIR/elision.rs:5:79 +error: associated type bounds are not allowed in `dyn` types + --> $DIR/elision.rs:5:27 | LL | fn f(x: &mut dyn Iterator>) -> Option<&'_ ()> { x.next() } - | ----------------------------- -------------- ^^^^^^^^ expected `Option<&()>`, found `Option>` - | | | - | | expected `Option<&()>` because of return type - | found this type parameter - | - = note: expected enum `Option<&()>` - found enum `Option>` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 2 previous errors -Some errors have detailed explanations: E0106, E0308. -For more information about an error, try `rustc --explain E0106`. +For more information about this error, try `rustc --explain E0106`. diff --git a/tests/ui/associated-type-bounds/fn-dyn-apit.rs b/tests/ui/associated-type-bounds/fn-dyn-apit.rs deleted file mode 100644 index c4e8092c211d6..0000000000000 --- a/tests/ui/associated-type-bounds/fn-dyn-apit.rs +++ /dev/null @@ -1,61 +0,0 @@ -// run-pass -// aux-build:fn-dyn-aux.rs - -#![allow(unused)] -#![feature(associated_type_bounds)] - -extern crate fn_dyn_aux; - -use fn_dyn_aux::*; - -// ATB, APIT (dyn trait): - -fn dyn_apit_bound(beta: &dyn Beta) -> usize { - desugared_bound(beta) -} - -fn dyn_apit_bound_region(beta: &dyn Beta) -> usize { - desugared_bound_region(beta) -} - -fn dyn_apit_bound_multi( - beta: &(dyn Beta + Send) -) -> usize { - desugared_bound_multi(beta) -} - -fn dyn_apit_bound_region_forall( - beta: &dyn Beta Epsilon<'a>> -) -> usize { - desugared_bound_region_forall(beta) -} - -fn dyn_apit_bound_region_forall2( - beta: &dyn Beta Epsilon<'a, Zeta: Eta>> -) -> usize { - desugared_bound_region_forall2(beta) -} - -fn dyn_apit_bound_nested( - beta: &dyn Beta> -) -> usize { - desugared_bound_nested(beta) -} - -fn dyn_apit_bound_nested2( - beta: &dyn Beta> -) -> usize { - desugared_bound_nested(beta) -} - -fn main() { - let beta = BetaType; - let _gamma = beta.gamma(); - - assert_eq!(42, dyn_apit_bound(&beta)); - assert_eq!(24, dyn_apit_bound_region(&beta)); - assert_eq!(42 + 24 + 1337, dyn_apit_bound_multi(&beta)); - assert_eq!(7331 * 2, dyn_apit_bound_region_forall(&beta)); - assert_eq!(42 + 1337, dyn_apit_bound_nested(&beta)); - assert_eq!(42 + 1337, dyn_apit_bound_nested2(&beta)); -} diff --git a/tests/ui/associated-type-bounds/inside-adt.rs b/tests/ui/associated-type-bounds/inside-adt.rs index 057966941dc09..2b4b060983e03 100644 --- a/tests/ui/associated-type-bounds/inside-adt.rs +++ b/tests/ui/associated-type-bounds/inside-adt.rs @@ -3,24 +3,24 @@ use std::mem::ManuallyDrop; struct S1 { f: dyn Iterator } -//~^ ERROR associated type bounds are only allowed in where clauses and function signatures +//~^ ERROR associated type bounds are not allowed in `dyn` types struct S2 { f: Box> } -//~^ ERROR associated type bounds are only allowed in where clauses and function signatures +//~^ ERROR associated type bounds are not allowed in `dyn` types struct S3 { f: dyn Iterator } -//~^ ERROR associated type bounds are only allowed in where clauses and function signatures +//~^ ERROR associated type bounds are not allowed in `dyn` types enum E1 { V(dyn Iterator) } -//~^ ERROR associated type bounds are only allowed in where clauses and function signatures +//~^ ERROR associated type bounds are not allowed in `dyn` types enum E2 { V(Box>) } -//~^ ERROR associated type bounds are only allowed in where clauses and function signatures +//~^ ERROR associated type bounds are not allowed in `dyn` types enum E3 { V(dyn Iterator) } -//~^ ERROR associated type bounds are only allowed in where clauses and function signatures +//~^ ERROR associated type bounds are not allowed in `dyn` types union U1 { f: ManuallyDrop> } -//~^ ERROR associated type bounds are only allowed in where clauses and function signatures +//~^ ERROR associated type bounds are not allowed in `dyn` types union U2 { f: ManuallyDrop>> } -//~^ ERROR associated type bounds are only allowed in where clauses and function signatures +//~^ ERROR associated type bounds are not allowed in `dyn` types union U3 { f: ManuallyDrop> } -//~^ ERROR associated type bounds are only allowed in where clauses and function signatures +//~^ ERROR associated type bounds are not allowed in `dyn` types fn main() {} diff --git a/tests/ui/associated-type-bounds/inside-adt.stderr b/tests/ui/associated-type-bounds/inside-adt.stderr index f848bd798ee0a..ef45fae8f2a1c 100644 --- a/tests/ui/associated-type-bounds/inside-adt.stderr +++ b/tests/ui/associated-type-bounds/inside-adt.stderr @@ -1,52 +1,52 @@ -error: associated type bounds are only allowed in where clauses and function signatures, not in field types +error: associated type bounds are not allowed in `dyn` types --> $DIR/inside-adt.rs:5:29 | LL | struct S1 { f: dyn Iterator } | ^^^^^^^^^^ -error: associated type bounds are only allowed in where clauses and function signatures, not in field types +error: associated type bounds are not allowed in `dyn` types --> $DIR/inside-adt.rs:7:33 | LL | struct S2 { f: Box> } | ^^^^^^^^^^ -error: associated type bounds are only allowed in where clauses and function signatures, not in field types +error: associated type bounds are not allowed in `dyn` types --> $DIR/inside-adt.rs:9:29 | LL | struct S3 { f: dyn Iterator } | ^^^^^^^^^^^^^ -error: associated type bounds are only allowed in where clauses and function signatures, not in field types +error: associated type bounds are not allowed in `dyn` types --> $DIR/inside-adt.rs:12:26 | LL | enum E1 { V(dyn Iterator) } | ^^^^^^^^^^ -error: associated type bounds are only allowed in where clauses and function signatures, not in field types +error: associated type bounds are not allowed in `dyn` types --> $DIR/inside-adt.rs:14:30 | LL | enum E2 { V(Box>) } | ^^^^^^^^^^ -error: associated type bounds are only allowed in where clauses and function signatures, not in field types +error: associated type bounds are not allowed in `dyn` types --> $DIR/inside-adt.rs:16:26 | LL | enum E3 { V(dyn Iterator) } | ^^^^^^^^^^^^^ -error: associated type bounds are only allowed in where clauses and function signatures, not in field types +error: associated type bounds are not allowed in `dyn` types --> $DIR/inside-adt.rs:19:41 | LL | union U1 { f: ManuallyDrop> } | ^^^^^^^^^^ -error: associated type bounds are only allowed in where clauses and function signatures, not in field types +error: associated type bounds are not allowed in `dyn` types --> $DIR/inside-adt.rs:21:45 | LL | union U2 { f: ManuallyDrop>> } | ^^^^^^^^^^ -error: associated type bounds are only allowed in where clauses and function signatures, not in field types +error: associated type bounds are not allowed in `dyn` types --> $DIR/inside-adt.rs:23:41 | LL | union U3 { f: ManuallyDrop> } diff --git a/tests/ui/associated-type-bounds/issue-104916.rs b/tests/ui/associated-type-bounds/issue-104916.rs index 3361fa011ed8e..ee29a0a2fc491 100644 --- a/tests/ui/associated-type-bounds/issue-104916.rs +++ b/tests/ui/associated-type-bounds/issue-104916.rs @@ -7,7 +7,7 @@ trait B { fn f() where dyn for<'j> B:, - //~^ ERROR: associated type bounds are only allowed in where clauses and function signatures + //~^ ERROR: associated type bounds are not allowed in `dyn` types { } diff --git a/tests/ui/associated-type-bounds/issue-104916.stderr b/tests/ui/associated-type-bounds/issue-104916.stderr index 65c89735c5dcc..e8618b7210369 100644 --- a/tests/ui/associated-type-bounds/issue-104916.stderr +++ b/tests/ui/associated-type-bounds/issue-104916.stderr @@ -1,4 +1,4 @@ -error: associated type bounds are only allowed in where clauses and function signatures, not in bounds +error: associated type bounds are not allowed in `dyn` types --> $DIR/issue-104916.rs:9:19 | LL | dyn for<'j> B:, diff --git a/tests/ui/feature-gates/feature-gate-associated_type_bounds.rs b/tests/ui/feature-gates/feature-gate-associated_type_bounds.rs index f87d3aab635c0..717da41f8713d 100644 --- a/tests/ui/feature-gates/feature-gate-associated_type_bounds.rs +++ b/tests/ui/feature-gates/feature-gate-associated_type_bounds.rs @@ -42,31 +42,20 @@ type _TaWhere1 where T: Iterator = T; fn _apit(_: impl Tr1) {} //~^ ERROR associated type bounds are unstable -fn _apit_dyn(_: &dyn Tr1) {} -//~^ ERROR associated type bounds are unstable fn _rpit() -> impl Tr1 { S1 } //~^ ERROR associated type bounds are unstable -fn _rpit_dyn() -> Box> { Box::new(S1) } -//~^ ERROR associated type bounds are unstable - const _cdef: impl Tr1 = S1; //~^ ERROR associated type bounds are unstable //~| ERROR `impl Trait` is not allowed in const types -// FIXME: uncomment when `impl_trait_in_bindings` feature is fixed. -// const _cdef_dyn: &dyn Tr1 = &S1; static _sdef: impl Tr1 = S1; //~^ ERROR associated type bounds are unstable //~| ERROR `impl Trait` is not allowed in static types -// FIXME: uncomment when `impl_trait_in_bindings` feature is fixed. -// static _sdef_dyn: &dyn Tr1 = &S1; fn main() { let _: impl Tr1 = S1; //~^ ERROR associated type bounds are unstable //~| ERROR `impl Trait` is not allowed in the type of variable bindings - // FIXME: uncomment when `impl_trait_in_bindings` feature is fixed. - // let _: &dyn Tr1 = &S1; } diff --git a/tests/ui/feature-gates/feature-gate-associated_type_bounds.stderr b/tests/ui/feature-gates/feature-gate-associated_type_bounds.stderr index 855a29953f1b0..1838eab5cda5f 100644 --- a/tests/ui/feature-gates/feature-gate-associated_type_bounds.stderr +++ b/tests/ui/feature-gates/feature-gate-associated_type_bounds.stderr @@ -69,17 +69,7 @@ LL | fn _apit(_: impl Tr1) {} = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: associated type bounds are unstable - --> $DIR/feature-gate-associated_type_bounds.rs:45:26 - | -LL | fn _apit_dyn(_: &dyn Tr1) {} - | ^^^^^^^^^ - | - = note: see issue #52662 for more information - = help: add `#![feature(associated_type_bounds)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - -error[E0658]: associated type bounds are unstable - --> $DIR/feature-gate-associated_type_bounds.rs:48:24 + --> $DIR/feature-gate-associated_type_bounds.rs:46:24 | LL | fn _rpit() -> impl Tr1 { S1 } | ^^^^^^^^^ @@ -89,17 +79,7 @@ LL | fn _rpit() -> impl Tr1 { S1 } = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: associated type bounds are unstable - --> $DIR/feature-gate-associated_type_bounds.rs:51:31 - | -LL | fn _rpit_dyn() -> Box> { Box::new(S1) } - | ^^^^^^^^^ - | - = note: see issue #52662 for more information - = help: add `#![feature(associated_type_bounds)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - -error[E0658]: associated type bounds are unstable - --> $DIR/feature-gate-associated_type_bounds.rs:54:23 + --> $DIR/feature-gate-associated_type_bounds.rs:49:23 | LL | const _cdef: impl Tr1 = S1; | ^^^^^^^^^ @@ -109,7 +89,7 @@ LL | const _cdef: impl Tr1 = S1; = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: associated type bounds are unstable - --> $DIR/feature-gate-associated_type_bounds.rs:60:24 + --> $DIR/feature-gate-associated_type_bounds.rs:53:24 | LL | static _sdef: impl Tr1 = S1; | ^^^^^^^^^ @@ -119,7 +99,7 @@ LL | static _sdef: impl Tr1 = S1; = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: associated type bounds are unstable - --> $DIR/feature-gate-associated_type_bounds.rs:67:21 + --> $DIR/feature-gate-associated_type_bounds.rs:58:21 | LL | let _: impl Tr1 = S1; | ^^^^^^^^^ @@ -129,7 +109,7 @@ LL | let _: impl Tr1 = S1; = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0562]: `impl Trait` is not allowed in const types - --> $DIR/feature-gate-associated_type_bounds.rs:54:14 + --> $DIR/feature-gate-associated_type_bounds.rs:49:14 | LL | const _cdef: impl Tr1 = S1; | ^^^^^^^^^^^^^^^^^^^ @@ -137,7 +117,7 @@ LL | const _cdef: impl Tr1 = S1; = note: `impl Trait` is only allowed in arguments and return types of functions and methods error[E0562]: `impl Trait` is not allowed in static types - --> $DIR/feature-gate-associated_type_bounds.rs:60:15 + --> $DIR/feature-gate-associated_type_bounds.rs:53:15 | LL | static _sdef: impl Tr1 = S1; | ^^^^^^^^^^^^^^^^^^^ @@ -145,14 +125,14 @@ LL | static _sdef: impl Tr1 = S1; = note: `impl Trait` is only allowed in arguments and return types of functions and methods error[E0562]: `impl Trait` is not allowed in the type of variable bindings - --> $DIR/feature-gate-associated_type_bounds.rs:67:12 + --> $DIR/feature-gate-associated_type_bounds.rs:58:12 | LL | let _: impl Tr1 = S1; | ^^^^^^^^^^^^^^^^^^^ | = note: `impl Trait` is only allowed in arguments and return types of functions and methods -error: aborting due to 16 previous errors +error: aborting due to 14 previous errors Some errors have detailed explanations: E0562, E0658. For more information about an error, try `rustc --explain E0562`. From fde695a2d19fc13a5773b8e9168341c67a21912e Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Tue, 6 Feb 2024 19:48:16 +0000 Subject: [PATCH 09/12] Add a helpful suggestion --- compiler/rustc_ast_lowering/messages.ftl | 1 + compiler/rustc_ast_lowering/src/errors.rs | 2 + compiler/rustc_ast_lowering/src/lib.rs | 63 +++++++++---------- .../assoc-type-eq-with-dyn-atb-fail.stderr | 5 ++ .../dyn-impl-trait-type.stderr | 12 ---- .../dyn-rpit-and-let.stderr | 12 ---- .../ui/associated-type-bounds/elision.stderr | 5 ++ 7 files changed, 43 insertions(+), 57 deletions(-) delete mode 100644 tests/ui/associated-type-bounds/dyn-impl-trait-type.stderr delete mode 100644 tests/ui/associated-type-bounds/dyn-rpit-and-let.stderr diff --git a/compiler/rustc_ast_lowering/messages.ftl b/compiler/rustc_ast_lowering/messages.ftl index 9c151ec80eefe..e87cf05713cd3 100644 --- a/compiler/rustc_ast_lowering/messages.ftl +++ b/compiler/rustc_ast_lowering/messages.ftl @@ -10,6 +10,7 @@ ast_lowering_argument = argument ast_lowering_assoc_ty_binding_in_dyn = associated type bounds are not allowed in `dyn` types + .suggestion = use `impl Trait` to introduce a type instead ast_lowering_assoc_ty_parentheses = parenthesized generic arguments cannot be used in associated type constraints diff --git a/compiler/rustc_ast_lowering/src/errors.rs b/compiler/rustc_ast_lowering/src/errors.rs index fba8ea206f140..274e6b7458c61 100644 --- a/compiler/rustc_ast_lowering/src/errors.rs +++ b/compiler/rustc_ast_lowering/src/errors.rs @@ -98,6 +98,8 @@ pub struct MisplacedImplTrait<'a> { pub struct MisplacedAssocTyBinding { #[primary_span] pub span: Span, + #[suggestion(code = " = impl", applicability = "maybe-incorrect", style = "verbose")] + pub suggestion: Option, } #[derive(Diagnostic, Clone, Copy)] diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 48cc301219a87..7c89600fa281c 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -1084,41 +1084,38 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { hir::TypeBindingKind::Equality { term } } AssocConstraintKind::Bound { bounds } => { - enum DesugarKind { - Error, - Bound, - } - - // Piggy-back on the `impl Trait` context to figure out the correct behavior. - let desugar_kind = match itctx { - _ if self.is_in_dyn_type => DesugarKind::Error, - - // We are in the parameter position, but not within a dyn type: - // - // fn foo(x: impl Iterator) - // - // so we leave it as is and this gets expanded in astconv to a bound like - // `::Item: Debug` where `T` is the type parameter for the - // `impl Iterator`. - _ => DesugarKind::Bound, - }; + // Disallow ATB in dyn types + if self.is_in_dyn_type { + let suggestion = match itctx { + ImplTraitContext::ReturnPositionOpaqueTy { .. } + | ImplTraitContext::TypeAliasesOpaqueTy { .. } + | ImplTraitContext::Universal => { + let bound_end_span = constraint + .gen_args + .as_ref() + .map_or(constraint.ident.span, |args| args.span()); + if bound_end_span.eq_ctxt(constraint.span) { + Some(self.tcx.sess.source_map().next_point(bound_end_span)) + } else { + None + } + } + _ => None, + }; - match desugar_kind { - DesugarKind::Bound => { - // Desugar `AssocTy: Bounds` into a type binding where the - // later desugars into a trait predicate. - let bounds = self.lower_param_bounds(bounds, itctx); + let guar = self.dcx().emit_err(errors::MisplacedAssocTyBinding { + span: constraint.span, + suggestion, + }); + let err_ty = + &*self.arena.alloc(self.ty(constraint.span, hir::TyKind::Err(guar))); + hir::TypeBindingKind::Equality { term: err_ty.into() } + } else { + // Desugar `AssocTy: Bounds` into a type binding where the + // later desugars into a trait predicate. + let bounds = self.lower_param_bounds(bounds, itctx); - hir::TypeBindingKind::Constraint { bounds } - } - DesugarKind::Error => { - let guar = self - .dcx() - .emit_err(errors::MisplacedAssocTyBinding { span: constraint.span }); - let err_ty = - &*self.arena.alloc(self.ty(constraint.span, hir::TyKind::Err(guar))); - hir::TypeBindingKind::Equality { term: err_ty.into() } - } + hir::TypeBindingKind::Constraint { bounds } } } }; diff --git a/tests/ui/associated-type-bounds/assoc-type-eq-with-dyn-atb-fail.stderr b/tests/ui/associated-type-bounds/assoc-type-eq-with-dyn-atb-fail.stderr index 2d38bbd8c923e..ad5409094118d 100644 --- a/tests/ui/associated-type-bounds/assoc-type-eq-with-dyn-atb-fail.stderr +++ b/tests/ui/associated-type-bounds/assoc-type-eq-with-dyn-atb-fail.stderr @@ -3,6 +3,11 @@ error: associated type bounds are not allowed in `dyn` types | LL | type Out = Box>; | ^^^^^^^^^^^ + | +help: use `impl Trait` to introduce a type instead + | +LL | type Out = Box>; + | ~~~~~~ error: aborting due to 1 previous error diff --git a/tests/ui/associated-type-bounds/dyn-impl-trait-type.stderr b/tests/ui/associated-type-bounds/dyn-impl-trait-type.stderr deleted file mode 100644 index 2e26a434f5d34..0000000000000 --- a/tests/ui/associated-type-bounds/dyn-impl-trait-type.stderr +++ /dev/null @@ -1,12 +0,0 @@ -warning: method `tr2` is never used - --> $DIR/dyn-impl-trait-type.rs:8:20 - | -LL | trait Tr2<'a> { fn tr2(self) -> &'a Self; } - | --- ^^^ - | | - | method in this trait - | - = note: `#[warn(dead_code)]` on by default - -warning: 1 warning emitted - diff --git a/tests/ui/associated-type-bounds/dyn-rpit-and-let.stderr b/tests/ui/associated-type-bounds/dyn-rpit-and-let.stderr deleted file mode 100644 index 9eddbe462847d..0000000000000 --- a/tests/ui/associated-type-bounds/dyn-rpit-and-let.stderr +++ /dev/null @@ -1,12 +0,0 @@ -warning: method `tr2` is never used - --> $DIR/dyn-rpit-and-let.rs:10:20 - | -LL | trait Tr2<'a> { fn tr2(self) -> &'a Self; } - | --- ^^^ - | | - | method in this trait - | - = note: `#[warn(dead_code)]` on by default - -warning: 1 warning emitted - diff --git a/tests/ui/associated-type-bounds/elision.stderr b/tests/ui/associated-type-bounds/elision.stderr index 70302d25b2b45..749dffdc4d318 100644 --- a/tests/ui/associated-type-bounds/elision.stderr +++ b/tests/ui/associated-type-bounds/elision.stderr @@ -15,6 +15,11 @@ error: associated type bounds are not allowed in `dyn` types | LL | fn f(x: &mut dyn Iterator>) -> Option<&'_ ()> { x.next() } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: use `impl Trait` to introduce a type instead + | +LL | fn f(x: &mut dyn Iterator>) -> Option<&'_ ()> { x.next() } + | ~~~~~~ error: aborting due to 2 previous errors From e6f5af967132139ba584ad3c04df8dac83dc2640 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sat, 10 Feb 2024 03:52:13 +0000 Subject: [PATCH 10/12] Remove unused fn --- compiler/rustc_ast_lowering/src/lib.rs | 6 ------ 1 file changed, 6 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 7c89600fa281c..5f7439060b3c9 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -197,7 +197,6 @@ trait ResolverAstLoweringExt { fn get_label_res(&self, id: NodeId) -> Option; fn get_lifetime_res(&self, id: NodeId) -> Option; fn take_extra_lifetime_params(&mut self, id: NodeId) -> Vec<(Ident, NodeId, LifetimeRes)>; - fn remap_extra_lifetime_params(&mut self, from: NodeId, to: NodeId); } impl ResolverAstLoweringExt for ResolverAstLowering { @@ -256,11 +255,6 @@ impl ResolverAstLoweringExt for ResolverAstLowering { fn take_extra_lifetime_params(&mut self, id: NodeId) -> Vec<(Ident, NodeId, LifetimeRes)> { self.extra_lifetime_params_map.remove(&id).unwrap_or_default() } - - fn remap_extra_lifetime_params(&mut self, from: NodeId, to: NodeId) { - let lifetimes = self.extra_lifetime_params_map.remove(&from).unwrap_or_default(); - self.extra_lifetime_params_map.insert(to, lifetimes); - } } /// Context of `impl Trait` in code, which determines whether it is allowed in an HIR subtree, From 7b73e4fd44c86405307afa5f1a03317bc560f746 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Sat, 10 Feb 2024 13:54:28 +1100 Subject: [PATCH 11/12] Allow restricted trait impls in macros with `min_specialization` Implementing traits marked with `#[rustc_specialization_trait]` normally requires (min-)specialization to be enabled for the enclosing crate. With this change, that permission can also be granted by an `allow_internal_unstable` attribute on the macro that generates the impl. --- compiler/rustc_hir_analysis/src/coherence/mod.rs | 8 ++++++-- .../{ => min_specialization}/allow_internal_unstable.rs | 9 ++++++++- 2 files changed, 14 insertions(+), 3 deletions(-) rename tests/ui/specialization/{ => min_specialization}/allow_internal_unstable.rs (64%) diff --git a/compiler/rustc_hir_analysis/src/coherence/mod.rs b/compiler/rustc_hir_analysis/src/coherence/mod.rs index 8cf1f2c9407f6..817dab993a37f 100644 --- a/compiler/rustc_hir_analysis/src/coherence/mod.rs +++ b/compiler/rustc_hir_analysis/src/coherence/mod.rs @@ -10,7 +10,7 @@ use rustc_errors::{codes::*, struct_span_code_err}; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_middle::query::Providers; use rustc_middle::ty::{self, TyCtxt, TypeVisitableExt}; -use rustc_span::ErrorGuaranteed; +use rustc_span::{sym, ErrorGuaranteed}; use rustc_trait_selection::traits; mod builtin; @@ -70,7 +70,11 @@ fn enforce_trait_manually_implementable( if let ty::trait_def::TraitSpecializationKind::AlwaysApplicable = tcx.trait_def(trait_def_id).specialization_kind { - if !tcx.features().specialization && !tcx.features().min_specialization { + if !tcx.features().specialization + && !tcx.features().min_specialization + && !impl_header_span.allows_unstable(sym::specialization) + && !impl_header_span.allows_unstable(sym::min_specialization) + { return Err(tcx.dcx().emit_err(errors::SpecializationTrait { span: impl_header_span })); } } diff --git a/tests/ui/specialization/allow_internal_unstable.rs b/tests/ui/specialization/min_specialization/allow_internal_unstable.rs similarity index 64% rename from tests/ui/specialization/allow_internal_unstable.rs rename to tests/ui/specialization/min_specialization/allow_internal_unstable.rs index 317782b7b7285..8f3677d976989 100644 --- a/tests/ui/specialization/allow_internal_unstable.rs +++ b/tests/ui/specialization/min_specialization/allow_internal_unstable.rs @@ -5,6 +5,9 @@ #![allow(internal_features)] #![feature(allow_internal_unstable)] +// aux-build:specialization-trait.rs +extern crate specialization_trait; + #[allow_internal_unstable(min_specialization)] macro_rules! test { () => { @@ -12,7 +15,11 @@ macro_rules! test { trait Tr {} impl Tr for T {} impl Tr for T {} - } + + impl specialization_trait::SpecTrait for T { + fn method(&self) {} + } + }; } test! {} From a2479a4ae75884953eb9eaad083105174549c2ed Mon Sep 17 00:00:00 2001 From: Zalathar Date: Sat, 10 Feb 2024 14:52:57 +1100 Subject: [PATCH 12/12] Remove unnecessary `min_specialization` after bootstrap These crates all needed specialization for `newtype_index!`, which will no longer be necessary when the current nightly eventually becomes the next bootstrap compiler. --- compiler/rustc_ast/src/lib.rs | 2 +- compiler/rustc_errors/src/lib.rs | 2 +- compiler/rustc_hir/src/lib.rs | 2 +- compiler/rustc_hir_analysis/src/lib.rs | 2 +- compiler/rustc_hir_typeck/src/lib.rs | 2 +- compiler/rustc_infer/src/lib.rs | 2 +- compiler/rustc_mir_build/src/lib.rs | 2 +- compiler/rustc_mir_dataflow/src/lib.rs | 2 +- compiler/rustc_mir_transform/src/lib.rs | 2 +- compiler/rustc_target/src/lib.rs | 2 +- compiler/rustc_trait_selection/src/lib.rs | 2 +- 11 files changed, 11 insertions(+), 11 deletions(-) diff --git a/compiler/rustc_ast/src/lib.rs b/compiler/rustc_ast/src/lib.rs index 356e9fef439ed..6414c8e904196 100644 --- a/compiler/rustc_ast/src/lib.rs +++ b/compiler/rustc_ast/src/lib.rs @@ -15,7 +15,7 @@ #![feature(box_patterns)] #![feature(if_let_guard)] #![feature(let_chains)] -#![feature(min_specialization)] +#![cfg_attr(bootstrap, feature(min_specialization))] #![feature(negative_impls)] #![feature(stmt_expr_attributes)] diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index 7216fa8f5e4f6..ab3ad0e9d6843 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -7,6 +7,7 @@ #![allow(internal_features)] #![allow(rustc::diagnostic_outside_of_impl)] #![allow(rustc::untranslatable_diagnostic)] +#![cfg_attr(bootstrap, feature(min_specialization))] #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] #![doc(rust_logo)] #![feature(array_windows)] @@ -16,7 +17,6 @@ #![feature(error_reporter)] #![feature(extract_if)] #![feature(let_chains)] -#![feature(min_specialization)] #![feature(negative_impls)] #![feature(never_type)] #![feature(rustc_attrs)] diff --git a/compiler/rustc_hir/src/lib.rs b/compiler/rustc_hir/src/lib.rs index aff946ac58081..9921686ce289c 100644 --- a/compiler/rustc_hir/src/lib.rs +++ b/compiler/rustc_hir/src/lib.rs @@ -5,7 +5,7 @@ #![feature(associated_type_defaults)] #![feature(closure_track_caller)] #![feature(let_chains)] -#![feature(min_specialization)] +#![cfg_attr(bootstrap, feature(min_specialization))] #![feature(never_type)] #![feature(rustc_attrs)] #![feature(variant_count)] diff --git a/compiler/rustc_hir_analysis/src/lib.rs b/compiler/rustc_hir_analysis/src/lib.rs index 883d416ecd187..1aaefc5b52087 100644 --- a/compiler/rustc_hir_analysis/src/lib.rs +++ b/compiler/rustc_hir_analysis/src/lib.rs @@ -67,7 +67,7 @@ This API is completely unstable and subject to change. #![feature(is_sorted)] #![feature(iter_intersperse)] #![feature(let_chains)] -#![feature(min_specialization)] +#![cfg_attr(bootstrap, feature(min_specialization))] #![feature(never_type)] #![feature(lazy_cell)] #![feature(slice_partition_dedup)] diff --git a/compiler/rustc_hir_typeck/src/lib.rs b/compiler/rustc_hir_typeck/src/lib.rs index 315dc4330ad32..06a1461356707 100644 --- a/compiler/rustc_hir_typeck/src/lib.rs +++ b/compiler/rustc_hir_typeck/src/lib.rs @@ -5,7 +5,7 @@ #![feature(try_blocks)] #![feature(never_type)] #![feature(box_patterns)] -#![feature(min_specialization)] +#![cfg_attr(bootstrap, feature(min_specialization))] #![feature(control_flow_enum)] #[macro_use] diff --git a/compiler/rustc_infer/src/lib.rs b/compiler/rustc_infer/src/lib.rs index 622cdf0c7b895..97f9a4b291d09 100644 --- a/compiler/rustc_infer/src/lib.rs +++ b/compiler/rustc_infer/src/lib.rs @@ -24,7 +24,7 @@ #![feature(let_chains)] #![feature(if_let_guard)] #![feature(iterator_try_collect)] -#![feature(min_specialization)] +#![cfg_attr(bootstrap, feature(min_specialization))] #![feature(try_blocks)] #![recursion_limit = "512"] // For rustdoc diff --git a/compiler/rustc_mir_build/src/lib.rs b/compiler/rustc_mir_build/src/lib.rs index 43e44b47e3f96..e3f202b7f1882 100644 --- a/compiler/rustc_mir_build/src/lib.rs +++ b/compiler/rustc_mir_build/src/lib.rs @@ -9,7 +9,7 @@ #![feature(box_patterns)] #![feature(if_let_guard)] #![feature(let_chains)] -#![feature(min_specialization)] +#![cfg_attr(bootstrap, feature(min_specialization))] #![feature(try_blocks)] #[macro_use] diff --git a/compiler/rustc_mir_dataflow/src/lib.rs b/compiler/rustc_mir_dataflow/src/lib.rs index a4b58e5bfc128..f18a2354301e4 100644 --- a/compiler/rustc_mir_dataflow/src/lib.rs +++ b/compiler/rustc_mir_dataflow/src/lib.rs @@ -2,7 +2,7 @@ #![feature(box_patterns)] #![feature(exact_size_is_empty)] #![feature(let_chains)] -#![feature(min_specialization)] +#![cfg_attr(bootstrap, feature(min_specialization))] #![feature(try_blocks)] #[macro_use] diff --git a/compiler/rustc_mir_transform/src/lib.rs b/compiler/rustc_mir_transform/src/lib.rs index 8e5d69605aa35..ad0cd4fcff9f8 100644 --- a/compiler/rustc_mir_transform/src/lib.rs +++ b/compiler/rustc_mir_transform/src/lib.rs @@ -8,7 +8,7 @@ #![feature(is_sorted)] #![feature(let_chains)] #![feature(map_try_insert)] -#![feature(min_specialization)] +#![cfg_attr(bootstrap, feature(min_specialization))] #![feature(never_type)] #![feature(option_get_or_insert_default)] #![feature(round_char_boundary)] diff --git a/compiler/rustc_target/src/lib.rs b/compiler/rustc_target/src/lib.rs index b19c5b6f28f08..04c5e60aa6ba1 100644 --- a/compiler/rustc_target/src/lib.rs +++ b/compiler/rustc_target/src/lib.rs @@ -14,7 +14,7 @@ #![feature(exhaustive_patterns)] #![feature(iter_intersperse)] #![feature(let_chains)] -#![feature(min_specialization)] +#![cfg_attr(bootstrap, feature(min_specialization))] #![feature(rustc_attrs)] #![feature(step_trait)] #![allow(internal_features)] diff --git a/compiler/rustc_trait_selection/src/lib.rs b/compiler/rustc_trait_selection/src/lib.rs index 053ecfc681ceb..00a2adccf64a5 100644 --- a/compiler/rustc_trait_selection/src/lib.rs +++ b/compiler/rustc_trait_selection/src/lib.rs @@ -24,7 +24,7 @@ #![feature(option_take_if)] #![feature(never_type)] #![feature(type_alias_impl_trait)] -#![feature(min_specialization)] +#![cfg_attr(bootstrap, feature(min_specialization))] #![recursion_limit = "512"] // For rustdoc #[macro_use]