Merge pull request #20268 from lnicola/sync-from-rust
minor: Sync from downstream
This commit is contained in:
commit
8f67bcf4b0
1297 changed files with 18441 additions and 13139 deletions
122
Cargo.lock
122
Cargo.lock
|
|
@ -216,7 +216,7 @@ dependencies = [
|
|||
"memchr",
|
||||
"serde",
|
||||
"serde_derive",
|
||||
"winnow 0.7.11",
|
||||
"winnow 0.7.12",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -470,23 +470,12 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "chrono-tz"
|
||||
version = "0.10.3"
|
||||
version = "0.10.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "efdce149c370f133a071ca8ef6ea340b7b88748ab0810097a9e2976eaa34b4f3"
|
||||
checksum = "a6139a8597ed92cf816dfb33f5dd6cf0bb93a6adc938f11039f371bc5bcd26c3"
|
||||
dependencies = [
|
||||
"chrono",
|
||||
"chrono-tz-build",
|
||||
"phf",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "chrono-tz-build"
|
||||
version = "0.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8f10f8c9340e31fc120ff885fcdb54a0b48e474bbd77cab557f0c30a3e569402"
|
||||
dependencies = [
|
||||
"parse-zoneinfo",
|
||||
"phf_codegen",
|
||||
"phf 0.12.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -501,9 +490,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "clap"
|
||||
version = "4.5.40"
|
||||
version = "4.5.41"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "40b6887a1d8685cebccf115538db5c0efe625ccac9696ad45c409d96566e910f"
|
||||
checksum = "be92d32e80243a54711e5d7ce823c35c41c9d929dc4ab58e1276f625841aadf9"
|
||||
dependencies = [
|
||||
"clap_builder",
|
||||
"clap_derive",
|
||||
|
|
@ -521,9 +510,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "clap_builder"
|
||||
version = "4.5.40"
|
||||
version = "4.5.41"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e0c66c08ce9f0c698cbce5c0279d0bb6ac936d8674174fe48f736533b964f59e"
|
||||
checksum = "707eab41e9622f9139419d573eca0900137718000c517d47da73045f54331c3d"
|
||||
dependencies = [
|
||||
"anstream",
|
||||
"anstyle",
|
||||
|
|
@ -533,9 +522,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "clap_derive"
|
||||
version = "4.5.40"
|
||||
version = "4.5.41"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d2c7947ae4cc3d851207c1adb5b5e260ff0cca11446b1d6d1423788e442257ce"
|
||||
checksum = "ef4f52386a59ca4c860f7393bcf8abd8dfd91ecccc0f774635ff68e92eeef491"
|
||||
dependencies = [
|
||||
"heck 0.5.0",
|
||||
"proc-macro2",
|
||||
|
|
@ -798,9 +787,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "crc32fast"
|
||||
version = "1.4.2"
|
||||
version = "1.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a97769d94ddab943e4510d138150169a2758b5ef3eb191a9ee688de3e23ef7b3"
|
||||
checksum = "9481c1c90cbf2ac953f07c8d4a58aa3945c425b7185c9154d67a65e4230da511"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
]
|
||||
|
|
@ -989,9 +978,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "derive_setters"
|
||||
version = "0.1.7"
|
||||
version = "0.1.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d9c848e86c87e5cc305313041c5677d4d95d60baa71cf95e5f6ea2554bb629ff"
|
||||
checksum = "ae5c625eda104c228c06ecaf988d1c60e542176bd7a490e60eeda3493244c0c9"
|
||||
dependencies = [
|
||||
"darling",
|
||||
"proc-macro2",
|
||||
|
|
@ -2045,9 +2034,9 @@ checksum = "f9fbbcab51052fe104eb5e5d351cf728d30a5be1fe14d9be8a3b097481fb97de"
|
|||
|
||||
[[package]]
|
||||
name = "libredox"
|
||||
version = "0.1.4"
|
||||
version = "0.1.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1580801010e535496706ba011c15f8532df6b42297d2e471fec38ceadd8c0638"
|
||||
checksum = "4488594b9328dee448adb906d8b126d9b7deb7cf5c22161ee591610bb1be83c0"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"libc",
|
||||
|
|
@ -2157,7 +2146,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "c7a7213d12e1864c0f002f52c2923d4556935a43dec5e71355c2760e0f6e7a18"
|
||||
dependencies = [
|
||||
"log",
|
||||
"phf",
|
||||
"phf 0.11.3",
|
||||
"phf_codegen",
|
||||
"string_cache",
|
||||
"string_cache_codegen",
|
||||
|
|
@ -2196,9 +2185,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "measureme"
|
||||
version = "12.0.1"
|
||||
version = "12.0.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "570a507d8948a66a97f42cbbaf8a6bb9516a51017d4ee949502ad7a10a864395"
|
||||
checksum = "6ebd1ebda747ae161a4a377bf93f87e18d46faad2331cc0c7d25b84b1d445f49"
|
||||
dependencies = [
|
||||
"log",
|
||||
"memmap2",
|
||||
|
|
@ -2632,15 +2621,6 @@ dependencies = [
|
|||
"windows-targets 0.52.6",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "parse-zoneinfo"
|
||||
version = "0.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1f2a05b18d44e2957b88f96ba460715e295bc1d7510468a2f3d3b44535d26c24"
|
||||
dependencies = [
|
||||
"regex",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pathdiff"
|
||||
version = "0.2.3"
|
||||
|
|
@ -2712,7 +2692,16 @@ version = "0.11.3"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1fd6780a80ae0c52cc120a26a1a42c1ae51b247a253e4e06113d23d2c2edd078"
|
||||
dependencies = [
|
||||
"phf_shared",
|
||||
"phf_shared 0.11.3",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "phf"
|
||||
version = "0.12.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "913273894cec178f401a31ec4b656318d95473527be05c0752cc41cdc32be8b7"
|
||||
dependencies = [
|
||||
"phf_shared 0.12.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -2722,7 +2711,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "aef8048c789fa5e851558d709946d6d79a8ff88c0440c587967f8e94bfb1216a"
|
||||
dependencies = [
|
||||
"phf_generator",
|
||||
"phf_shared",
|
||||
"phf_shared 0.11.3",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -2731,7 +2720,7 @@ version = "0.11.3"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3c80231409c20246a13fddb31776fb942c38553c51e871f8cbd687a4cfb5843d"
|
||||
dependencies = [
|
||||
"phf_shared",
|
||||
"phf_shared 0.11.3",
|
||||
"rand 0.8.5",
|
||||
]
|
||||
|
||||
|
|
@ -2744,6 +2733,15 @@ dependencies = [
|
|||
"siphasher",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "phf_shared"
|
||||
version = "0.12.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "06005508882fb681fd97892ecff4b7fd0fee13ef1aa569f8695dae7ab9099981"
|
||||
dependencies = [
|
||||
"siphasher",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pin-project-lite"
|
||||
version = "0.2.16"
|
||||
|
|
@ -3136,9 +3134,9 @@ checksum = "357703d41365b4b27c590e3ed91eabb1b663f07c4c084095e60cbed4362dff0d"
|
|||
|
||||
[[package]]
|
||||
name = "rustc-literal-escaper"
|
||||
version = "0.0.4"
|
||||
version = "0.0.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ab03008eb631b703dd16978282ae36c73282e7922fe101a4bd072a40ecea7b8b"
|
||||
checksum = "e4ee29da77c5a54f42697493cd4c9b9f31b74df666a6c04dfc4fde77abe0438b"
|
||||
|
||||
[[package]]
|
||||
name = "rustc-main"
|
||||
|
|
@ -4752,15 +4750,15 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "rustix"
|
||||
version = "1.0.7"
|
||||
version = "1.0.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c71e83d6afe7ff64890ec6b71d6a69bb8a610ab78ce364b3352876bb4c801266"
|
||||
checksum = "11181fbabf243db407ef8df94a6ce0b2f9a733bd8be4ad02b4eda9602296cac8"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"errno",
|
||||
"libc",
|
||||
"linux-raw-sys",
|
||||
"windows-sys 0.59.0",
|
||||
"windows-sys 0.60.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -4860,9 +4858,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "serde_json"
|
||||
version = "1.0.140"
|
||||
version = "1.0.141"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "20068b6e96dc6c9bd23e01df8827e6c7e1f2fddd43c21810382803c136b99373"
|
||||
checksum = "30b9eff21ebe718216c6ec64e1d9ac57087aad11efc64e32002bce4a0d4c03d3"
|
||||
dependencies = [
|
||||
"itoa",
|
||||
"memchr",
|
||||
|
|
@ -5027,7 +5025,7 @@ checksum = "bf776ba3fa74f83bf4b63c3dcbbf82173db2632ed8452cb2d891d33f459de70f"
|
|||
dependencies = [
|
||||
"new_debug_unreachable",
|
||||
"parking_lot",
|
||||
"phf_shared",
|
||||
"phf_shared 0.11.3",
|
||||
"precomputed-hash",
|
||||
"serde",
|
||||
]
|
||||
|
|
@ -5039,7 +5037,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "c711928715f1fe0fe509c53b43e993a9a557babc2d0a3567d0a3006f1ac931a0"
|
||||
dependencies = [
|
||||
"phf_generator",
|
||||
"phf_shared",
|
||||
"phf_shared 0.11.3",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
]
|
||||
|
|
@ -5069,14 +5067,6 @@ dependencies = [
|
|||
"syn 1.0.109",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "suggest-tests"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"build_helper",
|
||||
"glob",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "1.0.109"
|
||||
|
|
@ -5112,9 +5102,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "sysinfo"
|
||||
version = "0.36.0"
|
||||
version = "0.36.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "aab138f5c1bb35231de19049060a87977ad23e04f2303e953bc5c2947ac7dec4"
|
||||
checksum = "252800745060e7b9ffb7b2badbd8b31cfa4aa2e61af879d0a3bf2a317c20217d"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"objc2-core-foundation",
|
||||
|
|
@ -5419,7 +5409,7 @@ dependencies = [
|
|||
"serde_spanned",
|
||||
"toml_datetime",
|
||||
"toml_write",
|
||||
"winnow 0.7.11",
|
||||
"winnow 0.7.12",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -5837,9 +5827,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "wasi-preview1-component-adapter-provider"
|
||||
version = "34.0.1"
|
||||
version = "34.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "aafa1e6af9a954a4bcf6ef420c33355d0ce84ddc6afbcba7bb6f05126f9120ae"
|
||||
checksum = "33696c5f1ff1e083de9f36c3da471abd736362bc173e093f8b0b1ed5a387e39b"
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen"
|
||||
|
|
@ -6483,9 +6473,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "winnow"
|
||||
version = "0.7.11"
|
||||
version = "0.7.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "74c7b26e3480b707944fc872477815d29a8e429d2f93a1ce000f5fa84a15cbcd"
|
||||
checksum = "f3edebf492c8125044983378ecb5766203ad3b4c2f7a922bd7dd207f6d443e95"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
|
|
|
|||
|
|
@ -39,7 +39,6 @@ members = [
|
|||
"src/tools/rustdoc-gui-test",
|
||||
"src/tools/rustdoc-themes",
|
||||
"src/tools/rustfmt",
|
||||
"src/tools/suggest-tests",
|
||||
"src/tools/test-float-parse",
|
||||
"src/tools/tidy",
|
||||
"src/tools/tier-check",
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@ use std::fmt;
|
|||
#[cfg(feature = "nightly")]
|
||||
use std::iter::Step;
|
||||
use std::num::{NonZeroUsize, ParseIntError};
|
||||
use std::ops::{Add, AddAssign, Deref, Mul, RangeInclusive, Sub};
|
||||
use std::ops::{Add, AddAssign, Deref, Mul, RangeFull, RangeInclusive, Sub};
|
||||
use std::str::FromStr;
|
||||
|
||||
use bitflags::bitflags;
|
||||
|
|
@ -1391,12 +1391,45 @@ impl WrappingRange {
|
|||
}
|
||||
|
||||
/// Returns `true` if `size` completely fills the range.
|
||||
///
|
||||
/// Note that this is *not* the same as `self == WrappingRange::full(size)`.
|
||||
/// Niche calculations can produce full ranges which are not the canonical one;
|
||||
/// for example `Option<NonZero<u16>>` gets `valid_range: (..=0) | (1..)`.
|
||||
#[inline]
|
||||
fn is_full_for(&self, size: Size) -> bool {
|
||||
let max_value = size.unsigned_int_max();
|
||||
debug_assert!(self.start <= max_value && self.end <= max_value);
|
||||
self.start == (self.end.wrapping_add(1) & max_value)
|
||||
}
|
||||
|
||||
/// Checks whether this range is considered non-wrapping when the values are
|
||||
/// interpreted as *unsigned* numbers of width `size`.
|
||||
///
|
||||
/// Returns `Ok(true)` if there's no wrap-around, `Ok(false)` if there is,
|
||||
/// and `Err(..)` if the range is full so it depends how you think about it.
|
||||
#[inline]
|
||||
pub fn no_unsigned_wraparound(&self, size: Size) -> Result<bool, RangeFull> {
|
||||
if self.is_full_for(size) { Err(..) } else { Ok(self.start <= self.end) }
|
||||
}
|
||||
|
||||
/// Checks whether this range is considered non-wrapping when the values are
|
||||
/// interpreted as *signed* numbers of width `size`.
|
||||
///
|
||||
/// This is heavily dependent on the `size`, as `100..=200` does wrap when
|
||||
/// interpreted as `i8`, but doesn't when interpreted as `i16`.
|
||||
///
|
||||
/// Returns `Ok(true)` if there's no wrap-around, `Ok(false)` if there is,
|
||||
/// and `Err(..)` if the range is full so it depends how you think about it.
|
||||
#[inline]
|
||||
pub fn no_signed_wraparound(&self, size: Size) -> Result<bool, RangeFull> {
|
||||
if self.is_full_for(size) {
|
||||
Err(..)
|
||||
} else {
|
||||
let start: i128 = size.sign_extend(self.start);
|
||||
let end: i128 = size.sign_extend(self.end);
|
||||
Ok(start <= end)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for WrappingRange {
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ edition = "2024"
|
|||
# tidy-alphabetical-start
|
||||
bitflags = "2.4.1"
|
||||
memchr = "2.7.4"
|
||||
rustc-literal-escaper = "0.0.4"
|
||||
rustc-literal-escaper = "0.0.5"
|
||||
rustc_ast_ir = { path = "../rustc_ast_ir" }
|
||||
rustc_data_structures = { path = "../rustc_data_structures" }
|
||||
rustc_index = { path = "../rustc_index" }
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@
|
|||
//! - [`Attribute`]: Metadata associated with item.
|
||||
//! - [`UnOp`], [`BinOp`], and [`BinOpKind`]: Unary and binary operators.
|
||||
|
||||
use std::borrow::Cow;
|
||||
use std::borrow::{Borrow, Cow};
|
||||
use std::{cmp, fmt};
|
||||
|
||||
pub use GenericArgs::*;
|
||||
|
|
@ -155,6 +155,59 @@ impl Path {
|
|||
}
|
||||
}
|
||||
|
||||
/// Joins multiple symbols with "::" into a path, e.g. "a::b::c". If the first
|
||||
/// segment is `kw::PathRoot` it will be printed as empty, e.g. "::b::c".
|
||||
///
|
||||
/// The generics on the `path` argument mean it can accept many forms, such as:
|
||||
/// - `&[Symbol]`
|
||||
/// - `Vec<Symbol>`
|
||||
/// - `Vec<&Symbol>`
|
||||
/// - `impl Iterator<Item = Symbol>`
|
||||
/// - `impl Iterator<Item = &Symbol>`
|
||||
///
|
||||
/// Panics if `path` is empty or a segment after the first is `kw::PathRoot`.
|
||||
pub fn join_path_syms(path: impl IntoIterator<Item = impl Borrow<Symbol>>) -> String {
|
||||
// This is a guess at the needed capacity that works well in practice. It is slightly faster
|
||||
// than (a) starting with an empty string, or (b) computing the exact capacity required.
|
||||
// `8` works well because it's about the right size and jemalloc's size classes are all
|
||||
// multiples of 8.
|
||||
let mut iter = path.into_iter();
|
||||
let len_hint = iter.size_hint().1.unwrap_or(1);
|
||||
let mut s = String::with_capacity(len_hint * 8);
|
||||
|
||||
let first_sym = *iter.next().unwrap().borrow();
|
||||
if first_sym != kw::PathRoot {
|
||||
s.push_str(first_sym.as_str());
|
||||
}
|
||||
for sym in iter {
|
||||
let sym = *sym.borrow();
|
||||
debug_assert_ne!(sym, kw::PathRoot);
|
||||
s.push_str("::");
|
||||
s.push_str(sym.as_str());
|
||||
}
|
||||
s
|
||||
}
|
||||
|
||||
/// Like `join_path_syms`, but for `Ident`s. This function is necessary because
|
||||
/// `Ident::to_string` does more than just print the symbol in the `name` field.
|
||||
pub fn join_path_idents(path: impl IntoIterator<Item = impl Borrow<Ident>>) -> String {
|
||||
let mut iter = path.into_iter();
|
||||
let len_hint = iter.size_hint().1.unwrap_or(1);
|
||||
let mut s = String::with_capacity(len_hint * 8);
|
||||
|
||||
let first_ident = *iter.next().unwrap().borrow();
|
||||
if first_ident.name != kw::PathRoot {
|
||||
s.push_str(&first_ident.to_string());
|
||||
}
|
||||
for ident in iter {
|
||||
let ident = *ident.borrow();
|
||||
debug_assert_ne!(ident.name, kw::PathRoot);
|
||||
s.push_str("::");
|
||||
s.push_str(&ident.to_string());
|
||||
}
|
||||
s
|
||||
}
|
||||
|
||||
/// A segment of a path: an identifier, an optional lifetime, and a set of types.
|
||||
///
|
||||
/// E.g., `std`, `String` or `Box<T>`.
|
||||
|
|
@ -3637,6 +3690,7 @@ impl Default for FnHeader {
|
|||
|
||||
#[derive(Clone, Encodable, Decodable, Debug)]
|
||||
pub struct Trait {
|
||||
pub constness: Const,
|
||||
pub safety: Safety,
|
||||
pub is_auto: IsAuto,
|
||||
pub ident: Ident,
|
||||
|
|
|
|||
|
|
@ -126,11 +126,11 @@ impl LitKind {
|
|||
token::CStr => {
|
||||
let s = symbol.as_str();
|
||||
let mut buf = Vec::with_capacity(s.len());
|
||||
unescape_c_str(s, |_span, c| match c {
|
||||
unescape_c_str(s, |_span, res| match res {
|
||||
Ok(MixedUnit::Char(c)) => {
|
||||
buf.extend_from_slice(c.encode_utf8(&mut [0; 4]).as_bytes())
|
||||
buf.extend_from_slice(c.get().encode_utf8(&mut [0; 4]).as_bytes())
|
||||
}
|
||||
Ok(MixedUnit::HighByte(b)) => buf.push(b),
|
||||
Ok(MixedUnit::HighByte(b)) => buf.push(b.get()),
|
||||
Err(err) => {
|
||||
assert!(!err.is_fatal(), "failed to unescape C string literal")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -738,7 +738,8 @@ macro_rules! common_visitor_and_walkers {
|
|||
try_visit!(vis.visit_ty(self_ty));
|
||||
visit_assoc_items(vis, items, AssocCtxt::Impl { of_trait: of_trait.is_some() })
|
||||
}
|
||||
ItemKind::Trait(box Trait { safety, is_auto: _, ident, generics, bounds, items }) => {
|
||||
ItemKind::Trait(box Trait { constness, safety, is_auto: _, ident, generics, bounds, items }) => {
|
||||
try_visit!(visit_constness(vis, constness));
|
||||
try_visit!(visit_safety(vis, safety));
|
||||
try_visit!(vis.visit_ident(ident));
|
||||
try_visit!(vis.visit_generics(generics));
|
||||
|
|
|
|||
|
|
@ -127,9 +127,6 @@ ast_lowering_misplaced_impl_trait =
|
|||
`impl Trait` is not allowed in {$position}
|
||||
.note = `impl Trait` is only allowed in arguments and return types of functions and methods
|
||||
|
||||
ast_lowering_misplaced_relax_trait_bound =
|
||||
`?Trait` bounds are only permitted at the point where a type parameter is declared
|
||||
|
||||
ast_lowering_never_pattern_with_body =
|
||||
a never pattern is always unreachable
|
||||
.label = this will never be executed
|
||||
|
|
|
|||
|
|
@ -324,13 +324,6 @@ pub(crate) struct MisplacedDoubleDot {
|
|||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(ast_lowering_misplaced_relax_trait_bound)]
|
||||
pub(crate) struct MisplacedRelaxTraitBound {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(ast_lowering_match_arm_with_no_body)]
|
||||
pub(crate) struct MatchArmWithNoBody {
|
||||
|
|
|
|||
|
|
@ -16,14 +16,11 @@ use smallvec::{SmallVec, smallvec};
|
|||
use thin_vec::ThinVec;
|
||||
use tracing::instrument;
|
||||
|
||||
use super::errors::{
|
||||
InvalidAbi, InvalidAbiSuggestion, MisplacedRelaxTraitBound, TupleStructWithDefault,
|
||||
UnionWithDefault,
|
||||
};
|
||||
use super::errors::{InvalidAbi, InvalidAbiSuggestion, TupleStructWithDefault, UnionWithDefault};
|
||||
use super::stability::{enabled_names, gate_unstable_abi};
|
||||
use super::{
|
||||
AstOwner, FnDeclKind, ImplTraitContext, ImplTraitPosition, LoweringContext, ParamMode,
|
||||
ResolverAstLoweringExt,
|
||||
RelaxedBoundForbiddenReason, RelaxedBoundPolicy, ResolverAstLoweringExt,
|
||||
};
|
||||
|
||||
pub(super) struct ItemLowerer<'a, 'hir> {
|
||||
|
|
@ -417,7 +414,16 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
items: new_impl_items,
|
||||
}))
|
||||
}
|
||||
ItemKind::Trait(box Trait { is_auto, safety, ident, generics, bounds, items }) => {
|
||||
ItemKind::Trait(box Trait {
|
||||
constness,
|
||||
is_auto,
|
||||
safety,
|
||||
ident,
|
||||
generics,
|
||||
bounds,
|
||||
items,
|
||||
}) => {
|
||||
let constness = self.lower_constness(*constness);
|
||||
let ident = self.lower_ident(*ident);
|
||||
let (generics, (safety, items, bounds)) = self.lower_generics(
|
||||
generics,
|
||||
|
|
@ -426,6 +432,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
|this| {
|
||||
let bounds = this.lower_param_bounds(
|
||||
bounds,
|
||||
RelaxedBoundPolicy::Forbidden(RelaxedBoundForbiddenReason::SuperTrait),
|
||||
ImplTraitContext::Disallowed(ImplTraitPosition::Bound),
|
||||
);
|
||||
let items = this.arena.alloc_from_iter(
|
||||
|
|
@ -435,7 +442,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
(safety, items, bounds)
|
||||
},
|
||||
);
|
||||
hir::ItemKind::Trait(*is_auto, safety, ident, generics, bounds, items)
|
||||
hir::ItemKind::Trait(constness, *is_auto, safety, ident, generics, bounds, items)
|
||||
}
|
||||
ItemKind::TraitAlias(ident, generics, bounds) => {
|
||||
let ident = self.lower_ident(*ident);
|
||||
|
|
@ -446,6 +453,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
|this| {
|
||||
this.lower_param_bounds(
|
||||
bounds,
|
||||
RelaxedBoundPolicy::Allowed,
|
||||
ImplTraitContext::Disallowed(ImplTraitPosition::Bound),
|
||||
)
|
||||
},
|
||||
|
|
@ -931,6 +939,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
hir::TraitItemKind::Type(
|
||||
this.lower_param_bounds(
|
||||
bounds,
|
||||
RelaxedBoundPolicy::Allowed,
|
||||
ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
|
||||
),
|
||||
ty,
|
||||
|
|
@ -1668,61 +1677,6 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
assert!(self.impl_trait_defs.is_empty());
|
||||
assert!(self.impl_trait_bounds.is_empty());
|
||||
|
||||
// Error if `?Trait` bounds in where clauses don't refer directly to type parameters.
|
||||
// Note: we used to clone these bounds directly onto the type parameter (and avoid lowering
|
||||
// these into hir when we lower thee where clauses), but this makes it quite difficult to
|
||||
// keep track of the Span info. Now, `<dyn HirTyLowerer>::add_implicit_sized_bound`
|
||||
// checks both param bounds and where clauses for `?Sized`.
|
||||
for pred in &generics.where_clause.predicates {
|
||||
let WherePredicateKind::BoundPredicate(bound_pred) = &pred.kind else {
|
||||
continue;
|
||||
};
|
||||
let compute_is_param = || {
|
||||
// Check if the where clause type is a plain type parameter.
|
||||
match self
|
||||
.resolver
|
||||
.get_partial_res(bound_pred.bounded_ty.id)
|
||||
.and_then(|r| r.full_res())
|
||||
{
|
||||
Some(Res::Def(DefKind::TyParam, def_id))
|
||||
if bound_pred.bound_generic_params.is_empty() =>
|
||||
{
|
||||
generics
|
||||
.params
|
||||
.iter()
|
||||
.any(|p| def_id == self.local_def_id(p.id).to_def_id())
|
||||
}
|
||||
// Either the `bounded_ty` is not a plain type parameter, or
|
||||
// it's not found in the generic type parameters list.
|
||||
_ => false,
|
||||
}
|
||||
};
|
||||
// We only need to compute this once per `WherePredicate`, but don't
|
||||
// need to compute this at all unless there is a Maybe bound.
|
||||
let mut is_param: Option<bool> = None;
|
||||
for bound in &bound_pred.bounds {
|
||||
if !matches!(
|
||||
*bound,
|
||||
GenericBound::Trait(PolyTraitRef {
|
||||
modifiers: TraitBoundModifiers { polarity: BoundPolarity::Maybe(_), .. },
|
||||
..
|
||||
})
|
||||
) {
|
||||
continue;
|
||||
}
|
||||
let is_param = *is_param.get_or_insert_with(compute_is_param);
|
||||
if !is_param && !self.tcx.features().more_maybe_bounds() {
|
||||
self.tcx
|
||||
.sess
|
||||
.create_feature_err(
|
||||
MisplacedRelaxTraitBound { span: bound.span() },
|
||||
sym::more_maybe_bounds,
|
||||
)
|
||||
.emit();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let mut predicates: SmallVec<[hir::WherePredicate<'hir>; 4]> = SmallVec::new();
|
||||
predicates.extend(generics.params.iter().filter_map(|param| {
|
||||
self.lower_generic_bound_predicate(
|
||||
|
|
@ -1732,6 +1686,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
¶m.bounds,
|
||||
param.colon_span,
|
||||
generics.span,
|
||||
RelaxedBoundPolicy::Allowed,
|
||||
itctx,
|
||||
PredicateOrigin::GenericParam,
|
||||
)
|
||||
|
|
@ -1741,7 +1696,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
.where_clause
|
||||
.predicates
|
||||
.iter()
|
||||
.map(|predicate| self.lower_where_predicate(predicate)),
|
||||
.map(|predicate| self.lower_where_predicate(predicate, &generics.params)),
|
||||
);
|
||||
|
||||
let mut params: SmallVec<[hir::GenericParam<'hir>; 4]> = self
|
||||
|
|
@ -1818,6 +1773,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
bounds: &[GenericBound],
|
||||
colon_span: Option<Span>,
|
||||
parent_span: Span,
|
||||
rbp: RelaxedBoundPolicy<'_>,
|
||||
itctx: ImplTraitContext,
|
||||
origin: PredicateOrigin,
|
||||
) -> Option<hir::WherePredicate<'hir>> {
|
||||
|
|
@ -1826,7 +1782,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
return None;
|
||||
}
|
||||
|
||||
let bounds = self.lower_param_bounds(bounds, itctx);
|
||||
let bounds = self.lower_param_bounds(bounds, rbp, itctx);
|
||||
|
||||
let param_span = ident.span;
|
||||
|
||||
|
|
@ -1878,7 +1834,11 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
Some(hir::WherePredicate { hir_id, span, kind })
|
||||
}
|
||||
|
||||
fn lower_where_predicate(&mut self, pred: &WherePredicate) -> hir::WherePredicate<'hir> {
|
||||
fn lower_where_predicate(
|
||||
&mut self,
|
||||
pred: &WherePredicate,
|
||||
params: &[ast::GenericParam],
|
||||
) -> hir::WherePredicate<'hir> {
|
||||
let hir_id = self.lower_node_id(pred.id);
|
||||
let span = self.lower_span(pred.span);
|
||||
self.lower_attrs(hir_id, &pred.attrs, span);
|
||||
|
|
@ -1887,17 +1847,29 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
bound_generic_params,
|
||||
bounded_ty,
|
||||
bounds,
|
||||
}) => hir::WherePredicateKind::BoundPredicate(hir::WhereBoundPredicate {
|
||||
bound_generic_params: self
|
||||
.lower_generic_params(bound_generic_params, hir::GenericParamSource::Binder),
|
||||
bounded_ty: self
|
||||
.lower_ty(bounded_ty, ImplTraitContext::Disallowed(ImplTraitPosition::Bound)),
|
||||
bounds: self.lower_param_bounds(
|
||||
bounds,
|
||||
ImplTraitContext::Disallowed(ImplTraitPosition::Bound),
|
||||
),
|
||||
origin: PredicateOrigin::WhereClause,
|
||||
}),
|
||||
}) => {
|
||||
let rbp = if bound_generic_params.is_empty() {
|
||||
RelaxedBoundPolicy::AllowedIfOnTyParam(bounded_ty.id, params)
|
||||
} else {
|
||||
RelaxedBoundPolicy::Forbidden(RelaxedBoundForbiddenReason::LateBoundVarsInScope)
|
||||
};
|
||||
hir::WherePredicateKind::BoundPredicate(hir::WhereBoundPredicate {
|
||||
bound_generic_params: self.lower_generic_params(
|
||||
bound_generic_params,
|
||||
hir::GenericParamSource::Binder,
|
||||
),
|
||||
bounded_ty: self.lower_ty(
|
||||
bounded_ty,
|
||||
ImplTraitContext::Disallowed(ImplTraitPosition::Bound),
|
||||
),
|
||||
bounds: self.lower_param_bounds(
|
||||
bounds,
|
||||
rbp,
|
||||
ImplTraitContext::Disallowed(ImplTraitPosition::Bound),
|
||||
),
|
||||
origin: PredicateOrigin::WhereClause,
|
||||
})
|
||||
}
|
||||
WherePredicateKind::RegionPredicate(WhereRegionPredicate { lifetime, bounds }) => {
|
||||
hir::WherePredicateKind::RegionPredicate(hir::WhereRegionPredicate {
|
||||
lifetime: self.lower_lifetime(
|
||||
|
|
@ -1907,6 +1879,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
),
|
||||
bounds: self.lower_param_bounds(
|
||||
bounds,
|
||||
RelaxedBoundPolicy::Allowed,
|
||||
ImplTraitContext::Disallowed(ImplTraitPosition::Bound),
|
||||
),
|
||||
in_where_clause: true,
|
||||
|
|
|
|||
|
|
@ -53,8 +53,8 @@ use rustc_hir::def::{DefKind, LifetimeRes, Namespace, PartialRes, PerNS, Res};
|
|||
use rustc_hir::def_id::{CRATE_DEF_ID, LOCAL_CRATE, LocalDefId};
|
||||
use rustc_hir::lints::DelayedLint;
|
||||
use rustc_hir::{
|
||||
self as hir, AngleBrackets, ConstArg, GenericArg, HirId, ItemLocalMap, LangItem,
|
||||
LifetimeSource, LifetimeSyntax, ParamName, TraitCandidate,
|
||||
self as hir, AngleBrackets, ConstArg, GenericArg, HirId, ItemLocalMap, LifetimeSource,
|
||||
LifetimeSyntax, ParamName, TraitCandidate,
|
||||
};
|
||||
use rustc_index::{Idx, IndexSlice, IndexVec};
|
||||
use rustc_macros::extension;
|
||||
|
|
@ -281,6 +281,24 @@ impl ResolverAstLowering {
|
|||
}
|
||||
}
|
||||
|
||||
/// How relaxed bounds `?Trait` should be treated.
|
||||
///
|
||||
/// Relaxed bounds should only be allowed in places where we later
|
||||
/// (namely during HIR ty lowering) perform *sized elaboration*.
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
enum RelaxedBoundPolicy<'a> {
|
||||
Allowed,
|
||||
AllowedIfOnTyParam(NodeId, &'a [ast::GenericParam]),
|
||||
Forbidden(RelaxedBoundForbiddenReason),
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
enum RelaxedBoundForbiddenReason {
|
||||
TraitObjectTy,
|
||||
SuperTrait,
|
||||
LateBoundVarsInScope,
|
||||
}
|
||||
|
||||
/// Context of `impl Trait` in code, which determines whether it is allowed in an HIR subtree,
|
||||
/// and if so, what meaning it has.
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||
|
|
@ -1084,10 +1102,9 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
&*self.arena.alloc(self.ty(constraint.span, hir::TyKind::Err(guar)));
|
||||
hir::AssocItemConstraintKind::Equality { term: err_ty.into() }
|
||||
} else {
|
||||
// Desugar `AssocTy: Bounds` into an assoc type binding where the
|
||||
// later desugars into a trait predicate.
|
||||
let bounds = self.lower_param_bounds(bounds, itctx);
|
||||
|
||||
// FIXME(#135229): These should be forbidden!
|
||||
let bounds =
|
||||
self.lower_param_bounds(bounds, RelaxedBoundPolicy::Allowed, itctx);
|
||||
hir::AssocItemConstraintKind::Bound { bounds }
|
||||
}
|
||||
}
|
||||
|
|
@ -1216,6 +1233,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
span: t.span,
|
||||
parens: ast::Parens::No,
|
||||
},
|
||||
RelaxedBoundPolicy::Forbidden(RelaxedBoundForbiddenReason::TraitObjectTy),
|
||||
itctx,
|
||||
);
|
||||
let bounds = this.arena.alloc_from_iter([bound]);
|
||||
|
|
@ -1271,7 +1289,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
parenthesized: hir::GenericArgsParentheses::No,
|
||||
span_ext: span,
|
||||
});
|
||||
let path = self.make_lang_item_qpath(LangItem::Pin, span, Some(args));
|
||||
let path = self.make_lang_item_qpath(hir::LangItem::Pin, span, Some(args));
|
||||
hir::TyKind::Path(path)
|
||||
}
|
||||
TyKind::FnPtr(f) => {
|
||||
|
|
@ -1332,7 +1350,13 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
// takes care of rejecting invalid modifier combinations and
|
||||
// const trait bounds in trait object types.
|
||||
GenericBound::Trait(ty) => {
|
||||
let trait_ref = this.lower_poly_trait_ref(ty, itctx);
|
||||
let trait_ref = this.lower_poly_trait_ref(
|
||||
ty,
|
||||
RelaxedBoundPolicy::Forbidden(
|
||||
RelaxedBoundForbiddenReason::TraitObjectTy,
|
||||
),
|
||||
itctx,
|
||||
);
|
||||
Some(trait_ref)
|
||||
}
|
||||
GenericBound::Outlives(lifetime) => {
|
||||
|
|
@ -1387,9 +1411,9 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
}
|
||||
path
|
||||
}
|
||||
ImplTraitContext::InBinding => {
|
||||
hir::TyKind::TraitAscription(self.lower_param_bounds(bounds, itctx))
|
||||
}
|
||||
ImplTraitContext::InBinding => hir::TyKind::TraitAscription(
|
||||
self.lower_param_bounds(bounds, RelaxedBoundPolicy::Allowed, itctx),
|
||||
),
|
||||
ImplTraitContext::FeatureGated(position, feature) => {
|
||||
let guar = self
|
||||
.tcx
|
||||
|
|
@ -1505,7 +1529,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
let opaque_ty_span = self.mark_span_with_reason(DesugaringKind::OpaqueTy, span, None);
|
||||
|
||||
self.lower_opaque_inner(opaque_ty_node_id, origin, opaque_ty_span, |this| {
|
||||
this.lower_param_bounds(bounds, itctx)
|
||||
this.lower_param_bounds(bounds, RelaxedBoundPolicy::Allowed, itctx)
|
||||
})
|
||||
}
|
||||
|
||||
|
|
@ -1799,10 +1823,13 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
fn lower_param_bound(
|
||||
&mut self,
|
||||
tpb: &GenericBound,
|
||||
rbp: RelaxedBoundPolicy<'_>,
|
||||
itctx: ImplTraitContext,
|
||||
) -> hir::GenericBound<'hir> {
|
||||
match tpb {
|
||||
GenericBound::Trait(p) => hir::GenericBound::Trait(self.lower_poly_trait_ref(p, itctx)),
|
||||
GenericBound::Trait(p) => {
|
||||
hir::GenericBound::Trait(self.lower_poly_trait_ref(p, rbp, itctx))
|
||||
}
|
||||
GenericBound::Outlives(lifetime) => hir::GenericBound::Outlives(self.lower_lifetime(
|
||||
lifetime,
|
||||
LifetimeSource::OutlivesBound,
|
||||
|
|
@ -2017,21 +2044,93 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
#[instrument(level = "debug", skip(self))]
|
||||
fn lower_poly_trait_ref(
|
||||
&mut self,
|
||||
p: &PolyTraitRef,
|
||||
PolyTraitRef { bound_generic_params, modifiers, trait_ref, span, parens: _ }: &PolyTraitRef,
|
||||
rbp: RelaxedBoundPolicy<'_>,
|
||||
itctx: ImplTraitContext,
|
||||
) -> hir::PolyTraitRef<'hir> {
|
||||
let bound_generic_params =
|
||||
self.lower_lifetime_binder(p.trait_ref.ref_id, &p.bound_generic_params);
|
||||
let trait_ref = self.lower_trait_ref(p.modifiers, &p.trait_ref, itctx);
|
||||
let modifiers = self.lower_trait_bound_modifiers(p.modifiers);
|
||||
self.lower_lifetime_binder(trait_ref.ref_id, bound_generic_params);
|
||||
let trait_ref = self.lower_trait_ref(*modifiers, trait_ref, itctx);
|
||||
let modifiers = self.lower_trait_bound_modifiers(*modifiers);
|
||||
|
||||
if let ast::BoundPolarity::Maybe(_) = modifiers.polarity {
|
||||
self.validate_relaxed_bound(trait_ref, *span, rbp);
|
||||
}
|
||||
|
||||
hir::PolyTraitRef {
|
||||
bound_generic_params,
|
||||
modifiers,
|
||||
trait_ref,
|
||||
span: self.lower_span(p.span),
|
||||
span: self.lower_span(*span),
|
||||
}
|
||||
}
|
||||
|
||||
fn validate_relaxed_bound(
|
||||
&self,
|
||||
trait_ref: hir::TraitRef<'_>,
|
||||
span: Span,
|
||||
rbp: RelaxedBoundPolicy<'_>,
|
||||
) {
|
||||
// Even though feature `more_maybe_bounds` bypasses the given policy and (currently) enables
|
||||
// relaxed bounds in every conceivable position[^1], we don't want to advertise it to the user
|
||||
// (via a feature gate) since it's super internal. Besides this, it'd be quite distracting.
|
||||
//
|
||||
// [^1]: Strictly speaking, this is incorrect (at the very least for `Sized`) because it's
|
||||
// no longer fully consistent with default trait elaboration in HIR ty lowering.
|
||||
|
||||
match rbp {
|
||||
RelaxedBoundPolicy::Allowed => return,
|
||||
RelaxedBoundPolicy::AllowedIfOnTyParam(id, params) => {
|
||||
if let Some(res) = self.resolver.get_partial_res(id).and_then(|r| r.full_res())
|
||||
&& let Res::Def(DefKind::TyParam, def_id) = res
|
||||
&& params.iter().any(|p| def_id == self.local_def_id(p.id).to_def_id())
|
||||
{
|
||||
return;
|
||||
}
|
||||
if self.tcx.features().more_maybe_bounds() {
|
||||
return;
|
||||
}
|
||||
}
|
||||
RelaxedBoundPolicy::Forbidden(reason) => {
|
||||
if self.tcx.features().more_maybe_bounds() {
|
||||
return;
|
||||
}
|
||||
|
||||
match reason {
|
||||
RelaxedBoundForbiddenReason::TraitObjectTy => {
|
||||
self.dcx().span_err(
|
||||
span,
|
||||
"relaxed bounds are not permitted in trait object types",
|
||||
);
|
||||
return;
|
||||
}
|
||||
RelaxedBoundForbiddenReason::SuperTrait => {
|
||||
let mut diag = self.dcx().struct_span_err(
|
||||
span,
|
||||
"relaxed bounds are not permitted in supertrait bounds",
|
||||
);
|
||||
if let Some(def_id) = trait_ref.trait_def_id()
|
||||
&& self.tcx.is_lang_item(def_id, hir::LangItem::Sized)
|
||||
{
|
||||
diag.note("traits are `?Sized` by default");
|
||||
}
|
||||
diag.emit();
|
||||
return;
|
||||
}
|
||||
RelaxedBoundForbiddenReason::LateBoundVarsInScope => {}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
self.dcx()
|
||||
.struct_span_err(span, "this relaxed bound is not permitted here")
|
||||
.with_note(
|
||||
"in this context, relaxed bounds are only allowed on \
|
||||
type parameters defined by the closest item",
|
||||
)
|
||||
.emit();
|
||||
}
|
||||
|
||||
fn lower_mt(&mut self, mt: &MutTy, itctx: ImplTraitContext) -> hir::MutTy<'hir> {
|
||||
hir::MutTy { ty: self.lower_ty(&mt.ty, itctx), mutbl: mt.mutbl }
|
||||
}
|
||||
|
|
@ -2040,17 +2139,19 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
fn lower_param_bounds(
|
||||
&mut self,
|
||||
bounds: &[GenericBound],
|
||||
rbp: RelaxedBoundPolicy<'_>,
|
||||
itctx: ImplTraitContext,
|
||||
) -> hir::GenericBounds<'hir> {
|
||||
self.arena.alloc_from_iter(self.lower_param_bounds_mut(bounds, itctx))
|
||||
self.arena.alloc_from_iter(self.lower_param_bounds_mut(bounds, rbp, itctx))
|
||||
}
|
||||
|
||||
fn lower_param_bounds_mut(
|
||||
&mut self,
|
||||
bounds: &[GenericBound],
|
||||
rbp: RelaxedBoundPolicy<'_>,
|
||||
itctx: ImplTraitContext,
|
||||
) -> impl Iterator<Item = hir::GenericBound<'hir>> {
|
||||
bounds.iter().map(move |bound| self.lower_param_bound(bound, itctx))
|
||||
bounds.iter().map(move |bound| self.lower_param_bound(bound, rbp, itctx))
|
||||
}
|
||||
|
||||
#[instrument(level = "debug", skip(self), ret)]
|
||||
|
|
@ -2084,6 +2185,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
bounds,
|
||||
/* colon_span */ None,
|
||||
span,
|
||||
RelaxedBoundPolicy::Allowed,
|
||||
ImplTraitContext::Universal,
|
||||
hir::PredicateOrigin::ImplTrait,
|
||||
);
|
||||
|
|
|
|||
|
|
@ -212,11 +212,6 @@ ast_passes_nomangle_ascii = `#[no_mangle]` requires ASCII identifier
|
|||
ast_passes_obsolete_auto = `impl Trait for .. {"{}"}` is an obsolete syntax
|
||||
.help = use `auto trait Trait {"{}"}` instead
|
||||
|
||||
ast_passes_optional_trait_object = `?Trait` is not permitted in trait object types
|
||||
|
||||
ast_passes_optional_trait_supertrait = `?Trait` is not permitted in supertraits
|
||||
.note = traits are `?{$path_str}` by default
|
||||
|
||||
ast_passes_out_of_order_params = {$param_ord} parameters must be declared prior to {$max_param} parameters
|
||||
.suggestion = reorder the parameters: lifetimes, then consts and types
|
||||
|
||||
|
|
@ -240,10 +235,10 @@ ast_passes_static_without_body =
|
|||
ast_passes_tilde_const_disallowed = `[const]` is not allowed here
|
||||
.closure = closures cannot have `[const]` trait bounds
|
||||
.function = this function is not `const`, so it cannot have `[const]` trait bounds
|
||||
.trait = this trait is not a `#[const_trait]`, so it cannot have `[const]` trait bounds
|
||||
.trait = this trait is not `const`, so it cannot have `[const]` trait bounds
|
||||
.trait_impl = this impl is not `const`, so it cannot have `[const]` trait bounds
|
||||
.impl = inherent impls cannot have `[const]` trait bounds
|
||||
.trait_assoc_ty = associated types in non-`#[const_trait]` traits cannot have `[const]` trait bounds
|
||||
.trait_assoc_ty = associated types in non-`const` traits cannot have `[const]` trait bounds
|
||||
.trait_impl_assoc_ty = associated types in non-const impls cannot have `[const]` trait bounds
|
||||
.inherent_assoc_ty = inherent associated types cannot have `[const]` trait bounds
|
||||
.object = trait objects cannot have `[const]` trait bounds
|
||||
|
|
|
|||
|
|
@ -49,14 +49,14 @@ enum SelfSemantic {
|
|||
}
|
||||
|
||||
enum TraitOrTraitImpl {
|
||||
Trait { span: Span, constness_span: Option<Span> },
|
||||
Trait { span: Span, constness: Const },
|
||||
TraitImpl { constness: Const, polarity: ImplPolarity, trait_ref_span: Span },
|
||||
}
|
||||
|
||||
impl TraitOrTraitImpl {
|
||||
fn constness(&self) -> Option<Span> {
|
||||
match self {
|
||||
Self::Trait { constness_span: Some(span), .. }
|
||||
Self::Trait { constness: Const::Yes(span), .. }
|
||||
| Self::TraitImpl { constness: Const::Yes(span), .. } => Some(*span),
|
||||
_ => None,
|
||||
}
|
||||
|
|
@ -110,15 +110,10 @@ impl<'a> AstValidator<'a> {
|
|||
self.outer_trait_or_trait_impl = old;
|
||||
}
|
||||
|
||||
fn with_in_trait(
|
||||
&mut self,
|
||||
span: Span,
|
||||
constness_span: Option<Span>,
|
||||
f: impl FnOnce(&mut Self),
|
||||
) {
|
||||
fn with_in_trait(&mut self, span: Span, constness: Const, f: impl FnOnce(&mut Self)) {
|
||||
let old = mem::replace(
|
||||
&mut self.outer_trait_or_trait_impl,
|
||||
Some(TraitOrTraitImpl::Trait { span, constness_span }),
|
||||
Some(TraitOrTraitImpl::Trait { span, constness }),
|
||||
);
|
||||
f(self);
|
||||
self.outer_trait_or_trait_impl = old;
|
||||
|
|
@ -273,7 +268,7 @@ impl<'a> AstValidator<'a> {
|
|||
};
|
||||
|
||||
let make_trait_const_sugg = if const_trait_impl
|
||||
&& let TraitOrTraitImpl::Trait { span, constness_span: None } = parent
|
||||
&& let TraitOrTraitImpl::Trait { span, constness: ast::Const::No } = parent
|
||||
{
|
||||
Some(span.shrink_to_lo())
|
||||
} else {
|
||||
|
|
@ -1131,10 +1126,23 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
|
|||
}
|
||||
visit::walk_item(self, item)
|
||||
}
|
||||
ItemKind::Trait(box Trait { is_auto, generics, ident, bounds, items, .. }) => {
|
||||
ItemKind::Trait(box Trait {
|
||||
constness,
|
||||
is_auto,
|
||||
generics,
|
||||
ident,
|
||||
bounds,
|
||||
items,
|
||||
..
|
||||
}) => {
|
||||
self.visit_attrs_vis_ident(&item.attrs, &item.vis, ident);
|
||||
let is_const_trait =
|
||||
// FIXME(const_trait_impl) remove this
|
||||
let alt_const_trait_span =
|
||||
attr::find_by_name(&item.attrs, sym::const_trait).map(|attr| attr.span);
|
||||
let constness = match (*constness, alt_const_trait_span) {
|
||||
(Const::Yes(span), _) | (Const::No, Some(span)) => Const::Yes(span),
|
||||
(Const::No, None) => Const::No,
|
||||
};
|
||||
if *is_auto == IsAuto::Yes {
|
||||
// Auto traits cannot have generics, super traits nor contain items.
|
||||
self.deny_generic_params(generics, ident.span);
|
||||
|
|
@ -1145,13 +1153,13 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
|
|||
|
||||
// Equivalent of `visit::walk_item` for `ItemKind::Trait` that inserts a bound
|
||||
// context for the supertraits.
|
||||
let disallowed =
|
||||
is_const_trait.is_none().then(|| TildeConstReason::Trait { span: item.span });
|
||||
let disallowed = matches!(constness, ast::Const::No)
|
||||
.then(|| TildeConstReason::Trait { span: item.span });
|
||||
self.with_tilde_const(disallowed, |this| {
|
||||
this.visit_generics(generics);
|
||||
walk_list!(this, visit_param_bound, bounds, BoundKind::SuperTraits)
|
||||
});
|
||||
self.with_in_trait(item.span, is_const_trait, |this| {
|
||||
self.with_in_trait(item.span, constness, |this| {
|
||||
walk_list!(this, visit_assoc_item, items, AssocCtxt::Trait);
|
||||
});
|
||||
}
|
||||
|
|
@ -1373,29 +1381,6 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
|
|||
match bound {
|
||||
GenericBound::Trait(trait_ref) => {
|
||||
match (ctxt, trait_ref.modifiers.constness, trait_ref.modifiers.polarity) {
|
||||
(BoundKind::SuperTraits, BoundConstness::Never, BoundPolarity::Maybe(_))
|
||||
if !self.features.more_maybe_bounds() =>
|
||||
{
|
||||
self.sess
|
||||
.create_feature_err(
|
||||
errors::OptionalTraitSupertrait {
|
||||
span: trait_ref.span,
|
||||
path_str: pprust::path_to_string(&trait_ref.trait_ref.path),
|
||||
},
|
||||
sym::more_maybe_bounds,
|
||||
)
|
||||
.emit();
|
||||
}
|
||||
(BoundKind::TraitObject, BoundConstness::Never, BoundPolarity::Maybe(_))
|
||||
if !self.features.more_maybe_bounds() =>
|
||||
{
|
||||
self.sess
|
||||
.create_feature_err(
|
||||
errors::OptionalTraitObject { span: trait_ref.span },
|
||||
sym::more_maybe_bounds,
|
||||
)
|
||||
.emit();
|
||||
}
|
||||
(
|
||||
BoundKind::TraitObject,
|
||||
BoundConstness::Always(_),
|
||||
|
|
|
|||
|
|
@ -566,22 +566,6 @@ pub(crate) struct NestedLifetimes {
|
|||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(ast_passes_optional_trait_supertrait)]
|
||||
#[note]
|
||||
pub(crate) struct OptionalTraitSupertrait {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
pub path_str: String,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(ast_passes_optional_trait_object)]
|
||||
pub(crate) struct OptionalTraitObject {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(ast_passes_const_bound_trait_object)]
|
||||
pub(crate) struct ConstBoundTraitObject {
|
||||
|
|
@ -590,7 +574,7 @@ pub(crate) struct ConstBoundTraitObject {
|
|||
}
|
||||
|
||||
// FIXME(const_trait_impl): Consider making the note/reason the message of the diagnostic.
|
||||
// FIXME(const_trait_impl): Provide structured suggestions (e.g., add `const` / `#[const_trait]` here).
|
||||
// FIXME(const_trait_impl): Provide structured suggestions (e.g., add `const` here).
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(ast_passes_tilde_const_disallowed)]
|
||||
pub(crate) struct TildeConstDisallowed {
|
||||
|
|
|
|||
|
|
@ -357,6 +357,7 @@ impl<'a> State<'a> {
|
|||
self.bclose(item.span, empty, cb);
|
||||
}
|
||||
ast::ItemKind::Trait(box ast::Trait {
|
||||
constness,
|
||||
safety,
|
||||
is_auto,
|
||||
ident,
|
||||
|
|
@ -366,6 +367,7 @@ impl<'a> State<'a> {
|
|||
}) => {
|
||||
let (cb, ib) = self.head("");
|
||||
self.print_visibility(&item.vis);
|
||||
self.print_constness(*constness);
|
||||
self.print_safety(*safety);
|
||||
self.print_is_auto(*is_auto);
|
||||
self.word_nbsp("trait");
|
||||
|
|
|
|||
|
|
@ -110,6 +110,22 @@ pub enum DeprecatedSince {
|
|||
Err,
|
||||
}
|
||||
|
||||
#[derive(
|
||||
Copy,
|
||||
Debug,
|
||||
Eq,
|
||||
PartialEq,
|
||||
Encodable,
|
||||
Decodable,
|
||||
Clone,
|
||||
HashStable_Generic,
|
||||
PrintAttribute
|
||||
)]
|
||||
pub enum CoverageStatus {
|
||||
On,
|
||||
Off,
|
||||
}
|
||||
|
||||
impl Deprecation {
|
||||
/// Whether an item marked with #[deprecated(since = "X")] is currently
|
||||
/// deprecated (i.e., whether X is not greater than the current rustc
|
||||
|
|
@ -274,6 +290,9 @@ pub enum AttributeKind {
|
|||
/// Represents `#[const_trait]`.
|
||||
ConstTrait(Span),
|
||||
|
||||
/// Represents `#[coverage]`.
|
||||
Coverage(Span, CoverageStatus),
|
||||
|
||||
///Represents `#[rustc_deny_explicit_impl]`.
|
||||
DenyExplicitImpl(Span),
|
||||
|
||||
|
|
@ -374,6 +393,9 @@ pub enum AttributeKind {
|
|||
/// Represents `#[path]`
|
||||
Path(Symbol, Span),
|
||||
|
||||
/// Represents `#[pointee]`
|
||||
Pointee(Span),
|
||||
|
||||
/// Represents `#[rustc_pub_transparent]` (used by the `repr_transparent_external_private_fields` lint).
|
||||
PubTransparent(Span),
|
||||
|
||||
|
|
@ -417,6 +439,9 @@ pub enum AttributeKind {
|
|||
/// Represents `#[rustc_unsafe_specialization_marker]`.
|
||||
UnsafeSpecializationMarker(Span),
|
||||
|
||||
/// Represents `#[unstable_feature_bound]`.
|
||||
UnstableFeatureBound(ThinVec<(Symbol, Span)>),
|
||||
|
||||
/// Represents `#[used]`
|
||||
Used { used_by: UsedBy, span: Span },
|
||||
// tidy-alphabetical-end
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@ impl AttributeKind {
|
|||
ConstStability { .. } => Yes,
|
||||
ConstStabilityIndirect => No,
|
||||
ConstTrait(..) => No,
|
||||
Coverage(..) => No,
|
||||
DenyExplicitImpl(..) => No,
|
||||
Deprecation { .. } => Yes,
|
||||
DoNotImplementViaObject(..) => No,
|
||||
|
|
@ -40,9 +41,9 @@ impl AttributeKind {
|
|||
Fundamental { .. } => Yes,
|
||||
Ignore { .. } => No,
|
||||
Inline(..) => No,
|
||||
LinkName { .. } => Yes,
|
||||
LinkName { .. } => Yes, // Needed for rustdoc
|
||||
LinkOrdinal { .. } => No,
|
||||
LinkSection { .. } => No,
|
||||
LinkSection { .. } => Yes, // Needed for rustdoc
|
||||
LoopMatch(..) => No,
|
||||
MacroTransparency(..) => Yes,
|
||||
Marker(..) => No,
|
||||
|
|
@ -50,13 +51,14 @@ impl AttributeKind {
|
|||
MustUse { .. } => Yes,
|
||||
Naked(..) => No,
|
||||
NoImplicitPrelude(..) => No,
|
||||
NoMangle(..) => No,
|
||||
NonExhaustive(..) => Yes,
|
||||
NoMangle(..) => Yes, // Needed for rustdoc
|
||||
NonExhaustive(..) => Yes, // Needed for rustdoc
|
||||
OmitGdbPrettyPrinterSection => No,
|
||||
Optimize(..) => No,
|
||||
ParenSugar(..) => No,
|
||||
PassByValue(..) => Yes,
|
||||
Path(..) => No,
|
||||
Pointee(..) => No,
|
||||
PubTransparent(..) => Yes,
|
||||
Repr { .. } => No,
|
||||
RustcLayoutScalarValidRangeEnd(..) => Yes,
|
||||
|
|
@ -70,6 +72,7 @@ impl AttributeKind {
|
|||
TrackCaller(..) => Yes,
|
||||
TypeConst(..) => Yes,
|
||||
UnsafeSpecializationMarker(..) => No,
|
||||
UnstableFeatureBound(..) => No,
|
||||
Used { .. } => No,
|
||||
// tidy-alphabetical-end
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ use rustc_ast::token::CommentKind;
|
|||
use rustc_ast::{AttrStyle, IntTy, UintTy};
|
||||
use rustc_ast_pretty::pp::Printer;
|
||||
use rustc_span::hygiene::Transparency;
|
||||
use rustc_span::{Span, Symbol};
|
||||
use rustc_span::{ErrorGuaranteed, Span, Symbol};
|
||||
pub use stability::*;
|
||||
use thin_vec::ThinVec;
|
||||
pub use version::*;
|
||||
|
|
@ -170,7 +170,7 @@ macro_rules! print_tup {
|
|||
}
|
||||
|
||||
print_tup!(A B C D E F G H);
|
||||
print_skip!(Span, ());
|
||||
print_skip!(Span, (), ErrorGuaranteed);
|
||||
print_disp!(u16, bool, NonZero<u32>);
|
||||
print_debug!(Symbol, UintTy, IntTy, Align, AttrStyle, CommentKind, Transparency);
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
use std::num::NonZero;
|
||||
|
||||
use rustc_macros::{Decodable, Encodable, HashStable_Generic, PrintAttribute};
|
||||
use rustc_span::{Symbol, sym};
|
||||
use rustc_span::{ErrorGuaranteed, Symbol, sym};
|
||||
|
||||
use crate::{PrintAttribute, RustcVersion};
|
||||
|
||||
|
|
@ -153,7 +153,7 @@ pub enum StableSince {
|
|||
/// Stabilized in the upcoming version, whatever number that is.
|
||||
Current,
|
||||
/// Failed to parse a stabilization version.
|
||||
Err,
|
||||
Err(ErrorGuaranteed),
|
||||
}
|
||||
|
||||
impl StabilityLevel {
|
||||
|
|
|
|||
|
|
@ -136,6 +136,9 @@ attr_parsing_unrecognized_repr_hint =
|
|||
attr_parsing_unstable_cfg_target_compact =
|
||||
compact `cfg(target(..))` is experimental and subject to change
|
||||
|
||||
attr_parsing_unstable_feature_bound_incompatible_stability = Item annotated with `#[unstable_feature_bound]` should not be stable
|
||||
.help = If this item is meant to be stable, do not use any functions annotated with `#[unstable_feature_bound]`. Otherwise, mark this item as unstable with `#[unstable]`
|
||||
|
||||
attr_parsing_unsupported_literal_cfg_boolean =
|
||||
literal in `cfg` predicate value must be a boolean
|
||||
attr_parsing_unsupported_literal_cfg_string =
|
||||
|
|
|
|||
|
|
@ -27,6 +27,26 @@ impl<S: Stage> CombineAttributeParser<S> for AllowInternalUnstableParser {
|
|||
}
|
||||
}
|
||||
|
||||
pub(crate) struct UnstableFeatureBoundParser;
|
||||
impl<S: Stage> CombineAttributeParser<S> for UnstableFeatureBoundParser {
|
||||
const PATH: &'static [rustc_span::Symbol] = &[sym::unstable_feature_bound];
|
||||
type Item = (Symbol, Span);
|
||||
const CONVERT: ConvertFn<Self::Item> = |items, _| AttributeKind::UnstableFeatureBound(items);
|
||||
const TEMPLATE: AttributeTemplate = template!(Word, List: "feat1, feat2, ...");
|
||||
|
||||
fn extend<'c>(
|
||||
cx: &'c mut AcceptContext<'_, '_, S>,
|
||||
args: &'c ArgParser<'_>,
|
||||
) -> impl IntoIterator<Item = Self::Item> {
|
||||
if !cx.features().staged_api() {
|
||||
cx.emit_err(session_diagnostics::StabilityOutsideStd { span: cx.attr_span });
|
||||
}
|
||||
parse_unstable(cx, args, <Self as CombineAttributeParser<S>>::PATH[0])
|
||||
.into_iter()
|
||||
.zip(iter::repeat(cx.attr_span))
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) struct AllowConstFnUnstableParser;
|
||||
impl<S: Stage> CombineAttributeParser<S> for AllowConstFnUnstableParser {
|
||||
const PATH: &[Symbol] = &[sym::rustc_allow_const_fn_unstable];
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ use rustc_session::parse::feature_err;
|
|||
use rustc_span::{Span, Symbol, sym};
|
||||
use thin_vec::ThinVec;
|
||||
|
||||
use crate::context::{AcceptContext, Stage};
|
||||
use crate::context::{AcceptContext, ShouldEmit, Stage};
|
||||
use crate::parser::{ArgParser, MetaItemListParser, MetaItemOrLitParser, NameValueParser};
|
||||
use crate::{
|
||||
CfgMatchesLintEmitter, fluent_generated, parse_version, session_diagnostics, try_gate_cfg,
|
||||
|
|
@ -90,7 +90,7 @@ fn parse_cfg_entry_version<S: Stage>(
|
|||
list: &MetaItemListParser<'_>,
|
||||
meta_span: Span,
|
||||
) -> Option<CfgEntry> {
|
||||
try_gate_cfg(sym::version, meta_span, cx.sess(), Some(cx.features()));
|
||||
try_gate_cfg(sym::version, meta_span, cx.sess(), cx.features_option());
|
||||
let Some(version) = list.single() else {
|
||||
cx.emit_err(session_diagnostics::ExpectedSingleVersionLiteral { span: list.span });
|
||||
return None;
|
||||
|
|
@ -119,7 +119,9 @@ fn parse_cfg_entry_target<S: Stage>(
|
|||
list: &MetaItemListParser<'_>,
|
||||
meta_span: Span,
|
||||
) -> Option<CfgEntry> {
|
||||
if !cx.features().cfg_target_compact() {
|
||||
if let Some(features) = cx.features_option()
|
||||
&& !features.cfg_target_compact()
|
||||
{
|
||||
feature_err(
|
||||
cx.sess(),
|
||||
sym::cfg_target_compact,
|
||||
|
|
@ -186,12 +188,13 @@ pub fn eval_config_entry(
|
|||
cfg_entry: &CfgEntry,
|
||||
id: NodeId,
|
||||
features: Option<&Features>,
|
||||
emit_lints: ShouldEmit,
|
||||
) -> EvalConfigResult {
|
||||
match cfg_entry {
|
||||
CfgEntry::All(subs, ..) => {
|
||||
let mut all = None;
|
||||
for sub in subs {
|
||||
let res = eval_config_entry(sess, sub, id, features);
|
||||
let res = eval_config_entry(sess, sub, id, features, emit_lints);
|
||||
// We cannot short-circuit because `eval_config_entry` emits some lints
|
||||
if !res.as_bool() {
|
||||
all.get_or_insert(res);
|
||||
|
|
@ -202,7 +205,7 @@ pub fn eval_config_entry(
|
|||
CfgEntry::Any(subs, span) => {
|
||||
let mut any = None;
|
||||
for sub in subs {
|
||||
let res = eval_config_entry(sess, sub, id, features);
|
||||
let res = eval_config_entry(sess, sub, id, features, emit_lints);
|
||||
// We cannot short-circuit because `eval_config_entry` emits some lints
|
||||
if res.as_bool() {
|
||||
any.get_or_insert(res);
|
||||
|
|
@ -214,7 +217,7 @@ pub fn eval_config_entry(
|
|||
})
|
||||
}
|
||||
CfgEntry::Not(sub, span) => {
|
||||
if eval_config_entry(sess, sub, id, features).as_bool() {
|
||||
if eval_config_entry(sess, sub, id, features, emit_lints).as_bool() {
|
||||
EvalConfigResult::False { reason: cfg_entry.clone(), reason_span: *span }
|
||||
} else {
|
||||
EvalConfigResult::True
|
||||
|
|
@ -228,24 +231,28 @@ pub fn eval_config_entry(
|
|||
}
|
||||
}
|
||||
CfgEntry::NameValue { name, name_span, value, span } => {
|
||||
match sess.psess.check_config.expecteds.get(name) {
|
||||
Some(ExpectedValues::Some(values)) if !values.contains(&value.map(|(v, _)| v)) => {
|
||||
id.emit_span_lint(
|
||||
sess,
|
||||
UNEXPECTED_CFGS,
|
||||
*span,
|
||||
BuiltinLintDiag::UnexpectedCfgValue((*name, *name_span), *value),
|
||||
);
|
||||
if let ShouldEmit::ErrorsAndLints = emit_lints {
|
||||
match sess.psess.check_config.expecteds.get(name) {
|
||||
Some(ExpectedValues::Some(values))
|
||||
if !values.contains(&value.map(|(v, _)| v)) =>
|
||||
{
|
||||
id.emit_span_lint(
|
||||
sess,
|
||||
UNEXPECTED_CFGS,
|
||||
*span,
|
||||
BuiltinLintDiag::UnexpectedCfgValue((*name, *name_span), *value),
|
||||
);
|
||||
}
|
||||
None if sess.psess.check_config.exhaustive_names => {
|
||||
id.emit_span_lint(
|
||||
sess,
|
||||
UNEXPECTED_CFGS,
|
||||
*span,
|
||||
BuiltinLintDiag::UnexpectedCfgName((*name, *name_span), *value),
|
||||
);
|
||||
}
|
||||
_ => { /* not unexpected */ }
|
||||
}
|
||||
None if sess.psess.check_config.exhaustive_names => {
|
||||
id.emit_span_lint(
|
||||
sess,
|
||||
UNEXPECTED_CFGS,
|
||||
*span,
|
||||
BuiltinLintDiag::UnexpectedCfgName((*name, *name_span), *value),
|
||||
);
|
||||
}
|
||||
_ => { /* not unexpected */ }
|
||||
}
|
||||
|
||||
if sess.psess.config.contains(&(*name, value.map(|(v, _)| v))) {
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
use rustc_attr_data_structures::{AttributeKind, OptimizeAttr, UsedBy};
|
||||
use rustc_attr_data_structures::{AttributeKind, CoverageStatus, OptimizeAttr, UsedBy};
|
||||
use rustc_feature::{AttributeTemplate, template};
|
||||
use rustc_session::parse::feature_err;
|
||||
use rustc_span::{Span, Symbol, sym};
|
||||
|
|
@ -52,6 +52,45 @@ impl<S: Stage> NoArgsAttributeParser<S> for ColdParser {
|
|||
const CREATE: fn(Span) -> AttributeKind = AttributeKind::Cold;
|
||||
}
|
||||
|
||||
pub(crate) struct CoverageParser;
|
||||
|
||||
impl<S: Stage> SingleAttributeParser<S> for CoverageParser {
|
||||
const PATH: &[Symbol] = &[sym::coverage];
|
||||
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost;
|
||||
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
|
||||
const TEMPLATE: AttributeTemplate = template!(OneOf: &[sym::off, sym::on]);
|
||||
|
||||
fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser<'_>) -> Option<AttributeKind> {
|
||||
let Some(args) = args.list() else {
|
||||
cx.expected_specific_argument_and_list(cx.attr_span, vec!["on", "off"]);
|
||||
return None;
|
||||
};
|
||||
|
||||
let Some(arg) = args.single() else {
|
||||
cx.expected_single_argument(args.span);
|
||||
return None;
|
||||
};
|
||||
|
||||
let fail_incorrect_argument = |span| cx.expected_specific_argument(span, vec!["on", "off"]);
|
||||
|
||||
let Some(arg) = arg.meta_item() else {
|
||||
fail_incorrect_argument(args.span);
|
||||
return None;
|
||||
};
|
||||
|
||||
let status = match arg.path().word_sym() {
|
||||
Some(sym::off) => CoverageStatus::Off,
|
||||
Some(sym::on) => CoverageStatus::On,
|
||||
None | Some(_) => {
|
||||
fail_incorrect_argument(arg.span());
|
||||
return None;
|
||||
}
|
||||
};
|
||||
|
||||
Some(AttributeKind::Coverage(cx.attr_span, status))
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) struct ExportNameParser;
|
||||
|
||||
impl<S: Stage> SingleAttributeParser<S> for ExportNameParser {
|
||||
|
|
|
|||
|
|
@ -98,6 +98,16 @@ impl<S: Stage> AttributeParser<S> for StabilityParser {
|
|||
}
|
||||
}
|
||||
|
||||
if let Some((Stability { level: StabilityLevel::Stable { .. }, .. }, _)) = self.stability {
|
||||
for other_attr in cx.all_attrs {
|
||||
if other_attr.word_is(sym::unstable_feature_bound) {
|
||||
cx.emit_err(session_diagnostics::UnstableFeatureBoundIncompatibleStability {
|
||||
span: cx.target_span,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let (stability, span) = self.stability?;
|
||||
|
||||
Some(AttributeKind::Stability { stability, span })
|
||||
|
|
@ -282,12 +292,12 @@ pub(crate) fn parse_stability<S: Stage>(
|
|||
} else if let Some(version) = parse_version(since) {
|
||||
StableSince::Version(version)
|
||||
} else {
|
||||
cx.emit_err(session_diagnostics::InvalidSince { span: cx.attr_span });
|
||||
StableSince::Err
|
||||
let err = cx.emit_err(session_diagnostics::InvalidSince { span: cx.attr_span });
|
||||
StableSince::Err(err)
|
||||
}
|
||||
} else {
|
||||
cx.emit_err(session_diagnostics::MissingSince { span: cx.attr_span });
|
||||
StableSince::Err
|
||||
let err = cx.emit_err(session_diagnostics::MissingSince { span: cx.attr_span });
|
||||
StableSince::Err(err)
|
||||
};
|
||||
|
||||
match feature {
|
||||
|
|
|
|||
|
|
@ -91,6 +91,7 @@ impl<S: Stage> NoArgsAttributeParser<S> for DoNotImplementViaObjectParser {
|
|||
const CREATE: fn(Span) -> AttributeKind = AttributeKind::DoNotImplementViaObject;
|
||||
}
|
||||
|
||||
// FIXME(const_trait_impl): remove this
|
||||
// Const traits
|
||||
|
||||
pub(crate) struct ConstTraitParser;
|
||||
|
|
@ -145,3 +146,10 @@ impl<S: Stage> NoArgsAttributeParser<S> for FundamentalParser {
|
|||
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
|
||||
const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::Fundamental;
|
||||
}
|
||||
|
||||
pub(crate) struct PointeeParser;
|
||||
impl<S: Stage> NoArgsAttributeParser<S> for PointeeParser {
|
||||
const PATH: &[Symbol] = &[sym::pointee];
|
||||
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
|
||||
const CREATE: fn(Span) -> AttributeKind = AttributeKind::Pointee;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,10 +13,13 @@ use rustc_hir::{AttrArgs, AttrItem, AttrPath, Attribute, HashIgnoredAttrId, HirI
|
|||
use rustc_session::Session;
|
||||
use rustc_span::{DUMMY_SP, ErrorGuaranteed, Span, Symbol, sym};
|
||||
|
||||
use crate::attributes::allow_unstable::{AllowConstFnUnstableParser, AllowInternalUnstableParser};
|
||||
use crate::attributes::allow_unstable::{
|
||||
AllowConstFnUnstableParser, AllowInternalUnstableParser, UnstableFeatureBoundParser,
|
||||
};
|
||||
use crate::attributes::codegen_attrs::{
|
||||
ColdParser, ExportNameParser, NakedParser, NoMangleParser, OmitGdbPrettyPrinterSectionParser,
|
||||
OptimizeParser, TargetFeatureParser, TrackCallerParser, UsedParser,
|
||||
ColdParser, CoverageParser, ExportNameParser, NakedParser, NoMangleParser,
|
||||
OmitGdbPrettyPrinterSectionParser, OptimizeParser, TargetFeatureParser, TrackCallerParser,
|
||||
UsedParser,
|
||||
};
|
||||
use crate::attributes::confusables::ConfusablesParser;
|
||||
use crate::attributes::deprecation::DeprecationParser;
|
||||
|
|
@ -47,8 +50,8 @@ use crate::attributes::test_attrs::IgnoreParser;
|
|||
use crate::attributes::traits::{
|
||||
AllowIncoherentImplParser, CoherenceIsCoreParser, CoinductiveParser, ConstTraitParser,
|
||||
DenyExplicitImplParser, DoNotImplementViaObjectParser, FundamentalParser, MarkerParser,
|
||||
ParenSugarParser, SkipDuringMethodDispatchParser, SpecializationTraitParser, TypeConstParser,
|
||||
UnsafeSpecializationMarkerParser,
|
||||
ParenSugarParser, PointeeParser, SkipDuringMethodDispatchParser, SpecializationTraitParser,
|
||||
TypeConstParser, UnsafeSpecializationMarkerParser,
|
||||
};
|
||||
use crate::attributes::transparency::TransparencyParser;
|
||||
use crate::attributes::{AttributeParser as _, Combine, Single, WithoutArgs};
|
||||
|
|
@ -133,9 +136,11 @@ attribute_parsers!(
|
|||
Combine<AllowInternalUnstableParser>,
|
||||
Combine<ReprParser>,
|
||||
Combine<TargetFeatureParser>,
|
||||
Combine<UnstableFeatureBoundParser>,
|
||||
// tidy-alphabetical-end
|
||||
|
||||
// tidy-alphabetical-start
|
||||
Single<CoverageParser>,
|
||||
Single<DeprecationParser>,
|
||||
Single<DummyParser>,
|
||||
Single<ExportNameParser>,
|
||||
|
|
@ -177,6 +182,7 @@ attribute_parsers!(
|
|||
Single<WithoutArgs<OmitGdbPrettyPrinterSectionParser>>,
|
||||
Single<WithoutArgs<ParenSugarParser>>,
|
||||
Single<WithoutArgs<PassByValueParser>>,
|
||||
Single<WithoutArgs<PointeeParser>>,
|
||||
Single<WithoutArgs<PubTransparentParser>>,
|
||||
Single<WithoutArgs<SpecializationTraitParser>>,
|
||||
Single<WithoutArgs<StdInternalSymbolParser>>,
|
||||
|
|
@ -222,7 +228,7 @@ impl Stage for Early {
|
|||
sess: &'sess Session,
|
||||
diag: impl for<'x> Diagnostic<'x>,
|
||||
) -> ErrorGuaranteed {
|
||||
if self.emit_errors {
|
||||
if self.emit_errors.should_emit() {
|
||||
sess.dcx().emit_err(diag)
|
||||
} else {
|
||||
sess.dcx().create_err(diag).delay_as_bug()
|
||||
|
|
@ -253,7 +259,7 @@ pub struct Early {
|
|||
/// Whether to emit errors or delay them as a bug
|
||||
/// For most attributes, the attribute will be parsed again in the `Late` stage and in this case the errors should be delayed
|
||||
/// But for some, such as `cfg`, the attribute will be removed before the `Late` stage so errors must be emitted
|
||||
pub emit_errors: bool,
|
||||
pub emit_errors: ShouldEmit,
|
||||
}
|
||||
/// used when parsing attributes during ast lowering
|
||||
pub struct Late;
|
||||
|
|
@ -448,6 +454,25 @@ impl<'f, 'sess: 'f, S: Stage> AcceptContext<'f, 'sess, S> {
|
|||
reason: AttributeParseErrorReason::ExpectedSpecificArgument {
|
||||
possibilities,
|
||||
strings: false,
|
||||
list: false,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
pub(crate) fn expected_specific_argument_and_list(
|
||||
&self,
|
||||
span: Span,
|
||||
possibilities: Vec<&'static str>,
|
||||
) -> ErrorGuaranteed {
|
||||
self.emit_err(AttributeParseError {
|
||||
span,
|
||||
attr_span: self.attr_span,
|
||||
template: self.template.clone(),
|
||||
attribute: self.attr_path.clone(),
|
||||
reason: AttributeParseErrorReason::ExpectedSpecificArgument {
|
||||
possibilities,
|
||||
strings: false,
|
||||
list: true,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
|
@ -465,6 +490,7 @@ impl<'f, 'sess: 'f, S: Stage> AcceptContext<'f, 'sess, S> {
|
|||
reason: AttributeParseErrorReason::ExpectedSpecificArgument {
|
||||
possibilities,
|
||||
strings: true,
|
||||
list: false,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
|
@ -554,6 +580,25 @@ pub enum OmitDoc {
|
|||
Skip,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
pub enum ShouldEmit {
|
||||
/// The operation will emit errors and lints.
|
||||
/// This is usually what you need.
|
||||
ErrorsAndLints,
|
||||
/// The operation will emit *not* errors and lints.
|
||||
/// Use this if you are *sure* that this operation will be called at a different time with `ShouldEmit::Emit`.
|
||||
Nothing,
|
||||
}
|
||||
|
||||
impl ShouldEmit {
|
||||
pub fn should_emit(&self) -> bool {
|
||||
match self {
|
||||
ShouldEmit::ErrorsAndLints => true,
|
||||
ShouldEmit::Nothing => false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Context created once, for example as part of the ast lowering
|
||||
/// context, through which all attributes can be lowered.
|
||||
pub struct AttributeParser<'sess, S: Stage = Late> {
|
||||
|
|
@ -596,7 +641,7 @@ impl<'sess> AttributeParser<'sess, Early> {
|
|||
tools: Vec::new(),
|
||||
parse_only: Some(sym),
|
||||
sess,
|
||||
stage: Early { emit_errors: false },
|
||||
stage: Early { emit_errors: ShouldEmit::Nothing },
|
||||
};
|
||||
let mut parsed = p.parse_attribute_list(
|
||||
attrs,
|
||||
|
|
@ -619,7 +664,7 @@ impl<'sess> AttributeParser<'sess, Early> {
|
|||
target_span: Span,
|
||||
target_node_id: NodeId,
|
||||
features: Option<&'sess Features>,
|
||||
emit_errors: bool,
|
||||
emit_errors: ShouldEmit,
|
||||
parse_fn: fn(cx: &mut AcceptContext<'_, '_, Early>, item: &ArgParser<'_>) -> T,
|
||||
template: &AttributeTemplate,
|
||||
) -> T {
|
||||
|
|
|
|||
|
|
@ -95,7 +95,7 @@ pub use attributes::cfg_old::*;
|
|||
pub use attributes::util::{
|
||||
find_crate_name, is_builtin_attr, is_doc_alias_attrs_contain_symbol, parse_version,
|
||||
};
|
||||
pub use context::{AttributeParser, Early, Late, OmitDoc};
|
||||
pub use context::{AttributeParser, Early, Late, OmitDoc, ShouldEmit};
|
||||
pub use lints::emit_attribute_lint;
|
||||
|
||||
rustc_fluent_macro::fluent_messages! { "../messages.ftl" }
|
||||
|
|
|
|||
|
|
@ -503,6 +503,14 @@ pub(crate) struct UnrecognizedReprHint {
|
|||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(attr_parsing_unstable_feature_bound_incompatible_stability)]
|
||||
#[help]
|
||||
pub(crate) struct UnstableFeatureBoundIncompatibleStability {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(attr_parsing_naked_functions_incompatible_attribute, code = E0736)]
|
||||
pub(crate) struct NakedFunctionIncompatibleAttribute {
|
||||
|
|
@ -525,7 +533,9 @@ pub(crate) struct LinkOrdinalOutOfRange {
|
|||
|
||||
pub(crate) enum AttributeParseErrorReason {
|
||||
ExpectedNoArgs,
|
||||
ExpectedStringLiteral { byte_string: Option<Span> },
|
||||
ExpectedStringLiteral {
|
||||
byte_string: Option<Span>,
|
||||
},
|
||||
ExpectedIntegerLiteral,
|
||||
ExpectedAtLeastOneArgument,
|
||||
ExpectedSingleArgument,
|
||||
|
|
@ -533,7 +543,12 @@ pub(crate) enum AttributeParseErrorReason {
|
|||
UnexpectedLiteral,
|
||||
ExpectedNameValue(Option<Symbol>),
|
||||
DuplicateKey(Symbol),
|
||||
ExpectedSpecificArgument { possibilities: Vec<&'static str>, strings: bool },
|
||||
ExpectedSpecificArgument {
|
||||
possibilities: Vec<&'static str>,
|
||||
strings: bool,
|
||||
/// Should we tell the user to write a list when they didn't?
|
||||
list: bool,
|
||||
},
|
||||
}
|
||||
|
||||
pub(crate) struct AttributeParseError {
|
||||
|
|
@ -607,7 +622,11 @@ impl<'a, G: EmissionGuarantee> Diagnostic<'a, G> for AttributeParseError {
|
|||
format!("expected this to be of the form `{name} = \"...\"`"),
|
||||
);
|
||||
}
|
||||
AttributeParseErrorReason::ExpectedSpecificArgument { possibilities, strings } => {
|
||||
AttributeParseErrorReason::ExpectedSpecificArgument {
|
||||
possibilities,
|
||||
strings,
|
||||
list: false,
|
||||
} => {
|
||||
let quote = if strings { '"' } else { '`' };
|
||||
match possibilities.as_slice() {
|
||||
&[] => {}
|
||||
|
|
@ -633,6 +652,38 @@ impl<'a, G: EmissionGuarantee> Diagnostic<'a, G> for AttributeParseError {
|
|||
}
|
||||
}
|
||||
}
|
||||
AttributeParseErrorReason::ExpectedSpecificArgument {
|
||||
possibilities,
|
||||
strings,
|
||||
list: true,
|
||||
} => {
|
||||
let quote = if strings { '"' } else { '`' };
|
||||
match possibilities.as_slice() {
|
||||
&[] => {}
|
||||
&[x] => {
|
||||
diag.span_label(
|
||||
self.span,
|
||||
format!(
|
||||
"this attribute is only valid with {quote}{x}{quote} as an argument"
|
||||
),
|
||||
);
|
||||
}
|
||||
[first, second] => {
|
||||
diag.span_label(self.span, format!("this attribute is only valid with either {quote}{first}{quote} or {quote}{second}{quote} as an argument"));
|
||||
}
|
||||
[first @ .., second_to_last, last] => {
|
||||
let mut res = String::new();
|
||||
for i in first {
|
||||
res.push_str(&format!("{quote}{i}{quote}, "));
|
||||
}
|
||||
res.push_str(&format!(
|
||||
"{quote}{second_to_last}{quote} or {quote}{last}{quote}"
|
||||
));
|
||||
|
||||
diag.span_label(self.span, format!("this attribute is only valid with one of the following arguments: {res}"));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let suggestions = self.template.suggestions(false, &name);
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
use rustc_data_structures::fx::FxHashSet;
|
||||
use rustc_hir::def_id::LocalDefId;
|
||||
use rustc_infer::infer::canonical::QueryRegionConstraints;
|
||||
use rustc_infer::infer::outlives::env::RegionBoundPairs;
|
||||
|
|
@ -7,7 +8,7 @@ use rustc_infer::infer::{InferCtxt, SubregionOrigin};
|
|||
use rustc_infer::traits::query::type_op::DeeplyNormalize;
|
||||
use rustc_middle::bug;
|
||||
use rustc_middle::ty::{
|
||||
self, GenericArgKind, Ty, TyCtxt, TypeFoldable, TypeVisitableExt, fold_regions,
|
||||
self, GenericArgKind, Ty, TyCtxt, TypeFoldable, TypeVisitableExt, elaborate, fold_regions,
|
||||
};
|
||||
use rustc_span::Span;
|
||||
use rustc_trait_selection::traits::query::type_op::{TypeOp, TypeOpOutput};
|
||||
|
|
@ -70,10 +71,12 @@ impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> {
|
|||
|
||||
#[instrument(skip(self), level = "debug")]
|
||||
pub(super) fn convert_all(&mut self, query_constraints: &QueryRegionConstraints<'tcx>) {
|
||||
let QueryRegionConstraints { outlives } = query_constraints;
|
||||
let QueryRegionConstraints { outlives, assumptions } = query_constraints;
|
||||
let assumptions =
|
||||
elaborate::elaborate_outlives_assumptions(self.infcx.tcx, assumptions.iter().copied());
|
||||
|
||||
for &(predicate, constraint_category) in outlives {
|
||||
self.convert(predicate, constraint_category);
|
||||
self.convert(predicate, constraint_category, &assumptions);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -112,15 +115,20 @@ impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> {
|
|||
|
||||
self.category = outlives_requirement.category;
|
||||
self.span = outlives_requirement.blame_span;
|
||||
self.convert(ty::OutlivesPredicate(subject, outlived_region), self.category);
|
||||
self.convert(
|
||||
ty::OutlivesPredicate(subject, outlived_region),
|
||||
self.category,
|
||||
&Default::default(),
|
||||
);
|
||||
}
|
||||
(self.category, self.span, self.from_closure) = backup;
|
||||
}
|
||||
|
||||
fn convert(
|
||||
&mut self,
|
||||
predicate: ty::OutlivesPredicate<'tcx, ty::GenericArg<'tcx>>,
|
||||
predicate: ty::ArgOutlivesPredicate<'tcx>,
|
||||
constraint_category: ConstraintCategory<'tcx>,
|
||||
higher_ranked_assumptions: &FxHashSet<ty::ArgOutlivesPredicate<'tcx>>,
|
||||
) {
|
||||
let tcx = self.infcx.tcx;
|
||||
debug!("generate: constraints at: {:#?}", self.locations);
|
||||
|
|
@ -150,7 +158,15 @@ impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> {
|
|||
}
|
||||
|
||||
let mut next_outlives_predicates = vec![];
|
||||
for (ty::OutlivesPredicate(k1, r2), constraint_category) in outlives_predicates {
|
||||
for (pred, constraint_category) in outlives_predicates {
|
||||
// Constraint is implied by a coroutine's well-formedness.
|
||||
if self.infcx.tcx.sess.opts.unstable_opts.higher_ranked_assumptions
|
||||
&& higher_ranked_assumptions.contains(&pred)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
let ty::OutlivesPredicate(k1, r2) = pred;
|
||||
match k1.kind() {
|
||||
GenericArgKind::Lifetime(r1) => {
|
||||
let r1_vid = self.to_region_vid(r1);
|
||||
|
|
@ -266,14 +282,15 @@ impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> {
|
|||
&self,
|
||||
ty: Ty<'tcx>,
|
||||
next_outlives_predicates: &mut Vec<(
|
||||
ty::OutlivesPredicate<'tcx, ty::GenericArg<'tcx>>,
|
||||
ty::ArgOutlivesPredicate<'tcx>,
|
||||
ConstraintCategory<'tcx>,
|
||||
)>,
|
||||
) -> Ty<'tcx> {
|
||||
match self.param_env.and(DeeplyNormalize { value: ty }).fully_perform(self.infcx, self.span)
|
||||
{
|
||||
Ok(TypeOpOutput { output: ty, constraints, .. }) => {
|
||||
if let Some(QueryRegionConstraints { outlives }) = constraints {
|
||||
// FIXME(higher_ranked_auto): What should we do with the assumptions here?
|
||||
if let Some(QueryRegionConstraints { outlives, assumptions: _ }) = constraints {
|
||||
next_outlives_predicates.extend(outlives.iter().copied());
|
||||
}
|
||||
ty
|
||||
|
|
|
|||
|
|
@ -131,6 +131,11 @@ pub(crate) fn type_check<'tcx>(
|
|||
pre_obligations.is_empty(),
|
||||
"there should be no incoming region obligations = {pre_obligations:#?}",
|
||||
);
|
||||
let pre_assumptions = infcx.take_registered_region_assumptions();
|
||||
assert!(
|
||||
pre_assumptions.is_empty(),
|
||||
"there should be no incoming region assumptions = {pre_assumptions:#?}",
|
||||
);
|
||||
|
||||
debug!(?normalized_inputs_and_output);
|
||||
|
||||
|
|
|
|||
|
|
@ -81,11 +81,11 @@ builtin_macros_cfg_accessible_literal_path = `cfg_accessible` path cannot be a l
|
|||
builtin_macros_cfg_accessible_multiple_paths = multiple `cfg_accessible` paths are specified
|
||||
builtin_macros_cfg_accessible_unspecified_path = `cfg_accessible` path is not specified
|
||||
|
||||
builtin_macros_cfg_select_no_matches = none of the rules in this `cfg_select` evaluated to true
|
||||
builtin_macros_cfg_select_no_matches = none of the predicates in this `cfg_select` evaluated to true
|
||||
|
||||
builtin_macros_cfg_select_unreachable = unreachable rule
|
||||
builtin_macros_cfg_select_unreachable = unreachable predicate
|
||||
.label = always matches
|
||||
.label2 = this rules is never reached
|
||||
.label2 = this predicate is never reached
|
||||
|
||||
builtin_macros_coerce_pointee_requires_maybe_sized = `derive(CoercePointee)` requires `{$name}` to be marked `?Sized`
|
||||
|
||||
|
|
|
|||
|
|
@ -1,12 +1,12 @@
|
|||
use rustc_ast::tokenstream::TokenStream;
|
||||
use rustc_attr_parsing as attr;
|
||||
use rustc_expand::base::{DummyResult, ExpandResult, ExtCtxt, MacroExpanderResult};
|
||||
use rustc_parse::parser::cfg_select::{CfgSelectBranches, CfgSelectRule, parse_cfg_select};
|
||||
use rustc_parse::parser::cfg_select::{CfgSelectBranches, CfgSelectPredicate, parse_cfg_select};
|
||||
use rustc_span::{Ident, Span, sym};
|
||||
|
||||
use crate::errors::{CfgSelectNoMatches, CfgSelectUnreachable};
|
||||
|
||||
/// Selects the first arm whose rule evaluates to true.
|
||||
/// Selects the first arm whose predicate evaluates to true.
|
||||
fn select_arm(ecx: &ExtCtxt<'_>, branches: CfgSelectBranches) -> Option<(TokenStream, Span)> {
|
||||
for (cfg, tt, arm_span) in branches.reachable {
|
||||
if attr::cfg_matches(
|
||||
|
|
@ -30,11 +30,11 @@ pub(super) fn expand_cfg_select<'cx>(
|
|||
ExpandResult::Ready(match parse_cfg_select(&mut ecx.new_parser_from_tts(tts)) {
|
||||
Ok(branches) => {
|
||||
if let Some((underscore, _, _)) = branches.wildcard {
|
||||
// Warn for every unreachable rule. We store the fully parsed branch for rustfmt.
|
||||
for (rule, _, _) in &branches.unreachable {
|
||||
let span = match rule {
|
||||
CfgSelectRule::Wildcard(underscore) => underscore.span,
|
||||
CfgSelectRule::Cfg(cfg) => cfg.span(),
|
||||
// Warn for every unreachable predicate. We store the fully parsed branch for rustfmt.
|
||||
for (predicate, _, _) in &branches.unreachable {
|
||||
let span = match predicate {
|
||||
CfgSelectPredicate::Wildcard(underscore) => underscore.span,
|
||||
CfgSelectPredicate::Cfg(cfg) => cfg.span(),
|
||||
};
|
||||
let err = CfgSelectUnreachable { span, wildcard_span: underscore.span };
|
||||
ecx.dcx().emit_warn(err);
|
||||
|
|
@ -50,7 +50,7 @@ pub(super) fn expand_cfg_select<'cx>(
|
|||
Ident::with_dummy_span(sym::cfg_select),
|
||||
);
|
||||
} else {
|
||||
// Emit a compiler error when none of the rules matched.
|
||||
// Emit a compiler error when none of the predicates matched.
|
||||
let guar = ecx.dcx().emit_err(CfgSelectNoMatches { span: sp });
|
||||
DummyResult::any(sp, guar)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@ pub(crate) fn expand_deriving_copy(
|
|||
methods: Vec::new(),
|
||||
associated_types: Vec::new(),
|
||||
is_const,
|
||||
is_staged_api_crate: cx.ecfg.features.staged_api(),
|
||||
};
|
||||
|
||||
trait_def.expand(cx, mitem, item, push);
|
||||
|
|
@ -46,6 +47,7 @@ pub(crate) fn expand_deriving_const_param_ty(
|
|||
methods: Vec::new(),
|
||||
associated_types: Vec::new(),
|
||||
is_const,
|
||||
is_staged_api_crate: cx.ecfg.features.staged_api(),
|
||||
};
|
||||
|
||||
trait_def.expand(cx, mitem, item, push);
|
||||
|
|
@ -60,6 +62,7 @@ pub(crate) fn expand_deriving_const_param_ty(
|
|||
methods: Vec::new(),
|
||||
associated_types: Vec::new(),
|
||||
is_const,
|
||||
is_staged_api_crate: cx.ecfg.features.staged_api(),
|
||||
};
|
||||
|
||||
trait_def.expand(cx, mitem, item, push);
|
||||
|
|
@ -83,6 +86,7 @@ pub(crate) fn expand_deriving_unsized_const_param_ty(
|
|||
methods: Vec::new(),
|
||||
associated_types: Vec::new(),
|
||||
is_const,
|
||||
is_staged_api_crate: cx.ecfg.features.staged_api(),
|
||||
};
|
||||
|
||||
trait_def.expand(cx, mitem, item, push);
|
||||
|
|
|
|||
|
|
@ -87,6 +87,7 @@ pub(crate) fn expand_deriving_clone(
|
|||
}],
|
||||
associated_types: Vec::new(),
|
||||
is_const,
|
||||
is_staged_api_crate: cx.ecfg.features.staged_api(),
|
||||
};
|
||||
|
||||
trait_def.expand_ext(cx, mitem, item, push, is_simple)
|
||||
|
|
|
|||
|
|
@ -43,6 +43,7 @@ pub(crate) fn expand_deriving_eq(
|
|||
}],
|
||||
associated_types: Vec::new(),
|
||||
is_const,
|
||||
is_staged_api_crate: cx.ecfg.features.staged_api(),
|
||||
};
|
||||
trait_def.expand_ext(cx, mitem, item, push, true)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@ pub(crate) fn expand_deriving_ord(
|
|||
}],
|
||||
associated_types: Vec::new(),
|
||||
is_const,
|
||||
is_staged_api_crate: cx.ecfg.features.staged_api(),
|
||||
};
|
||||
|
||||
trait_def.expand(cx, mitem, item, push)
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@ pub(crate) fn expand_deriving_partial_eq(
|
|||
methods: Vec::new(),
|
||||
associated_types: Vec::new(),
|
||||
is_const: false,
|
||||
is_staged_api_crate: cx.ecfg.features.staged_api(),
|
||||
};
|
||||
structural_trait_def.expand(cx, mitem, item, push);
|
||||
|
||||
|
|
@ -58,6 +59,7 @@ pub(crate) fn expand_deriving_partial_eq(
|
|||
methods,
|
||||
associated_types: Vec::new(),
|
||||
is_const,
|
||||
is_staged_api_crate: cx.ecfg.features.staged_api(),
|
||||
};
|
||||
trait_def.expand(cx, mitem, item, push)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -64,6 +64,7 @@ pub(crate) fn expand_deriving_partial_ord(
|
|||
methods: vec![partial_cmp_def],
|
||||
associated_types: Vec::new(),
|
||||
is_const,
|
||||
is_staged_api_crate: cx.ecfg.features.staged_api(),
|
||||
};
|
||||
trait_def.expand(cx, mitem, item, push)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -41,6 +41,7 @@ pub(crate) fn expand_deriving_debug(
|
|||
}],
|
||||
associated_types: Vec::new(),
|
||||
is_const,
|
||||
is_staged_api_crate: cx.ecfg.features.staged_api(),
|
||||
};
|
||||
trait_def.expand(cx, mitem, item, push)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -51,6 +51,7 @@ pub(crate) fn expand_deriving_default(
|
|||
}],
|
||||
associated_types: Vec::new(),
|
||||
is_const,
|
||||
is_staged_api_crate: cx.ecfg.features.staged_api(),
|
||||
};
|
||||
trait_def.expand(cx, mitem, item, push)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -181,9 +181,11 @@ use std::{iter, vec};
|
|||
pub(crate) use StaticFields::*;
|
||||
pub(crate) use SubstructureFields::*;
|
||||
use rustc_ast::ptr::P;
|
||||
use rustc_ast::token::{IdentIsRaw, LitKind, Token, TokenKind};
|
||||
use rustc_ast::tokenstream::{DelimSpan, Spacing, TokenTree};
|
||||
use rustc_ast::{
|
||||
self as ast, AnonConst, BindingMode, ByRef, EnumDef, Expr, GenericArg, GenericParamKind,
|
||||
Generics, Mutability, PatKind, VariantData,
|
||||
self as ast, AnonConst, AttrArgs, BindingMode, ByRef, DelimArgs, EnumDef, Expr, GenericArg,
|
||||
GenericParamKind, Generics, Mutability, PatKind, Safety, VariantData,
|
||||
};
|
||||
use rustc_attr_data_structures::{AttributeKind, ReprPacked};
|
||||
use rustc_attr_parsing::AttributeParser;
|
||||
|
|
@ -222,6 +224,8 @@ pub(crate) struct TraitDef<'a> {
|
|||
pub associated_types: Vec<(Ident, Ty)>,
|
||||
|
||||
pub is_const: bool,
|
||||
|
||||
pub is_staged_api_crate: bool,
|
||||
}
|
||||
|
||||
pub(crate) struct MethodDef<'a> {
|
||||
|
|
@ -784,8 +788,45 @@ impl<'a> TraitDef<'a> {
|
|||
// Create the type of `self`.
|
||||
let path = cx.path_all(self.span, false, vec![type_ident], self_params);
|
||||
let self_type = cx.ty_path(path);
|
||||
let rustc_const_unstable =
|
||||
cx.path_ident(self.span, Ident::new(sym::rustc_const_unstable, self.span));
|
||||
|
||||
let mut attrs = thin_vec![cx.attr_word(sym::automatically_derived, self.span),];
|
||||
|
||||
// Only add `rustc_const_unstable` attributes if `derive_const` is used within libcore/libstd,
|
||||
// Other crates don't need stability attributes, so adding them is not useful, but libcore needs them
|
||||
// on all const trait impls.
|
||||
if self.is_const && self.is_staged_api_crate {
|
||||
attrs.push(
|
||||
cx.attr_nested(
|
||||
rustc_ast::AttrItem {
|
||||
unsafety: Safety::Default,
|
||||
path: rustc_const_unstable,
|
||||
args: AttrArgs::Delimited(DelimArgs {
|
||||
dspan: DelimSpan::from_single(self.span),
|
||||
delim: rustc_ast::token::Delimiter::Parenthesis,
|
||||
tokens: [
|
||||
TokenKind::Ident(sym::feature, IdentIsRaw::No),
|
||||
TokenKind::Eq,
|
||||
TokenKind::lit(LitKind::Str, sym::derive_const, None),
|
||||
TokenKind::Comma,
|
||||
TokenKind::Ident(sym::issue, IdentIsRaw::No),
|
||||
TokenKind::Eq,
|
||||
TokenKind::lit(LitKind::Str, sym::derive_const_issue, None),
|
||||
]
|
||||
.into_iter()
|
||||
.map(|kind| {
|
||||
TokenTree::Token(Token { kind, span: self.span }, Spacing::Alone)
|
||||
})
|
||||
.collect(),
|
||||
}),
|
||||
tokens: None,
|
||||
},
|
||||
self.span,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
let attrs = thin_vec![cx.attr_word(sym::automatically_derived, self.span),];
|
||||
let opt_trait_ref = Some(trait_ref);
|
||||
|
||||
cx.item(
|
||||
|
|
|
|||
|
|
@ -41,6 +41,7 @@ pub(crate) fn expand_deriving_hash(
|
|||
}],
|
||||
associated_types: Vec::new(),
|
||||
is_const,
|
||||
is_staged_api_crate: cx.ecfg.features.staged_api(),
|
||||
};
|
||||
|
||||
hash_trait_def.expand(cx, mitem, item, push);
|
||||
|
|
|
|||
|
|
@ -4,8 +4,8 @@ use std::sync::Arc;
|
|||
|
||||
use rustc_ast as ast;
|
||||
use rustc_ast::ptr::P;
|
||||
use rustc_ast::token;
|
||||
use rustc_ast::tokenstream::TokenStream;
|
||||
use rustc_ast::{join_path_idents, token};
|
||||
use rustc_ast_pretty::pprust;
|
||||
use rustc_expand::base::{
|
||||
DummyResult, ExpandResult, ExtCtxt, MacEager, MacResult, MacroExpanderResult, resolve_path,
|
||||
|
|
@ -100,7 +100,7 @@ pub(crate) fn expand_mod(
|
|||
let sp = cx.with_def_site_ctxt(sp);
|
||||
check_zero_tts(cx, sp, tts, "module_path!");
|
||||
let mod_path = &cx.current_expansion.module.mod_path;
|
||||
let string = mod_path.iter().map(|x| x.to_string()).collect::<Vec<String>>().join("::");
|
||||
let string = join_path_idents(mod_path);
|
||||
|
||||
ExpandResult::Ready(MacEager::expr(cx.expr_str(sp, Symbol::intern(&string))))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ use std::assert_matches::assert_matches;
|
|||
use std::iter;
|
||||
|
||||
use rustc_ast::ptr::P;
|
||||
use rustc_ast::{self as ast, GenericParamKind, attr};
|
||||
use rustc_ast::{self as ast, GenericParamKind, attr, join_path_idents};
|
||||
use rustc_ast_pretty::pprust;
|
||||
use rustc_errors::{Applicability, Diag, Level};
|
||||
use rustc_expand::base::*;
|
||||
|
|
@ -446,12 +446,7 @@ fn get_location_info(cx: &ExtCtxt<'_>, fn_: &ast::Fn) -> (Symbol, usize, usize,
|
|||
}
|
||||
|
||||
fn item_path(mod_path: &[Ident], item_ident: &Ident) -> String {
|
||||
mod_path
|
||||
.iter()
|
||||
.chain(iter::once(item_ident))
|
||||
.map(|x| x.to_string())
|
||||
.collect::<Vec<String>>()
|
||||
.join("::")
|
||||
join_path_idents(mod_path.iter().chain(iter::once(item_ident)))
|
||||
}
|
||||
|
||||
enum ShouldPanic {
|
||||
|
|
|
|||
|
|
@ -11,6 +11,12 @@
|
|||
#[derive(Copy, Clone, PartialEq, Debug)]
|
||||
struct f32x4(pub [f32; 4]);
|
||||
|
||||
impl f32x4 {
|
||||
fn into_array(self) -> [f32; 4] {
|
||||
unsafe { std::mem::transmute(self) }
|
||||
}
|
||||
}
|
||||
|
||||
use std::intrinsics::simd::*;
|
||||
|
||||
fn main() {
|
||||
|
|
@ -29,22 +35,22 @@ fn main() {
|
|||
unsafe {
|
||||
let min0 = simd_fmin(x, y);
|
||||
let min1 = simd_fmin(y, x);
|
||||
assert_eq!(min0, min1);
|
||||
assert_eq!(min0.into_array(), min1.into_array());
|
||||
let e = f32x4([1.0, 1.0, 3.0, 3.0]);
|
||||
assert_eq!(min0, e);
|
||||
assert_eq!(min0.into_array(), e.into_array());
|
||||
let minn = simd_fmin(x, n);
|
||||
assert_eq!(minn, x);
|
||||
assert_eq!(minn.into_array(), x.into_array());
|
||||
let minn = simd_fmin(y, n);
|
||||
assert_eq!(minn, y);
|
||||
assert_eq!(minn.into_array(), y.into_array());
|
||||
|
||||
let max0 = simd_fmax(x, y);
|
||||
let max1 = simd_fmax(y, x);
|
||||
assert_eq!(max0, max1);
|
||||
assert_eq!(max0.into_array(), max1.into_array());
|
||||
let e = f32x4([2.0, 2.0, 4.0, 4.0]);
|
||||
assert_eq!(max0, e);
|
||||
assert_eq!(max0.into_array(), e.into_array());
|
||||
let maxn = simd_fmax(x, n);
|
||||
assert_eq!(maxn, x);
|
||||
assert_eq!(maxn.into_array(), x.into_array());
|
||||
let maxn = simd_fmax(y, n);
|
||||
assert_eq!(maxn, y);
|
||||
assert_eq!(maxn.into_array(), y.into_array());
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -348,7 +348,8 @@ fn main() {
|
|||
struct V([f64; 2]);
|
||||
|
||||
let f = V([0.0, 1.0]);
|
||||
let _a = f.0[0];
|
||||
let fp = (&raw const f) as *const [f64; 2];
|
||||
let _a = (unsafe { &*fp })[0];
|
||||
|
||||
stack_val_align();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -530,8 +530,8 @@ fn codegen_cgu_content(
|
|||
for (mono_item, item_data) in mono_items {
|
||||
match mono_item {
|
||||
MonoItem::Fn(instance) => {
|
||||
if tcx.codegen_fn_attrs(instance.def_id()).flags.contains(CodegenFnAttrFlags::NAKED)
|
||||
{
|
||||
let flags = tcx.codegen_instance_attrs(instance.def).flags;
|
||||
if flags.contains(CodegenFnAttrFlags::NAKED) {
|
||||
rustc_codegen_ssa::mir::naked_asm::codegen_naked_asm(
|
||||
&mut GlobalAsmContext { tcx, global_asm: &mut cx.global_asm },
|
||||
instance,
|
||||
|
|
|
|||
|
|
@ -127,7 +127,7 @@ fn codegen_and_compile_fn<'tcx>(
|
|||
module: &mut dyn Module,
|
||||
instance: Instance<'tcx>,
|
||||
) {
|
||||
if tcx.codegen_fn_attrs(instance.def_id()).flags.contains(CodegenFnAttrFlags::NAKED) {
|
||||
if tcx.codegen_instance_attrs(instance.def).flags.contains(CodegenFnAttrFlags::NAKED) {
|
||||
tcx.dcx()
|
||||
.span_fatal(tcx.def_span(instance.def_id()), "Naked asm is not supported in JIT mode");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@ fn predefine_mono_items<'tcx>(
|
|||
is_compiler_builtins,
|
||||
);
|
||||
let is_naked = tcx
|
||||
.codegen_fn_attrs(instance.def_id())
|
||||
.codegen_instance_attrs(instance.def)
|
||||
.flags
|
||||
.contains(CodegenFnAttrFlags::NAKED);
|
||||
module
|
||||
|
|
|
|||
|
|
@ -14,8 +14,6 @@ permissions:
|
|||
env:
|
||||
# Enable backtraces for easier debugging
|
||||
RUST_BACKTRACE: 1
|
||||
# TODO: remove when confish.sh is removed.
|
||||
OVERWRITE_TARGET_TRIPLE: m68k-unknown-linux-gnu
|
||||
|
||||
jobs:
|
||||
build:
|
||||
|
|
@ -59,14 +57,12 @@ jobs:
|
|||
|
||||
- name: Setup path to libgccjit
|
||||
run: |
|
||||
sudo dpkg -i gcc-m68k-15.deb
|
||||
sudo dpkg --force-overwrite -i gcc-m68k-15.deb
|
||||
echo 'gcc-path = "/usr/lib/"' > config.toml
|
||||
|
||||
- name: Set env
|
||||
run: |
|
||||
echo "workspace="$GITHUB_WORKSPACE >> $GITHUB_ENV
|
||||
|
||||
|
||||
|
||||
#- name: Cache rust repository
|
||||
## We only clone the rust repository for rustc tests
|
||||
|
|
@ -86,16 +82,20 @@ jobs:
|
|||
- name: Build sample project with target defined as JSON spec
|
||||
run: |
|
||||
./y.sh prepare --only-libcore --cross
|
||||
./y.sh build --sysroot --features compiler_builtins/no-f16-f128 --target-triple m68k-unknown-linux-gnu --target ${{ github.workspace }}/target_specs/m68k-unknown-linux-gnu.json
|
||||
./y.sh cargo build --manifest-path=./tests/hello-world/Cargo.toml --target ${{ github.workspace }}/target_specs/m68k-unknown-linux-gnu.json
|
||||
./y.sh build --sysroot --features compiler-builtins-no-f16-f128 --target-triple m68k-unknown-linux-gnu --target ${{ github.workspace }}/target_specs/m68k-unknown-linux-gnu.json
|
||||
CG_RUSTFLAGS="-Clinker=m68k-unknown-linux-gnu-gcc" ./y.sh cargo build --manifest-path=./tests/hello-world/Cargo.toml --target ${{ github.workspace }}/target_specs/m68k-unknown-linux-gnu.json
|
||||
./y.sh clean all
|
||||
|
||||
- name: Build
|
||||
run: |
|
||||
./y.sh prepare --only-libcore --cross
|
||||
./y.sh build --sysroot --features compiler_builtins/no-f16-f128 --target-triple m68k-unknown-linux-gnu
|
||||
./y.sh test --mini-tests
|
||||
CG_GCC_TEST_TARGET=m68k-unknown-linux-gnu ./y.sh test --cargo-tests
|
||||
./y.sh build --sysroot --features compiler-builtins-no-f16-f128 --target-triple m68k-unknown-linux-gnu
|
||||
./y.sh test --mini-tests --target-triple m68k-unknown-linux-gnu
|
||||
# FIXME: since https://github.com/rust-lang/rust/pull/140809, we cannot run programs for architectures not
|
||||
# supported by the object crate, since this adds a dependency on symbols.o for the panic runtime.
|
||||
# And as such, a wrong order of the object files in the linker command now fails with an undefined reference
|
||||
# to some symbols like __rustc::rust_panic.
|
||||
#CG_GCC_TEST_TARGET=m68k-unknown-linux-gnu ./y.sh test --cargo-tests --target-triple m68k-unknown-linux-gnu
|
||||
./y.sh clean all
|
||||
|
||||
- name: Prepare dependencies
|
||||
|
|
@ -104,9 +104,23 @@ jobs:
|
|||
git config --global user.name "User"
|
||||
./y.sh prepare --cross
|
||||
|
||||
- name: Run tests
|
||||
run: |
|
||||
./y.sh test --release --clean --build-sysroot --sysroot-features compiler_builtins/no-f16-f128 ${{ matrix.commands }}
|
||||
# FIXME: We cannot run programs for architectures not supported by the object crate. See comment above.
|
||||
#- name: Run tests
|
||||
#run: |
|
||||
#./y.sh test --target-triple m68k-unknown-linux-gnu --release --clean --build-sysroot --sysroot-features compiler-builtins-no-f16-f128 ${{ matrix.commands }}
|
||||
|
||||
# FIXME: We cannot run programs for architectures not supported by the object crate. See comment above.
|
||||
#- name: Run Hello World!
|
||||
#run: |
|
||||
#./y.sh build --target-triple m68k-unknown-linux-gnu
|
||||
|
||||
#vm_dir=$(pwd)/vm
|
||||
#cd tests/hello-world
|
||||
#CG_RUSTFLAGS="-Clinker=m68k-unknown-linux-gnu-gcc" ../../y.sh cargo build --target m68k-unknown-linux-gnu
|
||||
#sudo cp target/m68k-unknown-linux-gnu/debug/hello_world $vm_dir/home/
|
||||
#sudo chroot $vm_dir qemu-m68k-static /home/hello_world > hello_world_stdout
|
||||
#expected_output="40"
|
||||
#test $(cat hello_world_stdout) == $expected_output || (echo "Output differs. Actual output: $(cat hello_world_stdout)"; exit 1)
|
||||
|
||||
# Summary job for the merge queue.
|
||||
# ALL THE PREVIOUS JOBS NEED TO BE ADDED TO THE `needs` SECTION OF THIS JOB!
|
||||
|
|
|
|||
|
|
@ -78,7 +78,8 @@ jobs:
|
|||
- name: Run tests
|
||||
run: |
|
||||
# FIXME(antoyo): we cannot enable LTO for stdarch tests currently because of some failing LTO tests using proc-macros.
|
||||
echo -n 'lto = "fat"' >> build_system/build_sysroot/Cargo.toml
|
||||
# FIXME(antoyo): this should probably not be needed since we embed the LTO bitcode.
|
||||
printf '[profile.release]\nlto = "fat"\n' >> build/build_sysroot/sysroot_src/library/Cargo.toml
|
||||
EMBED_LTO_BITCODE=1 ./y.sh test --release --clean --release-sysroot --build-sysroot --keep-lto-tests ${{ matrix.commands }}
|
||||
|
||||
- name: Run y.sh cargo build
|
||||
|
|
|
|||
|
|
@ -1,502 +0,0 @@
|
|||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
version = 4
|
||||
|
||||
[[package]]
|
||||
name = "addr2line"
|
||||
version = "0.24.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dfbe277e56a376000877090da837660b4427aad530e3028d44e0bffe4f89a1c1"
|
||||
dependencies = [
|
||||
"compiler_builtins",
|
||||
"gimli",
|
||||
"rustc-std-workspace-alloc",
|
||||
"rustc-std-workspace-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "adler2"
|
||||
version = "2.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627"
|
||||
dependencies = [
|
||||
"compiler_builtins",
|
||||
"rustc-std-workspace-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "alloc"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"compiler_builtins",
|
||||
"core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "alloctests"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"rand",
|
||||
"rand_xorshift",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cc"
|
||||
version = "1.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1aeb932158bd710538c73702db6945cb68a8fb08c519e6e12706b94263b36db8"
|
||||
dependencies = [
|
||||
"shlex",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||
dependencies = [
|
||||
"compiler_builtins",
|
||||
"rustc-std-workspace-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "compiler_builtins"
|
||||
version = "0.1.160"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6376049cfa92c0aa8b9ac95fae22184b981c658208d4ed8a1dc553cd83612895"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"rustc-std-workspace-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "core"
|
||||
version = "0.0.0"
|
||||
|
||||
[[package]]
|
||||
name = "coretests"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"rand",
|
||||
"rand_xorshift",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dlmalloc"
|
||||
version = "0.2.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8cff88b751e7a276c4ab0e222c3f355190adc6dde9ce39c851db39da34990df7"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"compiler_builtins",
|
||||
"libc",
|
||||
"rustc-std-workspace-core",
|
||||
"windows-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "fortanix-sgx-abi"
|
||||
version = "0.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "57cafc2274c10fab234f176b25903ce17e690fca7597090d50880e047a0389c5"
|
||||
dependencies = [
|
||||
"compiler_builtins",
|
||||
"rustc-std-workspace-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "getopts"
|
||||
version = "0.2.21"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "14dbbfd5c71d70241ecf9e6f13737f7b5ce823821063188d7e46c41d371eebd5"
|
||||
dependencies = [
|
||||
"rustc-std-workspace-core",
|
||||
"rustc-std-workspace-std",
|
||||
"unicode-width",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "gimli"
|
||||
version = "0.31.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f"
|
||||
dependencies = [
|
||||
"compiler_builtins",
|
||||
"rustc-std-workspace-alloc",
|
||||
"rustc-std-workspace-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hashbrown"
|
||||
version = "0.15.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "84b26c544d002229e640969970a2e74021aadf6e2f96372b9c58eff97de08eb3"
|
||||
dependencies = [
|
||||
"compiler_builtins",
|
||||
"rustc-std-workspace-alloc",
|
||||
"rustc-std-workspace-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hermit-abi"
|
||||
version = "0.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f154ce46856750ed433c8649605bf7ed2de3bc35fd9d2a9f30cddd873c80cb08"
|
||||
dependencies = [
|
||||
"compiler_builtins",
|
||||
"rustc-std-workspace-alloc",
|
||||
"rustc-std-workspace-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.172"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d750af042f7ef4f724306de029d18836c26c1765a54a6a3f094cbd23a7267ffa"
|
||||
dependencies = [
|
||||
"rustc-std-workspace-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "memchr"
|
||||
version = "2.7.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3"
|
||||
dependencies = [
|
||||
"compiler_builtins",
|
||||
"rustc-std-workspace-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "miniz_oxide"
|
||||
version = "0.8.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3be647b768db090acb35d5ec5db2b0e1f1de11133ca123b9eacf5137868f892a"
|
||||
dependencies = [
|
||||
"adler2",
|
||||
"compiler_builtins",
|
||||
"rustc-std-workspace-alloc",
|
||||
"rustc-std-workspace-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "object"
|
||||
version = "0.36.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "62948e14d923ea95ea2c7c86c71013138b66525b86bdc08d2dcc262bdb497b87"
|
||||
dependencies = [
|
||||
"compiler_builtins",
|
||||
"memchr",
|
||||
"rustc-std-workspace-alloc",
|
||||
"rustc-std-workspace-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "panic_abort"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"alloc",
|
||||
"compiler_builtins",
|
||||
"core",
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "panic_unwind"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"alloc",
|
||||
"cfg-if",
|
||||
"compiler_builtins",
|
||||
"core",
|
||||
"libc",
|
||||
"unwind",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc_macro"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"core",
|
||||
"rustc-literal-escaper",
|
||||
"std",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "profiler_builtins"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"cc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "r-efi"
|
||||
version = "5.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "74765f6d916ee2faa39bc8e68e4f3ed8949b48cccdac59983d287a7cb71ce9c5"
|
||||
dependencies = [
|
||||
"compiler_builtins",
|
||||
"rustc-std-workspace-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "r-efi-alloc"
|
||||
version = "2.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e43c53ff1a01d423d1cb762fd991de07d32965ff0ca2e4f80444ac7804198203"
|
||||
dependencies = [
|
||||
"compiler_builtins",
|
||||
"r-efi",
|
||||
"rustc-std-workspace-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand"
|
||||
version = "0.9.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9fbfd9d094a40bf3ae768db9361049ace4c0e04a4fd6b359518bd7b73a73dd97"
|
||||
dependencies = [
|
||||
"rand_core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_core"
|
||||
version = "0.9.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38"
|
||||
|
||||
[[package]]
|
||||
name = "rand_xorshift"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "513962919efc330f829edb2535844d1b912b0fbe2ca165d613e4e8788bb05a5a"
|
||||
dependencies = [
|
||||
"rand_core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustc-demangle"
|
||||
version = "0.1.24"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f"
|
||||
dependencies = [
|
||||
"compiler_builtins",
|
||||
"rustc-std-workspace-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustc-literal-escaper"
|
||||
version = "0.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0041b6238913c41fe704213a4a9329e2f685a156d1781998128b4149c230ad04"
|
||||
dependencies = [
|
||||
"rustc-std-workspace-std",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustc-std-workspace-alloc"
|
||||
version = "1.99.0"
|
||||
dependencies = [
|
||||
"alloc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustc-std-workspace-core"
|
||||
version = "1.99.0"
|
||||
dependencies = [
|
||||
"core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustc-std-workspace-std"
|
||||
version = "1.99.0"
|
||||
dependencies = [
|
||||
"std",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "shlex"
|
||||
version = "1.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
|
||||
|
||||
[[package]]
|
||||
name = "std"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"addr2line",
|
||||
"alloc",
|
||||
"cfg-if",
|
||||
"compiler_builtins",
|
||||
"core",
|
||||
"dlmalloc",
|
||||
"fortanix-sgx-abi",
|
||||
"hashbrown",
|
||||
"hermit-abi",
|
||||
"libc",
|
||||
"miniz_oxide",
|
||||
"object",
|
||||
"panic_abort",
|
||||
"panic_unwind",
|
||||
"r-efi",
|
||||
"r-efi-alloc",
|
||||
"rand",
|
||||
"rand_xorshift",
|
||||
"rustc-demangle",
|
||||
"std_detect",
|
||||
"unwind",
|
||||
"wasi",
|
||||
"windows-targets 0.0.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "std_detect"
|
||||
version = "0.1.5"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"compiler_builtins",
|
||||
"libc",
|
||||
"rustc-std-workspace-alloc",
|
||||
"rustc-std-workspace-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sysroot"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"proc_macro",
|
||||
"profiler_builtins",
|
||||
"std",
|
||||
"test",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "test"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"core",
|
||||
"getopts",
|
||||
"libc",
|
||||
"std",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unicode-width"
|
||||
version = "0.1.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af"
|
||||
dependencies = [
|
||||
"compiler_builtins",
|
||||
"rustc-std-workspace-core",
|
||||
"rustc-std-workspace-std",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unwind"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"compiler_builtins",
|
||||
"core",
|
||||
"libc",
|
||||
"unwinding",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unwinding"
|
||||
version = "0.2.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8393f2782b6060a807337ff353780c1ca15206f9ba2424df18cb6e733bd7b345"
|
||||
dependencies = [
|
||||
"compiler_builtins",
|
||||
"gimli",
|
||||
"rustc-std-workspace-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasi"
|
||||
version = "0.11.0+wasi-snapshot-preview1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
|
||||
dependencies = [
|
||||
"compiler_builtins",
|
||||
"rustc-std-workspace-alloc",
|
||||
"rustc-std-workspace-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-sys"
|
||||
version = "0.59.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b"
|
||||
dependencies = [
|
||||
"windows-targets 0.52.6",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-targets"
|
||||
version = "0.0.0"
|
||||
|
||||
[[package]]
|
||||
name = "windows-targets"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973"
|
||||
dependencies = [
|
||||
"windows_aarch64_gnullvm",
|
||||
"windows_aarch64_msvc",
|
||||
"windows_i686_gnu",
|
||||
"windows_i686_gnullvm",
|
||||
"windows_i686_msvc",
|
||||
"windows_x86_64_gnu",
|
||||
"windows_x86_64_gnullvm",
|
||||
"windows_x86_64_msvc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_gnullvm"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3"
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_msvc"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_gnu"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_gnullvm"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_msvc"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnu"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnullvm"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_msvc"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
|
||||
|
|
@ -1,39 +0,0 @@
|
|||
[package]
|
||||
authors = ["rustc_codegen_gcc devs"]
|
||||
name = "sysroot"
|
||||
version = "0.0.0"
|
||||
resolver = "2"
|
||||
|
||||
[dependencies]
|
||||
core = { path = "./sysroot_src/library/core" }
|
||||
compiler_builtins = { path = "./sysroot_src/library/compiler-builtins/compiler-builtins" }
|
||||
alloc = { path = "./sysroot_src/library/alloc" }
|
||||
std = { path = "./sysroot_src/library/std", features = ["panic_unwind", "backtrace"] }
|
||||
test = { path = "./sysroot_src/library/test" }
|
||||
proc_macro = { path = "./sysroot_src/library/proc_macro" }
|
||||
|
||||
[patch.crates-io]
|
||||
rustc-std-workspace-core = { path = "./sysroot_src/library/rustc-std-workspace-core" }
|
||||
rustc-std-workspace-alloc = { path = "./sysroot_src/library/rustc-std-workspace-alloc" }
|
||||
rustc-std-workspace-std = { path = "./sysroot_src/library/rustc-std-workspace-std" }
|
||||
compiler_builtins = { path = "./sysroot_src/library/compiler-builtins/compiler-builtins" }
|
||||
|
||||
# For compiler-builtins we always use a high number of codegen units.
|
||||
# The goal here is to place every single intrinsic into its own object
|
||||
# file to avoid symbol clashes with the system libgcc if possible. Note
|
||||
# that this number doesn't actually produce this many object files, we
|
||||
# just don't create more than this number of object files.
|
||||
#
|
||||
# It's a bit of a bummer that we have to pass this here, unfortunately.
|
||||
# Ideally this would be specified through an env var to Cargo so Cargo
|
||||
# knows how many CGUs are for this specific crate, but for now
|
||||
# per-crate configuration isn't specifiable in the environment.
|
||||
[profile.dev.package.compiler_builtins]
|
||||
codegen-units = 10000
|
||||
|
||||
[profile.release.package.compiler_builtins]
|
||||
codegen-units = 10000
|
||||
|
||||
[profile.release]
|
||||
debug = "limited"
|
||||
#lto = "fat" # TODO(antoyo): re-enable when the failing LTO tests regarding proc-macros are fixed.
|
||||
|
|
@ -1 +0,0 @@
|
|||
#![no_std]
|
||||
|
|
@ -5,7 +5,7 @@ use std::path::Path;
|
|||
|
||||
use crate::config::{Channel, ConfigInfo};
|
||||
use crate::utils::{
|
||||
copy_file, create_dir, get_sysroot_dir, run_command, run_command_with_output_and_env, walk_dir,
|
||||
create_dir, get_sysroot_dir, run_command, run_command_with_output_and_env, walk_dir,
|
||||
};
|
||||
|
||||
#[derive(Default)]
|
||||
|
|
@ -53,11 +53,11 @@ impl BuildArg {
|
|||
}
|
||||
}
|
||||
|
||||
fn cleanup_sysroot_previous_build(start_dir: &Path) {
|
||||
fn cleanup_sysroot_previous_build(library_dir: &Path) {
|
||||
// Cleanup for previous run
|
||||
// Clean target dir except for build scripts and incremental cache
|
||||
let _ = walk_dir(
|
||||
start_dir.join("target"),
|
||||
library_dir.join("target"),
|
||||
&mut |dir: &Path| {
|
||||
for top in &["debug", "release"] {
|
||||
let _ = fs::remove_dir_all(dir.join(top).join("build"));
|
||||
|
|
@ -95,31 +95,13 @@ fn cleanup_sysroot_previous_build(start_dir: &Path) {
|
|||
&mut |_| Ok(()),
|
||||
false,
|
||||
);
|
||||
|
||||
let _ = fs::remove_file(start_dir.join("Cargo.lock"));
|
||||
let _ = fs::remove_file(start_dir.join("test_target/Cargo.lock"));
|
||||
let _ = fs::remove_dir_all(start_dir.join("sysroot"));
|
||||
}
|
||||
|
||||
pub fn create_build_sysroot_content(start_dir: &Path) -> Result<(), String> {
|
||||
if !start_dir.is_dir() {
|
||||
create_dir(start_dir)?;
|
||||
}
|
||||
copy_file("build_system/build_sysroot/Cargo.toml", start_dir.join("Cargo.toml"))?;
|
||||
copy_file("build_system/build_sysroot/Cargo.lock", start_dir.join("Cargo.lock"))?;
|
||||
|
||||
let src_dir = start_dir.join("src");
|
||||
if !src_dir.is_dir() {
|
||||
create_dir(&src_dir)?;
|
||||
}
|
||||
copy_file("build_system/build_sysroot/lib.rs", start_dir.join("src/lib.rs"))
|
||||
}
|
||||
|
||||
pub fn build_sysroot(env: &HashMap<String, String>, config: &ConfigInfo) -> Result<(), String> {
|
||||
let start_dir = get_sysroot_dir();
|
||||
|
||||
cleanup_sysroot_previous_build(&start_dir);
|
||||
create_build_sysroot_content(&start_dir)?;
|
||||
let library_dir = start_dir.join("sysroot_src").join("library");
|
||||
cleanup_sysroot_previous_build(&library_dir);
|
||||
|
||||
// Builds libs
|
||||
let mut rustflags = env.get("RUSTFLAGS").cloned().unwrap_or_default();
|
||||
|
|
@ -157,9 +139,13 @@ pub fn build_sysroot(env: &HashMap<String, String>, config: &ConfigInfo) -> Resu
|
|||
rustflags.push_str(&cg_rustflags);
|
||||
}
|
||||
|
||||
args.push(&"--features");
|
||||
args.push(&"backtrace");
|
||||
|
||||
let mut env = env.clone();
|
||||
env.insert("RUSTFLAGS".to_string(), rustflags);
|
||||
run_command_with_output_and_env(&args, Some(&start_dir), Some(&env))?;
|
||||
let sysroot_dir = library_dir.join("sysroot");
|
||||
run_command_with_output_and_env(&args, Some(&sysroot_dir), Some(&env))?;
|
||||
|
||||
// Copy files to sysroot
|
||||
let sysroot_path = start_dir.join(format!("sysroot/lib/rustlib/{}/lib/", config.target_triple));
|
||||
|
|
@ -169,7 +155,7 @@ pub fn build_sysroot(env: &HashMap<String, String>, config: &ConfigInfo) -> Resu
|
|||
run_command(&[&"cp", &"-r", &dir_to_copy, &sysroot_path], None).map(|_| ())
|
||||
};
|
||||
walk_dir(
|
||||
start_dir.join(format!("target/{}/{}/deps", config.target_triple, channel)),
|
||||
library_dir.join(format!("target/{}/{}/deps", config.target_triple, channel)),
|
||||
&mut copier.clone(),
|
||||
&mut copier,
|
||||
false,
|
||||
|
|
@ -178,7 +164,7 @@ pub fn build_sysroot(env: &HashMap<String, String>, config: &ConfigInfo) -> Resu
|
|||
// Copy the source files to the sysroot (Rust for Linux needs this).
|
||||
let sysroot_src_path = start_dir.join("sysroot/lib/rustlib/src/rust");
|
||||
create_dir(&sysroot_src_path)?;
|
||||
run_command(&[&"cp", &"-r", &start_dir.join("sysroot_src/library/"), &sysroot_src_path], None)?;
|
||||
run_command(&[&"cp", &"-r", &library_dir, &sysroot_src_path], None)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
|||
|
|
@ -352,11 +352,6 @@ impl ConfigInfo {
|
|||
None => return Err("no host found".to_string()),
|
||||
};
|
||||
|
||||
if self.target_triple.is_empty()
|
||||
&& let Some(overwrite) = env.get("OVERWRITE_TARGET_TRIPLE")
|
||||
{
|
||||
self.target_triple = overwrite.clone();
|
||||
}
|
||||
if self.target_triple.is_empty() {
|
||||
self.target_triple = self.host_triple.clone();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -303,19 +303,6 @@ pub fn create_dir<P: AsRef<Path>>(path: P) -> Result<(), String> {
|
|||
})
|
||||
}
|
||||
|
||||
pub fn copy_file<F: AsRef<Path>, T: AsRef<Path>>(from: F, to: T) -> Result<(), String> {
|
||||
fs::copy(&from, &to)
|
||||
.map_err(|error| {
|
||||
format!(
|
||||
"Failed to copy file `{}` into `{}`: {:?}",
|
||||
from.as_ref().display(),
|
||||
to.as_ref().display(),
|
||||
error
|
||||
)
|
||||
})
|
||||
.map(|_| ())
|
||||
}
|
||||
|
||||
/// This function differs from `git_clone` in how it handles *where* the repository will be cloned.
|
||||
/// In `git_clone`, it is cloned in the provided path. In this function, the path you provide is
|
||||
/// the parent folder. So if you pass "a" as folder and try to clone "b.git", it will be cloned into
|
||||
|
|
|
|||
|
|
@ -62,14 +62,14 @@ generate it in [gimple.md](./doc/gimple.md).
|
|||
|
||||
* Run `./y.sh prepare --cross` so that the sysroot is patched for the cross-compiling case.
|
||||
* Set the path to the cross-compiling libgccjit in `gcc-path` (in `config.toml`).
|
||||
* Make sure you have the linker for your target (for instance `m68k-unknown-linux-gnu-gcc`) in your `$PATH`. Currently, the linker name is hardcoded as being `$TARGET-gcc`. Specify the target when building the sysroot: `./y.sh build --sysroot --target-triple m68k-unknown-linux-gnu`.
|
||||
* Build your project by specifying the target: `OVERWRITE_TARGET_TRIPLE=m68k-unknown-linux-gnu ../y.sh cargo build --target m68k-unknown-linux-gnu`.
|
||||
* Make sure you have the linker for your target (for instance `m68k-unknown-linux-gnu-gcc`) in your `$PATH`. You can specify which linker to use via `CG_RUSTFLAGS="-Clinker=<linker>"`, for instance: `CG_RUSTFLAGS="-Clinker=m68k-unknown-linux-gnu-gcc"`. Specify the target when building the sysroot: `./y.sh build --sysroot --target-triple m68k-unknown-linux-gnu`.
|
||||
* Build your project by specifying the target and the linker to use: `CG_RUSTFLAGS="-Clinker=m68k-unknown-linux-gnu-gcc" ../y.sh cargo build --target m68k-unknown-linux-gnu`.
|
||||
|
||||
If the target is not yet supported by the Rust compiler, create a [target specification file](https://docs.rust-embedded.org/embedonomicon/custom-target.html) (note that the `arch` specified in this file must be supported by the rust compiler).
|
||||
Then, you can use it the following way:
|
||||
|
||||
* Add the target specification file using `--target` as an **absolute** path to build the sysroot: `./y.sh build --sysroot --target-triple m68k-unknown-linux-gnu --target $(pwd)/m68k-unknown-linux-gnu.json`
|
||||
* Build your project by specifying the target specification file: `OVERWRITE_TARGET_TRIPLE=m68k-unknown-linux-gnu ../y.sh cargo build --target path/to/m68k-unknown-linux-gnu.json`.
|
||||
* Build your project by specifying the target specification file: `../y.sh cargo build --target path/to/m68k-unknown-linux-gnu.json`.
|
||||
|
||||
If you get the following error:
|
||||
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
)]
|
||||
#![no_core]
|
||||
#![allow(dead_code, internal_features, non_camel_case_types)]
|
||||
#![rustfmt::skip]
|
||||
#![rustfmt_skip]
|
||||
|
||||
extern crate mini_core;
|
||||
|
||||
|
|
@ -198,10 +198,17 @@ fn main() {
|
|||
assert_eq!(intrinsics::align_of::<u16>() as u8, 2);
|
||||
assert_eq!(intrinsics::align_of_val(&a) as u8, intrinsics::align_of::<&str>() as u8);
|
||||
|
||||
assert!(!const { intrinsics::needs_drop::<u8>() });
|
||||
assert!(!const { intrinsics::needs_drop::<[u8]>() });
|
||||
assert!(const { intrinsics::needs_drop::<NoisyDrop>() });
|
||||
assert!(const { intrinsics::needs_drop::<NoisyDropUnsized>() });
|
||||
/*
|
||||
* TODO: re-enable in the next sync.
|
||||
let u8_needs_drop = const { intrinsics::needs_drop::<u8>() };
|
||||
assert!(!u8_needs_drop);
|
||||
let slice_needs_drop = const { intrinsics::needs_drop::<[u8]>() };
|
||||
assert!(!slice_needs_drop);
|
||||
let noisy_drop = const { intrinsics::needs_drop::<NoisyDrop>() };
|
||||
assert!(noisy_drop);
|
||||
let noisy_unsized_drop = const { intrinsics::needs_drop::<NoisyDropUnsized>() };
|
||||
assert!(noisy_unsized_drop);
|
||||
*/
|
||||
|
||||
Unique {
|
||||
pointer: 0 as *const &str,
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
[toolchain]
|
||||
channel = "nightly-2025-06-28"
|
||||
channel = "nightly-2025-07-04"
|
||||
components = ["rust-src", "rustc-dev", "llvm-tools-preview"]
|
||||
|
|
|
|||
|
|
@ -87,7 +87,7 @@ pub fn from_fn_attrs<'gcc, 'tcx>(
|
|||
#[cfg_attr(not(feature = "master"), allow(unused_variables))] func: Function<'gcc>,
|
||||
instance: ty::Instance<'tcx>,
|
||||
) {
|
||||
let codegen_fn_attrs = cx.tcx.codegen_fn_attrs(instance.def_id());
|
||||
let codegen_fn_attrs = cx.tcx.codegen_instance_attrs(instance.def);
|
||||
|
||||
#[cfg(feature = "master")]
|
||||
{
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ use std::sync::Arc;
|
|||
|
||||
use gccjit::{Context, OutputKind};
|
||||
use object::read::archive::ArchiveFile;
|
||||
use rustc_codegen_ssa::back::lto::{LtoModuleCodegen, SerializedModule, ThinModule, ThinShared};
|
||||
use rustc_codegen_ssa::back::lto::{SerializedModule, ThinModule, ThinShared};
|
||||
use rustc_codegen_ssa::back::symbol_export;
|
||||
use rustc_codegen_ssa::back::write::{CodegenContext, FatLtoInput};
|
||||
use rustc_codegen_ssa::traits::*;
|
||||
|
|
@ -176,7 +176,7 @@ pub(crate) fn run_fat(
|
|||
cgcx: &CodegenContext<GccCodegenBackend>,
|
||||
modules: Vec<FatLtoInput<GccCodegenBackend>>,
|
||||
cached_modules: Vec<(SerializedModule<ModuleBuffer>, WorkProduct)>,
|
||||
) -> Result<LtoModuleCodegen<GccCodegenBackend>, FatalError> {
|
||||
) -> Result<ModuleCodegen<GccContext>, FatalError> {
|
||||
let dcx = cgcx.create_dcx();
|
||||
let dcx = dcx.handle();
|
||||
let lto_data = prepare_lto(cgcx, dcx)?;
|
||||
|
|
@ -201,7 +201,7 @@ fn fat_lto(
|
|||
mut serialized_modules: Vec<(SerializedModule<ModuleBuffer>, CString)>,
|
||||
tmp_path: TempDir,
|
||||
//symbols_below_threshold: &[String],
|
||||
) -> Result<LtoModuleCodegen<GccCodegenBackend>, FatalError> {
|
||||
) -> Result<ModuleCodegen<GccContext>, FatalError> {
|
||||
let _timer = cgcx.prof.generic_activity("GCC_fat_lto_build_monolithic_module");
|
||||
info!("going for a fat lto");
|
||||
|
||||
|
|
@ -334,7 +334,7 @@ fn fat_lto(
|
|||
// of now.
|
||||
module.module_llvm.temp_dir = Some(tmp_path);
|
||||
|
||||
Ok(LtoModuleCodegen::Fat(module))
|
||||
Ok(module)
|
||||
}
|
||||
|
||||
pub struct ModuleBuffer(PathBuf);
|
||||
|
|
@ -358,7 +358,7 @@ pub(crate) fn run_thin(
|
|||
cgcx: &CodegenContext<GccCodegenBackend>,
|
||||
modules: Vec<(String, ThinBuffer)>,
|
||||
cached_modules: Vec<(SerializedModule<ModuleBuffer>, WorkProduct)>,
|
||||
) -> Result<(Vec<LtoModuleCodegen<GccCodegenBackend>>, Vec<WorkProduct>), FatalError> {
|
||||
) -> Result<(Vec<ThinModule<GccCodegenBackend>>, Vec<WorkProduct>), FatalError> {
|
||||
let dcx = cgcx.create_dcx();
|
||||
let dcx = dcx.handle();
|
||||
let lto_data = prepare_lto(cgcx, dcx)?;
|
||||
|
|
@ -427,7 +427,7 @@ fn thin_lto(
|
|||
tmp_path: TempDir,
|
||||
cached_modules: Vec<(SerializedModule<ModuleBuffer>, WorkProduct)>,
|
||||
//_symbols_below_threshold: &[String],
|
||||
) -> Result<(Vec<LtoModuleCodegen<GccCodegenBackend>>, Vec<WorkProduct>), FatalError> {
|
||||
) -> Result<(Vec<ThinModule<GccCodegenBackend>>, Vec<WorkProduct>), FatalError> {
|
||||
let _timer = cgcx.prof.generic_activity("LLVM_thin_lto_global_analysis");
|
||||
info!("going for that thin, thin LTO");
|
||||
|
||||
|
|
@ -573,8 +573,7 @@ fn thin_lto(
|
|||
}*/
|
||||
|
||||
info!(" - {}: re-compiled", module_name);
|
||||
opt_jobs
|
||||
.push(LtoModuleCodegen::Thin(ThinModule { shared: shared.clone(), idx: module_index }));
|
||||
opt_jobs.push(ThinModule { shared: shared.clone(), idx: module_index });
|
||||
}
|
||||
|
||||
// Save the current ThinLTO import information for the next compilation
|
||||
|
|
|
|||
|
|
@ -16,10 +16,12 @@ use crate::{GccCodegenBackend, GccContext};
|
|||
|
||||
pub(crate) fn codegen(
|
||||
cgcx: &CodegenContext<GccCodegenBackend>,
|
||||
dcx: DiagCtxtHandle<'_>,
|
||||
module: ModuleCodegen<GccContext>,
|
||||
config: &ModuleConfig,
|
||||
) -> Result<CompiledModule, FatalError> {
|
||||
let dcx = cgcx.create_dcx();
|
||||
let dcx = dcx.handle();
|
||||
|
||||
let _timer = cgcx.prof.generic_activity_with_arg("GCC_module_codegen", &*module.name);
|
||||
{
|
||||
let context = &module.module_llvm.context;
|
||||
|
|
|
|||
|
|
@ -971,7 +971,11 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
|
|||
|
||||
fn volatile_load(&mut self, ty: Type<'gcc>, ptr: RValue<'gcc>) -> RValue<'gcc> {
|
||||
let ptr = self.context.new_cast(self.location, ptr, ty.make_volatile().make_pointer());
|
||||
ptr.dereference(self.location).to_rvalue()
|
||||
// (FractalFir): We insert a local here, to ensure this volatile load can't move across
|
||||
// blocks.
|
||||
let local = self.current_func().new_local(self.location, ty, "volatile_tmp");
|
||||
self.block.add_assignment(self.location, local, ptr.dereference(self.location).to_rvalue());
|
||||
local.to_rvalue()
|
||||
}
|
||||
|
||||
fn atomic_load(
|
||||
|
|
|
|||
|
|
@ -105,7 +105,7 @@ pub fn get_fn<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, instance: Instance<'tcx>)
|
|||
let is_hidden = if is_generic {
|
||||
// This is a monomorphization of a generic function.
|
||||
if !(cx.tcx.sess.opts.share_generics()
|
||||
|| tcx.codegen_fn_attrs(instance_def_id).inline
|
||||
|| tcx.codegen_instance_attrs(instance.def).inline
|
||||
== rustc_attr_data_structures::InlineAttr::Never)
|
||||
{
|
||||
// When not sharing generics, all instances are in the same
|
||||
|
|
|
|||
|
|
@ -93,7 +93,7 @@ use gccjit::{CType, Context, OptimizationLevel};
|
|||
use gccjit::{TargetInfo, Version};
|
||||
use rustc_ast::expand::allocator::AllocatorKind;
|
||||
use rustc_ast::expand::autodiff_attrs::AutoDiffItem;
|
||||
use rustc_codegen_ssa::back::lto::{LtoModuleCodegen, SerializedModule, ThinModule};
|
||||
use rustc_codegen_ssa::back::lto::{SerializedModule, ThinModule};
|
||||
use rustc_codegen_ssa::back::write::{
|
||||
CodegenContext, FatLtoInput, ModuleConfig, TargetMachineFactoryFn,
|
||||
};
|
||||
|
|
@ -273,6 +273,10 @@ fn new_context<'gcc, 'tcx>(tcx: TyCtxt<'tcx>) -> Context<'gcc> {
|
|||
}
|
||||
|
||||
impl ExtraBackendMethods for GccCodegenBackend {
|
||||
fn supports_parallel(&self) -> bool {
|
||||
false
|
||||
}
|
||||
|
||||
fn codegen_allocator(
|
||||
&self,
|
||||
tcx: TyCtxt<'_>,
|
||||
|
|
@ -341,8 +345,7 @@ impl Deref for SyncContext {
|
|||
}
|
||||
|
||||
unsafe impl Send for SyncContext {}
|
||||
// FIXME(antoyo): that shouldn't be Sync. Parallel compilation is currently disabled with "-Zno-parallel-llvm".
|
||||
// TODO: disable it here by returning false in CodegenBackend::supports_parallel().
|
||||
// FIXME(antoyo): that shouldn't be Sync. Parallel compilation is currently disabled with "CodegenBackend::supports_parallel()".
|
||||
unsafe impl Sync for SyncContext {}
|
||||
|
||||
impl WriteBackendMethods for GccCodegenBackend {
|
||||
|
|
@ -353,11 +356,16 @@ impl WriteBackendMethods for GccCodegenBackend {
|
|||
type ThinData = ThinData;
|
||||
type ThinBuffer = ThinBuffer;
|
||||
|
||||
fn run_fat_lto(
|
||||
fn run_and_optimize_fat_lto(
|
||||
cgcx: &CodegenContext<Self>,
|
||||
modules: Vec<FatLtoInput<Self>>,
|
||||
cached_modules: Vec<(SerializedModule<Self::ModuleBuffer>, WorkProduct)>,
|
||||
) -> Result<LtoModuleCodegen<Self>, FatalError> {
|
||||
diff_fncs: Vec<AutoDiffItem>,
|
||||
) -> Result<ModuleCodegen<Self::Module>, FatalError> {
|
||||
if !diff_fncs.is_empty() {
|
||||
unimplemented!();
|
||||
}
|
||||
|
||||
back::lto::run_fat(cgcx, modules, cached_modules)
|
||||
}
|
||||
|
||||
|
|
@ -365,7 +373,7 @@ impl WriteBackendMethods for GccCodegenBackend {
|
|||
cgcx: &CodegenContext<Self>,
|
||||
modules: Vec<(String, Self::ThinBuffer)>,
|
||||
cached_modules: Vec<(SerializedModule<Self::ModuleBuffer>, WorkProduct)>,
|
||||
) -> Result<(Vec<LtoModuleCodegen<Self>>, Vec<WorkProduct>), FatalError> {
|
||||
) -> Result<(Vec<ThinModule<Self>>, Vec<WorkProduct>), FatalError> {
|
||||
back::lto::run_thin(cgcx, modules, cached_modules)
|
||||
}
|
||||
|
||||
|
|
@ -387,14 +395,6 @@ impl WriteBackendMethods for GccCodegenBackend {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn optimize_fat(
|
||||
_cgcx: &CodegenContext<Self>,
|
||||
_module: &mut ModuleCodegen<Self::Module>,
|
||||
) -> Result<(), FatalError> {
|
||||
// TODO(antoyo)
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn optimize_thin(
|
||||
cgcx: &CodegenContext<Self>,
|
||||
thin: ThinModule<Self>,
|
||||
|
|
@ -404,11 +404,10 @@ impl WriteBackendMethods for GccCodegenBackend {
|
|||
|
||||
fn codegen(
|
||||
cgcx: &CodegenContext<Self>,
|
||||
dcx: DiagCtxtHandle<'_>,
|
||||
module: ModuleCodegen<Self::Module>,
|
||||
config: &ModuleConfig,
|
||||
) -> Result<CompiledModule, FatalError> {
|
||||
back::write::codegen(cgcx, dcx, module, config)
|
||||
back::write::codegen(cgcx, module, config)
|
||||
}
|
||||
|
||||
fn prepare_thin(
|
||||
|
|
@ -429,15 +428,6 @@ impl WriteBackendMethods for GccCodegenBackend {
|
|||
) -> Result<ModuleCodegen<Self::Module>, FatalError> {
|
||||
back::write::link(cgcx, dcx, modules)
|
||||
}
|
||||
|
||||
fn autodiff(
|
||||
_cgcx: &CodegenContext<Self>,
|
||||
_module: &ModuleCodegen<Self::Module>,
|
||||
_diff_functions: Vec<AutoDiffItem>,
|
||||
_config: &ModuleConfig,
|
||||
) -> Result<(), FatalError> {
|
||||
unimplemented!()
|
||||
}
|
||||
}
|
||||
|
||||
/// This is the entrypoint for a hot plugged rustc_codegen_gccjit
|
||||
|
|
|
|||
|
|
@ -53,7 +53,7 @@ impl<'gcc, 'tcx> PreDefineCodegenMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
|
|||
let fn_abi = self.fn_abi_of_instance(instance, ty::List::empty());
|
||||
self.linkage.set(base::linkage_to_gcc(linkage));
|
||||
let decl = self.declare_fn(symbol_name, fn_abi);
|
||||
//let attrs = self.tcx.codegen_fn_attrs(instance.def_id());
|
||||
//let attrs = self.tcx.codegen_instance_attrs(instance.def);
|
||||
|
||||
attributes::from_fn_attrs(self, decl, instance);
|
||||
|
||||
|
|
@ -64,7 +64,7 @@ impl<'gcc, 'tcx> PreDefineCodegenMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
|
|||
if linkage != Linkage::Internal && self.tcx.is_compiler_builtins(LOCAL_CRATE) {
|
||||
#[cfg(feature = "master")]
|
||||
decl.add_attribute(FnAttribute::Visibility(gccjit::Visibility::Hidden));
|
||||
} else {
|
||||
} else if visibility != Visibility::Default {
|
||||
#[cfg(feature = "master")]
|
||||
decl.add_attribute(FnAttribute::Visibility(base::visibility_to_gcc(visibility)));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -80,3 +80,5 @@ tests/ui/uninhabited/uninhabited-transparent-return-abi.rs
|
|||
tests/ui/coroutine/panic-drops-resume.rs
|
||||
tests/ui/coroutine/panic-drops.rs
|
||||
tests/ui/coroutine/panic-safe.rs
|
||||
tests/ui/process/nofile-limit.rs
|
||||
tests/ui/simd/intrinsic/generic-arithmetic-pass.rs
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@ add_asm:
|
|||
ret"
|
||||
);
|
||||
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
extern "C" {
|
||||
fn add_asm(a: i64, b: i64) -> i64;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,8 +3,6 @@
|
|||
// Run-time:
|
||||
// status: 0
|
||||
|
||||
#![feature(const_black_box)]
|
||||
|
||||
fn main() {
|
||||
use std::hint::black_box;
|
||||
|
||||
|
|
@ -15,14 +13,14 @@ fn main() {
|
|||
}};
|
||||
}
|
||||
|
||||
check!(i32, (black_box(0.0f32) as i32));
|
||||
check!(i32, black_box(0.0f32) as i32);
|
||||
|
||||
check!(u64, (black_box(f32::NAN) as u64));
|
||||
check!(u128, (black_box(f32::NAN) as u128));
|
||||
check!(u64, black_box(f32::NAN) as u64);
|
||||
check!(u128, black_box(f32::NAN) as u128);
|
||||
|
||||
check!(i64, (black_box(f64::NAN) as i64));
|
||||
check!(u64, (black_box(f64::NAN) as u64));
|
||||
check!(i64, black_box(f64::NAN) as i64);
|
||||
check!(u64, black_box(f64::NAN) as u64);
|
||||
|
||||
check!(i16, (black_box(f32::MIN) as i16));
|
||||
check!(i16, (black_box(f32::MAX) as i16));
|
||||
check!(i16, black_box(f32::MIN) as i16);
|
||||
check!(i16, black_box(f32::MAX) as i16);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,8 +3,6 @@
|
|||
// Run-time:
|
||||
// status: 0
|
||||
|
||||
#![feature(const_black_box)]
|
||||
|
||||
fn main() {
|
||||
use std::hint::black_box;
|
||||
|
||||
|
|
|
|||
|
|
@ -5,13 +5,14 @@
|
|||
|
||||
use std::mem::MaybeUninit;
|
||||
|
||||
#[allow(dead_code)]
|
||||
#[derive(Debug)]
|
||||
struct Struct {
|
||||
pointer: *const (),
|
||||
func: unsafe fn(*const ()),
|
||||
}
|
||||
|
||||
fn func(ptr: *const ()) {
|
||||
fn func(_ptr: *const ()) {
|
||||
}
|
||||
|
||||
fn main() {
|
||||
|
|
|
|||
|
|
@ -6,8 +6,6 @@
|
|||
mod libc {
|
||||
#[link(name = "c")]
|
||||
extern "C" {
|
||||
pub fn puts(s: *const u8) -> i32;
|
||||
|
||||
pub fn sigaction(signum: i32, act: *const sigaction, oldact: *mut sigaction) -> i32;
|
||||
pub fn mmap(addr: *mut (), len: usize, prot: i32, flags: i32, fd: i32, offset: i64) -> *mut ();
|
||||
pub fn mprotect(addr: *mut (), len: usize, prot: i32) -> i32;
|
||||
|
|
@ -61,7 +59,7 @@ fn main() {
|
|||
panic!("error: mmap failed");
|
||||
}
|
||||
|
||||
let p_count = (&mut COUNT) as *mut u32;
|
||||
let p_count = (&raw mut COUNT) as *mut u32;
|
||||
p_count.write_volatile(0);
|
||||
|
||||
// Trigger segfaults
|
||||
|
|
@ -94,7 +92,7 @@ fn main() {
|
|||
}
|
||||
|
||||
unsafe extern "C" fn segv_handler(_: i32, _: *mut (), _: *mut ()) {
|
||||
let p_count = (&mut COUNT) as *mut u32;
|
||||
let p_count = (&raw mut COUNT) as *mut u32;
|
||||
p_count.write_volatile(p_count.read_volatile() + 1);
|
||||
let count = p_count.read_volatile();
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
codegen_llvm_autodiff_without_enable = using the autodiff feature requires -Z autodiff=Enable
|
||||
codegen_llvm_autodiff_without_lto = using the autodiff feature requires using fat-lto
|
||||
|
||||
codegen_llvm_copy_bitcode = failed to copy bitcode to object file: {$err}
|
||||
|
||||
|
|
|
|||
|
|
@ -344,7 +344,7 @@ pub(crate) fn llfn_attrs_from_instance<'ll, 'tcx>(
|
|||
llfn: &'ll Value,
|
||||
instance: ty::Instance<'tcx>,
|
||||
) {
|
||||
let codegen_fn_attrs = cx.tcx.codegen_fn_attrs(instance.def_id());
|
||||
let codegen_fn_attrs = cx.tcx.codegen_instance_attrs(instance.def);
|
||||
|
||||
let mut to_add = SmallVec::<[_; 16]>::new();
|
||||
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ use std::sync::Arc;
|
|||
use std::{io, iter, slice};
|
||||
|
||||
use object::read::archive::ArchiveFile;
|
||||
use rustc_codegen_ssa::back::lto::{LtoModuleCodegen, SerializedModule, ThinModule, ThinShared};
|
||||
use rustc_codegen_ssa::back::lto::{SerializedModule, ThinModule, ThinShared};
|
||||
use rustc_codegen_ssa::back::symbol_export;
|
||||
use rustc_codegen_ssa::back::write::{CodegenContext, FatLtoInput};
|
||||
use rustc_codegen_ssa::traits::*;
|
||||
|
|
@ -201,7 +201,7 @@ pub(crate) fn run_fat(
|
|||
cgcx: &CodegenContext<LlvmCodegenBackend>,
|
||||
modules: Vec<FatLtoInput<LlvmCodegenBackend>>,
|
||||
cached_modules: Vec<(SerializedModule<ModuleBuffer>, WorkProduct)>,
|
||||
) -> Result<LtoModuleCodegen<LlvmCodegenBackend>, FatalError> {
|
||||
) -> Result<ModuleCodegen<ModuleLlvm>, FatalError> {
|
||||
let dcx = cgcx.create_dcx();
|
||||
let dcx = dcx.handle();
|
||||
let (symbols_below_threshold, upstream_modules) = prepare_lto(cgcx, dcx)?;
|
||||
|
|
@ -217,7 +217,7 @@ pub(crate) fn run_thin(
|
|||
cgcx: &CodegenContext<LlvmCodegenBackend>,
|
||||
modules: Vec<(String, ThinBuffer)>,
|
||||
cached_modules: Vec<(SerializedModule<ModuleBuffer>, WorkProduct)>,
|
||||
) -> Result<(Vec<LtoModuleCodegen<LlvmCodegenBackend>>, Vec<WorkProduct>), FatalError> {
|
||||
) -> Result<(Vec<ThinModule<LlvmCodegenBackend>>, Vec<WorkProduct>), FatalError> {
|
||||
let dcx = cgcx.create_dcx();
|
||||
let dcx = dcx.handle();
|
||||
let (symbols_below_threshold, upstream_modules) = prepare_lto(cgcx, dcx)?;
|
||||
|
|
@ -248,7 +248,7 @@ fn fat_lto(
|
|||
cached_modules: Vec<(SerializedModule<ModuleBuffer>, WorkProduct)>,
|
||||
mut serialized_modules: Vec<(SerializedModule<ModuleBuffer>, CString)>,
|
||||
symbols_below_threshold: &[*const libc::c_char],
|
||||
) -> Result<LtoModuleCodegen<LlvmCodegenBackend>, FatalError> {
|
||||
) -> Result<ModuleCodegen<ModuleLlvm>, FatalError> {
|
||||
let _timer = cgcx.prof.generic_activity("LLVM_fat_lto_build_monolithic_module");
|
||||
info!("going for a fat lto");
|
||||
|
||||
|
|
@ -366,7 +366,7 @@ fn fat_lto(
|
|||
save_temp_bitcode(cgcx, &module, "lto.after-restriction");
|
||||
}
|
||||
|
||||
Ok(LtoModuleCodegen::Fat(module))
|
||||
Ok(module)
|
||||
}
|
||||
|
||||
pub(crate) struct Linker<'a>(&'a mut llvm::Linker<'a>);
|
||||
|
|
@ -436,7 +436,7 @@ fn thin_lto(
|
|||
serialized_modules: Vec<(SerializedModule<ModuleBuffer>, CString)>,
|
||||
cached_modules: Vec<(SerializedModule<ModuleBuffer>, WorkProduct)>,
|
||||
symbols_below_threshold: &[*const libc::c_char],
|
||||
) -> Result<(Vec<LtoModuleCodegen<LlvmCodegenBackend>>, Vec<WorkProduct>), FatalError> {
|
||||
) -> Result<(Vec<ThinModule<LlvmCodegenBackend>>, Vec<WorkProduct>), FatalError> {
|
||||
let _timer = cgcx.prof.generic_activity("LLVM_thin_lto_global_analysis");
|
||||
unsafe {
|
||||
info!("going for that thin, thin LTO");
|
||||
|
|
@ -568,10 +568,7 @@ fn thin_lto(
|
|||
}
|
||||
|
||||
info!(" - {}: re-compiled", module_name);
|
||||
opt_jobs.push(LtoModuleCodegen::Thin(ThinModule {
|
||||
shared: Arc::clone(&shared),
|
||||
idx: module_index,
|
||||
}));
|
||||
opt_jobs.push(ThinModule { shared: Arc::clone(&shared), idx: module_index });
|
||||
}
|
||||
|
||||
// Save the current ThinLTO import information for the next compilation
|
||||
|
|
|
|||
|
|
@ -39,6 +39,7 @@ impl OwnedTargetMachine {
|
|||
debug_info_compression: &CStr,
|
||||
use_emulated_tls: bool,
|
||||
args_cstr_buff: &[u8],
|
||||
use_wasm_eh: bool,
|
||||
) -> Result<Self, LlvmError<'static>> {
|
||||
assert!(args_cstr_buff.len() > 0);
|
||||
assert!(
|
||||
|
|
@ -72,6 +73,7 @@ impl OwnedTargetMachine {
|
|||
use_emulated_tls,
|
||||
args_cstr_buff.as_ptr() as *const c_char,
|
||||
args_cstr_buff.len(),
|
||||
use_wasm_eh,
|
||||
)
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ use rustc_codegen_ssa::back::write::{
|
|||
BitcodeSection, CodegenContext, EmitObj, ModuleConfig, TargetMachineFactoryConfig,
|
||||
TargetMachineFactoryFn,
|
||||
};
|
||||
use rustc_codegen_ssa::base::wants_wasm_eh;
|
||||
use rustc_codegen_ssa::traits::*;
|
||||
use rustc_codegen_ssa::{CompiledModule, ModuleCodegen, ModuleKind};
|
||||
use rustc_data_structures::profiling::SelfProfilerRef;
|
||||
|
|
@ -285,6 +286,8 @@ pub(crate) fn target_machine_factory(
|
|||
let file_name_display_preference =
|
||||
sess.filename_display_preference(RemapPathScopeComponents::DEBUGINFO);
|
||||
|
||||
let use_wasm_eh = wants_wasm_eh(sess);
|
||||
|
||||
Arc::new(move |config: TargetMachineFactoryConfig| {
|
||||
let path_to_cstring_helper = |path: Option<PathBuf>| -> CString {
|
||||
let path = path.unwrap_or_default();
|
||||
|
|
@ -321,6 +324,7 @@ pub(crate) fn target_machine_factory(
|
|||
&debuginfo_compression,
|
||||
use_emulated_tls,
|
||||
&args_cstr_buff,
|
||||
use_wasm_eh,
|
||||
)
|
||||
})
|
||||
}
|
||||
|
|
@ -817,10 +821,12 @@ pub(crate) fn link(
|
|||
|
||||
pub(crate) fn codegen(
|
||||
cgcx: &CodegenContext<LlvmCodegenBackend>,
|
||||
dcx: DiagCtxtHandle<'_>,
|
||||
module: ModuleCodegen<ModuleLlvm>,
|
||||
config: &ModuleConfig,
|
||||
) -> Result<CompiledModule, FatalError> {
|
||||
let dcx = cgcx.create_dcx();
|
||||
let dcx = dcx.handle();
|
||||
|
||||
let _timer = cgcx.prof.generic_activity_with_arg("LLVM_module_codegen", &*module.name);
|
||||
{
|
||||
let llmod = module.module_llvm.llmod();
|
||||
|
|
@ -879,9 +885,7 @@ pub(crate) fn codegen(
|
|||
.generic_activity_with_arg("LLVM_module_codegen_embed_bitcode", &*module.name);
|
||||
let thin_bc =
|
||||
module.thin_lto_buffer.as_deref().expect("cannot find embedded bitcode");
|
||||
unsafe {
|
||||
embed_bitcode(cgcx, llcx, llmod, &config.bc_cmdline, &thin_bc);
|
||||
}
|
||||
embed_bitcode(cgcx, llcx, llmod, &config.bc_cmdline, &thin_bc);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -945,7 +949,7 @@ pub(crate) fn codegen(
|
|||
// binaries. So we must clone the module to produce the asm output
|
||||
// if we are also producing object code.
|
||||
let llmod = if let EmitObj::ObjectCode(_) = config.emit_obj {
|
||||
unsafe { llvm::LLVMCloneModule(llmod) }
|
||||
llvm::LLVMCloneModule(llmod)
|
||||
} else {
|
||||
llmod
|
||||
};
|
||||
|
|
@ -1073,7 +1077,7 @@ pub(crate) fn bitcode_section_name(cgcx: &CodegenContext<LlvmCodegenBackend>) ->
|
|||
}
|
||||
|
||||
/// Embed the bitcode of an LLVM module for LTO in the LLVM module itself.
|
||||
unsafe fn embed_bitcode(
|
||||
fn embed_bitcode(
|
||||
cgcx: &CodegenContext<LlvmCodegenBackend>,
|
||||
llcx: &llvm::Context,
|
||||
llmod: &llvm::Module,
|
||||
|
|
@ -1115,43 +1119,40 @@ unsafe fn embed_bitcode(
|
|||
// Unfortunately, LLVM provides no way to set custom section flags. For ELF
|
||||
// and COFF we emit the sections using module level inline assembly for that
|
||||
// reason (see issue #90326 for historical background).
|
||||
unsafe {
|
||||
if cgcx.target_is_like_darwin
|
||||
|| cgcx.target_is_like_aix
|
||||
|| cgcx.target_arch == "wasm32"
|
||||
|| cgcx.target_arch == "wasm64"
|
||||
{
|
||||
// We don't need custom section flags, create LLVM globals.
|
||||
let llconst = common::bytes_in_context(llcx, bitcode);
|
||||
let llglobal =
|
||||
llvm::add_global(llmod, common::val_ty(llconst), c"rustc.embedded.module");
|
||||
llvm::set_initializer(llglobal, llconst);
|
||||
|
||||
llvm::set_section(llglobal, bitcode_section_name(cgcx));
|
||||
llvm::set_linkage(llglobal, llvm::Linkage::PrivateLinkage);
|
||||
llvm::LLVMSetGlobalConstant(llglobal, llvm::True);
|
||||
if cgcx.target_is_like_darwin
|
||||
|| cgcx.target_is_like_aix
|
||||
|| cgcx.target_arch == "wasm32"
|
||||
|| cgcx.target_arch == "wasm64"
|
||||
{
|
||||
// We don't need custom section flags, create LLVM globals.
|
||||
let llconst = common::bytes_in_context(llcx, bitcode);
|
||||
let llglobal = llvm::add_global(llmod, common::val_ty(llconst), c"rustc.embedded.module");
|
||||
llvm::set_initializer(llglobal, llconst);
|
||||
|
||||
let llconst = common::bytes_in_context(llcx, cmdline.as_bytes());
|
||||
let llglobal =
|
||||
llvm::add_global(llmod, common::val_ty(llconst), c"rustc.embedded.cmdline");
|
||||
llvm::set_initializer(llglobal, llconst);
|
||||
let section = if cgcx.target_is_like_darwin {
|
||||
c"__LLVM,__cmdline"
|
||||
} else if cgcx.target_is_like_aix {
|
||||
c".info"
|
||||
} else {
|
||||
c".llvmcmd"
|
||||
};
|
||||
llvm::set_section(llglobal, section);
|
||||
llvm::set_linkage(llglobal, llvm::Linkage::PrivateLinkage);
|
||||
llvm::set_section(llglobal, bitcode_section_name(cgcx));
|
||||
llvm::set_linkage(llglobal, llvm::Linkage::PrivateLinkage);
|
||||
llvm::LLVMSetGlobalConstant(llglobal, llvm::True);
|
||||
|
||||
let llconst = common::bytes_in_context(llcx, cmdline.as_bytes());
|
||||
let llglobal = llvm::add_global(llmod, common::val_ty(llconst), c"rustc.embedded.cmdline");
|
||||
llvm::set_initializer(llglobal, llconst);
|
||||
let section = if cgcx.target_is_like_darwin {
|
||||
c"__LLVM,__cmdline"
|
||||
} else if cgcx.target_is_like_aix {
|
||||
c".info"
|
||||
} else {
|
||||
// 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::append_module_inline_asm(llmod, &asm);
|
||||
let asm = create_section_with_flags_asm(".llvmcmd", section_flags, cmdline.as_bytes());
|
||||
llvm::append_module_inline_asm(llmod, &asm);
|
||||
}
|
||||
c".llvmcmd"
|
||||
};
|
||||
llvm::set_section(llglobal, section);
|
||||
llvm::set_linkage(llglobal, llvm::Linkage::PrivateLinkage);
|
||||
} else {
|
||||
// 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::append_module_inline_asm(llmod, &asm);
|
||||
let asm = create_section_with_flags_asm(".llvmcmd", section_flags, cmdline.as_bytes());
|
||||
llvm::append_module_inline_asm(llmod, &asm);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -302,10 +302,7 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
|
|||
return;
|
||||
}
|
||||
|
||||
let id_str = "branch_weights";
|
||||
let id = unsafe {
|
||||
llvm::LLVMMDStringInContext2(self.cx.llcx, id_str.as_ptr().cast(), id_str.len())
|
||||
};
|
||||
let id = self.cx.create_metadata(b"branch_weights");
|
||||
|
||||
// For switch instructions with 2 targets, the `llvm.expect` intrinsic is used.
|
||||
// This function handles switch instructions with more than 2 targets and it needs to
|
||||
|
|
@ -637,17 +634,16 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
|
|||
} else if place.layout.is_llvm_immediate() {
|
||||
let mut const_llval = None;
|
||||
let llty = place.layout.llvm_type(self);
|
||||
unsafe {
|
||||
if let Some(global) = llvm::LLVMIsAGlobalVariable(place.val.llval) {
|
||||
if llvm::LLVMIsGlobalConstant(global) == llvm::True {
|
||||
if let Some(init) = llvm::LLVMGetInitializer(global) {
|
||||
if self.val_ty(init) == llty {
|
||||
const_llval = Some(init);
|
||||
}
|
||||
if let Some(global) = llvm::LLVMIsAGlobalVariable(place.val.llval) {
|
||||
if llvm::LLVMIsGlobalConstant(global) == llvm::True {
|
||||
if let Some(init) = llvm::LLVMGetInitializer(global) {
|
||||
if self.val_ty(init) == llty {
|
||||
const_llval = Some(init);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let llval = const_llval.unwrap_or_else(|| {
|
||||
let load = self.load(llty, place.val.llval, place.val.align);
|
||||
if let abi::BackendRepr::Scalar(scalar) = place.layout.backend_repr {
|
||||
|
|
@ -1721,7 +1717,7 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> {
|
|||
} else {
|
||||
cfi::typeid_for_fnabi(self.tcx, fn_abi, options)
|
||||
};
|
||||
let typeid_metadata = self.cx.typeid_metadata(typeid).unwrap();
|
||||
let typeid_metadata = self.cx.create_metadata(typeid.as_bytes());
|
||||
let dbg_loc = self.get_dbg_loc();
|
||||
|
||||
// Test whether the function pointer is associated with the type identifier using the
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@ use std::ptr;
|
|||
|
||||
use rustc_ast::expand::autodiff_attrs::{AutoDiffAttrs, AutoDiffItem, DiffActivity, DiffMode};
|
||||
use rustc_codegen_ssa::ModuleCodegen;
|
||||
use rustc_codegen_ssa::back::write::ModuleConfig;
|
||||
use rustc_codegen_ssa::common::TypeKind;
|
||||
use rustc_codegen_ssa::traits::BaseTypeCodegenMethods;
|
||||
use rustc_errors::FatalError;
|
||||
|
|
@ -76,12 +75,12 @@ fn match_args_from_caller_to_enzyme<'ll>(
|
|||
outer_pos = 1;
|
||||
}
|
||||
|
||||
let enzyme_const = cx.create_metadata("enzyme_const".to_string()).unwrap();
|
||||
let enzyme_out = cx.create_metadata("enzyme_out".to_string()).unwrap();
|
||||
let enzyme_dup = cx.create_metadata("enzyme_dup".to_string()).unwrap();
|
||||
let enzyme_dupv = cx.create_metadata("enzyme_dupv".to_string()).unwrap();
|
||||
let enzyme_dupnoneed = cx.create_metadata("enzyme_dupnoneed".to_string()).unwrap();
|
||||
let enzyme_dupnoneedv = cx.create_metadata("enzyme_dupnoneedv".to_string()).unwrap();
|
||||
let enzyme_const = cx.create_metadata(b"enzyme_const");
|
||||
let enzyme_out = cx.create_metadata(b"enzyme_out");
|
||||
let enzyme_dup = cx.create_metadata(b"enzyme_dup");
|
||||
let enzyme_dupv = cx.create_metadata(b"enzyme_dupv");
|
||||
let enzyme_dupnoneed = cx.create_metadata(b"enzyme_dupnoneed");
|
||||
let enzyme_dupnoneedv = cx.create_metadata(b"enzyme_dupnoneedv");
|
||||
|
||||
while activity_pos < inputs.len() {
|
||||
let diff_activity = inputs[activity_pos as usize];
|
||||
|
|
@ -378,12 +377,12 @@ fn generate_enzyme_call<'ll>(
|
|||
let mut args = Vec::with_capacity(num_args as usize + 1);
|
||||
args.push(fn_to_diff);
|
||||
|
||||
let enzyme_primal_ret = cx.create_metadata("enzyme_primal_return".to_string()).unwrap();
|
||||
let enzyme_primal_ret = cx.create_metadata(b"enzyme_primal_return");
|
||||
if matches!(attrs.ret_activity, DiffActivity::Dual | DiffActivity::Active) {
|
||||
args.push(cx.get_metadata_value(enzyme_primal_ret));
|
||||
}
|
||||
if attrs.width > 1 {
|
||||
let enzyme_width = cx.create_metadata("enzyme_width".to_string()).unwrap();
|
||||
let enzyme_width = cx.create_metadata(b"enzyme_width");
|
||||
args.push(cx.get_metadata_value(enzyme_width));
|
||||
args.push(cx.get_const_int(cx.type_i64(), attrs.width as u64));
|
||||
}
|
||||
|
|
@ -461,7 +460,6 @@ pub(crate) fn differentiate<'ll>(
|
|||
module: &'ll ModuleCodegen<ModuleLlvm>,
|
||||
cgcx: &CodegenContext<LlvmCodegenBackend>,
|
||||
diff_items: Vec<AutoDiffItem>,
|
||||
_config: &ModuleConfig,
|
||||
) -> Result<(), FatalError> {
|
||||
for item in &diff_items {
|
||||
trace!("{}", item);
|
||||
|
|
|
|||
|
|
@ -102,7 +102,7 @@ pub(crate) fn get_fn<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>, instance: Instance<'t
|
|||
let is_hidden = if is_generic {
|
||||
// This is a monomorphization of a generic function.
|
||||
if !(cx.tcx.sess.opts.share_generics()
|
||||
|| tcx.codegen_fn_attrs(instance_def_id).inline
|
||||
|| tcx.codegen_instance_attrs(instance.def).inline
|
||||
== rustc_attr_data_structures::InlineAttr::Never)
|
||||
{
|
||||
// When not sharing generics, all instances are in the same
|
||||
|
|
|
|||
|
|
@ -215,10 +215,10 @@ impl<'ll, 'tcx> ConstCodegenMethods for CodegenCx<'ll, 'tcx> {
|
|||
bug!("symbol `{}` is already defined", sym);
|
||||
});
|
||||
llvm::set_initializer(g, sc);
|
||||
unsafe {
|
||||
llvm::LLVMSetGlobalConstant(g, True);
|
||||
llvm::LLVMSetUnnamedAddress(g, llvm::UnnamedAddr::Global);
|
||||
}
|
||||
|
||||
llvm::set_global_constant(g, true);
|
||||
llvm::set_unnamed_address(g, llvm::UnnamedAddr::Global);
|
||||
|
||||
llvm::set_linkage(g, llvm::Linkage::InternalLinkage);
|
||||
// Cast to default address space if globals are in a different addrspace
|
||||
let g = self.const_pointercast(g, self.type_ptr());
|
||||
|
|
|
|||
|
|
@ -17,13 +17,12 @@ use rustc_middle::ty::{self, Instance};
|
|||
use rustc_middle::{bug, span_bug};
|
||||
use tracing::{debug, instrument, trace};
|
||||
|
||||
use crate::common::{AsCCharPtr, CodegenCx};
|
||||
use crate::common::CodegenCx;
|
||||
use crate::errors::SymbolAlreadyDefined;
|
||||
use crate::llvm::{self, True};
|
||||
use crate::type_::Type;
|
||||
use crate::type_of::LayoutLlvmExt;
|
||||
use crate::value::Value;
|
||||
use crate::{base, debuginfo};
|
||||
use crate::{base, debuginfo, llvm};
|
||||
|
||||
pub(crate) fn const_alloc_to_llvm<'ll>(
|
||||
cx: &CodegenCx<'ll, '_>,
|
||||
|
|
@ -247,7 +246,7 @@ impl<'ll> CodegenCx<'ll, '_> {
|
|||
};
|
||||
llvm::set_initializer(gv, cv);
|
||||
set_global_alignment(self, gv, align);
|
||||
llvm::SetUnnamedAddress(gv, llvm::UnnamedAddr::Global);
|
||||
llvm::set_unnamed_address(gv, llvm::UnnamedAddr::Global);
|
||||
gv
|
||||
}
|
||||
|
||||
|
|
@ -272,9 +271,8 @@ impl<'ll> CodegenCx<'ll, '_> {
|
|||
return gv;
|
||||
}
|
||||
let gv = self.static_addr_of_mut(cv, align, kind);
|
||||
unsafe {
|
||||
llvm::LLVMSetGlobalConstant(gv, True);
|
||||
}
|
||||
llvm::set_global_constant(gv, true);
|
||||
|
||||
self.const_globals.borrow_mut().insert(cv, gv);
|
||||
gv
|
||||
}
|
||||
|
|
@ -398,149 +396,140 @@ impl<'ll> CodegenCx<'ll, '_> {
|
|||
}
|
||||
|
||||
fn codegen_static_item(&mut self, def_id: DefId) {
|
||||
unsafe {
|
||||
assert!(
|
||||
llvm::LLVMGetInitializer(
|
||||
self.instances.borrow().get(&Instance::mono(self.tcx, def_id)).unwrap()
|
||||
)
|
||||
.is_none()
|
||||
);
|
||||
let attrs = self.tcx.codegen_fn_attrs(def_id);
|
||||
assert!(
|
||||
llvm::LLVMGetInitializer(
|
||||
self.instances.borrow().get(&Instance::mono(self.tcx, def_id)).unwrap()
|
||||
)
|
||||
.is_none()
|
||||
);
|
||||
let attrs = self.tcx.codegen_fn_attrs(def_id);
|
||||
|
||||
let Ok((v, alloc)) = codegen_static_initializer(self, def_id) else {
|
||||
// Error has already been reported
|
||||
return;
|
||||
};
|
||||
let alloc = alloc.inner();
|
||||
let Ok((v, alloc)) = codegen_static_initializer(self, def_id) else {
|
||||
// Error has already been reported
|
||||
return;
|
||||
};
|
||||
let alloc = alloc.inner();
|
||||
|
||||
let val_llty = self.val_ty(v);
|
||||
let val_llty = self.val_ty(v);
|
||||
|
||||
let g = self.get_static_inner(def_id, val_llty);
|
||||
let llty = self.get_type_of_global(g);
|
||||
let g = self.get_static_inner(def_id, val_llty);
|
||||
let llty = self.get_type_of_global(g);
|
||||
|
||||
let g = if val_llty == llty {
|
||||
g
|
||||
} else {
|
||||
// codegen_static_initializer creates the global value just from the
|
||||
// `Allocation` data by generating one big struct value that is just
|
||||
// all the bytes and pointers after each other. This will almost never
|
||||
// match the type that the static was declared with. Unfortunately
|
||||
// we can't just LLVMConstBitCast our way out of it because that has very
|
||||
// specific rules on what can be cast. So instead of adding a new way to
|
||||
// generate static initializers that match the static's type, we picked
|
||||
// the easier option and retroactively change the type of the static item itself.
|
||||
let name = llvm::get_value_name(g);
|
||||
llvm::set_value_name(g, b"");
|
||||
let g = if val_llty == llty {
|
||||
g
|
||||
} else {
|
||||
// codegen_static_initializer creates the global value just from the
|
||||
// `Allocation` data by generating one big struct value that is just
|
||||
// all the bytes and pointers after each other. This will almost never
|
||||
// match the type that the static was declared with. Unfortunately
|
||||
// we can't just LLVMConstBitCast our way out of it because that has very
|
||||
// specific rules on what can be cast. So instead of adding a new way to
|
||||
// generate static initializers that match the static's type, we picked
|
||||
// the easier option and retroactively change the type of the static item itself.
|
||||
let name = String::from_utf8(llvm::get_value_name(g))
|
||||
.expect("we declare our statics with a utf8-valid name");
|
||||
llvm::set_value_name(g, b"");
|
||||
|
||||
let linkage = llvm::get_linkage(g);
|
||||
let visibility = llvm::get_visibility(g);
|
||||
let linkage = llvm::get_linkage(g);
|
||||
let visibility = llvm::get_visibility(g);
|
||||
|
||||
let new_g = llvm::LLVMRustGetOrInsertGlobal(
|
||||
self.llmod,
|
||||
name.as_c_char_ptr(),
|
||||
name.len(),
|
||||
val_llty,
|
||||
);
|
||||
let new_g = self.declare_global(&name, val_llty);
|
||||
|
||||
llvm::set_linkage(new_g, linkage);
|
||||
llvm::set_visibility(new_g, visibility);
|
||||
llvm::set_linkage(new_g, linkage);
|
||||
llvm::set_visibility(new_g, visibility);
|
||||
|
||||
// The old global has had its name removed but is returned by
|
||||
// get_static since it is in the instance cache. Provide an
|
||||
// alternative lookup that points to the new global so that
|
||||
// global_asm! can compute the correct mangled symbol name
|
||||
// for the global.
|
||||
self.renamed_statics.borrow_mut().insert(def_id, new_g);
|
||||
// The old global has had its name removed but is returned by
|
||||
// get_static since it is in the instance cache. Provide an
|
||||
// alternative lookup that points to the new global so that
|
||||
// global_asm! can compute the correct mangled symbol name
|
||||
// for the global.
|
||||
self.renamed_statics.borrow_mut().insert(def_id, new_g);
|
||||
|
||||
// To avoid breaking any invariants, we leave around the old
|
||||
// global for the moment; we'll replace all references to it
|
||||
// with the new global later. (See base::codegen_backend.)
|
||||
self.statics_to_rauw.borrow_mut().push((g, new_g));
|
||||
new_g
|
||||
};
|
||||
set_global_alignment(self, g, alloc.align);
|
||||
llvm::set_initializer(g, v);
|
||||
// To avoid breaking any invariants, we leave around the old
|
||||
// global for the moment; we'll replace all references to it
|
||||
// with the new global later. (See base::codegen_backend.)
|
||||
self.statics_to_rauw.borrow_mut().push((g, new_g));
|
||||
new_g
|
||||
};
|
||||
set_global_alignment(self, g, alloc.align);
|
||||
llvm::set_initializer(g, v);
|
||||
|
||||
self.assume_dso_local(g, true);
|
||||
self.assume_dso_local(g, true);
|
||||
|
||||
// Forward the allocation's mutability (picked by the const interner) to LLVM.
|
||||
if alloc.mutability.is_not() {
|
||||
llvm::LLVMSetGlobalConstant(g, llvm::True);
|
||||
}
|
||||
// Forward the allocation's mutability (picked by the const interner) to LLVM.
|
||||
if alloc.mutability.is_not() {
|
||||
llvm::set_global_constant(g, true);
|
||||
}
|
||||
|
||||
debuginfo::build_global_var_di_node(self, def_id, g);
|
||||
debuginfo::build_global_var_di_node(self, def_id, g);
|
||||
|
||||
if attrs.flags.contains(CodegenFnAttrFlags::THREAD_LOCAL) {
|
||||
llvm::set_thread_local_mode(g, self.tls_model);
|
||||
}
|
||||
if attrs.flags.contains(CodegenFnAttrFlags::THREAD_LOCAL) {
|
||||
llvm::set_thread_local_mode(g, self.tls_model);
|
||||
}
|
||||
|
||||
// Wasm statics with custom link sections get special treatment as they
|
||||
// go into custom sections of the wasm executable. The exception to this
|
||||
// is the `.init_array` section which are treated specially by the wasm linker.
|
||||
if self.tcx.sess.target.is_like_wasm
|
||||
&& attrs
|
||||
.link_section
|
||||
.map(|link_section| !link_section.as_str().starts_with(".init_array"))
|
||||
.unwrap_or(true)
|
||||
{
|
||||
if let Some(section) = attrs.link_section {
|
||||
let section = llvm::LLVMMDStringInContext2(
|
||||
self.llcx,
|
||||
section.as_str().as_c_char_ptr(),
|
||||
section.as_str().len(),
|
||||
);
|
||||
assert!(alloc.provenance().ptrs().is_empty());
|
||||
// Wasm statics with custom link sections get special treatment as they
|
||||
// go into custom sections of the wasm executable. The exception to this
|
||||
// is the `.init_array` section which are treated specially by the wasm linker.
|
||||
if self.tcx.sess.target.is_like_wasm
|
||||
&& attrs
|
||||
.link_section
|
||||
.map(|link_section| !link_section.as_str().starts_with(".init_array"))
|
||||
.unwrap_or(true)
|
||||
{
|
||||
if let Some(section) = attrs.link_section {
|
||||
let section = self.create_metadata(section.as_str().as_bytes());
|
||||
assert!(alloc.provenance().ptrs().is_empty());
|
||||
|
||||
// The `inspect` method is okay here because we checked for provenance, and
|
||||
// because we are doing this access to inspect the final interpreter state (not
|
||||
// as part of the interpreter execution).
|
||||
let bytes =
|
||||
alloc.inspect_with_uninit_and_ptr_outside_interpreter(0..alloc.len());
|
||||
let alloc =
|
||||
llvm::LLVMMDStringInContext2(self.llcx, bytes.as_c_char_ptr(), bytes.len());
|
||||
let data = [section, alloc];
|
||||
let meta = llvm::LLVMMDNodeInContext2(self.llcx, data.as_ptr(), data.len());
|
||||
let val = self.get_metadata_value(meta);
|
||||
// The `inspect` method is okay here because we checked for provenance, and
|
||||
// because we are doing this access to inspect the final interpreter state (not
|
||||
// as part of the interpreter execution).
|
||||
let bytes = alloc.inspect_with_uninit_and_ptr_outside_interpreter(0..alloc.len());
|
||||
let alloc = self.create_metadata(bytes);
|
||||
let data = [section, alloc];
|
||||
let meta =
|
||||
unsafe { llvm::LLVMMDNodeInContext2(self.llcx, data.as_ptr(), data.len()) };
|
||||
let val = self.get_metadata_value(meta);
|
||||
unsafe {
|
||||
llvm::LLVMAddNamedMetadataOperand(
|
||||
self.llmod,
|
||||
c"wasm.custom_sections".as_ptr(),
|
||||
val,
|
||||
);
|
||||
}
|
||||
} else {
|
||||
base::set_link_section(g, attrs);
|
||||
)
|
||||
};
|
||||
}
|
||||
} else {
|
||||
base::set_link_section(g, attrs);
|
||||
}
|
||||
|
||||
base::set_variable_sanitizer_attrs(g, attrs);
|
||||
base::set_variable_sanitizer_attrs(g, attrs);
|
||||
|
||||
if attrs.flags.contains(CodegenFnAttrFlags::USED_COMPILER) {
|
||||
// `USED` and `USED_LINKER` can't be used together.
|
||||
assert!(!attrs.flags.contains(CodegenFnAttrFlags::USED_LINKER));
|
||||
if attrs.flags.contains(CodegenFnAttrFlags::USED_COMPILER) {
|
||||
// `USED` and `USED_LINKER` can't be used together.
|
||||
assert!(!attrs.flags.contains(CodegenFnAttrFlags::USED_LINKER));
|
||||
|
||||
// The semantics of #[used] in Rust only require the symbol to make it into the
|
||||
// object file. It is explicitly allowed for the linker to strip the symbol if it
|
||||
// is dead, which means we are allowed to use `llvm.compiler.used` instead of
|
||||
// `llvm.used` here.
|
||||
//
|
||||
// Additionally, https://reviews.llvm.org/D97448 in LLVM 13 started emitting unique
|
||||
// sections with SHF_GNU_RETAIN flag for llvm.used symbols, which may trigger bugs
|
||||
// in the handling of `.init_array` (the static constructor list) in versions of
|
||||
// the gold linker (prior to the one released with binutils 2.36).
|
||||
//
|
||||
// That said, we only ever emit these when `#[used(compiler)]` is explicitly
|
||||
// requested. This is to avoid similar breakage on other targets, in particular
|
||||
// MachO targets have *their* static constructor lists broken if `llvm.compiler.used`
|
||||
// is emitted rather than `llvm.used`. However, that check happens when assigning
|
||||
// the `CodegenFnAttrFlags` in the `codegen_fn_attrs` query, so we don't need to
|
||||
// take care of it here.
|
||||
self.add_compiler_used_global(g);
|
||||
}
|
||||
if attrs.flags.contains(CodegenFnAttrFlags::USED_LINKER) {
|
||||
// `USED` and `USED_LINKER` can't be used together.
|
||||
assert!(!attrs.flags.contains(CodegenFnAttrFlags::USED_COMPILER));
|
||||
// The semantics of #[used] in Rust only require the symbol to make it into the
|
||||
// object file. It is explicitly allowed for the linker to strip the symbol if it
|
||||
// is dead, which means we are allowed to use `llvm.compiler.used` instead of
|
||||
// `llvm.used` here.
|
||||
//
|
||||
// Additionally, https://reviews.llvm.org/D97448 in LLVM 13 started emitting unique
|
||||
// sections with SHF_GNU_RETAIN flag for llvm.used symbols, which may trigger bugs
|
||||
// in the handling of `.init_array` (the static constructor list) in versions of
|
||||
// the gold linker (prior to the one released with binutils 2.36).
|
||||
//
|
||||
// That said, we only ever emit these when `#[used(compiler)]` is explicitly
|
||||
// requested. This is to avoid similar breakage on other targets, in particular
|
||||
// MachO targets have *their* static constructor lists broken if `llvm.compiler.used`
|
||||
// is emitted rather than `llvm.used`. However, that check happens when assigning
|
||||
// the `CodegenFnAttrFlags` in the `codegen_fn_attrs` query, so we don't need to
|
||||
// take care of it here.
|
||||
self.add_compiler_used_global(g);
|
||||
}
|
||||
if attrs.flags.contains(CodegenFnAttrFlags::USED_LINKER) {
|
||||
// `USED` and `USED_LINKER` can't be used together.
|
||||
assert!(!attrs.flags.contains(CodegenFnAttrFlags::USED_COMPILER));
|
||||
|
||||
self.add_used_global(g);
|
||||
}
|
||||
self.add_used_global(g);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -34,7 +34,6 @@ use smallvec::SmallVec;
|
|||
|
||||
use crate::back::write::to_llvm_code_model;
|
||||
use crate::callee::get_fn;
|
||||
use crate::common::AsCCharPtr;
|
||||
use crate::debuginfo::metadata::apply_vcall_visibility_metadata;
|
||||
use crate::llvm::Metadata;
|
||||
use crate::type_::Type;
|
||||
|
|
@ -169,6 +168,8 @@ pub(crate) unsafe fn create_module<'ll>(
|
|||
let mod_name = SmallCStr::new(mod_name);
|
||||
let llmod = unsafe { llvm::LLVMModuleCreateWithNameInContext(mod_name.as_ptr(), llcx) };
|
||||
|
||||
let cx = SimpleCx::new(llmod, llcx, tcx.data_layout.pointer_size());
|
||||
|
||||
let mut target_data_layout = sess.target.data_layout.to_string();
|
||||
let llvm_version = llvm_util::get_version();
|
||||
|
||||
|
|
@ -206,6 +207,11 @@ pub(crate) unsafe fn create_module<'ll>(
|
|||
// LLVM 21 updated the default layout on nvptx: https://github.com/llvm/llvm-project/pull/124961
|
||||
target_data_layout = target_data_layout.replace("e-p6:32:32-i64", "e-i64");
|
||||
}
|
||||
if sess.target.arch == "amdgpu" {
|
||||
// LLVM 21 adds the address width for address space 8.
|
||||
// See https://github.com/llvm/llvm-project/pull/139419
|
||||
target_data_layout = target_data_layout.replace("p8:128:128:128:48", "p8:128:128")
|
||||
}
|
||||
}
|
||||
|
||||
// Ensure the data-layout values hardcoded remain the defaults.
|
||||
|
|
@ -473,18 +479,14 @@ pub(crate) unsafe fn create_module<'ll>(
|
|||
#[allow(clippy::option_env_unwrap)]
|
||||
let rustc_producer =
|
||||
format!("rustc version {}", option_env!("CFG_VERSION").expect("CFG_VERSION"));
|
||||
let name_metadata = unsafe {
|
||||
llvm::LLVMMDStringInContext2(
|
||||
llcx,
|
||||
rustc_producer.as_c_char_ptr(),
|
||||
rustc_producer.as_bytes().len(),
|
||||
)
|
||||
};
|
||||
|
||||
let name_metadata = cx.create_metadata(rustc_producer.as_bytes());
|
||||
|
||||
unsafe {
|
||||
llvm::LLVMAddNamedMetadataOperand(
|
||||
llmod,
|
||||
c"llvm.ident".as_ptr(),
|
||||
&llvm::LLVMMetadataAsValue(llcx, llvm::LLVMMDNodeInContext2(llcx, &name_metadata, 1)),
|
||||
&cx.get_metadata_value(llvm::LLVMMDNodeInContext2(llcx, &name_metadata, 1)),
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -698,10 +700,10 @@ impl<'ll, CX: Borrow<SCx<'ll>>> GenericCx<'ll, CX> {
|
|||
}
|
||||
}
|
||||
|
||||
pub(crate) fn create_metadata(&self, name: String) -> Option<&'ll Metadata> {
|
||||
Some(unsafe {
|
||||
pub(crate) fn create_metadata(&self, name: &[u8]) -> &'ll Metadata {
|
||||
unsafe {
|
||||
llvm::LLVMMDStringInContext2(self.llcx(), name.as_ptr() as *const c_char, name.len())
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn get_functions(&self) -> Vec<&'ll Value> {
|
||||
|
|
|
|||
|
|
@ -74,7 +74,7 @@ pub(crate) fn get_or_insert_gdb_debug_scripts_section_global<'ll>(
|
|||
llvm::set_section(section_var, c".debug_gdb_scripts");
|
||||
llvm::set_initializer(section_var, cx.const_bytes(section_contents));
|
||||
llvm::LLVMSetGlobalConstant(section_var, llvm::True);
|
||||
llvm::LLVMSetUnnamedAddress(section_var, llvm::UnnamedAddr::Global);
|
||||
llvm::set_unnamed_address(section_var, llvm::UnnamedAddr::Global);
|
||||
llvm::set_linkage(section_var, llvm::Linkage::LinkOnceODRLinkage);
|
||||
// This should make sure that the whole section is not larger than
|
||||
// the string it contains. Otherwise we get a warning from GDB.
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ use std::path::{Path, PathBuf};
|
|||
use std::sync::Arc;
|
||||
use std::{iter, ptr};
|
||||
|
||||
use libc::{c_char, c_longlong, c_uint};
|
||||
use libc::{c_longlong, c_uint};
|
||||
use rustc_abi::{Align, Size};
|
||||
use rustc_codegen_ssa::debuginfo::type_names::{VTableNameKind, cpp_like_debuginfo};
|
||||
use rustc_codegen_ssa::traits::*;
|
||||
|
|
@ -1582,13 +1582,9 @@ pub(crate) fn apply_vcall_visibility_metadata<'ll, 'tcx>(
|
|||
};
|
||||
|
||||
let trait_ref_typeid = typeid_for_trait_ref(cx.tcx, trait_ref);
|
||||
let typeid = cx.create_metadata(trait_ref_typeid.as_bytes());
|
||||
|
||||
unsafe {
|
||||
let typeid = llvm::LLVMMDStringInContext2(
|
||||
cx.llcx,
|
||||
trait_ref_typeid.as_ptr() as *const c_char,
|
||||
trait_ref_typeid.as_bytes().len(),
|
||||
);
|
||||
let v = [llvm::LLVMValueAsMetadata(cx.const_usize(0)), typeid];
|
||||
llvm::LLVMRustGlobalAddMetadata(
|
||||
vtable,
|
||||
|
|
@ -1630,7 +1626,7 @@ pub(crate) fn create_vtable_di_node<'ll, 'tcx>(
|
|||
// When full debuginfo is enabled, we want to try and prevent vtables from being
|
||||
// merged. Otherwise debuggers will have a hard time mapping from dyn pointer
|
||||
// to concrete type.
|
||||
llvm::SetUnnamedAddress(vtable, llvm::UnnamedAddr::No);
|
||||
llvm::set_unnamed_address(vtable, llvm::UnnamedAddr::No);
|
||||
|
||||
let vtable_name =
|
||||
compute_debuginfo_vtable_name(cx.tcx, ty, poly_trait_ref, VTableNameKind::GlobalVariable);
|
||||
|
|
|
|||
|
|
@ -49,7 +49,7 @@ pub(crate) fn declare_simple_fn<'ll>(
|
|||
};
|
||||
|
||||
llvm::SetFunctionCallConv(llfn, callconv);
|
||||
llvm::SetUnnamedAddress(llfn, unnamed);
|
||||
llvm::set_unnamed_address(llfn, unnamed);
|
||||
llvm::set_visibility(llfn, visibility);
|
||||
|
||||
llfn
|
||||
|
|
@ -176,7 +176,7 @@ impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> {
|
|||
{
|
||||
let typeid = cfi::typeid_for_instance(self.tcx, instance, options);
|
||||
if typeids.insert(typeid.clone()) {
|
||||
self.add_type_metadata(llfn, typeid);
|
||||
self.add_type_metadata(llfn, typeid.as_bytes());
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
|
@ -189,7 +189,7 @@ impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> {
|
|||
.map(cfi::TypeIdOptions::from_iter)
|
||||
{
|
||||
let typeid = cfi::typeid_for_fnabi(self.tcx, fn_abi, options);
|
||||
self.add_type_metadata(llfn, typeid);
|
||||
self.add_type_metadata(llfn, typeid.as_bytes());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -37,10 +37,6 @@ impl<G: EmissionGuarantee> Diagnostic<'_, G> for ParseTargetMachineConfig<'_> {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(codegen_llvm_autodiff_without_lto)]
|
||||
pub(crate) struct AutoDiffWithoutLTO;
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(codegen_llvm_autodiff_without_enable)]
|
||||
pub(crate) struct AutoDiffWithoutEnable;
|
||||
|
|
|
|||
|
|
@ -26,11 +26,11 @@ use std::mem::ManuallyDrop;
|
|||
use back::owned_target_machine::OwnedTargetMachine;
|
||||
use back::write::{create_informational_target_machine, create_target_machine};
|
||||
use context::SimpleCx;
|
||||
use errors::{AutoDiffWithoutLTO, ParseTargetMachineConfig};
|
||||
use errors::ParseTargetMachineConfig;
|
||||
use llvm_util::target_config;
|
||||
use rustc_ast::expand::allocator::AllocatorKind;
|
||||
use rustc_ast::expand::autodiff_attrs::AutoDiffItem;
|
||||
use rustc_codegen_ssa::back::lto::{LtoModuleCodegen, SerializedModule, ThinModule};
|
||||
use rustc_codegen_ssa::back::lto::{SerializedModule, ThinModule};
|
||||
use rustc_codegen_ssa::back::write::{
|
||||
CodegenContext, FatLtoInput, ModuleConfig, TargetMachineFactoryConfig, TargetMachineFactoryFn,
|
||||
};
|
||||
|
|
@ -43,7 +43,7 @@ use rustc_middle::dep_graph::{WorkProduct, WorkProductId};
|
|||
use rustc_middle::ty::TyCtxt;
|
||||
use rustc_middle::util::Providers;
|
||||
use rustc_session::Session;
|
||||
use rustc_session::config::{Lto, OptLevel, OutputFilenames, PrintKind, PrintRequest};
|
||||
use rustc_session::config::{OptLevel, OutputFilenames, PrintKind, PrintRequest};
|
||||
use rustc_span::Symbol;
|
||||
|
||||
mod back {
|
||||
|
|
@ -174,18 +174,29 @@ impl WriteBackendMethods for LlvmCodegenBackend {
|
|||
) -> Result<ModuleCodegen<Self::Module>, FatalError> {
|
||||
back::write::link(cgcx, dcx, modules)
|
||||
}
|
||||
fn run_fat_lto(
|
||||
fn run_and_optimize_fat_lto(
|
||||
cgcx: &CodegenContext<Self>,
|
||||
modules: Vec<FatLtoInput<Self>>,
|
||||
cached_modules: Vec<(SerializedModule<Self::ModuleBuffer>, WorkProduct)>,
|
||||
) -> Result<LtoModuleCodegen<Self>, FatalError> {
|
||||
back::lto::run_fat(cgcx, modules, cached_modules)
|
||||
diff_fncs: Vec<AutoDiffItem>,
|
||||
) -> Result<ModuleCodegen<Self::Module>, FatalError> {
|
||||
let mut module = back::lto::run_fat(cgcx, modules, cached_modules)?;
|
||||
|
||||
if !diff_fncs.is_empty() {
|
||||
builder::autodiff::differentiate(&module, cgcx, diff_fncs)?;
|
||||
}
|
||||
|
||||
let dcx = cgcx.create_dcx();
|
||||
let dcx = dcx.handle();
|
||||
back::lto::run_pass_manager(cgcx, dcx, &mut module, false)?;
|
||||
|
||||
Ok(module)
|
||||
}
|
||||
fn run_thin_lto(
|
||||
cgcx: &CodegenContext<Self>,
|
||||
modules: Vec<(String, Self::ThinBuffer)>,
|
||||
cached_modules: Vec<(SerializedModule<Self::ModuleBuffer>, WorkProduct)>,
|
||||
) -> Result<(Vec<LtoModuleCodegen<Self>>, Vec<WorkProduct>), FatalError> {
|
||||
) -> Result<(Vec<ThinModule<Self>>, Vec<WorkProduct>), FatalError> {
|
||||
back::lto::run_thin(cgcx, modules, cached_modules)
|
||||
}
|
||||
fn optimize(
|
||||
|
|
@ -196,14 +207,6 @@ impl WriteBackendMethods for LlvmCodegenBackend {
|
|||
) -> Result<(), FatalError> {
|
||||
back::write::optimize(cgcx, dcx, module, config)
|
||||
}
|
||||
fn optimize_fat(
|
||||
cgcx: &CodegenContext<Self>,
|
||||
module: &mut ModuleCodegen<Self::Module>,
|
||||
) -> Result<(), FatalError> {
|
||||
let dcx = cgcx.create_dcx();
|
||||
let dcx = dcx.handle();
|
||||
back::lto::run_pass_manager(cgcx, dcx, module, false)
|
||||
}
|
||||
fn optimize_thin(
|
||||
cgcx: &CodegenContext<Self>,
|
||||
thin: ThinModule<Self>,
|
||||
|
|
@ -212,11 +215,10 @@ impl WriteBackendMethods for LlvmCodegenBackend {
|
|||
}
|
||||
fn codegen(
|
||||
cgcx: &CodegenContext<Self>,
|
||||
dcx: DiagCtxtHandle<'_>,
|
||||
module: ModuleCodegen<Self::Module>,
|
||||
config: &ModuleConfig,
|
||||
) -> Result<CompiledModule, FatalError> {
|
||||
back::write::codegen(cgcx, dcx, module, config)
|
||||
back::write::codegen(cgcx, module, config)
|
||||
}
|
||||
fn prepare_thin(
|
||||
module: ModuleCodegen<Self::Module>,
|
||||
|
|
@ -227,19 +229,6 @@ impl WriteBackendMethods for LlvmCodegenBackend {
|
|||
fn serialize_module(module: ModuleCodegen<Self::Module>) -> (String, Self::ModuleBuffer) {
|
||||
(module.name, back::lto::ModuleBuffer::new(module.module_llvm.llmod()))
|
||||
}
|
||||
/// Generate autodiff rules
|
||||
fn autodiff(
|
||||
cgcx: &CodegenContext<Self>,
|
||||
module: &ModuleCodegen<Self::Module>,
|
||||
diff_fncs: Vec<AutoDiffItem>,
|
||||
config: &ModuleConfig,
|
||||
) -> Result<(), FatalError> {
|
||||
if cgcx.lto != Lto::Fat {
|
||||
let dcx = cgcx.create_dcx();
|
||||
return Err(dcx.handle().emit_almost_fatal(AutoDiffWithoutLTO));
|
||||
}
|
||||
builder::autodiff::differentiate(module, cgcx, diff_fncs, config)
|
||||
}
|
||||
}
|
||||
|
||||
impl LlvmCodegenBackend {
|
||||
|
|
|
|||
|
|
@ -1009,7 +1009,7 @@ unsafe extern "C" {
|
|||
ModuleID: *const c_char,
|
||||
C: &Context,
|
||||
) -> &Module;
|
||||
pub(crate) fn LLVMCloneModule(M: &Module) -> &Module;
|
||||
pub(crate) safe fn LLVMCloneModule(M: &Module) -> &Module;
|
||||
|
||||
/// Data layout. See Module::getDataLayout.
|
||||
pub(crate) fn LLVMGetDataLayoutStr(M: &Module) -> *const c_char;
|
||||
|
|
@ -1168,18 +1168,18 @@ unsafe extern "C" {
|
|||
pub(crate) fn LLVMGlobalGetValueType(Global: &Value) -> &Type;
|
||||
|
||||
// Operations on global variables
|
||||
pub(crate) fn LLVMIsAGlobalVariable(GlobalVar: &Value) -> Option<&Value>;
|
||||
pub(crate) safe fn LLVMIsAGlobalVariable(GlobalVar: &Value) -> Option<&Value>;
|
||||
pub(crate) fn LLVMAddGlobal<'a>(M: &'a Module, Ty: &'a Type, Name: *const c_char) -> &'a Value;
|
||||
pub(crate) fn LLVMGetNamedGlobal(M: &Module, Name: *const c_char) -> Option<&Value>;
|
||||
pub(crate) fn LLVMGetFirstGlobal(M: &Module) -> Option<&Value>;
|
||||
pub(crate) fn LLVMGetNextGlobal(GlobalVar: &Value) -> Option<&Value>;
|
||||
pub(crate) fn LLVMDeleteGlobal(GlobalVar: &Value);
|
||||
pub(crate) fn LLVMGetInitializer(GlobalVar: &Value) -> Option<&Value>;
|
||||
pub(crate) safe fn LLVMGetInitializer(GlobalVar: &Value) -> Option<&Value>;
|
||||
pub(crate) fn LLVMSetInitializer<'a>(GlobalVar: &'a Value, ConstantVal: &'a Value);
|
||||
pub(crate) fn LLVMIsThreadLocal(GlobalVar: &Value) -> Bool;
|
||||
pub(crate) safe fn LLVMIsThreadLocal(GlobalVar: &Value) -> Bool;
|
||||
pub(crate) fn LLVMSetThreadLocalMode(GlobalVar: &Value, Mode: ThreadLocalMode);
|
||||
pub(crate) fn LLVMIsGlobalConstant(GlobalVar: &Value) -> Bool;
|
||||
pub(crate) fn LLVMSetGlobalConstant(GlobalVar: &Value, IsConstant: Bool);
|
||||
pub(crate) safe fn LLVMIsGlobalConstant(GlobalVar: &Value) -> Bool;
|
||||
pub(crate) safe fn LLVMSetGlobalConstant(GlobalVar: &Value, IsConstant: Bool);
|
||||
pub(crate) safe fn LLVMSetTailCall(CallInst: &Value, IsTailCall: Bool);
|
||||
|
||||
// Operations on attributes
|
||||
|
|
@ -1718,7 +1718,7 @@ unsafe extern "C" {
|
|||
|
||||
pub(crate) safe fn LLVMMetadataAsValue<'a>(C: &'a Context, MD: &'a Metadata) -> &'a Value;
|
||||
|
||||
pub(crate) fn LLVMSetUnnamedAddress(Global: &Value, UnnamedAddr: UnnamedAddr);
|
||||
pub(crate) safe fn LLVMSetUnnamedAddress(Global: &Value, UnnamedAddr: UnnamedAddr);
|
||||
|
||||
pub(crate) fn LLVMIsAConstantInt(value_ref: &Value) -> Option<&ConstantInt>;
|
||||
|
||||
|
|
@ -2425,6 +2425,7 @@ unsafe extern "C" {
|
|||
UseEmulatedTls: bool,
|
||||
ArgsCstrBuff: *const c_char,
|
||||
ArgsCstrBuffLen: usize,
|
||||
UseWasmEH: bool,
|
||||
) -> *mut TargetMachine;
|
||||
|
||||
pub(crate) fn LLVMRustDisposeTargetMachine(T: *mut TargetMachine);
|
||||
|
|
|
|||
|
|
@ -217,10 +217,8 @@ pub(crate) fn SetUniqueComdat(llmod: &Module, val: &Value) {
|
|||
set_comdat(llmod, val, &name);
|
||||
}
|
||||
|
||||
pub(crate) fn SetUnnamedAddress(global: &Value, unnamed: UnnamedAddr) {
|
||||
unsafe {
|
||||
LLVMSetUnnamedAddress(global, unnamed);
|
||||
}
|
||||
pub(crate) fn set_unnamed_address(global: &Value, unnamed: UnnamedAddr) {
|
||||
LLVMSetUnnamedAddress(global, unnamed);
|
||||
}
|
||||
|
||||
pub(crate) fn set_thread_local_mode(global: &Value, mode: ThreadLocalMode) {
|
||||
|
|
@ -260,9 +258,7 @@ pub(crate) fn set_initializer(llglobal: &Value, constant_val: &Value) {
|
|||
}
|
||||
|
||||
pub(crate) fn set_global_constant(llglobal: &Value, is_constant: bool) {
|
||||
unsafe {
|
||||
LLVMSetGlobalConstant(llglobal, if is_constant { ffi::True } else { ffi::False });
|
||||
}
|
||||
LLVMSetGlobalConstant(llglobal, if is_constant { ffi::True } else { ffi::False });
|
||||
}
|
||||
|
||||
pub(crate) fn get_linkage(llglobal: &Value) -> Linkage {
|
||||
|
|
|
|||
|
|
@ -55,8 +55,8 @@ impl<'tcx> PreDefineCodegenMethods<'tcx> for CodegenCx<'_, 'tcx> {
|
|||
let fn_abi = self.fn_abi_of_instance(instance, ty::List::empty());
|
||||
let lldecl = self.declare_fn(symbol_name, fn_abi, Some(instance));
|
||||
llvm::set_linkage(lldecl, base::linkage_to_llvm(linkage));
|
||||
let attrs = self.tcx.codegen_fn_attrs(instance.def_id());
|
||||
base::set_link_section(lldecl, attrs);
|
||||
let attrs = self.tcx.codegen_instance_attrs(instance.def);
|
||||
base::set_link_section(lldecl, &attrs);
|
||||
if (linkage == Linkage::LinkOnceODR || linkage == Linkage::WeakODR)
|
||||
&& self.tcx.sess.target.supports_comdat()
|
||||
{
|
||||
|
|
@ -131,8 +131,8 @@ impl CodegenCx<'_, '_> {
|
|||
}
|
||||
|
||||
// Thread-local variables generally don't support copy relocations.
|
||||
let is_thread_local_var = unsafe { llvm::LLVMIsAGlobalVariable(llval) }
|
||||
.is_some_and(|v| unsafe { llvm::LLVMIsThreadLocal(v) } == llvm::True);
|
||||
let is_thread_local_var = llvm::LLVMIsAGlobalVariable(llval)
|
||||
.is_some_and(|v| llvm::LLVMIsThreadLocal(v) == llvm::True);
|
||||
if is_thread_local_var {
|
||||
return false;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ use std::borrow::Borrow;
|
|||
use std::hash::{Hash, Hasher};
|
||||
use std::{fmt, ptr};
|
||||
|
||||
use libc::{c_char, c_uint};
|
||||
use libc::c_uint;
|
||||
use rustc_abi::{AddressSpace, Align, Integer, Reg, Size};
|
||||
use rustc_codegen_ssa::common::TypeKind;
|
||||
use rustc_codegen_ssa::traits::*;
|
||||
|
|
@ -298,8 +298,8 @@ impl<'ll, 'tcx> LayoutTypeCodegenMethods<'tcx> for CodegenCx<'ll, 'tcx> {
|
|||
}
|
||||
|
||||
impl<'ll, 'tcx> TypeMembershipCodegenMethods<'tcx> for CodegenCx<'ll, 'tcx> {
|
||||
fn add_type_metadata(&self, function: &'ll Value, typeid: String) {
|
||||
let typeid_metadata = self.typeid_metadata(typeid).unwrap();
|
||||
fn add_type_metadata(&self, function: &'ll Value, typeid: &[u8]) {
|
||||
let typeid_metadata = self.create_metadata(typeid);
|
||||
unsafe {
|
||||
let v = [llvm::LLVMValueAsMetadata(self.const_usize(0)), typeid_metadata];
|
||||
llvm::LLVMRustGlobalAddMetadata(
|
||||
|
|
@ -310,8 +310,8 @@ impl<'ll, 'tcx> TypeMembershipCodegenMethods<'tcx> for CodegenCx<'ll, 'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
fn set_type_metadata(&self, function: &'ll Value, typeid: String) {
|
||||
let typeid_metadata = self.typeid_metadata(typeid).unwrap();
|
||||
fn set_type_metadata(&self, function: &'ll Value, typeid: &[u8]) {
|
||||
let typeid_metadata = self.create_metadata(typeid);
|
||||
unsafe {
|
||||
let v = [llvm::LLVMValueAsMetadata(self.const_usize(0)), typeid_metadata];
|
||||
llvm::LLVMGlobalSetMetadata(
|
||||
|
|
@ -322,10 +322,8 @@ impl<'ll, 'tcx> TypeMembershipCodegenMethods<'tcx> for CodegenCx<'ll, 'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
fn typeid_metadata(&self, typeid: String) -> Option<&'ll Metadata> {
|
||||
Some(unsafe {
|
||||
llvm::LLVMMDStringInContext2(self.llcx, typeid.as_ptr() as *const c_char, typeid.len())
|
||||
})
|
||||
fn typeid_metadata(&self, typeid: &[u8]) -> Option<&'ll Metadata> {
|
||||
Some(self.create_metadata(typeid))
|
||||
}
|
||||
|
||||
fn add_kcfi_type_metadata(&self, function: &'ll Value, kcfi_typeid: u32) {
|
||||
|
|
|
|||
|
|
@ -2542,12 +2542,7 @@ fn add_order_independent_options(
|
|||
// sections to ensure we have all the data for PGO.
|
||||
let keep_metadata =
|
||||
crate_type == CrateType::Dylib || sess.opts.cg.profile_generate.enabled();
|
||||
if crate_type != CrateType::Executable || !sess.opts.unstable_opts.export_executable_symbols
|
||||
{
|
||||
cmd.gc_sections(keep_metadata);
|
||||
} else {
|
||||
cmd.no_gc_sections();
|
||||
}
|
||||
cmd.gc_sections(keep_metadata);
|
||||
}
|
||||
|
||||
cmd.set_output_kind(link_output_kind, crate_type, out_filename);
|
||||
|
|
|
|||
|
|
@ -326,7 +326,6 @@ pub(crate) trait Linker {
|
|||
link_or_cc_args(self, &[path]);
|
||||
}
|
||||
fn gc_sections(&mut self, keep_metadata: bool);
|
||||
fn no_gc_sections(&mut self);
|
||||
fn full_relro(&mut self);
|
||||
fn partial_relro(&mut self);
|
||||
fn no_relro(&mut self);
|
||||
|
|
@ -688,12 +687,6 @@ impl<'a> Linker for GccLinker<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
fn no_gc_sections(&mut self) {
|
||||
if self.is_gnu || self.sess.target.is_like_wasm {
|
||||
self.link_arg("--no-gc-sections");
|
||||
}
|
||||
}
|
||||
|
||||
fn optimize(&mut self) {
|
||||
if !self.is_gnu && !self.sess.target.is_like_wasm {
|
||||
return;
|
||||
|
|
@ -1010,10 +1003,6 @@ impl<'a> Linker for MsvcLinker<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
fn no_gc_sections(&mut self) {
|
||||
self.link_arg("/OPT:NOREF,NOICF");
|
||||
}
|
||||
|
||||
fn full_relro(&mut self) {
|
||||
// noop
|
||||
}
|
||||
|
|
@ -1243,10 +1232,6 @@ impl<'a> Linker for EmLinker<'a> {
|
|||
// noop
|
||||
}
|
||||
|
||||
fn no_gc_sections(&mut self) {
|
||||
// noop
|
||||
}
|
||||
|
||||
fn optimize(&mut self) {
|
||||
// Emscripten performs own optimizations
|
||||
self.cc_arg(match self.sess.opts.optimize {
|
||||
|
|
@ -1418,10 +1403,6 @@ impl<'a> Linker for WasmLd<'a> {
|
|||
self.link_arg("--gc-sections");
|
||||
}
|
||||
|
||||
fn no_gc_sections(&mut self) {
|
||||
self.link_arg("--no-gc-sections");
|
||||
}
|
||||
|
||||
fn optimize(&mut self) {
|
||||
// The -O flag is, as of late 2023, only used for merging of strings and debuginfo, and
|
||||
// only differentiates -O0 and -O1. It does not apply to LTO.
|
||||
|
|
@ -1567,10 +1548,6 @@ impl<'a> Linker for L4Bender<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
fn no_gc_sections(&mut self) {
|
||||
self.link_arg("--no-gc-sections");
|
||||
}
|
||||
|
||||
fn optimize(&mut self) {
|
||||
// GNU-style linkers support optimization with -O. GNU ld doesn't
|
||||
// need a numeric argument, but other linkers do.
|
||||
|
|
@ -1734,10 +1711,6 @@ impl<'a> Linker for AixLinker<'a> {
|
|||
self.link_arg("-bgc");
|
||||
}
|
||||
|
||||
fn no_gc_sections(&mut self) {
|
||||
self.link_arg("-bnogc");
|
||||
}
|
||||
|
||||
fn optimize(&mut self) {}
|
||||
|
||||
fn pgo_gen(&mut self) {
|
||||
|
|
@ -1982,8 +1955,6 @@ impl<'a> Linker for PtxLinker<'a> {
|
|||
|
||||
fn gc_sections(&mut self, _keep_metadata: bool) {}
|
||||
|
||||
fn no_gc_sections(&mut self) {}
|
||||
|
||||
fn pgo_gen(&mut self) {}
|
||||
|
||||
fn no_crt_objects(&mut self) {}
|
||||
|
|
@ -2057,8 +2028,6 @@ impl<'a> Linker for LlbcLinker<'a> {
|
|||
|
||||
fn gc_sections(&mut self, _keep_metadata: bool) {}
|
||||
|
||||
fn no_gc_sections(&mut self) {}
|
||||
|
||||
fn pgo_gen(&mut self) {}
|
||||
|
||||
fn no_crt_objects(&mut self) {}
|
||||
|
|
@ -2139,8 +2108,6 @@ impl<'a> Linker for BpfLinker<'a> {
|
|||
|
||||
fn gc_sections(&mut self, _keep_metadata: bool) {}
|
||||
|
||||
fn no_gc_sections(&mut self) {}
|
||||
|
||||
fn pgo_gen(&mut self) {}
|
||||
|
||||
fn no_crt_objects(&mut self) {}
|
||||
|
|
|
|||
|
|
@ -1,13 +1,8 @@
|
|||
use std::ffi::CString;
|
||||
use std::sync::Arc;
|
||||
|
||||
use rustc_ast::expand::autodiff_attrs::AutoDiffItem;
|
||||
use rustc_data_structures::memmap::Mmap;
|
||||
use rustc_errors::FatalError;
|
||||
|
||||
use super::write::CodegenContext;
|
||||
use crate::ModuleCodegen;
|
||||
use crate::back::write::ModuleConfig;
|
||||
use crate::traits::*;
|
||||
|
||||
pub struct ThinModule<B: WriteBackendMethods> {
|
||||
|
|
@ -42,61 +37,6 @@ pub struct ThinShared<B: WriteBackendMethods> {
|
|||
pub module_names: Vec<CString>,
|
||||
}
|
||||
|
||||
pub enum LtoModuleCodegen<B: WriteBackendMethods> {
|
||||
Fat(ModuleCodegen<B::Module>),
|
||||
Thin(ThinModule<B>),
|
||||
}
|
||||
|
||||
impl<B: WriteBackendMethods> LtoModuleCodegen<B> {
|
||||
pub fn name(&self) -> &str {
|
||||
match *self {
|
||||
LtoModuleCodegen::Fat(_) => "everything",
|
||||
LtoModuleCodegen::Thin(ref m) => m.name(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Optimize this module within the given codegen context.
|
||||
pub fn optimize(
|
||||
self,
|
||||
cgcx: &CodegenContext<B>,
|
||||
) -> Result<ModuleCodegen<B::Module>, FatalError> {
|
||||
match self {
|
||||
LtoModuleCodegen::Fat(mut module) => {
|
||||
B::optimize_fat(cgcx, &mut module)?;
|
||||
Ok(module)
|
||||
}
|
||||
LtoModuleCodegen::Thin(thin) => B::optimize_thin(cgcx, thin),
|
||||
}
|
||||
}
|
||||
|
||||
/// A "gauge" of how costly it is to optimize this module, used to sort
|
||||
/// biggest modules first.
|
||||
pub fn cost(&self) -> u64 {
|
||||
match *self {
|
||||
// Only one module with fat LTO, so the cost doesn't matter.
|
||||
LtoModuleCodegen::Fat(_) => 0,
|
||||
LtoModuleCodegen::Thin(ref m) => m.cost(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Run autodiff on Fat LTO module
|
||||
pub fn autodiff(
|
||||
self,
|
||||
cgcx: &CodegenContext<B>,
|
||||
diff_fncs: Vec<AutoDiffItem>,
|
||||
config: &ModuleConfig,
|
||||
) -> Result<LtoModuleCodegen<B>, FatalError> {
|
||||
match &self {
|
||||
LtoModuleCodegen::Fat(module) => {
|
||||
B::autodiff(cgcx, &module, diff_fncs, config)?;
|
||||
}
|
||||
_ => panic!("autodiff called with non-fat LTO module"),
|
||||
}
|
||||
|
||||
Ok(self)
|
||||
}
|
||||
}
|
||||
|
||||
pub enum SerializedModule<M: ModuleBufferMethods> {
|
||||
Local(M),
|
||||
FromRlib(Vec<u8>),
|
||||
|
|
|
|||
|
|
@ -397,50 +397,31 @@ impl<B: WriteBackendMethods> CodegenContext<B> {
|
|||
}
|
||||
}
|
||||
|
||||
fn generate_lto_work<B: ExtraBackendMethods>(
|
||||
fn generate_thin_lto_work<B: ExtraBackendMethods>(
|
||||
cgcx: &CodegenContext<B>,
|
||||
autodiff: Vec<AutoDiffItem>,
|
||||
needs_fat_lto: Vec<FatLtoInput<B>>,
|
||||
needs_thin_lto: Vec<(String, B::ThinBuffer)>,
|
||||
import_only_modules: Vec<(SerializedModule<B::ModuleBuffer>, WorkProduct)>,
|
||||
) -> Vec<(WorkItem<B>, u64)> {
|
||||
let _prof_timer = cgcx.prof.generic_activity("codegen_generate_lto_work");
|
||||
let _prof_timer = cgcx.prof.generic_activity("codegen_thin_generate_lto_work");
|
||||
|
||||
if !needs_fat_lto.is_empty() {
|
||||
assert!(needs_thin_lto.is_empty());
|
||||
let mut module =
|
||||
B::run_fat_lto(cgcx, needs_fat_lto, import_only_modules).unwrap_or_else(|e| e.raise());
|
||||
if cgcx.lto == Lto::Fat && !autodiff.is_empty() {
|
||||
let config = cgcx.config(ModuleKind::Regular);
|
||||
module = module.autodiff(cgcx, autodiff, config).unwrap_or_else(|e| e.raise());
|
||||
}
|
||||
// We are adding a single work item, so the cost doesn't matter.
|
||||
vec![(WorkItem::LTO(module), 0)]
|
||||
} else {
|
||||
if !autodiff.is_empty() {
|
||||
let dcx = cgcx.create_dcx();
|
||||
dcx.handle().emit_fatal(AutodiffWithoutLto {});
|
||||
}
|
||||
assert!(needs_fat_lto.is_empty());
|
||||
let (lto_modules, copy_jobs) = B::run_thin_lto(cgcx, needs_thin_lto, import_only_modules)
|
||||
.unwrap_or_else(|e| e.raise());
|
||||
lto_modules
|
||||
.into_iter()
|
||||
.map(|module| {
|
||||
let cost = module.cost();
|
||||
(WorkItem::LTO(module), cost)
|
||||
})
|
||||
.chain(copy_jobs.into_iter().map(|wp| {
|
||||
(
|
||||
WorkItem::CopyPostLtoArtifacts(CachedModuleCodegen {
|
||||
name: wp.cgu_name.clone(),
|
||||
source: wp,
|
||||
}),
|
||||
0, // copying is very cheap
|
||||
)
|
||||
}))
|
||||
.collect()
|
||||
}
|
||||
let (lto_modules, copy_jobs) =
|
||||
B::run_thin_lto(cgcx, needs_thin_lto, import_only_modules).unwrap_or_else(|e| e.raise());
|
||||
lto_modules
|
||||
.into_iter()
|
||||
.map(|module| {
|
||||
let cost = module.cost();
|
||||
(WorkItem::ThinLto(module), cost)
|
||||
})
|
||||
.chain(copy_jobs.into_iter().map(|wp| {
|
||||
(
|
||||
WorkItem::CopyPostLtoArtifacts(CachedModuleCodegen {
|
||||
name: wp.cgu_name.clone(),
|
||||
source: wp,
|
||||
}),
|
||||
0, // copying is very cheap
|
||||
)
|
||||
}))
|
||||
.collect()
|
||||
}
|
||||
|
||||
struct CompiledModules {
|
||||
|
|
@ -470,6 +451,7 @@ pub(crate) fn start_async_codegen<B: ExtraBackendMethods>(
|
|||
backend: B,
|
||||
tcx: TyCtxt<'_>,
|
||||
target_cpu: String,
|
||||
autodiff_items: &[AutoDiffItem],
|
||||
) -> OngoingCodegen<B> {
|
||||
let (coordinator_send, coordinator_receive) = channel();
|
||||
|
||||
|
|
@ -488,6 +470,7 @@ pub(crate) fn start_async_codegen<B: ExtraBackendMethods>(
|
|||
backend.clone(),
|
||||
tcx,
|
||||
&crate_info,
|
||||
autodiff_items,
|
||||
shared_emitter,
|
||||
codegen_worker_send,
|
||||
coordinator_receive,
|
||||
|
|
@ -736,15 +719,23 @@ pub(crate) enum WorkItem<B: WriteBackendMethods> {
|
|||
/// Copy the post-LTO artifacts from the incremental cache to the output
|
||||
/// directory.
|
||||
CopyPostLtoArtifacts(CachedModuleCodegen),
|
||||
/// Performs (Thin)LTO on the given module.
|
||||
LTO(lto::LtoModuleCodegen<B>),
|
||||
/// Performs fat LTO on the given module.
|
||||
FatLto {
|
||||
needs_fat_lto: Vec<FatLtoInput<B>>,
|
||||
import_only_modules: Vec<(SerializedModule<B::ModuleBuffer>, WorkProduct)>,
|
||||
autodiff: Vec<AutoDiffItem>,
|
||||
},
|
||||
/// Performs thin-LTO on the given module.
|
||||
ThinLto(lto::ThinModule<B>),
|
||||
}
|
||||
|
||||
impl<B: WriteBackendMethods> WorkItem<B> {
|
||||
fn module_kind(&self) -> ModuleKind {
|
||||
match *self {
|
||||
WorkItem::Optimize(ref m) => m.kind,
|
||||
WorkItem::CopyPostLtoArtifacts(_) | WorkItem::LTO(_) => ModuleKind::Regular,
|
||||
WorkItem::CopyPostLtoArtifacts(_) | WorkItem::FatLto { .. } | WorkItem::ThinLto(_) => {
|
||||
ModuleKind::Regular
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -792,7 +783,8 @@ impl<B: WriteBackendMethods> WorkItem<B> {
|
|||
match self {
|
||||
WorkItem::Optimize(m) => desc("opt", "optimize module", &m.name),
|
||||
WorkItem::CopyPostLtoArtifacts(m) => desc("cpy", "copy LTO artifacts for", &m.name),
|
||||
WorkItem::LTO(m) => desc("lto", "LTO module", m.name()),
|
||||
WorkItem::FatLto { .. } => desc("lto", "fat LTO module", "everything"),
|
||||
WorkItem::ThinLto(m) => desc("lto", "thin-LTO module", m.name()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -996,12 +988,24 @@ fn execute_copy_from_cache_work_item<B: ExtraBackendMethods>(
|
|||
})
|
||||
}
|
||||
|
||||
fn execute_lto_work_item<B: ExtraBackendMethods>(
|
||||
fn execute_fat_lto_work_item<B: ExtraBackendMethods>(
|
||||
cgcx: &CodegenContext<B>,
|
||||
module: lto::LtoModuleCodegen<B>,
|
||||
needs_fat_lto: Vec<FatLtoInput<B>>,
|
||||
import_only_modules: Vec<(SerializedModule<B::ModuleBuffer>, WorkProduct)>,
|
||||
autodiff: Vec<AutoDiffItem>,
|
||||
module_config: &ModuleConfig,
|
||||
) -> Result<WorkItemResult<B>, FatalError> {
|
||||
let module = module.optimize(cgcx)?;
|
||||
let module = B::run_and_optimize_fat_lto(cgcx, needs_fat_lto, import_only_modules, autodiff)?;
|
||||
let module = B::codegen(cgcx, module, module_config)?;
|
||||
Ok(WorkItemResult::Finished(module))
|
||||
}
|
||||
|
||||
fn execute_thin_lto_work_item<B: ExtraBackendMethods>(
|
||||
cgcx: &CodegenContext<B>,
|
||||
module: lto::ThinModule<B>,
|
||||
module_config: &ModuleConfig,
|
||||
) -> Result<WorkItemResult<B>, FatalError> {
|
||||
let module = B::optimize_thin(cgcx, module)?;
|
||||
finish_intra_module_work(cgcx, module, module_config)
|
||||
}
|
||||
|
||||
|
|
@ -1010,11 +1014,8 @@ fn finish_intra_module_work<B: ExtraBackendMethods>(
|
|||
module: ModuleCodegen<B::Module>,
|
||||
module_config: &ModuleConfig,
|
||||
) -> Result<WorkItemResult<B>, FatalError> {
|
||||
let dcx = cgcx.create_dcx();
|
||||
let dcx = dcx.handle();
|
||||
|
||||
if !cgcx.opts.unstable_opts.combine_cgu || module.kind == ModuleKind::Allocator {
|
||||
let module = B::codegen(cgcx, dcx, module, module_config)?;
|
||||
let module = B::codegen(cgcx, module, module_config)?;
|
||||
Ok(WorkItemResult::Finished(module))
|
||||
} else {
|
||||
Ok(WorkItemResult::NeedsLink(module))
|
||||
|
|
@ -1031,9 +1032,6 @@ pub(crate) enum Message<B: WriteBackendMethods> {
|
|||
/// Sent from a backend worker thread.
|
||||
WorkItem { result: Result<WorkItemResult<B>, Option<WorkerFatalError>>, worker_id: usize },
|
||||
|
||||
/// A vector containing all the AutoDiff tasks that we have to pass to Enzyme.
|
||||
AddAutoDiffItems(Vec<AutoDiffItem>),
|
||||
|
||||
/// The frontend has finished generating something (backend IR or a
|
||||
/// post-LTO artifact) for a codegen unit, and it should be passed to the
|
||||
/// backend. Sent from the main thread.
|
||||
|
|
@ -1100,6 +1098,7 @@ fn start_executing_work<B: ExtraBackendMethods>(
|
|||
backend: B,
|
||||
tcx: TyCtxt<'_>,
|
||||
crate_info: &CrateInfo,
|
||||
autodiff_items: &[AutoDiffItem],
|
||||
shared_emitter: SharedEmitter,
|
||||
codegen_worker_send: Sender<CguMessage>,
|
||||
coordinator_receive: Receiver<Box<dyn Any + Send>>,
|
||||
|
|
@ -1109,6 +1108,7 @@ fn start_executing_work<B: ExtraBackendMethods>(
|
|||
) -> thread::JoinHandle<Result<CompiledModules, ()>> {
|
||||
let coordinator_send = tx_to_llvm_workers;
|
||||
let sess = tcx.sess;
|
||||
let autodiff_items = autodiff_items.to_vec();
|
||||
|
||||
let mut each_linked_rlib_for_lto = Vec::new();
|
||||
drop(link::each_linked_rlib(crate_info, None, &mut |cnum, path| {
|
||||
|
|
@ -1362,7 +1362,6 @@ fn start_executing_work<B: ExtraBackendMethods>(
|
|||
|
||||
// This is where we collect codegen units that have gone all the way
|
||||
// through codegen and LLVM.
|
||||
let mut autodiff_items = Vec::new();
|
||||
let mut compiled_modules = vec![];
|
||||
let mut compiled_allocator_module = None;
|
||||
let mut needs_link = Vec::new();
|
||||
|
|
@ -1474,20 +1473,37 @@ fn start_executing_work<B: ExtraBackendMethods>(
|
|||
let needs_thin_lto = mem::take(&mut needs_thin_lto);
|
||||
let import_only_modules = mem::take(&mut lto_import_only_modules);
|
||||
|
||||
for (work, cost) in generate_lto_work(
|
||||
&cgcx,
|
||||
autodiff_items.clone(),
|
||||
needs_fat_lto,
|
||||
needs_thin_lto,
|
||||
import_only_modules,
|
||||
) {
|
||||
let insertion_index = work_items
|
||||
.binary_search_by_key(&cost, |&(_, cost)| cost)
|
||||
.unwrap_or_else(|e| e);
|
||||
work_items.insert(insertion_index, (work, cost));
|
||||
if !needs_fat_lto.is_empty() {
|
||||
assert!(needs_thin_lto.is_empty());
|
||||
|
||||
work_items.push((
|
||||
WorkItem::FatLto {
|
||||
needs_fat_lto,
|
||||
import_only_modules,
|
||||
autodiff: autodiff_items.clone(),
|
||||
},
|
||||
0,
|
||||
));
|
||||
if cgcx.parallel {
|
||||
helper.request_token();
|
||||
}
|
||||
} else {
|
||||
if !autodiff_items.is_empty() {
|
||||
let dcx = cgcx.create_dcx();
|
||||
dcx.handle().emit_fatal(AutodiffWithoutLto {});
|
||||
}
|
||||
|
||||
for (work, cost) in
|
||||
generate_thin_lto_work(&cgcx, needs_thin_lto, import_only_modules)
|
||||
{
|
||||
let insertion_index = work_items
|
||||
.binary_search_by_key(&cost, |&(_, cost)| cost)
|
||||
.unwrap_or_else(|e| e);
|
||||
work_items.insert(insertion_index, (work, cost));
|
||||
if cgcx.parallel {
|
||||
helper.request_token();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1616,10 +1632,6 @@ fn start_executing_work<B: ExtraBackendMethods>(
|
|||
main_thread_state = MainThreadState::Idle;
|
||||
}
|
||||
|
||||
Message::AddAutoDiffItems(mut items) => {
|
||||
autodiff_items.append(&mut items);
|
||||
}
|
||||
|
||||
Message::CodegenComplete => {
|
||||
if codegen_state != Aborted {
|
||||
codegen_state = Completed;
|
||||
|
|
@ -1702,7 +1714,7 @@ fn start_executing_work<B: ExtraBackendMethods>(
|
|||
let dcx = dcx.handle();
|
||||
let module = B::run_link(&cgcx, dcx, needs_link).map_err(|_| ())?;
|
||||
let module =
|
||||
B::codegen(&cgcx, dcx, module, cgcx.config(ModuleKind::Regular)).map_err(|_| ())?;
|
||||
B::codegen(&cgcx, module, cgcx.config(ModuleKind::Regular)).map_err(|_| ())?;
|
||||
compiled_modules.push(module);
|
||||
}
|
||||
|
||||
|
|
@ -1842,10 +1854,22 @@ fn spawn_work<'a, B: ExtraBackendMethods>(
|
|||
);
|
||||
Ok(execute_copy_from_cache_work_item(&cgcx, m, module_config))
|
||||
}
|
||||
WorkItem::LTO(m) => {
|
||||
WorkItem::FatLto { needs_fat_lto, import_only_modules, autodiff } => {
|
||||
let _timer = cgcx
|
||||
.prof
|
||||
.generic_activity_with_arg("codegen_module_perform_lto", "everything");
|
||||
execute_fat_lto_work_item(
|
||||
&cgcx,
|
||||
needs_fat_lto,
|
||||
import_only_modules,
|
||||
autodiff,
|
||||
module_config,
|
||||
)
|
||||
}
|
||||
WorkItem::ThinLto(m) => {
|
||||
let _timer =
|
||||
cgcx.prof.generic_activity_with_arg("codegen_module_perform_lto", m.name());
|
||||
execute_lto_work_item(&cgcx, m, module_config)
|
||||
execute_thin_lto_work_item(&cgcx, m, module_config)
|
||||
}
|
||||
})
|
||||
};
|
||||
|
|
@ -2082,10 +2106,6 @@ impl<B: ExtraBackendMethods> OngoingCodegen<B> {
|
|||
drop(self.coordinator.sender.send(Box::new(Message::CodegenComplete::<B>)));
|
||||
}
|
||||
|
||||
pub(crate) fn submit_autodiff_items(&self, items: Vec<AutoDiffItem>) {
|
||||
drop(self.coordinator.sender.send(Box::new(Message::<B>::AddAutoDiffItems(items))));
|
||||
}
|
||||
|
||||
pub(crate) fn check_for_errors(&self, sess: &Session) {
|
||||
self.shared_emitter_main.check(sess, false);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -647,7 +647,7 @@ pub fn codegen_crate<B: ExtraBackendMethods>(
|
|||
) -> OngoingCodegen<B> {
|
||||
// Skip crate items and just output metadata in -Z no-codegen mode.
|
||||
if tcx.sess.opts.unstable_opts.no_codegen || !tcx.sess.opts.output_types.should_codegen() {
|
||||
let ongoing_codegen = start_async_codegen(backend, tcx, target_cpu);
|
||||
let ongoing_codegen = start_async_codegen(backend, tcx, target_cpu, &[]);
|
||||
|
||||
ongoing_codegen.codegen_finished(tcx);
|
||||
|
||||
|
|
@ -667,7 +667,6 @@ pub fn codegen_crate<B: ExtraBackendMethods>(
|
|||
// codegen units.
|
||||
let MonoItemPartitions { codegen_units, autodiff_items, .. } =
|
||||
tcx.collect_and_partition_mono_items(());
|
||||
let autodiff_fncs = autodiff_items.to_vec();
|
||||
|
||||
// Force all codegen_unit queries so they are already either red or green
|
||||
// when compile_codegen_unit accesses them. We are not able to re-execute
|
||||
|
|
@ -680,7 +679,7 @@ pub fn codegen_crate<B: ExtraBackendMethods>(
|
|||
}
|
||||
}
|
||||
|
||||
let ongoing_codegen = start_async_codegen(backend.clone(), tcx, target_cpu);
|
||||
let ongoing_codegen = start_async_codegen(backend.clone(), tcx, target_cpu, autodiff_items);
|
||||
|
||||
// Codegen an allocator shim, if necessary.
|
||||
if let Some(kind) = allocator_kind_for_codegen(tcx) {
|
||||
|
|
@ -710,10 +709,6 @@ pub fn codegen_crate<B: ExtraBackendMethods>(
|
|||
);
|
||||
}
|
||||
|
||||
if !autodiff_fncs.is_empty() {
|
||||
ongoing_codegen.submit_autodiff_items(autodiff_fncs);
|
||||
}
|
||||
|
||||
// For better throughput during parallel processing by LLVM, we used to sort
|
||||
// CGUs largest to smallest. This would lead to better thread utilization
|
||||
// by, for example, preventing a large CGU from being processed last and
|
||||
|
|
|
|||
|
|
@ -139,7 +139,8 @@ pub(crate) fn load_vtable<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
|
|||
&& bx.cx().sess().lto() == Lto::Fat
|
||||
{
|
||||
if let Some(trait_ref) = dyn_trait_in_self(bx.tcx(), ty) {
|
||||
let typeid = bx.typeid_metadata(typeid_for_trait_ref(bx.tcx(), trait_ref)).unwrap();
|
||||
let typeid =
|
||||
bx.typeid_metadata(typeid_for_trait_ref(bx.tcx(), trait_ref).as_bytes()).unwrap();
|
||||
let func = bx.type_checked_load(llvtable, vtable_byte_offset, typeid);
|
||||
return func;
|
||||
} else if nonnull {
|
||||
|
|
|
|||
|
|
@ -356,7 +356,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||
LocalRef::Operand(operand) => {
|
||||
// Don't spill operands onto the stack in naked functions.
|
||||
// See: https://github.com/rust-lang/rust/issues/42779
|
||||
let attrs = bx.tcx().codegen_fn_attrs(self.instance.def_id());
|
||||
let attrs = bx.tcx().codegen_instance_attrs(self.instance.def);
|
||||
if attrs.flags.contains(CodegenFnAttrFlags::NAKED) {
|
||||
return;
|
||||
}
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue