mirror of
https://github.com/rust-lang/rust.git
synced 2026-05-15 20:45:45 +03:00
Merge from rustc
This commit is contained in:
+27
-57
@@ -4,19 +4,13 @@ version = 4
|
||||
|
||||
[[package]]
|
||||
name = "addr2line"
|
||||
version = "0.21.0"
|
||||
version = "0.24.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb"
|
||||
checksum = "dfbe277e56a376000877090da837660b4427aad530e3028d44e0bffe4f89a1c1"
|
||||
dependencies = [
|
||||
"gimli 0.28.1",
|
||||
"gimli",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "adler"
|
||||
version = "1.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
|
||||
|
||||
[[package]]
|
||||
name = "adler2"
|
||||
version = "2.0.0"
|
||||
@@ -168,7 +162,7 @@ version = "0.4.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "01667f6f40216b9a0b2945e05fed5f1ad0ab6470e69cb9378001e37b1c0668e4"
|
||||
dependencies = [
|
||||
"object 0.36.7",
|
||||
"object",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -233,17 +227,17 @@ checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26"
|
||||
|
||||
[[package]]
|
||||
name = "backtrace"
|
||||
version = "0.3.71"
|
||||
version = "0.3.75"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "26b05800d2e817c8b3b4b54abd461726265fa9789ae34330622f2db9ee696f9d"
|
||||
checksum = "6806a6321ec58106fea15becdad98371e28d92ccbc7c8f1b3b6dd724fe8f1002"
|
||||
dependencies = [
|
||||
"addr2line",
|
||||
"cc",
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"miniz_oxide 0.7.4",
|
||||
"object 0.32.2",
|
||||
"miniz_oxide",
|
||||
"object",
|
||||
"rustc-demangle",
|
||||
"windows-targets 0.52.6",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -780,7 +774,7 @@ dependencies = [
|
||||
"itertools",
|
||||
"leb128",
|
||||
"md-5",
|
||||
"miniz_oxide 0.7.4",
|
||||
"miniz_oxide",
|
||||
"regex",
|
||||
"rustc-demangle",
|
||||
]
|
||||
@@ -849,9 +843,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "ctrlc"
|
||||
version = "3.4.6"
|
||||
version = "3.4.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "697b5419f348fd5ae2478e8018cb016c00a5881c7f46c717de98ffd135a5651c"
|
||||
checksum = "46f93780a459b7d656ef7f071fe699c4d3d2cb201c4b24d085b6ddc505276e73"
|
||||
dependencies = [
|
||||
"nix",
|
||||
"windows-sys 0.59.0",
|
||||
@@ -1220,7 +1214,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7ced92e76e966ca2fd84c8f7aa01a4aea65b0eb6648d72f7c8f3e2764a67fece"
|
||||
dependencies = [
|
||||
"crc32fast",
|
||||
"miniz_oxide 0.8.8",
|
||||
"miniz_oxide",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1453,12 +1447,6 @@ dependencies = [
|
||||
"wasi 0.14.2+wasi-0.2.4",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "gimli"
|
||||
version = "0.28.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253"
|
||||
|
||||
[[package]]
|
||||
name = "gimli"
|
||||
version = "0.31.1"
|
||||
@@ -2064,12 +2052,12 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "libloading"
|
||||
version = "0.8.6"
|
||||
version = "0.8.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fc2f4eb4bc735547cfed7c0a4922cbd04a4655978c09b54f1f7b228750664c34"
|
||||
checksum = "6a793df0d7afeac54f95b471d3af7f0d4fb975699f972341a4b76988d49cdf0c"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"windows-targets 0.48.5",
|
||||
"windows-targets 0.53.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -2263,15 +2251,6 @@ version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a"
|
||||
|
||||
[[package]]
|
||||
name = "miniz_oxide"
|
||||
version = "0.7.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b8a240ddb74feaf34a79a7add65a741f3167852fba007066dcac1ca548d89c08"
|
||||
dependencies = [
|
||||
"adler",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "miniz_oxide"
|
||||
version = "0.8.8"
|
||||
@@ -2327,9 +2306,9 @@ checksum = "650eef8c711430f1a879fdd01d4745a7deea475becfb90269c06775983bbf086"
|
||||
|
||||
[[package]]
|
||||
name = "nix"
|
||||
version = "0.29.0"
|
||||
version = "0.30.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "71e2746dc3a24dd78b3cfcb7be93368c6de9963d30f43a6a73998a9cf4b17b46"
|
||||
checksum = "74523f3a35e05aba87a1d978330aef40f67b0304ac79c1c00b294c9830543db6"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"cfg-if",
|
||||
@@ -2483,15 +2462,6 @@ dependencies = [
|
||||
"objc2-core-foundation",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "object"
|
||||
version = "0.32.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a6a622008b6e321afc04970976f62ee297fdbaa6f95318ca343e3eebb9648441"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "object"
|
||||
version = "0.36.7"
|
||||
@@ -2567,7 +2537,6 @@ dependencies = [
|
||||
"humansize",
|
||||
"humantime",
|
||||
"log",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"sysinfo",
|
||||
"tabled",
|
||||
@@ -3094,9 +3063,9 @@ version = "0.2.0"
|
||||
dependencies = [
|
||||
"bstr",
|
||||
"build_helper",
|
||||
"gimli 0.31.1",
|
||||
"gimli",
|
||||
"libc",
|
||||
"object 0.36.7",
|
||||
"object",
|
||||
"regex",
|
||||
"serde_json",
|
||||
"similar",
|
||||
@@ -3403,11 +3372,11 @@ name = "rustc_codegen_llvm"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"gimli 0.31.1",
|
||||
"gimli",
|
||||
"itertools",
|
||||
"libc",
|
||||
"measureme",
|
||||
"object 0.36.7",
|
||||
"object",
|
||||
"rustc-demangle",
|
||||
"rustc_abi",
|
||||
"rustc_ast",
|
||||
@@ -3448,7 +3417,7 @@ dependencies = [
|
||||
"either",
|
||||
"itertools",
|
||||
"libc",
|
||||
"object 0.36.7",
|
||||
"object",
|
||||
"pathdiff",
|
||||
"regex",
|
||||
"rustc_abi",
|
||||
@@ -4330,6 +4299,7 @@ dependencies = [
|
||||
"rustc_arena",
|
||||
"rustc_ast",
|
||||
"rustc_ast_pretty",
|
||||
"rustc_attr_data_structures",
|
||||
"rustc_attr_parsing",
|
||||
"rustc_data_structures",
|
||||
"rustc_errors",
|
||||
@@ -4465,7 +4435,7 @@ name = "rustc_target"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"object 0.36.7",
|
||||
"object",
|
||||
"rustc_abi",
|
||||
"rustc_data_structures",
|
||||
"rustc_fs_util",
|
||||
@@ -5229,9 +5199,9 @@ version = "0.9.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9e9c1e705f82a260173f3eec93f2ff6d7807f23ad5a8cc2e7316a891733ea7a1"
|
||||
dependencies = [
|
||||
"gimli 0.31.1",
|
||||
"gimli",
|
||||
"hashbrown",
|
||||
"object 0.36.7",
|
||||
"object",
|
||||
"tracing",
|
||||
]
|
||||
|
||||
|
||||
+166
@@ -1,3 +1,169 @@
|
||||
Version 1.87.0 (2025-05-15)
|
||||
==========================
|
||||
|
||||
<a id="1.87.0-Language"></a>
|
||||
|
||||
Language
|
||||
--------
|
||||
- [Stabilize `asm_goto` feature](https://github.com/rust-lang/rust/pull/133870)
|
||||
- [Allow parsing open beginning ranges (`..EXPR`) after unary operators `!`, `-`, and `*`](https://github.com/rust-lang/rust/pull/134900).
|
||||
- [Don't require method impls for methods with `Self: Sized` bounds in `impl`s for unsized types](https://github.com/rust-lang/rust/pull/135480)
|
||||
- [Stabilize `feature(precise_capturing_in_traits)` allowing `use<...>` bounds on return position `impl Trait` in `trait`s](https://github.com/rust-lang/rust/pull/138128)
|
||||
|
||||
<a id="1.87.0-Compiler"></a>
|
||||
|
||||
Compiler
|
||||
--------
|
||||
- [x86: make SSE2 required for i686 targets and use it to pass SIMD types](https://github.com/rust-lang/rust/pull/135408)
|
||||
|
||||
<a id="1.87.0-Platform-Support"></a>
|
||||
|
||||
Platform Support
|
||||
----------------
|
||||
- [Remove `i586-pc-windows-msvc` target](https://github.com/rust-lang/rust/pull/137957)
|
||||
|
||||
Refer to Rust's [platform support page][platform-support-doc]
|
||||
for more information on Rust's tiered platform support.
|
||||
|
||||
[platform-support-doc]: https://doc.rust-lang.org/rustc/platform-support.html
|
||||
|
||||
<a id="1.87.0-Libraries"></a>
|
||||
|
||||
Libraries
|
||||
---------
|
||||
- [Stabilize the anonymous pipe API](https://github.com/rust-lang/rust/issues/127154)
|
||||
- [Add support for unbounded left/right shift operations](https://github.com/rust-lang/rust/issues/129375)
|
||||
- [Print pointer metadata in `Debug` impl of raw pointers](https://github.com/rust-lang/rust/pull/135080)
|
||||
- [`Vec::with_capacity` guarantees it allocates with the amount requested, even if `Vec::capacity` returns a different number.](https://github.com/rust-lang/rust/pull/135933)
|
||||
- Most `std::arch` intrinsics which don't take pointer arguments can now be called from safe code if the caller has the appropriate target features already enabled (https://github.com/rust-lang/stdarch/pull/1714, https://github.com/rust-lang/stdarch/pull/1716, https://github.com/rust-lang/stdarch/pull/1717)
|
||||
- [Undeprecate `env::home_dir`](https://github.com/rust-lang/rust/pull/137327)
|
||||
- [Denote `ControlFlow` as `#[must_use]`](https://github.com/rust-lang/rust/pull/137449)
|
||||
- [Macros such as `assert_eq!` and `vec!` now support `const {...}` expressions](https://github.com/rust-lang/rust/pull/138162)
|
||||
|
||||
<a id="1.87.0-Stabilized-APIs"></a>
|
||||
|
||||
Stabilized APIs
|
||||
---------------
|
||||
|
||||
- [`Vec::extract_if`](https://doc.rust-lang.org/stable/std/vec/struct.Vec.html#method.extract_if)
|
||||
- [`vec::ExtractIf`](https://doc.rust-lang.org/stable/std/vec/struct.ExtractIf.html)
|
||||
- [`LinkedList::extract_if`](https://doc.rust-lang.org/stable/std/collections/struct.LinkedList.html#method.extract_if)
|
||||
- [`linked_list::ExtractIf`](https://doc.rust-lang.org/stable/std/collections/linked_list/struct.ExtractIf.html)
|
||||
- [`<[T]>::split_off`](https://doc.rust-lang.org/stable/std/primitive.slice.html#method.split_off)
|
||||
- [`<[T]>::split_off_mut`](https://doc.rust-lang.org/stable/std/primitive.slice.html#method.split_off_mut)
|
||||
- [`<[T]>::split_off_first`](https://doc.rust-lang.org/stable/std/primitive.slice.html#method.split_off_first)
|
||||
- [`<[T]>::split_off_first_mut`](https://doc.rust-lang.org/stable/std/primitive.slice.html#method.split_off_first_mut)
|
||||
- [`<[T]>::split_off_last`](https://doc.rust-lang.org/stable/std/primitive.slice.html#method.split_off_last)
|
||||
- [`<[T]>::split_off_last_mut`](https://doc.rust-lang.org/stable/std/primitive.slice.html#method.split_off_last_mut)
|
||||
- [`String::extend_from_within`](https://doc.rust-lang.org/stable/alloc/string/struct.String.html#method.extend_from_within)
|
||||
- [`os_str::Display`](https://doc.rust-lang.org/stable/std/ffi/os_str/struct.Display.html)
|
||||
- [`OsString::display`](https://doc.rust-lang.org/stable/std/ffi/struct.OsString.html#method.display)
|
||||
- [`OsStr::display`](https://doc.rust-lang.org/stable/std/ffi/struct.OsStr.html#method.display)
|
||||
- [`io::pipe`](https://doc.rust-lang.org/stable/std/io/fn.pipe.html)
|
||||
- [`io::PipeReader`](https://doc.rust-lang.org/stable/std/io/struct.PipeReader.html)
|
||||
- [`io::PipeWriter`](https://doc.rust-lang.org/stable/std/io/struct.PipeWriter.html)
|
||||
- [`impl From<PipeReader> for OwnedHandle`](https://doc.rust-lang.org/stable/std/os/windows/io/struct.OwnedHandle.html#impl-From%3CPipeReader%3E-for-OwnedHandle)
|
||||
- [`impl From<PipeWriter> for OwnedHandle`](https://doc.rust-lang.org/stable/std/os/windows/io/struct.OwnedHandle.html#impl-From%3CPipeWriter%3E-for-OwnedHandle)
|
||||
- [`impl From<PipeReader> for Stdio`](https://doc.rust-lang.org/stable/std/process/struct.Stdio.html)
|
||||
- [`impl From<PipeWriter> for Stdio`](https://doc.rust-lang.org/stable/std/process/struct.Stdio.html#impl-From%3CPipeWriter%3E-for-Stdio)
|
||||
- [`impl From<PipeReader> for OwnedFd`](https://doc.rust-lang.org/stable/std/os/fd/struct.OwnedFd.html#impl-From%3CPipeReader%3E-for-OwnedFd)
|
||||
- [`impl From<PipeWriter> for OwnedFd`](https://doc.rust-lang.org/stable/std/os/fd/struct.OwnedFd.html#impl-From%3CPipeWriter%3E-for-OwnedFd)
|
||||
- [`Box<MaybeUninit<T>>::write`](https://doc.rust-lang.org/stable/std/boxed/struct.Box.html#method.write)
|
||||
- [`impl TryFrom<Vec<u8>> for String`](https://doc.rust-lang.org/stable/std/string/struct.String.html#impl-TryFrom%3CVec%3Cu8%3E%3E-for-String)
|
||||
- [`<*const T>::offset_from_unsigned`](https://doc.rust-lang.org/stable/std/primitive.pointer.html#method.offset_from_unsigned)
|
||||
- [`<*const T>::byte_offset_from_unsigned`](https://doc.rust-lang.org/stable/std/primitive.pointer.html#method.byte_offset_from_unsigned)
|
||||
- [`<*mut T>::offset_from_unsigned`](https://doc.rust-lang.org/stable/std/primitive.pointer.html#method.offset_from_unsigned-1)
|
||||
- [`<*mut T>::byte_offset_from_unsigned`](https://doc.rust-lang.org/stable/std/primitive.pointer.html#method.byte_offset_from_unsigned-1)
|
||||
- [`NonNull::offset_from_unsigned`](https://doc.rust-lang.org/stable/std/ptr/struct.NonNull.html#method.offset_from_unsigned)
|
||||
- [`NonNull::byte_offset_from_unsigned`](https://doc.rust-lang.org/stable/std/ptr/struct.NonNull.html#method.byte_offset_from_unsigned)
|
||||
- [`<uN>::cast_signed`](https://doc.rust-lang.org/stable/std/primitive.usize.html#method.cast_signed)
|
||||
- [`NonZero::<uN>::cast_signed`](https://doc.rust-lang.org/stable/std/num/struct.NonZero.html#method.cast_signed-5).
|
||||
- [`<iN>::cast_unsigned`](https://doc.rust-lang.org/stable/std/primitive.isize.html#method.cast_unsigned).
|
||||
- [`NonZero::<iN>::cast_unsigned`](https://doc.rust-lang.org/stable/std/num/struct.NonZero.html#method.cast_unsigned-5).
|
||||
- [`<uN>::is_multiple_of`](https://doc.rust-lang.org/stable/std/primitive.usize.html#method.is_multiple_of)
|
||||
- [`<uN>::unbounded_shl`](https://doc.rust-lang.org/stable/std/primitive.usize.html#method.unbounded_shl)
|
||||
- [`<uN>::unbounded_shr`](https://doc.rust-lang.org/stable/std/primitive.usize.html#method.unbounded_shr)
|
||||
- [`<iN>::unbounded_shl`](https://doc.rust-lang.org/stable/std/primitive.isize.html#method.unbounded_shl)
|
||||
- [`<iN>::unbounded_shr`](https://doc.rust-lang.org/stable/std/primitive.isize.html#method.unbounded_shr)
|
||||
- [`<iN>::midpoint`](https://doc.rust-lang.org/stable/std/primitive.isize.html#method.midpoint)
|
||||
- [`<str>::from_utf8`](https://doc.rust-lang.org/stable/std/primitive.str.html#method.from_utf8)
|
||||
- [`<str>::from_utf8_mut`](https://doc.rust-lang.org/stable/std/primitive.str.html#method.from_utf8_mut)
|
||||
- [`<str>::from_utf8_unchecked`](https://doc.rust-lang.org/stable/std/primitive.str.html#method.from_utf8_unchecked)
|
||||
- [`<str>::from_utf8_unchecked_mut`](https://doc.rust-lang.org/stable/std/primitive.str.html#method.from_utf8_unchecked_mut)
|
||||
|
||||
These previously stable APIs are now stable in const contexts:
|
||||
|
||||
- [`core::str::from_utf8_mut`](https://doc.rust-lang.org/stable/std/str/fn.from_utf8_mut.html)
|
||||
- [`<[T]>::copy_from_slice`](https://doc.rust-lang.org/stable/std/primitive.slice.html#method.copy_from_slice)
|
||||
- [`SocketAddr::set_ip`](https://doc.rust-lang.org/stable/std/net/enum.SocketAddr.html#method.set_ip)
|
||||
- [`SocketAddr::set_port`](https://doc.rust-lang.org/stable/std/net/enum.SocketAddr.html#method.set_port),
|
||||
- [`SocketAddrV4::set_ip`](https://doc.rust-lang.org/stable/std/net/struct.SocketAddrV4.html#method.set_ip)
|
||||
- [`SocketAddrV4::set_port`](https://doc.rust-lang.org/stable/std/net/struct.SocketAddrV4.html#method.set_port),
|
||||
- [`SocketAddrV6::set_ip`](https://doc.rust-lang.org/stable/std/net/struct.SocketAddrV6.html#method.set_ip)
|
||||
- [`SocketAddrV6::set_port`](https://doc.rust-lang.org/stable/std/net/struct.SocketAddrV6.html#method.set_port)
|
||||
- [`SocketAddrV6::set_flowinfo`](https://doc.rust-lang.org/stable/std/net/struct.SocketAddrV6.html#method.set_flowinfo)
|
||||
- [`SocketAddrV6::set_scope_id`](https://doc.rust-lang.org/stable/std/net/struct.SocketAddrV6.html#method.set_scope_id)
|
||||
- [`char::is_digit`](https://doc.rust-lang.org/stable/std/primitive.char.html#method.is_digit)
|
||||
- [`char::is_whitespace`](https://doc.rust-lang.org/stable/std/primitive.char.html#method.is_whitespace)
|
||||
- [`<[[T; N]]>::as_flattened`](https://doc.rust-lang.org/stable/std/primitive.slice.html#method.as_flattened)
|
||||
- [`<[[T; N]]>::as_flattened_mut`](https://doc.rust-lang.org/stable/std/primitive.slice.html#method.as_flattened_mut)
|
||||
- [`String::into_bytes`](https://doc.rust-lang.org/stable/std/string/struct.String.html#method.into_bytes)
|
||||
- [`String::as_str`](https://doc.rust-lang.org/stable/std/string/struct.String.html#method.as_str)
|
||||
- [`String::capacity`](https://doc.rust-lang.org/stable/std/string/struct.String.html#method.capacity)
|
||||
- [`String::as_bytes`](https://doc.rust-lang.org/stable/std/string/struct.String.html#method.as_bytes)
|
||||
- [`String::len`](https://doc.rust-lang.org/stable/std/string/struct.String.html#method.len)
|
||||
- [`String::is_empty`](https://doc.rust-lang.org/stable/std/string/struct.String.html#method.is_empty)
|
||||
- [`String::as_mut_str`](https://doc.rust-lang.org/stable/std/string/struct.String.html#method.as_mut_str)
|
||||
- [`String::as_mut_vec`](https://doc.rust-lang.org/stable/std/string/struct.String.html#method.as_mut_vec)
|
||||
- [`Vec::as_ptr`](https://doc.rust-lang.org/stable/std/vec/struct.Vec.html#method.as_ptr)
|
||||
- [`Vec::as_slice`](https://doc.rust-lang.org/stable/std/vec/struct.Vec.html#method.as_slice)
|
||||
- [`Vec::capacity`](https://doc.rust-lang.org/stable/std/vec/struct.Vec.html#method.capacity)
|
||||
- [`Vec::len`](https://doc.rust-lang.org/stable/std/vec/struct.Vec.html#method.len)
|
||||
- [`Vec::is_empty`](https://doc.rust-lang.org/stable/std/vec/struct.Vec.html#method.is_empty)
|
||||
- [`Vec::as_mut_slice`](https://doc.rust-lang.org/stable/std/vec/struct.Vec.html#method.as_mut_slice)
|
||||
- [`Vec::as_mut_ptr`](https://doc.rust-lang.org/stable/std/vec/struct.Vec.html#method.as_mut_ptr)
|
||||
|
||||
<a id="1.87.0-Cargo"></a>
|
||||
|
||||
Cargo
|
||||
-----
|
||||
- [Add terminal integration via ANSI OSC 9;4 sequences](https://github.com/rust-lang/cargo/pull/14615/)
|
||||
- [chore: bump openssl to v3](https://github.com/rust-lang/cargo/pull/15232/)
|
||||
- [feat(package): add --exclude-lockfile flag](https://github.com/rust-lang/cargo/pull/15234/)
|
||||
|
||||
<a id="1.87.0-Compatibility-Notes"></a>
|
||||
|
||||
Compatibility Notes
|
||||
-------------------
|
||||
- [Rust now raises an error for macro invocations inside the `#![crate_name]` attribute](https://github.com/rust-lang/rust/pull/127581)
|
||||
- [Unstable fields are now always considered to be inhabited](https://github.com/rust-lang/rust/pull/133889)
|
||||
- [Macro arguments of unary operators followed by open beginning ranges may now be matched differently](https://github.com/rust-lang/rust/pull/134900)
|
||||
- [Make `Debug` impl of raw pointers print metadata if present](https://github.com/rust-lang/rust/pull/135080)
|
||||
- [Warn against function pointers using unsupported ABI strings in dependencies](https://github.com/rust-lang/rust/pull/135767)
|
||||
- [Associated types on `dyn` types are no longer deduplicated](https://github.com/rust-lang/rust/pull/136458)
|
||||
- [Forbid attributes on `..` inside of struct patterns (`let Struct { #[attribute] .. }) =`](https://github.com/rust-lang/rust/pull/136490)
|
||||
- [Make `ptr_cast_add_auto_to_object` lint into hard error](https://github.com/rust-lang/rust/pull/136764)
|
||||
- Many `std::arch` intrinsics are now safe to call in some contexts, there may now be new `unused_unsafe` warnings in existing codebases.
|
||||
- [Limit `width` and `precision` formatting options to 16 bits on all targets](https://github.com/rust-lang/rust/pull/136932)
|
||||
- [Turn order dependent trait objects future incompat warning into a hard error](https://github.com/rust-lang/rust/pull/136968)
|
||||
- [Denote `ControlFlow` as `#[must_use]`](https://github.com/rust-lang/rust/pull/137449)
|
||||
- [Windows: The standard library no longer links `advapi32`, except on win7.](https://github.com/rust-lang/rust/pull/138233) Code such as C libraries that were relying on this assumption may need to explicitly link advapi32.
|
||||
- [Proc macros can no longer observe expanded `cfg(true)` attributes.](https://github.com/rust-lang/rust/pull/138844)
|
||||
- [Start changing the internal representation of pasted tokens](https://github.com/rust-lang/rust/pull/124141). Certain invalid declarative macros that were previously accepted in obscure circumstances are now correctly rejected by the compiler. Use of a `tt` fragment specifier can often fix these macros.
|
||||
- [Don't allow flattened format_args in const.](https://github.com/rust-lang/rust/pull/139624)
|
||||
|
||||
<a id="1.87.0-Internal-Changes"></a>
|
||||
|
||||
Internal Changes
|
||||
----------------
|
||||
|
||||
These changes do not affect any public interfaces of Rust, but they represent
|
||||
significant improvements to the performance or internals of rustc and related
|
||||
tools.
|
||||
|
||||
- [Update to LLVM 20](https://github.com/rust-lang/rust/pull/135763)
|
||||
|
||||
|
||||
Version 1.86.0 (2025-04-03)
|
||||
==========================
|
||||
|
||||
|
||||
@@ -308,7 +308,6 @@ pub fn as_angle_bracketed_args(&self) -> AngleBracketedArgs {
|
||||
}
|
||||
}
|
||||
|
||||
use crate::AstDeref;
|
||||
pub use crate::node_id::{CRATE_NODE_ID, DUMMY_NODE_ID, NodeId};
|
||||
|
||||
/// Modifiers on a trait bound like `~const`, `?` and `!`.
|
||||
@@ -2349,7 +2348,7 @@ pub fn peel_refs(&self) -> &Self {
|
||||
pub fn is_maybe_parenthesised_infer(&self) -> bool {
|
||||
match &self.kind {
|
||||
TyKind::Infer => true,
|
||||
TyKind::Paren(inner) => inner.ast_deref().is_maybe_parenthesised_infer(),
|
||||
TyKind::Paren(inner) => inner.is_maybe_parenthesised_infer(),
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,34 +13,6 @@
|
||||
Ty, Variant, Visibility, WherePredicate,
|
||||
};
|
||||
|
||||
/// A utility trait to reduce boilerplate.
|
||||
/// Standard `Deref(Mut)` cannot be reused due to coherence.
|
||||
pub trait AstDeref {
|
||||
type Target;
|
||||
fn ast_deref(&self) -> &Self::Target;
|
||||
fn ast_deref_mut(&mut self) -> &mut Self::Target;
|
||||
}
|
||||
|
||||
macro_rules! impl_not_ast_deref {
|
||||
($($T:ty),+ $(,)?) => {
|
||||
$(
|
||||
impl !AstDeref for $T {}
|
||||
)+
|
||||
};
|
||||
}
|
||||
|
||||
impl_not_ast_deref!(AssocItem, Expr, ForeignItem, Item, Stmt);
|
||||
|
||||
impl<T> AstDeref for P<T> {
|
||||
type Target = T;
|
||||
fn ast_deref(&self) -> &Self::Target {
|
||||
self
|
||||
}
|
||||
fn ast_deref_mut(&mut self) -> &mut Self::Target {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
/// A trait for AST nodes having an ID.
|
||||
pub trait HasNodeId {
|
||||
fn node_id(&self) -> NodeId;
|
||||
@@ -81,12 +53,12 @@ fn node_id_mut(&mut self) -> &mut NodeId {
|
||||
WherePredicate,
|
||||
);
|
||||
|
||||
impl<T: AstDeref<Target: HasNodeId>> HasNodeId for T {
|
||||
impl<T: HasNodeId> HasNodeId for P<T> {
|
||||
fn node_id(&self) -> NodeId {
|
||||
self.ast_deref().node_id()
|
||||
(**self).node_id()
|
||||
}
|
||||
fn node_id_mut(&mut self) -> &mut NodeId {
|
||||
self.ast_deref_mut().node_id_mut()
|
||||
(**self).node_id_mut()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -138,15 +110,6 @@ fn tokens_mut(&mut self) -> Option<&mut Option<LazyAttrTokenStream>> {
|
||||
WherePredicate
|
||||
);
|
||||
|
||||
impl<T: AstDeref<Target: HasTokens>> HasTokens for T {
|
||||
fn tokens(&self) -> Option<&LazyAttrTokenStream> {
|
||||
self.ast_deref().tokens()
|
||||
}
|
||||
fn tokens_mut(&mut self) -> Option<&mut Option<LazyAttrTokenStream>> {
|
||||
self.ast_deref_mut().tokens_mut()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: HasTokens> HasTokens for Option<T> {
|
||||
fn tokens(&self) -> Option<&LazyAttrTokenStream> {
|
||||
self.as_ref().and_then(|inner| inner.tokens())
|
||||
@@ -156,6 +119,15 @@ fn tokens_mut(&mut self) -> Option<&mut Option<LazyAttrTokenStream>> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: HasTokens> HasTokens for P<T> {
|
||||
fn tokens(&self) -> Option<&LazyAttrTokenStream> {
|
||||
(**self).tokens()
|
||||
}
|
||||
fn tokens_mut(&mut self) -> Option<&mut Option<LazyAttrTokenStream>> {
|
||||
(**self).tokens_mut()
|
||||
}
|
||||
}
|
||||
|
||||
impl HasTokens for StmtKind {
|
||||
fn tokens(&self) -> Option<&LazyAttrTokenStream> {
|
||||
match self {
|
||||
@@ -273,13 +245,13 @@ fn visit_attrs(&mut self, _f: impl FnOnce(&mut AttrVec)) {}
|
||||
);
|
||||
impl_has_attrs_none!(Attribute, AttrItem, Block, Pat, Path, Ty, Visibility);
|
||||
|
||||
impl<T: AstDeref<Target: HasAttrs>> HasAttrs for T {
|
||||
const SUPPORTS_CUSTOM_INNER_ATTRS: bool = T::Target::SUPPORTS_CUSTOM_INNER_ATTRS;
|
||||
impl<T: HasAttrs> HasAttrs for P<T> {
|
||||
const SUPPORTS_CUSTOM_INNER_ATTRS: bool = T::SUPPORTS_CUSTOM_INNER_ATTRS;
|
||||
fn attrs(&self) -> &[Attribute] {
|
||||
self.ast_deref().attrs()
|
||||
(**self).attrs()
|
||||
}
|
||||
fn visit_attrs(&mut self, f: impl FnOnce(&mut AttrVec)) {
|
||||
self.ast_deref_mut().visit_attrs(f)
|
||||
(**self).visit_attrs(f);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -343,13 +315,22 @@ pub fn new(wrapped: Wrapped, _tag: Tag) -> AstNodeWrapper<Wrapped, Tag> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<Wrapped, Tag> AstDeref for AstNodeWrapper<Wrapped, Tag> {
|
||||
type Target = Wrapped;
|
||||
fn ast_deref(&self) -> &Self::Target {
|
||||
&self.wrapped
|
||||
impl<Wrapped: HasNodeId, Tag> HasNodeId for AstNodeWrapper<Wrapped, Tag> {
|
||||
fn node_id(&self) -> NodeId {
|
||||
self.wrapped.node_id()
|
||||
}
|
||||
fn ast_deref_mut(&mut self) -> &mut Self::Target {
|
||||
&mut self.wrapped
|
||||
fn node_id_mut(&mut self) -> &mut NodeId {
|
||||
self.wrapped.node_id_mut()
|
||||
}
|
||||
}
|
||||
|
||||
impl<Wrapped: HasAttrs, Tag> HasAttrs for AstNodeWrapper<Wrapped, Tag> {
|
||||
const SUPPORTS_CUSTOM_INNER_ATTRS: bool = Wrapped::SUPPORTS_CUSTOM_INNER_ATTRS;
|
||||
fn attrs(&self) -> &[Attribute] {
|
||||
self.wrapped.attrs()
|
||||
}
|
||||
fn visit_attrs(&mut self, f: impl FnOnce(&mut AttrVec)) {
|
||||
self.wrapped.visit_attrs(f);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
|
||||
// tidy-alphabetical-start
|
||||
#![allow(internal_features)]
|
||||
#![cfg_attr(bootstrap, feature(let_chains))]
|
||||
#![doc(
|
||||
html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/",
|
||||
test(attr(deny(warnings)))
|
||||
@@ -46,7 +45,7 @@ pub mod util {
|
||||
pub mod visit;
|
||||
|
||||
pub use self::ast::*;
|
||||
pub use self::ast_traits::{AstDeref, AstNodeWrapper, HasAttrs, HasNodeId, HasTokens};
|
||||
pub use self::ast_traits::{AstNodeWrapper, HasAttrs, HasNodeId, HasTokens};
|
||||
|
||||
/// Requirements for a `StableHashingContext` to be used in this crate.
|
||||
/// This is a hack to allow using the `HashStable_Generic` derive macro
|
||||
|
||||
@@ -32,7 +32,6 @@
|
||||
|
||||
// tidy-alphabetical-start
|
||||
#![allow(internal_features)]
|
||||
#![cfg_attr(bootstrap, feature(let_chains))]
|
||||
#![doc(rust_logo)]
|
||||
#![feature(assert_matches)]
|
||||
#![feature(box_patterns)]
|
||||
@@ -896,7 +895,7 @@ fn lower_attrs(
|
||||
let ret = self.arena.alloc_from_iter(lowered_attrs);
|
||||
|
||||
// this is possible if an item contained syntactical attribute,
|
||||
// but none of them parse succesfully or all of them were ignored
|
||||
// but none of them parse successfully or all of them were ignored
|
||||
// for not being built-in attributes at all. They could be remaining
|
||||
// unexpanded attributes used as markers in proc-macro derives for example.
|
||||
// This will have emitted some diagnostics for the misparse, but will then
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
|
||||
// tidy-alphabetical-start
|
||||
#![allow(internal_features)]
|
||||
#![cfg_attr(bootstrap, feature(let_chains))]
|
||||
#![doc(rust_logo)]
|
||||
#![feature(box_patterns)]
|
||||
#![feature(if_let_guard)]
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
// tidy-alphabetical-start
|
||||
#![allow(internal_features)]
|
||||
#![cfg_attr(bootstrap, feature(let_chains))]
|
||||
#![doc(rust_logo)]
|
||||
#![feature(rustdoc_internals)]
|
||||
// tidy-alphabetical-end
|
||||
|
||||
@@ -53,7 +53,7 @@ fn parse_unstable<'a>(
|
||||
|
||||
for param in list.mixed() {
|
||||
let param_span = param.span();
|
||||
if let Some(ident) = param.meta_item().and_then(|i| i.word_without_args()) {
|
||||
if let Some(ident) = param.meta_item().and_then(|i| i.path_without_args().word()) {
|
||||
res.push(ident.name);
|
||||
} else {
|
||||
cx.emit_err(session_diagnostics::ExpectsFeatures {
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
use rustc_attr_data_structures::{AttributeKind, DeprecatedSince, Deprecation};
|
||||
use rustc_span::symbol::Ident;
|
||||
use rustc_span::{Span, Symbol, sym};
|
||||
|
||||
use super::SingleAttributeParser;
|
||||
@@ -13,16 +12,13 @@
|
||||
|
||||
fn get(
|
||||
cx: &AcceptContext<'_>,
|
||||
ident: Ident,
|
||||
name: Symbol,
|
||||
param_span: Span,
|
||||
arg: &ArgParser<'_>,
|
||||
item: &Option<Symbol>,
|
||||
) -> Option<Symbol> {
|
||||
if item.is_some() {
|
||||
cx.emit_err(session_diagnostics::MultipleItem {
|
||||
span: param_span,
|
||||
item: ident.to_string(),
|
||||
});
|
||||
cx.emit_err(session_diagnostics::MultipleItem { span: param_span, item: name.to_string() });
|
||||
return None;
|
||||
}
|
||||
if let Some(v) = arg.name_value() {
|
||||
@@ -83,16 +79,16 @@ fn convert(cx: &AcceptContext<'_>, args: &ArgParser<'_>) -> Option<AttributeKind
|
||||
return None;
|
||||
};
|
||||
|
||||
let (ident, arg) = param.word_or_empty();
|
||||
let ident_name = param.path_without_args().word_sym();
|
||||
|
||||
match ident.name {
|
||||
sym::since => {
|
||||
since = Some(get(cx, ident, param_span, arg, &since)?);
|
||||
match ident_name {
|
||||
Some(name @ sym::since) => {
|
||||
since = Some(get(cx, name, param_span, param.args(), &since)?);
|
||||
}
|
||||
sym::note => {
|
||||
note = Some(get(cx, ident, param_span, arg, ¬e)?);
|
||||
Some(name @ sym::note) => {
|
||||
note = Some(get(cx, name, param_span, param.args(), ¬e)?);
|
||||
}
|
||||
sym::suggestion => {
|
||||
Some(name @ sym::suggestion) => {
|
||||
if !features.deprecated_suggestion() {
|
||||
cx.emit_err(session_diagnostics::DeprecatedItemSuggestion {
|
||||
span: param_span,
|
||||
@@ -101,12 +97,12 @@ fn convert(cx: &AcceptContext<'_>, args: &ArgParser<'_>) -> Option<AttributeKind
|
||||
});
|
||||
}
|
||||
|
||||
suggestion = Some(get(cx, ident, param_span, arg, &suggestion)?);
|
||||
suggestion = Some(get(cx, name, param_span, param.args(), &suggestion)?);
|
||||
}
|
||||
_ => {
|
||||
cx.emit_err(session_diagnostics::UnknownMetaItem {
|
||||
span: param_span,
|
||||
item: ident.to_string(),
|
||||
item: param.path_without_args().to_string(),
|
||||
expected: if features.deprecated_suggestion() {
|
||||
&["since", "note", "suggestion"]
|
||||
} else {
|
||||
|
||||
@@ -96,58 +96,75 @@ fn parse_repr(cx: &AcceptContext<'_>, param: &MetaItemParser<'_>) -> Option<Repr
|
||||
|
||||
// FIXME(jdonszelmann): invert the parsing here to match on the word first and then the
|
||||
// structure.
|
||||
let (ident, args) = param.word_or_empty();
|
||||
let (name, ident_span) = if let Some(ident) = param.path_without_args().word() {
|
||||
(Some(ident.name), ident.span)
|
||||
} else {
|
||||
(None, rustc_span::DUMMY_SP)
|
||||
};
|
||||
|
||||
match (ident.name, args) {
|
||||
(sym::align, ArgParser::NoArgs) => {
|
||||
cx.emit_err(session_diagnostics::InvalidReprAlignNeedArg { span: ident.span });
|
||||
let args = param.args();
|
||||
|
||||
match (name, args) {
|
||||
(Some(sym::align), ArgParser::NoArgs) => {
|
||||
cx.emit_err(session_diagnostics::InvalidReprAlignNeedArg { span: ident_span });
|
||||
None
|
||||
}
|
||||
(sym::align, ArgParser::List(l)) => parse_repr_align(cx, l, param.span(), AlignKind::Align),
|
||||
(Some(sym::align), ArgParser::List(l)) => {
|
||||
parse_repr_align(cx, l, param.span(), AlignKind::Align)
|
||||
}
|
||||
|
||||
(sym::packed, ArgParser::NoArgs) => Some(ReprPacked(Align::ONE)),
|
||||
(sym::packed, ArgParser::List(l)) => {
|
||||
(Some(sym::packed), ArgParser::NoArgs) => Some(ReprPacked(Align::ONE)),
|
||||
(Some(sym::packed), ArgParser::List(l)) => {
|
||||
parse_repr_align(cx, l, param.span(), AlignKind::Packed)
|
||||
}
|
||||
|
||||
(sym::align | sym::packed, ArgParser::NameValue(l)) => {
|
||||
(Some(name @ sym::align | name @ sym::packed), ArgParser::NameValue(l)) => {
|
||||
cx.emit_err(session_diagnostics::IncorrectReprFormatGeneric {
|
||||
span: param.span(),
|
||||
// FIXME(jdonszelmann) can just be a string in the diag type
|
||||
repr_arg: &ident.to_string(),
|
||||
repr_arg: name,
|
||||
cause: IncorrectReprFormatGenericCause::from_lit_kind(
|
||||
param.span(),
|
||||
&l.value_as_lit().kind,
|
||||
ident.name.as_str(),
|
||||
name,
|
||||
),
|
||||
});
|
||||
None
|
||||
}
|
||||
|
||||
(sym::Rust, ArgParser::NoArgs) => Some(ReprRust),
|
||||
(sym::C, ArgParser::NoArgs) => Some(ReprC),
|
||||
(sym::simd, ArgParser::NoArgs) => Some(ReprSimd),
|
||||
(sym::transparent, ArgParser::NoArgs) => Some(ReprTransparent),
|
||||
(i @ int_pat!(), ArgParser::NoArgs) => {
|
||||
(Some(sym::Rust), ArgParser::NoArgs) => Some(ReprRust),
|
||||
(Some(sym::C), ArgParser::NoArgs) => Some(ReprC),
|
||||
(Some(sym::simd), ArgParser::NoArgs) => Some(ReprSimd),
|
||||
(Some(sym::transparent), ArgParser::NoArgs) => Some(ReprTransparent),
|
||||
(Some(name @ int_pat!()), ArgParser::NoArgs) => {
|
||||
// int_pat!() should make sure it always parses
|
||||
Some(ReprInt(int_type_of_word(i).unwrap()))
|
||||
Some(ReprInt(int_type_of_word(name).unwrap()))
|
||||
}
|
||||
|
||||
(
|
||||
sym::Rust | sym::C | sym::simd | sym::transparent | int_pat!(),
|
||||
Some(
|
||||
name @ sym::Rust
|
||||
| name @ sym::C
|
||||
| name @ sym::simd
|
||||
| name @ sym::transparent
|
||||
| name @ int_pat!(),
|
||||
),
|
||||
ArgParser::NameValue(_),
|
||||
) => {
|
||||
cx.emit_err(session_diagnostics::InvalidReprHintNoValue {
|
||||
span: param.span(),
|
||||
name: ident.to_string(),
|
||||
});
|
||||
cx.emit_err(session_diagnostics::InvalidReprHintNoValue { span: param.span(), name });
|
||||
None
|
||||
}
|
||||
(sym::Rust | sym::C | sym::simd | sym::transparent | int_pat!(), ArgParser::List(_)) => {
|
||||
cx.emit_err(session_diagnostics::InvalidReprHintNoParen {
|
||||
span: param.span(),
|
||||
name: ident.to_string(),
|
||||
});
|
||||
(
|
||||
Some(
|
||||
name @ sym::Rust
|
||||
| name @ sym::C
|
||||
| name @ sym::simd
|
||||
| name @ sym::transparent
|
||||
| name @ int_pat!(),
|
||||
),
|
||||
ArgParser::List(_),
|
||||
) => {
|
||||
cx.emit_err(session_diagnostics::InvalidReprHintNoParen { span: param.span(), name });
|
||||
None
|
||||
}
|
||||
|
||||
|
||||
@@ -242,9 +242,9 @@ pub(crate) fn parse_stability(
|
||||
return None;
|
||||
};
|
||||
|
||||
match param.word_or_empty_without_args().name {
|
||||
sym::feature => insert_value_into_option_or_error(cx, ¶m, &mut feature)?,
|
||||
sym::since => insert_value_into_option_or_error(cx, ¶m, &mut since)?,
|
||||
match param.path_without_args().word_sym() {
|
||||
Some(sym::feature) => insert_value_into_option_or_error(cx, ¶m, &mut feature)?,
|
||||
Some(sym::since) => insert_value_into_option_or_error(cx, ¶m, &mut since)?,
|
||||
_ => {
|
||||
cx.emit_err(session_diagnostics::UnknownMetaItem {
|
||||
span: param_span,
|
||||
@@ -310,11 +310,10 @@ pub(crate) fn parse_unstability(
|
||||
return None;
|
||||
};
|
||||
|
||||
let (word, args) = param.word_or_empty();
|
||||
match word.name {
|
||||
sym::feature => insert_value_into_option_or_error(cx, ¶m, &mut feature)?,
|
||||
sym::reason => insert_value_into_option_or_error(cx, ¶m, &mut reason)?,
|
||||
sym::issue => {
|
||||
match param.path_without_args().word_sym() {
|
||||
Some(sym::feature) => insert_value_into_option_or_error(cx, ¶m, &mut feature)?,
|
||||
Some(sym::reason) => insert_value_into_option_or_error(cx, ¶m, &mut reason)?,
|
||||
Some(sym::issue) => {
|
||||
insert_value_into_option_or_error(cx, ¶m, &mut issue)?;
|
||||
|
||||
// These unwraps are safe because `insert_value_into_option_or_error` ensures the meta item
|
||||
@@ -328,7 +327,7 @@ pub(crate) fn parse_unstability(
|
||||
session_diagnostics::InvalidIssueString {
|
||||
span: param.span(),
|
||||
cause: session_diagnostics::InvalidIssueStringCause::from_int_error_kind(
|
||||
args.name_value().unwrap().value_span,
|
||||
param.args().name_value().unwrap().value_span,
|
||||
err.kind(),
|
||||
),
|
||||
},
|
||||
@@ -338,13 +337,15 @@ pub(crate) fn parse_unstability(
|
||||
},
|
||||
};
|
||||
}
|
||||
sym::soft => {
|
||||
if !args.no_args() {
|
||||
Some(sym::soft) => {
|
||||
if !param.args().no_args() {
|
||||
cx.emit_err(session_diagnostics::SoftNoArgs { span: param.span() });
|
||||
}
|
||||
is_soft = true;
|
||||
}
|
||||
sym::implied_by => insert_value_into_option_or_error(cx, ¶m, &mut implied_by)?,
|
||||
Some(sym::implied_by) => {
|
||||
insert_value_into_option_or_error(cx, ¶m, &mut implied_by)?
|
||||
}
|
||||
_ => {
|
||||
cx.emit_err(session_diagnostics::UnknownMetaItem {
|
||||
span: param.span(),
|
||||
|
||||
@@ -77,7 +77,6 @@
|
||||
|
||||
// tidy-alphabetical-start
|
||||
#![allow(internal_features)]
|
||||
#![cfg_attr(bootstrap, feature(let_chains))]
|
||||
#![doc(rust_logo)]
|
||||
#![feature(rustdoc_internals)]
|
||||
#![recursion_limit = "256"]
|
||||
|
||||
@@ -78,8 +78,8 @@ pub fn word(&self) -> Option<Ident> {
|
||||
(self.len() == 1).then(|| **self.segments().next().as_ref().unwrap())
|
||||
}
|
||||
|
||||
pub fn word_or_empty(&self) -> Ident {
|
||||
self.word().unwrap_or_else(Ident::empty)
|
||||
pub fn word_sym(&self) -> Option<Symbol> {
|
||||
self.word().map(|ident| ident.name)
|
||||
}
|
||||
|
||||
/// Asserts that this MetaItem is some specific word.
|
||||
@@ -284,11 +284,6 @@ pub fn word_without_args(&self) -> Option<Ident> {
|
||||
Some(self.word()?.0)
|
||||
}
|
||||
|
||||
/// Like [`word`](Self::word), but returns an empty symbol instead of None
|
||||
pub fn word_or_empty_without_args(&self) -> Ident {
|
||||
self.word_or_empty().0
|
||||
}
|
||||
|
||||
/// Asserts that this MetaItem starts with a word, or single segment path.
|
||||
///
|
||||
/// Some examples:
|
||||
@@ -300,12 +295,6 @@ pub fn word(&self) -> Option<(Ident, &ArgParser<'a>)> {
|
||||
Some((path.word()?, args))
|
||||
}
|
||||
|
||||
/// Like [`word`](Self::word), but returns an empty symbol instead of None
|
||||
pub fn word_or_empty(&self) -> (Ident, &ArgParser<'a>) {
|
||||
let (path, args) = self.deconstruct();
|
||||
(path.word().unwrap_or(Ident::empty()), args)
|
||||
}
|
||||
|
||||
/// Asserts that this MetaItem starts with some specific word.
|
||||
///
|
||||
/// See [`word`](Self::word) for examples of what a word is.
|
||||
|
||||
@@ -204,7 +204,7 @@ pub(crate) struct InvalidReprHintNoParen {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
|
||||
pub name: String,
|
||||
pub name: Symbol,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
@@ -213,7 +213,7 @@ pub(crate) struct InvalidReprHintNoValue {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
|
||||
pub name: String,
|
||||
pub name: Symbol,
|
||||
}
|
||||
|
||||
/// Error code: E0565
|
||||
@@ -295,21 +295,21 @@ pub(crate) struct IncorrectReprFormatExpectInteger {
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(attr_parsing_incorrect_repr_format_generic, code = E0693)]
|
||||
pub(crate) struct IncorrectReprFormatGeneric<'a> {
|
||||
pub(crate) struct IncorrectReprFormatGeneric {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
|
||||
pub repr_arg: &'a str,
|
||||
pub repr_arg: Symbol,
|
||||
|
||||
#[subdiagnostic]
|
||||
pub cause: Option<IncorrectReprFormatGenericCause<'a>>,
|
||||
pub cause: Option<IncorrectReprFormatGenericCause>,
|
||||
}
|
||||
|
||||
#[derive(Subdiagnostic)]
|
||||
pub(crate) enum IncorrectReprFormatGenericCause<'a> {
|
||||
pub(crate) enum IncorrectReprFormatGenericCause {
|
||||
#[suggestion(
|
||||
attr_parsing_suggestion,
|
||||
code = "{name}({int})",
|
||||
code = "{name}({value})",
|
||||
applicability = "machine-applicable"
|
||||
)]
|
||||
Int {
|
||||
@@ -317,15 +317,15 @@ pub(crate) enum IncorrectReprFormatGenericCause<'a> {
|
||||
span: Span,
|
||||
|
||||
#[skip_arg]
|
||||
name: &'a str,
|
||||
name: Symbol,
|
||||
|
||||
#[skip_arg]
|
||||
int: u128,
|
||||
value: u128,
|
||||
},
|
||||
|
||||
#[suggestion(
|
||||
attr_parsing_suggestion,
|
||||
code = "{name}({symbol})",
|
||||
code = "{name}({value})",
|
||||
applicability = "machine-applicable"
|
||||
)]
|
||||
Symbol {
|
||||
@@ -333,20 +333,20 @@ pub(crate) enum IncorrectReprFormatGenericCause<'a> {
|
||||
span: Span,
|
||||
|
||||
#[skip_arg]
|
||||
name: &'a str,
|
||||
name: Symbol,
|
||||
|
||||
#[skip_arg]
|
||||
symbol: Symbol,
|
||||
value: Symbol,
|
||||
},
|
||||
}
|
||||
|
||||
impl<'a> IncorrectReprFormatGenericCause<'a> {
|
||||
pub(crate) fn from_lit_kind(span: Span, kind: &ast::LitKind, name: &'a str) -> Option<Self> {
|
||||
match kind {
|
||||
ast::LitKind::Int(int, ast::LitIntType::Unsuffixed) => {
|
||||
Some(Self::Int { span, name, int: int.get() })
|
||||
impl IncorrectReprFormatGenericCause {
|
||||
pub(crate) fn from_lit_kind(span: Span, kind: &ast::LitKind, name: Symbol) -> Option<Self> {
|
||||
match *kind {
|
||||
ast::LitKind::Int(value, ast::LitIntType::Unsuffixed) => {
|
||||
Some(Self::Int { span, name, value: value.get() })
|
||||
}
|
||||
ast::LitKind::Str(symbol, _) => Some(Self::Symbol { span, name, symbol: *symbol }),
|
||||
ast::LitKind::Str(value, _) => Some(Self::Symbol { span, name, value }),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
|
||||
// tidy-alphabetical-start
|
||||
#![allow(internal_features)]
|
||||
#![cfg_attr(bootstrap, feature(let_chains))]
|
||||
#![doc(rust_logo)]
|
||||
#![feature(assert_matches)]
|
||||
#![feature(box_patterns)]
|
||||
|
||||
@@ -266,10 +266,6 @@ impl<'tcx, OP> TypeVisitor<TyCtxt<'tcx>> for ConstrainOpaqueTypeRegionVisitor<'t
|
||||
where
|
||||
OP: FnMut(ty::Region<'tcx>),
|
||||
{
|
||||
fn visit_binder<T: TypeVisitable<TyCtxt<'tcx>>>(&mut self, t: &ty::Binder<'tcx, T>) {
|
||||
t.super_visit_with(self);
|
||||
}
|
||||
|
||||
fn visit_region(&mut self, r: ty::Region<'tcx>) {
|
||||
match r.kind() {
|
||||
// ignore bound regions, keep visiting
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
|
||||
use rustc_ast::token::{self, LitKind};
|
||||
use rustc_ast::tokenstream::TokenStream;
|
||||
use rustc_ast::{AstDeref, ExprKind, GenericArg, Mutability};
|
||||
use rustc_ast::{ExprKind, GenericArg, Mutability};
|
||||
use rustc_expand::base::{DummyResult, ExpandResult, ExtCtxt, MacEager, MacroExpanderResult};
|
||||
use rustc_span::{Ident, Span, Symbol, kw, sym};
|
||||
use thin_vec::thin_vec;
|
||||
@@ -148,13 +148,13 @@ pub(crate) fn expand_env<'cx>(
|
||||
cx.dcx().emit_err(errors::EnvNotDefined::CargoEnvVar {
|
||||
span,
|
||||
var: *symbol,
|
||||
var_expr: var_expr.ast_deref(),
|
||||
var_expr: &var_expr,
|
||||
})
|
||||
} else {
|
||||
cx.dcx().emit_err(errors::EnvNotDefined::CustomEnvVar {
|
||||
span,
|
||||
var: *symbol,
|
||||
var_expr: var_expr.ast_deref(),
|
||||
var_expr: &var_expr,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
#![allow(internal_features)]
|
||||
#![allow(rustc::diagnostic_outside_of_impl)]
|
||||
#![allow(rustc::untranslatable_diagnostic)]
|
||||
#![cfg_attr(bootstrap, feature(let_chains))]
|
||||
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
|
||||
#![doc(rust_logo)]
|
||||
#![feature(assert_matches)]
|
||||
|
||||
@@ -1109,6 +1109,43 @@ fn codegen_regular_intrinsic_call<'tcx>(
|
||||
ret.write_cvalue(fx, old);
|
||||
}
|
||||
|
||||
sym::minimumf32 => {
|
||||
intrinsic_args!(fx, args => (a, b); intrinsic);
|
||||
let a = a.load_scalar(fx);
|
||||
let b = b.load_scalar(fx);
|
||||
|
||||
let val = fx.bcx.ins().fmin(a, b);
|
||||
let val = CValue::by_val(val, fx.layout_of(fx.tcx.types.f32));
|
||||
ret.write_cvalue(fx, val);
|
||||
}
|
||||
sym::minimumf64 => {
|
||||
intrinsic_args!(fx, args => (a, b); intrinsic);
|
||||
let a = a.load_scalar(fx);
|
||||
let b = b.load_scalar(fx);
|
||||
|
||||
let val = fx.bcx.ins().fmin(a, b);
|
||||
let val = CValue::by_val(val, fx.layout_of(fx.tcx.types.f64));
|
||||
ret.write_cvalue(fx, val);
|
||||
}
|
||||
sym::maximumf32 => {
|
||||
intrinsic_args!(fx, args => (a, b); intrinsic);
|
||||
let a = a.load_scalar(fx);
|
||||
let b = b.load_scalar(fx);
|
||||
|
||||
let val = fx.bcx.ins().fmax(a, b);
|
||||
let val = CValue::by_val(val, fx.layout_of(fx.tcx.types.f32));
|
||||
ret.write_cvalue(fx, val);
|
||||
}
|
||||
sym::maximumf64 => {
|
||||
intrinsic_args!(fx, args => (a, b); intrinsic);
|
||||
let a = a.load_scalar(fx);
|
||||
let b = b.load_scalar(fx);
|
||||
|
||||
let val = fx.bcx.ins().fmax(a, b);
|
||||
let val = CValue::by_val(val, fx.layout_of(fx.tcx.types.f64));
|
||||
ret.write_cvalue(fx, val);
|
||||
}
|
||||
|
||||
sym::minnumf32 => {
|
||||
intrinsic_args!(fx, args => (a, b); intrinsic);
|
||||
let a = a.load_scalar(fx);
|
||||
|
||||
@@ -2454,7 +2454,6 @@ fn to_gcc(self) -> i32 {
|
||||
use MemOrdering::*;
|
||||
|
||||
let ordering = match self {
|
||||
AtomicOrdering::Unordered => __ATOMIC_RELAXED,
|
||||
AtomicOrdering::Relaxed => __ATOMIC_RELAXED, // TODO(antoyo): check if that's the same.
|
||||
AtomicOrdering::Acquire => __ATOMIC_ACQUIRE,
|
||||
AtomicOrdering::Release => __ATOMIC_RELEASE,
|
||||
|
||||
@@ -74,8 +74,44 @@ fn get_simple_intrinsic<'gcc, 'tcx>(
|
||||
sym::fabsf64 => "fabs",
|
||||
sym::minnumf32 => "fminf",
|
||||
sym::minnumf64 => "fmin",
|
||||
sym::minimumf32 => "fminimumf",
|
||||
sym::minimumf64 => "fminimum",
|
||||
sym::minimumf128 => {
|
||||
// GCC doesn't have the intrinsic we want so we use the compiler-builtins one
|
||||
// https://docs.rs/compiler_builtins/latest/compiler_builtins/math/full_availability/fn.fminimumf128.html
|
||||
let f128_type = cx.type_f128();
|
||||
return Some(cx.context.new_function(
|
||||
None,
|
||||
FunctionType::Extern,
|
||||
f128_type,
|
||||
&[
|
||||
cx.context.new_parameter(None, f128_type, "a"),
|
||||
cx.context.new_parameter(None, f128_type, "b"),
|
||||
],
|
||||
"fminimumf128",
|
||||
false,
|
||||
));
|
||||
}
|
||||
sym::maxnumf32 => "fmaxf",
|
||||
sym::maxnumf64 => "fmax",
|
||||
sym::maximumf32 => "fmaximumf",
|
||||
sym::maximumf64 => "fmaximum",
|
||||
sym::maximumf128 => {
|
||||
// GCC doesn't have the intrinsic we want so we use the compiler-builtins one
|
||||
// https://docs.rs/compiler_builtins/latest/compiler_builtins/math/full_availability/fn.fmaximumf128.html
|
||||
let f128_type = cx.type_f128();
|
||||
return Some(cx.context.new_function(
|
||||
None,
|
||||
FunctionType::Extern,
|
||||
f128_type,
|
||||
&[
|
||||
cx.context.new_parameter(None, f128_type, "a"),
|
||||
cx.context.new_parameter(None, f128_type, "b"),
|
||||
],
|
||||
"fmaximumf128",
|
||||
false,
|
||||
));
|
||||
}
|
||||
sym::copysignf32 => "copysignf",
|
||||
sym::copysignf64 => "copysign",
|
||||
sym::copysignf128 => "copysignl",
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
use tracing::debug;
|
||||
|
||||
use crate::builder::Builder;
|
||||
use crate::common::{AsCCharPtr, Funclet};
|
||||
use crate::common::Funclet;
|
||||
use crate::context::CodegenCx;
|
||||
use crate::type_::Type;
|
||||
use crate::type_of::LayoutLlvmExt;
|
||||
@@ -435,13 +435,7 @@ fn codegen_global_asm(
|
||||
template_str.push_str("\n.att_syntax\n");
|
||||
}
|
||||
|
||||
unsafe {
|
||||
llvm::LLVMAppendModuleInlineAsm(
|
||||
self.llmod,
|
||||
template_str.as_c_char_ptr(),
|
||||
template_str.len(),
|
||||
);
|
||||
}
|
||||
llvm::append_module_inline_asm(self.llmod, template_str.as_bytes());
|
||||
}
|
||||
|
||||
fn mangled_name(&self, instance: Instance<'tcx>) -> String {
|
||||
@@ -482,67 +476,67 @@ pub(crate) fn inline_asm_call<'ll>(
|
||||
|
||||
debug!("Asm Output Type: {:?}", output);
|
||||
let fty = bx.cx.type_func(&argtys, output);
|
||||
|
||||
// Ask LLVM to verify that the constraints are well-formed.
|
||||
let constraints_ok =
|
||||
unsafe { llvm::LLVMRustInlineAsmVerify(fty, cons.as_c_char_ptr(), cons.len()) };
|
||||
let constraints_ok = unsafe { llvm::LLVMRustInlineAsmVerify(fty, cons.as_ptr(), cons.len()) };
|
||||
debug!("constraint verification result: {:?}", constraints_ok);
|
||||
if constraints_ok {
|
||||
let v = unsafe {
|
||||
llvm::LLVMRustInlineAsm(
|
||||
fty,
|
||||
asm.as_c_char_ptr(),
|
||||
asm.len(),
|
||||
cons.as_c_char_ptr(),
|
||||
cons.len(),
|
||||
volatile,
|
||||
alignstack,
|
||||
dia,
|
||||
can_throw,
|
||||
)
|
||||
};
|
||||
|
||||
let call = if !labels.is_empty() {
|
||||
assert!(catch_funclet.is_none());
|
||||
bx.callbr(fty, None, None, v, inputs, dest.unwrap(), labels, None, None)
|
||||
} else if let Some((catch, funclet)) = catch_funclet {
|
||||
bx.invoke(fty, None, None, v, inputs, dest.unwrap(), catch, funclet, None)
|
||||
} else {
|
||||
bx.call(fty, None, None, v, inputs, None, None)
|
||||
};
|
||||
|
||||
// Store mark in a metadata node so we can map LLVM errors
|
||||
// back to source locations. See #17552.
|
||||
let key = "srcloc";
|
||||
let kind = bx.get_md_kind_id(key);
|
||||
|
||||
// `srcloc` contains one 64-bit integer for each line of assembly code,
|
||||
// where the lower 32 bits hold the lo byte position and the upper 32 bits
|
||||
// hold the hi byte position.
|
||||
let mut srcloc = vec![];
|
||||
if dia == llvm::AsmDialect::Intel && line_spans.len() > 1 {
|
||||
// LLVM inserts an extra line to add the ".intel_syntax", so add
|
||||
// a dummy srcloc entry for it.
|
||||
//
|
||||
// Don't do this if we only have 1 line span since that may be
|
||||
// due to the asm template string coming from a macro. LLVM will
|
||||
// default to the first srcloc for lines that don't have an
|
||||
// associated srcloc.
|
||||
srcloc.push(llvm::LLVMValueAsMetadata(bx.const_u64(0)));
|
||||
}
|
||||
srcloc.extend(line_spans.iter().map(|span| {
|
||||
llvm::LLVMValueAsMetadata(
|
||||
bx.const_u64(u64::from(span.lo().to_u32()) | (u64::from(span.hi().to_u32()) << 32)),
|
||||
)
|
||||
}));
|
||||
let md = unsafe { llvm::LLVMMDNodeInContext2(bx.llcx, srcloc.as_ptr(), srcloc.len()) };
|
||||
let md = bx.get_metadata_value(md);
|
||||
llvm::LLVMSetMetadata(call, kind, md);
|
||||
|
||||
Some(call)
|
||||
} else {
|
||||
// LLVM has detected an issue with our constraints, bail out
|
||||
None
|
||||
if !constraints_ok {
|
||||
// LLVM has detected an issue with our constraints, so bail out.
|
||||
return None;
|
||||
}
|
||||
|
||||
let v = unsafe {
|
||||
llvm::LLVMGetInlineAsm(
|
||||
fty,
|
||||
asm.as_ptr(),
|
||||
asm.len(),
|
||||
cons.as_ptr(),
|
||||
cons.len(),
|
||||
volatile,
|
||||
alignstack,
|
||||
dia,
|
||||
can_throw,
|
||||
)
|
||||
};
|
||||
|
||||
let call = if !labels.is_empty() {
|
||||
assert!(catch_funclet.is_none());
|
||||
bx.callbr(fty, None, None, v, inputs, dest.unwrap(), labels, None, None)
|
||||
} else if let Some((catch, funclet)) = catch_funclet {
|
||||
bx.invoke(fty, None, None, v, inputs, dest.unwrap(), catch, funclet, None)
|
||||
} else {
|
||||
bx.call(fty, None, None, v, inputs, None, None)
|
||||
};
|
||||
|
||||
// Store mark in a metadata node so we can map LLVM errors
|
||||
// back to source locations. See #17552.
|
||||
let key = "srcloc";
|
||||
let kind = bx.get_md_kind_id(key);
|
||||
|
||||
// `srcloc` contains one 64-bit integer for each line of assembly code,
|
||||
// where the lower 32 bits hold the lo byte position and the upper 32 bits
|
||||
// hold the hi byte position.
|
||||
let mut srcloc = vec![];
|
||||
if dia == llvm::AsmDialect::Intel && line_spans.len() > 1 {
|
||||
// LLVM inserts an extra line to add the ".intel_syntax", so add
|
||||
// a dummy srcloc entry for it.
|
||||
//
|
||||
// Don't do this if we only have 1 line span since that may be
|
||||
// due to the asm template string coming from a macro. LLVM will
|
||||
// default to the first srcloc for lines that don't have an
|
||||
// associated srcloc.
|
||||
srcloc.push(llvm::LLVMValueAsMetadata(bx.const_u64(0)));
|
||||
}
|
||||
srcloc.extend(line_spans.iter().map(|span| {
|
||||
llvm::LLVMValueAsMetadata(
|
||||
bx.const_u64(u64::from(span.lo().to_u32()) | (u64::from(span.hi().to_u32()) << 32)),
|
||||
)
|
||||
}));
|
||||
let md = unsafe { llvm::LLVMMDNodeInContext2(bx.llcx, srcloc.as_ptr(), srcloc.len()) };
|
||||
let md = bx.get_metadata_value(md);
|
||||
llvm::LLVMSetMetadata(call, kind, md);
|
||||
|
||||
Some(call)
|
||||
}
|
||||
|
||||
/// If the register is an xmm/ymm/zmm register then return its index.
|
||||
|
||||
@@ -1148,9 +1148,9 @@ unsafe fn embed_bitcode(
|
||||
// We need custom section flags, so emit module-level inline assembly.
|
||||
let section_flags = if cgcx.is_pe_coff { "n" } else { "e" };
|
||||
let asm = create_section_with_flags_asm(".llvmbc", section_flags, bitcode);
|
||||
llvm::LLVMAppendModuleInlineAsm(llmod, asm.as_c_char_ptr(), asm.len());
|
||||
llvm::append_module_inline_asm(llmod, &asm);
|
||||
let asm = create_section_with_flags_asm(".llvmcmd", section_flags, cmdline.as_bytes());
|
||||
llvm::LLVMAppendModuleInlineAsm(llmod, asm.as_c_char_ptr(), asm.len());
|
||||
llvm::append_module_inline_asm(llmod, &asm);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -361,7 +361,7 @@ fn invoke(
|
||||
|
||||
// Emit KCFI operand bundle
|
||||
let kcfi_bundle = self.kcfi_operand_bundle(fn_attrs, fn_abi, instance, llfn);
|
||||
if let Some(kcfi_bundle) = kcfi_bundle.as_ref().map(|b| b.raw()) {
|
||||
if let Some(kcfi_bundle) = kcfi_bundle.as_ref().map(|b| b.as_ref()) {
|
||||
bundles.push(kcfi_bundle);
|
||||
}
|
||||
|
||||
@@ -1416,7 +1416,7 @@ fn call(
|
||||
|
||||
// Emit KCFI operand bundle
|
||||
let kcfi_bundle = self.kcfi_operand_bundle(fn_attrs, fn_abi, instance, llfn);
|
||||
if let Some(kcfi_bundle) = kcfi_bundle.as_ref().map(|b| b.raw()) {
|
||||
if let Some(kcfi_bundle) = kcfi_bundle.as_ref().map(|b| b.as_ref()) {
|
||||
bundles.push(kcfi_bundle);
|
||||
}
|
||||
|
||||
@@ -1749,7 +1749,7 @@ pub(crate) fn callbr(
|
||||
|
||||
// Emit KCFI operand bundle
|
||||
let kcfi_bundle = self.kcfi_operand_bundle(fn_attrs, fn_abi, instance, llfn);
|
||||
if let Some(kcfi_bundle) = kcfi_bundle.as_ref().map(|b| b.raw()) {
|
||||
if let Some(kcfi_bundle) = kcfi_bundle.as_ref().map(|b| b.as_ref()) {
|
||||
bundles.push(kcfi_bundle);
|
||||
}
|
||||
|
||||
@@ -1836,7 +1836,7 @@ fn kcfi_operand_bundle(
|
||||
fn_abi: Option<&FnAbi<'tcx, Ty<'tcx>>>,
|
||||
instance: Option<Instance<'tcx>>,
|
||||
llfn: &'ll Value,
|
||||
) -> Option<llvm::OperandBundleOwned<'ll>> {
|
||||
) -> Option<llvm::OperandBundleBox<'ll>> {
|
||||
let is_indirect_call = unsafe { llvm::LLVMRustIsNonGVFunctionPointerTy(llfn) };
|
||||
let kcfi_bundle = if self.tcx.sess.is_sanitizer_kcfi_enabled()
|
||||
&& let Some(fn_abi) = fn_abi
|
||||
@@ -1862,7 +1862,7 @@ fn kcfi_operand_bundle(
|
||||
kcfi::typeid_for_fnabi(self.tcx, fn_abi, options)
|
||||
};
|
||||
|
||||
Some(llvm::OperandBundleOwned::new("kcfi", &[self.const_u32(kcfi_typeid)]))
|
||||
Some(llvm::OperandBundleBox::new("kcfi", &[self.const_u32(kcfi_typeid)]))
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
@@ -67,12 +67,12 @@
|
||||
/// the `OperandBundleDef` value created for MSVC landing pads.
|
||||
pub(crate) struct Funclet<'ll> {
|
||||
cleanuppad: &'ll Value,
|
||||
operand: llvm::OperandBundleOwned<'ll>,
|
||||
operand: llvm::OperandBundleBox<'ll>,
|
||||
}
|
||||
|
||||
impl<'ll> Funclet<'ll> {
|
||||
pub(crate) fn new(cleanuppad: &'ll Value) -> Self {
|
||||
Funclet { cleanuppad, operand: llvm::OperandBundleOwned::new("funclet", &[cleanuppad]) }
|
||||
Funclet { cleanuppad, operand: llvm::OperandBundleBox::new("funclet", &[cleanuppad]) }
|
||||
}
|
||||
|
||||
pub(crate) fn cleanuppad(&self) -> &'ll Value {
|
||||
@@ -80,7 +80,7 @@ pub(crate) fn cleanuppad(&self) -> &'ll Value {
|
||||
}
|
||||
|
||||
pub(crate) fn bundle(&self) -> &llvm::OperandBundle<'ll> {
|
||||
self.operand.raw()
|
||||
self.operand.as_ref()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -364,7 +364,12 @@ fn get_static_inner(&self, def_id: DefId, llty: &'ll Type) -> &'ll Value {
|
||||
|
||||
if !def_id.is_local() {
|
||||
let needs_dll_storage_attr = self.use_dll_storage_attrs
|
||||
&& !self.tcx.is_foreign_item(def_id)
|
||||
// If the symbol is a foreign item, then don't automatically apply DLLImport, as
|
||||
// we'll rely on the #[link] attribute instead. BUT, if this is an internal symbol
|
||||
// then it may be generated by the compiler in some crate, so we do need to apply
|
||||
// DLLImport when linking with the MSVC linker.
|
||||
&& (!self.tcx.is_foreign_item(def_id)
|
||||
|| (self.sess().target.is_like_msvc && fn_attrs.flags.contains(CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL)))
|
||||
// Local definitions can never be imported, so we must not apply
|
||||
// the DLLImport annotation.
|
||||
&& !dso_local
|
||||
|
||||
@@ -1009,11 +1009,27 @@ macro_rules! mk_struct {
|
||||
ifn!("llvm.minnum.f64", fn(t_f64, t_f64) -> t_f64);
|
||||
ifn!("llvm.minnum.f128", fn(t_f128, t_f128) -> t_f128);
|
||||
|
||||
ifn!("llvm.minimum.f16", fn(t_f16, t_f16) -> t_f16);
|
||||
ifn!("llvm.minimum.f32", fn(t_f32, t_f32) -> t_f32);
|
||||
ifn!("llvm.minimum.f64", fn(t_f64, t_f64) -> t_f64);
|
||||
// There are issues on x86_64 and aarch64 with the f128 variant.
|
||||
// - https://github.com/llvm/llvm-project/issues/139380
|
||||
// - https://github.com/llvm/llvm-project/issues/139381
|
||||
// ifn!("llvm.minimum.f128", fn(t_f128, t_f128) -> t_f128);
|
||||
|
||||
ifn!("llvm.maxnum.f16", fn(t_f16, t_f16) -> t_f16);
|
||||
ifn!("llvm.maxnum.f32", fn(t_f32, t_f32) -> t_f32);
|
||||
ifn!("llvm.maxnum.f64", fn(t_f64, t_f64) -> t_f64);
|
||||
ifn!("llvm.maxnum.f128", fn(t_f128, t_f128) -> t_f128);
|
||||
|
||||
ifn!("llvm.maximum.f16", fn(t_f16, t_f16) -> t_f16);
|
||||
ifn!("llvm.maximum.f32", fn(t_f32, t_f32) -> t_f32);
|
||||
ifn!("llvm.maximum.f64", fn(t_f64, t_f64) -> t_f64);
|
||||
// There are issues on x86_64 and aarch64 with the f128 variant.
|
||||
// - https://github.com/llvm/llvm-project/issues/139380
|
||||
// - https://github.com/llvm/llvm-project/issues/139381
|
||||
// ifn!("llvm.maximum.f128", fn(t_f128, t_f128) -> t_f128);
|
||||
|
||||
ifn!("llvm.floor.f16", fn(t_f16) -> t_f16);
|
||||
ifn!("llvm.floor.f32", fn(t_f32) -> t_f32);
|
||||
ifn!("llvm.floor.f64", fn(t_f64) -> t_f64);
|
||||
|
||||
@@ -103,11 +103,23 @@ fn get_simple_intrinsic<'ll>(
|
||||
sym::minnumf64 => "llvm.minnum.f64",
|
||||
sym::minnumf128 => "llvm.minnum.f128",
|
||||
|
||||
sym::minimumf16 => "llvm.minimum.f16",
|
||||
sym::minimumf32 => "llvm.minimum.f32",
|
||||
sym::minimumf64 => "llvm.minimum.f64",
|
||||
// There are issues on x86_64 and aarch64 with the f128 variant,
|
||||
// let's instead use the instrinsic fallback body.
|
||||
// sym::minimumf128 => "llvm.minimum.f128",
|
||||
sym::maxnumf16 => "llvm.maxnum.f16",
|
||||
sym::maxnumf32 => "llvm.maxnum.f32",
|
||||
sym::maxnumf64 => "llvm.maxnum.f64",
|
||||
sym::maxnumf128 => "llvm.maxnum.f128",
|
||||
|
||||
sym::maximumf16 => "llvm.maximum.f16",
|
||||
sym::maximumf32 => "llvm.maximum.f32",
|
||||
sym::maximumf64 => "llvm.maximum.f64",
|
||||
// There are issues on x86_64 and aarch64 with the f128 variant,
|
||||
// let's instead use the instrinsic fallback body.
|
||||
// sym::maximumf128 => "llvm.maximum.f128",
|
||||
sym::copysignf16 => "llvm.copysign.f16",
|
||||
sym::copysignf32 => "llvm.copysign.f32",
|
||||
sym::copysignf64 => "llvm.copysign.f64",
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
|
||||
// tidy-alphabetical-start
|
||||
#![allow(internal_features)]
|
||||
#![cfg_attr(bootstrap, feature(let_chains))]
|
||||
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
|
||||
#![doc(rust_logo)]
|
||||
#![feature(assert_matches)]
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
//! Bindings to the LLVM-C API (`LLVM*`), and to our own `extern "C"` wrapper
|
||||
//! functions around the unstable LLVM C++ API (`LLVMRust*`).
|
||||
//!
|
||||
//! ## Passing pointer/length strings as `*const c_uchar`
|
||||
//! ## Passing pointer/length strings as `*const c_uchar` (PTR_LEN_STR)
|
||||
//!
|
||||
//! Normally it's a good idea for Rust-side bindings to match the corresponding
|
||||
//! C-side function declarations as closely as possible. But when passing `&str`
|
||||
@@ -415,6 +415,7 @@ pub(crate) fn from_generic(op: rustc_codegen_ssa::common::AtomicRmwBinOp) -> Sel
|
||||
pub(crate) enum AtomicOrdering {
|
||||
#[allow(dead_code)]
|
||||
NotAtomic = 0,
|
||||
#[allow(dead_code)]
|
||||
Unordered = 1,
|
||||
Monotonic = 2,
|
||||
// Consume = 3, // Not specified yet.
|
||||
@@ -428,7 +429,6 @@ impl AtomicOrdering {
|
||||
pub(crate) fn from_generic(ao: rustc_codegen_ssa::common::AtomicOrdering) -> Self {
|
||||
use rustc_codegen_ssa::common::AtomicOrdering as Common;
|
||||
match ao {
|
||||
Common::Unordered => Self::Unordered,
|
||||
Common::Relaxed => Self::Monotonic,
|
||||
Common::Acquire => Self::Acquire,
|
||||
Common::Release => Self::Release,
|
||||
@@ -471,7 +471,7 @@ pub(crate) enum MetadataType {
|
||||
MD_kcfi_type = 36,
|
||||
}
|
||||
|
||||
/// LLVMRustAsmDialect
|
||||
/// Must match the layout of `LLVMInlineAsmDialect`.
|
||||
#[derive(Copy, Clone, PartialEq)]
|
||||
#[repr(C)]
|
||||
pub(crate) enum AsmDialect {
|
||||
@@ -1014,8 +1014,25 @@ pub(crate) fn LLVMModuleCreateWithNameInContext(
|
||||
pub(crate) fn LLVMGetDataLayoutStr(M: &Module) -> *const c_char;
|
||||
pub(crate) fn LLVMSetDataLayout(M: &Module, Triple: *const c_char);
|
||||
|
||||
/// See Module::setModuleInlineAsm.
|
||||
pub(crate) fn LLVMAppendModuleInlineAsm(M: &Module, Asm: *const c_char, Len: size_t);
|
||||
/// Append inline assembly to a module. See `Module::appendModuleInlineAsm`.
|
||||
pub(crate) fn LLVMAppendModuleInlineAsm(
|
||||
M: &Module,
|
||||
Asm: *const c_uchar, // See "PTR_LEN_STR".
|
||||
Len: size_t,
|
||||
);
|
||||
|
||||
/// Create the specified uniqued inline asm string. See `InlineAsm::get()`.
|
||||
pub(crate) fn LLVMGetInlineAsm<'ll>(
|
||||
Ty: &'ll Type,
|
||||
AsmString: *const c_uchar, // See "PTR_LEN_STR".
|
||||
AsmStringSize: size_t,
|
||||
Constraints: *const c_uchar, // See "PTR_LEN_STR".
|
||||
ConstraintsSize: size_t,
|
||||
HasSideEffects: llvm::Bool,
|
||||
IsAlignStack: llvm::Bool,
|
||||
Dialect: AsmDialect,
|
||||
CanThrow: llvm::Bool,
|
||||
) -> &'ll Value;
|
||||
|
||||
// Operations on integer types
|
||||
pub(crate) fn LLVMInt1TypeInContext(C: &Context) -> &Type;
|
||||
@@ -1766,7 +1783,7 @@ pub(crate) fn LLVMBuildCallBr<'a>(
|
||||
pub(crate) fn LLVMDIBuilderCreateNameSpace<'ll>(
|
||||
Builder: &DIBuilder<'ll>,
|
||||
ParentScope: Option<&'ll Metadata>,
|
||||
Name: *const c_uchar,
|
||||
Name: *const c_uchar, // See "PTR_LEN_STR".
|
||||
NameLen: size_t,
|
||||
ExportSymbols: llvm::Bool,
|
||||
) -> &'ll Metadata;
|
||||
@@ -1994,21 +2011,9 @@ pub(crate) fn LLVMRustBuildAtomicStore<'a>(
|
||||
/// Prints the statistics collected by `-Zprint-codegen-stats`.
|
||||
pub(crate) fn LLVMRustPrintStatistics(OutStr: &RustString);
|
||||
|
||||
/// Prepares inline assembly.
|
||||
pub(crate) fn LLVMRustInlineAsm(
|
||||
Ty: &Type,
|
||||
AsmString: *const c_char,
|
||||
AsmStringLen: size_t,
|
||||
Constraints: *const c_char,
|
||||
ConstraintsLen: size_t,
|
||||
SideEffects: Bool,
|
||||
AlignStack: Bool,
|
||||
Dialect: AsmDialect,
|
||||
CanThrow: Bool,
|
||||
) -> &Value;
|
||||
pub(crate) fn LLVMRustInlineAsmVerify(
|
||||
Ty: &Type,
|
||||
Constraints: *const c_char,
|
||||
Constraints: *const c_uchar, // See "PTR_LEN_STR".
|
||||
ConstraintsLen: size_t,
|
||||
) -> bool;
|
||||
|
||||
|
||||
@@ -363,12 +363,13 @@ pub(crate) fn last_error() -> Option<String> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Owns an [`OperandBundle`], and will dispose of it when dropped.
|
||||
pub(crate) struct OperandBundleOwned<'a> {
|
||||
/// Owning pointer to an [`OperandBundle`] that will dispose of the bundle
|
||||
/// when dropped.
|
||||
pub(crate) struct OperandBundleBox<'a> {
|
||||
raw: ptr::NonNull<OperandBundle<'a>>,
|
||||
}
|
||||
|
||||
impl<'a> OperandBundleOwned<'a> {
|
||||
impl<'a> OperandBundleBox<'a> {
|
||||
pub(crate) fn new(name: &str, vals: &[&'a Value]) -> Self {
|
||||
let raw = unsafe {
|
||||
LLVMCreateOperandBundle(
|
||||
@@ -378,21 +379,21 @@ pub(crate) fn new(name: &str, vals: &[&'a Value]) -> Self {
|
||||
vals.len() as c_uint,
|
||||
)
|
||||
};
|
||||
OperandBundleOwned { raw: ptr::NonNull::new(raw).unwrap() }
|
||||
Self { raw: ptr::NonNull::new(raw).unwrap() }
|
||||
}
|
||||
|
||||
/// Returns inner `OperandBundle` type.
|
||||
/// Dereferences to the underlying `&OperandBundle`.
|
||||
///
|
||||
/// This could be a `Deref` implementation, but `OperandBundle` contains an extern type and
|
||||
/// `Deref::Target: ?Sized`.
|
||||
pub(crate) fn raw(&self) -> &OperandBundle<'a> {
|
||||
/// This can't be a `Deref` implementation because `OperandBundle` transitively
|
||||
/// contains an extern type, which is incompatible with `Deref::Target: ?Sized`.
|
||||
pub(crate) fn as_ref(&self) -> &OperandBundle<'a> {
|
||||
// SAFETY: The returned reference is opaque and can only used for FFI.
|
||||
// It is valid for as long as `&self` is.
|
||||
unsafe { self.raw.as_ref() }
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for OperandBundleOwned<'_> {
|
||||
impl Drop for OperandBundleBox<'_> {
|
||||
fn drop(&mut self) {
|
||||
unsafe {
|
||||
LLVMDisposeOperandBundle(self.raw);
|
||||
@@ -440,3 +441,11 @@ pub(crate) fn set_dso_local<'ll>(v: &'ll Value) {
|
||||
LLVMRustSetDSOLocal(v, true);
|
||||
}
|
||||
}
|
||||
|
||||
/// Safe wrapper for `LLVMAppendModuleInlineAsm`, which delegates to
|
||||
/// `Module::appendModuleInlineAsm`.
|
||||
pub(crate) fn append_module_inline_asm<'ll>(llmod: &'ll Module, asm: &[u8]) {
|
||||
unsafe {
|
||||
LLVMAppendModuleInlineAsm(llmod, asm.as_ptr(), asm.len());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -337,7 +337,12 @@ fn add_object(&mut self, path: &Path) {
|
||||
fn debuginfo(&mut self, strip: Strip, natvis_debugger_visualizers: &[PathBuf]);
|
||||
fn no_crt_objects(&mut self);
|
||||
fn no_default_libraries(&mut self);
|
||||
fn export_symbols(&mut self, tmpdir: &Path, crate_type: CrateType, symbols: &[String]);
|
||||
fn export_symbols(
|
||||
&mut self,
|
||||
tmpdir: &Path,
|
||||
crate_type: CrateType,
|
||||
symbols: &[(String, SymbolExportKind)],
|
||||
);
|
||||
fn subsystem(&mut self, subsystem: &str);
|
||||
fn linker_plugin_lto(&mut self);
|
||||
fn add_eh_frame_header(&mut self) {}
|
||||
@@ -770,7 +775,12 @@ fn no_default_libraries(&mut self) {
|
||||
}
|
||||
}
|
||||
|
||||
fn export_symbols(&mut self, tmpdir: &Path, crate_type: CrateType, symbols: &[String]) {
|
||||
fn export_symbols(
|
||||
&mut self,
|
||||
tmpdir: &Path,
|
||||
crate_type: CrateType,
|
||||
symbols: &[(String, SymbolExportKind)],
|
||||
) {
|
||||
// Symbol visibility in object files typically takes care of this.
|
||||
if crate_type == CrateType::Executable {
|
||||
let should_export_executable_symbols =
|
||||
@@ -799,7 +809,7 @@ fn export_symbols(&mut self, tmpdir: &Path, crate_type: CrateType, symbols: &[St
|
||||
// Write a plain, newline-separated list of symbols
|
||||
let res: io::Result<()> = try {
|
||||
let mut f = File::create_buffered(&path)?;
|
||||
for sym in symbols {
|
||||
for (sym, _) in symbols {
|
||||
debug!(" _{sym}");
|
||||
writeln!(f, "_{sym}")?;
|
||||
}
|
||||
@@ -814,11 +824,12 @@ fn export_symbols(&mut self, tmpdir: &Path, crate_type: CrateType, symbols: &[St
|
||||
// .def file similar to MSVC one but without LIBRARY section
|
||||
// because LD doesn't like when it's empty
|
||||
writeln!(f, "EXPORTS")?;
|
||||
for symbol in symbols {
|
||||
for (symbol, kind) in symbols {
|
||||
let kind_marker = if *kind == SymbolExportKind::Data { " DATA" } else { "" };
|
||||
debug!(" _{symbol}");
|
||||
// Quote the name in case it's reserved by linker in some way
|
||||
// (this accounts for names with dots in particular).
|
||||
writeln!(f, " \"{symbol}\"")?;
|
||||
writeln!(f, " \"{symbol}\"{kind_marker}")?;
|
||||
}
|
||||
};
|
||||
if let Err(error) = res {
|
||||
@@ -831,7 +842,7 @@ fn export_symbols(&mut self, tmpdir: &Path, crate_type: CrateType, symbols: &[St
|
||||
writeln!(f, "{{")?;
|
||||
if !symbols.is_empty() {
|
||||
writeln!(f, " global:")?;
|
||||
for sym in symbols {
|
||||
for (sym, _) in symbols {
|
||||
debug!(" {sym};");
|
||||
writeln!(f, " {sym};")?;
|
||||
}
|
||||
@@ -1098,7 +1109,12 @@ fn debuginfo(&mut self, _strip: Strip, natvis_debugger_visualizers: &[PathBuf])
|
||||
// crates. Upstream rlibs may be linked statically to this dynamic library,
|
||||
// in which case they may continue to transitively be used and hence need
|
||||
// their symbols exported.
|
||||
fn export_symbols(&mut self, tmpdir: &Path, crate_type: CrateType, symbols: &[String]) {
|
||||
fn export_symbols(
|
||||
&mut self,
|
||||
tmpdir: &Path,
|
||||
crate_type: CrateType,
|
||||
symbols: &[(String, SymbolExportKind)],
|
||||
) {
|
||||
// Symbol visibility takes care of this typically
|
||||
if crate_type == CrateType::Executable {
|
||||
let should_export_executable_symbols =
|
||||
@@ -1116,9 +1132,10 @@ fn export_symbols(&mut self, tmpdir: &Path, crate_type: CrateType, symbols: &[St
|
||||
// straight to exports.
|
||||
writeln!(f, "LIBRARY")?;
|
||||
writeln!(f, "EXPORTS")?;
|
||||
for symbol in symbols {
|
||||
for (symbol, kind) in symbols {
|
||||
let kind_marker = if *kind == SymbolExportKind::Data { " DATA" } else { "" };
|
||||
debug!(" _{symbol}");
|
||||
writeln!(f, " {symbol}")?;
|
||||
writeln!(f, " {symbol}{kind_marker}")?;
|
||||
}
|
||||
};
|
||||
if let Err(error) = res {
|
||||
@@ -1259,14 +1276,19 @@ fn no_default_libraries(&mut self) {
|
||||
self.cc_arg("-nodefaultlibs");
|
||||
}
|
||||
|
||||
fn export_symbols(&mut self, _tmpdir: &Path, _crate_type: CrateType, symbols: &[String]) {
|
||||
fn export_symbols(
|
||||
&mut self,
|
||||
_tmpdir: &Path,
|
||||
_crate_type: CrateType,
|
||||
symbols: &[(String, SymbolExportKind)],
|
||||
) {
|
||||
debug!("EXPORTED SYMBOLS:");
|
||||
|
||||
self.cc_arg("-s");
|
||||
|
||||
let mut arg = OsString::from("EXPORTED_FUNCTIONS=");
|
||||
let encoded = serde_json::to_string(
|
||||
&symbols.iter().map(|sym| "_".to_owned() + sym).collect::<Vec<_>>(),
|
||||
&symbols.iter().map(|(sym, _)| "_".to_owned() + sym).collect::<Vec<_>>(),
|
||||
)
|
||||
.unwrap();
|
||||
debug!("{encoded}");
|
||||
@@ -1428,8 +1450,13 @@ fn no_crt_objects(&mut self) {}
|
||||
|
||||
fn no_default_libraries(&mut self) {}
|
||||
|
||||
fn export_symbols(&mut self, _tmpdir: &Path, _crate_type: CrateType, symbols: &[String]) {
|
||||
for sym in symbols {
|
||||
fn export_symbols(
|
||||
&mut self,
|
||||
_tmpdir: &Path,
|
||||
_crate_type: CrateType,
|
||||
symbols: &[(String, SymbolExportKind)],
|
||||
) {
|
||||
for (sym, _) in symbols {
|
||||
self.link_args(&["--export", sym]);
|
||||
}
|
||||
|
||||
@@ -1563,7 +1590,7 @@ fn no_default_libraries(&mut self) {
|
||||
self.cc_arg("-nostdlib");
|
||||
}
|
||||
|
||||
fn export_symbols(&mut self, _: &Path, _: CrateType, _: &[String]) {
|
||||
fn export_symbols(&mut self, _: &Path, _: CrateType, _: &[(String, SymbolExportKind)]) {
|
||||
// ToDo, not implemented, copy from GCC
|
||||
self.sess.dcx().emit_warn(errors::L4BenderExportingSymbolsUnimplemented);
|
||||
}
|
||||
@@ -1720,12 +1747,17 @@ fn no_crt_objects(&mut self) {}
|
||||
|
||||
fn no_default_libraries(&mut self) {}
|
||||
|
||||
fn export_symbols(&mut self, tmpdir: &Path, _crate_type: CrateType, symbols: &[String]) {
|
||||
fn export_symbols(
|
||||
&mut self,
|
||||
tmpdir: &Path,
|
||||
_crate_type: CrateType,
|
||||
symbols: &[(String, SymbolExportKind)],
|
||||
) {
|
||||
let path = tmpdir.join("list.exp");
|
||||
let res: io::Result<()> = try {
|
||||
let mut f = File::create_buffered(&path)?;
|
||||
// FIXME: use llvm-nm to generate export list.
|
||||
for symbol in symbols {
|
||||
for (symbol, _) in symbols {
|
||||
debug!(" _{symbol}");
|
||||
writeln!(f, " {symbol}")?;
|
||||
}
|
||||
@@ -1769,9 +1801,12 @@ fn for_each_exported_symbols_include_dep<'tcx>(
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn exported_symbols(tcx: TyCtxt<'_>, crate_type: CrateType) -> Vec<String> {
|
||||
pub(crate) fn exported_symbols(
|
||||
tcx: TyCtxt<'_>,
|
||||
crate_type: CrateType,
|
||||
) -> Vec<(String, SymbolExportKind)> {
|
||||
if let Some(ref exports) = tcx.sess.target.override_export_symbols {
|
||||
return exports.iter().map(ToString::to_string).collect();
|
||||
return exports.iter().map(|name| (name.to_string(), SymbolExportKind::Text)).collect();
|
||||
}
|
||||
|
||||
if let CrateType::ProcMacro = crate_type {
|
||||
@@ -1781,7 +1816,10 @@ pub(crate) fn exported_symbols(tcx: TyCtxt<'_>, crate_type: CrateType) -> Vec<St
|
||||
}
|
||||
}
|
||||
|
||||
fn exported_symbols_for_non_proc_macro(tcx: TyCtxt<'_>, crate_type: CrateType) -> Vec<String> {
|
||||
fn exported_symbols_for_non_proc_macro(
|
||||
tcx: TyCtxt<'_>,
|
||||
crate_type: CrateType,
|
||||
) -> Vec<(String, SymbolExportKind)> {
|
||||
let mut symbols = Vec::new();
|
||||
let export_threshold = symbol_export::crates_export_threshold(&[crate_type]);
|
||||
for_each_exported_symbols_include_dep(tcx, crate_type, |symbol, info, cnum| {
|
||||
@@ -1789,17 +1827,18 @@ fn exported_symbols_for_non_proc_macro(tcx: TyCtxt<'_>, crate_type: CrateType) -
|
||||
// from any cdylib. The latter doesn't work anyway as we use hidden visibility for
|
||||
// compiler-builtins. Most linkers silently ignore it, but ld64 gives a warning.
|
||||
if info.level.is_below_threshold(export_threshold) && !tcx.is_compiler_builtins(cnum) {
|
||||
symbols.push(symbol_export::exporting_symbol_name_for_instance_in_crate(
|
||||
tcx, symbol, cnum,
|
||||
symbols.push((
|
||||
symbol_export::exporting_symbol_name_for_instance_in_crate(tcx, symbol, cnum),
|
||||
info.kind,
|
||||
));
|
||||
symbol_export::extend_exported_symbols(&mut symbols, tcx, symbol, cnum);
|
||||
symbol_export::extend_exported_symbols(&mut symbols, tcx, symbol, info, cnum);
|
||||
}
|
||||
});
|
||||
|
||||
symbols
|
||||
}
|
||||
|
||||
fn exported_symbols_for_proc_macro_crate(tcx: TyCtxt<'_>) -> Vec<String> {
|
||||
fn exported_symbols_for_proc_macro_crate(tcx: TyCtxt<'_>) -> Vec<(String, SymbolExportKind)> {
|
||||
// `exported_symbols` will be empty when !should_codegen.
|
||||
if !tcx.sess.opts.output_types.should_codegen() {
|
||||
return Vec::new();
|
||||
@@ -1809,7 +1848,10 @@ fn exported_symbols_for_proc_macro_crate(tcx: TyCtxt<'_>) -> Vec<String> {
|
||||
let proc_macro_decls_name = tcx.sess.generate_proc_macro_decls_symbol(stable_crate_id);
|
||||
let metadata_symbol_name = exported_symbols::metadata_symbol_name(tcx);
|
||||
|
||||
vec![proc_macro_decls_name, metadata_symbol_name]
|
||||
vec![
|
||||
(proc_macro_decls_name, SymbolExportKind::Text),
|
||||
(metadata_symbol_name, SymbolExportKind::Text),
|
||||
]
|
||||
}
|
||||
|
||||
pub(crate) fn linked_symbols(
|
||||
@@ -1831,7 +1873,9 @@ pub(crate) fn linked_symbols(
|
||||
|| info.used
|
||||
{
|
||||
symbols.push((
|
||||
symbol_export::linking_symbol_name_for_instance_in_crate(tcx, symbol, cnum),
|
||||
symbol_export::linking_symbol_name_for_instance_in_crate(
|
||||
tcx, symbol, info.kind, cnum,
|
||||
),
|
||||
info.kind,
|
||||
));
|
||||
}
|
||||
@@ -1906,7 +1950,13 @@ fn control_flow_guard(&mut self) {}
|
||||
|
||||
fn ehcont_guard(&mut self) {}
|
||||
|
||||
fn export_symbols(&mut self, _tmpdir: &Path, _crate_type: CrateType, _symbols: &[String]) {}
|
||||
fn export_symbols(
|
||||
&mut self,
|
||||
_tmpdir: &Path,
|
||||
_crate_type: CrateType,
|
||||
_symbols: &[(String, SymbolExportKind)],
|
||||
) {
|
||||
}
|
||||
|
||||
fn subsystem(&mut self, _subsystem: &str) {}
|
||||
|
||||
@@ -1975,10 +2025,15 @@ fn control_flow_guard(&mut self) {}
|
||||
|
||||
fn ehcont_guard(&mut self) {}
|
||||
|
||||
fn export_symbols(&mut self, _tmpdir: &Path, _crate_type: CrateType, symbols: &[String]) {
|
||||
fn export_symbols(
|
||||
&mut self,
|
||||
_tmpdir: &Path,
|
||||
_crate_type: CrateType,
|
||||
symbols: &[(String, SymbolExportKind)],
|
||||
) {
|
||||
match _crate_type {
|
||||
CrateType::Cdylib => {
|
||||
for sym in symbols {
|
||||
for (sym, _) in symbols {
|
||||
self.link_args(&["--export-symbol", sym]);
|
||||
}
|
||||
}
|
||||
@@ -2052,11 +2107,16 @@ fn control_flow_guard(&mut self) {}
|
||||
|
||||
fn ehcont_guard(&mut self) {}
|
||||
|
||||
fn export_symbols(&mut self, tmpdir: &Path, _crate_type: CrateType, symbols: &[String]) {
|
||||
fn export_symbols(
|
||||
&mut self,
|
||||
tmpdir: &Path,
|
||||
_crate_type: CrateType,
|
||||
symbols: &[(String, SymbolExportKind)],
|
||||
) {
|
||||
let path = tmpdir.join("symbols");
|
||||
let res: io::Result<()> = try {
|
||||
let mut f = File::create_buffered(&path)?;
|
||||
for sym in symbols {
|
||||
for (sym, _) in symbols {
|
||||
writeln!(f, "{sym}")?;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -692,6 +692,7 @@ fn calling_convention_for_symbol<'tcx>(
|
||||
pub(crate) fn linking_symbol_name_for_instance_in_crate<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
symbol: ExportedSymbol<'tcx>,
|
||||
export_kind: SymbolExportKind,
|
||||
instantiating_crate: CrateNum,
|
||||
) -> String {
|
||||
let mut undecorated = symbol_name_for_instance_in_crate(tcx, symbol, instantiating_crate);
|
||||
@@ -712,8 +713,9 @@ pub(crate) fn linking_symbol_name_for_instance_in_crate<'tcx>(
|
||||
let prefix = match &target.arch[..] {
|
||||
"x86" => Some('_'),
|
||||
"x86_64" => None,
|
||||
"arm64ec" => Some('#'),
|
||||
// Only x86/64 use symbol decorations.
|
||||
// Only functions are decorated for arm64ec.
|
||||
"arm64ec" if export_kind == SymbolExportKind::Text => Some('#'),
|
||||
// Only x86/64 and arm64ec use symbol decorations.
|
||||
_ => return undecorated,
|
||||
};
|
||||
|
||||
@@ -753,9 +755,10 @@ pub(crate) fn exporting_symbol_name_for_instance_in_crate<'tcx>(
|
||||
/// Add it to the symbols list for all kernel functions, so that it is exported in the linked
|
||||
/// object.
|
||||
pub(crate) fn extend_exported_symbols<'tcx>(
|
||||
symbols: &mut Vec<String>,
|
||||
symbols: &mut Vec<(String, SymbolExportKind)>,
|
||||
tcx: TyCtxt<'tcx>,
|
||||
symbol: ExportedSymbol<'tcx>,
|
||||
info: SymbolExportInfo,
|
||||
instantiating_crate: CrateNum,
|
||||
) {
|
||||
let (conv, _) = calling_convention_for_symbol(tcx, symbol);
|
||||
@@ -767,7 +770,7 @@ pub(crate) fn extend_exported_symbols<'tcx>(
|
||||
let undecorated = symbol_name_for_instance_in_crate(tcx, symbol, instantiating_crate);
|
||||
|
||||
// Add the symbol for the kernel descriptor (with .kd suffix)
|
||||
symbols.push(format!("{undecorated}.kd"));
|
||||
symbols.push((format!("{undecorated}.kd"), info.kind));
|
||||
}
|
||||
|
||||
fn maybe_emutls_symbol_name<'tcx>(
|
||||
|
||||
@@ -12,9 +12,9 @@
|
||||
use rustc_data_structures::profiling::{get_resident_set_size, print_time_passes_entry};
|
||||
use rustc_data_structures::sync::{IntoDynSyncSend, par_map};
|
||||
use rustc_data_structures::unord::UnordMap;
|
||||
use rustc_hir::ItemId;
|
||||
use rustc_hir::def_id::{DefId, LOCAL_CRATE};
|
||||
use rustc_hir::lang_items::LangItem;
|
||||
use rustc_hir::{ItemId, Target};
|
||||
use rustc_metadata::EncodedMetadata;
|
||||
use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrs;
|
||||
use rustc_middle::middle::debugger_visualizer::{DebuggerVisualizerFile, DebuggerVisualizerType};
|
||||
@@ -1038,21 +1038,35 @@ pub fn new(tcx: TyCtxt<'_>, target_cpu: String) -> CrateInfo {
|
||||
// by the compiler, but that's ok because all this stuff is unstable anyway.
|
||||
let target = &tcx.sess.target;
|
||||
if !are_upstream_rust_objects_already_included(tcx.sess) {
|
||||
let missing_weak_lang_items: FxIndexSet<Symbol> = info
|
||||
let add_prefix = match (target.is_like_windows, target.arch.as_ref()) {
|
||||
(true, "x86") => |name: String, _: SymbolExportKind| format!("_{name}"),
|
||||
(true, "arm64ec") => {
|
||||
// Only functions are decorated for arm64ec.
|
||||
|name: String, export_kind: SymbolExportKind| match export_kind {
|
||||
SymbolExportKind::Text => format!("#{name}"),
|
||||
_ => name,
|
||||
}
|
||||
}
|
||||
_ => |name: String, _: SymbolExportKind| name,
|
||||
};
|
||||
let missing_weak_lang_items: FxIndexSet<(Symbol, SymbolExportKind)> = info
|
||||
.used_crates
|
||||
.iter()
|
||||
.flat_map(|&cnum| tcx.missing_lang_items(cnum))
|
||||
.filter(|l| l.is_weak())
|
||||
.filter_map(|&l| {
|
||||
let name = l.link_name()?;
|
||||
lang_items::required(tcx, l).then_some(name)
|
||||
let export_kind = match l.target() {
|
||||
Target::Fn => SymbolExportKind::Text,
|
||||
Target::Static => SymbolExportKind::Data,
|
||||
_ => bug!(
|
||||
"Don't know what the export kind is for lang item of kind {:?}",
|
||||
l.target()
|
||||
),
|
||||
};
|
||||
lang_items::required(tcx, l).then_some((name, export_kind))
|
||||
})
|
||||
.collect();
|
||||
let prefix = match (target.is_like_windows, target.arch.as_ref()) {
|
||||
(true, "x86") => "_",
|
||||
(true, "arm64ec") => "#",
|
||||
_ => "",
|
||||
};
|
||||
|
||||
// This loop only adds new items to values of the hash map, so the order in which we
|
||||
// iterate over the values is not important.
|
||||
@@ -1065,10 +1079,13 @@ pub fn new(tcx: TyCtxt<'_>, target_cpu: String) -> CrateInfo {
|
||||
.for_each(|(_, linked_symbols)| {
|
||||
let mut symbols = missing_weak_lang_items
|
||||
.iter()
|
||||
.map(|item| {
|
||||
.map(|(item, export_kind)| {
|
||||
(
|
||||
format!("{prefix}{}", mangle_internal_symbol(tcx, item.as_str())),
|
||||
SymbolExportKind::Text,
|
||||
add_prefix(
|
||||
mangle_internal_symbol(tcx, item.as_str()),
|
||||
*export_kind,
|
||||
),
|
||||
*export_kind,
|
||||
)
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
@@ -1083,12 +1100,12 @@ pub fn new(tcx: TyCtxt<'_>, target_cpu: String) -> CrateInfo {
|
||||
// errors.
|
||||
linked_symbols.extend(ALLOCATOR_METHODS.iter().map(|method| {
|
||||
(
|
||||
format!(
|
||||
"{prefix}{}",
|
||||
add_prefix(
|
||||
mangle_internal_symbol(
|
||||
tcx,
|
||||
global_fn_name(method.name).as_str()
|
||||
)
|
||||
global_fn_name(method.name).as_str(),
|
||||
),
|
||||
SymbolExportKind::Text,
|
||||
),
|
||||
SymbolExportKind::Text,
|
||||
)
|
||||
|
||||
@@ -387,7 +387,7 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
|
||||
[sym::arm, sym::a32 | sym::t32]
|
||||
if !tcx.sess.target.has_thumb_interworking =>
|
||||
{
|
||||
tcx.dcx().emit_err(errors::UnsuportedInstructionSet {
|
||||
tcx.dcx().emit_err(errors::UnsupportedInstructionSet {
|
||||
span: attr.span(),
|
||||
});
|
||||
None
|
||||
|
||||
@@ -61,7 +61,6 @@ pub enum AtomicRmwBinOp {
|
||||
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
pub enum AtomicOrdering {
|
||||
Unordered,
|
||||
Relaxed,
|
||||
Acquire,
|
||||
Release,
|
||||
|
||||
@@ -149,7 +149,7 @@ pub(crate) struct NullOnExport {
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(codegen_ssa_unsupported_instruction_set, code = E0779)]
|
||||
pub(crate) struct UnsuportedInstructionSet {
|
||||
pub(crate) struct UnsupportedInstructionSet {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
#![allow(internal_features)]
|
||||
#![allow(rustc::diagnostic_outside_of_impl)]
|
||||
#![allow(rustc::untranslatable_diagnostic)]
|
||||
#![cfg_attr(bootstrap, feature(let_chains))]
|
||||
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
|
||||
#![doc(rust_logo)]
|
||||
#![feature(assert_matches)]
|
||||
@@ -219,7 +218,7 @@ pub struct CrateInfo {
|
||||
pub target_cpu: String,
|
||||
pub target_features: Vec<String>,
|
||||
pub crate_types: Vec<CrateType>,
|
||||
pub exported_symbols: UnordMap<CrateType, Vec<String>>,
|
||||
pub exported_symbols: UnordMap<CrateType, Vec<(String, SymbolExportKind)>>,
|
||||
pub linked_symbols: FxIndexMap<CrateType, Vec<(String, SymbolExportKind)>>,
|
||||
pub local_crate_name: Symbol,
|
||||
pub compiler_builtins: Option<CrateNum>,
|
||||
|
||||
@@ -336,7 +336,6 @@ pub fn codegen_intrinsic_call(
|
||||
};
|
||||
|
||||
let parse_ordering = |bx: &Bx, s| match s {
|
||||
"unordered" => Unordered,
|
||||
"relaxed" => Relaxed,
|
||||
"acquire" => Acquire,
|
||||
"release" => Release,
|
||||
|
||||
@@ -493,11 +493,21 @@ pub fn eval_intrinsic(
|
||||
sym::minnumf64 => self.float_min_intrinsic::<Double>(args, dest)?,
|
||||
sym::minnumf128 => self.float_min_intrinsic::<Quad>(args, dest)?,
|
||||
|
||||
sym::minimumf16 => self.float_minimum_intrinsic::<Half>(args, dest)?,
|
||||
sym::minimumf32 => self.float_minimum_intrinsic::<Single>(args, dest)?,
|
||||
sym::minimumf64 => self.float_minimum_intrinsic::<Double>(args, dest)?,
|
||||
sym::minimumf128 => self.float_minimum_intrinsic::<Quad>(args, dest)?,
|
||||
|
||||
sym::maxnumf16 => self.float_max_intrinsic::<Half>(args, dest)?,
|
||||
sym::maxnumf32 => self.float_max_intrinsic::<Single>(args, dest)?,
|
||||
sym::maxnumf64 => self.float_max_intrinsic::<Double>(args, dest)?,
|
||||
sym::maxnumf128 => self.float_max_intrinsic::<Quad>(args, dest)?,
|
||||
|
||||
sym::maximumf16 => self.float_maximum_intrinsic::<Half>(args, dest)?,
|
||||
sym::maximumf32 => self.float_maximum_intrinsic::<Single>(args, dest)?,
|
||||
sym::maximumf64 => self.float_maximum_intrinsic::<Double>(args, dest)?,
|
||||
sym::maximumf128 => self.float_maximum_intrinsic::<Quad>(args, dest)?,
|
||||
|
||||
sym::copysignf16 => self.float_copysign_intrinsic::<Half>(args, dest)?,
|
||||
sym::copysignf32 => self.float_copysign_intrinsic::<Single>(args, dest)?,
|
||||
sym::copysignf64 => self.float_copysign_intrinsic::<Double>(args, dest)?,
|
||||
@@ -830,6 +840,38 @@ fn float_max_intrinsic<F>(
|
||||
interp_ok(())
|
||||
}
|
||||
|
||||
fn float_minimum_intrinsic<F>(
|
||||
&mut self,
|
||||
args: &[OpTy<'tcx, M::Provenance>],
|
||||
dest: &MPlaceTy<'tcx, M::Provenance>,
|
||||
) -> InterpResult<'tcx, ()>
|
||||
where
|
||||
F: rustc_apfloat::Float + rustc_apfloat::FloatConvert<F> + Into<Scalar<M::Provenance>>,
|
||||
{
|
||||
let a: F = self.read_scalar(&args[0])?.to_float()?;
|
||||
let b: F = self.read_scalar(&args[1])?.to_float()?;
|
||||
let res = a.minimum(b);
|
||||
let res = self.adjust_nan(res, &[a, b]);
|
||||
self.write_scalar(res, dest)?;
|
||||
interp_ok(())
|
||||
}
|
||||
|
||||
fn float_maximum_intrinsic<F>(
|
||||
&mut self,
|
||||
args: &[OpTy<'tcx, M::Provenance>],
|
||||
dest: &MPlaceTy<'tcx, M::Provenance>,
|
||||
) -> InterpResult<'tcx, ()>
|
||||
where
|
||||
F: rustc_apfloat::Float + rustc_apfloat::FloatConvert<F> + Into<Scalar<M::Provenance>>,
|
||||
{
|
||||
let a: F = self.read_scalar(&args[0])?.to_float()?;
|
||||
let b: F = self.read_scalar(&args[1])?.to_float()?;
|
||||
let res = a.maximum(b);
|
||||
let res = self.adjust_nan(res, &[a, b]);
|
||||
self.write_scalar(res, dest)?;
|
||||
interp_ok(())
|
||||
}
|
||||
|
||||
fn float_copysign_intrinsic<F>(
|
||||
&mut self,
|
||||
args: &[OpTy<'tcx, M::Provenance>],
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
// tidy-alphabetical-start
|
||||
#![allow(internal_features)]
|
||||
#![allow(rustc::diagnostic_outside_of_impl)]
|
||||
#![cfg_attr(bootstrap, feature(let_chains))]
|
||||
#![doc(rust_logo)]
|
||||
#![feature(assert_matches)]
|
||||
#![feature(box_patterns)]
|
||||
|
||||
@@ -7,7 +7,6 @@
|
||||
// tidy-alphabetical-start
|
||||
#![allow(internal_features)]
|
||||
#![allow(rustc::untranslatable_diagnostic)] // FIXME: make this translatable
|
||||
#![cfg_attr(bootstrap, feature(let_chains))]
|
||||
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
|
||||
#![doc(rust_logo)]
|
||||
#![feature(decl_macro)]
|
||||
|
||||
@@ -7,7 +7,6 @@
|
||||
#![allow(internal_features)]
|
||||
#![allow(rustc::diagnostic_outside_of_impl)]
|
||||
#![allow(rustc::untranslatable_diagnostic)]
|
||||
#![cfg_attr(bootstrap, feature(let_chains))]
|
||||
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
|
||||
#![doc(rust_logo)]
|
||||
#![feature(array_windows)]
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
use std::ops::Deref;
|
||||
use std::path::PathBuf;
|
||||
use std::rc::Rc;
|
||||
use std::sync::Arc;
|
||||
@@ -1117,7 +1116,6 @@ enum AddSemicolon {
|
||||
/// of functionality used by `InvocationCollector`.
|
||||
trait InvocationCollectorNode: HasAttrs + HasNodeId + Sized {
|
||||
type OutputTy = SmallVec<[Self; 1]>;
|
||||
type AttrsTy: Deref<Target = [ast::Attribute]> = ast::AttrVec;
|
||||
type ItemKind = ItemKind;
|
||||
const KIND: AstFragmentKind;
|
||||
fn to_annotatable(self) -> Annotatable;
|
||||
@@ -1134,7 +1132,7 @@ fn walk<V: MutVisitor>(&mut self, _visitor: &mut V) {
|
||||
fn is_mac_call(&self) -> bool {
|
||||
false
|
||||
}
|
||||
fn take_mac_call(self) -> (P<ast::MacCall>, Self::AttrsTy, AddSemicolon) {
|
||||
fn take_mac_call(self) -> (P<ast::MacCall>, ast::AttrVec, AddSemicolon) {
|
||||
unreachable!()
|
||||
}
|
||||
fn delegation(&self) -> Option<(&ast::DelegationMac, &ast::Item<Self::ItemKind>)> {
|
||||
@@ -1189,7 +1187,7 @@ fn walk_flat_map<V: MutVisitor>(self, visitor: &mut V) -> Self::OutputTy {
|
||||
fn is_mac_call(&self) -> bool {
|
||||
matches!(self.kind, ItemKind::MacCall(..))
|
||||
}
|
||||
fn take_mac_call(self) -> (P<ast::MacCall>, Self::AttrsTy, AddSemicolon) {
|
||||
fn take_mac_call(self) -> (P<ast::MacCall>, ast::AttrVec, AddSemicolon) {
|
||||
let node = self.into_inner();
|
||||
match node.kind {
|
||||
ItemKind::MacCall(mac) => (mac, node.attrs, AddSemicolon::No),
|
||||
@@ -1345,7 +1343,7 @@ fn walk_flat_map<V: MutVisitor>(self, visitor: &mut V) -> Self::OutputTy {
|
||||
fn is_mac_call(&self) -> bool {
|
||||
matches!(self.wrapped.kind, AssocItemKind::MacCall(..))
|
||||
}
|
||||
fn take_mac_call(self) -> (P<ast::MacCall>, Self::AttrsTy, AddSemicolon) {
|
||||
fn take_mac_call(self) -> (P<ast::MacCall>, ast::AttrVec, AddSemicolon) {
|
||||
let item = self.wrapped.into_inner();
|
||||
match item.kind {
|
||||
AssocItemKind::MacCall(mac) => (mac, item.attrs, AddSemicolon::No),
|
||||
@@ -1386,7 +1384,7 @@ fn walk_flat_map<V: MutVisitor>(self, visitor: &mut V) -> Self::OutputTy {
|
||||
fn is_mac_call(&self) -> bool {
|
||||
matches!(self.wrapped.kind, AssocItemKind::MacCall(..))
|
||||
}
|
||||
fn take_mac_call(self) -> (P<ast::MacCall>, Self::AttrsTy, AddSemicolon) {
|
||||
fn take_mac_call(self) -> (P<ast::MacCall>, ast::AttrVec, AddSemicolon) {
|
||||
let item = self.wrapped.into_inner();
|
||||
match item.kind {
|
||||
AssocItemKind::MacCall(mac) => (mac, item.attrs, AddSemicolon::No),
|
||||
@@ -1427,7 +1425,7 @@ fn walk_flat_map<V: MutVisitor>(self, visitor: &mut V) -> Self::OutputTy {
|
||||
fn is_mac_call(&self) -> bool {
|
||||
matches!(self.wrapped.kind, AssocItemKind::MacCall(..))
|
||||
}
|
||||
fn take_mac_call(self) -> (P<ast::MacCall>, Self::AttrsTy, AddSemicolon) {
|
||||
fn take_mac_call(self) -> (P<ast::MacCall>, ast::AttrVec, AddSemicolon) {
|
||||
let item = self.wrapped.into_inner();
|
||||
match item.kind {
|
||||
AssocItemKind::MacCall(mac) => (mac, item.attrs, AddSemicolon::No),
|
||||
@@ -1465,7 +1463,7 @@ fn walk_flat_map<V: MutVisitor>(self, visitor: &mut V) -> Self::OutputTy {
|
||||
fn is_mac_call(&self) -> bool {
|
||||
matches!(self.kind, ForeignItemKind::MacCall(..))
|
||||
}
|
||||
fn take_mac_call(self) -> (P<ast::MacCall>, Self::AttrsTy, AddSemicolon) {
|
||||
fn take_mac_call(self) -> (P<ast::MacCall>, ast::AttrVec, AddSemicolon) {
|
||||
let node = self.into_inner();
|
||||
match node.kind {
|
||||
ForeignItemKind::MacCall(mac) => (mac, node.attrs, AddSemicolon::No),
|
||||
@@ -1579,7 +1577,6 @@ fn walk_flat_map<V: MutVisitor>(self, visitor: &mut V) -> Self::OutputTy {
|
||||
}
|
||||
|
||||
impl InvocationCollectorNode for ast::Stmt {
|
||||
type AttrsTy = ast::AttrVec;
|
||||
const KIND: AstFragmentKind = AstFragmentKind::Stmts;
|
||||
fn to_annotatable(self) -> Annotatable {
|
||||
Annotatable::Stmt(P(self))
|
||||
@@ -1599,7 +1596,7 @@ fn is_mac_call(&self) -> bool {
|
||||
StmtKind::Let(..) | StmtKind::Empty => false,
|
||||
}
|
||||
}
|
||||
fn take_mac_call(self) -> (P<ast::MacCall>, Self::AttrsTy, AddSemicolon) {
|
||||
fn take_mac_call(self) -> (P<ast::MacCall>, ast::AttrVec, AddSemicolon) {
|
||||
// We pull macro invocations (both attributes and fn-like macro calls) out of their
|
||||
// `StmtKind`s and treat them as statement macro invocations, not as items or expressions.
|
||||
let (add_semicolon, mac, attrs) = match self.kind {
|
||||
@@ -1693,7 +1690,7 @@ fn walk<V: MutVisitor>(&mut self, visitor: &mut V) {
|
||||
fn is_mac_call(&self) -> bool {
|
||||
matches!(self.kind, ast::TyKind::MacCall(..))
|
||||
}
|
||||
fn take_mac_call(self) -> (P<ast::MacCall>, Self::AttrsTy, AddSemicolon) {
|
||||
fn take_mac_call(self) -> (P<ast::MacCall>, ast::AttrVec, AddSemicolon) {
|
||||
let node = self.into_inner();
|
||||
match node.kind {
|
||||
TyKind::MacCall(mac) => (mac, AttrVec::new(), AddSemicolon::No),
|
||||
@@ -1717,7 +1714,7 @@ fn walk<V: MutVisitor>(&mut self, visitor: &mut V) {
|
||||
fn is_mac_call(&self) -> bool {
|
||||
matches!(self.kind, PatKind::MacCall(..))
|
||||
}
|
||||
fn take_mac_call(self) -> (P<ast::MacCall>, Self::AttrsTy, AddSemicolon) {
|
||||
fn take_mac_call(self) -> (P<ast::MacCall>, ast::AttrVec, AddSemicolon) {
|
||||
let node = self.into_inner();
|
||||
match node.kind {
|
||||
PatKind::MacCall(mac) => (mac, AttrVec::new(), AddSemicolon::No),
|
||||
@@ -1728,7 +1725,6 @@ fn take_mac_call(self) -> (P<ast::MacCall>, Self::AttrsTy, AddSemicolon) {
|
||||
|
||||
impl InvocationCollectorNode for P<ast::Expr> {
|
||||
type OutputTy = P<ast::Expr>;
|
||||
type AttrsTy = ast::AttrVec;
|
||||
const KIND: AstFragmentKind = AstFragmentKind::Expr;
|
||||
fn to_annotatable(self) -> Annotatable {
|
||||
Annotatable::Expr(self)
|
||||
@@ -1745,7 +1741,7 @@ fn walk<V: MutVisitor>(&mut self, visitor: &mut V) {
|
||||
fn is_mac_call(&self) -> bool {
|
||||
matches!(self.kind, ExprKind::MacCall(..))
|
||||
}
|
||||
fn take_mac_call(self) -> (P<ast::MacCall>, Self::AttrsTy, AddSemicolon) {
|
||||
fn take_mac_call(self) -> (P<ast::MacCall>, ast::AttrVec, AddSemicolon) {
|
||||
let node = self.into_inner();
|
||||
match node.kind {
|
||||
ExprKind::MacCall(mac) => (mac, node.attrs, AddSemicolon::No),
|
||||
@@ -1757,7 +1753,6 @@ fn take_mac_call(self) -> (P<ast::MacCall>, Self::AttrsTy, AddSemicolon) {
|
||||
struct OptExprTag;
|
||||
impl InvocationCollectorNode for AstNodeWrapper<P<ast::Expr>, OptExprTag> {
|
||||
type OutputTy = Option<P<ast::Expr>>;
|
||||
type AttrsTy = ast::AttrVec;
|
||||
const KIND: AstFragmentKind = AstFragmentKind::OptExpr;
|
||||
fn to_annotatable(self) -> Annotatable {
|
||||
Annotatable::Expr(self.wrapped)
|
||||
@@ -1772,7 +1767,7 @@ fn walk_flat_map<V: MutVisitor>(mut self, visitor: &mut V) -> Self::OutputTy {
|
||||
fn is_mac_call(&self) -> bool {
|
||||
matches!(self.wrapped.kind, ast::ExprKind::MacCall(..))
|
||||
}
|
||||
fn take_mac_call(self) -> (P<ast::MacCall>, Self::AttrsTy, AddSemicolon) {
|
||||
fn take_mac_call(self) -> (P<ast::MacCall>, ast::AttrVec, AddSemicolon) {
|
||||
let node = self.wrapped.into_inner();
|
||||
match node.kind {
|
||||
ExprKind::MacCall(mac) => (mac, node.attrs, AddSemicolon::No),
|
||||
@@ -1794,7 +1789,6 @@ fn dummy() -> MethodReceiverTag {
|
||||
}
|
||||
impl InvocationCollectorNode for AstNodeWrapper<P<ast::Expr>, MethodReceiverTag> {
|
||||
type OutputTy = Self;
|
||||
type AttrsTy = ast::AttrVec;
|
||||
const KIND: AstFragmentKind = AstFragmentKind::MethodReceiverExpr;
|
||||
fn descr() -> &'static str {
|
||||
"an expression"
|
||||
@@ -1811,7 +1805,7 @@ fn walk<V: MutVisitor>(&mut self, visitor: &mut V) {
|
||||
fn is_mac_call(&self) -> bool {
|
||||
matches!(self.wrapped.kind, ast::ExprKind::MacCall(..))
|
||||
}
|
||||
fn take_mac_call(self) -> (P<ast::MacCall>, Self::AttrsTy, AddSemicolon) {
|
||||
fn take_mac_call(self) -> (P<ast::MacCall>, ast::AttrVec, AddSemicolon) {
|
||||
let node = self.wrapped.into_inner();
|
||||
match node.kind {
|
||||
ExprKind::MacCall(mac) => (mac, node.attrs, AddSemicolon::No),
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
// tidy-alphabetical-start
|
||||
#![allow(internal_features)]
|
||||
#![allow(rustc::diagnostic_outside_of_impl)]
|
||||
#![cfg_attr(bootstrap, feature(let_chains))]
|
||||
#![doc(rust_logo)]
|
||||
#![feature(array_windows)]
|
||||
#![feature(associated_type_defaults)]
|
||||
|
||||
@@ -96,7 +96,7 @@ macro_rules! declare_features {
|
||||
/// Allows `#[cfg_attr(predicate, multiple, attributes, here)]`.
|
||||
(accepted, cfg_attr_multi, "1.33.0", Some(54881)),
|
||||
/// Allows the use of `#[cfg(<true/false>)]`.
|
||||
(accepted, cfg_boolean_literals, "CURRENT_RUSTC_VERSION", Some(131204)),
|
||||
(accepted, cfg_boolean_literals, "1.88.0", Some(131204)),
|
||||
/// Allows the use of `#[cfg(doctest)]`, set when rustdoc is collecting doctests.
|
||||
(accepted, cfg_doctest, "1.40.0", Some(62210)),
|
||||
/// Enables `#[cfg(panic = "...")]` config key.
|
||||
@@ -301,7 +301,7 @@ macro_rules! declare_features {
|
||||
/// For example, you can write `Foo(a, ref b)` where `a` is by-move and `b` is by-ref.
|
||||
(accepted, move_ref_pattern, "1.49.0", Some(68354)),
|
||||
/// Allows using `#[naked]` on functions.
|
||||
(accepted, naked_functions, "CURRENT_RUSTC_VERSION", Some(90957)),
|
||||
(accepted, naked_functions, "1.88.0", Some(90957)),
|
||||
/// Allows specifying modifiers in the link attribute: `#[link(modifiers = "...")]`
|
||||
(accepted, native_link_modifiers, "1.61.0", Some(81490)),
|
||||
/// Allows specifying the bundle link modifier
|
||||
|
||||
@@ -143,7 +143,7 @@ macro_rules! declare_features {
|
||||
(removed, infer_static_outlives_requirements, "1.63.0", Some(54185),
|
||||
Some("removed as it caused some confusion and discussion was inactive for years")),
|
||||
/// Allow anonymous constants from an inline `const` block in pattern position
|
||||
(removed, inline_const_pat, "CURRENT_RUSTC_VERSION", Some(76001),
|
||||
(removed, inline_const_pat, "1.88.0", Some(76001),
|
||||
Some("removed due to implementation concerns as it requires significant refactorings")),
|
||||
/// Lazily evaluate constants. This allows constants to depend on type parameters.
|
||||
(removed, lazy_normalization_consts, "1.46.0", Some(72219), Some("superseded by `generic_const_exprs`")),
|
||||
|
||||
@@ -206,7 +206,7 @@ pub fn internal(&self, feature: Symbol) -> bool {
|
||||
/// Allows access to the emscripten_wasm_eh config, used by panic_unwind and unwind
|
||||
(internal, cfg_emscripten_wasm_eh, "1.86.0", None),
|
||||
/// Allows checking whether or not the backend correctly supports unstable float types.
|
||||
(internal, cfg_target_has_reliable_f16_f128, "CURRENT_RUSTC_VERSION", None),
|
||||
(internal, cfg_target_has_reliable_f16_f128, "1.88.0", None),
|
||||
/// Allows identifying the `compiler_builtins` crate.
|
||||
(internal, compiler_builtins, "1.13.0", None),
|
||||
/// Allows writing custom MIR
|
||||
@@ -316,7 +316,7 @@ pub fn internal(&self, feature: Symbol) -> bool {
|
||||
// Unstable `#[target_feature]` directives.
|
||||
(unstable, aarch64_unstable_target_feature, "1.82.0", Some(44839)),
|
||||
(unstable, aarch64_ver_target_feature, "1.27.0", Some(44839)),
|
||||
(unstable, apx_target_feature, "CURRENT_RUSTC_VERSION", Some(139284)),
|
||||
(unstable, apx_target_feature, "1.88.0", Some(139284)),
|
||||
(unstable, arm_target_feature, "1.27.0", Some(44839)),
|
||||
(unstable, avx512_target_feature, "1.27.0", Some(44839)),
|
||||
(unstable, bpf_target_feature, "1.54.0", Some(44839)),
|
||||
@@ -327,7 +327,7 @@ pub fn internal(&self, feature: Symbol) -> bool {
|
||||
(unstable, loongarch_target_feature, "1.73.0", Some(44839)),
|
||||
(unstable, m68k_target_feature, "1.85.0", Some(134328)),
|
||||
(unstable, mips_target_feature, "1.27.0", Some(44839)),
|
||||
(unstable, movrs_target_feature, "CURRENT_RUSTC_VERSION", Some(137976)),
|
||||
(unstable, movrs_target_feature, "1.88.0", Some(137976)),
|
||||
(unstable, powerpc_target_feature, "1.27.0", Some(44839)),
|
||||
(unstable, prfchw_target_feature, "1.78.0", Some(44839)),
|
||||
(unstable, riscv_target_feature, "1.45.0", Some(44839)),
|
||||
@@ -385,7 +385,7 @@ pub fn internal(&self, feature: Symbol) -> bool {
|
||||
/// Allows associated type defaults.
|
||||
(unstable, associated_type_defaults, "1.2.0", Some(29661)),
|
||||
/// Allows implementing `AsyncDrop`.
|
||||
(incomplete, async_drop, "CURRENT_RUSTC_VERSION", Some(126482)),
|
||||
(incomplete, async_drop, "1.88.0", Some(126482)),
|
||||
/// Allows async functions to be called from `dyn Trait`.
|
||||
(incomplete, async_fn_in_dyn_trait, "1.85.0", Some(133119)),
|
||||
/// Allows `#[track_caller]` on async functions.
|
||||
@@ -395,7 +395,7 @@ pub fn internal(&self, feature: Symbol) -> bool {
|
||||
/// Allows `async` trait bound modifier.
|
||||
(unstable, async_trait_bounds, "1.85.0", Some(62290)),
|
||||
/// Allows using Intel AVX10 target features and intrinsics
|
||||
(unstable, avx10_target_feature, "CURRENT_RUSTC_VERSION", Some(138843)),
|
||||
(unstable, avx10_target_feature, "1.88.0", Some(138843)),
|
||||
/// Allows using C-variadics.
|
||||
(unstable, c_variadic, "1.34.0", Some(44930)),
|
||||
/// Allows the use of `#[cfg(contract_checks)` to check if contract checks are enabled.
|
||||
@@ -483,11 +483,11 @@ pub fn internal(&self, feature: Symbol) -> bool {
|
||||
/// Allows exhaustive pattern matching on types that contain uninhabited types.
|
||||
(unstable, exhaustive_patterns, "1.13.0", Some(51085)),
|
||||
/// Disallows `extern` without an explicit ABI.
|
||||
(unstable, explicit_extern_abis, "CURRENT_RUSTC_VERSION", Some(134986)),
|
||||
(unstable, explicit_extern_abis, "1.88.0", Some(134986)),
|
||||
/// Allows explicit tail calls via `become` expression.
|
||||
(incomplete, explicit_tail_calls, "1.72.0", Some(112788)),
|
||||
/// Allows using `#[export_stable]` which indicates that an item is exportable.
|
||||
(incomplete, export_stable, "CURRENT_RUSTC_VERSION", Some(139939)),
|
||||
(incomplete, export_stable, "1.88.0", Some(139939)),
|
||||
/// Allows using `aapcs`, `efiapi`, `sysv64` and `win64` as calling conventions
|
||||
/// for functions with varargs.
|
||||
(unstable, extended_varargs_abi_support, "1.65.0", Some(100189)),
|
||||
@@ -512,7 +512,7 @@ pub fn internal(&self, feature: Symbol) -> bool {
|
||||
/// Allows impls for the Freeze trait.
|
||||
(internal, freeze_impls, "1.78.0", Some(121675)),
|
||||
/// Frontmatter `---` blocks for use by external tools.
|
||||
(unstable, frontmatter, "CURRENT_RUSTC_VERSION", Some(136889)),
|
||||
(unstable, frontmatter, "1.88.0", Some(136889)),
|
||||
/// Allows defining gen blocks and `gen fn`.
|
||||
(unstable, gen_blocks, "1.75.0", Some(117078)),
|
||||
/// Infer generic args for both consts and types.
|
||||
@@ -575,7 +575,7 @@ pub fn internal(&self, feature: Symbol) -> bool {
|
||||
/// Allows `mut ref` and `mut ref mut` identifier patterns.
|
||||
(incomplete, mut_ref, "1.79.0", Some(123076)),
|
||||
/// Allows using `#[naked]` on `extern "Rust"` functions.
|
||||
(unstable, naked_functions_rustic_abi, "CURRENT_RUSTC_VERSION", Some(138997)),
|
||||
(unstable, naked_functions_rustic_abi, "1.88.0", Some(138997)),
|
||||
/// Allows using `#[target_feature(enable = "...")]` on `#[naked]` on functions.
|
||||
(unstable, naked_functions_target_feature, "1.86.0", Some(138568)),
|
||||
/// Allows specifying the as-needed link modifier
|
||||
@@ -641,7 +641,7 @@ pub fn internal(&self, feature: Symbol) -> bool {
|
||||
/// Allows string patterns to dereference values to match them.
|
||||
(unstable, string_deref_patterns, "1.67.0", Some(87121)),
|
||||
/// Allows `super let` statements.
|
||||
(unstable, super_let, "CURRENT_RUSTC_VERSION", Some(139076)),
|
||||
(unstable, super_let, "1.88.0", Some(139076)),
|
||||
/// Allows subtrait items to shadow supertrait items.
|
||||
(unstable, supertrait_item_shadowing, "1.86.0", Some(89151)),
|
||||
/// Allows using `#[thread_local]` on `static` items.
|
||||
|
||||
@@ -25,9 +25,6 @@ fn invocation_relative_path_to_absolute(span: Span, path: &str) -> PathBuf {
|
||||
path.to_path_buf()
|
||||
} else {
|
||||
// `/a/b/c/foo/bar.rs` contains the current macro invocation
|
||||
#[cfg(bootstrap)]
|
||||
let mut source_file_path = span.source_file().path();
|
||||
#[cfg(not(bootstrap))]
|
||||
let mut source_file_path = span.local_file().unwrap();
|
||||
// `/a/b/c/foo/`
|
||||
source_file_path.pop();
|
||||
|
||||
@@ -309,6 +309,8 @@ pub enum DefPathData {
|
||||
/// An existential `impl Trait` type node.
|
||||
/// Argument position `impl Trait` have a `TypeNs` with their pretty-printed name.
|
||||
OpaqueTy,
|
||||
/// Used for remapped captured lifetimes in an existential `impl Trait` type node.
|
||||
OpaqueLifetime(Symbol),
|
||||
/// An anonymous associated type from an RPITIT. The symbol refers to the name of the method
|
||||
/// that defined the type.
|
||||
AnonAssocTy(Symbol),
|
||||
@@ -445,7 +447,8 @@ impl DefPathData {
|
||||
pub fn get_opt_name(&self) -> Option<Symbol> {
|
||||
use self::DefPathData::*;
|
||||
match *self {
|
||||
TypeNs(name) | ValueNs(name) | MacroNs(name) | LifetimeNs(name) => Some(name),
|
||||
TypeNs(name) | ValueNs(name) | MacroNs(name) | LifetimeNs(name)
|
||||
| OpaqueLifetime(name) => Some(name),
|
||||
|
||||
Impl
|
||||
| ForeignMod
|
||||
@@ -465,9 +468,8 @@ pub fn get_opt_name(&self) -> Option<Symbol> {
|
||||
fn hashed_symbol(&self) -> Option<Symbol> {
|
||||
use self::DefPathData::*;
|
||||
match *self {
|
||||
TypeNs(name) | ValueNs(name) | MacroNs(name) | LifetimeNs(name) | AnonAssocTy(name) => {
|
||||
Some(name)
|
||||
}
|
||||
TypeNs(name) | ValueNs(name) | MacroNs(name) | LifetimeNs(name) | AnonAssocTy(name)
|
||||
| OpaqueLifetime(name) => Some(name),
|
||||
|
||||
Impl
|
||||
| ForeignMod
|
||||
@@ -486,9 +488,8 @@ fn hashed_symbol(&self) -> Option<Symbol> {
|
||||
pub fn name(&self) -> DefPathDataName {
|
||||
use self::DefPathData::*;
|
||||
match *self {
|
||||
TypeNs(name) | ValueNs(name) | MacroNs(name) | LifetimeNs(name) => {
|
||||
DefPathDataName::Named(name)
|
||||
}
|
||||
TypeNs(name) | ValueNs(name) | MacroNs(name) | LifetimeNs(name)
|
||||
| OpaqueLifetime(name) => DefPathDataName::Named(name),
|
||||
// Note that this does not show up in user print-outs.
|
||||
CrateRoot => DefPathDataName::Anon { namespace: kw::Crate },
|
||||
Impl => DefPathDataName::Anon { namespace: kw::Impl },
|
||||
|
||||
@@ -50,21 +50,14 @@ fn trait_object_roundtrips() {
|
||||
}
|
||||
|
||||
fn trait_object_roundtrips_impl(syntax: TraitObjectSyntax) {
|
||||
let unambig = TyKind::TraitObject::<'_, ()>(
|
||||
&[],
|
||||
TaggedRef::new(
|
||||
&const {
|
||||
Lifetime {
|
||||
hir_id: HirId::INVALID,
|
||||
ident: Ident::new(sym::name, DUMMY_SP),
|
||||
kind: LifetimeKind::Static,
|
||||
source: LifetimeSource::Other,
|
||||
syntax: LifetimeSyntax::Hidden,
|
||||
}
|
||||
},
|
||||
syntax,
|
||||
),
|
||||
);
|
||||
let lt = Lifetime {
|
||||
hir_id: HirId::INVALID,
|
||||
ident: Ident::new(sym::name, DUMMY_SP),
|
||||
kind: LifetimeKind::Static,
|
||||
source: LifetimeSource::Other,
|
||||
syntax: LifetimeSyntax::Hidden,
|
||||
};
|
||||
let unambig = TyKind::TraitObject::<'_, ()>(&[], TaggedRef::new(<, syntax));
|
||||
let unambig_to_ambig = unsafe { std::mem::transmute::<_, TyKind<'_, AmbigArg>>(unambig) };
|
||||
|
||||
match unambig_to_ambig {
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
|
||||
// tidy-alphabetical-start
|
||||
#![allow(internal_features)]
|
||||
#![cfg_attr(bootstrap, feature(let_chains))]
|
||||
#![feature(associated_type_defaults)]
|
||||
#![feature(box_patterns)]
|
||||
#![feature(closure_track_caller)]
|
||||
|
||||
@@ -522,7 +522,7 @@ hir_analysis_trait_object_declared_with_no_traits =
|
||||
at least one trait is required for an object type
|
||||
.alias_span = this alias does not contain a trait
|
||||
|
||||
hir_analysis_traits_with_defualt_impl = traits with a default impl, like `{$traits}`, cannot be implemented for {$problematic_kind} `{$self_ty}`
|
||||
hir_analysis_traits_with_default_impl = traits with a default impl, like `{$traits}`, cannot be implemented for {$problematic_kind} `{$self_ty}`
|
||||
.note = a trait object implements `{$traits}` if and only if `{$traits}` is one of the trait object's trait bounds
|
||||
|
||||
hir_analysis_transparent_enum_variant = transparent enum needs exactly one variant, but has {$number}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
use hir::def_id::{DefId, DefIdMap, LocalDefId};
|
||||
use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet};
|
||||
use rustc_errors::codes::*;
|
||||
use rustc_errors::{Applicability, ErrorGuaranteed, pluralize, struct_span_code_err};
|
||||
use rustc_errors::{Applicability, ErrorGuaranteed, MultiSpan, pluralize, struct_span_code_err};
|
||||
use rustc_hir::def::{DefKind, Res};
|
||||
use rustc_hir::intravisit::VisitorExt;
|
||||
use rustc_hir::{self as hir, AmbigArg, GenericParamKind, ImplItemKind, intravisit};
|
||||
@@ -14,10 +14,10 @@
|
||||
use rustc_middle::ty::error::{ExpectedFound, TypeError};
|
||||
use rustc_middle::ty::{
|
||||
self, BottomUpFolder, GenericArgs, GenericParamDefKind, Ty, TyCtxt, TypeFoldable, TypeFolder,
|
||||
TypeSuperFoldable, TypeVisitableExt, TypingMode, Upcast,
|
||||
TypeSuperFoldable, TypeVisitable, TypeVisitableExt, TypeVisitor, TypingMode, Upcast,
|
||||
};
|
||||
use rustc_middle::{bug, span_bug};
|
||||
use rustc_span::Span;
|
||||
use rustc_span::{DUMMY_SP, Span};
|
||||
use rustc_trait_selection::error_reporting::InferCtxtErrorExt;
|
||||
use rustc_trait_selection::infer::InferCtxtExt;
|
||||
use rustc_trait_selection::regions::InferCtxtRegionExt;
|
||||
@@ -1137,65 +1137,319 @@ fn check_region_bounds_on_impl_item<'tcx>(
|
||||
// but found 0" it's confusing, because it looks like there
|
||||
// are zero. Since I don't quite know how to phrase things at
|
||||
// the moment, give a kind of vague error message.
|
||||
if trait_params != impl_params {
|
||||
let span = tcx
|
||||
.hir_get_generics(impl_m.def_id.expect_local())
|
||||
.expect("expected impl item to have generics or else we can't compare them")
|
||||
.span;
|
||||
if trait_params == impl_params {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let mut generics_span = None;
|
||||
let mut bounds_span = vec![];
|
||||
let mut where_span = None;
|
||||
if let Some(trait_node) = tcx.hir_get_if_local(trait_m.def_id)
|
||||
&& let Some(trait_generics) = trait_node.generics()
|
||||
{
|
||||
generics_span = Some(trait_generics.span);
|
||||
// FIXME: we could potentially look at the impl's bounds to not point at bounds that
|
||||
// *are* present in the impl.
|
||||
for p in trait_generics.predicates {
|
||||
if let hir::WherePredicateKind::BoundPredicate(pred) = p.kind {
|
||||
for b in pred.bounds {
|
||||
if !delay && let Some(guar) = check_region_late_boundedness(tcx, impl_m, trait_m) {
|
||||
return Err(guar);
|
||||
}
|
||||
|
||||
let span = tcx
|
||||
.hir_get_generics(impl_m.def_id.expect_local())
|
||||
.expect("expected impl item to have generics or else we can't compare them")
|
||||
.span;
|
||||
|
||||
let mut generics_span = None;
|
||||
let mut bounds_span = vec![];
|
||||
let mut where_span = None;
|
||||
|
||||
if let Some(trait_node) = tcx.hir_get_if_local(trait_m.def_id)
|
||||
&& let Some(trait_generics) = trait_node.generics()
|
||||
{
|
||||
generics_span = Some(trait_generics.span);
|
||||
// FIXME: we could potentially look at the impl's bounds to not point at bounds that
|
||||
// *are* present in the impl.
|
||||
for p in trait_generics.predicates {
|
||||
match p.kind {
|
||||
hir::WherePredicateKind::BoundPredicate(hir::WhereBoundPredicate {
|
||||
bounds,
|
||||
..
|
||||
})
|
||||
| hir::WherePredicateKind::RegionPredicate(hir::WhereRegionPredicate {
|
||||
bounds,
|
||||
..
|
||||
}) => {
|
||||
for b in *bounds {
|
||||
if let hir::GenericBound::Outlives(lt) = b {
|
||||
bounds_span.push(lt.ident.span);
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
if let Some(impl_node) = tcx.hir_get_if_local(impl_m.def_id)
|
||||
&& let Some(impl_generics) = impl_node.generics()
|
||||
{
|
||||
let mut impl_bounds = 0;
|
||||
for p in impl_generics.predicates {
|
||||
if let hir::WherePredicateKind::BoundPredicate(pred) = p.kind {
|
||||
for b in pred.bounds {
|
||||
}
|
||||
if let Some(impl_node) = tcx.hir_get_if_local(impl_m.def_id)
|
||||
&& let Some(impl_generics) = impl_node.generics()
|
||||
{
|
||||
let mut impl_bounds = 0;
|
||||
for p in impl_generics.predicates {
|
||||
match p.kind {
|
||||
hir::WherePredicateKind::BoundPredicate(hir::WhereBoundPredicate {
|
||||
bounds,
|
||||
..
|
||||
})
|
||||
| hir::WherePredicateKind::RegionPredicate(hir::WhereRegionPredicate {
|
||||
bounds,
|
||||
..
|
||||
}) => {
|
||||
for b in *bounds {
|
||||
if let hir::GenericBound::Outlives(_) = b {
|
||||
impl_bounds += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if impl_bounds == bounds_span.len() {
|
||||
bounds_span = vec![];
|
||||
} else if impl_generics.has_where_clause_predicates {
|
||||
where_span = Some(impl_generics.where_clause_span);
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
if impl_bounds == bounds_span.len() {
|
||||
bounds_span = vec![];
|
||||
} else if impl_generics.has_where_clause_predicates {
|
||||
where_span = Some(impl_generics.where_clause_span);
|
||||
}
|
||||
}
|
||||
let reported = tcx
|
||||
.dcx()
|
||||
.create_err(LifetimesOrBoundsMismatchOnTrait {
|
||||
span,
|
||||
item_kind: impl_m.descr(),
|
||||
ident: impl_m.ident(tcx),
|
||||
generics_span,
|
||||
bounds_span,
|
||||
where_span,
|
||||
})
|
||||
.emit_unless(delay);
|
||||
return Err(reported);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
let reported = tcx
|
||||
.dcx()
|
||||
.create_err(LifetimesOrBoundsMismatchOnTrait {
|
||||
span,
|
||||
item_kind: impl_m.descr(),
|
||||
ident: impl_m.ident(tcx),
|
||||
generics_span,
|
||||
bounds_span,
|
||||
where_span,
|
||||
})
|
||||
.emit_unless(delay);
|
||||
|
||||
Err(reported)
|
||||
}
|
||||
|
||||
#[allow(unused)]
|
||||
enum LateEarlyMismatch<'tcx> {
|
||||
EarlyInImpl(DefId, DefId, ty::Region<'tcx>),
|
||||
LateInImpl(DefId, DefId, ty::Region<'tcx>),
|
||||
}
|
||||
|
||||
fn check_region_late_boundedness<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
impl_m: ty::AssocItem,
|
||||
trait_m: ty::AssocItem,
|
||||
) -> Option<ErrorGuaranteed> {
|
||||
if !impl_m.is_fn() {
|
||||
return None;
|
||||
}
|
||||
|
||||
let (infcx, param_env) = tcx
|
||||
.infer_ctxt()
|
||||
.build_with_typing_env(ty::TypingEnv::non_body_analysis(tcx, impl_m.def_id));
|
||||
|
||||
let impl_m_args = infcx.fresh_args_for_item(DUMMY_SP, impl_m.def_id);
|
||||
let impl_m_sig = tcx.fn_sig(impl_m.def_id).instantiate(tcx, impl_m_args);
|
||||
let impl_m_sig = tcx.liberate_late_bound_regions(impl_m.def_id, impl_m_sig);
|
||||
|
||||
let trait_m_args = infcx.fresh_args_for_item(DUMMY_SP, trait_m.def_id);
|
||||
let trait_m_sig = tcx.fn_sig(trait_m.def_id).instantiate(tcx, trait_m_args);
|
||||
let trait_m_sig = tcx.liberate_late_bound_regions(impl_m.def_id, trait_m_sig);
|
||||
|
||||
let ocx = ObligationCtxt::new(&infcx);
|
||||
|
||||
// Equate the signatures so that we can infer whether a late-bound param was present where
|
||||
// an early-bound param was expected, since we replace the late-bound lifetimes with
|
||||
// `ReLateParam`, and early-bound lifetimes with infer vars, so the early-bound args will
|
||||
// resolve to `ReLateParam` if there is a mismatch.
|
||||
let Ok(()) = ocx.eq(
|
||||
&ObligationCause::dummy(),
|
||||
param_env,
|
||||
ty::Binder::dummy(trait_m_sig),
|
||||
ty::Binder::dummy(impl_m_sig),
|
||||
) else {
|
||||
return None;
|
||||
};
|
||||
|
||||
let errors = ocx.select_where_possible();
|
||||
if !errors.is_empty() {
|
||||
return None;
|
||||
}
|
||||
|
||||
let mut mismatched = vec![];
|
||||
|
||||
let impl_generics = tcx.generics_of(impl_m.def_id);
|
||||
for (id_arg, arg) in
|
||||
std::iter::zip(ty::GenericArgs::identity_for_item(tcx, impl_m.def_id), impl_m_args)
|
||||
{
|
||||
if let ty::GenericArgKind::Lifetime(r) = arg.unpack()
|
||||
&& let ty::ReVar(vid) = r.kind()
|
||||
&& let r = infcx
|
||||
.inner
|
||||
.borrow_mut()
|
||||
.unwrap_region_constraints()
|
||||
.opportunistic_resolve_var(tcx, vid)
|
||||
&& let ty::ReLateParam(ty::LateParamRegion {
|
||||
kind: ty::LateParamRegionKind::Named(trait_param_def_id, _),
|
||||
..
|
||||
}) = r.kind()
|
||||
&& let ty::ReEarlyParam(ebr) = id_arg.expect_region().kind()
|
||||
{
|
||||
mismatched.push(LateEarlyMismatch::EarlyInImpl(
|
||||
impl_generics.region_param(ebr, tcx).def_id,
|
||||
trait_param_def_id,
|
||||
id_arg.expect_region(),
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
let trait_generics = tcx.generics_of(trait_m.def_id);
|
||||
for (id_arg, arg) in
|
||||
std::iter::zip(ty::GenericArgs::identity_for_item(tcx, trait_m.def_id), trait_m_args)
|
||||
{
|
||||
if let ty::GenericArgKind::Lifetime(r) = arg.unpack()
|
||||
&& let ty::ReVar(vid) = r.kind()
|
||||
&& let r = infcx
|
||||
.inner
|
||||
.borrow_mut()
|
||||
.unwrap_region_constraints()
|
||||
.opportunistic_resolve_var(tcx, vid)
|
||||
&& let ty::ReLateParam(ty::LateParamRegion {
|
||||
kind: ty::LateParamRegionKind::Named(impl_param_def_id, _),
|
||||
..
|
||||
}) = r.kind()
|
||||
&& let ty::ReEarlyParam(ebr) = id_arg.expect_region().kind()
|
||||
{
|
||||
mismatched.push(LateEarlyMismatch::LateInImpl(
|
||||
impl_param_def_id,
|
||||
trait_generics.region_param(ebr, tcx).def_id,
|
||||
id_arg.expect_region(),
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
if mismatched.is_empty() {
|
||||
return None;
|
||||
}
|
||||
|
||||
let spans: Vec<_> = mismatched
|
||||
.iter()
|
||||
.map(|param| {
|
||||
let (LateEarlyMismatch::EarlyInImpl(impl_param_def_id, ..)
|
||||
| LateEarlyMismatch::LateInImpl(impl_param_def_id, ..)) = param;
|
||||
tcx.def_span(impl_param_def_id)
|
||||
})
|
||||
.collect();
|
||||
|
||||
let mut diag = tcx
|
||||
.dcx()
|
||||
.struct_span_err(spans, "lifetime parameters do not match the trait definition")
|
||||
.with_note("lifetime parameters differ in whether they are early- or late-bound")
|
||||
.with_code(E0195);
|
||||
for mismatch in mismatched {
|
||||
match mismatch {
|
||||
LateEarlyMismatch::EarlyInImpl(
|
||||
impl_param_def_id,
|
||||
trait_param_def_id,
|
||||
early_bound_region,
|
||||
) => {
|
||||
let mut multispan = MultiSpan::from_spans(vec![
|
||||
tcx.def_span(impl_param_def_id),
|
||||
tcx.def_span(trait_param_def_id),
|
||||
]);
|
||||
multispan
|
||||
.push_span_label(tcx.def_span(tcx.parent(impl_m.def_id)), "in this impl...");
|
||||
multispan
|
||||
.push_span_label(tcx.def_span(tcx.parent(trait_m.def_id)), "in this trait...");
|
||||
multispan.push_span_label(
|
||||
tcx.def_span(impl_param_def_id),
|
||||
format!("`{}` is early-bound", tcx.item_name(impl_param_def_id)),
|
||||
);
|
||||
multispan.push_span_label(
|
||||
tcx.def_span(trait_param_def_id),
|
||||
format!("`{}` is late-bound", tcx.item_name(trait_param_def_id)),
|
||||
);
|
||||
if let Some(span) =
|
||||
find_region_in_predicates(tcx, impl_m.def_id, early_bound_region)
|
||||
{
|
||||
multispan.push_span_label(
|
||||
span,
|
||||
format!(
|
||||
"this lifetime bound makes `{}` early-bound",
|
||||
tcx.item_name(impl_param_def_id)
|
||||
),
|
||||
);
|
||||
}
|
||||
diag.span_note(
|
||||
multispan,
|
||||
format!(
|
||||
"`{}` differs between the trait and impl",
|
||||
tcx.item_name(impl_param_def_id)
|
||||
),
|
||||
);
|
||||
}
|
||||
LateEarlyMismatch::LateInImpl(
|
||||
impl_param_def_id,
|
||||
trait_param_def_id,
|
||||
early_bound_region,
|
||||
) => {
|
||||
let mut multispan = MultiSpan::from_spans(vec![
|
||||
tcx.def_span(impl_param_def_id),
|
||||
tcx.def_span(trait_param_def_id),
|
||||
]);
|
||||
multispan
|
||||
.push_span_label(tcx.def_span(tcx.parent(impl_m.def_id)), "in this impl...");
|
||||
multispan
|
||||
.push_span_label(tcx.def_span(tcx.parent(trait_m.def_id)), "in this trait...");
|
||||
multispan.push_span_label(
|
||||
tcx.def_span(impl_param_def_id),
|
||||
format!("`{}` is late-bound", tcx.item_name(impl_param_def_id)),
|
||||
);
|
||||
multispan.push_span_label(
|
||||
tcx.def_span(trait_param_def_id),
|
||||
format!("`{}` is early-bound", tcx.item_name(trait_param_def_id)),
|
||||
);
|
||||
if let Some(span) =
|
||||
find_region_in_predicates(tcx, trait_m.def_id, early_bound_region)
|
||||
{
|
||||
multispan.push_span_label(
|
||||
span,
|
||||
format!(
|
||||
"this lifetime bound makes `{}` early-bound",
|
||||
tcx.item_name(trait_param_def_id)
|
||||
),
|
||||
);
|
||||
}
|
||||
diag.span_note(
|
||||
multispan,
|
||||
format!(
|
||||
"`{}` differs between the trait and impl",
|
||||
tcx.item_name(impl_param_def_id)
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Some(diag.emit())
|
||||
}
|
||||
|
||||
fn find_region_in_predicates<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
def_id: DefId,
|
||||
early_bound_region: ty::Region<'tcx>,
|
||||
) -> Option<Span> {
|
||||
for (pred, span) in tcx.explicit_predicates_of(def_id).instantiate_identity(tcx) {
|
||||
if pred.visit_with(&mut FindRegion(early_bound_region)).is_break() {
|
||||
return Some(span);
|
||||
}
|
||||
}
|
||||
|
||||
struct FindRegion<'tcx>(ty::Region<'tcx>);
|
||||
impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for FindRegion<'tcx> {
|
||||
type Result = ControlFlow<()>;
|
||||
fn visit_region(&mut self, r: ty::Region<'tcx>) -> Self::Result {
|
||||
if r == self.0 { ControlFlow::Break(()) } else { ControlFlow::Continue(()) }
|
||||
}
|
||||
}
|
||||
|
||||
None
|
||||
}
|
||||
|
||||
#[instrument(level = "debug", skip(infcx))]
|
||||
|
||||
@@ -103,10 +103,18 @@ fn intrinsic_operation_unsafety(tcx: TyCtxt<'_>, intrinsic_id: LocalDefId) -> hi
|
||||
| sym::minnumf32
|
||||
| sym::minnumf64
|
||||
| sym::minnumf128
|
||||
| sym::minimumf16
|
||||
| sym::minimumf32
|
||||
| sym::minimumf64
|
||||
| sym::minimumf128
|
||||
| sym::maxnumf16
|
||||
| sym::maxnumf32
|
||||
| sym::maxnumf64
|
||||
| sym::maxnumf128
|
||||
| sym::maximumf16
|
||||
| sym::maximumf32
|
||||
| sym::maximumf64
|
||||
| sym::maximumf128
|
||||
| sym::rustc_peek
|
||||
| sym::type_name
|
||||
| sym::forget
|
||||
@@ -374,11 +382,21 @@ pub(crate) fn check_intrinsic_type(
|
||||
sym::minnumf64 => (0, 0, vec![tcx.types.f64, tcx.types.f64], tcx.types.f64),
|
||||
sym::minnumf128 => (0, 0, vec![tcx.types.f128, tcx.types.f128], tcx.types.f128),
|
||||
|
||||
sym::minimumf16 => (0, 0, vec![tcx.types.f16, tcx.types.f16], tcx.types.f16),
|
||||
sym::minimumf32 => (0, 0, vec![tcx.types.f32, tcx.types.f32], tcx.types.f32),
|
||||
sym::minimumf64 => (0, 0, vec![tcx.types.f64, tcx.types.f64], tcx.types.f64),
|
||||
sym::minimumf128 => (0, 0, vec![tcx.types.f128, tcx.types.f128], tcx.types.f128),
|
||||
|
||||
sym::maxnumf16 => (0, 0, vec![tcx.types.f16, tcx.types.f16], tcx.types.f16),
|
||||
sym::maxnumf32 => (0, 0, vec![tcx.types.f32, tcx.types.f32], tcx.types.f32),
|
||||
sym::maxnumf64 => (0, 0, vec![tcx.types.f64, tcx.types.f64], tcx.types.f64),
|
||||
sym::maxnumf128 => (0, 0, vec![tcx.types.f128, tcx.types.f128], tcx.types.f128),
|
||||
|
||||
sym::maximumf16 => (0, 0, vec![tcx.types.f16, tcx.types.f16], tcx.types.f16),
|
||||
sym::maximumf32 => (0, 0, vec![tcx.types.f32, tcx.types.f32], tcx.types.f32),
|
||||
sym::maximumf64 => (0, 0, vec![tcx.types.f64, tcx.types.f64], tcx.types.f64),
|
||||
sym::maximumf128 => (0, 0, vec![tcx.types.f128, tcx.types.f128], tcx.types.f128),
|
||||
|
||||
sym::copysignf16 => (0, 0, vec![tcx.types.f16, tcx.types.f16], tcx.types.f16),
|
||||
sym::copysignf32 => (0, 0, vec![tcx.types.f32, tcx.types.f32], tcx.types.f32),
|
||||
sym::copysignf64 => (0, 0, vec![tcx.types.f64, tcx.types.f64], tcx.types.f64),
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet};
|
||||
use rustc_errors::ErrorGuaranteed;
|
||||
use rustc_hir::def::{DefKind, Res};
|
||||
use rustc_hir::definitions::DisambiguatorState;
|
||||
use rustc_hir::definitions::{DefPathData, DisambiguatorState};
|
||||
use rustc_hir::intravisit::{self, InferKind, Visitor, VisitorExt};
|
||||
use rustc_hir::{
|
||||
self as hir, AmbigArg, GenericArg, GenericParam, GenericParamKind, HirId, LifetimeKind, Node,
|
||||
@@ -1470,14 +1470,14 @@ fn remap_opaque_captures(
|
||||
let mut captures = captures.borrow_mut();
|
||||
let remapped = *captures.entry(lifetime).or_insert_with(|| {
|
||||
// `opaque_def_id` is unique to the `BoundVarContext` pass which is executed once
|
||||
// per `resolve_bound_vars` query. This is the only location that creates nested
|
||||
// lifetime inside a opaque type. `<opaque_def_id>::LifetimeNs(..)` is thus unique
|
||||
// per `resolve_bound_vars` query. This is the only location that creates
|
||||
// `OpaqueLifetime` paths. `<opaque_def_id>::OpaqueLifetime(..)` is thus unique
|
||||
// to this query and duplicates within the query are handled by `self.disambiguator`.
|
||||
let feed = self.tcx.create_def(
|
||||
opaque_def_id,
|
||||
Some(ident.name),
|
||||
DefKind::LifetimeParam,
|
||||
None,
|
||||
DefKind::LifetimeParam,
|
||||
Some(DefPathData::OpaqueLifetime(ident.name)),
|
||||
&mut self.disambiguator,
|
||||
);
|
||||
feed.def_span(ident.span);
|
||||
|
||||
@@ -1327,7 +1327,7 @@ pub(crate) struct ImplForTyRequires {
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(hir_analysis_traits_with_defualt_impl, code = E0321)]
|
||||
#[diag(hir_analysis_traits_with_default_impl, code = E0321)]
|
||||
#[note]
|
||||
pub(crate) struct TraitsWithDefaultImpl<'a> {
|
||||
#[primary_span]
|
||||
|
||||
@@ -9,8 +9,8 @@
|
||||
use rustc_hir::{AmbigArg, HirId};
|
||||
use rustc_middle::bug;
|
||||
use rustc_middle::ty::{
|
||||
self as ty, IsSuggestable, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitableExt,
|
||||
TypeVisitor, Upcast,
|
||||
self as ty, IsSuggestable, Ty, TyCtxt, TypeFoldable, TypeSuperVisitable, TypeVisitable,
|
||||
TypeVisitableExt, TypeVisitor, Upcast,
|
||||
};
|
||||
use rustc_span::{ErrorGuaranteed, Ident, Span, Symbol, kw, sym};
|
||||
use rustc_trait_selection::traits;
|
||||
@@ -996,7 +996,7 @@ struct GenericParamAndBoundVarCollector<'a, 'tcx> {
|
||||
impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for GenericParamAndBoundVarCollector<'_, 'tcx> {
|
||||
type Result = ControlFlow<ErrorGuaranteed>;
|
||||
|
||||
fn visit_binder<T: TypeVisitable<TyCtxt<'tcx>>>(
|
||||
fn visit_binder<T: TypeFoldable<TyCtxt<'tcx>>>(
|
||||
&mut self,
|
||||
binder: &ty::Binder<'tcx, T>,
|
||||
) -> Self::Result {
|
||||
|
||||
@@ -172,7 +172,14 @@ pub(super) fn lower_trait_object_ty(
|
||||
|
||||
let principal_trait = regular_traits.into_iter().next();
|
||||
|
||||
let mut needed_associated_types = vec![];
|
||||
// A stable ordering of associated types from the principal trait and all its
|
||||
// supertraits. We use this to ensure that different substitutions of a trait
|
||||
// don't result in `dyn Trait` types with different projections lists, which
|
||||
// can be unsound: <https://github.com/rust-lang/rust/pull/136458>.
|
||||
// We achieve a stable ordering by walking over the unsubstituted principal
|
||||
// trait ref.
|
||||
let mut ordered_associated_types = vec![];
|
||||
|
||||
if let Some((principal_trait, ref spans)) = principal_trait {
|
||||
let principal_trait = principal_trait.map_bound(|trait_pred| {
|
||||
assert_eq!(trait_pred.polarity, ty::PredicatePolarity::Positive);
|
||||
@@ -197,16 +204,13 @@ pub(super) fn lower_trait_object_ty(
|
||||
// FIXME(negative_bounds): Handle this correctly...
|
||||
let trait_ref =
|
||||
tcx.anonymize_bound_vars(bound_predicate.rebind(pred.trait_ref));
|
||||
needed_associated_types.extend(
|
||||
ordered_associated_types.extend(
|
||||
tcx.associated_items(pred.trait_ref.def_id)
|
||||
.in_definition_order()
|
||||
// We only care about associated types.
|
||||
.filter(|item| item.is_type())
|
||||
// No RPITITs -- they're not dyn-compatible for now.
|
||||
.filter(|item| !item.is_impl_trait_in_trait())
|
||||
// If the associated type has a `where Self: Sized` bound,
|
||||
// we do not need to constrain the associated type.
|
||||
.filter(|item| !tcx.generics_require_sized_self(item.def_id))
|
||||
.map(|item| (item.def_id, trait_ref)),
|
||||
);
|
||||
}
|
||||
@@ -278,14 +282,26 @@ pub(super) fn lower_trait_object_ty(
|
||||
}
|
||||
}
|
||||
|
||||
// We compute the list of projection bounds taking the ordered associated types,
|
||||
// and check if there was an entry in the collected `projection_bounds`. Those
|
||||
// are computed by first taking the user-written associated types, then elaborating
|
||||
// the principal trait ref, and only using those if there was no user-written.
|
||||
// See note below about how we handle missing associated types with `Self: Sized`,
|
||||
// which are not required to be provided, but are still used if they are provided.
|
||||
let mut missing_assoc_types = FxIndexSet::default();
|
||||
let projection_bounds: Vec<_> = needed_associated_types
|
||||
let projection_bounds: Vec<_> = ordered_associated_types
|
||||
.into_iter()
|
||||
.filter_map(|key| {
|
||||
if let Some(assoc) = projection_bounds.get(&key) {
|
||||
Some(*assoc)
|
||||
} else {
|
||||
missing_assoc_types.insert(key);
|
||||
// If the associated type has a `where Self: Sized` bound, then
|
||||
// we do not need to provide the associated type. This results in
|
||||
// a `dyn Trait` type that has a different number of projection
|
||||
// bounds, which may lead to type mismatches.
|
||||
if !tcx.generics_require_sized_self(key.0) {
|
||||
missing_assoc_types.insert(key);
|
||||
}
|
||||
None
|
||||
}
|
||||
})
|
||||
|
||||
@@ -59,7 +59,6 @@
|
||||
#![allow(internal_features)]
|
||||
#![allow(rustc::diagnostic_outside_of_impl)]
|
||||
#![allow(rustc::untranslatable_diagnostic)]
|
||||
#![cfg_attr(bootstrap, feature(let_chains))]
|
||||
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
|
||||
#![doc(rust_logo)]
|
||||
#![feature(assert_matches)]
|
||||
@@ -223,10 +222,6 @@ pub fn check_crate(tcx: TyCtxt<'_>) {
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
});
|
||||
|
||||
tcx.par_hir_body_owners(|item_def_id| {
|
||||
let def_kind = tcx.def_kind(item_def_id);
|
||||
// Skip `AnonConst`s because we feed their `type_of`.
|
||||
if !matches!(def_kind, DefKind::AnonConst) {
|
||||
tcx.ensure_ok().typeck(item_def_id);
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
//! the definitions in this file have equivalents in `rustc_ast_pretty`.
|
||||
|
||||
// tidy-alphabetical-start
|
||||
#![cfg_attr(bootstrap, feature(let_chains))]
|
||||
#![recursion_limit = "256"]
|
||||
// tidy-alphabetical-end
|
||||
|
||||
|
||||
@@ -2339,7 +2339,7 @@ struct MismatchedParam<'a> {
|
||||
}
|
||||
|
||||
if !mismatched_params.is_empty() {
|
||||
// For each mismatched paramter, create a two-way link to each matched parameter
|
||||
// For each mismatched parameter, create a two-way link to each matched parameter
|
||||
// of the same type.
|
||||
let mut dependants = IndexVec::<ExpectedIdx, _>::from_fn_n(
|
||||
|_| SmallVec::<[u32; 4]>::new(),
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
// tidy-alphabetical-start
|
||||
#![allow(rustc::diagnostic_outside_of_impl)]
|
||||
#![allow(rustc::untranslatable_diagnostic)]
|
||||
#![cfg_attr(bootstrap, feature(let_chains))]
|
||||
#![feature(array_windows)]
|
||||
#![feature(box_patterns)]
|
||||
#![feature(if_let_guard)]
|
||||
@@ -32,6 +31,7 @@
|
||||
mod intrinsicck;
|
||||
mod method;
|
||||
mod op;
|
||||
mod opaque_types;
|
||||
mod pat;
|
||||
mod place_op;
|
||||
mod rvalue_scopes;
|
||||
@@ -245,9 +245,7 @@ fn typeck_with_inspect<'tcx>(
|
||||
|
||||
let typeck_results = fcx.resolve_type_vars_in_body(body);
|
||||
|
||||
// We clone the defined opaque types during writeback in the new solver
|
||||
// because we have to use them during normalization.
|
||||
let _ = fcx.infcx.take_opaque_types();
|
||||
fcx.detect_opaque_types_added_during_writeback();
|
||||
|
||||
// Consistency check our TypeckResults instance can hold all ItemLocalIds
|
||||
// it will need to hold.
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
use super::FnCtxt;
|
||||
impl<'tcx> FnCtxt<'_, 'tcx> {
|
||||
/// We may in theory add further uses of an opaque after cloning the opaque
|
||||
/// types storage during writeback when computing the defining uses.
|
||||
///
|
||||
/// Silently ignoring them is dangerous and could result in ICE or even in
|
||||
/// unsoundness, so we make sure we catch such cases here. There's currently
|
||||
/// no known code where this actually happens, even with the new solver which
|
||||
/// does normalize types in writeback after cloning the opaque type storage.
|
||||
///
|
||||
/// FIXME(@lcnr): I believe this should be possible in theory and would like
|
||||
/// an actual test here. After playing around with this for an hour, I wasn't
|
||||
/// able to do anything which didn't already try to normalize the opaque before
|
||||
/// then, either allowing compilation to succeed or causing an ambiguity error.
|
||||
pub(super) fn detect_opaque_types_added_during_writeback(&self) {
|
||||
let num_entries = self.checked_opaque_types_storage_entries.take().unwrap();
|
||||
for (key, hidden_type) in
|
||||
self.inner.borrow_mut().opaque_types().opaque_types_added_since(num_entries)
|
||||
{
|
||||
let opaque_type_string = self.tcx.def_path_str(key.def_id);
|
||||
let msg = format!("unexpected cyclic definition of `{opaque_type_string}`");
|
||||
self.dcx().span_delayed_bug(hidden_type.span, msg);
|
||||
}
|
||||
let _ = self.take_opaque_types();
|
||||
}
|
||||
}
|
||||
@@ -650,14 +650,13 @@ fn calc_adjust_mode(
|
||||
match &pat.kind {
|
||||
// Type checking these product-like types successfully always require
|
||||
// that the expected type be of those types and not reference types.
|
||||
PatKind::Tuple(..)
|
||||
| PatKind::Range(..)
|
||||
| PatKind::Slice(..) => AdjustMode::peel_all(),
|
||||
PatKind::Tuple(..) | PatKind::Range(..) | PatKind::Slice(..) => AdjustMode::peel_all(),
|
||||
// When checking an explicit deref pattern, only peel reference types.
|
||||
// FIXME(deref_patterns): If box patterns and deref patterns need to coexist, box
|
||||
// patterns may want `PeelKind::Implicit`, stopping on encountering a box.
|
||||
| PatKind::Box(_)
|
||||
| PatKind::Deref(_) => AdjustMode::Peel { kind: PeelKind::ExplicitDerefPat },
|
||||
PatKind::Box(_) | PatKind::Deref(_) => {
|
||||
AdjustMode::Peel { kind: PeelKind::ExplicitDerefPat }
|
||||
}
|
||||
// A never pattern behaves somewhat like a literal or unit variant.
|
||||
PatKind::Never => AdjustMode::peel_all(),
|
||||
// For patterns with paths, how we peel the scrutinee depends on the path's resolution.
|
||||
@@ -679,7 +678,11 @@ fn calc_adjust_mode(
|
||||
&& self.tcx.features().deref_patterns()
|
||||
&& !matches!(lt.kind, PatExprKind::Lit { .. })
|
||||
{
|
||||
span_bug!(lt.span, "FIXME(deref_patterns): adjust mode unimplemented for {:?}", lt.kind);
|
||||
span_bug!(
|
||||
lt.span,
|
||||
"FIXME(deref_patterns): adjust mode unimplemented for {:?}",
|
||||
lt.kind
|
||||
);
|
||||
}
|
||||
// Call `resolve_vars_if_possible` here for inline const blocks.
|
||||
let lit_ty = self.resolve_vars_if_possible(self.check_pat_expr_unadjusted(lt));
|
||||
@@ -687,17 +690,21 @@ fn calc_adjust_mode(
|
||||
if self.tcx.features().deref_patterns() {
|
||||
let mut peeled_ty = lit_ty;
|
||||
let mut pat_ref_layers = 0;
|
||||
while let ty::Ref(_, inner_ty, mutbl) = *peeled_ty.kind() {
|
||||
while let ty::Ref(_, inner_ty, mutbl) =
|
||||
*self.try_structurally_resolve_type(pat.span, peeled_ty).kind()
|
||||
{
|
||||
// We rely on references at the head of constants being immutable.
|
||||
debug_assert!(mutbl.is_not());
|
||||
pat_ref_layers += 1;
|
||||
peeled_ty = inner_ty;
|
||||
}
|
||||
AdjustMode::Peel { kind: PeelKind::Implicit { until_adt: None, pat_ref_layers } }
|
||||
AdjustMode::Peel {
|
||||
kind: PeelKind::Implicit { until_adt: None, pat_ref_layers },
|
||||
}
|
||||
} else {
|
||||
if lit_ty.is_ref() { AdjustMode::Pass } else { AdjustMode::peel_all() }
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
// Ref patterns are complicated, we handle them in `check_pat_ref`.
|
||||
PatKind::Ref(..)
|
||||
@@ -928,6 +935,7 @@ fn check_pat_range(
|
||||
// be peeled to `str` while ty here is still `&str`, if we don't
|
||||
// err early here, a rather confusing unification error will be
|
||||
// emitted instead).
|
||||
let ty = self.try_structurally_resolve_type(expr.span, ty);
|
||||
let fail =
|
||||
!(ty.is_numeric() || ty.is_char() || ty.is_ty_var() || ty.references_error());
|
||||
Some((fail, ty, expr.span))
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
use std::cell::RefCell;
|
||||
use std::cell::{Cell, RefCell};
|
||||
use std::ops::Deref;
|
||||
|
||||
use rustc_data_structures::unord::{UnordMap, UnordSet};
|
||||
use rustc_hir::def_id::LocalDefId;
|
||||
use rustc_hir::{self as hir, HirId, HirIdMap, LangItem};
|
||||
use rustc_infer::infer::{InferCtxt, InferOk, TyCtxtInferExt};
|
||||
use rustc_infer::infer::{InferCtxt, InferOk, OpaqueTypeStorageEntries, TyCtxtInferExt};
|
||||
use rustc_middle::span_bug;
|
||||
use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt, TypingMode};
|
||||
use rustc_span::Span;
|
||||
@@ -37,6 +37,11 @@ pub(crate) struct TypeckRootCtxt<'tcx> {
|
||||
|
||||
pub(super) fulfillment_cx: RefCell<Box<dyn TraitEngine<'tcx, FulfillmentError<'tcx>>>>,
|
||||
|
||||
// Used to detect opaque types uses added after we've already checked them.
|
||||
//
|
||||
// See [FnCtxt::detect_opaque_types_added_during_writeback] for more details.
|
||||
pub(super) checked_opaque_types_storage_entries: Cell<Option<OpaqueTypeStorageEntries>>,
|
||||
|
||||
/// Some additional `Sized` obligations badly affect type inference.
|
||||
/// These obligations are added in a later stage of typeck.
|
||||
/// Removing these may also cause additional complications, see #101066.
|
||||
@@ -85,12 +90,14 @@ pub(crate) fn new(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Self {
|
||||
let infcx =
|
||||
tcx.infer_ctxt().ignoring_regions().build(TypingMode::typeck_for_body(tcx, def_id));
|
||||
let typeck_results = RefCell::new(ty::TypeckResults::new(hir_owner));
|
||||
let fulfillment_cx = RefCell::new(<dyn TraitEngine<'_, _>>::new(&infcx));
|
||||
|
||||
TypeckRootCtxt {
|
||||
typeck_results,
|
||||
fulfillment_cx: RefCell::new(<dyn TraitEngine<'_, _>>::new(&infcx)),
|
||||
infcx,
|
||||
typeck_results,
|
||||
locals: RefCell::new(Default::default()),
|
||||
fulfillment_cx,
|
||||
checked_opaque_types_storage_entries: Cell::new(None),
|
||||
deferred_sized_obligations: RefCell::new(Vec::new()),
|
||||
deferred_call_resolutions: RefCell::new(Default::default()),
|
||||
deferred_cast_checks: RefCell::new(Vec::new()),
|
||||
|
||||
@@ -535,13 +535,10 @@ fn visit_opaque_types(&mut self) {
|
||||
let tcx = self.tcx();
|
||||
// We clone the opaques instead of stealing them here as they are still used for
|
||||
// normalization in the next generation trait solver.
|
||||
//
|
||||
// FIXME(-Znext-solver): Opaque types defined after this would simply get dropped
|
||||
// at the end of typeck. While this seems unlikely to happen in practice this
|
||||
// should still get fixed. Either by preventing writeback from defining new opaque
|
||||
// types or by using this function at the end of writeback and running it as a
|
||||
// fixpoint.
|
||||
let opaque_types = self.fcx.infcx.clone_opaque_types();
|
||||
let num_entries = self.fcx.inner.borrow_mut().opaque_types().num_entries();
|
||||
let prev = self.fcx.checked_opaque_types_storage_entries.replace(Some(num_entries));
|
||||
debug_assert_eq!(prev, None);
|
||||
for (opaque_type_key, hidden_type) in opaque_types {
|
||||
let hidden_type = self.resolve(hidden_type, &hidden_type.span);
|
||||
let opaque_type_key = self.resolve(opaque_type_key, &hidden_type.span);
|
||||
|
||||
@@ -6,7 +6,10 @@
|
||||
use rustc_middle::ty::{self, Ty, TyCtxt, TypeFoldable};
|
||||
use rustc_span::{DUMMY_SP, ErrorGuaranteed, Span};
|
||||
|
||||
use super::{BoundRegionConversionTime, InferCtxt, RegionVariableOrigin, SubregionOrigin};
|
||||
use super::{
|
||||
BoundRegionConversionTime, InferCtxt, OpaqueTypeStorageEntries, RegionVariableOrigin,
|
||||
SubregionOrigin,
|
||||
};
|
||||
|
||||
impl<'tcx> rustc_type_ir::InferCtxtLike for InferCtxt<'tcx> {
|
||||
type Interner = TyCtxt<'tcx>;
|
||||
@@ -213,4 +216,58 @@ fn equate_regions(&self, a: ty::Region<'tcx>, b: ty::Region<'tcx>, span: Span) {
|
||||
fn register_ty_outlives(&self, ty: Ty<'tcx>, r: ty::Region<'tcx>, span: Span) {
|
||||
self.register_region_obligation_with_cause(ty, r, &ObligationCause::dummy_with_span(span));
|
||||
}
|
||||
|
||||
type OpaqueTypeStorageEntries = OpaqueTypeStorageEntries;
|
||||
fn opaque_types_storage_num_entries(&self) -> OpaqueTypeStorageEntries {
|
||||
self.inner.borrow_mut().opaque_types().num_entries()
|
||||
}
|
||||
fn clone_opaque_types_lookup_table(&self) -> Vec<(ty::OpaqueTypeKey<'tcx>, Ty<'tcx>)> {
|
||||
self.inner.borrow_mut().opaque_types().iter_lookup_table().map(|(k, h)| (k, h.ty)).collect()
|
||||
}
|
||||
fn clone_duplicate_opaque_types(&self) -> Vec<(ty::OpaqueTypeKey<'tcx>, Ty<'tcx>)> {
|
||||
self.inner
|
||||
.borrow_mut()
|
||||
.opaque_types()
|
||||
.iter_duplicate_entries()
|
||||
.map(|(k, h)| (k, h.ty))
|
||||
.collect()
|
||||
}
|
||||
fn clone_opaque_types_added_since(
|
||||
&self,
|
||||
prev_entries: OpaqueTypeStorageEntries,
|
||||
) -> Vec<(ty::OpaqueTypeKey<'tcx>, Ty<'tcx>)> {
|
||||
self.inner
|
||||
.borrow_mut()
|
||||
.opaque_types()
|
||||
.opaque_types_added_since(prev_entries)
|
||||
.map(|(k, h)| (k, h.ty))
|
||||
.collect()
|
||||
}
|
||||
|
||||
fn register_hidden_type_in_storage(
|
||||
&self,
|
||||
opaque_type_key: ty::OpaqueTypeKey<'tcx>,
|
||||
hidden_ty: Ty<'tcx>,
|
||||
span: Span,
|
||||
) -> Option<Ty<'tcx>> {
|
||||
self.register_hidden_type_in_storage(
|
||||
opaque_type_key,
|
||||
ty::OpaqueHiddenType { span, ty: hidden_ty },
|
||||
)
|
||||
}
|
||||
fn add_duplicate_opaque_type(
|
||||
&self,
|
||||
opaque_type_key: ty::OpaqueTypeKey<'tcx>,
|
||||
hidden_ty: Ty<'tcx>,
|
||||
span: Span,
|
||||
) {
|
||||
self.inner
|
||||
.borrow_mut()
|
||||
.opaque_types()
|
||||
.add_duplicate(opaque_type_key, ty::OpaqueHiddenType { span, ty: hidden_ty })
|
||||
}
|
||||
|
||||
fn reset_opaque_types(&self) {
|
||||
let _ = self.take_opaque_types();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
pub use freshen::TypeFreshener;
|
||||
use lexical_region_resolve::LexicalRegionResolutions;
|
||||
pub use lexical_region_resolve::RegionResolutionError;
|
||||
use opaque_types::OpaqueTypeStorage;
|
||||
pub use opaque_types::{OpaqueTypeStorage, OpaqueTypeStorageEntries, OpaqueTypeTable};
|
||||
use region_constraints::{
|
||||
GenericKind, RegionConstraintCollector, RegionConstraintStorage, VarInfos, VerifyBound,
|
||||
};
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
|
||||
mod table;
|
||||
|
||||
pub(crate) use table::{OpaqueTypeStorage, OpaqueTypeTable};
|
||||
pub use table::{OpaqueTypeStorage, OpaqueTypeStorageEntries, OpaqueTypeTable};
|
||||
|
||||
impl<'tcx> InferCtxt<'tcx> {
|
||||
/// This is a backwards compatibility hack to prevent breaking changes from
|
||||
|
||||
@@ -14,6 +14,16 @@ pub struct OpaqueTypeStorage<'tcx> {
|
||||
duplicate_entries: Vec<(OpaqueTypeKey<'tcx>, OpaqueHiddenType<'tcx>)>,
|
||||
}
|
||||
|
||||
/// The number of entries in the opaque type storage at a given point.
|
||||
///
|
||||
/// Used to check that we haven't added any new opaque types after checking
|
||||
/// the opaque types currently in the storage.
|
||||
#[derive(Default, Debug, Clone, Copy, PartialEq, Eq)]
|
||||
pub struct OpaqueTypeStorageEntries {
|
||||
opaque_types: usize,
|
||||
duplicate_entries: usize,
|
||||
}
|
||||
|
||||
impl<'tcx> OpaqueTypeStorage<'tcx> {
|
||||
#[instrument(level = "debug")]
|
||||
pub(crate) fn remove(
|
||||
@@ -49,6 +59,24 @@ pub(crate) fn take_opaque_types(
|
||||
std::mem::take(opaque_types).into_iter().chain(std::mem::take(duplicate_entries))
|
||||
}
|
||||
|
||||
pub fn num_entries(&self) -> OpaqueTypeStorageEntries {
|
||||
OpaqueTypeStorageEntries {
|
||||
opaque_types: self.opaque_types.len(),
|
||||
duplicate_entries: self.duplicate_entries.len(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn opaque_types_added_since(
|
||||
&self,
|
||||
prev_entries: OpaqueTypeStorageEntries,
|
||||
) -> impl Iterator<Item = (OpaqueTypeKey<'tcx>, OpaqueHiddenType<'tcx>)> {
|
||||
self.opaque_types
|
||||
.iter()
|
||||
.skip(prev_entries.opaque_types)
|
||||
.map(|(k, v)| (*k, *v))
|
||||
.chain(self.duplicate_entries.iter().skip(prev_entries.duplicate_entries).copied())
|
||||
}
|
||||
|
||||
/// Only returns the opaque types from the lookup table. These are used
|
||||
/// when normalizing opaque types and have a unique key.
|
||||
///
|
||||
|
||||
@@ -24,10 +24,6 @@ impl<'tcx, OP> TypeVisitor<TyCtxt<'tcx>> for FreeRegionsVisitor<'tcx, OP>
|
||||
where
|
||||
OP: FnMut(ty::Region<'tcx>),
|
||||
{
|
||||
fn visit_binder<T: TypeVisitable<TyCtxt<'tcx>>>(&mut self, t: &ty::Binder<'tcx, T>) {
|
||||
t.super_visit_with(self);
|
||||
}
|
||||
|
||||
fn visit_region(&mut self, r: ty::Region<'tcx>) {
|
||||
match r.kind() {
|
||||
// ignore bound regions, keep visiting
|
||||
|
||||
@@ -16,7 +16,6 @@
|
||||
#![allow(internal_features)]
|
||||
#![allow(rustc::diagnostic_outside_of_impl)]
|
||||
#![allow(rustc::untranslatable_diagnostic)]
|
||||
#![cfg_attr(bootstrap, feature(let_chains))]
|
||||
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
|
||||
#![doc(rust_logo)]
|
||||
#![feature(assert_matches)]
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
// tidy-alphabetical-start
|
||||
#![cfg_attr(bootstrap, feature(let_chains))]
|
||||
#![feature(decl_macro)]
|
||||
#![feature(file_buffered)]
|
||||
#![feature(iter_intersperse)]
|
||||
|
||||
@@ -907,7 +907,7 @@ pub fn create_and_enter_global_ctxt<T, F: for<'tcx> FnOnce(TyCtxt<'tcx>) -> T>(
|
||||
feed.output_filenames(Arc::new(outputs));
|
||||
|
||||
let res = f(tcx);
|
||||
// FIXME maybe run finish even when a fatal error occured? or at least tcx.alloc_self_profile_query_strings()?
|
||||
// FIXME maybe run finish even when a fatal error occurred? or at least tcx.alloc_self_profile_query_strings()?
|
||||
tcx.finish();
|
||||
res
|
||||
},
|
||||
|
||||
@@ -720,7 +720,7 @@ macro_rules! untracked {
|
||||
untracked!(pre_link_args, vec![String::from("abc"), String::from("def")]);
|
||||
untracked!(print_codegen_stats, true);
|
||||
untracked!(print_llvm_passes, true);
|
||||
untracked!(print_mono_items, Some(String::from("abc")));
|
||||
untracked!(print_mono_items, true);
|
||||
untracked!(print_type_sizes, true);
|
||||
untracked!(proc_macro_backtrace, true);
|
||||
untracked!(proc_macro_execution_strategy, ProcMacroExecutionStrategy::CrossThread);
|
||||
|
||||
@@ -49,6 +49,8 @@ impl<'tcx> LateLintPass<'tcx> for ForLoopsOverFallibles {
|
||||
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
|
||||
let Some((pat, arg)) = extract_for_loop(expr) else { return };
|
||||
|
||||
let arg_span = arg.span.source_callsite();
|
||||
|
||||
let ty = cx.typeck_results().expr_ty(arg);
|
||||
|
||||
let (adt, args, ref_mutability) = match ty.kind() {
|
||||
@@ -78,27 +80,27 @@ fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
|
||||
&& let Ok(recv_snip) = cx.sess().source_map().span_to_snippet(recv.span)
|
||||
{
|
||||
ForLoopsOverFalliblesLoopSub::RemoveNext {
|
||||
suggestion: recv.span.between(arg.span.shrink_to_hi()),
|
||||
suggestion: recv.span.between(arg_span.shrink_to_hi()),
|
||||
recv_snip,
|
||||
}
|
||||
} else {
|
||||
ForLoopsOverFalliblesLoopSub::UseWhileLet {
|
||||
start_span: expr.span.with_hi(pat.span.lo()),
|
||||
end_span: pat.span.between(arg.span),
|
||||
end_span: pat.span.between(arg_span),
|
||||
var,
|
||||
}
|
||||
};
|
||||
let question_mark = suggest_question_mark(cx, adt, args, expr.span)
|
||||
.then(|| ForLoopsOverFalliblesQuestionMark { suggestion: arg.span.shrink_to_hi() });
|
||||
.then(|| ForLoopsOverFalliblesQuestionMark { suggestion: arg_span.shrink_to_hi() });
|
||||
let suggestion = ForLoopsOverFalliblesSuggestion {
|
||||
var,
|
||||
start_span: expr.span.with_hi(pat.span.lo()),
|
||||
end_span: pat.span.between(arg.span),
|
||||
end_span: pat.span.between(arg_span),
|
||||
};
|
||||
|
||||
cx.emit_span_lint(
|
||||
FOR_LOOPS_OVER_FALLIBLES,
|
||||
arg.span,
|
||||
arg_span,
|
||||
ForLoopsOverFalliblesDiag { article, ref_prefix, ty, sub, question_mark, suggestion },
|
||||
);
|
||||
}
|
||||
|
||||
@@ -15,7 +15,8 @@
|
||||
Relate, RelateResult, TypeRelation, structurally_relate_consts, structurally_relate_tys,
|
||||
};
|
||||
use rustc_middle::ty::{
|
||||
self, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor,
|
||||
self, Ty, TyCtxt, TypeFoldable, TypeSuperVisitable, TypeVisitable, TypeVisitableExt,
|
||||
TypeVisitor,
|
||||
};
|
||||
use rustc_middle::{bug, span_bug};
|
||||
use rustc_session::lint::FutureIncompatibilityReason;
|
||||
@@ -209,7 +210,7 @@ impl<'tcx, VarFn, OutlivesFn> TypeVisitor<TyCtxt<'tcx>>
|
||||
VarFn: FnOnce() -> FxHashMap<DefId, ty::Variance>,
|
||||
OutlivesFn: FnOnce() -> OutlivesEnvironment<'tcx>,
|
||||
{
|
||||
fn visit_binder<T: TypeVisitable<TyCtxt<'tcx>>>(&mut self, t: &ty::Binder<'tcx, T>) {
|
||||
fn visit_binder<T: TypeFoldable<TyCtxt<'tcx>>>(&mut self, t: &ty::Binder<'tcx, T>) {
|
||||
// When we get into a binder, we need to add its own bound vars to the scope.
|
||||
let mut added = vec![];
|
||||
for arg in t.bound_vars() {
|
||||
|
||||
@@ -21,7 +21,6 @@
|
||||
|
||||
// tidy-alphabetical-start
|
||||
#![allow(internal_features)]
|
||||
#![cfg_attr(bootstrap, feature(let_chains))]
|
||||
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
|
||||
#![doc(rust_logo)]
|
||||
#![feature(array_windows)]
|
||||
|
||||
@@ -622,37 +622,10 @@ extern "C" LLVMValueRef LLVMRustBuildAtomicStore(LLVMBuilderRef B,
|
||||
return wrap(SI);
|
||||
}
|
||||
|
||||
enum class LLVMRustAsmDialect {
|
||||
Att,
|
||||
Intel,
|
||||
};
|
||||
|
||||
static InlineAsm::AsmDialect fromRust(LLVMRustAsmDialect Dialect) {
|
||||
switch (Dialect) {
|
||||
case LLVMRustAsmDialect::Att:
|
||||
return InlineAsm::AD_ATT;
|
||||
case LLVMRustAsmDialect::Intel:
|
||||
return InlineAsm::AD_Intel;
|
||||
default:
|
||||
report_fatal_error("bad AsmDialect.");
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" uint64_t LLVMRustGetArrayNumElements(LLVMTypeRef Ty) {
|
||||
return unwrap(Ty)->getArrayNumElements();
|
||||
}
|
||||
|
||||
extern "C" LLVMValueRef
|
||||
LLVMRustInlineAsm(LLVMTypeRef Ty, char *AsmString, size_t AsmStringLen,
|
||||
char *Constraints, size_t ConstraintsLen,
|
||||
LLVMBool HasSideEffects, LLVMBool IsAlignStack,
|
||||
LLVMRustAsmDialect Dialect, LLVMBool CanThrow) {
|
||||
return wrap(InlineAsm::get(
|
||||
unwrap<FunctionType>(Ty), StringRef(AsmString, AsmStringLen),
|
||||
StringRef(Constraints, ConstraintsLen), HasSideEffects, IsAlignStack,
|
||||
fromRust(Dialect), CanThrow));
|
||||
}
|
||||
|
||||
extern "C" bool LLVMRustInlineAsmVerify(LLVMTypeRef Ty, char *Constraints,
|
||||
size_t ConstraintsLen) {
|
||||
// llvm::Error converts to true if it is an error.
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
// tidy-alphabetical-start
|
||||
#![allow(rustc::default_hash_types)]
|
||||
#![cfg_attr(bootstrap, feature(let_chains))]
|
||||
#![feature(if_let_guard)]
|
||||
#![feature(never_type)]
|
||||
#![feature(proc_macro_diagnostic)]
|
||||
|
||||
@@ -299,7 +299,7 @@ fn symbols_with_errors(input: TokenStream) -> (TokenStream, Vec<syn::Error>) {
|
||||
let output = quote! {
|
||||
const SYMBOL_DIGITS_BASE: u32 = #symbol_digits_base;
|
||||
|
||||
/// The number of predefined symbols; this is the the first index for
|
||||
/// The number of predefined symbols; this is the first index for
|
||||
/// extra pre-interned symbols in an Interner created via
|
||||
/// [`Interner::with_extra_symbols`].
|
||||
pub const PREDEFINED_SYMBOLS_COUNT: u32 = #predefined_symbols_count;
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
// tidy-alphabetical-start
|
||||
#![allow(internal_features)]
|
||||
#![cfg_attr(bootstrap, feature(let_chains))]
|
||||
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
|
||||
#![doc(rust_logo)]
|
||||
#![feature(coroutines)]
|
||||
|
||||
@@ -28,7 +28,6 @@
|
||||
#![allow(internal_features)]
|
||||
#![allow(rustc::diagnostic_outside_of_impl)]
|
||||
#![allow(rustc::untranslatable_diagnostic)]
|
||||
#![cfg_attr(bootstrap, feature(let_chains))]
|
||||
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
|
||||
#![doc(rust_logo)]
|
||||
#![feature(allocator_api)]
|
||||
|
||||
@@ -22,7 +22,7 @@ pub fn is_below_threshold(self, threshold: SymbolExportLevel) -> bool {
|
||||
}
|
||||
|
||||
/// Kind of exported symbols.
|
||||
#[derive(Eq, PartialEq, Debug, Copy, Clone, Encodable, Decodable, HashStable)]
|
||||
#[derive(Eq, PartialEq, Debug, Copy, Clone, Encodable, Decodable, HashStable, Hash)]
|
||||
pub enum SymbolExportKind {
|
||||
Text,
|
||||
Data,
|
||||
|
||||
@@ -1924,6 +1924,9 @@ fn async_drop_coroutine_layout(
|
||||
def_id: DefId,
|
||||
args: GenericArgsRef<'tcx>,
|
||||
) -> Option<&'tcx CoroutineLayout<'tcx>> {
|
||||
if args[0].has_placeholders() || args[0].has_non_region_param() {
|
||||
return None;
|
||||
}
|
||||
let instance = InstanceKind::AsyncDropGlue(def_id, Ty::new_coroutine(self, def_id, args));
|
||||
self.mir_shims(instance).coroutine_layout_raw()
|
||||
}
|
||||
|
||||
@@ -2934,7 +2934,7 @@ pub fn pretty_wrap_binder<T, C: FnOnce(&T, &mut Self) -> Result<(), fmt::Error>>
|
||||
|
||||
fn prepare_region_info<T>(&mut self, value: &ty::Binder<'tcx, T>)
|
||||
where
|
||||
T: TypeVisitable<TyCtxt<'tcx>>,
|
||||
T: TypeFoldable<TyCtxt<'tcx>>,
|
||||
{
|
||||
struct RegionNameCollector<'tcx> {
|
||||
used_region_names: FxHashSet<Symbol>,
|
||||
|
||||
@@ -723,7 +723,10 @@ pub fn new_dynamic(
|
||||
repr: DynKind,
|
||||
) -> Ty<'tcx> {
|
||||
if cfg!(debug_assertions) {
|
||||
let projection_count = obj.projection_bounds().count();
|
||||
let projection_count = obj
|
||||
.projection_bounds()
|
||||
.filter(|item| !tcx.generics_require_sized_self(item.item_def_id()))
|
||||
.count();
|
||||
let expected_count: usize = obj
|
||||
.principal_def_id()
|
||||
.into_iter()
|
||||
|
||||
@@ -66,7 +66,7 @@ impl<'tcx, F> TypeVisitor<TyCtxt<'tcx>> for RegionVisitor<F>
|
||||
{
|
||||
type Result = ControlFlow<()>;
|
||||
|
||||
fn visit_binder<T: TypeVisitable<TyCtxt<'tcx>>>(
|
||||
fn visit_binder<T: TypeFoldable<TyCtxt<'tcx>>>(
|
||||
&mut self,
|
||||
t: &Binder<'tcx, T>,
|
||||
) -> Self::Result {
|
||||
@@ -168,7 +168,7 @@ fn new(just_constrained: bool) -> Self {
|
||||
}
|
||||
|
||||
impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for LateBoundRegionsCollector {
|
||||
fn visit_binder<T: TypeVisitable<TyCtxt<'tcx>>>(&mut self, t: &Binder<'tcx, T>) {
|
||||
fn visit_binder<T: TypeFoldable<TyCtxt<'tcx>>>(&mut self, t: &Binder<'tcx, T>) {
|
||||
self.current_index.shift_in(1);
|
||||
t.super_visit_with(self);
|
||||
self.current_index.shift_out(1);
|
||||
|
||||
@@ -1485,7 +1485,7 @@ pub(crate) fn clear_top_scope(&mut self, region_scope: region::Scope) {
|
||||
/// panic occurred (a subset of the drops in `scope`, since we sometimes elide StorageDead and other
|
||||
/// instructions on unwinding)
|
||||
/// * `dropline_to`, describes the drops that would occur at this point in the code if a
|
||||
/// coroutine drop occured.
|
||||
/// coroutine drop occurred.
|
||||
/// * `storage_dead_on_unwind`, if true, then we should emit `StorageDead` even when unwinding
|
||||
/// * `arg_count`, number of MIR local variables corresponding to fn arguments (used to assert that we don't drop those)
|
||||
fn build_scope_drops<'tcx, F>(
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
// tidy-alphabetical-start
|
||||
#![allow(rustc::diagnostic_outside_of_impl)]
|
||||
#![allow(rustc::untranslatable_diagnostic)]
|
||||
#![cfg_attr(bootstrap, feature(let_chains))]
|
||||
#![feature(assert_matches)]
|
||||
#![feature(box_patterns)]
|
||||
#![feature(if_let_guard)]
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
// tidy-alphabetical-start
|
||||
#![cfg_attr(bootstrap, feature(let_chains))]
|
||||
#![feature(assert_matches)]
|
||||
#![feature(associated_type_defaults)]
|
||||
#![feature(box_patterns)]
|
||||
|
||||
@@ -55,18 +55,45 @@ fn is_unnecessary_transmute(
|
||||
},
|
||||
// char → u32
|
||||
(Char, Uint(UintTy::U32)) => err(format!("u32::from({arg})")),
|
||||
// char (→ u32) → i32
|
||||
(Char, Int(IntTy::I32)) => err(format!("u32::from({arg}).cast_signed()")),
|
||||
// u32 → char
|
||||
(Uint(UintTy::U32), Char) => Error {
|
||||
sugg: format!("char::from_u32_unchecked({arg})"),
|
||||
help: Some("consider `char::from_u32(…).unwrap()`"),
|
||||
span,
|
||||
},
|
||||
// i32 → char
|
||||
(Int(IntTy::I32), Char) => Error {
|
||||
sugg: format!("char::from_u32_unchecked(i32::cast_unsigned({arg}))"),
|
||||
help: Some("consider `char::from_u32(i32::cast_unsigned(…)).unwrap()`"),
|
||||
span,
|
||||
},
|
||||
// uNN → iNN
|
||||
(Uint(ty), Int(_)) => err(format!("{}::cast_signed({arg})", ty.name_str())),
|
||||
// iNN → uNN
|
||||
(Int(ty), Uint(_)) => err(format!("{}::cast_unsigned({arg})", ty.name_str())),
|
||||
// fNN → xsize
|
||||
(Float(ty), Uint(UintTy::Usize)) => {
|
||||
err(format!("{}::to_bits({arg}) as usize", ty.name_str()))
|
||||
}
|
||||
(Float(ty), Int(IntTy::Isize)) => {
|
||||
err(format!("{}::to_bits({arg}) as isize", ty.name_str()))
|
||||
}
|
||||
// fNN (→ uNN) → iNN
|
||||
(Float(ty), Int(..)) => err(format!("{}::to_bits({arg}).cast_signed()", ty.name_str())),
|
||||
// fNN → uNN
|
||||
(Float(ty), Uint(..)) => err(format!("{}::to_bits({arg})", ty.name_str())),
|
||||
// xsize → fNN
|
||||
(Uint(UintTy::Usize) | Int(IntTy::Isize), Float(ty)) => {
|
||||
err(format!("{}::from_bits({arg} as _)", ty.name_str(),))
|
||||
}
|
||||
// iNN (→ uNN) → fNN
|
||||
(Int(int_ty), Float(ty)) => err(format!(
|
||||
"{}::from_bits({}::cast_unsigned({arg}))",
|
||||
ty.name_str(),
|
||||
int_ty.name_str()
|
||||
)),
|
||||
// uNN → fNN
|
||||
(Uint(_), Float(ty)) => err(format!("{}::from_bits({arg})", ty.name_str())),
|
||||
// bool → { x8 }
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
// tidy-alphabetical-start
|
||||
#![cfg_attr(bootstrap, feature(let_chains))]
|
||||
#![feature(array_windows)]
|
||||
#![feature(assert_matches)]
|
||||
#![feature(box_patterns)]
|
||||
|
||||
@@ -60,9 +60,6 @@ monomorphize_start_not_found = using `fn main` requires the standard library
|
||||
|
||||
monomorphize_symbol_already_defined = symbol `{$symbol}` is already defined
|
||||
|
||||
monomorphize_unknown_cgu_collection_mode =
|
||||
unknown codegen-item collection mode '{$mode}', falling back to 'lazy' mode
|
||||
|
||||
monomorphize_wasm_c_abi_transition =
|
||||
this function {$is_call ->
|
||||
[true] call
|
||||
|
||||
@@ -64,12 +64,6 @@ pub(crate) struct EncounteredErrorWhileInstantiating {
|
||||
#[help]
|
||||
pub(crate) struct StartNotFound;
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(monomorphize_unknown_cgu_collection_mode)]
|
||||
pub(crate) struct UnknownCguCollectionMode<'a> {
|
||||
pub mode: &'a str,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(monomorphize_abi_error_disabled_vector_type)]
|
||||
#[help]
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
// tidy-alphabetical-start
|
||||
#![cfg_attr(bootstrap, feature(let_chains))]
|
||||
#![feature(array_windows)]
|
||||
#![feature(file_buffered)]
|
||||
#![feature(if_let_guard)]
|
||||
|
||||
@@ -124,7 +124,7 @@
|
||||
use tracing::debug;
|
||||
|
||||
use crate::collector::{self, MonoItemCollectionStrategy, UsageMap};
|
||||
use crate::errors::{CouldntDumpMonoStats, SymbolAlreadyDefined, UnknownCguCollectionMode};
|
||||
use crate::errors::{CouldntDumpMonoStats, SymbolAlreadyDefined};
|
||||
|
||||
struct PartitioningCx<'a, 'tcx> {
|
||||
tcx: TyCtxt<'tcx>,
|
||||
@@ -1127,27 +1127,10 @@ fn assert_symbols_are_distinct<'a, 'tcx, I>(tcx: TyCtxt<'tcx>, mono_items: I)
|
||||
}
|
||||
|
||||
fn collect_and_partition_mono_items(tcx: TyCtxt<'_>, (): ()) -> MonoItemPartitions<'_> {
|
||||
let collection_strategy = match tcx.sess.opts.unstable_opts.print_mono_items {
|
||||
Some(ref s) => {
|
||||
let mode = s.to_lowercase();
|
||||
let mode = mode.trim();
|
||||
if mode == "eager" {
|
||||
MonoItemCollectionStrategy::Eager
|
||||
} else {
|
||||
if mode != "lazy" {
|
||||
tcx.dcx().emit_warn(UnknownCguCollectionMode { mode });
|
||||
}
|
||||
|
||||
MonoItemCollectionStrategy::Lazy
|
||||
}
|
||||
}
|
||||
None => {
|
||||
if tcx.sess.link_dead_code() {
|
||||
MonoItemCollectionStrategy::Eager
|
||||
} else {
|
||||
MonoItemCollectionStrategy::Lazy
|
||||
}
|
||||
}
|
||||
let collection_strategy = if tcx.sess.link_dead_code() {
|
||||
MonoItemCollectionStrategy::Eager
|
||||
} else {
|
||||
MonoItemCollectionStrategy::Lazy
|
||||
};
|
||||
|
||||
let (items, usage_map) = collector::collect_crate_mono_items(tcx, collection_strategy);
|
||||
@@ -1209,7 +1192,7 @@ fn collect_and_partition_mono_items(tcx: TyCtxt<'_>, (): ()) -> MonoItemPartitio
|
||||
}
|
||||
}
|
||||
|
||||
if tcx.sess.opts.unstable_opts.print_mono_items.is_some() {
|
||||
if tcx.sess.opts.unstable_opts.print_mono_items {
|
||||
let mut item_to_cgus: UnordMap<_, Vec<_>> = Default::default();
|
||||
|
||||
for cgu in codegen_units {
|
||||
|
||||
@@ -39,13 +39,6 @@ fn well_formed_goals(
|
||||
term: <Self::Interner as Interner>::Term,
|
||||
) -> Option<Vec<Goal<Self::Interner, <Self::Interner as Interner>::Predicate>>>;
|
||||
|
||||
fn clone_opaque_types_lookup_table(
|
||||
&self,
|
||||
) -> Vec<(ty::OpaqueTypeKey<Self::Interner>, <Self::Interner as Interner>::Ty)>;
|
||||
fn clone_duplicate_opaque_types(
|
||||
&self,
|
||||
) -> Vec<(ty::OpaqueTypeKey<Self::Interner>, <Self::Interner as Interner>::Ty)>;
|
||||
|
||||
fn make_deduplicated_outlives_constraints(
|
||||
&self,
|
||||
) -> Vec<ty::OutlivesPredicate<Self::Interner, <Self::Interner as Interner>::GenericArg>>;
|
||||
@@ -64,20 +57,6 @@ fn instantiate_canonical_var_with_infer(
|
||||
span: <Self::Interner as Interner>::Span,
|
||||
universe_map: impl Fn(ty::UniverseIndex) -> ty::UniverseIndex,
|
||||
) -> <Self::Interner as Interner>::GenericArg;
|
||||
|
||||
fn register_hidden_type_in_storage(
|
||||
&self,
|
||||
opaque_type_key: ty::OpaqueTypeKey<Self::Interner>,
|
||||
hidden_ty: <Self::Interner as Interner>::Ty,
|
||||
span: <Self::Interner as Interner>::Span,
|
||||
) -> Option<<Self::Interner as Interner>::Ty>;
|
||||
fn add_duplicate_opaque_type(
|
||||
&self,
|
||||
opaque_type_key: ty::OpaqueTypeKey<Self::Interner>,
|
||||
hidden_ty: <Self::Interner as Interner>::Ty,
|
||||
span: <Self::Interner as Interner>::Span,
|
||||
);
|
||||
|
||||
fn add_item_bounds_for_hidden_type(
|
||||
&self,
|
||||
def_id: <Self::Interner as Interner>::DefId,
|
||||
@@ -86,7 +65,6 @@ fn add_item_bounds_for_hidden_type(
|
||||
hidden_ty: <Self::Interner as Interner>::Ty,
|
||||
goals: &mut Vec<Goal<Self::Interner, <Self::Interner as Interner>::Predicate>>,
|
||||
);
|
||||
fn reset_opaque_types(&self);
|
||||
|
||||
fn fetch_eligible_assoc_item(
|
||||
&self,
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user