mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-23 07:14:28 +00:00
Auto merge of #111210 - matthiaskrgr:rollup-doquh2n, r=matthiaskrgr
Rollup of 8 pull requests Successful merges: - #108865 (Add a `sysroot` crate to represent the standard library crates) - #110651 (libtest: include test output in junit xml reports) - #110826 (Make PlaceMention a non-mutating use.) - #110982 (Do not recurse into const generic args when resolving self lifetime elision.) - #111009 (Add `ascii::Char` (ACP#179)) - #111100 (check array type of repeat exprs is wf) - #111186 (Add `is_positive` method for signed non-zero integers.) - #111201 (bootstrap: add .gitmodules to the sources) Failed merges: - #110954 (Reject borrows of projections in ConstProp.) r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
eb7a743421
10
Cargo.lock
10
Cargo.lock
@ -4739,6 +4739,15 @@ dependencies = [
|
|||||||
"unicode-xid",
|
"unicode-xid",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "sysroot"
|
||||||
|
version = "0.0.0"
|
||||||
|
dependencies = [
|
||||||
|
"proc_macro",
|
||||||
|
"std",
|
||||||
|
"test",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tar"
|
name = "tar"
|
||||||
version = "0.4.38"
|
version = "0.4.38"
|
||||||
@ -4823,7 +4832,6 @@ dependencies = [
|
|||||||
"getopts",
|
"getopts",
|
||||||
"panic_abort",
|
"panic_abort",
|
||||||
"panic_unwind",
|
"panic_unwind",
|
||||||
"proc_macro",
|
|
||||||
"std",
|
"std",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
members = [
|
members = [
|
||||||
"compiler/rustc",
|
"compiler/rustc",
|
||||||
"library/std",
|
"library/std",
|
||||||
"library/test",
|
"library/sysroot",
|
||||||
"src/rustdoc-json-types",
|
"src/rustdoc-json-types",
|
||||||
"src/tools/build_helper",
|
"src/tools/build_helper",
|
||||||
"src/tools/cargotest",
|
"src/tools/cargotest",
|
||||||
|
@ -54,7 +54,7 @@ pub fn categorize(context: PlaceContext) -> Option<DefUse> {
|
|||||||
|
|
||||||
// `PlaceMention` and `AscribeUserType` both evaluate the place, which must not
|
// `PlaceMention` and `AscribeUserType` both evaluate the place, which must not
|
||||||
// contain dangling references.
|
// contain dangling references.
|
||||||
PlaceContext::NonUse(NonUseContext::PlaceMention) |
|
PlaceContext::NonMutatingUse(NonMutatingUseContext::PlaceMention) |
|
||||||
PlaceContext::NonUse(NonUseContext::AscribeUserTy) |
|
PlaceContext::NonUse(NonUseContext::AscribeUserTy) |
|
||||||
|
|
||||||
PlaceContext::MutatingUse(MutatingUseContext::AddressOf) |
|
PlaceContext::MutatingUse(MutatingUseContext::AddressOf) |
|
||||||
|
@ -108,6 +108,14 @@ impl<'a, 'tcx> MutVisitor<'tcx> for RegionRenumberer<'a, 'tcx> {
|
|||||||
debug!(?region);
|
debug!(?region);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[instrument(skip(self), level = "debug")]
|
||||||
|
fn visit_ty_const(&mut self, ct: &mut ty::Const<'tcx>, location: Location) {
|
||||||
|
let old_ct = *ct;
|
||||||
|
*ct = self.renumber_regions(old_ct, || RegionCtxt::Location(location));
|
||||||
|
|
||||||
|
debug!(?ct);
|
||||||
|
}
|
||||||
|
|
||||||
#[instrument(skip(self), level = "debug")]
|
#[instrument(skip(self), level = "debug")]
|
||||||
fn visit_constant(&mut self, constant: &mut Constant<'tcx>, location: Location) {
|
fn visit_constant(&mut self, constant: &mut Constant<'tcx>, location: Location) {
|
||||||
let literal = constant.literal;
|
let literal = constant.literal;
|
||||||
|
@ -772,12 +772,10 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> {
|
|||||||
|
|
||||||
match context {
|
match context {
|
||||||
PlaceContext::MutatingUse(_) => ty::Invariant,
|
PlaceContext::MutatingUse(_) => ty::Invariant,
|
||||||
PlaceContext::NonUse(StorageDead | StorageLive | PlaceMention | VarDebugInfo) => {
|
PlaceContext::NonUse(StorageDead | StorageLive | VarDebugInfo) => ty::Invariant,
|
||||||
ty::Invariant
|
|
||||||
}
|
|
||||||
PlaceContext::NonMutatingUse(
|
PlaceContext::NonMutatingUse(
|
||||||
Inspect | Copy | Move | SharedBorrow | ShallowBorrow | UniqueBorrow | AddressOf
|
Inspect | Copy | Move | PlaceMention | SharedBorrow | ShallowBorrow | UniqueBorrow
|
||||||
| Projection,
|
| AddressOf | Projection,
|
||||||
) => ty::Covariant,
|
) => ty::Covariant,
|
||||||
PlaceContext::NonUse(AscribeUserTy) => ty::Covariant,
|
PlaceContext::NonUse(AscribeUserTy) => ty::Covariant,
|
||||||
}
|
}
|
||||||
@ -1803,6 +1801,13 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
|||||||
Rvalue::Repeat(operand, len) => {
|
Rvalue::Repeat(operand, len) => {
|
||||||
self.check_operand(operand, location);
|
self.check_operand(operand, location);
|
||||||
|
|
||||||
|
let array_ty = rvalue.ty(body.local_decls(), tcx);
|
||||||
|
self.prove_predicate(
|
||||||
|
ty::PredicateKind::WellFormed(array_ty.into()),
|
||||||
|
Locations::Single(location),
|
||||||
|
ConstraintCategory::Boring,
|
||||||
|
);
|
||||||
|
|
||||||
// If the length cannot be evaluated we must assume that the length can be larger
|
// If the length cannot be evaluated we must assume that the length can be larger
|
||||||
// than 1.
|
// than 1.
|
||||||
// If the length is larger than 1, the repeat expression will need to copy the
|
// If the length is larger than 1, the repeat expression will need to copy the
|
||||||
|
@ -203,7 +203,9 @@ impl<'mir, 'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> Visitor<'tcx>
|
|||||||
self.assign(local, DefLocation::Body(location));
|
self.assign(local, DefLocation::Body(location));
|
||||||
}
|
}
|
||||||
|
|
||||||
PlaceContext::NonUse(_) | PlaceContext::MutatingUse(MutatingUseContext::Retag) => {}
|
PlaceContext::NonUse(_)
|
||||||
|
| PlaceContext::NonMutatingUse(NonMutatingUseContext::PlaceMention)
|
||||||
|
| PlaceContext::MutatingUse(MutatingUseContext::Retag) => {}
|
||||||
|
|
||||||
PlaceContext::NonMutatingUse(
|
PlaceContext::NonMutatingUse(
|
||||||
NonMutatingUseContext::Copy | NonMutatingUseContext::Move,
|
NonMutatingUseContext::Copy | NonMutatingUseContext::Move,
|
||||||
|
@ -1426,6 +1426,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||||||
|
|
||||||
self.check_repeat_element_needs_copy_bound(element, count, element_ty);
|
self.check_repeat_element_needs_copy_bound(element, count, element_ty);
|
||||||
|
|
||||||
|
self.register_wf_obligation(
|
||||||
|
tcx.mk_array_with_const_len(t, count).into(),
|
||||||
|
expr.span,
|
||||||
|
traits::WellFormed(None),
|
||||||
|
);
|
||||||
|
|
||||||
tcx.mk_array_with_const_len(t, count)
|
tcx.mk_array_with_const_len(t, count)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -192,6 +192,14 @@ macro_rules! make_mir_visitor {
|
|||||||
self.super_constant(constant, location);
|
self.super_constant(constant, location);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn visit_ty_const(
|
||||||
|
&mut self,
|
||||||
|
ct: $( & $mutability)? ty::Const<'tcx>,
|
||||||
|
location: Location,
|
||||||
|
) {
|
||||||
|
self.super_ty_const(ct, location);
|
||||||
|
}
|
||||||
|
|
||||||
fn visit_span(
|
fn visit_span(
|
||||||
&mut self,
|
&mut self,
|
||||||
span: $(& $mutability)? Span,
|
span: $(& $mutability)? Span,
|
||||||
@ -410,7 +418,7 @@ macro_rules! make_mir_visitor {
|
|||||||
StatementKind::PlaceMention(place) => {
|
StatementKind::PlaceMention(place) => {
|
||||||
self.visit_place(
|
self.visit_place(
|
||||||
place,
|
place,
|
||||||
PlaceContext::NonUse(NonUseContext::PlaceMention),
|
PlaceContext::NonMutatingUse(NonMutatingUseContext::PlaceMention),
|
||||||
location
|
location
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -625,8 +633,9 @@ macro_rules! make_mir_visitor {
|
|||||||
self.visit_operand(operand, location);
|
self.visit_operand(operand, location);
|
||||||
}
|
}
|
||||||
|
|
||||||
Rvalue::Repeat(value, _) => {
|
Rvalue::Repeat(value, ct) => {
|
||||||
self.visit_operand(value, location);
|
self.visit_operand(value, location);
|
||||||
|
self.visit_ty_const($(&$mutability)? *ct, location);
|
||||||
}
|
}
|
||||||
|
|
||||||
Rvalue::ThreadLocalRef(_) => {}
|
Rvalue::ThreadLocalRef(_) => {}
|
||||||
@ -878,12 +887,20 @@ macro_rules! make_mir_visitor {
|
|||||||
self.visit_span($(& $mutability)? *span);
|
self.visit_span($(& $mutability)? *span);
|
||||||
drop(user_ty); // no visit method for this
|
drop(user_ty); // no visit method for this
|
||||||
match literal {
|
match literal {
|
||||||
ConstantKind::Ty(_) => {}
|
ConstantKind::Ty(ct) => self.visit_ty_const($(&$mutability)? *ct, location),
|
||||||
ConstantKind::Val(_, ty) => self.visit_ty($(& $mutability)? *ty, TyContext::Location(location)),
|
ConstantKind::Val(_, ty) => self.visit_ty($(& $mutability)? *ty, TyContext::Location(location)),
|
||||||
ConstantKind::Unevaluated(_, ty) => self.visit_ty($(& $mutability)? *ty, TyContext::Location(location)),
|
ConstantKind::Unevaluated(_, ty) => self.visit_ty($(& $mutability)? *ty, TyContext::Location(location)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn super_ty_const(
|
||||||
|
&mut self,
|
||||||
|
_ct: $(& $mutability)? ty::Const<'tcx>,
|
||||||
|
_location: Location,
|
||||||
|
) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
fn super_span(&mut self, _span: $(& $mutability)? Span) {
|
fn super_span(&mut self, _span: $(& $mutability)? Span) {
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1251,6 +1268,11 @@ pub enum NonMutatingUseContext {
|
|||||||
UniqueBorrow,
|
UniqueBorrow,
|
||||||
/// AddressOf for *const pointer.
|
/// AddressOf for *const pointer.
|
||||||
AddressOf,
|
AddressOf,
|
||||||
|
/// PlaceMention statement.
|
||||||
|
///
|
||||||
|
/// This statement is executed as a check that the `Place` is live without reading from it,
|
||||||
|
/// so it must be considered as a non-mutating use.
|
||||||
|
PlaceMention,
|
||||||
/// Used as base for another place, e.g., `x` in `x.y`. Will not mutate the place.
|
/// Used as base for another place, e.g., `x` in `x.y`. Will not mutate the place.
|
||||||
/// For example, the projection `x.y` is not marked as a mutation in these cases:
|
/// For example, the projection `x.y` is not marked as a mutation in these cases:
|
||||||
/// ```ignore (illustrative)
|
/// ```ignore (illustrative)
|
||||||
@ -1301,8 +1323,6 @@ pub enum NonUseContext {
|
|||||||
AscribeUserTy,
|
AscribeUserTy,
|
||||||
/// The data of a user variable, for debug info.
|
/// The data of a user variable, for debug info.
|
||||||
VarDebugInfo,
|
VarDebugInfo,
|
||||||
/// PlaceMention statement.
|
|
||||||
PlaceMention,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
||||||
|
@ -197,6 +197,7 @@ impl DefUse {
|
|||||||
| NonMutatingUseContext::Copy
|
| NonMutatingUseContext::Copy
|
||||||
| NonMutatingUseContext::Inspect
|
| NonMutatingUseContext::Inspect
|
||||||
| NonMutatingUseContext::Move
|
| NonMutatingUseContext::Move
|
||||||
|
| NonMutatingUseContext::PlaceMention
|
||||||
| NonMutatingUseContext::ShallowBorrow
|
| NonMutatingUseContext::ShallowBorrow
|
||||||
| NonMutatingUseContext::SharedBorrow
|
| NonMutatingUseContext::SharedBorrow
|
||||||
| NonMutatingUseContext::UniqueBorrow,
|
| NonMutatingUseContext::UniqueBorrow,
|
||||||
|
@ -752,6 +752,7 @@ impl Visitor<'_> for CanConstProp {
|
|||||||
| NonMutatingUse(NonMutatingUseContext::Move)
|
| NonMutatingUse(NonMutatingUseContext::Move)
|
||||||
| NonMutatingUse(NonMutatingUseContext::Inspect)
|
| NonMutatingUse(NonMutatingUseContext::Inspect)
|
||||||
| NonMutatingUse(NonMutatingUseContext::Projection)
|
| NonMutatingUse(NonMutatingUseContext::Projection)
|
||||||
|
| NonMutatingUse(NonMutatingUseContext::PlaceMention)
|
||||||
| NonUse(_) => {}
|
| NonUse(_) => {}
|
||||||
|
|
||||||
// These could be propagated with a smarter analysis or just some careful thinking about
|
// These could be propagated with a smarter analysis or just some careful thinking about
|
||||||
|
@ -2070,6 +2070,10 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
|
|||||||
}
|
}
|
||||||
visit::walk_ty(self, ty)
|
visit::walk_ty(self, ty)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// A type may have an expression as a const generic argument.
|
||||||
|
// We do not want to recurse into those.
|
||||||
|
fn visit_expr(&mut self, _: &'a Expr) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
let impl_self = self
|
let impl_self = self
|
||||||
|
@ -101,6 +101,7 @@
|
|||||||
#![feature(array_into_iter_constructors)]
|
#![feature(array_into_iter_constructors)]
|
||||||
#![feature(array_methods)]
|
#![feature(array_methods)]
|
||||||
#![feature(array_windows)]
|
#![feature(array_windows)]
|
||||||
|
#![feature(ascii_char)]
|
||||||
#![feature(assert_matches)]
|
#![feature(assert_matches)]
|
||||||
#![feature(async_iterator)]
|
#![feature(async_iterator)]
|
||||||
#![feature(coerce_unsized)]
|
#![feature(coerce_unsized)]
|
||||||
|
@ -2526,6 +2526,15 @@ impl<T: fmt::Display + ?Sized> ToString for T {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(not(no_global_oom_handling))]
|
||||||
|
#[unstable(feature = "ascii_char", issue = "110998")]
|
||||||
|
impl ToString for core::ascii::Char {
|
||||||
|
#[inline]
|
||||||
|
fn to_string(&self) -> String {
|
||||||
|
self.as_str().to_owned()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(not(no_global_oom_handling))]
|
#[cfg(not(no_global_oom_handling))]
|
||||||
#[stable(feature = "char_to_string_specialization", since = "1.46.0")]
|
#[stable(feature = "char_to_string_specialization", since = "1.46.0")]
|
||||||
impl ToString for char {
|
impl ToString for char {
|
||||||
|
34
library/core/src/array/ascii.rs
Normal file
34
library/core/src/array/ascii.rs
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
use crate::ascii;
|
||||||
|
|
||||||
|
#[cfg(not(test))]
|
||||||
|
impl<const N: usize> [u8; N] {
|
||||||
|
/// Converts this array of bytes into a array of ASCII characters,
|
||||||
|
/// or returns `None` if any of the characters is non-ASCII.
|
||||||
|
#[unstable(feature = "ascii_char", issue = "110998")]
|
||||||
|
#[must_use]
|
||||||
|
#[inline]
|
||||||
|
pub fn as_ascii(&self) -> Option<&[ascii::Char; N]> {
|
||||||
|
if self.is_ascii() {
|
||||||
|
// SAFETY: Just checked that it's ASCII
|
||||||
|
Some(unsafe { self.as_ascii_unchecked() })
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Converts this array of bytes into a array of ASCII characters,
|
||||||
|
/// without checking whether they're valid.
|
||||||
|
///
|
||||||
|
/// # Safety
|
||||||
|
///
|
||||||
|
/// Every byte in the array must be in `0..=127`, or else this is UB.
|
||||||
|
#[unstable(feature = "ascii_char", issue = "110998")]
|
||||||
|
#[must_use]
|
||||||
|
#[inline]
|
||||||
|
pub const unsafe fn as_ascii_unchecked(&self) -> &[ascii::Char; N] {
|
||||||
|
let byte_ptr: *const [u8; N] = self;
|
||||||
|
let ascii_ptr = byte_ptr as *const [ascii::Char; N];
|
||||||
|
// SAFETY: The caller promised all the bytes are ASCII
|
||||||
|
unsafe { &*ascii_ptr }
|
||||||
|
}
|
||||||
|
}
|
@ -17,6 +17,7 @@ use crate::ops::{
|
|||||||
};
|
};
|
||||||
use crate::slice::{Iter, IterMut};
|
use crate::slice::{Iter, IterMut};
|
||||||
|
|
||||||
|
mod ascii;
|
||||||
mod drain;
|
mod drain;
|
||||||
mod equality;
|
mod equality;
|
||||||
mod iter;
|
mod iter;
|
||||||
|
@ -14,6 +14,10 @@ use crate::fmt;
|
|||||||
use crate::iter::FusedIterator;
|
use crate::iter::FusedIterator;
|
||||||
use crate::num::NonZeroUsize;
|
use crate::num::NonZeroUsize;
|
||||||
|
|
||||||
|
mod ascii_char;
|
||||||
|
#[unstable(feature = "ascii_char", issue = "110998")]
|
||||||
|
pub use ascii_char::AsciiChar as Char;
|
||||||
|
|
||||||
/// An iterator over the escaped version of a byte.
|
/// An iterator over the escaped version of a byte.
|
||||||
///
|
///
|
||||||
/// This `struct` is created by the [`escape_default`] function. See its
|
/// This `struct` is created by the [`escape_default`] function. See its
|
||||||
|
565
library/core/src/ascii/ascii_char.rs
Normal file
565
library/core/src/ascii/ascii_char.rs
Normal file
@ -0,0 +1,565 @@
|
|||||||
|
//! This uses the name `AsciiChar`, even though it's not exposed that way right now,
|
||||||
|
//! because it avoids a whole bunch of "are you sure you didn't mean `char`?"
|
||||||
|
//! suggestions from rustc if you get anything slightly wrong in here, and overall
|
||||||
|
//! helps with clarity as we're also referring to `char` intentionally in here.
|
||||||
|
|
||||||
|
use crate::fmt;
|
||||||
|
use crate::mem::transmute;
|
||||||
|
|
||||||
|
/// One of the 128 Unicode characters from U+0000 through U+007F,
|
||||||
|
/// often known as the [ASCII] subset.
|
||||||
|
///
|
||||||
|
/// Officially, this is the first [block] in Unicode, _Basic Latin_.
|
||||||
|
/// For details, see the [*C0 Controls and Basic Latin*][chart] code chart.
|
||||||
|
///
|
||||||
|
/// This block was based on older 7-bit character code standards such as
|
||||||
|
/// ANSI X3.4-1977, ISO 646-1973, and [NIST FIPS 1-2].
|
||||||
|
///
|
||||||
|
/// # When to use this
|
||||||
|
///
|
||||||
|
/// The main advantage of this subset is that it's always valid UTF-8. As such,
|
||||||
|
/// the `&[ascii::Char]` -> `&str` conversion function (as well as other related
|
||||||
|
/// ones) are O(1): *no* runtime checks are needed.
|
||||||
|
///
|
||||||
|
/// If you're consuming strings, you should usually handle Unicode and thus
|
||||||
|
/// accept `str`s, not limit yourself to `ascii::Char`s.
|
||||||
|
///
|
||||||
|
/// However, certain formats are intentionally designed to produce ASCII-only
|
||||||
|
/// output in order to be 8-bit-clean. In those cases, it can be simpler and
|
||||||
|
/// faster to generate `ascii::Char`s instead of dealing with the variable width
|
||||||
|
/// properties of general UTF-8 encoded strings, while still allowing the result
|
||||||
|
/// to be used freely with other Rust things that deal in general `str`s.
|
||||||
|
///
|
||||||
|
/// For example, a UUID library might offer a way to produce the string
|
||||||
|
/// representation of a UUID as an `[ascii::Char; 36]` to avoid memory
|
||||||
|
/// allocation yet still allow it to be used as UTF-8 via `as_str` without
|
||||||
|
/// paying for validation (or needing `unsafe` code) the way it would if it
|
||||||
|
/// were provided as a `[u8; 36]`.
|
||||||
|
///
|
||||||
|
/// # Layout
|
||||||
|
///
|
||||||
|
/// This type is guaranteed to have a size and alignment of 1 byte.
|
||||||
|
///
|
||||||
|
/// # Names
|
||||||
|
///
|
||||||
|
/// The variants on this type are [Unicode names][NamesList] of the characters
|
||||||
|
/// in upper camel case, with a few tweaks:
|
||||||
|
/// - For `<control>` characters, the primary alias name is used.
|
||||||
|
/// - `LATIN` is dropped, as this block has no non-latin letters.
|
||||||
|
/// - `LETTER` is dropped, as `CAPITAL`/`SMALL` suffices in this block.
|
||||||
|
/// - `DIGIT`s use a single digit rather than writing out `ZERO`, `ONE`, etc.
|
||||||
|
///
|
||||||
|
/// [ASCII]: https://www.unicode.org/glossary/index.html#ASCII
|
||||||
|
/// [block]: https://www.unicode.org/glossary/index.html#block
|
||||||
|
/// [chart]: https://www.unicode.org/charts/PDF/U0000.pdf
|
||||||
|
/// [NIST FIPS 1-2]: https://nvlpubs.nist.gov/nistpubs/Legacy/FIPS/fipspub1-2-1977.pdf
|
||||||
|
/// [NamesList]: https://www.unicode.org/Public/15.0.0/ucd/NamesList.txt
|
||||||
|
#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
|
||||||
|
#[unstable(feature = "ascii_char", issue = "110998")]
|
||||||
|
#[repr(u8)]
|
||||||
|
pub enum AsciiChar {
|
||||||
|
/// U+0000
|
||||||
|
#[unstable(feature = "ascii_char_variants", issue = "110998")]
|
||||||
|
Null = 0,
|
||||||
|
/// U+0001
|
||||||
|
#[unstable(feature = "ascii_char_variants", issue = "110998")]
|
||||||
|
StartOfHeading = 1,
|
||||||
|
/// U+0002
|
||||||
|
#[unstable(feature = "ascii_char_variants", issue = "110998")]
|
||||||
|
StartOfText = 2,
|
||||||
|
/// U+0003
|
||||||
|
#[unstable(feature = "ascii_char_variants", issue = "110998")]
|
||||||
|
EndOfText = 3,
|
||||||
|
/// U+0004
|
||||||
|
#[unstable(feature = "ascii_char_variants", issue = "110998")]
|
||||||
|
EndOfTransmission = 4,
|
||||||
|
/// U+0005
|
||||||
|
#[unstable(feature = "ascii_char_variants", issue = "110998")]
|
||||||
|
Enquiry = 5,
|
||||||
|
/// U+0006
|
||||||
|
#[unstable(feature = "ascii_char_variants", issue = "110998")]
|
||||||
|
Acknowledge = 6,
|
||||||
|
/// U+0007
|
||||||
|
#[unstable(feature = "ascii_char_variants", issue = "110998")]
|
||||||
|
Bell = 7,
|
||||||
|
/// U+0008
|
||||||
|
#[unstable(feature = "ascii_char_variants", issue = "110998")]
|
||||||
|
Backspace = 8,
|
||||||
|
/// U+0009
|
||||||
|
#[unstable(feature = "ascii_char_variants", issue = "110998")]
|
||||||
|
CharacterTabulation = 9,
|
||||||
|
/// U+000A
|
||||||
|
#[unstable(feature = "ascii_char_variants", issue = "110998")]
|
||||||
|
LineFeed = 10,
|
||||||
|
/// U+000B
|
||||||
|
#[unstable(feature = "ascii_char_variants", issue = "110998")]
|
||||||
|
LineTabulation = 11,
|
||||||
|
/// U+000C
|
||||||
|
#[unstable(feature = "ascii_char_variants", issue = "110998")]
|
||||||
|
FormFeed = 12,
|
||||||
|
/// U+000D
|
||||||
|
#[unstable(feature = "ascii_char_variants", issue = "110998")]
|
||||||
|
CarriageReturn = 13,
|
||||||
|
/// U+000E
|
||||||
|
#[unstable(feature = "ascii_char_variants", issue = "110998")]
|
||||||
|
ShiftOut = 14,
|
||||||
|
/// U+000F
|
||||||
|
#[unstable(feature = "ascii_char_variants", issue = "110998")]
|
||||||
|
ShiftIn = 15,
|
||||||
|
/// U+0010
|
||||||
|
#[unstable(feature = "ascii_char_variants", issue = "110998")]
|
||||||
|
DataLinkEscape = 16,
|
||||||
|
/// U+0011
|
||||||
|
#[unstable(feature = "ascii_char_variants", issue = "110998")]
|
||||||
|
DeviceControlOne = 17,
|
||||||
|
/// U+0012
|
||||||
|
#[unstable(feature = "ascii_char_variants", issue = "110998")]
|
||||||
|
DeviceControlTwo = 18,
|
||||||
|
/// U+0013
|
||||||
|
#[unstable(feature = "ascii_char_variants", issue = "110998")]
|
||||||
|
DeviceControlThree = 19,
|
||||||
|
/// U+0014
|
||||||
|
#[unstable(feature = "ascii_char_variants", issue = "110998")]
|
||||||
|
DeviceControlFour = 20,
|
||||||
|
/// U+0015
|
||||||
|
#[unstable(feature = "ascii_char_variants", issue = "110998")]
|
||||||
|
NegativeAcknowledge = 21,
|
||||||
|
/// U+0016
|
||||||
|
#[unstable(feature = "ascii_char_variants", issue = "110998")]
|
||||||
|
SynchronousIdle = 22,
|
||||||
|
/// U+0017
|
||||||
|
#[unstable(feature = "ascii_char_variants", issue = "110998")]
|
||||||
|
EndOfTransmissionBlock = 23,
|
||||||
|
/// U+0018
|
||||||
|
#[unstable(feature = "ascii_char_variants", issue = "110998")]
|
||||||
|
Cancel = 24,
|
||||||
|
/// U+0019
|
||||||
|
#[unstable(feature = "ascii_char_variants", issue = "110998")]
|
||||||
|
EndOfMedium = 25,
|
||||||
|
/// U+001A
|
||||||
|
#[unstable(feature = "ascii_char_variants", issue = "110998")]
|
||||||
|
Substitute = 26,
|
||||||
|
/// U+001B
|
||||||
|
#[unstable(feature = "ascii_char_variants", issue = "110998")]
|
||||||
|
Escape = 27,
|
||||||
|
/// U+001C
|
||||||
|
#[unstable(feature = "ascii_char_variants", issue = "110998")]
|
||||||
|
InformationSeparatorFour = 28,
|
||||||
|
/// U+001D
|
||||||
|
#[unstable(feature = "ascii_char_variants", issue = "110998")]
|
||||||
|
InformationSeparatorThree = 29,
|
||||||
|
/// U+001E
|
||||||
|
#[unstable(feature = "ascii_char_variants", issue = "110998")]
|
||||||
|
InformationSeparatorTwo = 30,
|
||||||
|
/// U+001F
|
||||||
|
#[unstable(feature = "ascii_char_variants", issue = "110998")]
|
||||||
|
InformationSeparatorOne = 31,
|
||||||
|
/// U+0020
|
||||||
|
#[unstable(feature = "ascii_char_variants", issue = "110998")]
|
||||||
|
Space = 32,
|
||||||
|
/// U+0021
|
||||||
|
#[unstable(feature = "ascii_char_variants", issue = "110998")]
|
||||||
|
ExclamationMark = 33,
|
||||||
|
/// U+0022
|
||||||
|
#[unstable(feature = "ascii_char_variants", issue = "110998")]
|
||||||
|
QuotationMark = 34,
|
||||||
|
/// U+0023
|
||||||
|
#[unstable(feature = "ascii_char_variants", issue = "110998")]
|
||||||
|
NumberSign = 35,
|
||||||
|
/// U+0024
|
||||||
|
#[unstable(feature = "ascii_char_variants", issue = "110998")]
|
||||||
|
DollarSign = 36,
|
||||||
|
/// U+0025
|
||||||
|
#[unstable(feature = "ascii_char_variants", issue = "110998")]
|
||||||
|
PercentSign = 37,
|
||||||
|
/// U+0026
|
||||||
|
#[unstable(feature = "ascii_char_variants", issue = "110998")]
|
||||||
|
Ampersand = 38,
|
||||||
|
/// U+0027
|
||||||
|
#[unstable(feature = "ascii_char_variants", issue = "110998")]
|
||||||
|
Apostrophe = 39,
|
||||||
|
/// U+0028
|
||||||
|
#[unstable(feature = "ascii_char_variants", issue = "110998")]
|
||||||
|
LeftParenthesis = 40,
|
||||||
|
/// U+0029
|
||||||
|
#[unstable(feature = "ascii_char_variants", issue = "110998")]
|
||||||
|
RightParenthesis = 41,
|
||||||
|
/// U+002A
|
||||||
|
#[unstable(feature = "ascii_char_variants", issue = "110998")]
|
||||||
|
Asterisk = 42,
|
||||||
|
/// U+002B
|
||||||
|
#[unstable(feature = "ascii_char_variants", issue = "110998")]
|
||||||
|
PlusSign = 43,
|
||||||
|
/// U+002C
|
||||||
|
#[unstable(feature = "ascii_char_variants", issue = "110998")]
|
||||||
|
Comma = 44,
|
||||||
|
/// U+002D
|
||||||
|
#[unstable(feature = "ascii_char_variants", issue = "110998")]
|
||||||
|
HyphenMinus = 45,
|
||||||
|
/// U+002E
|
||||||
|
#[unstable(feature = "ascii_char_variants", issue = "110998")]
|
||||||
|
FullStop = 46,
|
||||||
|
/// U+002F
|
||||||
|
#[unstable(feature = "ascii_char_variants", issue = "110998")]
|
||||||
|
Solidus = 47,
|
||||||
|
/// U+0030
|
||||||
|
#[unstable(feature = "ascii_char_variants", issue = "110998")]
|
||||||
|
Digit0 = 48,
|
||||||
|
/// U+0031
|
||||||
|
#[unstable(feature = "ascii_char_variants", issue = "110998")]
|
||||||
|
Digit1 = 49,
|
||||||
|
/// U+0032
|
||||||
|
#[unstable(feature = "ascii_char_variants", issue = "110998")]
|
||||||
|
Digit2 = 50,
|
||||||
|
/// U+0033
|
||||||
|
#[unstable(feature = "ascii_char_variants", issue = "110998")]
|
||||||
|
Digit3 = 51,
|
||||||
|
/// U+0034
|
||||||
|
#[unstable(feature = "ascii_char_variants", issue = "110998")]
|
||||||
|
Digit4 = 52,
|
||||||
|
/// U+0035
|
||||||
|
#[unstable(feature = "ascii_char_variants", issue = "110998")]
|
||||||
|
Digit5 = 53,
|
||||||
|
/// U+0036
|
||||||
|
#[unstable(feature = "ascii_char_variants", issue = "110998")]
|
||||||
|
Digit6 = 54,
|
||||||
|
/// U+0037
|
||||||
|
#[unstable(feature = "ascii_char_variants", issue = "110998")]
|
||||||
|
Digit7 = 55,
|
||||||
|
/// U+0038
|
||||||
|
#[unstable(feature = "ascii_char_variants", issue = "110998")]
|
||||||
|
Digit8 = 56,
|
||||||
|
/// U+0039
|
||||||
|
#[unstable(feature = "ascii_char_variants", issue = "110998")]
|
||||||
|
Digit9 = 57,
|
||||||
|
/// U+003A
|
||||||
|
#[unstable(feature = "ascii_char_variants", issue = "110998")]
|
||||||
|
Colon = 58,
|
||||||
|
/// U+003B
|
||||||
|
#[unstable(feature = "ascii_char_variants", issue = "110998")]
|
||||||
|
Semicolon = 59,
|
||||||
|
/// U+003C
|
||||||
|
#[unstable(feature = "ascii_char_variants", issue = "110998")]
|
||||||
|
LessThanSign = 60,
|
||||||
|
/// U+003D
|
||||||
|
#[unstable(feature = "ascii_char_variants", issue = "110998")]
|
||||||
|
EqualsSign = 61,
|
||||||
|
/// U+003E
|
||||||
|
#[unstable(feature = "ascii_char_variants", issue = "110998")]
|
||||||
|
GreaterThanSign = 62,
|
||||||
|
/// U+003F
|
||||||
|
#[unstable(feature = "ascii_char_variants", issue = "110998")]
|
||||||
|
QuestionMark = 63,
|
||||||
|
/// U+0040
|
||||||
|
#[unstable(feature = "ascii_char_variants", issue = "110998")]
|
||||||
|
CommercialAt = 64,
|
||||||
|
/// U+0041
|
||||||
|
#[unstable(feature = "ascii_char_variants", issue = "110998")]
|
||||||
|
CapitalA = 65,
|
||||||
|
/// U+0042
|
||||||
|
#[unstable(feature = "ascii_char_variants", issue = "110998")]
|
||||||
|
CapitalB = 66,
|
||||||
|
/// U+0043
|
||||||
|
#[unstable(feature = "ascii_char_variants", issue = "110998")]
|
||||||
|
CapitalC = 67,
|
||||||
|
/// U+0044
|
||||||
|
#[unstable(feature = "ascii_char_variants", issue = "110998")]
|
||||||
|
CapitalD = 68,
|
||||||
|
/// U+0045
|
||||||
|
#[unstable(feature = "ascii_char_variants", issue = "110998")]
|
||||||
|
CapitalE = 69,
|
||||||
|
/// U+0046
|
||||||
|
#[unstable(feature = "ascii_char_variants", issue = "110998")]
|
||||||
|
CapitalF = 70,
|
||||||
|
/// U+0047
|
||||||
|
#[unstable(feature = "ascii_char_variants", issue = "110998")]
|
||||||
|
CapitalG = 71,
|
||||||
|
/// U+0048
|
||||||
|
#[unstable(feature = "ascii_char_variants", issue = "110998")]
|
||||||
|
CapitalH = 72,
|
||||||
|
/// U+0049
|
||||||
|
#[unstable(feature = "ascii_char_variants", issue = "110998")]
|
||||||
|
CapitalI = 73,
|
||||||
|
/// U+004A
|
||||||
|
#[unstable(feature = "ascii_char_variants", issue = "110998")]
|
||||||
|
CapitalJ = 74,
|
||||||
|
/// U+004B
|
||||||
|
#[unstable(feature = "ascii_char_variants", issue = "110998")]
|
||||||
|
CapitalK = 75,
|
||||||
|
/// U+004C
|
||||||
|
#[unstable(feature = "ascii_char_variants", issue = "110998")]
|
||||||
|
CapitalL = 76,
|
||||||
|
/// U+004D
|
||||||
|
#[unstable(feature = "ascii_char_variants", issue = "110998")]
|
||||||
|
CapitalM = 77,
|
||||||
|
/// U+004E
|
||||||
|
#[unstable(feature = "ascii_char_variants", issue = "110998")]
|
||||||
|
CapitalN = 78,
|
||||||
|
/// U+004F
|
||||||
|
#[unstable(feature = "ascii_char_variants", issue = "110998")]
|
||||||
|
CapitalO = 79,
|
||||||
|
/// U+0050
|
||||||
|
#[unstable(feature = "ascii_char_variants", issue = "110998")]
|
||||||
|
CapitalP = 80,
|
||||||
|
/// U+0051
|
||||||
|
#[unstable(feature = "ascii_char_variants", issue = "110998")]
|
||||||
|
CapitalQ = 81,
|
||||||
|
/// U+0052
|
||||||
|
#[unstable(feature = "ascii_char_variants", issue = "110998")]
|
||||||
|
CapitalR = 82,
|
||||||
|
/// U+0053
|
||||||
|
#[unstable(feature = "ascii_char_variants", issue = "110998")]
|
||||||
|
CapitalS = 83,
|
||||||
|
/// U+0054
|
||||||
|
#[unstable(feature = "ascii_char_variants", issue = "110998")]
|
||||||
|
CapitalT = 84,
|
||||||
|
/// U+0055
|
||||||
|
#[unstable(feature = "ascii_char_variants", issue = "110998")]
|
||||||
|
CapitalU = 85,
|
||||||
|
/// U+0056
|
||||||
|
#[unstable(feature = "ascii_char_variants", issue = "110998")]
|
||||||
|
CapitalV = 86,
|
||||||
|
/// U+0057
|
||||||
|
#[unstable(feature = "ascii_char_variants", issue = "110998")]
|
||||||
|
CapitalW = 87,
|
||||||
|
/// U+0058
|
||||||
|
#[unstable(feature = "ascii_char_variants", issue = "110998")]
|
||||||
|
CapitalX = 88,
|
||||||
|
/// U+0059
|
||||||
|
#[unstable(feature = "ascii_char_variants", issue = "110998")]
|
||||||
|
CapitalY = 89,
|
||||||
|
/// U+005A
|
||||||
|
#[unstable(feature = "ascii_char_variants", issue = "110998")]
|
||||||
|
CapitalZ = 90,
|
||||||
|
/// U+005B
|
||||||
|
#[unstable(feature = "ascii_char_variants", issue = "110998")]
|
||||||
|
LeftSquareBracket = 91,
|
||||||
|
/// U+005C
|
||||||
|
#[unstable(feature = "ascii_char_variants", issue = "110998")]
|
||||||
|
ReverseSolidus = 92,
|
||||||
|
/// U+005D
|
||||||
|
#[unstable(feature = "ascii_char_variants", issue = "110998")]
|
||||||
|
RightSquareBracket = 93,
|
||||||
|
/// U+005E
|
||||||
|
#[unstable(feature = "ascii_char_variants", issue = "110998")]
|
||||||
|
CircumflexAccent = 94,
|
||||||
|
/// U+005F
|
||||||
|
#[unstable(feature = "ascii_char_variants", issue = "110998")]
|
||||||
|
LowLine = 95,
|
||||||
|
/// U+0060
|
||||||
|
#[unstable(feature = "ascii_char_variants", issue = "110998")]
|
||||||
|
GraveAccent = 96,
|
||||||
|
/// U+0061
|
||||||
|
#[unstable(feature = "ascii_char_variants", issue = "110998")]
|
||||||
|
SmallA = 97,
|
||||||
|
/// U+0062
|
||||||
|
#[unstable(feature = "ascii_char_variants", issue = "110998")]
|
||||||
|
SmallB = 98,
|
||||||
|
/// U+0063
|
||||||
|
#[unstable(feature = "ascii_char_variants", issue = "110998")]
|
||||||
|
SmallC = 99,
|
||||||
|
/// U+0064
|
||||||
|
#[unstable(feature = "ascii_char_variants", issue = "110998")]
|
||||||
|
SmallD = 100,
|
||||||
|
/// U+0065
|
||||||
|
#[unstable(feature = "ascii_char_variants", issue = "110998")]
|
||||||
|
SmallE = 101,
|
||||||
|
/// U+0066
|
||||||
|
#[unstable(feature = "ascii_char_variants", issue = "110998")]
|
||||||
|
SmallF = 102,
|
||||||
|
/// U+0067
|
||||||
|
#[unstable(feature = "ascii_char_variants", issue = "110998")]
|
||||||
|
SmallG = 103,
|
||||||
|
/// U+0068
|
||||||
|
#[unstable(feature = "ascii_char_variants", issue = "110998")]
|
||||||
|
SmallH = 104,
|
||||||
|
/// U+0069
|
||||||
|
#[unstable(feature = "ascii_char_variants", issue = "110998")]
|
||||||
|
SmallI = 105,
|
||||||
|
/// U+006A
|
||||||
|
#[unstable(feature = "ascii_char_variants", issue = "110998")]
|
||||||
|
SmallJ = 106,
|
||||||
|
/// U+006B
|
||||||
|
#[unstable(feature = "ascii_char_variants", issue = "110998")]
|
||||||
|
SmallK = 107,
|
||||||
|
/// U+006C
|
||||||
|
#[unstable(feature = "ascii_char_variants", issue = "110998")]
|
||||||
|
SmallL = 108,
|
||||||
|
/// U+006D
|
||||||
|
#[unstable(feature = "ascii_char_variants", issue = "110998")]
|
||||||
|
SmallM = 109,
|
||||||
|
/// U+006E
|
||||||
|
#[unstable(feature = "ascii_char_variants", issue = "110998")]
|
||||||
|
SmallN = 110,
|
||||||
|
/// U+006F
|
||||||
|
#[unstable(feature = "ascii_char_variants", issue = "110998")]
|
||||||
|
SmallO = 111,
|
||||||
|
/// U+0070
|
||||||
|
#[unstable(feature = "ascii_char_variants", issue = "110998")]
|
||||||
|
SmallP = 112,
|
||||||
|
/// U+0071
|
||||||
|
#[unstable(feature = "ascii_char_variants", issue = "110998")]
|
||||||
|
SmallQ = 113,
|
||||||
|
/// U+0072
|
||||||
|
#[unstable(feature = "ascii_char_variants", issue = "110998")]
|
||||||
|
SmallR = 114,
|
||||||
|
/// U+0073
|
||||||
|
#[unstable(feature = "ascii_char_variants", issue = "110998")]
|
||||||
|
SmallS = 115,
|
||||||
|
/// U+0074
|
||||||
|
#[unstable(feature = "ascii_char_variants", issue = "110998")]
|
||||||
|
SmallT = 116,
|
||||||
|
/// U+0075
|
||||||
|
#[unstable(feature = "ascii_char_variants", issue = "110998")]
|
||||||
|
SmallU = 117,
|
||||||
|
/// U+0076
|
||||||
|
#[unstable(feature = "ascii_char_variants", issue = "110998")]
|
||||||
|
SmallV = 118,
|
||||||
|
/// U+0077
|
||||||
|
#[unstable(feature = "ascii_char_variants", issue = "110998")]
|
||||||
|
SmallW = 119,
|
||||||
|
/// U+0078
|
||||||
|
#[unstable(feature = "ascii_char_variants", issue = "110998")]
|
||||||
|
SmallX = 120,
|
||||||
|
/// U+0079
|
||||||
|
#[unstable(feature = "ascii_char_variants", issue = "110998")]
|
||||||
|
SmallY = 121,
|
||||||
|
/// U+007A
|
||||||
|
#[unstable(feature = "ascii_char_variants", issue = "110998")]
|
||||||
|
SmallZ = 122,
|
||||||
|
/// U+007B
|
||||||
|
#[unstable(feature = "ascii_char_variants", issue = "110998")]
|
||||||
|
LeftCurlyBracket = 123,
|
||||||
|
/// U+007C
|
||||||
|
#[unstable(feature = "ascii_char_variants", issue = "110998")]
|
||||||
|
VerticalLine = 124,
|
||||||
|
/// U+007D
|
||||||
|
#[unstable(feature = "ascii_char_variants", issue = "110998")]
|
||||||
|
RightCurlyBracket = 125,
|
||||||
|
/// U+007E
|
||||||
|
#[unstable(feature = "ascii_char_variants", issue = "110998")]
|
||||||
|
Tilde = 126,
|
||||||
|
/// U+007F
|
||||||
|
#[unstable(feature = "ascii_char_variants", issue = "110998")]
|
||||||
|
Delete = 127,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AsciiChar {
|
||||||
|
/// Creates an ascii character from the byte `b`,
|
||||||
|
/// or returns `None` if it's too large.
|
||||||
|
#[unstable(feature = "ascii_char", issue = "110998")]
|
||||||
|
#[inline]
|
||||||
|
pub const fn from_u8(b: u8) -> Option<Self> {
|
||||||
|
if b <= 127 {
|
||||||
|
// SAFETY: Just checked that `b` is in-range
|
||||||
|
Some(unsafe { Self::from_u8_unchecked(b) })
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Creates an ASCII character from the byte `b`,
|
||||||
|
/// without checking whether it's valid.
|
||||||
|
///
|
||||||
|
/// # Safety
|
||||||
|
///
|
||||||
|
/// `b` must be in `0..=127`, or else this is UB.
|
||||||
|
#[unstable(feature = "ascii_char", issue = "110998")]
|
||||||
|
#[inline]
|
||||||
|
pub const unsafe fn from_u8_unchecked(b: u8) -> Self {
|
||||||
|
// SAFETY: Our safety precondition is that `b` is in-range.
|
||||||
|
unsafe { transmute(b) }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// When passed the *number* `0`, `1`, …, `9`, returns the *character*
|
||||||
|
/// `'0'`, `'1'`, …, `'9'` respectively.
|
||||||
|
///
|
||||||
|
/// If `d >= 10`, returns `None`.
|
||||||
|
#[unstable(feature = "ascii_char", issue = "110998")]
|
||||||
|
#[inline]
|
||||||
|
pub const fn digit(d: u8) -> Option<Self> {
|
||||||
|
if d < 10 {
|
||||||
|
// SAFETY: Just checked it's in-range.
|
||||||
|
Some(unsafe { Self::digit_unchecked(d) })
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// When passed the *number* `0`, `1`, …, `9`, returns the *character*
|
||||||
|
/// `'0'`, `'1'`, …, `'9'` respectively, without checking that it's in-range.
|
||||||
|
///
|
||||||
|
/// # Safety
|
||||||
|
///
|
||||||
|
/// This is immediate UB if called with `d > 64`.
|
||||||
|
///
|
||||||
|
/// If `d >= 10` and `d <= 64`, this is allowed to return any value or panic.
|
||||||
|
/// Notably, it should not be expected to return hex digits, or any other
|
||||||
|
/// reasonable extension of the decimal digits.
|
||||||
|
///
|
||||||
|
/// (This lose safety condition is intended to simplify soundness proofs
|
||||||
|
/// when writing code using this method, since the implementation doesn't
|
||||||
|
/// need something really specific, not to make those other arguments do
|
||||||
|
/// something useful. It might be tightened before stabilization.)
|
||||||
|
#[unstable(feature = "ascii_char", issue = "110998")]
|
||||||
|
#[inline]
|
||||||
|
pub const unsafe fn digit_unchecked(d: u8) -> Self {
|
||||||
|
debug_assert!(d < 10);
|
||||||
|
|
||||||
|
// SAFETY: `'0'` through `'9'` are U+00030 through U+0039,
|
||||||
|
// so because `d` must be 64 or less the addition can return at most
|
||||||
|
// 112 (0x70), which doesn't overflow and is within the ASCII range.
|
||||||
|
unsafe {
|
||||||
|
let byte = b'0'.unchecked_add(d);
|
||||||
|
Self::from_u8_unchecked(byte)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Gets this ASCII character as a byte.
|
||||||
|
#[unstable(feature = "ascii_char", issue = "110998")]
|
||||||
|
#[inline]
|
||||||
|
pub const fn as_u8(self) -> u8 {
|
||||||
|
self as u8
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Gets this ASCII character as a `char` Unicode Scalar Value.
|
||||||
|
#[unstable(feature = "ascii_char", issue = "110998")]
|
||||||
|
#[inline]
|
||||||
|
pub const fn as_char(self) -> char {
|
||||||
|
self as u8 as char
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Views this ASCII character as a one-code-unit UTF-8 `str`.
|
||||||
|
#[unstable(feature = "ascii_char", issue = "110998")]
|
||||||
|
#[inline]
|
||||||
|
pub const fn as_str(&self) -> &str {
|
||||||
|
crate::slice::from_ref(self).as_str()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl [AsciiChar] {
|
||||||
|
/// Views this slice of ASCII characters as a UTF-8 `str`.
|
||||||
|
#[unstable(feature = "ascii_char", issue = "110998")]
|
||||||
|
#[inline]
|
||||||
|
pub const fn as_str(&self) -> &str {
|
||||||
|
let ascii_ptr: *const Self = self;
|
||||||
|
let str_ptr = ascii_ptr as *const str;
|
||||||
|
// SAFETY: Each ASCII codepoint in UTF-8 is encoded as one single-byte
|
||||||
|
// code unit having the same value as the ASCII byte.
|
||||||
|
unsafe { &*str_ptr }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Views this slice of ASCII characters as a slice of `u8` bytes.
|
||||||
|
#[unstable(feature = "ascii_char", issue = "110998")]
|
||||||
|
#[inline]
|
||||||
|
pub const fn as_bytes(&self) -> &[u8] {
|
||||||
|
self.as_str().as_bytes()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[unstable(feature = "ascii_char", issue = "110998")]
|
||||||
|
impl fmt::Display for AsciiChar {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
<str as fmt::Display>::fmt(self.as_str(), f)
|
||||||
|
}
|
||||||
|
}
|
@ -1,5 +1,6 @@
|
|||||||
//! impl char {}
|
//! impl char {}
|
||||||
|
|
||||||
|
use crate::ascii;
|
||||||
use crate::slice;
|
use crate::slice;
|
||||||
use crate::str::from_utf8_unchecked_mut;
|
use crate::str::from_utf8_unchecked_mut;
|
||||||
use crate::unicode::printable::is_printable;
|
use crate::unicode::printable::is_printable;
|
||||||
@ -1101,6 +1102,24 @@ impl char {
|
|||||||
*self as u32 <= 0x7F
|
*self as u32 <= 0x7F
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns `Some` if the value is within the ASCII range,
|
||||||
|
/// or `None` if it's not.
|
||||||
|
///
|
||||||
|
/// This is preferred to [`Self::is_ascii`] when you're passing the value
|
||||||
|
/// along to something else that can take [`ascii::Char`] rather than
|
||||||
|
/// needing to check again for itself whether the value is in ASCII.
|
||||||
|
#[must_use]
|
||||||
|
#[unstable(feature = "ascii_char", issue = "110998")]
|
||||||
|
#[inline]
|
||||||
|
pub const fn as_ascii(&self) -> Option<ascii::Char> {
|
||||||
|
if self.is_ascii() {
|
||||||
|
// SAFETY: Just checked that this is ASCII.
|
||||||
|
Some(unsafe { ascii::Char::from_u8_unchecked(*self as u8) })
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Makes a copy of the value in its ASCII upper case equivalent.
|
/// Makes a copy of the value in its ASCII upper case equivalent.
|
||||||
///
|
///
|
||||||
/// ASCII letters 'a' to 'z' are mapped to 'A' to 'Z',
|
/// ASCII letters 'a' to 'z' are mapped to 'A' to 'Z',
|
||||||
|
@ -472,7 +472,16 @@ impl u8 {
|
|||||||
#[rustc_const_stable(feature = "const_u8_is_ascii", since = "1.43.0")]
|
#[rustc_const_stable(feature = "const_u8_is_ascii", since = "1.43.0")]
|
||||||
#[inline]
|
#[inline]
|
||||||
pub const fn is_ascii(&self) -> bool {
|
pub const fn is_ascii(&self) -> bool {
|
||||||
*self & 128 == 0
|
*self <= 127
|
||||||
|
}
|
||||||
|
|
||||||
|
/// If the value of this byte is within the ASCII range, returns it as an
|
||||||
|
/// [ASCII character](ascii::Char). Otherwise, returns `None`.
|
||||||
|
#[must_use]
|
||||||
|
#[unstable(feature = "ascii_char", issue = "110998")]
|
||||||
|
#[inline]
|
||||||
|
pub const fn as_ascii(&self) -> Option<ascii::Char> {
|
||||||
|
ascii::Char::from_u8(*self)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Makes a copy of the value in its ASCII upper case equivalent.
|
/// Makes a copy of the value in its ASCII upper case equivalent.
|
||||||
|
@ -713,6 +713,32 @@ macro_rules! nonzero_signed_operations {
|
|||||||
unsafe { $Uty::new_unchecked(self.get().unsigned_abs()) }
|
unsafe { $Uty::new_unchecked(self.get().unsigned_abs()) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns `true` if `self` is positive and `false` if the
|
||||||
|
/// number is negative.
|
||||||
|
///
|
||||||
|
/// # Example
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// #![feature(nonzero_negation_ops)]
|
||||||
|
///
|
||||||
|
#[doc = concat!("# use std::num::", stringify!($Ty), ";")]
|
||||||
|
/// # fn main() { test().unwrap(); }
|
||||||
|
/// # fn test() -> Option<()> {
|
||||||
|
#[doc = concat!("let pos_five = ", stringify!($Ty), "::new(5)?;")]
|
||||||
|
#[doc = concat!("let neg_five = ", stringify!($Ty), "::new(-5)?;")]
|
||||||
|
///
|
||||||
|
/// assert!(pos_five.is_positive());
|
||||||
|
/// assert!(!neg_five.is_positive());
|
||||||
|
/// # Some(())
|
||||||
|
/// # }
|
||||||
|
/// ```
|
||||||
|
#[must_use]
|
||||||
|
#[inline]
|
||||||
|
#[unstable(feature = "nonzero_negation_ops", issue = "102443")]
|
||||||
|
pub const fn is_positive(self) -> bool {
|
||||||
|
self.get().is_positive()
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns `true` if `self` is negative and `false` if the
|
/// Returns `true` if `self` is negative and `false` if the
|
||||||
/// number is positive.
|
/// number is positive.
|
||||||
///
|
///
|
||||||
|
@ -16,6 +16,36 @@ impl [u8] {
|
|||||||
is_ascii(self)
|
is_ascii(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// If this slice [`is_ascii`](Self::is_ascii), returns it as a slice of
|
||||||
|
/// [ASCII characters](`ascii::Char`), otherwise returns `None`.
|
||||||
|
#[unstable(feature = "ascii_char", issue = "110998")]
|
||||||
|
#[must_use]
|
||||||
|
#[inline]
|
||||||
|
pub fn as_ascii(&self) -> Option<&[ascii::Char]> {
|
||||||
|
if self.is_ascii() {
|
||||||
|
// SAFETY: Just checked that it's ASCII
|
||||||
|
Some(unsafe { self.as_ascii_unchecked() })
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Converts this slice of bytes into a slice of ASCII characters,
|
||||||
|
/// without checking whether they're valid.
|
||||||
|
///
|
||||||
|
/// # Safety
|
||||||
|
///
|
||||||
|
/// Every byte in the slice must be in `0..=127`, or else this is UB.
|
||||||
|
#[unstable(feature = "ascii_char", issue = "110998")]
|
||||||
|
#[must_use]
|
||||||
|
#[inline]
|
||||||
|
pub const unsafe fn as_ascii_unchecked(&self) -> &[ascii::Char] {
|
||||||
|
let byte_ptr: *const [u8] = self;
|
||||||
|
let ascii_ptr = byte_ptr as *const [ascii::Char];
|
||||||
|
// SAFETY: The caller promised all the bytes are ASCII
|
||||||
|
unsafe { &*ascii_ptr }
|
||||||
|
}
|
||||||
|
|
||||||
/// Checks that two slices are an ASCII case-insensitive match.
|
/// Checks that two slices are an ASCII case-insensitive match.
|
||||||
///
|
///
|
||||||
/// Same as `to_ascii_lowercase(a) == to_ascii_lowercase(b)`,
|
/// Same as `to_ascii_lowercase(a) == to_ascii_lowercase(b)`,
|
||||||
|
@ -16,6 +16,7 @@ mod validations;
|
|||||||
use self::pattern::Pattern;
|
use self::pattern::Pattern;
|
||||||
use self::pattern::{DoubleEndedSearcher, ReverseSearcher, Searcher};
|
use self::pattern::{DoubleEndedSearcher, ReverseSearcher, Searcher};
|
||||||
|
|
||||||
|
use crate::ascii;
|
||||||
use crate::char::{self, EscapeDebugExtArgs};
|
use crate::char::{self, EscapeDebugExtArgs};
|
||||||
use crate::mem;
|
use crate::mem;
|
||||||
use crate::slice::{self, SliceIndex};
|
use crate::slice::{self, SliceIndex};
|
||||||
@ -2366,6 +2367,16 @@ impl str {
|
|||||||
self.as_bytes().is_ascii()
|
self.as_bytes().is_ascii()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// If this string slice [`is_ascii`](Self::is_ascii), returns it as a slice
|
||||||
|
/// of [ASCII characters](`ascii::Char`), otherwise returns `None`.
|
||||||
|
#[unstable(feature = "ascii_char", issue = "110998")]
|
||||||
|
#[must_use]
|
||||||
|
#[inline]
|
||||||
|
pub fn as_ascii(&self) -> Option<&[ascii::Char]> {
|
||||||
|
// Like in `is_ascii`, we can work on the bytes directly.
|
||||||
|
self.as_bytes().as_ascii()
|
||||||
|
}
|
||||||
|
|
||||||
/// Checks that two strings are an ASCII case-insensitive match.
|
/// Checks that two strings are an ASCII case-insensitive match.
|
||||||
///
|
///
|
||||||
/// Same as `to_ascii_lowercase(a) == to_ascii_lowercase(b)`,
|
/// Same as `to_ascii_lowercase(a) == to_ascii_lowercase(b)`,
|
||||||
|
@ -16,6 +16,9 @@
|
|||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
pub use core::ascii::{escape_default, EscapeDefault};
|
pub use core::ascii::{escape_default, EscapeDefault};
|
||||||
|
|
||||||
|
#[unstable(feature = "ascii_char", issue = "110998")]
|
||||||
|
pub use core::ascii::Char;
|
||||||
|
|
||||||
/// Extension methods for ASCII-subset only operations.
|
/// Extension methods for ASCII-subset only operations.
|
||||||
///
|
///
|
||||||
/// Be aware that operations on seemingly non-ASCII characters can sometimes
|
/// Be aware that operations on seemingly non-ASCII characters can sometimes
|
||||||
|
27
library/sysroot/Cargo.toml
Normal file
27
library/sysroot/Cargo.toml
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
[package]
|
||||||
|
name = "sysroot"
|
||||||
|
version = "0.0.0"
|
||||||
|
edition = "2021"
|
||||||
|
|
||||||
|
# this is a dummy crate to ensure that all required crates appear in the sysroot
|
||||||
|
[dependencies]
|
||||||
|
proc_macro = { path = "../proc_macro" }
|
||||||
|
std = { path = "../std" }
|
||||||
|
test = { path = "../test" }
|
||||||
|
|
||||||
|
# Forward features to the `std` crate as necessary
|
||||||
|
[features]
|
||||||
|
default = ["std_detect_file_io", "std_detect_dlsym_getauxval", "panic-unwind"]
|
||||||
|
backtrace = ["std/backtrace"]
|
||||||
|
compiler-builtins-c = ["std/compiler-builtins-c"]
|
||||||
|
compiler-builtins-mem = ["std/compiler-builtins-mem"]
|
||||||
|
compiler-builtins-no-asm = ["std/compiler-builtins-no-asm"]
|
||||||
|
compiler-builtins-mangled-names = ["std/compiler-builtins-mangled-names"]
|
||||||
|
llvm-libunwind = ["std/llvm-libunwind"]
|
||||||
|
system-llvm-libunwind = ["std/system-llvm-libunwind"]
|
||||||
|
panic-unwind = ["std/panic_unwind"]
|
||||||
|
panic_immediate_abort = ["std/panic_immediate_abort"]
|
||||||
|
profiler = ["std/profiler"]
|
||||||
|
std_detect_file_io = ["std/std_detect_file_io"]
|
||||||
|
std_detect_dlsym_getauxval = ["std/std_detect_dlsym_getauxval"]
|
||||||
|
std_detect_env_override = ["std/std_detect_env_override"]
|
1
library/sysroot/src/lib.rs
Normal file
1
library/sysroot/src/lib.rs
Normal file
@ -0,0 +1 @@
|
|||||||
|
// This is intentionally empty since this crate is only used to depend on other library crates.
|
@ -12,23 +12,3 @@ std = { path = "../std" }
|
|||||||
core = { path = "../core" }
|
core = { path = "../core" }
|
||||||
panic_unwind = { path = "../panic_unwind" }
|
panic_unwind = { path = "../panic_unwind" }
|
||||||
panic_abort = { path = "../panic_abort" }
|
panic_abort = { path = "../panic_abort" }
|
||||||
|
|
||||||
# not actually used but needed to always have proc_macro in the sysroot
|
|
||||||
proc_macro = { path = "../proc_macro" }
|
|
||||||
|
|
||||||
# Forward features to the `std` crate as necessary
|
|
||||||
[features]
|
|
||||||
default = ["std_detect_file_io", "std_detect_dlsym_getauxval", "panic-unwind"]
|
|
||||||
backtrace = ["std/backtrace"]
|
|
||||||
compiler-builtins-c = ["std/compiler-builtins-c"]
|
|
||||||
compiler-builtins-mem = ["std/compiler-builtins-mem"]
|
|
||||||
compiler-builtins-no-asm = ["std/compiler-builtins-no-asm"]
|
|
||||||
compiler-builtins-mangled-names = ["std/compiler-builtins-mangled-names"]
|
|
||||||
llvm-libunwind = ["std/llvm-libunwind"]
|
|
||||||
system-llvm-libunwind = ["std/system-llvm-libunwind"]
|
|
||||||
panic-unwind = ["std/panic_unwind"]
|
|
||||||
panic_immediate_abort = ["std/panic_immediate_abort"]
|
|
||||||
profiler = ["std/profiler"]
|
|
||||||
std_detect_file_io = ["std/std_detect_file_io"]
|
|
||||||
std_detect_dlsym_getauxval = ["std/std_detect_dlsym_getauxval"]
|
|
||||||
std_detect_env_override = ["std/std_detect_env_override"]
|
|
||||||
|
@ -11,7 +11,7 @@ use crate::{
|
|||||||
|
|
||||||
pub struct JunitFormatter<T> {
|
pub struct JunitFormatter<T> {
|
||||||
out: OutputLocation<T>,
|
out: OutputLocation<T>,
|
||||||
results: Vec<(TestDesc, TestResult, Duration)>,
|
results: Vec<(TestDesc, TestResult, Duration, Vec<u8>)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: Write> JunitFormatter<T> {
|
impl<T: Write> JunitFormatter<T> {
|
||||||
@ -26,6 +26,18 @@ impl<T: Write> JunitFormatter<T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn str_to_cdata(s: &str) -> String {
|
||||||
|
// Drop the stdout in a cdata. Unfortunately, you can't put either of `]]>` or
|
||||||
|
// `<?'` in a CDATA block, so the escaping gets a little weird.
|
||||||
|
let escaped_output = s.replace("]]>", "]]]]><![CDATA[>");
|
||||||
|
let escaped_output = escaped_output.replace("<?", "<]]><![CDATA[?");
|
||||||
|
// We also smuggle newlines as 
 so as to keep all the output on one line
|
||||||
|
let escaped_output = escaped_output.replace("\n", "]]>
<![CDATA[");
|
||||||
|
// Prune empty CDATA blocks resulting from any escaping
|
||||||
|
let escaped_output = escaped_output.replace("<![CDATA[]]>", "");
|
||||||
|
format!("<![CDATA[{}]]>", escaped_output)
|
||||||
|
}
|
||||||
|
|
||||||
impl<T: Write> OutputFormatter for JunitFormatter<T> {
|
impl<T: Write> OutputFormatter for JunitFormatter<T> {
|
||||||
fn write_discovery_start(&mut self) -> io::Result<()> {
|
fn write_discovery_start(&mut self) -> io::Result<()> {
|
||||||
Err(io::Error::new(io::ErrorKind::NotFound, "Not yet implemented!"))
|
Err(io::Error::new(io::ErrorKind::NotFound, "Not yet implemented!"))
|
||||||
@ -63,14 +75,14 @@ impl<T: Write> OutputFormatter for JunitFormatter<T> {
|
|||||||
desc: &TestDesc,
|
desc: &TestDesc,
|
||||||
result: &TestResult,
|
result: &TestResult,
|
||||||
exec_time: Option<&time::TestExecTime>,
|
exec_time: Option<&time::TestExecTime>,
|
||||||
_stdout: &[u8],
|
stdout: &[u8],
|
||||||
_state: &ConsoleTestState,
|
_state: &ConsoleTestState,
|
||||||
) -> io::Result<()> {
|
) -> io::Result<()> {
|
||||||
// Because the testsuite node holds some of the information as attributes, we can't write it
|
// Because the testsuite node holds some of the information as attributes, we can't write it
|
||||||
// until all of the tests have finished. Instead of writing every result as they come in, we add
|
// until all of the tests have finished. Instead of writing every result as they come in, we add
|
||||||
// them to a Vec and write them all at once when run is complete.
|
// them to a Vec and write them all at once when run is complete.
|
||||||
let duration = exec_time.map(|t| t.0).unwrap_or_default();
|
let duration = exec_time.map(|t| t.0).unwrap_or_default();
|
||||||
self.results.push((desc.clone(), result.clone(), duration));
|
self.results.push((desc.clone(), result.clone(), duration, stdout.to_vec()));
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
fn write_run_finish(&mut self, state: &ConsoleTestState) -> io::Result<bool> {
|
fn write_run_finish(&mut self, state: &ConsoleTestState) -> io::Result<bool> {
|
||||||
@ -85,7 +97,7 @@ impl<T: Write> OutputFormatter for JunitFormatter<T> {
|
|||||||
>",
|
>",
|
||||||
state.failed, state.total, state.ignored
|
state.failed, state.total, state.ignored
|
||||||
))?;
|
))?;
|
||||||
for (desc, result, duration) in std::mem::take(&mut self.results) {
|
for (desc, result, duration, stdout) in std::mem::take(&mut self.results) {
|
||||||
let (class_name, test_name) = parse_class_name(&desc);
|
let (class_name, test_name) = parse_class_name(&desc);
|
||||||
match result {
|
match result {
|
||||||
TestResult::TrIgnored => { /* no-op */ }
|
TestResult::TrIgnored => { /* no-op */ }
|
||||||
@ -98,6 +110,11 @@ impl<T: Write> OutputFormatter for JunitFormatter<T> {
|
|||||||
duration.as_secs_f64()
|
duration.as_secs_f64()
|
||||||
))?;
|
))?;
|
||||||
self.write_message("<failure type=\"assert\"/>")?;
|
self.write_message("<failure type=\"assert\"/>")?;
|
||||||
|
if !stdout.is_empty() {
|
||||||
|
self.write_message("<system-out>")?;
|
||||||
|
self.write_message(&str_to_cdata(&String::from_utf8_lossy(&stdout)))?;
|
||||||
|
self.write_message("</system-out>")?;
|
||||||
|
}
|
||||||
self.write_message("</testcase>")?;
|
self.write_message("</testcase>")?;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -110,6 +127,11 @@ impl<T: Write> OutputFormatter for JunitFormatter<T> {
|
|||||||
duration.as_secs_f64()
|
duration.as_secs_f64()
|
||||||
))?;
|
))?;
|
||||||
self.write_message(&format!("<failure message=\"{m}\" type=\"assert\"/>"))?;
|
self.write_message(&format!("<failure message=\"{m}\" type=\"assert\"/>"))?;
|
||||||
|
if !stdout.is_empty() {
|
||||||
|
self.write_message("<system-out>")?;
|
||||||
|
self.write_message(&str_to_cdata(&String::from_utf8_lossy(&stdout)))?;
|
||||||
|
self.write_message("</system-out>")?;
|
||||||
|
}
|
||||||
self.write_message("</testcase>")?;
|
self.write_message("</testcase>")?;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -136,11 +158,19 @@ impl<T: Write> OutputFormatter for JunitFormatter<T> {
|
|||||||
TestResult::TrOk => {
|
TestResult::TrOk => {
|
||||||
self.write_message(&format!(
|
self.write_message(&format!(
|
||||||
"<testcase classname=\"{}\" \
|
"<testcase classname=\"{}\" \
|
||||||
name=\"{}\" time=\"{}\"/>",
|
name=\"{}\" time=\"{}\"",
|
||||||
class_name,
|
class_name,
|
||||||
test_name,
|
test_name,
|
||||||
duration.as_secs_f64()
|
duration.as_secs_f64()
|
||||||
))?;
|
))?;
|
||||||
|
if stdout.is_empty() || !state.options.display_output {
|
||||||
|
self.write_message("/>")?;
|
||||||
|
} else {
|
||||||
|
self.write_message("><system-out>")?;
|
||||||
|
self.write_message(&str_to_cdata(&String::from_utf8_lossy(&stdout)))?;
|
||||||
|
self.write_message("</system-out>")?;
|
||||||
|
self.write_message("</testcase>")?;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -79,7 +79,7 @@ impl Step for Std {
|
|||||||
const DEFAULT: bool = true;
|
const DEFAULT: bool = true;
|
||||||
|
|
||||||
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
|
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
|
||||||
run.all_krates("test").path("library")
|
run.all_krates("sysroot").path("library")
|
||||||
}
|
}
|
||||||
|
|
||||||
fn make_run(run: RunConfig<'_>) {
|
fn make_run(run: RunConfig<'_>) {
|
||||||
|
@ -81,7 +81,7 @@ macro_rules! clean_crate_tree {
|
|||||||
|
|
||||||
clean_crate_tree! {
|
clean_crate_tree! {
|
||||||
Rustc, Mode::Rustc, "rustc-main";
|
Rustc, Mode::Rustc, "rustc-main";
|
||||||
Std, Mode::Std, "test";
|
Std, Mode::Std, "sysroot";
|
||||||
}
|
}
|
||||||
|
|
||||||
fn clean_default(build: &Build, all: bool) {
|
fn clean_default(build: &Build, all: bool) {
|
||||||
|
@ -56,7 +56,7 @@ impl Step for Std {
|
|||||||
// When downloading stage1, the standard library has already been copied to the sysroot, so
|
// When downloading stage1, the standard library has already been copied to the sysroot, so
|
||||||
// there's no need to rebuild it.
|
// there's no need to rebuild it.
|
||||||
let builder = run.builder;
|
let builder = run.builder;
|
||||||
run.crate_or_deps("test")
|
run.crate_or_deps("sysroot")
|
||||||
.path("library")
|
.path("library")
|
||||||
.lazy_default_condition(Box::new(|| !builder.download_rustc()))
|
.lazy_default_condition(Box::new(|| !builder.download_rustc()))
|
||||||
}
|
}
|
||||||
@ -364,7 +364,7 @@ pub fn std_cargo(builder: &Builder<'_>, target: TargetSelection, stage: u32, car
|
|||||||
.arg("--features")
|
.arg("--features")
|
||||||
.arg(features)
|
.arg(features)
|
||||||
.arg("--manifest-path")
|
.arg("--manifest-path")
|
||||||
.arg(builder.src.join("library/test/Cargo.toml"));
|
.arg(builder.src.join("library/sysroot/Cargo.toml"));
|
||||||
|
|
||||||
// Help the libc crate compile by assisting it in finding various
|
// Help the libc crate compile by assisting it in finding various
|
||||||
// sysroot native libraries.
|
// sysroot native libraries.
|
||||||
|
@ -976,6 +976,7 @@ impl Step for PlainSourceTarball {
|
|||||||
"config.example.toml",
|
"config.example.toml",
|
||||||
"Cargo.toml",
|
"Cargo.toml",
|
||||||
"Cargo.lock",
|
"Cargo.lock",
|
||||||
|
".gitmodules",
|
||||||
];
|
];
|
||||||
let src_dirs = ["src", "compiler", "library", "tests"];
|
let src_dirs = ["src", "compiler", "library", "tests"];
|
||||||
|
|
||||||
|
@ -438,7 +438,7 @@ impl Step for Std {
|
|||||||
|
|
||||||
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
|
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
|
||||||
let builder = run.builder;
|
let builder = run.builder;
|
||||||
run.all_krates("test").path("library").default_condition(builder.config.docs)
|
run.all_krates("sysroot").path("library").default_condition(builder.config.docs)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn make_run(run: RunConfig<'_>) {
|
fn make_run(run: RunConfig<'_>) {
|
||||||
|
@ -2145,7 +2145,7 @@ impl Step for Crate {
|
|||||||
const DEFAULT: bool = true;
|
const DEFAULT: bool = true;
|
||||||
|
|
||||||
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
|
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
|
||||||
run.crate_or_deps("test")
|
run.crate_or_deps("sysroot")
|
||||||
}
|
}
|
||||||
|
|
||||||
fn make_run(run: RunConfig<'_>) {
|
fn make_run(run: RunConfig<'_>) {
|
||||||
|
37
tests/codegen/ascii-char.rs
Normal file
37
tests/codegen/ascii-char.rs
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
// compile-flags: -C opt-level=1
|
||||||
|
// ignore-debug (the extra assertions get in the way)
|
||||||
|
|
||||||
|
#![crate_type = "lib"]
|
||||||
|
#![feature(ascii_char)]
|
||||||
|
|
||||||
|
use std::ascii::Char as AsciiChar;
|
||||||
|
|
||||||
|
// CHECK-LABEL: i8 @unwrap_digit_from_remainder(i32
|
||||||
|
#[no_mangle]
|
||||||
|
pub fn unwrap_digit_from_remainder(v: u32) -> AsciiChar {
|
||||||
|
// CHECK-NOT: icmp
|
||||||
|
// CHECK-NOT: panic
|
||||||
|
|
||||||
|
// CHECK: %[[R:.+]] = urem i32 %v, 10
|
||||||
|
// CHECK-NEXT: %[[T:.+]] = trunc i32 %[[R]] to i8
|
||||||
|
// CHECK-NEXT: %[[D:.+]] = or i8 %[[T]], 48
|
||||||
|
// CHECK-NEXT: ret i8 %[[D]]
|
||||||
|
|
||||||
|
// CHECK-NOT: icmp
|
||||||
|
// CHECK-NOT: panic
|
||||||
|
AsciiChar::digit((v % 10) as u8).unwrap()
|
||||||
|
}
|
||||||
|
|
||||||
|
// CHECK-LABEL: i8 @unwrap_from_masked(i8
|
||||||
|
#[no_mangle]
|
||||||
|
pub fn unwrap_from_masked(b: u8) -> AsciiChar {
|
||||||
|
// CHECK-NOT: icmp
|
||||||
|
// CHECK-NOT: panic
|
||||||
|
|
||||||
|
// CHECK: %[[M:.+]] = and i8 %b, 127
|
||||||
|
// CHECK-NEXT: ret i8 %[[M]]
|
||||||
|
|
||||||
|
// CHECK-NOT: icmp
|
||||||
|
// CHECK-NOT: panic
|
||||||
|
AsciiChar::from_u8(b & 0x7f).unwrap()
|
||||||
|
}
|
@ -0,0 +1,25 @@
|
|||||||
|
- // MIR for `main` before DeadStoreElimination
|
||||||
|
+ // MIR for `main` after DeadStoreElimination
|
||||||
|
|
||||||
|
fn main() -> () {
|
||||||
|
let mut _0: (); // return place in scope 0 at $DIR/place_mention.rs:+0:11: +0:11
|
||||||
|
let mut _1: (&str, &str); // in scope 0 at $DIR/place_mention.rs:+3:18: +3:36
|
||||||
|
scope 1 {
|
||||||
|
}
|
||||||
|
|
||||||
|
bb0: {
|
||||||
|
StorageLive(_1); // scope 0 at $DIR/place_mention.rs:+3:18: +3:36
|
||||||
|
_1 = (const "Hello", const "World"); // scope 0 at $DIR/place_mention.rs:+3:18: +3:36
|
||||||
|
// mir::Constant
|
||||||
|
// + span: $DIR/place_mention.rs:8:19: 8:26
|
||||||
|
// + literal: Const { ty: &str, val: Value(Slice(..)) }
|
||||||
|
// mir::Constant
|
||||||
|
// + span: $DIR/place_mention.rs:8:28: 8:35
|
||||||
|
// + literal: Const { ty: &str, val: Value(Slice(..)) }
|
||||||
|
PlaceMention(_1); // scope 0 at $DIR/place_mention.rs:+3:18: +3:36
|
||||||
|
StorageDead(_1); // scope 0 at $DIR/place_mention.rs:+3:36: +3:37
|
||||||
|
_0 = const (); // scope 0 at $DIR/place_mention.rs:+0:11: +4:2
|
||||||
|
return; // scope 0 at $DIR/place_mention.rs:+4:2: +4:2
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
9
tests/mir-opt/dead-store-elimination/place_mention.rs
Normal file
9
tests/mir-opt/dead-store-elimination/place_mention.rs
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
// unit-test: DeadStoreElimination
|
||||||
|
// compile-flags: -Zmir-keep-place-mention
|
||||||
|
|
||||||
|
// EMIT_MIR place_mention.main.DeadStoreElimination.diff
|
||||||
|
fn main() {
|
||||||
|
// Verify that we account for the `PlaceMention` statement as a use of the tuple,
|
||||||
|
// and don't remove it as a dead store.
|
||||||
|
let (_, _) = ("Hello", "World");
|
||||||
|
}
|
19
tests/run-make/libtest-junit/Makefile
Normal file
19
tests/run-make/libtest-junit/Makefile
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
# ignore-cross-compile
|
||||||
|
include ../tools.mk
|
||||||
|
|
||||||
|
# Test expected libtest's junit output
|
||||||
|
|
||||||
|
OUTPUT_FILE_DEFAULT := $(TMPDIR)/libtest-junit-output-default.xml
|
||||||
|
OUTPUT_FILE_STDOUT_SUCCESS := $(TMPDIR)/libtest-junit-output-stdout-success.xml
|
||||||
|
|
||||||
|
all: f.rs validate_junit.py output-default.xml output-stdout-success.xml
|
||||||
|
$(RUSTC) --test f.rs
|
||||||
|
RUST_BACKTRACE=0 $(call RUN,f) -Z unstable-options --test-threads=1 --format=junit > $(OUTPUT_FILE_DEFAULT) || true
|
||||||
|
RUST_BACKTRACE=0 $(call RUN,f) -Z unstable-options --test-threads=1 --format=junit --show-output > $(OUTPUT_FILE_STDOUT_SUCCESS) || true
|
||||||
|
|
||||||
|
cat $(OUTPUT_FILE_DEFAULT) | "$(PYTHON)" validate_junit.py
|
||||||
|
cat $(OUTPUT_FILE_STDOUT_SUCCESS) | "$(PYTHON)" validate_junit.py
|
||||||
|
|
||||||
|
# Normalize the actual output and compare to expected output file
|
||||||
|
cat $(OUTPUT_FILE_DEFAULT) | sed 's/time="[0-9.]*"/time="$$TIME"/g' | diff output-default.xml -
|
||||||
|
cat $(OUTPUT_FILE_STDOUT_SUCCESS) | sed 's/time="[0-9.]*"/time="$$TIME"/g' | diff output-stdout-success.xml -
|
23
tests/run-make/libtest-junit/f.rs
Normal file
23
tests/run-make/libtest-junit/f.rs
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
#[test]
|
||||||
|
fn a() {
|
||||||
|
println!("print from successful test");
|
||||||
|
// Should pass
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn b() {
|
||||||
|
println!("print from failing test");
|
||||||
|
assert!(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[should_panic]
|
||||||
|
fn c() {
|
||||||
|
assert!(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[ignore = "msg"]
|
||||||
|
fn d() {
|
||||||
|
assert!(false);
|
||||||
|
}
|
1
tests/run-make/libtest-junit/output-default.xml
Normal file
1
tests/run-make/libtest-junit/output-default.xml
Normal file
@ -0,0 +1 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?><testsuites><testsuite name="test" package="test" id="0" errors="0" failures="1" tests="4" skipped="1" ><testcase classname="unknown" name="a" time="$TIME"/><testcase classname="unknown" name="b" time="$TIME"><failure type="assert"/><system-out><![CDATA[print from failing test]]>
<![CDATA[thread 'b' panicked at 'assertion failed: false', f.rs:10:5]]>
<![CDATA[note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace]]>
<![CDATA[]]></system-out></testcase><testcase classname="unknown" name="c" time="$TIME"/><system-out/><system-err/></testsuite></testsuites>
|
1
tests/run-make/libtest-junit/output-stdout-success.xml
Normal file
1
tests/run-make/libtest-junit/output-stdout-success.xml
Normal file
@ -0,0 +1 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?><testsuites><testsuite name="test" package="test" id="0" errors="0" failures="1" tests="4" skipped="1" ><testcase classname="unknown" name="a" time="$TIME"><system-out><![CDATA[print from successful test]]>
<![CDATA[]]></system-out></testcase><testcase classname="unknown" name="b" time="$TIME"><failure type="assert"/><system-out><![CDATA[print from failing test]]>
<![CDATA[thread 'b' panicked at 'assertion failed: false', f.rs:10:5]]>
<![CDATA[note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace]]>
<![CDATA[]]></system-out></testcase><testcase classname="unknown" name="c" time="$TIME"><system-out><![CDATA[thread 'c' panicked at 'assertion failed: false', f.rs:16:5]]>
<![CDATA[]]></system-out></testcase><system-out/><system-err/></testsuite></testsuites>
|
12
tests/run-make/libtest-junit/validate_junit.py
Executable file
12
tests/run-make/libtest-junit/validate_junit.py
Executable file
@ -0,0 +1,12 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
|
||||||
|
import sys
|
||||||
|
import xml.etree.ElementTree as ET
|
||||||
|
|
||||||
|
# Try to decode line in order to ensure it is a valid XML document
|
||||||
|
for line in sys.stdin:
|
||||||
|
try:
|
||||||
|
ET.fromstring(line)
|
||||||
|
except ET.ParseError as pe:
|
||||||
|
print("Invalid xml: %r" % line)
|
||||||
|
raise
|
@ -10,6 +10,7 @@ impl<const N: usize> Trait<N> for () {
|
|||||||
pub const fn foo<const N: usize>() where (): Trait<N> {
|
pub const fn foo<const N: usize>() where (): Trait<N> {
|
||||||
let bar = [(); <()>::Assoc];
|
let bar = [(); <()>::Assoc];
|
||||||
//~^ error: constant expression depends on a generic parameter
|
//~^ error: constant expression depends on a generic parameter
|
||||||
|
//~| error: constant expression depends on a generic parameter
|
||||||
}
|
}
|
||||||
|
|
||||||
trait Trait2<const N: usize> {
|
trait Trait2<const N: usize> {
|
||||||
@ -24,6 +25,7 @@ impl<const N: usize> Trait2<N> for () {
|
|||||||
pub const fn foo2<const N: usize>() where (): Trait2<N> {
|
pub const fn foo2<const N: usize>() where (): Trait2<N> {
|
||||||
let bar2 = [(); <()>::Assoc2];
|
let bar2 = [(); <()>::Assoc2];
|
||||||
//~^ error: constant expression depends on a generic parameter
|
//~^ error: constant expression depends on a generic parameter
|
||||||
|
//~| error: constant expression depends on a generic parameter
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
|
@ -7,12 +7,28 @@ LL | let bar = [(); <()>::Assoc];
|
|||||||
= note: this may fail depending on what value the parameter takes
|
= note: this may fail depending on what value the parameter takes
|
||||||
|
|
||||||
error: constant expression depends on a generic parameter
|
error: constant expression depends on a generic parameter
|
||||||
--> $DIR/sneaky-array-repeat-expr.rs:25:21
|
--> $DIR/sneaky-array-repeat-expr.rs:11:15
|
||||||
|
|
|
||||||
|
LL | let bar = [(); <()>::Assoc];
|
||||||
|
| ^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
||||||
|
= note: this may fail depending on what value the parameter takes
|
||||||
|
|
||||||
|
error: constant expression depends on a generic parameter
|
||||||
|
--> $DIR/sneaky-array-repeat-expr.rs:26:21
|
||||||
|
|
|
|
||||||
LL | let bar2 = [(); <()>::Assoc2];
|
LL | let bar2 = [(); <()>::Assoc2];
|
||||||
| ^^^^^^^^^^^^
|
| ^^^^^^^^^^^^
|
||||||
|
|
|
|
||||||
= note: this may fail depending on what value the parameter takes
|
= note: this may fail depending on what value the parameter takes
|
||||||
|
|
||||||
error: aborting due to 2 previous errors
|
error: constant expression depends on a generic parameter
|
||||||
|
--> $DIR/sneaky-array-repeat-expr.rs:26:16
|
||||||
|
|
|
||||||
|
LL | let bar2 = [(); <()>::Assoc2];
|
||||||
|
| ^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
||||||
|
= note: this may fail depending on what value the parameter takes
|
||||||
|
|
||||||
|
error: aborting due to 4 previous errors
|
||||||
|
|
||||||
|
@ -22,7 +22,9 @@ impl<T: Sized> PinDropInternal for Bears<T> {
|
|||||||
where
|
where
|
||||||
Self: ReflectDrop,
|
Self: ReflectDrop,
|
||||||
{
|
{
|
||||||
let _ = [(); 0 - !!(<Bears<T> as ReflectDrop>::REFLECT_DROP) as usize]; //~ ERROR constant expression depends on a generic parameter
|
let _ = [(); 0 - !!(<Bears<T> as ReflectDrop>::REFLECT_DROP) as usize];
|
||||||
|
//~^ ERROR constant expression depends on a generic parameter
|
||||||
|
//~| ERROR constant expression depends on a generic parameter
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6,5 +6,13 @@ LL | let _ = [(); 0 - !!(<Bears<T> as ReflectDrop>::REFLECT_DROP) as usi
|
|||||||
|
|
|
|
||||||
= note: this may fail depending on what value the parameter takes
|
= note: this may fail depending on what value the parameter takes
|
||||||
|
|
||||||
error: aborting due to previous error
|
error: constant expression depends on a generic parameter
|
||||||
|
--> $DIR/issue-50439.rs:25:17
|
||||||
|
|
|
||||||
|
LL | let _ = [(); 0 - !!(<Bears<T> as ReflectDrop>::REFLECT_DROP) as usize];
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
||||||
|
= note: this may fail depending on what value the parameter takes
|
||||||
|
|
||||||
|
error: aborting due to 2 previous errors
|
||||||
|
|
||||||
|
13
tests/ui/self/elision/nested-item.rs
Normal file
13
tests/ui/self/elision/nested-item.rs
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
// Regression test for #110899.
|
||||||
|
// When looking for the elided lifetime for `wrap`,
|
||||||
|
// we must not consider the lifetimes in `bar` as candidates.
|
||||||
|
|
||||||
|
fn wrap(self: Wrap<{ fn bar(&self) {} }>) -> &() {
|
||||||
|
//~^ ERROR `self` parameter is only allowed in associated functions
|
||||||
|
//~| ERROR `self` parameter is only allowed in associated functions
|
||||||
|
//~| ERROR missing lifetime specifier
|
||||||
|
//~| ERROR cannot find type `Wrap` in this scope
|
||||||
|
&()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {}
|
38
tests/ui/self/elision/nested-item.stderr
Normal file
38
tests/ui/self/elision/nested-item.stderr
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
error: `self` parameter is only allowed in associated functions
|
||||||
|
--> $DIR/nested-item.rs:5:9
|
||||||
|
|
|
||||||
|
LL | fn wrap(self: Wrap<{ fn bar(&self) {} }>) -> &() {
|
||||||
|
| ^^^^ not semantically valid as function parameter
|
||||||
|
|
|
||||||
|
= note: associated functions are those in `impl` or `trait` definitions
|
||||||
|
|
||||||
|
error: `self` parameter is only allowed in associated functions
|
||||||
|
--> $DIR/nested-item.rs:5:29
|
||||||
|
|
|
||||||
|
LL | fn wrap(self: Wrap<{ fn bar(&self) {} }>) -> &() {
|
||||||
|
| ^^^^^ not semantically valid as function parameter
|
||||||
|
|
|
||||||
|
= note: associated functions are those in `impl` or `trait` definitions
|
||||||
|
|
||||||
|
error[E0106]: missing lifetime specifier
|
||||||
|
--> $DIR/nested-item.rs:5:46
|
||||||
|
|
|
||||||
|
LL | fn wrap(self: Wrap<{ fn bar(&self) {} }>) -> &() {
|
||||||
|
| ^ expected named lifetime parameter
|
||||||
|
|
|
||||||
|
= help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from
|
||||||
|
help: consider using the `'static` lifetime
|
||||||
|
|
|
||||||
|
LL | fn wrap(self: Wrap<{ fn bar(&self) {} }>) -> &'static () {
|
||||||
|
| +++++++
|
||||||
|
|
||||||
|
error[E0412]: cannot find type `Wrap` in this scope
|
||||||
|
--> $DIR/nested-item.rs:5:15
|
||||||
|
|
|
||||||
|
LL | fn wrap(self: Wrap<{ fn bar(&self) {} }>) -> &() {
|
||||||
|
| ^^^^ not found in this scope
|
||||||
|
|
||||||
|
error: aborting due to 4 previous errors
|
||||||
|
|
||||||
|
Some errors have detailed explanations: E0106, E0412.
|
||||||
|
For more information about an error, try `rustc --explain E0106`.
|
10
tests/ui/typeck/repeat-expr-checks-wf.rs
Normal file
10
tests/ui/typeck/repeat-expr-checks-wf.rs
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
trait Foo {
|
||||||
|
const ASSOC: [u8];
|
||||||
|
}
|
||||||
|
|
||||||
|
fn bar<T: Foo>() {
|
||||||
|
let a = [T::ASSOC; 2];
|
||||||
|
//~^ ERROR: the size for values of type `[u8]` cannot be known at compilation time
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {}
|
12
tests/ui/typeck/repeat-expr-checks-wf.stderr
Normal file
12
tests/ui/typeck/repeat-expr-checks-wf.stderr
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
|
||||||
|
--> $DIR/repeat-expr-checks-wf.rs:6:13
|
||||||
|
|
|
||||||
|
LL | let a = [T::ASSOC; 2];
|
||||||
|
| ^^^^^^^^^^^^^ doesn't have a size known at compile-time
|
||||||
|
|
|
||||||
|
= help: the trait `Sized` is not implemented for `[u8]`
|
||||||
|
= note: slice and array elements must have `Sized` type
|
||||||
|
|
||||||
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0277`.
|
Loading…
Reference in New Issue
Block a user