Skip to content

Rollup of 8 pull requests #104589

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 34 commits into from
Closed
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
a02ec4c
remove HRTB from `[T]::is_sorted_by{,_key}`
Oct 12, 2022
f3d7b39
add regression test
Oct 12, 2022
3b16c04
`unchecked_{shl|shr}` should use `u32` as the RHS
scottmcm Oct 24, 2022
6c54745
Make `pointer::with_metadata_of` const (+simplify implementation)
WaffleLapkin Oct 28, 2022
d3b5192
Simplify implementation of various pointer methods
WaffleLapkin Oct 28, 2022
422b935
Add `rustc_baked_icu_data` crate.
crlf0710 Nov 5, 2022
18a1de2
Migrate diagnostics list output to use icu list formatter.
crlf0710 Nov 6, 2022
1ebe279
Import icu locale fallback data
crlf0710 Nov 6, 2022
9f6c6bd
Enable icu sync feature for parallel compiler
crlf0710 Nov 6, 2022
4c24176
Include `zh` locale in icu data
crlf0710 Nov 6, 2022
ecaf5f7
Fix compilation issue after rebase
crlf0710 Nov 12, 2022
1c56a53
constify remaining layout methods
CraftSpider Sep 23, 2022
c207dc9
Add stability for alignment
CraftSpider Oct 17, 2022
3860cb1
Update with derive_const
CraftSpider Nov 12, 2022
21c61e1
Add derive_const feature
CraftSpider Nov 13, 2022
c8e5ac4
Fix issue number
CraftSpider Nov 13, 2022
bbcdebd
Use ? instead of match
CraftSpider Nov 13, 2022
d75c76d
Update crate documentation of `rustc_baked_icu_data` crate
crlf0710 Nov 15, 2022
9d4b1f9
Ignore the unchecked-shifts codegen test in debug-assertions builds
scottmcm Nov 16, 2022
19b63bc
Edit docs for `rustc_errors::Handler::stash_diagnostic`
pierwill Nov 16, 2022
4525eb1
rustdoc: use `code-header` class to format enum variants
notriddle Nov 17, 2022
616f34e
rustdoc: update tests for enum variant margin tweak
notriddle Nov 17, 2022
da3c539
Enforce that dyn* casts are actually pointer-sized
compiler-errors Nov 12, 2022
b3da04a
Check both align and size in PointerSized
compiler-errors Nov 15, 2022
39e076a
Only enforce ABI-mandated align, not preferred align is compatible
compiler-errors Nov 16, 2022
3c19543
Rollup merge of #102207 - CraftSpider:const-layout, r=scottmcm
Manishearth Nov 18, 2022
c4fb7f9
Rollup merge of #102977 - lukas-code:is-sorted-hrtb, r=m-ou-se
Manishearth Nov 18, 2022
1bb8339
Rollup merge of #103456 - scottmcm:fix-unchecked-shifts, r=scottmcm
Manishearth Nov 18, 2022
774f17f
Rollup merge of #103701 - WaffleLapkin:__points-at-implementation__--…
Manishearth Nov 18, 2022
2709c2d
Rollup merge of #104047 - crlf0710:icu_based_list_formatting, r=david…
Manishearth Nov 18, 2022
171b519
Rollup merge of #104338 - compiler-errors:pointer-sized, r=eholk
Manishearth Nov 18, 2022
6a8391a
Rollup merge of #104498 - pierwill:stash-diag-docs, r=compiler-errors
Manishearth Nov 18, 2022
75bb4f9
Rollup merge of #104556 - notriddle:notriddle/variant, r=GuillaumeGomez
Manishearth Nov 18, 2022
60b2f24
coalesce lockfile changes
Manishearth Nov 18, 2022
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
180 changes: 177 additions & 3 deletions Cargo.lock
Original file line number Diff line number Diff line change
@@ -211,7 +211,7 @@ checksum = "ba3569f383e8f1598449f1a423e72e99569137b47740b1da11ef19af3d5c3223"
dependencies = [
"lazy_static",
"memchr",
"regex-automata",
"regex-automata 0.1.10",
]

[[package]]
@@ -222,7 +222,7 @@ checksum = "fca0852af221f458706eb0725c03e4ed6c46af9ac98e6a689d5e634215d594dd"
dependencies = [
"memchr",
"once_cell",
"regex-automata",
"regex-automata 0.1.10",
"serde",
]

@@ -1707,6 +1707,73 @@ version = "2.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3c1ad908cc71012b7bea4d0c53ba96a8cba9962f048fa68d143376143d863b7a"

[[package]]
name = "icu_list"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c40218275f081c4493f190357c5395647b06734c2dc3dcb41cc099a0f60168b1"
dependencies = [
"displaydoc",
"icu_locid",
"icu_provider",
"regex-automata 0.2.0",
"writeable",
"zerovec",
]

[[package]]
name = "icu_locid"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "34b3de5d99a0e275fe6193b9586dbf37364daebc0d39c89b5cf8376a53b789e8"
dependencies = [
"displaydoc",
"litemap",
"tinystr",
"writeable",
"zerovec",
]

[[package]]
name = "icu_provider"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2f911086e3c521a8a824d4f8bfd87769645ced2f07ff913b521c0d793be07100"
dependencies = [
"displaydoc",
"icu_locid",
"icu_provider_macros",
"stable_deref_trait",
"writeable",
"yoke",
"zerofrom",
"zerovec",
]

[[package]]
name = "icu_provider_adapters"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "980c71d8a91b246ebbb97847178a4b816eea39d1d550c70ee566384555bb6545"
dependencies = [
"icu_locid",
"icu_provider",
"tinystr",
"yoke",
"zerovec",
]

[[package]]
name = "icu_provider_macros"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "38cf6f5b65cf81f0b4298da647101acbfe6ae0e25263f92bd7a22597e9d6d606"
dependencies = [
"proc-macro2",
"quote",
"syn",
]

[[package]]
name = "idna"
version = "0.2.0"
@@ -2034,6 +2101,12 @@ dependencies = [
"walkdir",
]

[[package]]
name = "litemap"
version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f34a3f4798fac63fb48cf277eefa38f94d3443baff555bb98e4f56bc9092368e"

[[package]]
name = "lld-wrapper"
version = "0.1.0"
@@ -2100,7 +2173,7 @@ version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8263075bb86c5a1b1427b5ae862e8889656f126e9f77c484496e8b47cf5c5558"
dependencies = [
"regex-automata",
"regex-automata 0.1.10",
]

[[package]]
@@ -2927,6 +3000,15 @@ dependencies = [
"regex-syntax",
]

[[package]]
name = "regex-automata"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e9368763f5a9b804326f3af749e16f9abf378d227bcdee7634b13d8f17793782"
dependencies = [
"memchr",
]

[[package]]
name = "regex-syntax"
version = "0.6.26"
@@ -3202,6 +3284,18 @@ dependencies = [
"rustc_span",
]

[[package]]
name = "rustc_baked_icu_data"
version = "0.0.0"
dependencies = [
"icu_list",
"icu_locid",
"icu_provider",
"icu_provider_adapters",
"litemap",
"zerovec",
]

[[package]]
name = "rustc_borrowck"
version = "0.0.0"
@@ -3422,13 +3516,18 @@ version = "0.0.0"
dependencies = [
"fluent-bundle",
"fluent-syntax",
"icu_list",
"icu_locid",
"icu_provider_adapters",
"intl-memoizer",
"rustc_baked_icu_data",
"rustc_data_structures",
"rustc_macros",
"rustc_serialize",
"rustc_span",
"tracing",
"unic-langid",
"writeable",
]

[[package]]
@@ -4934,6 +5033,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f8aeafdfd935e4a7fe16a91ab711fa52d54df84f9c8f7ca5837a9d1d902ef4c2"
dependencies = [
"displaydoc",
"zerovec",
]

[[package]]
@@ -5546,6 +5646,12 @@ version = "0.42.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f40009d85759725a34da6d89a94e63d7bdc50a862acf0dbc7c8e488f1edcb6f5"

[[package]]
name = "writeable"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f8e6ab4f5da1b24daf2c590cfac801bacb27b15b4f050e84eb60149ea726f06b"

[[package]]
name = "xattr"
version = "0.2.2"
@@ -5598,3 +5704,71 @@ checksum = "fe5c30ade05e61656247b2e334a031dfd0cc466fadef865bdcdea8d537951bf1"
dependencies = [
"winapi",
]

[[package]]
name = "yoke"
version = "0.6.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1fe1d55ca72c32d573bfbd5cb2f0ca65a497854c44762957a6d3da96041a5184"
dependencies = [
"serde",
"stable_deref_trait",
"yoke-derive",
"zerofrom",
]

[[package]]
name = "yoke-derive"
version = "0.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1346e4cd025ae818b88566eac7eb65ab33a994ea55f355c86889af2e7e56b14e"
dependencies = [
"proc-macro2",
"quote",
"syn",
"synstructure",
]

[[package]]
name = "zerofrom"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "79e9355fccf72b04b7deaa99ce7a0f6630530acf34045391b74460fcd714de54"
dependencies = [
"zerofrom-derive",
]

[[package]]
name = "zerofrom-derive"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2e8aa86add9ddbd2409c1ed01e033cd457d79b1b1229b64922c25095c595e829"
dependencies = [
"proc-macro2",
"quote",
"syn",
"synstructure",
]

[[package]]
name = "zerovec"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b9d919a74c17749ccb17beaf6405562e413cd94e98ba52ca1e64bbe7eefbd8b8"
dependencies = [
"yoke",
"zerofrom",
"zerovec-derive",
]

[[package]]
name = "zerovec-derive"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "490e5f878c2856225e884c35927e7ea6db3c24cdb7229b72542c7526ad7ed49e"
dependencies = [
"proc-macro2",
"quote",
"syn",
"synstructure",
]
15 changes: 15 additions & 0 deletions compiler/rustc_baked_icu_data/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
[package]
name = "rustc_baked_icu_data"
version = "0.0.0"
edition = "2021"

[dependencies]
icu_list = "1.0.0"
icu_locid = "1.0.0"
icu_provider = "1.0.1"
icu_provider_adapters = "1.0.0"
litemap = "0.6.0"
zerovec = "0.9.0"

[features]
rustc_use_parallel_compiler = ['icu_provider/sync']
42 changes: 42 additions & 0 deletions compiler/rustc_baked_icu_data/src/data/any.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
// @generated
impl AnyProvider for BakedDataProvider {
fn load_any(&self, key: DataKey, req: DataRequest) -> Result<AnyResponse, DataError> {
const ANDLISTV1MARKER: ::icu_provider::DataKeyHash =
::icu_list::provider::AndListV1Marker::KEY.hashed();
const COLLATIONFALLBACKSUPPLEMENTV1MARKER: ::icu_provider::DataKeyHash =
::icu_provider_adapters::fallback::provider::CollationFallbackSupplementV1Marker::KEY
.hashed();
const LOCALEFALLBACKLIKELYSUBTAGSV1MARKER: ::icu_provider::DataKeyHash =
::icu_provider_adapters::fallback::provider::LocaleFallbackLikelySubtagsV1Marker::KEY
.hashed();
const LOCALEFALLBACKPARENTSV1MARKER: ::icu_provider::DataKeyHash =
::icu_provider_adapters::fallback::provider::LocaleFallbackParentsV1Marker::KEY
.hashed();
#[allow(clippy::match_single_binding)]
match key.hashed() {
ANDLISTV1MARKER => list::and_v1::DATA
.get_by(|k| req.locale.strict_cmp(k.as_bytes()).reverse())
.copied()
.map(AnyPayload::from_static_ref)
.ok_or(DataErrorKind::MissingLocale),
COLLATIONFALLBACKSUPPLEMENTV1MARKER => fallback::supplement::co_v1::DATA
.get_by(|k| req.locale.strict_cmp(k.as_bytes()).reverse())
.copied()
.map(AnyPayload::from_static_ref)
.ok_or(DataErrorKind::MissingLocale),
LOCALEFALLBACKLIKELYSUBTAGSV1MARKER => fallback::likelysubtags_v1::DATA
.get_by(|k| req.locale.strict_cmp(k.as_bytes()).reverse())
.copied()
.map(AnyPayload::from_static_ref)
.ok_or(DataErrorKind::MissingLocale),
LOCALEFALLBACKPARENTSV1MARKER => fallback::parents_v1::DATA
.get_by(|k| req.locale.strict_cmp(k.as_bytes()).reverse())
.copied()
.map(AnyPayload::from_static_ref)
.ok_or(DataErrorKind::MissingLocale),
_ => Err(DataErrorKind::MissingDataKey),
}
.map_err(|e| e.with_req(key, req))
.map(|payload| AnyResponse { payload: Some(payload), metadata: Default::default() })
}
}
733 changes: 733 additions & 0 deletions compiler/rustc_baked_icu_data/src/data/fallback/likelysubtags_v1.rs

Large diffs are not rendered by default.

4 changes: 4 additions & 0 deletions compiler/rustc_baked_icu_data/src/data/fallback/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
// @generated
pub mod likelysubtags_v1;
pub mod parents_v1;
pub mod supplement;
207 changes: 207 additions & 0 deletions compiler/rustc_baked_icu_data/src/data/fallback/parents_v1.rs

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
// @generated
type DataStruct = < :: icu_provider_adapters :: fallback :: provider :: CollationFallbackSupplementV1Marker as :: icu_provider :: DataMarker > :: Yokeable ;
pub static DATA: litemap::LiteMap<&str, &DataStruct, &[(&str, &DataStruct)]> =
litemap::LiteMap::from_sorted_store_unchecked(&[("und", UND)]);
static UND: &DataStruct =
&::icu_provider_adapters::fallback::provider::LocaleFallbackSupplementV1 {
parents: unsafe {
#[allow(unused_unsafe)]
::zerovec::ZeroMap::from_parts_unchecked(
unsafe {
::zerovec::VarZeroVec::from_bytes_unchecked(&[
1u8, 0u8, 0u8, 0u8, 0u8, 0u8, 121u8, 117u8, 101u8,
])
},
unsafe {
::zerovec::ZeroVec::from_bytes_unchecked(&[
122u8, 104u8, 0u8, 1u8, 72u8, 97u8, 110u8, 116u8, 0u8, 0u8, 0u8, 0u8,
])
},
)
},
unicode_extension_defaults: unsafe {
#[allow(unused_unsafe)]
::zerovec::ZeroMap2d::from_parts_unchecked(
unsafe { ::zerovec::ZeroVec::from_bytes_unchecked(&[99u8, 111u8]) },
unsafe { ::zerovec::ZeroVec::from_bytes_unchecked(&[2u8, 0u8, 0u8, 0u8]) },
unsafe {
::zerovec::VarZeroVec::from_bytes_unchecked(&[
2u8, 0u8, 0u8, 0u8, 0u8, 0u8, 2u8, 0u8, 122u8, 104u8, 122u8, 104u8, 45u8,
72u8, 97u8, 110u8, 116u8,
])
},
unsafe {
::zerovec::VarZeroVec::from_bytes_unchecked(&[
2u8, 0u8, 0u8, 0u8, 0u8, 0u8, 6u8, 0u8, 112u8, 105u8, 110u8, 121u8, 105u8,
110u8, 115u8, 116u8, 114u8, 111u8, 107u8, 101u8,
])
},
)
},
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
// @generated
pub mod co_v1;
1,161 changes: 1,161 additions & 0 deletions compiler/rustc_baked_icu_data/src/data/list/and_v1.rs

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions compiler/rustc_baked_icu_data/src/data/list/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
// @generated
pub mod and_v1;
90 changes: 90 additions & 0 deletions compiler/rustc_baked_icu_data/src/data/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
// @generated
mod fallback;
mod list;
/// This data provider was programmatically generated by [`icu_datagen`](
/// https://unicode-org.github.io/icu4x-docs/doc/icu_datagen/enum.Out.html#variant.Module).
#[non_exhaustive]
pub struct BakedDataProvider;
use ::icu_provider::prelude::*;
impl DataProvider<::icu_list::provider::AndListV1Marker> for BakedDataProvider {
fn load(
&self,
req: DataRequest,
) -> Result<DataResponse<::icu_list::provider::AndListV1Marker>, DataError> {
Ok(DataResponse {
metadata: Default::default(),
payload: Some(DataPayload::from_owned(zerofrom::ZeroFrom::zero_from(
*list::and_v1::DATA
.get_by(|k| req.locale.strict_cmp(k.as_bytes()).reverse())
.ok_or_else(|| {
DataErrorKind::MissingLocale
.with_req(::icu_list::provider::AndListV1Marker::KEY, req)
})?,
))),
})
}
}
impl DataProvider<::icu_provider_adapters::fallback::provider::CollationFallbackSupplementV1Marker>
for BakedDataProvider
{
fn load(
&self,
req: DataRequest,
) -> Result<
DataResponse<
::icu_provider_adapters::fallback::provider::CollationFallbackSupplementV1Marker,
>,
DataError,
> {
Ok(DataResponse {
metadata: Default::default(),
payload: Some(DataPayload::from_owned(zerofrom::ZeroFrom::zero_from(
*fallback::supplement::co_v1::DATA.get_by(|k| req.locale.strict_cmp(k.as_bytes()).reverse()).ok_or_else(|| {
DataErrorKind::MissingLocale.with_req(::icu_provider_adapters::fallback::provider::CollationFallbackSupplementV1Marker::KEY, req)
})?,
))),
})
}
}
impl DataProvider<::icu_provider_adapters::fallback::provider::LocaleFallbackLikelySubtagsV1Marker>
for BakedDataProvider
{
fn load(
&self,
req: DataRequest,
) -> Result<
DataResponse<
::icu_provider_adapters::fallback::provider::LocaleFallbackLikelySubtagsV1Marker,
>,
DataError,
> {
Ok(DataResponse {
metadata: Default::default(),
payload: Some(DataPayload::from_owned(zerofrom::ZeroFrom::zero_from(
*fallback::likelysubtags_v1::DATA.get_by(|k| req.locale.strict_cmp(k.as_bytes()).reverse()).ok_or_else(|| {
DataErrorKind::MissingLocale.with_req(::icu_provider_adapters::fallback::provider::LocaleFallbackLikelySubtagsV1Marker::KEY, req)
})?,
))),
})
}
}
impl DataProvider<::icu_provider_adapters::fallback::provider::LocaleFallbackParentsV1Marker>
for BakedDataProvider
{
fn load(
&self,
req: DataRequest,
) -> Result<
DataResponse<::icu_provider_adapters::fallback::provider::LocaleFallbackParentsV1Marker>,
DataError,
> {
Ok(DataResponse {
metadata: Default::default(),
payload: Some(DataPayload::from_owned(zerofrom::ZeroFrom::zero_from(
*fallback::parents_v1::DATA.get_by(|k| req.locale.strict_cmp(k.as_bytes()).reverse()).ok_or_else(|| {
DataErrorKind::MissingLocale.with_req(::icu_provider_adapters::fallback::provider::LocaleFallbackParentsV1Marker::KEY, req)
})?,
))),
})
}
}
46 changes: 46 additions & 0 deletions compiler/rustc_baked_icu_data/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
//! This crate contains pre-baked ICU4X data, generated by `icu4x-datagen`. The tool
//! fetches locale data from CLDR and transforms them into const code in statics that
//! ICU4X can load, via databake. `lib.rs` in this crate is manually written, but all
//! other code is generated.
//!
//! This crate can be regenerated when there's a new CLDR version, though that is unlikely
//! to result in changes in most cases (currently this only covers list formatting data, which
//! is rather stable). It may need to be regenerated when updating ICU4X versions, especially
//! across major versions, in case it fails to compile after an update.
//!
//! It must be regenerated when adding new locales to Rust, or if Rust's usage of ICU4X
//! grows to need more kinds of data.
//!
//! To regenerate the data, run this command:
//!
//! ```text
//! icu4x-datagen -W --pretty --fingerprint --use-separate-crates \
//! --format mod -l en es fr it ja pt ru tr zh zh-Hans zh-Hant \
//! -k list/and@1 fallback/likelysubtags@1 fallback/parents@1 fallback/supplement/co@1 \
//! --cldr-tag latest --icuexport-tag latest -o src/data
//! ```
#![allow(elided_lifetimes_in_paths)]

mod data {
include!("data/mod.rs");
include!("data/any.rs");
}

pub use data::BakedDataProvider;

pub const fn baked_data_provider() -> BakedDataProvider {
data::BakedDataProvider
}

pub mod supported_locales {
pub const EN: icu_locid::Locale = icu_locid::locale!("en");
pub const ES: icu_locid::Locale = icu_locid::locale!("es");
pub const FR: icu_locid::Locale = icu_locid::locale!("fr");
pub const IT: icu_locid::Locale = icu_locid::locale!("it");
pub const JA: icu_locid::Locale = icu_locid::locale!("ja");
pub const PT: icu_locid::Locale = icu_locid::locale!("pt");
pub const RU: icu_locid::Locale = icu_locid::locale!("ru");
pub const TR: icu_locid::Locale = icu_locid::locale!("tr");
pub const ZH_HANS: icu_locid::Locale = icu_locid::locale!("zh-Hans");
pub const ZH_HANT: icu_locid::Locale = icu_locid::locale!("zh-Hant");
}
8 changes: 8 additions & 0 deletions compiler/rustc_error_messages/Cargo.toml
Original file line number Diff line number Diff line change
@@ -9,9 +9,17 @@ edition = "2021"
fluent-bundle = "0.15.2"
fluent-syntax = "0.11"
intl-memoizer = "0.5.1"
rustc_baked_icu_data = { path = "../rustc_baked_icu_data" }
rustc_data_structures = { path = "../rustc_data_structures" }
rustc_serialize = { path = "../rustc_serialize" }
rustc_span = { path = "../rustc_span" }
rustc_macros = { path = "../rustc_macros" }
tracing = "0.1"
unic-langid = { version = "0.9.0", features = ["macros"] }
icu_list = "1.0.0"
writeable = "0.5.0"
icu_locid = "1.0.0"
icu_provider_adapters = "1.0.0"

[features]
rustc_use_parallel_compiler = ['rustc_baked_icu_data/rustc_use_parallel_compiler']
93 changes: 91 additions & 2 deletions compiler/rustc_error_messages/src/lib.rs
Original file line number Diff line number Diff line change
@@ -10,6 +10,7 @@ extern crate tracing;

use fluent_bundle::FluentResource;
use fluent_syntax::parser::ParserError;
use icu_provider_adapters::fallback::{LocaleFallbackProvider, LocaleFallbacker};
use rustc_data_structures::sync::Lrc;
use rustc_macros::{fluent_messages, Decodable, Encodable};
use rustc_span::Span;
@@ -30,8 +31,7 @@ use intl_memoizer::concurrent::IntlLangMemoizer;
#[cfg(not(parallel_compiler))]
use intl_memoizer::IntlLangMemoizer;

pub use fluent_bundle::{self, FluentArgs, FluentError, FluentValue};

pub use fluent_bundle::{self, types::FluentType, FluentArgs, FluentError, FluentValue};
pub use unic_langid::{langid, LanguageIdentifier};

// Generates `DEFAULT_LOCALE_RESOURCES` static and `fluent_generated` module.
@@ -541,3 +541,92 @@ impl From<Vec<Span>> for MultiSpan {
MultiSpan::from_spans(spans)
}
}

fn icu_locale_from_unic_langid(lang: LanguageIdentifier) -> Option<icu_locid::Locale> {
icu_locid::Locale::try_from_bytes(lang.to_string().as_bytes()).ok()
}

pub fn fluent_value_from_str_list_sep_by_and<'source>(
l: Vec<Cow<'source, str>>,
) -> FluentValue<'source> {
// Fluent requires 'static value here for its AnyEq usages.
#[derive(Clone, PartialEq, Debug)]
struct FluentStrListSepByAnd(Vec<String>);

impl FluentType for FluentStrListSepByAnd {
fn duplicate(&self) -> Box<dyn FluentType + Send> {
Box::new(self.clone())
}

fn as_string(&self, intls: &intl_memoizer::IntlLangMemoizer) -> Cow<'static, str> {
let result = intls
.with_try_get::<MemoizableListFormatter, _, _>((), |list_formatter| {
list_formatter.format_to_string(self.0.iter())
})
.unwrap();
Cow::Owned(result)
}

#[cfg(not(parallel_compiler))]
fn as_string_threadsafe(
&self,
_intls: &intl_memoizer::concurrent::IntlLangMemoizer,
) -> Cow<'static, str> {
unreachable!("`as_string_threadsafe` is not used in non-parallel rustc")
}

#[cfg(parallel_compiler)]
fn as_string_threadsafe(
&self,
intls: &intl_memoizer::concurrent::IntlLangMemoizer,
) -> Cow<'static, str> {
let result = intls
.with_try_get::<MemoizableListFormatter, _, _>((), |list_formatter| {
list_formatter.format_to_string(self.0.iter())
})
.unwrap();
Cow::Owned(result)
}
}

struct MemoizableListFormatter(icu_list::ListFormatter);

impl std::ops::Deref for MemoizableListFormatter {
type Target = icu_list::ListFormatter;
fn deref(&self) -> &Self::Target {
&self.0
}
}

impl intl_memoizer::Memoizable for MemoizableListFormatter {
type Args = ();
type Error = ();

fn construct(lang: LanguageIdentifier, _args: Self::Args) -> Result<Self, Self::Error>
where
Self: Sized,
{
let baked_data_provider = rustc_baked_icu_data::baked_data_provider();
let locale_fallbacker =
LocaleFallbacker::try_new_with_any_provider(&baked_data_provider)
.expect("Failed to create fallback provider");
let data_provider =
LocaleFallbackProvider::new_with_fallbacker(baked_data_provider, locale_fallbacker);
let locale = icu_locale_from_unic_langid(lang)
.unwrap_or_else(|| rustc_baked_icu_data::supported_locales::EN);
let list_formatter =
icu_list::ListFormatter::try_new_and_with_length_with_any_provider(
&data_provider,
&locale.into(),
icu_list::ListLength::Wide,
)
.expect("Failed to create list formatter");

Ok(MemoizableListFormatter(list_formatter))
}
}

let l = l.into_iter().map(|x| x.into_owned()).collect();

FluentValue::Custom(Box::new(FluentStrListSepByAnd(l)))
}
3 changes: 3 additions & 0 deletions compiler/rustc_errors/Cargo.toml
Original file line number Diff line number Diff line change
@@ -27,3 +27,6 @@ serde_json = "1.0.59"

[target.'cfg(windows)'.dependencies]
winapi = { version = "0.3", features = [ "handleapi", "synchapi", "winbase" ] }

[features]
rustc_use_parallel_compiler = ['rustc_error_messages/rustc_use_parallel_compiler']
6 changes: 6 additions & 0 deletions compiler/rustc_errors/src/diagnostic.rs
Original file line number Diff line number Diff line change
@@ -4,6 +4,7 @@ use crate::{
SubdiagnosticMessage, Substitution, SubstitutionPart, SuggestionStyle,
};
use rustc_data_structures::fx::FxHashMap;
use rustc_error_messages::fluent_value_from_str_list_sep_by_and;
use rustc_error_messages::FluentValue;
use rustc_lint_defs::{Applicability, LintExpectationId};
use rustc_span::edition::LATEST_STABLE_EDITION;
@@ -34,6 +35,7 @@ pub type DiagnosticArgName<'source> = Cow<'source, str>;
pub enum DiagnosticArgValue<'source> {
Str(Cow<'source, str>),
Number(usize),
StrListSepByAnd(Vec<Cow<'source, str>>),
}

/// Converts a value of a type into a `DiagnosticArg` (typically a field of an `IntoDiagnostic`
@@ -49,6 +51,9 @@ impl<'source> IntoDiagnosticArg for DiagnosticArgValue<'source> {
match self {
DiagnosticArgValue::Str(s) => DiagnosticArgValue::Str(Cow::Owned(s.into_owned())),
DiagnosticArgValue::Number(n) => DiagnosticArgValue::Number(n),
DiagnosticArgValue::StrListSepByAnd(l) => DiagnosticArgValue::StrListSepByAnd(
l.into_iter().map(|s| Cow::Owned(s.into_owned())).collect(),
),
}
}
}
@@ -58,6 +63,7 @@ impl<'source> Into<FluentValue<'source>> for DiagnosticArgValue<'source> {
match self {
DiagnosticArgValue::Str(s) => From::from(s),
DiagnosticArgValue::Number(n) => From::from(n),
DiagnosticArgValue::StrListSepByAnd(l) => fluent_value_from_str_list_sep_by_and(l),
}
}
}
21 changes: 3 additions & 18 deletions compiler/rustc_errors/src/diagnostic_impls.rs
Original file line number Diff line number Diff line change
@@ -11,7 +11,6 @@ use rustc_target::abi::TargetDataLayoutErrors;
use rustc_target::spec::{PanicStrategy, SplitDebuginfo, StackProtector, TargetTriple};
use std::borrow::Cow;
use std::fmt;
use std::fmt::Write;
use std::num::ParseIntError;
use std::path::{Path, PathBuf};
use std::process::ExitStatus;
@@ -191,23 +190,9 @@ impl From<Vec<Symbol>> for DiagnosticSymbolList {

impl IntoDiagnosticArg for DiagnosticSymbolList {
fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> {
// FIXME: replace the logic here with a real list formatter
let symbols = match &self.0[..] {
[symbol] => format!("`{symbol}`"),
[symbol, last] => {
format!("`{symbol}` and `{last}`",)
}
[symbols @ .., last] => {
let mut result = String::new();
for symbol in symbols {
write!(result, "`{symbol}`, ").unwrap();
}
write!(result, "and `{last}`").unwrap();
result
}
[] => unreachable!(),
};
DiagnosticArgValue::Str(Cow::Owned(symbols))
DiagnosticArgValue::StrListSepByAnd(
self.0.into_iter().map(|sym| Cow::Owned(format!("`{sym}`"))).collect(),
)
}
}

5 changes: 3 additions & 2 deletions compiler/rustc_errors/src/lib.rs
Original file line number Diff line number Diff line change
@@ -644,13 +644,14 @@ impl Handler {
inner.stashed_diagnostics = Default::default();
}

/// Stash a given diagnostic with the given `Span` and `StashKey` as the key for later stealing.
/// Stash a given diagnostic with the given `Span` and [`StashKey`] as the key.
/// Retrieve a stashed diagnostic with `steal_diagnostic`.
pub fn stash_diagnostic(&self, span: Span, key: StashKey, diag: Diagnostic) {
let mut inner = self.inner.borrow_mut();
inner.stash((span, key), diag);
}

/// Steal a previously stashed diagnostic with the given `Span` and `StashKey` as the key.
/// Steal a previously stashed diagnostic with the given `Span` and [`StashKey`] as the key.
pub fn steal_diagnostic(&self, span: Span, key: StashKey) -> Option<DiagnosticBuilder<'_, ()>> {
let mut inner = self.inner.borrow_mut();
inner.steal((span, key)).map(|diag| DiagnosticBuilder::new_diagnostic(self, diag))
2 changes: 2 additions & 0 deletions compiler/rustc_hir/src/lang_items.rs
Original file line number Diff line number Diff line change
@@ -270,6 +270,8 @@ language_item_table! {
TryTraitBranch, sym::branch, branch_fn, Target::Method(MethodKind::Trait { body: false }), GenericRequirement::None;
TryTraitFromYeet, sym::from_yeet, from_yeet_fn, Target::Fn, GenericRequirement::None;

PointerSized, sym::pointer_sized, pointer_sized, Target::Trait, GenericRequirement::Exact(0);

PollReady, sym::Ready, poll_ready_variant, Target::Variant, GenericRequirement::None;
PollPending, sym::Pending, poll_pending_variant, Target::Variant, GenericRequirement::None;

33 changes: 25 additions & 8 deletions compiler/rustc_hir_typeck/src/coercion.rs
Original file line number Diff line number Diff line change
@@ -775,7 +775,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {

// Check the obligations of the cast -- for example, when casting
// `usize` to `dyn* Clone + 'static`:
let obligations = predicates
let mut obligations: Vec<_> = predicates
.iter()
.map(|predicate| {
// For each existential predicate (e.g., `?Self: Clone`) substitute
@@ -785,16 +785,33 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
let predicate = predicate.with_self_ty(self.tcx, a);
Obligation::new(self.tcx, self.cause.clone(), self.param_env, predicate)
})
// Enforce the region bound (e.g., `usize: 'static`, in our example).
.chain([Obligation::new(
.chain([
// Enforce the region bound (e.g., `usize: 'static`, in our example).
Obligation::new(
self.tcx,
self.cause.clone(),
self.param_env,
ty::Binder::dummy(ty::PredicateKind::TypeOutlives(ty::OutlivesPredicate(
a, b_region,
))),
),
])
.collect();

// Enforce that the type is `usize`/pointer-sized. For now, only those
// can be coerced to `dyn*`, except for `dyn* -> dyn*` upcasts.
if !a.is_dyn_star() {
obligations.push(Obligation::new(
self.tcx,
self.cause.clone(),
self.param_env,
self.tcx.mk_predicate(ty::Binder::dummy(ty::PredicateKind::TypeOutlives(
ty::OutlivesPredicate(a, b_region),
))),
)])
.collect();
ty::Binder::dummy(ty::TraitRef::new(
self.tcx.require_lang_item(hir::LangItem::PointerSized, Some(self.cause.span)),
self.tcx.mk_substs_trait(a, &[]),
))
.to_poly_trait_predicate(),
));
}

Ok(InferOk {
value: (vec![Adjustment { kind: Adjust::DynStar, target: b }], b),
2 changes: 1 addition & 1 deletion compiler/rustc_interface/Cargo.toml
Original file line number Diff line number Diff line change
@@ -53,4 +53,4 @@ rustc_target = { path = "../rustc_target" }

[features]
llvm = ['rustc_codegen_llvm']
rustc_use_parallel_compiler = ['rayon', 'rustc-rayon-core', 'rustc_query_impl/rustc_use_parallel_compiler']
rustc_use_parallel_compiler = ['rayon', 'rustc-rayon-core', 'rustc_query_impl/rustc_use_parallel_compiler', 'rustc_errors/rustc_use_parallel_compiler']
1 change: 1 addition & 0 deletions compiler/rustc_span/src/symbol.rs
Original file line number Diff line number Diff line change
@@ -1067,6 +1067,7 @@ symbols! {
plugins,
pointee_trait,
pointer,
pointer_sized,
poll,
position,
post_dash_lto: "post-lto",
Original file line number Diff line number Diff line change
@@ -304,6 +304,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
self.assemble_candidates_for_transmutability(obligation, &mut candidates);
} else if lang_items.tuple_trait() == Some(def_id) {
self.assemble_candidate_for_tuple(obligation, &mut candidates);
} else if lang_items.pointer_sized() == Some(def_id) {
self.assemble_candidate_for_ptr_sized(obligation, &mut candidates);
} else {
if lang_items.clone_trait() == Some(def_id) {
// Same builtin conditions as `Copy`, i.e., every type which has builtin support
@@ -1047,4 +1049,30 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
| ty::Placeholder(_) => {}
}
}

fn assemble_candidate_for_ptr_sized(
&mut self,
obligation: &TraitObligation<'tcx>,
candidates: &mut SelectionCandidateSet<'tcx>,
) {
// The regions of a type don't affect the size of the type
let self_ty = self
.tcx()
.erase_regions(self.tcx().erase_late_bound_regions(obligation.predicate.self_ty()));

// But if there are inference variables, we have to wait until it's resolved.
if self_ty.has_non_region_infer() {
candidates.ambiguous = true;
return;
}

let usize_layout =
self.tcx().layout_of(ty::ParamEnv::empty().and(self.tcx().types.usize)).unwrap().layout;
if let Ok(layout) = self.tcx().layout_of(obligation.param_env.and(self_ty))
&& layout.layout.size() == usize_layout.size()
&& layout.layout.align().abi == usize_layout.align().abi
{
candidates.vec.push(BuiltinCandidate { has_nested: false });
}
}
}
36 changes: 25 additions & 11 deletions library/core/src/alloc/layout.rs
Original file line number Diff line number Diff line change
@@ -157,9 +157,10 @@ impl Layout {
/// allocate backing structure for `T` (which could be a trait
/// or other unsized type like a slice).
#[stable(feature = "alloc_layout", since = "1.28.0")]
#[rustc_const_unstable(feature = "const_alloc_layout", issue = "67521")]
#[must_use]
#[inline]
pub fn for_value<T: ?Sized>(t: &T) -> Self {
pub const fn for_value<T: ?Sized>(t: &T) -> Self {
let (size, align) = (mem::size_of_val(t), mem::align_of_val(t));
// SAFETY: see rationale in `new` for why this is using the unsafe variant
unsafe { Layout::from_size_align_unchecked(size, align) }
@@ -191,8 +192,9 @@ impl Layout {
/// [trait object]: ../../book/ch17-02-trait-objects.html
/// [extern type]: ../../unstable-book/language-features/extern-types.html
#[unstable(feature = "layout_for_ptr", issue = "69835")]
#[rustc_const_unstable(feature = "const_alloc_layout", issue = "67521")]
#[must_use]
pub unsafe fn for_value_raw<T: ?Sized>(t: *const T) -> Self {
pub const unsafe fn for_value_raw<T: ?Sized>(t: *const T) -> Self {
// SAFETY: we pass along the prerequisites of these functions to the caller
let (size, align) = unsafe { (mem::size_of_val_raw(t), mem::align_of_val_raw(t)) };
// SAFETY: see rationale in `new` for why this is using the unsafe variant
@@ -229,8 +231,9 @@ impl Layout {
/// Returns an error if the combination of `self.size()` and the given
/// `align` violates the conditions listed in [`Layout::from_size_align`].
#[stable(feature = "alloc_layout_manipulation", since = "1.44.0")]
#[rustc_const_unstable(feature = "const_alloc_layout", issue = "67521")]
#[inline]
pub fn align_to(&self, align: usize) -> Result<Self, LayoutError> {
pub const fn align_to(&self, align: usize) -> Result<Self, LayoutError> {
Layout::from_size_align(self.size(), cmp::max(self.align(), align))
}

@@ -287,10 +290,11 @@ impl Layout {
/// This is equivalent to adding the result of `padding_needed_for`
/// to the layout's current size.
#[stable(feature = "alloc_layout_manipulation", since = "1.44.0")]
#[rustc_const_unstable(feature = "const_alloc_layout", issue = "67521")]
#[must_use = "this returns a new `Layout`, \
without modifying the original"]
#[inline]
pub fn pad_to_align(&self) -> Layout {
pub const fn pad_to_align(&self) -> Layout {
let pad = self.padding_needed_for(self.align());
// This cannot overflow. Quoting from the invariant of Layout:
// > `size`, when rounded up to the nearest multiple of `align`,
@@ -311,8 +315,9 @@ impl Layout {
///
/// On arithmetic overflow, returns `LayoutError`.
#[unstable(feature = "alloc_layout_extra", issue = "55724")]
#[rustc_const_unstable(feature = "const_alloc_layout", issue = "67521")]
#[inline]
pub fn repeat(&self, n: usize) -> Result<(Self, usize), LayoutError> {
pub const fn repeat(&self, n: usize) -> Result<(Self, usize), LayoutError> {
// This cannot overflow. Quoting from the invariant of Layout:
// > `size`, when rounded up to the nearest multiple of `align`,
// > must not overflow isize (i.e., the rounded value must be
@@ -321,7 +326,8 @@ impl Layout {
let alloc_size = padded_size.checked_mul(n).ok_or(LayoutError)?;

// The safe constructor is called here to enforce the isize size limit.
Layout::from_size_alignment(alloc_size, self.align).map(|layout| (layout, padded_size))
let layout = Layout::from_size_alignment(alloc_size, self.align)?;
Ok((layout, padded_size))
}

/// Creates a layout describing the record for `self` followed by
@@ -370,8 +376,9 @@ impl Layout {
/// # assert_eq!(repr_c(&[u64, u32, u16, u32]), Ok((s, vec![0, 8, 12, 16])));
/// ```
#[stable(feature = "alloc_layout_manipulation", since = "1.44.0")]
#[rustc_const_unstable(feature = "const_alloc_layout", issue = "67521")]
#[inline]
pub fn extend(&self, next: Self) -> Result<(Self, usize), LayoutError> {
pub const fn extend(&self, next: Self) -> Result<(Self, usize), LayoutError> {
let new_align = cmp::max(self.align, next.align);
let pad = self.padding_needed_for(next.align());

@@ -396,8 +403,9 @@ impl Layout {
///
/// On arithmetic overflow, returns `LayoutError`.
#[unstable(feature = "alloc_layout_extra", issue = "55724")]
#[rustc_const_unstable(feature = "const_alloc_layout", issue = "67521")]
#[inline]
pub fn repeat_packed(&self, n: usize) -> Result<Self, LayoutError> {
pub const fn repeat_packed(&self, n: usize) -> Result<Self, LayoutError> {
let size = self.size().checked_mul(n).ok_or(LayoutError)?;
// The safe constructor is called here to enforce the isize size limit.
Layout::from_size_alignment(size, self.align)
@@ -410,8 +418,9 @@ impl Layout {
///
/// On arithmetic overflow, returns `LayoutError`.
#[unstable(feature = "alloc_layout_extra", issue = "55724")]
#[rustc_const_unstable(feature = "const_alloc_layout", issue = "67521")]
#[inline]
pub fn extend_packed(&self, next: Self) -> Result<Self, LayoutError> {
pub const fn extend_packed(&self, next: Self) -> Result<Self, LayoutError> {
let new_size = self.size().checked_add(next.size()).ok_or(LayoutError)?;
// The safe constructor is called here to enforce the isize size limit.
Layout::from_size_alignment(new_size, self.align)
@@ -422,13 +431,18 @@ impl Layout {
/// On arithmetic overflow or when the total size would exceed
/// `isize::MAX`, returns `LayoutError`.
#[stable(feature = "alloc_layout_manipulation", since = "1.44.0")]
#[rustc_const_unstable(feature = "const_alloc_layout", issue = "67521")]
#[inline]
pub fn array<T>(n: usize) -> Result<Self, LayoutError> {
pub const fn array<T>(n: usize) -> Result<Self, LayoutError> {
// Reduce the amount of code we need to monomorphize per `T`.
return inner(mem::size_of::<T>(), Alignment::of::<T>(), n);

#[inline]
fn inner(element_size: usize, align: Alignment, n: usize) -> Result<Layout, LayoutError> {
const fn inner(
element_size: usize,
align: Alignment,
n: usize,
) -> Result<Layout, LayoutError> {
// We need to check two things about the size:
// - That the total size won't overflow a `usize`, and
// - That the total size still fits in an `isize`.
6 changes: 6 additions & 0 deletions library/core/src/lib.rs
Original file line number Diff line number Diff line change
@@ -98,6 +98,8 @@
// Library features:
#![feature(const_align_offset)]
#![feature(const_align_of_val)]
#![feature(const_align_of_val_raw)]
#![feature(const_alloc_layout)]
#![feature(const_arguments_as_str)]
#![feature(const_array_into_iter_constructors)]
#![feature(const_bigint_helper_methods)]
@@ -131,12 +133,14 @@
#![feature(const_pin)]
#![feature(const_ptr_sub_ptr)]
#![feature(const_replace)]
#![feature(const_result_drop)]
#![feature(const_ptr_as_ref)]
#![feature(const_ptr_is_null)]
#![feature(const_ptr_read)]
#![feature(const_ptr_write)]
#![feature(const_raw_ptr_comparison)]
#![feature(const_size_of_val)]
#![feature(const_size_of_val_raw)]
#![feature(const_slice_from_raw_parts_mut)]
#![feature(const_slice_ptr_len)]
#![feature(const_slice_split_at_mut)]
@@ -151,10 +155,12 @@
#![feature(const_unsafecell_get_mut)]
#![feature(const_waker)]
#![feature(core_panic)]
#![cfg_attr(not(bootstrap), feature(derive_const))]
#![feature(duration_consts_float)]
#![feature(maybe_uninit_uninit_array)]
#![feature(ptr_alignment_type)]
#![feature(ptr_metadata)]
#![feature(set_ptr_value)]
#![feature(slice_ptr_get)]
#![feature(slice_split_at_unchecked)]
#![feature(str_internals)]
9 changes: 9 additions & 0 deletions library/core/src/marker.rs
Original file line number Diff line number Diff line change
@@ -809,6 +809,15 @@ pub trait Destruct {}
#[cfg_attr(not(bootstrap), rustc_deny_explicit_impl)]
pub trait Tuple {}

/// A marker for things
#[unstable(feature = "pointer_sized_trait", issue = "none")]
#[cfg_attr(not(bootstrap), lang = "pointer_sized")]
#[rustc_on_unimplemented(
message = "`{Self}` needs to be a pointer-sized type",
label = "`{Self}` needs to be a pointer-sized type"
)]
pub trait PointerSized {}

/// Implementations of `Copy` for primitive types.
///
/// Implementations that cannot be described in Rust
16 changes: 10 additions & 6 deletions library/core/src/num/int_macros.rs
Original file line number Diff line number Diff line change
@@ -761,10 +761,11 @@ macro_rules! int_impl {
#[rustc_const_unstable(feature = "const_inherent_unchecked_arith", issue = "85122")]
#[inline(always)]
#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
pub const unsafe fn unchecked_shl(self, rhs: Self) -> Self {
pub const unsafe fn unchecked_shl(self, rhs: u32) -> Self {
// SAFETY: the caller must uphold the safety contract for
// `unchecked_shl`.
unsafe { intrinsics::unchecked_shl(self, rhs) }
// Any legal shift amount is losslessly representable in the self type.
unsafe { intrinsics::unchecked_shl(self, rhs.try_into().ok().unwrap_unchecked()) }
}

/// Checked shift right. Computes `self >> rhs`, returning `None` if `rhs` is
@@ -808,10 +809,11 @@ macro_rules! int_impl {
#[rustc_const_unstable(feature = "const_inherent_unchecked_arith", issue = "85122")]
#[inline(always)]
#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
pub const unsafe fn unchecked_shr(self, rhs: Self) -> Self {
pub const unsafe fn unchecked_shr(self, rhs: u32) -> Self {
// SAFETY: the caller must uphold the safety contract for
// `unchecked_shr`.
unsafe { intrinsics::unchecked_shr(self, rhs) }
// Any legal shift amount is losslessly representable in the self type.
unsafe { intrinsics::unchecked_shr(self, rhs.try_into().ok().unwrap_unchecked()) }
}

/// Checked absolute value. Computes `self.abs()`, returning `None` if
@@ -1358,11 +1360,12 @@ macro_rules! int_impl {
#[must_use = "this returns the result of the operation, \
without modifying the original"]
#[inline(always)]
#[rustc_allow_const_fn_unstable(const_inherent_unchecked_arith)]
pub const fn wrapping_shl(self, rhs: u32) -> Self {
// SAFETY: the masking by the bitsize of the type ensures that we do not shift
// out of bounds
unsafe {
intrinsics::unchecked_shl(self, (rhs & ($BITS - 1)) as $SelfT)
self.unchecked_shl(rhs & ($BITS - 1))
}
}

@@ -1387,11 +1390,12 @@ macro_rules! int_impl {
#[must_use = "this returns the result of the operation, \
without modifying the original"]
#[inline(always)]
#[rustc_allow_const_fn_unstable(const_inherent_unchecked_arith)]
pub const fn wrapping_shr(self, rhs: u32) -> Self {
// SAFETY: the masking by the bitsize of the type ensures that we do not shift
// out of bounds
unsafe {
intrinsics::unchecked_shr(self, (rhs & ($BITS - 1)) as $SelfT)
self.unchecked_shr(rhs & ($BITS - 1))
}
}

1 change: 1 addition & 0 deletions library/core/src/num/mod.rs
Original file line number Diff line number Diff line change
@@ -3,6 +3,7 @@
#![stable(feature = "rust1", since = "1.0.0")]

use crate::ascii;
use crate::convert::TryInto;
use crate::error::Error;
use crate::intrinsics;
use crate::mem;
16 changes: 10 additions & 6 deletions library/core/src/num/uint_macros.rs
Original file line number Diff line number Diff line change
@@ -908,10 +908,11 @@ macro_rules! uint_impl {
#[rustc_const_unstable(feature = "const_inherent_unchecked_arith", issue = "85122")]
#[inline(always)]
#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
pub const unsafe fn unchecked_shl(self, rhs: Self) -> Self {
pub const unsafe fn unchecked_shl(self, rhs: u32) -> Self {
// SAFETY: the caller must uphold the safety contract for
// `unchecked_shl`.
unsafe { intrinsics::unchecked_shl(self, rhs) }
// Any legal shift amount is losslessly representable in the self type.
unsafe { intrinsics::unchecked_shl(self, rhs.try_into().ok().unwrap_unchecked()) }
}

/// Checked shift right. Computes `self >> rhs`, returning `None`
@@ -955,10 +956,11 @@ macro_rules! uint_impl {
#[rustc_const_unstable(feature = "const_inherent_unchecked_arith", issue = "85122")]
#[inline(always)]
#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
pub const unsafe fn unchecked_shr(self, rhs: Self) -> Self {
pub const unsafe fn unchecked_shr(self, rhs: u32) -> Self {
// SAFETY: the caller must uphold the safety contract for
// `unchecked_shr`.
unsafe { intrinsics::unchecked_shr(self, rhs) }
// Any legal shift amount is losslessly representable in the self type.
unsafe { intrinsics::unchecked_shr(self, rhs.try_into().ok().unwrap_unchecked()) }
}

/// Checked exponentiation. Computes `self.pow(exp)`, returning `None` if
@@ -1374,11 +1376,12 @@ macro_rules! uint_impl {
#[must_use = "this returns the result of the operation, \
without modifying the original"]
#[inline(always)]
#[rustc_allow_const_fn_unstable(const_inherent_unchecked_arith)]
pub const fn wrapping_shl(self, rhs: u32) -> Self {
// SAFETY: the masking by the bitsize of the type ensures that we do not shift
// out of bounds
unsafe {
intrinsics::unchecked_shl(self, (rhs & ($BITS - 1)) as $SelfT)
self.unchecked_shl(rhs & ($BITS - 1))
}
}

@@ -1406,11 +1409,12 @@ macro_rules! uint_impl {
#[must_use = "this returns the result of the operation, \
without modifying the original"]
#[inline(always)]
#[rustc_allow_const_fn_unstable(const_inherent_unchecked_arith)]
pub const fn wrapping_shr(self, rhs: u32) -> Self {
// SAFETY: the masking by the bitsize of the type ensures that we do not shift
// out of bounds
unsafe {
intrinsics::unchecked_shr(self, (rhs & ($BITS - 1)) as $SelfT)
self.unchecked_shr(rhs & ($BITS - 1))
}
}

24 changes: 17 additions & 7 deletions library/core/src/ptr/alignment.rs
Original file line number Diff line number Diff line change
@@ -9,7 +9,9 @@ use crate::{cmp, fmt, hash, mem, num};
/// Note that particularly large alignments, while representable in this type,
/// are likely not to be supported by actual allocators and linkers.
#[unstable(feature = "ptr_alignment_type", issue = "102070")]
#[derive(Copy, Clone, Eq, PartialEq)]
#[derive(Copy, Clone, Eq)]
#[cfg_attr(bootstrap, derive(PartialEq))]
#[cfg_attr(not(bootstrap), derive_const(PartialEq))]
#[repr(transparent)]
pub struct Alignment(AlignmentEnum);

@@ -167,16 +169,18 @@ impl From<Alignment> for usize {
}
}

#[rustc_const_unstable(feature = "const_alloc_layout", issue = "67521")]
#[unstable(feature = "ptr_alignment_type", issue = "102070")]
impl cmp::Ord for Alignment {
impl const cmp::Ord for Alignment {
#[inline]
fn cmp(&self, other: &Self) -> cmp::Ordering {
self.as_nonzero().cmp(&other.as_nonzero())
self.as_nonzero().get().cmp(&other.as_nonzero().get())
}
}

#[rustc_const_unstable(feature = "const_alloc_layout", issue = "67521")]
#[unstable(feature = "ptr_alignment_type", issue = "102070")]
impl cmp::PartialOrd for Alignment {
impl const cmp::PartialOrd for Alignment {
#[inline]
fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> {
Some(self.cmp(other))
@@ -198,7 +202,9 @@ type AlignmentEnum = AlignmentEnum32;
#[cfg(target_pointer_width = "64")]
type AlignmentEnum = AlignmentEnum64;

#[derive(Copy, Clone, Eq, PartialEq)]
#[derive(Copy, Clone, Eq)]
#[cfg_attr(bootstrap, derive(PartialEq))]
#[cfg_attr(not(bootstrap), derive_const(PartialEq))]
#[repr(u16)]
enum AlignmentEnum16 {
_Align1Shl0 = 1 << 0,
@@ -219,7 +225,9 @@ enum AlignmentEnum16 {
_Align1Shl15 = 1 << 15,
}

#[derive(Copy, Clone, Eq, PartialEq)]
#[derive(Copy, Clone, Eq)]
#[cfg_attr(bootstrap, derive(PartialEq))]
#[cfg_attr(not(bootstrap), derive_const(PartialEq))]
#[repr(u32)]
enum AlignmentEnum32 {
_Align1Shl0 = 1 << 0,
@@ -256,7 +264,9 @@ enum AlignmentEnum32 {
_Align1Shl31 = 1 << 31,
}

#[derive(Copy, Clone, Eq, PartialEq)]
#[derive(Copy, Clone, Eq)]
#[cfg_attr(bootstrap, derive(PartialEq))]
#[cfg_attr(not(bootstrap), derive_const(PartialEq))]
#[repr(u64)]
enum AlignmentEnum64 {
_Align1Shl0 = 1 << 0,
29 changes: 10 additions & 19 deletions library/core/src/ptr/const_ptr.rs
Original file line number Diff line number Diff line change
@@ -79,19 +79,14 @@ impl<T: ?Sized> *const T {
/// }
/// ```
#[unstable(feature = "set_ptr_value", issue = "75091")]
#[rustc_const_unstable(feature = "set_ptr_value", issue = "75091")]
#[must_use = "returns a new pointer rather than modifying its argument"]
#[inline]
pub fn with_metadata_of<U>(self, mut val: *const U) -> *const U
pub const fn with_metadata_of<U>(self, meta: *const U) -> *const U
where
U: ?Sized,
{
let target = &mut val as *mut *const U as *mut *const u8;
// SAFETY: In case of a thin pointer, this operations is identical
// to a simple assignment. In case of a fat pointer, with the current
// fat pointer layout implementation, the first field of such a
// pointer is always the data pointer, which is likewise assigned.
unsafe { *target = self as *const u8 };
val
from_raw_parts::<U>(self as *const (), metadata(meta))
}

/// Changes constness without changing the type.
@@ -478,8 +473,7 @@ impl<T: ?Sized> *const T {
#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
pub const unsafe fn byte_offset(self, count: isize) -> Self {
// SAFETY: the caller must uphold the safety contract for `offset`.
let this = unsafe { self.cast::<u8>().offset(count).cast::<()>() };
from_raw_parts::<T>(this, metadata(self))
unsafe { self.cast::<u8>().offset(count).with_metadata_of(self) }
}

/// Calculates the offset from a pointer using wrapping arithmetic.
@@ -559,7 +553,7 @@ impl<T: ?Sized> *const T {
#[unstable(feature = "pointer_byte_offsets", issue = "96283")]
#[rustc_const_unstable(feature = "const_pointer_byte_offsets", issue = "96283")]
pub const fn wrapping_byte_offset(self, count: isize) -> Self {
from_raw_parts::<T>(self.cast::<u8>().wrapping_offset(count).cast::<()>(), metadata(self))
self.cast::<u8>().wrapping_offset(count).with_metadata_of(self)
}

/// Masks out bits of the pointer according to a mask.
@@ -597,8 +591,7 @@ impl<T: ?Sized> *const T {
#[must_use = "returns a new pointer rather than modifying its argument"]
#[inline(always)]
pub fn mask(self, mask: usize) -> *const T {
let this = intrinsics::ptr_mask(self.cast::<()>(), mask);
from_raw_parts::<T>(this, metadata(self))
intrinsics::ptr_mask(self.cast::<()>(), mask).with_metadata_of(self)
}

/// Calculates the distance between two pointers. The returned value is in
@@ -939,8 +932,7 @@ impl<T: ?Sized> *const T {
#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
pub const unsafe fn byte_add(self, count: usize) -> Self {
// SAFETY: the caller must uphold the safety contract for `add`.
let this = unsafe { self.cast::<u8>().add(count).cast::<()>() };
from_raw_parts::<T>(this, metadata(self))
unsafe { self.cast::<u8>().add(count).with_metadata_of(self) }
}

/// Calculates the offset from a pointer (convenience for
@@ -1026,8 +1018,7 @@ impl<T: ?Sized> *const T {
#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
pub const unsafe fn byte_sub(self, count: usize) -> Self {
// SAFETY: the caller must uphold the safety contract for `sub`.
let this = unsafe { self.cast::<u8>().sub(count).cast::<()>() };
from_raw_parts::<T>(this, metadata(self))
unsafe { self.cast::<u8>().sub(count).with_metadata_of(self) }
}

/// Calculates the offset from a pointer using wrapping arithmetic.
@@ -1107,7 +1098,7 @@ impl<T: ?Sized> *const T {
#[unstable(feature = "pointer_byte_offsets", issue = "96283")]
#[rustc_const_unstable(feature = "const_pointer_byte_offsets", issue = "96283")]
pub const fn wrapping_byte_add(self, count: usize) -> Self {
from_raw_parts::<T>(self.cast::<u8>().wrapping_add(count).cast::<()>(), metadata(self))
self.cast::<u8>().wrapping_add(count).with_metadata_of(self)
}

/// Calculates the offset from a pointer using wrapping arithmetic.
@@ -1187,7 +1178,7 @@ impl<T: ?Sized> *const T {
#[unstable(feature = "pointer_byte_offsets", issue = "96283")]
#[rustc_const_unstable(feature = "const_pointer_byte_offsets", issue = "96283")]
pub const fn wrapping_byte_sub(self, count: usize) -> Self {
from_raw_parts::<T>(self.cast::<u8>().wrapping_sub(count).cast::<()>(), metadata(self))
self.cast::<u8>().wrapping_sub(count).with_metadata_of(self)
}

/// Reads the value from `self` without moving it. This leaves the
36 changes: 10 additions & 26 deletions library/core/src/ptr/mut_ptr.rs
Original file line number Diff line number Diff line change
@@ -78,23 +78,14 @@ impl<T: ?Sized> *mut T {
/// }
/// ```
#[unstable(feature = "set_ptr_value", issue = "75091")]
#[rustc_const_unstable(feature = "set_ptr_value", issue = "75091")]
#[must_use = "returns a new pointer rather than modifying its argument"]
#[inline]
pub fn with_metadata_of<U>(self, val: *const U) -> *mut U
pub const fn with_metadata_of<U>(self, meta: *const U) -> *mut U
where
U: ?Sized,
{
// Prepare in the type system that we will replace the pointer value with a mutable
// pointer, taking the mutable provenance from the `self` pointer.
let mut val = val as *mut U;
// Pointer to the pointer value within the value.
let target = &mut val as *mut *mut U as *mut *mut u8;
// SAFETY: In case of a thin pointer, this operations is identical
// to a simple assignment. In case of a fat pointer, with the current
// fat pointer layout implementation, the first field of such a
// pointer is always the data pointer, which is likewise assigned.
unsafe { *target = self as *mut u8 };
val
from_raw_parts_mut::<U>(self as *mut (), metadata(meta))
}

/// Changes constness without changing the type.
@@ -496,8 +487,7 @@ impl<T: ?Sized> *mut T {
#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
pub const unsafe fn byte_offset(self, count: isize) -> Self {
// SAFETY: the caller must uphold the safety contract for `offset`.
let this = unsafe { self.cast::<u8>().offset(count).cast::<()>() };
from_raw_parts_mut::<T>(this, metadata(self))
unsafe { self.cast::<u8>().offset(count).with_metadata_of(self) }
}

/// Calculates the offset from a pointer using wrapping arithmetic.
@@ -576,10 +566,7 @@ impl<T: ?Sized> *mut T {
#[unstable(feature = "pointer_byte_offsets", issue = "96283")]
#[rustc_const_unstable(feature = "const_pointer_byte_offsets", issue = "96283")]
pub const fn wrapping_byte_offset(self, count: isize) -> Self {
from_raw_parts_mut::<T>(
self.cast::<u8>().wrapping_offset(count).cast::<()>(),
metadata(self),
)
self.cast::<u8>().wrapping_offset(count).with_metadata_of(self)
}

/// Masks out bits of the pointer according to a mask.
@@ -620,8 +607,7 @@ impl<T: ?Sized> *mut T {
#[must_use = "returns a new pointer rather than modifying its argument"]
#[inline(always)]
pub fn mask(self, mask: usize) -> *mut T {
let this = intrinsics::ptr_mask(self.cast::<()>(), mask) as *mut ();
from_raw_parts_mut::<T>(this, metadata(self))
intrinsics::ptr_mask(self.cast::<()>(), mask).cast_mut().with_metadata_of(self)
}

/// Returns `None` if the pointer is null, or else returns a unique reference to
@@ -1048,8 +1034,7 @@ impl<T: ?Sized> *mut T {
#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
pub const unsafe fn byte_add(self, count: usize) -> Self {
// SAFETY: the caller must uphold the safety contract for `add`.
let this = unsafe { self.cast::<u8>().add(count).cast::<()>() };
from_raw_parts_mut::<T>(this, metadata(self))
unsafe { self.cast::<u8>().add(count).with_metadata_of(self) }
}

/// Calculates the offset from a pointer (convenience for
@@ -1135,8 +1120,7 @@ impl<T: ?Sized> *mut T {
#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
pub const unsafe fn byte_sub(self, count: usize) -> Self {
// SAFETY: the caller must uphold the safety contract for `sub`.
let this = unsafe { self.cast::<u8>().sub(count).cast::<()>() };
from_raw_parts_mut::<T>(this, metadata(self))
unsafe { self.cast::<u8>().sub(count).with_metadata_of(self) }
}

/// Calculates the offset from a pointer using wrapping arithmetic.
@@ -1216,7 +1200,7 @@ impl<T: ?Sized> *mut T {
#[unstable(feature = "pointer_byte_offsets", issue = "96283")]
#[rustc_const_unstable(feature = "const_pointer_byte_offsets", issue = "96283")]
pub const fn wrapping_byte_add(self, count: usize) -> Self {
from_raw_parts_mut::<T>(self.cast::<u8>().wrapping_add(count).cast::<()>(), metadata(self))
self.cast::<u8>().wrapping_add(count).with_metadata_of(self)
}

/// Calculates the offset from a pointer using wrapping arithmetic.
@@ -1296,7 +1280,7 @@ impl<T: ?Sized> *mut T {
#[unstable(feature = "pointer_byte_offsets", issue = "96283")]
#[rustc_const_unstable(feature = "const_pointer_byte_offsets", issue = "96283")]
pub const fn wrapping_byte_sub(self, count: usize) -> Self {
from_raw_parts_mut::<T>(self.cast::<u8>().wrapping_sub(count).cast::<()>(), metadata(self))
self.cast::<u8>().wrapping_sub(count).with_metadata_of(self)
}

/// Reads the value from `self` without moving it. This leaves the
8 changes: 4 additions & 4 deletions library/core/src/slice/mod.rs
Original file line number Diff line number Diff line change
@@ -3752,9 +3752,9 @@ impl<T> [T] {
/// [`is_sorted`]: slice::is_sorted
#[unstable(feature = "is_sorted", reason = "new API", issue = "53485")]
#[must_use]
pub fn is_sorted_by<F>(&self, mut compare: F) -> bool
pub fn is_sorted_by<'a, F>(&'a self, mut compare: F) -> bool
where
F: FnMut(&T, &T) -> Option<Ordering>,
F: FnMut(&'a T, &'a T) -> Option<Ordering>,
{
self.iter().is_sorted_by(|a, b| compare(*a, *b))
}
@@ -3778,9 +3778,9 @@ impl<T> [T] {
#[inline]
#[unstable(feature = "is_sorted", reason = "new API", issue = "53485")]
#[must_use]
pub fn is_sorted_by_key<F, K>(&self, f: F) -> bool
pub fn is_sorted_by_key<'a, F, K>(&'a self, f: F) -> bool
where
F: FnMut(&T) -> K,
F: FnMut(&'a T) -> K,
K: PartialOrd,
{
self.iter().is_sorted_by_key(f)
31 changes: 16 additions & 15 deletions src/librustdoc/html/render/print_item.rs
Original file line number Diff line number Diff line change
@@ -19,8 +19,8 @@ use super::{
collect_paths_for_type, document, ensure_trailing_slash, get_filtered_impls_for_reference,
item_ty_to_section, notable_traits_button, notable_traits_json, render_all_impls,
render_assoc_item, render_assoc_items, render_attributes_in_code, render_attributes_in_pre,
render_impl, render_rightside, render_stability_since_raw, AssocItemLink, Context,
ImplRenderingParameters,
render_impl, render_rightside, render_stability_since_raw,
render_stability_since_raw_with_extra, AssocItemLink, Context, ImplRenderingParameters,
};
use crate::clean;
use crate::config::ModuleSorting;
@@ -1267,30 +1267,30 @@ fn item_enum(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, e: &clean::
document_non_exhaustive_header(it)
);
document_non_exhaustive(w, it);
write!(w, "<div class=\"variants\">");
for variant in e.variants() {
let id = cx.derive_id(format!("{}.{}", ItemType::Variant, variant.name.unwrap()));
write!(
w,
"<h3 id=\"{id}\" class=\"variant small-section-header\">\
<a href=\"#{id}\" class=\"anchor field\"></a>\
<code>{name}",
"<section id=\"{id}\" class=\"variant\">\
<a href=\"#{id}\" class=\"anchor\"></a>",
id = id,
name = variant.name.unwrap()
);
if let clean::VariantItem(clean::Variant::Tuple(ref s)) = *variant.kind {
w.write_str("(");
print_tuple_struct_fields(w, cx, s);
w.write_str(")");
}
w.write_str("</code>");
render_stability_since_raw(
render_stability_since_raw_with_extra(
w,
variant.stable_since(tcx),
variant.const_stability(tcx),
it.stable_since(tcx),
it.const_stable_since(tcx),
" rightside",
);
w.write_str("</h3>");
write!(w, "<h3 class=\"code-header\">{name}", name = variant.name.unwrap());
if let clean::VariantItem(clean::Variant::Tuple(ref s)) = *variant.kind {
w.write_str("(");
print_tuple_struct_fields(w, cx, s);
w.write_str(")");
}
w.write_str("</h3></section>");

use crate::clean::Variant;

@@ -1324,7 +1324,7 @@ fn item_enum(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, e: &clean::
write!(
w,
"<div class=\"sub-variant-field\">\
<span id=\"{id}\" class=\"variant small-section-header\">\
<span id=\"{id}\" class=\"small-section-header\">\
<a href=\"#{id}\" class=\"anchor field\"></a>\
<code>{f}:&nbsp;{t}</code>\
</span>",
@@ -1343,6 +1343,7 @@ fn item_enum(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, e: &clean::

document(w, cx, variant, Some(it), HeadingOffset::H4);
}
write!(w, "</div>");
}
let def_id = it.item_id.expect_def_id();
render_assoc_items(w, cx, it, def_id, AssocItemRender::All);
12 changes: 3 additions & 9 deletions src/librustdoc/html/static/css/rustdoc.css
Original file line number Diff line number Diff line change
@@ -706,16 +706,14 @@ a {
}

.small-section-header {
display: flex;
justify-content: space-between;
position: relative;
}

.small-section-header:hover > .anchor {
display: initial;
}

.impl:hover > .anchor, .trait-impl:hover > .anchor {
.impl:hover > .anchor, .trait-impl:hover > .anchor, .variant:hover > .anchor {
display: inline-block;
position: absolute;
}
@@ -1234,12 +1232,6 @@ a.test-arrow:hover {
font-size: 1.25rem;
}

h3.variant {
font-weight: 600;
font-size: 1.125rem;
margin-bottom: 10px;
}

.sub-variant h4 {
font-size: 1rem;
font-weight: 400;
@@ -1908,6 +1900,7 @@ in storage.js
}
}

.variant,
.implementors-toggle > summary,
.impl,
#implementors-list > .docblock,
@@ -1919,6 +1912,7 @@ in storage.js
margin-bottom: 0.75em;
}

.variants > .docblock,
.impl-items > .rustdoc-toggle[open]:not(:last-child),
.methods > .rustdoc-toggle[open]:not(:last-child),
.implementors-toggle[open]:not(:last-child) {
66 changes: 66 additions & 0 deletions src/test/codegen/unchecked_shifts.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
// compile-flags: -O
// min-llvm-version: 15.0 (LLVM 13 in CI does this differently from submodule LLVM)
// ignore-debug (because unchecked is checked in debug)

#![crate_type = "lib"]
#![feature(unchecked_math)]

// CHECK-LABEL: @unchecked_shl_unsigned_same
#[no_mangle]
pub unsafe fn unchecked_shl_unsigned_same(a: u32, b: u32) -> u32 {
// CHECK-NOT: and i32
// CHECK: shl i32 %a, %b
// CHECK-NOT: and i32
a.unchecked_shl(b)
}

// CHECK-LABEL: @unchecked_shl_unsigned_smaller
#[no_mangle]
pub unsafe fn unchecked_shl_unsigned_smaller(a: u16, b: u32) -> u16 {
// This uses -DAG to avoid failing on irrelevant reorderings,
// like emitting the truncation earlier.

// CHECK-DAG: %[[INRANGE:.+]] = icmp ult i32 %b, 65536
// CHECK-DAG: tail call void @llvm.assume(i1 %[[INRANGE]])
// CHECK-DAG: %[[TRUNC:.+]] = trunc i32 %b to i16
// CHECK-DAG: shl i16 %a, %[[TRUNC]]
a.unchecked_shl(b)
}

// CHECK-LABEL: @unchecked_shl_unsigned_bigger
#[no_mangle]
pub unsafe fn unchecked_shl_unsigned_bigger(a: u64, b: u32) -> u64 {
// CHECK: %[[EXT:.+]] = zext i32 %b to i64
// CHECK: shl i64 %a, %[[EXT]]
a.unchecked_shl(b)
}

// CHECK-LABEL: @unchecked_shr_signed_same
#[no_mangle]
pub unsafe fn unchecked_shr_signed_same(a: i32, b: u32) -> i32 {
// CHECK-NOT: and i32
// CHECK: ashr i32 %a, %b
// CHECK-NOT: and i32
a.unchecked_shr(b)
}

// CHECK-LABEL: @unchecked_shr_signed_smaller
#[no_mangle]
pub unsafe fn unchecked_shr_signed_smaller(a: i16, b: u32) -> i16 {
// This uses -DAG to avoid failing on irrelevant reorderings,
// like emitting the truncation earlier.

// CHECK-DAG: %[[INRANGE:.+]] = icmp ult i32 %b, 32768
// CHECK-DAG: tail call void @llvm.assume(i1 %[[INRANGE]])
// CHECK-DAG: %[[TRUNC:.+]] = trunc i32 %b to i16
// CHECK-DAG: ashr i16 %a, %[[TRUNC]]
a.unchecked_shr(b)
}

// CHECK-LABEL: @unchecked_shr_signed_bigger
#[no_mangle]
pub unsafe fn unchecked_shr_signed_bigger(a: i64, b: u32) -> i64 {
// CHECK: %[[EXT:.+]] = zext i32 %b to i64
// CHECK: ashr i64 %a, %[[EXT]]
a.unchecked_shr(b)
}
5 changes: 5 additions & 0 deletions src/test/rustdoc-gui/enum-variants.goml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
// Verifies that there is non-zero margin on variants and their docblocks.
goto: "file://" + |DOC_PATH| + "/test_docs/enum.WhoLetTheDogOut.html"

assert-css: (".variants > .variant", {"margin": "0px 0px 12px"})
assert-css: (".variants > .docblock", {"margin": "0px 0px 32px 24px"})
10 changes: 5 additions & 5 deletions src/test/rustdoc/issue-88600.rs
Original file line number Diff line number Diff line change
@@ -8,22 +8,22 @@ pub struct S;

// @has issue_88600/enum.FooEnum.html
pub enum FooEnum {
// @has - '//*[@id="variant.HiddenTupleItem"]//code' 'HiddenTupleItem(_)'
// @has - '//*[@id="variant.HiddenTupleItem"]//h3' 'HiddenTupleItem(_)'
// @count - '//*[@id="variant.HiddenTupleItem.field.0"]' 0
HiddenTupleItem(#[doc(hidden)] H),
// @has - '//*[@id="variant.MultipleHidden"]//code' 'MultipleHidden(_, _)'
// @has - '//*[@id="variant.MultipleHidden"]//h3' 'MultipleHidden(_, _)'
// @count - '//*[@id="variant.MultipleHidden.field.0"]' 0
// @count - '//*[@id="variant.MultipleHidden.field.1"]' 0
MultipleHidden(#[doc(hidden)] H, #[doc(hidden)] H),
// @has - '//*[@id="variant.MixedHiddenFirst"]//code' 'MixedHiddenFirst(_, S)'
// @has - '//*[@id="variant.MixedHiddenFirst"]//h3' 'MixedHiddenFirst(_, S)'
// @count - '//*[@id="variant.MixedHiddenFirst.field.0"]' 0
// @has - '//*[@id="variant.MixedHiddenFirst.field.1"]' '1: S'
MixedHiddenFirst(#[doc(hidden)] H, /** dox */ S),
// @has - '//*[@id="variant.MixedHiddenLast"]//code' 'MixedHiddenLast(S, _)'
// @has - '//*[@id="variant.MixedHiddenLast"]//h3' 'MixedHiddenLast(S, _)'
// @has - '//*[@id="variant.MixedHiddenLast.field.0"]' '0: S'
// @count - '//*[@id="variant.MixedHiddenLast.field.1"]' 0
MixedHiddenLast(/** dox */ S, #[doc(hidden)] H),
// @has - '//*[@id="variant.HiddenStruct"]//code' 'HiddenStruct'
// @has - '//*[@id="variant.HiddenStruct"]//h3' 'HiddenStruct'
// @count - '//*[@id="variant.HiddenStruct.field.h"]' 0
// @has - '//*[@id="variant.HiddenStruct.field.s"]' 's: S'
HiddenStruct {
20 changes: 20 additions & 0 deletions src/test/ui/array-slice-vec/slice_is_sorted_by_borrow.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
// check-pass
// regression test for https://github.com/rust-lang/rust/issues/53485#issuecomment-885393452

#![feature(is_sorted)]

struct A {
name: String,
}

fn main() {
let a = &[
A {
name: "1".to_string(),
},
A {
name: "2".to_string(),
},
];
assert!(a.is_sorted_by_key(|a| a.name.as_str()));
}
11 changes: 11 additions & 0 deletions src/test/ui/dyn-star/align.normal.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
warning: the feature `dyn_star` is incomplete and may not be safe to use and/or cause compiler crashes
--> $DIR/align.rs:4:12
|
LL | #![feature(dyn_star)]
| ^^^^^^^^
|
= note: see issue #91611 <https://github.com/rust-lang/rust/issues/91611> for more information
= note: `#[warn(incomplete_features)]` on by default

warning: 1 warning emitted

20 changes: 20 additions & 0 deletions src/test/ui/dyn-star/align.over_aligned.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
warning: the feature `dyn_star` is incomplete and may not be safe to use and/or cause compiler crashes
--> $DIR/align.rs:4:12
|
LL | #![feature(dyn_star)]
| ^^^^^^^^
|
= note: see issue #91611 <https://github.com/rust-lang/rust/issues/91611> for more information
= note: `#[warn(incomplete_features)]` on by default

error[E0277]: `AlignedUsize` needs to be a pointer-sized type
--> $DIR/align.rs:15:13
|
LL | let x = AlignedUsize(12) as dyn* Debug;
| ^^^^^^^^^^^^^^^^ `AlignedUsize` needs to be a pointer-sized type
|
= help: the trait `PointerSized` is not implemented for `AlignedUsize`

error: aborting due to previous error; 1 warning emitted

For more information about this error, try `rustc --explain E0277`.
17 changes: 17 additions & 0 deletions src/test/ui/dyn-star/align.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// revisions: normal over_aligned
//[normal] check-pass

#![feature(dyn_star)]
//~^ WARN the feature `dyn_star` is incomplete and may not be safe to use and/or cause compiler crashes

use std::fmt::Debug;

#[cfg_attr(over_aligned, repr(C, align(1024)))]
#[cfg_attr(not(over_aligned), repr(C))]
#[derive(Debug)]
struct AlignedUsize(usize);

fn main() {
let x = AlignedUsize(12) as dyn* Debug;
//[over_aligned]~^ ERROR `AlignedUsize` needs to be a pointer-sized type
}
15 changes: 15 additions & 0 deletions src/test/ui/dyn-star/check-size-at-cast-polymorphic-bad.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
#![feature(dyn_star)]
#![allow(incomplete_features)]

use std::fmt::Debug;

fn dyn_debug(_: (dyn* Debug + '_)) {

}

fn polymorphic<T: Debug + ?Sized>(t: &T) {
dyn_debug(t);
//~^ ERROR `&T` needs to be a pointer-sized type
}

fn main() {}
15 changes: 15 additions & 0 deletions src/test/ui/dyn-star/check-size-at-cast-polymorphic-bad.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
error[E0277]: `&T` needs to be a pointer-sized type
--> $DIR/check-size-at-cast-polymorphic-bad.rs:11:15
|
LL | dyn_debug(t);
| ^ `&T` needs to be a pointer-sized type
|
= help: the trait `PointerSized` is not implemented for `&T`
help: consider introducing a `where` clause, but there might be an alternative better way to express this requirement
|
LL | fn polymorphic<T: Debug + ?Sized>(t: &T) where &T: PointerSized {
| ++++++++++++++++++++++

error: aborting due to previous error

For more information about this error, try `rustc --explain E0277`.
16 changes: 16 additions & 0 deletions src/test/ui/dyn-star/check-size-at-cast-polymorphic.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
// check-pass

#![feature(dyn_star)]
#![allow(incomplete_features)]

use std::fmt::Debug;

fn dyn_debug(_: (dyn* Debug + '_)) {

}

fn polymorphic<T: Debug>(t: &T) {
dyn_debug(t);
}

fn main() {}
10 changes: 10 additions & 0 deletions src/test/ui/dyn-star/check-size-at-cast.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
#![feature(dyn_star)]
#![allow(incomplete_features)]

use std::fmt::Debug;

fn main() {
let i = [1, 2, 3, 4] as dyn* Debug;
//~^ ERROR `[i32; 4]` needs to be a pointer-sized type
dbg!(i);
}
11 changes: 11 additions & 0 deletions src/test/ui/dyn-star/check-size-at-cast.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
error[E0277]: `[i32; 4]` needs to be a pointer-sized type
--> $DIR/check-size-at-cast.rs:7:13
|
LL | let i = [1, 2, 3, 4] as dyn* Debug;
| ^^^^^^^^^^^^ `[i32; 4]` needs to be a pointer-sized type
|
= help: the trait `PointerSized` is not implemented for `[i32; 4]`

error: aborting due to previous error

For more information about this error, try `rustc --explain E0277`.
13 changes: 13 additions & 0 deletions src/tools/tidy/src/deps.rs
Original file line number Diff line number Diff line change
@@ -133,6 +133,11 @@ const PERMITTED_RUSTC_DEPENDENCIES: &[&str] = &[
"hashbrown",
"hermit-abi",
"humantime",
"icu_list",
"icu_locid",
"icu_provider",
"icu_provider_adapters",
"icu_provider_macros",
"if_chain",
"indexmap",
"instant",
@@ -145,6 +150,7 @@ const PERMITTED_RUSTC_DEPENDENCIES: &[&str] = &[
"libc",
"libloading",
"libz-sys",
"litemap",
"lock_api",
"log",
"matchers",
@@ -253,9 +259,16 @@ const PERMITTED_RUSTC_DEPENDENCIES: &[&str] = &[
"winapi-i686-pc-windows-gnu",
"winapi-util",
"winapi-x86_64-pc-windows-gnu",
"writeable",
// this is a false-positive: it's only used by rustfmt, but because it's enabled through a
// feature, tidy thinks it's used by rustc as well.
"yansi-term",
"yoke",
"yoke-derive",
"zerofrom",
"zerofrom-derive",
"zerovec",
"zerovec-derive",
];

const PERMITTED_CRANELIFT_DEPENDENCIES: &[&str] = &[