Auto merge of #104192 - Dylan-DPC:rollup-jjo1o80, r=Dylan-DPC
Rollup of 7 pull requests Successful merges: - #103570 (Stabilize integer logarithms) - #103694 (Add documentation examples for `pointer::mask`) - #103919 (Unescaping cleanups) - #103933 (Promote {aarch64,i686,x86_64}-unknown-uefi to Tier 2) - #103952 (Don't intra linkcheck reference) - #104111 (rustdoc: Add mutable to the description) - #104125 (Const Compare for Tuples) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
c71658706f
36 changed files with 340 additions and 366 deletions
|
@ -2,12 +2,9 @@
|
||||||
|
|
||||||
use crate::ast::{self, Lit, LitKind};
|
use crate::ast::{self, Lit, LitKind};
|
||||||
use crate::token::{self, Token};
|
use crate::token::{self, Token};
|
||||||
|
use rustc_lexer::unescape::{byte_from_char, unescape_byte, unescape_char, unescape_literal, Mode};
|
||||||
use rustc_lexer::unescape::{unescape_byte, unescape_char};
|
|
||||||
use rustc_lexer::unescape::{unescape_byte_literal, unescape_literal, Mode};
|
|
||||||
use rustc_span::symbol::{kw, sym, Symbol};
|
use rustc_span::symbol::{kw, sym, Symbol};
|
||||||
use rustc_span::Span;
|
use rustc_span::Span;
|
||||||
|
|
||||||
use std::ascii;
|
use std::ascii;
|
||||||
|
|
||||||
pub enum LitError {
|
pub enum LitError {
|
||||||
|
@ -109,13 +106,11 @@ impl LitKind {
|
||||||
let s = symbol.as_str();
|
let s = symbol.as_str();
|
||||||
let mut buf = Vec::with_capacity(s.len());
|
let mut buf = Vec::with_capacity(s.len());
|
||||||
let mut error = Ok(());
|
let mut error = Ok(());
|
||||||
unescape_byte_literal(&s, Mode::ByteStr, &mut |_, unescaped_byte| {
|
unescape_literal(&s, Mode::ByteStr, &mut |_, c| match c {
|
||||||
match unescaped_byte {
|
Ok(c) => buf.push(byte_from_char(c)),
|
||||||
Ok(c) => buf.push(c),
|
Err(err) => {
|
||||||
Err(err) => {
|
if err.is_fatal() {
|
||||||
if err.is_fatal() {
|
error = Err(LitError::LexerError);
|
||||||
error = Err(LitError::LexerError);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -127,13 +122,11 @@ impl LitKind {
|
||||||
let bytes = if s.contains('\r') {
|
let bytes = if s.contains('\r') {
|
||||||
let mut buf = Vec::with_capacity(s.len());
|
let mut buf = Vec::with_capacity(s.len());
|
||||||
let mut error = Ok(());
|
let mut error = Ok(());
|
||||||
unescape_byte_literal(&s, Mode::RawByteStr, &mut |_, unescaped_byte| {
|
unescape_literal(&s, Mode::RawByteStr, &mut |_, c| match c {
|
||||||
match unescaped_byte {
|
Ok(c) => buf.push(byte_from_char(c)),
|
||||||
Ok(c) => buf.push(c),
|
Err(err) => {
|
||||||
Err(err) => {
|
if err.is_fatal() {
|
||||||
if err.is_fatal() {
|
error = Err(LitError::LexerError);
|
||||||
error = Err(LitError::LexerError);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -205,13 +205,13 @@ pub enum RawStrError {
|
||||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)]
|
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)]
|
||||||
pub enum Base {
|
pub enum Base {
|
||||||
/// Literal starts with "0b".
|
/// Literal starts with "0b".
|
||||||
Binary,
|
Binary = 2,
|
||||||
/// Literal starts with "0o".
|
/// Literal starts with "0o".
|
||||||
Octal,
|
Octal = 8,
|
||||||
/// Literal starts with "0x".
|
|
||||||
Hexadecimal,
|
|
||||||
/// Literal doesn't contain a prefix.
|
/// Literal doesn't contain a prefix.
|
||||||
Decimal,
|
Decimal = 10,
|
||||||
|
/// Literal starts with "0x".
|
||||||
|
Hexadecimal = 16,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// `rustc` allows files to have a shebang, e.g. "#!/usr/bin/rustrun",
|
/// `rustc` allows files to have a shebang, e.g. "#!/usr/bin/rustrun",
|
||||||
|
|
|
@ -52,10 +52,8 @@ pub enum EscapeError {
|
||||||
|
|
||||||
/// Unicode escape code in byte literal.
|
/// Unicode escape code in byte literal.
|
||||||
UnicodeEscapeInByte,
|
UnicodeEscapeInByte,
|
||||||
/// Non-ascii character in byte literal.
|
/// Non-ascii character in byte literal, byte string literal, or raw byte string literal.
|
||||||
NonAsciiCharInByte,
|
NonAsciiCharInByte,
|
||||||
/// Non-ascii character in byte string literal.
|
|
||||||
NonAsciiCharInByteString,
|
|
||||||
|
|
||||||
/// After a line ending with '\', the next line contains whitespace
|
/// After a line ending with '\', the next line contains whitespace
|
||||||
/// characters that are not skipped.
|
/// characters that are not skipped.
|
||||||
|
@ -78,54 +76,33 @@ impl EscapeError {
|
||||||
/// Takes a contents of a literal (without quotes) and produces a
|
/// Takes a contents of a literal (without quotes) and produces a
|
||||||
/// sequence of escaped characters or errors.
|
/// sequence of escaped characters or errors.
|
||||||
/// Values are returned through invoking of the provided callback.
|
/// Values are returned through invoking of the provided callback.
|
||||||
pub fn unescape_literal<F>(literal_text: &str, mode: Mode, callback: &mut F)
|
pub fn unescape_literal<F>(src: &str, mode: Mode, callback: &mut F)
|
||||||
where
|
where
|
||||||
F: FnMut(Range<usize>, Result<char, EscapeError>),
|
F: FnMut(Range<usize>, Result<char, EscapeError>),
|
||||||
{
|
{
|
||||||
match mode {
|
match mode {
|
||||||
Mode::Char | Mode::Byte => {
|
Mode::Char | Mode::Byte => {
|
||||||
let mut chars = literal_text.chars();
|
let mut chars = src.chars();
|
||||||
let result = unescape_char_or_byte(&mut chars, mode);
|
let res = unescape_char_or_byte(&mut chars, mode == Mode::Byte);
|
||||||
// The Chars iterator moved forward.
|
callback(0..(src.len() - chars.as_str().len()), res);
|
||||||
callback(0..(literal_text.len() - chars.as_str().len()), result);
|
|
||||||
}
|
}
|
||||||
Mode::Str | Mode::ByteStr => unescape_str_or_byte_str(literal_text, mode, callback),
|
Mode::Str | Mode::ByteStr => unescape_str_or_byte_str(src, mode == Mode::ByteStr, callback),
|
||||||
// NOTE: Raw strings do not perform any explicit character escaping, here we
|
|
||||||
// only translate CRLF to LF and produce errors on bare CR.
|
|
||||||
Mode::RawStr | Mode::RawByteStr => {
|
Mode::RawStr | Mode::RawByteStr => {
|
||||||
unescape_raw_str_or_raw_byte_str(literal_text, mode, callback)
|
unescape_raw_str_or_raw_byte_str(src, mode == Mode::RawByteStr, callback)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Takes a contents of a byte, byte string or raw byte string (without quotes)
|
|
||||||
/// and produces a sequence of bytes or errors.
|
|
||||||
/// Values are returned through invoking of the provided callback.
|
|
||||||
pub fn unescape_byte_literal<F>(literal_text: &str, mode: Mode, callback: &mut F)
|
|
||||||
where
|
|
||||||
F: FnMut(Range<usize>, Result<u8, EscapeError>),
|
|
||||||
{
|
|
||||||
debug_assert!(mode.is_bytes());
|
|
||||||
unescape_literal(literal_text, mode, &mut |range, result| {
|
|
||||||
callback(range, result.map(byte_from_char));
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Takes a contents of a char literal (without quotes), and returns an
|
/// Takes a contents of a char literal (without quotes), and returns an
|
||||||
/// unescaped char or an error
|
/// unescaped char or an error.
|
||||||
pub fn unescape_char(literal_text: &str) -> Result<char, (usize, EscapeError)> {
|
pub fn unescape_char(src: &str) -> Result<char, EscapeError> {
|
||||||
let mut chars = literal_text.chars();
|
unescape_char_or_byte(&mut src.chars(), false)
|
||||||
unescape_char_or_byte(&mut chars, Mode::Char)
|
|
||||||
.map_err(|err| (literal_text.len() - chars.as_str().len(), err))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Takes a contents of a byte literal (without quotes), and returns an
|
/// Takes a contents of a byte literal (without quotes), and returns an
|
||||||
/// unescaped byte or an error.
|
/// unescaped byte or an error.
|
||||||
pub fn unescape_byte(literal_text: &str) -> Result<u8, (usize, EscapeError)> {
|
pub fn unescape_byte(src: &str) -> Result<u8, EscapeError> {
|
||||||
let mut chars = literal_text.chars();
|
unescape_char_or_byte(&mut src.chars(), true).map(byte_from_char)
|
||||||
unescape_char_or_byte(&mut chars, Mode::Byte)
|
|
||||||
.map(byte_from_char)
|
|
||||||
.map_err(|err| (literal_text.len() - chars.as_str().len(), err))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// What kind of literal do we parse.
|
/// What kind of literal do we parse.
|
||||||
|
@ -147,7 +124,7 @@ impl Mode {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_bytes(self) -> bool {
|
pub fn is_byte(self) -> bool {
|
||||||
match self {
|
match self {
|
||||||
Mode::Byte | Mode::ByteStr | Mode::RawByteStr => true,
|
Mode::Byte | Mode::ByteStr | Mode::RawByteStr => true,
|
||||||
Mode::Char | Mode::Str | Mode::RawStr => false,
|
Mode::Char | Mode::Str | Mode::RawStr => false,
|
||||||
|
@ -155,12 +132,9 @@ impl Mode {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn scan_escape(chars: &mut Chars<'_>, mode: Mode) -> Result<char, EscapeError> {
|
fn scan_escape(chars: &mut Chars<'_>, is_byte: bool) -> Result<char, EscapeError> {
|
||||||
// Previous character was '\\', unescape what follows.
|
// Previous character was '\\', unescape what follows.
|
||||||
|
let res = match chars.next().ok_or(EscapeError::LoneSlash)? {
|
||||||
let second_char = chars.next().ok_or(EscapeError::LoneSlash)?;
|
|
||||||
|
|
||||||
let res = match second_char {
|
|
||||||
'"' => '"',
|
'"' => '"',
|
||||||
'n' => '\n',
|
'n' => '\n',
|
||||||
'r' => '\r',
|
'r' => '\r',
|
||||||
|
@ -181,7 +155,7 @@ fn scan_escape(chars: &mut Chars<'_>, mode: Mode) -> Result<char, EscapeError> {
|
||||||
let value = hi * 16 + lo;
|
let value = hi * 16 + lo;
|
||||||
|
|
||||||
// For a non-byte literal verify that it is within ASCII range.
|
// For a non-byte literal verify that it is within ASCII range.
|
||||||
if !mode.is_bytes() && !is_ascii(value) {
|
if !is_byte && !is_ascii(value) {
|
||||||
return Err(EscapeError::OutOfRangeHexEscape);
|
return Err(EscapeError::OutOfRangeHexEscape);
|
||||||
}
|
}
|
||||||
let value = value as u8;
|
let value = value as u8;
|
||||||
|
@ -217,7 +191,7 @@ fn scan_escape(chars: &mut Chars<'_>, mode: Mode) -> Result<char, EscapeError> {
|
||||||
|
|
||||||
// Incorrect syntax has higher priority for error reporting
|
// Incorrect syntax has higher priority for error reporting
|
||||||
// than unallowed value for a literal.
|
// than unallowed value for a literal.
|
||||||
if mode.is_bytes() {
|
if is_byte {
|
||||||
return Err(EscapeError::UnicodeEscapeInByte);
|
return Err(EscapeError::UnicodeEscapeInByte);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -249,23 +223,22 @@ fn scan_escape(chars: &mut Chars<'_>, mode: Mode) -> Result<char, EscapeError> {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn ascii_check(first_char: char, mode: Mode) -> Result<char, EscapeError> {
|
fn ascii_check(c: char, is_byte: bool) -> Result<char, EscapeError> {
|
||||||
if mode.is_bytes() && !first_char.is_ascii() {
|
if is_byte && !c.is_ascii() {
|
||||||
// Byte literal can't be a non-ascii character.
|
// Byte literal can't be a non-ascii character.
|
||||||
Err(EscapeError::NonAsciiCharInByte)
|
Err(EscapeError::NonAsciiCharInByte)
|
||||||
} else {
|
} else {
|
||||||
Ok(first_char)
|
Ok(c)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn unescape_char_or_byte(chars: &mut Chars<'_>, mode: Mode) -> Result<char, EscapeError> {
|
fn unescape_char_or_byte(chars: &mut Chars<'_>, is_byte: bool) -> Result<char, EscapeError> {
|
||||||
debug_assert!(mode == Mode::Char || mode == Mode::Byte);
|
let c = chars.next().ok_or(EscapeError::ZeroChars)?;
|
||||||
let first_char = chars.next().ok_or(EscapeError::ZeroChars)?;
|
let res = match c {
|
||||||
let res = match first_char {
|
'\\' => scan_escape(chars, is_byte),
|
||||||
'\\' => scan_escape(chars, mode),
|
|
||||||
'\n' | '\t' | '\'' => Err(EscapeError::EscapeOnlyChar),
|
'\n' | '\t' | '\'' => Err(EscapeError::EscapeOnlyChar),
|
||||||
'\r' => Err(EscapeError::BareCarriageReturn),
|
'\r' => Err(EscapeError::BareCarriageReturn),
|
||||||
_ => ascii_check(first_char, mode),
|
_ => ascii_check(c, is_byte),
|
||||||
}?;
|
}?;
|
||||||
if chars.next().is_some() {
|
if chars.next().is_some() {
|
||||||
return Err(EscapeError::MoreThanOneChar);
|
return Err(EscapeError::MoreThanOneChar);
|
||||||
|
@ -275,20 +248,20 @@ fn unescape_char_or_byte(chars: &mut Chars<'_>, mode: Mode) -> Result<char, Esca
|
||||||
|
|
||||||
/// Takes a contents of a string literal (without quotes) and produces a
|
/// Takes a contents of a string literal (without quotes) and produces a
|
||||||
/// sequence of escaped characters or errors.
|
/// sequence of escaped characters or errors.
|
||||||
fn unescape_str_or_byte_str<F>(src: &str, mode: Mode, callback: &mut F)
|
fn unescape_str_or_byte_str<F>(src: &str, is_byte: bool, callback: &mut F)
|
||||||
where
|
where
|
||||||
F: FnMut(Range<usize>, Result<char, EscapeError>),
|
F: FnMut(Range<usize>, Result<char, EscapeError>),
|
||||||
{
|
{
|
||||||
debug_assert!(mode == Mode::Str || mode == Mode::ByteStr);
|
|
||||||
let initial_len = src.len();
|
|
||||||
let mut chars = src.chars();
|
let mut chars = src.chars();
|
||||||
while let Some(first_char) = chars.next() {
|
|
||||||
let start = initial_len - chars.as_str().len() - first_char.len_utf8();
|
|
||||||
|
|
||||||
let unescaped_char = match first_char {
|
// The `start` and `end` computation here is complicated because
|
||||||
|
// `skip_ascii_whitespace` makes us to skip over chars without counting
|
||||||
|
// them in the range computation.
|
||||||
|
while let Some(c) = chars.next() {
|
||||||
|
let start = src.len() - chars.as_str().len() - c.len_utf8();
|
||||||
|
let res = match c {
|
||||||
'\\' => {
|
'\\' => {
|
||||||
let second_char = chars.clone().next();
|
match chars.clone().next() {
|
||||||
match second_char {
|
|
||||||
Some('\n') => {
|
Some('\n') => {
|
||||||
// Rust language specification requires us to skip whitespaces
|
// Rust language specification requires us to skip whitespaces
|
||||||
// if unescaped '\' character is followed by '\n'.
|
// if unescaped '\' character is followed by '\n'.
|
||||||
|
@ -297,17 +270,17 @@ where
|
||||||
skip_ascii_whitespace(&mut chars, start, callback);
|
skip_ascii_whitespace(&mut chars, start, callback);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
_ => scan_escape(&mut chars, mode),
|
_ => scan_escape(&mut chars, is_byte),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
'\n' => Ok('\n'),
|
'\n' => Ok('\n'),
|
||||||
'\t' => Ok('\t'),
|
'\t' => Ok('\t'),
|
||||||
'"' => Err(EscapeError::EscapeOnlyChar),
|
'"' => Err(EscapeError::EscapeOnlyChar),
|
||||||
'\r' => Err(EscapeError::BareCarriageReturn),
|
'\r' => Err(EscapeError::BareCarriageReturn),
|
||||||
_ => ascii_check(first_char, mode),
|
_ => ascii_check(c, is_byte),
|
||||||
};
|
};
|
||||||
let end = initial_len - chars.as_str().len();
|
let end = src.len() - chars.as_str().len();
|
||||||
callback(start..end, unescaped_char);
|
callback(start..end, res);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn skip_ascii_whitespace<F>(chars: &mut Chars<'_>, start: usize, callback: &mut F)
|
fn skip_ascii_whitespace<F>(chars: &mut Chars<'_>, start: usize, callback: &mut F)
|
||||||
|
@ -340,30 +313,29 @@ where
|
||||||
/// Takes a contents of a string literal (without quotes) and produces a
|
/// Takes a contents of a string literal (without quotes) and produces a
|
||||||
/// sequence of characters or errors.
|
/// sequence of characters or errors.
|
||||||
/// NOTE: Raw strings do not perform any explicit character escaping, here we
|
/// NOTE: Raw strings do not perform any explicit character escaping, here we
|
||||||
/// only translate CRLF to LF and produce errors on bare CR.
|
/// only produce errors on bare CR.
|
||||||
fn unescape_raw_str_or_raw_byte_str<F>(literal_text: &str, mode: Mode, callback: &mut F)
|
fn unescape_raw_str_or_raw_byte_str<F>(src: &str, is_byte: bool, callback: &mut F)
|
||||||
where
|
where
|
||||||
F: FnMut(Range<usize>, Result<char, EscapeError>),
|
F: FnMut(Range<usize>, Result<char, EscapeError>),
|
||||||
{
|
{
|
||||||
debug_assert!(mode == Mode::RawStr || mode == Mode::RawByteStr);
|
let mut chars = src.chars();
|
||||||
let initial_len = literal_text.len();
|
|
||||||
|
|
||||||
let mut chars = literal_text.chars();
|
// The `start` and `end` computation here matches the one in
|
||||||
while let Some(curr) = chars.next() {
|
// `unescape_str_or_byte_str` for consistency, even though this function
|
||||||
let start = initial_len - chars.as_str().len() - curr.len_utf8();
|
// doesn't have to worry about skipping any chars.
|
||||||
|
while let Some(c) = chars.next() {
|
||||||
let result = match curr {
|
let start = src.len() - chars.as_str().len() - c.len_utf8();
|
||||||
|
let res = match c {
|
||||||
'\r' => Err(EscapeError::BareCarriageReturnInRawString),
|
'\r' => Err(EscapeError::BareCarriageReturnInRawString),
|
||||||
c if mode.is_bytes() && !c.is_ascii() => Err(EscapeError::NonAsciiCharInByteString),
|
_ => ascii_check(c, is_byte),
|
||||||
c => Ok(c),
|
|
||||||
};
|
};
|
||||||
let end = initial_len - chars.as_str().len();
|
let end = src.len() - chars.as_str().len();
|
||||||
|
callback(start..end, res);
|
||||||
callback(start..end, result);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn byte_from_char(c: char) -> u8 {
|
#[inline]
|
||||||
|
pub fn byte_from_char(c: char) -> u8 {
|
||||||
let res = c as u32;
|
let res = c as u32;
|
||||||
debug_assert!(res <= u8::MAX as u32, "guaranteed because of Mode::ByteStr");
|
debug_assert!(res <= u8::MAX as u32, "guaranteed because of Mode::ByteStr");
|
||||||
res as u8
|
res as u8
|
||||||
|
|
|
@ -3,8 +3,7 @@ use super::*;
|
||||||
#[test]
|
#[test]
|
||||||
fn test_unescape_char_bad() {
|
fn test_unescape_char_bad() {
|
||||||
fn check(literal_text: &str, expected_error: EscapeError) {
|
fn check(literal_text: &str, expected_error: EscapeError) {
|
||||||
let actual_result = unescape_char(literal_text).map_err(|(_offset, err)| err);
|
assert_eq!(unescape_char(literal_text), Err(expected_error));
|
||||||
assert_eq!(actual_result, Err(expected_error));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
check("", EscapeError::ZeroChars);
|
check("", EscapeError::ZeroChars);
|
||||||
|
@ -68,8 +67,7 @@ fn test_unescape_char_bad() {
|
||||||
#[test]
|
#[test]
|
||||||
fn test_unescape_char_good() {
|
fn test_unescape_char_good() {
|
||||||
fn check(literal_text: &str, expected_char: char) {
|
fn check(literal_text: &str, expected_char: char) {
|
||||||
let actual_result = unescape_char(literal_text);
|
assert_eq!(unescape_char(literal_text), Ok(expected_char));
|
||||||
assert_eq!(actual_result, Ok(expected_char));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
check("a", 'a');
|
check("a", 'a');
|
||||||
|
@ -149,8 +147,7 @@ fn test_unescape_str_good() {
|
||||||
#[test]
|
#[test]
|
||||||
fn test_unescape_byte_bad() {
|
fn test_unescape_byte_bad() {
|
||||||
fn check(literal_text: &str, expected_error: EscapeError) {
|
fn check(literal_text: &str, expected_error: EscapeError) {
|
||||||
let actual_result = unescape_byte(literal_text).map_err(|(_offset, err)| err);
|
assert_eq!(unescape_byte(literal_text), Err(expected_error));
|
||||||
assert_eq!(actual_result, Err(expected_error));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
check("", EscapeError::ZeroChars);
|
check("", EscapeError::ZeroChars);
|
||||||
|
@ -219,8 +216,7 @@ fn test_unescape_byte_bad() {
|
||||||
#[test]
|
#[test]
|
||||||
fn test_unescape_byte_good() {
|
fn test_unescape_byte_good() {
|
||||||
fn check(literal_text: &str, expected_byte: u8) {
|
fn check(literal_text: &str, expected_byte: u8) {
|
||||||
let actual_result = unescape_byte(literal_text);
|
assert_eq!(unescape_byte(literal_text), Ok(expected_byte));
|
||||||
assert_eq!(actual_result, Ok(expected_byte));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
check("a", b'a');
|
check("a", b'a');
|
||||||
|
@ -246,10 +242,10 @@ fn test_unescape_byte_good() {
|
||||||
fn test_unescape_byte_str_good() {
|
fn test_unescape_byte_str_good() {
|
||||||
fn check(literal_text: &str, expected: &[u8]) {
|
fn check(literal_text: &str, expected: &[u8]) {
|
||||||
let mut buf = Ok(Vec::with_capacity(literal_text.len()));
|
let mut buf = Ok(Vec::with_capacity(literal_text.len()));
|
||||||
unescape_byte_literal(literal_text, Mode::ByteStr, &mut |range, c| {
|
unescape_literal(literal_text, Mode::ByteStr, &mut |range, c| {
|
||||||
if let Ok(b) = &mut buf {
|
if let Ok(b) = &mut buf {
|
||||||
match c {
|
match c {
|
||||||
Ok(c) => b.push(c),
|
Ok(c) => b.push(byte_from_char(c)),
|
||||||
Err(e) => buf = Err((range, e)),
|
Err(e) => buf = Err((range, e)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -280,18 +276,13 @@ fn test_unescape_raw_str() {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_unescape_raw_byte_str() {
|
fn test_unescape_raw_byte_str() {
|
||||||
fn check(literal: &str, expected: &[(Range<usize>, Result<u8, EscapeError>)]) {
|
fn check(literal: &str, expected: &[(Range<usize>, Result<char, EscapeError>)]) {
|
||||||
let mut unescaped = Vec::with_capacity(literal.len());
|
let mut unescaped = Vec::with_capacity(literal.len());
|
||||||
unescape_byte_literal(literal, Mode::RawByteStr, &mut |range, res| {
|
unescape_literal(literal, Mode::RawByteStr, &mut |range, res| unescaped.push((range, res)));
|
||||||
unescaped.push((range, res))
|
|
||||||
});
|
|
||||||
assert_eq!(unescaped, expected);
|
assert_eq!(unescaped, expected);
|
||||||
}
|
}
|
||||||
|
|
||||||
check("\r", &[(0..1, Err(EscapeError::BareCarriageReturnInRawString))]);
|
check("\r", &[(0..1, Err(EscapeError::BareCarriageReturnInRawString))]);
|
||||||
check("🦀", &[(0..4, Err(EscapeError::NonAsciiCharInByteString))]);
|
check("🦀", &[(0..4, Err(EscapeError::NonAsciiCharInByte))]);
|
||||||
check(
|
check("🦀a", &[(0..4, Err(EscapeError::NonAsciiCharInByte)), (4..5, Ok('a'))]);
|
||||||
"🦀a",
|
|
||||||
&[(0..4, Err(EscapeError::NonAsciiCharInByteString)), (4..5, Ok(byte_from_char('a')))],
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -353,55 +353,55 @@ impl<'a> StringReader<'a> {
|
||||||
fn cook_lexer_literal(
|
fn cook_lexer_literal(
|
||||||
&self,
|
&self,
|
||||||
start: BytePos,
|
start: BytePos,
|
||||||
suffix_start: BytePos,
|
end: BytePos,
|
||||||
kind: rustc_lexer::LiteralKind,
|
kind: rustc_lexer::LiteralKind,
|
||||||
) -> (token::LitKind, Symbol) {
|
) -> (token::LitKind, Symbol) {
|
||||||
// prefix means `"` or `br"` or `r###"`, ...
|
match kind {
|
||||||
let (lit_kind, mode, prefix_len, postfix_len) = match kind {
|
|
||||||
rustc_lexer::LiteralKind::Char { terminated } => {
|
rustc_lexer::LiteralKind::Char { terminated } => {
|
||||||
if !terminated {
|
if !terminated {
|
||||||
self.sess.span_diagnostic.span_fatal_with_code(
|
self.sess.span_diagnostic.span_fatal_with_code(
|
||||||
self.mk_sp(start, suffix_start),
|
self.mk_sp(start, end),
|
||||||
"unterminated character literal",
|
"unterminated character literal",
|
||||||
error_code!(E0762),
|
error_code!(E0762),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
(token::Char, Mode::Char, 1, 1) // ' '
|
self.cook_quoted(token::Char, Mode::Char, start, end, 1, 1) // ' '
|
||||||
}
|
}
|
||||||
rustc_lexer::LiteralKind::Byte { terminated } => {
|
rustc_lexer::LiteralKind::Byte { terminated } => {
|
||||||
if !terminated {
|
if !terminated {
|
||||||
self.sess.span_diagnostic.span_fatal_with_code(
|
self.sess.span_diagnostic.span_fatal_with_code(
|
||||||
self.mk_sp(start + BytePos(1), suffix_start),
|
self.mk_sp(start + BytePos(1), end),
|
||||||
"unterminated byte constant",
|
"unterminated byte constant",
|
||||||
error_code!(E0763),
|
error_code!(E0763),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
(token::Byte, Mode::Byte, 2, 1) // b' '
|
self.cook_quoted(token::Byte, Mode::Byte, start, end, 2, 1) // b' '
|
||||||
}
|
}
|
||||||
rustc_lexer::LiteralKind::Str { terminated } => {
|
rustc_lexer::LiteralKind::Str { terminated } => {
|
||||||
if !terminated {
|
if !terminated {
|
||||||
self.sess.span_diagnostic.span_fatal_with_code(
|
self.sess.span_diagnostic.span_fatal_with_code(
|
||||||
self.mk_sp(start, suffix_start),
|
self.mk_sp(start, end),
|
||||||
"unterminated double quote string",
|
"unterminated double quote string",
|
||||||
error_code!(E0765),
|
error_code!(E0765),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
(token::Str, Mode::Str, 1, 1) // " "
|
self.cook_quoted(token::Str, Mode::Str, start, end, 1, 1) // " "
|
||||||
}
|
}
|
||||||
rustc_lexer::LiteralKind::ByteStr { terminated } => {
|
rustc_lexer::LiteralKind::ByteStr { terminated } => {
|
||||||
if !terminated {
|
if !terminated {
|
||||||
self.sess.span_diagnostic.span_fatal_with_code(
|
self.sess.span_diagnostic.span_fatal_with_code(
|
||||||
self.mk_sp(start + BytePos(1), suffix_start),
|
self.mk_sp(start + BytePos(1), end),
|
||||||
"unterminated double quote byte string",
|
"unterminated double quote byte string",
|
||||||
error_code!(E0766),
|
error_code!(E0766),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
(token::ByteStr, Mode::ByteStr, 2, 1) // b" "
|
self.cook_quoted(token::ByteStr, Mode::ByteStr, start, end, 2, 1) // b" "
|
||||||
}
|
}
|
||||||
rustc_lexer::LiteralKind::RawStr { n_hashes } => {
|
rustc_lexer::LiteralKind::RawStr { n_hashes } => {
|
||||||
if let Some(n_hashes) = n_hashes {
|
if let Some(n_hashes) = n_hashes {
|
||||||
let n = u32::from(n_hashes);
|
let n = u32::from(n_hashes);
|
||||||
(token::StrRaw(n_hashes), Mode::RawStr, 2 + n, 1 + n) // r##" "##
|
let kind = token::StrRaw(n_hashes);
|
||||||
|
self.cook_quoted(kind, Mode::RawStr, start, end, 2 + n, 1 + n) // r##" "##
|
||||||
} else {
|
} else {
|
||||||
self.report_raw_str_error(start, 1);
|
self.report_raw_str_error(start, 1);
|
||||||
}
|
}
|
||||||
|
@ -409,56 +409,59 @@ impl<'a> StringReader<'a> {
|
||||||
rustc_lexer::LiteralKind::RawByteStr { n_hashes } => {
|
rustc_lexer::LiteralKind::RawByteStr { n_hashes } => {
|
||||||
if let Some(n_hashes) = n_hashes {
|
if let Some(n_hashes) = n_hashes {
|
||||||
let n = u32::from(n_hashes);
|
let n = u32::from(n_hashes);
|
||||||
(token::ByteStrRaw(n_hashes), Mode::RawByteStr, 3 + n, 1 + n) // br##" "##
|
let kind = token::ByteStrRaw(n_hashes);
|
||||||
|
self.cook_quoted(kind, Mode::RawByteStr, start, end, 3 + n, 1 + n) // br##" "##
|
||||||
} else {
|
} else {
|
||||||
self.report_raw_str_error(start, 2);
|
self.report_raw_str_error(start, 2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
rustc_lexer::LiteralKind::Int { base, empty_int } => {
|
rustc_lexer::LiteralKind::Int { base, empty_int } => {
|
||||||
return if empty_int {
|
if empty_int {
|
||||||
self.sess
|
self.sess
|
||||||
.span_diagnostic
|
.span_diagnostic
|
||||||
.struct_span_err_with_code(
|
.struct_span_err_with_code(
|
||||||
self.mk_sp(start, suffix_start),
|
self.mk_sp(start, end),
|
||||||
"no valid digits found for number",
|
"no valid digits found for number",
|
||||||
error_code!(E0768),
|
error_code!(E0768),
|
||||||
)
|
)
|
||||||
.emit();
|
.emit();
|
||||||
(token::Integer, sym::integer(0))
|
(token::Integer, sym::integer(0))
|
||||||
} else {
|
} else {
|
||||||
self.validate_int_literal(base, start, suffix_start);
|
if matches!(base, Base::Binary | Base::Octal) {
|
||||||
(token::Integer, self.symbol_from_to(start, suffix_start))
|
let base = base as u32;
|
||||||
};
|
let s = self.str_from_to(start + BytePos(2), end);
|
||||||
|
for (idx, c) in s.char_indices() {
|
||||||
|
if c != '_' && c.to_digit(base).is_none() {
|
||||||
|
self.err_span_(
|
||||||
|
start + BytePos::from_usize(2 + idx),
|
||||||
|
start + BytePos::from_usize(2 + idx + c.len_utf8()),
|
||||||
|
&format!("invalid digit for a base {} literal", base),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
(token::Integer, self.symbol_from_to(start, end))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
rustc_lexer::LiteralKind::Float { base, empty_exponent } => {
|
rustc_lexer::LiteralKind::Float { base, empty_exponent } => {
|
||||||
if empty_exponent {
|
if empty_exponent {
|
||||||
self.err_span_(start, self.pos, "expected at least one digit in exponent");
|
self.err_span_(start, self.pos, "expected at least one digit in exponent");
|
||||||
}
|
}
|
||||||
|
|
||||||
match base {
|
match base {
|
||||||
Base::Hexadecimal => self.err_span_(
|
Base::Hexadecimal => {
|
||||||
start,
|
self.err_span_(start, end, "hexadecimal float literal is not supported")
|
||||||
suffix_start,
|
}
|
||||||
"hexadecimal float literal is not supported",
|
|
||||||
),
|
|
||||||
Base::Octal => {
|
Base::Octal => {
|
||||||
self.err_span_(start, suffix_start, "octal float literal is not supported")
|
self.err_span_(start, end, "octal float literal is not supported")
|
||||||
}
|
}
|
||||||
Base::Binary => {
|
Base::Binary => {
|
||||||
self.err_span_(start, suffix_start, "binary float literal is not supported")
|
self.err_span_(start, end, "binary float literal is not supported")
|
||||||
}
|
}
|
||||||
_ => (),
|
_ => {}
|
||||||
}
|
}
|
||||||
|
(token::Float, self.symbol_from_to(start, end))
|
||||||
let id = self.symbol_from_to(start, suffix_start);
|
|
||||||
return (token::Float, id);
|
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
let content_start = start + BytePos(prefix_len);
|
|
||||||
let content_end = suffix_start - BytePos(postfix_len);
|
|
||||||
let id = self.symbol_from_to(content_start, content_end);
|
|
||||||
self.validate_literal_escape(mode, content_start, content_end, prefix_len, postfix_len);
|
|
||||||
(lit_kind, id)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -649,20 +652,22 @@ impl<'a> StringReader<'a> {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn validate_literal_escape(
|
fn cook_quoted(
|
||||||
&self,
|
&self,
|
||||||
|
kind: token::LitKind,
|
||||||
mode: Mode,
|
mode: Mode,
|
||||||
content_start: BytePos,
|
start: BytePos,
|
||||||
content_end: BytePos,
|
end: BytePos,
|
||||||
prefix_len: u32,
|
prefix_len: u32,
|
||||||
postfix_len: u32,
|
postfix_len: u32,
|
||||||
) {
|
) -> (token::LitKind, Symbol) {
|
||||||
|
let content_start = start + BytePos(prefix_len);
|
||||||
|
let content_end = end - BytePos(postfix_len);
|
||||||
let lit_content = self.str_from_to(content_start, content_end);
|
let lit_content = self.str_from_to(content_start, content_end);
|
||||||
unescape::unescape_literal(lit_content, mode, &mut |range, result| {
|
unescape::unescape_literal(lit_content, mode, &mut |range, result| {
|
||||||
// Here we only check for errors. The actual unescaping is done later.
|
// Here we only check for errors. The actual unescaping is done later.
|
||||||
if let Err(err) = result {
|
if let Err(err) = result {
|
||||||
let span_with_quotes = self
|
let span_with_quotes = self.mk_sp(start, end);
|
||||||
.mk_sp(content_start - BytePos(prefix_len), content_end + BytePos(postfix_len));
|
|
||||||
let (start, end) = (range.start as u32, range.end as u32);
|
let (start, end) = (range.start as u32, range.end as u32);
|
||||||
let lo = content_start + BytePos(start);
|
let lo = content_start + BytePos(start);
|
||||||
let hi = lo + BytePos(end - start);
|
let hi = lo + BytePos(end - start);
|
||||||
|
@ -678,23 +683,7 @@ impl<'a> StringReader<'a> {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
(kind, Symbol::intern(lit_content))
|
||||||
|
|
||||||
fn validate_int_literal(&self, base: Base, content_start: BytePos, content_end: BytePos) {
|
|
||||||
let base = match base {
|
|
||||||
Base::Binary => 2,
|
|
||||||
Base::Octal => 8,
|
|
||||||
_ => return,
|
|
||||||
};
|
|
||||||
let s = self.str_from_to(content_start + BytePos(2), content_end);
|
|
||||||
for (idx, c) in s.char_indices() {
|
|
||||||
let idx = idx as u32;
|
|
||||||
if c != '_' && c.to_digit(base).is_none() {
|
|
||||||
let lo = content_start + BytePos(2 + idx);
|
|
||||||
let hi = content_start + BytePos(2 + idx + c.len_utf8() as u32);
|
|
||||||
self.err_span_(lo, hi, &format!("invalid digit for a base {} literal", base));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -108,7 +108,7 @@ pub(crate) fn emit_unescape_error(
|
||||||
}
|
}
|
||||||
|
|
||||||
if !has_help {
|
if !has_help {
|
||||||
let (prefix, msg) = if mode.is_bytes() {
|
let (prefix, msg) = if mode.is_byte() {
|
||||||
("b", "if you meant to write a byte string literal, use double quotes")
|
("b", "if you meant to write a byte string literal, use double quotes")
|
||||||
} else {
|
} else {
|
||||||
("", "if you meant to write a `str` literal, use double quotes")
|
("", "if you meant to write a `str` literal, use double quotes")
|
||||||
|
@ -142,7 +142,7 @@ pub(crate) fn emit_unescape_error(
|
||||||
EscapeError::EscapeOnlyChar => {
|
EscapeError::EscapeOnlyChar => {
|
||||||
let (c, char_span) = last_char();
|
let (c, char_span) = last_char();
|
||||||
|
|
||||||
let msg = if mode.is_bytes() {
|
let msg = if mode.is_byte() {
|
||||||
"byte constant must be escaped"
|
"byte constant must be escaped"
|
||||||
} else {
|
} else {
|
||||||
"character constant must be escaped"
|
"character constant must be escaped"
|
||||||
|
@ -182,11 +182,11 @@ pub(crate) fn emit_unescape_error(
|
||||||
let (c, span) = last_char();
|
let (c, span) = last_char();
|
||||||
|
|
||||||
let label =
|
let label =
|
||||||
if mode.is_bytes() { "unknown byte escape" } else { "unknown character escape" };
|
if mode.is_byte() { "unknown byte escape" } else { "unknown character escape" };
|
||||||
let ec = escaped_char(c);
|
let ec = escaped_char(c);
|
||||||
let mut diag = handler.struct_span_err(span, &format!("{}: `{}`", label, ec));
|
let mut diag = handler.struct_span_err(span, &format!("{}: `{}`", label, ec));
|
||||||
diag.span_label(span, label);
|
diag.span_label(span, label);
|
||||||
if c == '{' || c == '}' && !mode.is_bytes() {
|
if c == '{' || c == '}' && !mode.is_byte() {
|
||||||
diag.help(
|
diag.help(
|
||||||
"if used in a formatting string, curly braces are escaped with `{{` and `}}`",
|
"if used in a formatting string, curly braces are escaped with `{{` and `}}`",
|
||||||
);
|
);
|
||||||
|
@ -196,7 +196,7 @@ pub(crate) fn emit_unescape_error(
|
||||||
version control settings",
|
version control settings",
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
if !mode.is_bytes() {
|
if !mode.is_byte() {
|
||||||
diag.span_suggestion(
|
diag.span_suggestion(
|
||||||
span_with_quotes,
|
span_with_quotes,
|
||||||
"if you meant to write a literal backslash (perhaps escaping in a regular expression), consider a raw string literal",
|
"if you meant to write a literal backslash (perhaps escaping in a regular expression), consider a raw string literal",
|
||||||
|
@ -231,16 +231,23 @@ pub(crate) fn emit_unescape_error(
|
||||||
.emit();
|
.emit();
|
||||||
}
|
}
|
||||||
EscapeError::NonAsciiCharInByte => {
|
EscapeError::NonAsciiCharInByte => {
|
||||||
assert!(mode.is_bytes());
|
|
||||||
let (c, span) = last_char();
|
let (c, span) = last_char();
|
||||||
let mut err = handler.struct_span_err(span, "non-ASCII character in byte constant");
|
let desc = match mode {
|
||||||
|
Mode::Byte => "byte literal",
|
||||||
|
Mode::ByteStr => "byte string literal",
|
||||||
|
Mode::RawByteStr => "raw byte string literal",
|
||||||
|
_ => panic!("non-is_byte literal paired with NonAsciiCharInByte"),
|
||||||
|
};
|
||||||
|
let mut err = handler.struct_span_err(span, format!("non-ASCII character in {}", desc));
|
||||||
let postfix = if unicode_width::UnicodeWidthChar::width(c).unwrap_or(1) == 0 {
|
let postfix = if unicode_width::UnicodeWidthChar::width(c).unwrap_or(1) == 0 {
|
||||||
format!(" but is {:?}", c)
|
format!(" but is {:?}", c)
|
||||||
} else {
|
} else {
|
||||||
String::new()
|
String::new()
|
||||||
};
|
};
|
||||||
err.span_label(span, &format!("byte constant must be ASCII{}", postfix));
|
err.span_label(span, &format!("must be ASCII{}", postfix));
|
||||||
if (c as u32) <= 0xFF {
|
// Note: the \\xHH suggestions are not given for raw byte string
|
||||||
|
// literals, because they are araw and so cannot use any escapes.
|
||||||
|
if (c as u32) <= 0xFF && mode != Mode::RawByteStr {
|
||||||
err.span_suggestion(
|
err.span_suggestion(
|
||||||
span,
|
span,
|
||||||
&format!(
|
&format!(
|
||||||
|
@ -250,9 +257,9 @@ pub(crate) fn emit_unescape_error(
|
||||||
format!("\\x{:X}", c as u32),
|
format!("\\x{:X}", c as u32),
|
||||||
Applicability::MaybeIncorrect,
|
Applicability::MaybeIncorrect,
|
||||||
);
|
);
|
||||||
} else if matches!(mode, Mode::Byte) {
|
} else if mode == Mode::Byte {
|
||||||
err.span_label(span, "this multibyte character does not fit into a single byte");
|
err.span_label(span, "this multibyte character does not fit into a single byte");
|
||||||
} else if matches!(mode, Mode::ByteStr) {
|
} else if mode != Mode::RawByteStr {
|
||||||
let mut utf8 = String::new();
|
let mut utf8 = String::new();
|
||||||
utf8.push(c);
|
utf8.push(c);
|
||||||
err.span_suggestion(
|
err.span_suggestion(
|
||||||
|
@ -270,19 +277,6 @@ pub(crate) fn emit_unescape_error(
|
||||||
}
|
}
|
||||||
err.emit();
|
err.emit();
|
||||||
}
|
}
|
||||||
EscapeError::NonAsciiCharInByteString => {
|
|
||||||
assert!(mode.is_bytes());
|
|
||||||
let (c, span) = last_char();
|
|
||||||
let postfix = if unicode_width::UnicodeWidthChar::width(c).unwrap_or(1) == 0 {
|
|
||||||
format!(" but is {:?}", c)
|
|
||||||
} else {
|
|
||||||
String::new()
|
|
||||||
};
|
|
||||||
handler
|
|
||||||
.struct_span_err(span, "raw byte string must be ASCII")
|
|
||||||
.span_label(span, &format!("must be ASCII{}", postfix))
|
|
||||||
.emit();
|
|
||||||
}
|
|
||||||
EscapeError::OutOfRangeHexEscape => {
|
EscapeError::OutOfRangeHexEscape => {
|
||||||
handler
|
handler
|
||||||
.struct_span_err(span, "out of range hex escape")
|
.struct_span_err(span, "out of range hex escape")
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
// wasm32 does not support benches (no time).
|
// wasm32 does not support benches (no time).
|
||||||
#![cfg(not(target_arch = "wasm32"))]
|
#![cfg(not(target_arch = "wasm32"))]
|
||||||
#![feature(flt2dec)]
|
#![feature(flt2dec)]
|
||||||
#![feature(int_log)]
|
|
||||||
#![feature(test)]
|
#![feature(test)]
|
||||||
#![feature(trusted_random_access)]
|
#![feature(trusted_random_access)]
|
||||||
#![feature(iter_array_chunks)]
|
#![feature(iter_array_chunks)]
|
||||||
|
|
|
@ -2271,15 +2271,16 @@ macro_rules! int_impl {
|
||||||
/// # Panics
|
/// # Panics
|
||||||
///
|
///
|
||||||
/// This function will panic if `self` is less than or equal to zero,
|
/// This function will panic if `self` is less than or equal to zero,
|
||||||
/// or if `base` is less then 2.
|
/// or if `base` is less than 2.
|
||||||
///
|
///
|
||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// #![feature(int_log)]
|
|
||||||
#[doc = concat!("assert_eq!(5", stringify!($SelfT), ".ilog(5), 1);")]
|
#[doc = concat!("assert_eq!(5", stringify!($SelfT), ".ilog(5), 1);")]
|
||||||
/// ```
|
/// ```
|
||||||
#[unstable(feature = "int_log", issue = "70887")]
|
#[stable(feature = "int_log", since = "CURRENT_RUSTC_VERSION")]
|
||||||
|
#[rustc_const_stable(feature = "int_log", since = "CURRENT_RUSTC_VERSION")]
|
||||||
|
#[rustc_allow_const_fn_unstable(const_option)]
|
||||||
#[must_use = "this returns the result of the operation, \
|
#[must_use = "this returns the result of the operation, \
|
||||||
without modifying the original"]
|
without modifying the original"]
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -2298,10 +2299,11 @@ macro_rules! int_impl {
|
||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// #![feature(int_log)]
|
|
||||||
#[doc = concat!("assert_eq!(2", stringify!($SelfT), ".ilog2(), 1);")]
|
#[doc = concat!("assert_eq!(2", stringify!($SelfT), ".ilog2(), 1);")]
|
||||||
/// ```
|
/// ```
|
||||||
#[unstable(feature = "int_log", issue = "70887")]
|
#[stable(feature = "int_log", since = "CURRENT_RUSTC_VERSION")]
|
||||||
|
#[rustc_const_stable(feature = "int_log", since = "CURRENT_RUSTC_VERSION")]
|
||||||
|
#[rustc_allow_const_fn_unstable(const_option)]
|
||||||
#[must_use = "this returns the result of the operation, \
|
#[must_use = "this returns the result of the operation, \
|
||||||
without modifying the original"]
|
without modifying the original"]
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -2319,10 +2321,11 @@ macro_rules! int_impl {
|
||||||
/// # Example
|
/// # Example
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// #![feature(int_log)]
|
|
||||||
#[doc = concat!("assert_eq!(10", stringify!($SelfT), ".ilog10(), 1);")]
|
#[doc = concat!("assert_eq!(10", stringify!($SelfT), ".ilog10(), 1);")]
|
||||||
/// ```
|
/// ```
|
||||||
#[unstable(feature = "int_log", issue = "70887")]
|
#[stable(feature = "int_log", since = "CURRENT_RUSTC_VERSION")]
|
||||||
|
#[rustc_const_stable(feature = "int_log", since = "CURRENT_RUSTC_VERSION")]
|
||||||
|
#[rustc_allow_const_fn_unstable(const_option)]
|
||||||
#[must_use = "this returns the result of the operation, \
|
#[must_use = "this returns the result of the operation, \
|
||||||
without modifying the original"]
|
without modifying the original"]
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -2343,10 +2346,10 @@ macro_rules! int_impl {
|
||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// #![feature(int_log)]
|
|
||||||
#[doc = concat!("assert_eq!(5", stringify!($SelfT), ".checked_ilog(5), Some(1));")]
|
#[doc = concat!("assert_eq!(5", stringify!($SelfT), ".checked_ilog(5), Some(1));")]
|
||||||
/// ```
|
/// ```
|
||||||
#[unstable(feature = "int_log", issue = "70887")]
|
#[stable(feature = "int_log", since = "CURRENT_RUSTC_VERSION")]
|
||||||
|
#[rustc_const_stable(feature = "int_log", since = "CURRENT_RUSTC_VERSION")]
|
||||||
#[must_use = "this returns the result of the operation, \
|
#[must_use = "this returns the result of the operation, \
|
||||||
without modifying the original"]
|
without modifying the original"]
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -2379,10 +2382,10 @@ macro_rules! int_impl {
|
||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// #![feature(int_log)]
|
|
||||||
#[doc = concat!("assert_eq!(2", stringify!($SelfT), ".checked_ilog2(), Some(1));")]
|
#[doc = concat!("assert_eq!(2", stringify!($SelfT), ".checked_ilog2(), Some(1));")]
|
||||||
/// ```
|
/// ```
|
||||||
#[unstable(feature = "int_log", issue = "70887")]
|
#[stable(feature = "int_log", since = "CURRENT_RUSTC_VERSION")]
|
||||||
|
#[rustc_const_stable(feature = "int_log", since = "CURRENT_RUSTC_VERSION")]
|
||||||
#[must_use = "this returns the result of the operation, \
|
#[must_use = "this returns the result of the operation, \
|
||||||
without modifying the original"]
|
without modifying the original"]
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -2403,10 +2406,10 @@ macro_rules! int_impl {
|
||||||
/// # Example
|
/// # Example
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// #![feature(int_log)]
|
|
||||||
#[doc = concat!("assert_eq!(10", stringify!($SelfT), ".checked_ilog10(), Some(1));")]
|
#[doc = concat!("assert_eq!(10", stringify!($SelfT), ".checked_ilog10(), Some(1));")]
|
||||||
/// ```
|
/// ```
|
||||||
#[unstable(feature = "int_log", issue = "70887")]
|
#[stable(feature = "int_log", since = "CURRENT_RUSTC_VERSION")]
|
||||||
|
#[rustc_const_stable(feature = "int_log", since = "CURRENT_RUSTC_VERSION")]
|
||||||
#[must_use = "this returns the result of the operation, \
|
#[must_use = "this returns the result of the operation, \
|
||||||
without modifying the original"]
|
without modifying the original"]
|
||||||
#[inline]
|
#[inline]
|
||||||
|
|
|
@ -460,14 +460,14 @@ macro_rules! nonzero_unsigned_operations {
|
||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// #![feature(int_log)]
|
|
||||||
#[doc = concat!("# use std::num::", stringify!($Ty), ";")]
|
#[doc = concat!("# use std::num::", stringify!($Ty), ";")]
|
||||||
///
|
///
|
||||||
#[doc = concat!("assert_eq!(", stringify!($Ty), "::new(7).unwrap().ilog2(), 2);")]
|
#[doc = concat!("assert_eq!(", stringify!($Ty), "::new(7).unwrap().ilog2(), 2);")]
|
||||||
#[doc = concat!("assert_eq!(", stringify!($Ty), "::new(8).unwrap().ilog2(), 3);")]
|
#[doc = concat!("assert_eq!(", stringify!($Ty), "::new(8).unwrap().ilog2(), 3);")]
|
||||||
#[doc = concat!("assert_eq!(", stringify!($Ty), "::new(9).unwrap().ilog2(), 3);")]
|
#[doc = concat!("assert_eq!(", stringify!($Ty), "::new(9).unwrap().ilog2(), 3);")]
|
||||||
/// ```
|
/// ```
|
||||||
#[unstable(feature = "int_log", issue = "70887")]
|
#[stable(feature = "int_log", since = "CURRENT_RUSTC_VERSION")]
|
||||||
|
#[rustc_const_stable(feature = "int_log", since = "CURRENT_RUSTC_VERSION")]
|
||||||
#[must_use = "this returns the result of the operation, \
|
#[must_use = "this returns the result of the operation, \
|
||||||
without modifying the original"]
|
without modifying the original"]
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -485,14 +485,14 @@ macro_rules! nonzero_unsigned_operations {
|
||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// #![feature(int_log)]
|
|
||||||
#[doc = concat!("# use std::num::", stringify!($Ty), ";")]
|
#[doc = concat!("# use std::num::", stringify!($Ty), ";")]
|
||||||
///
|
///
|
||||||
#[doc = concat!("assert_eq!(", stringify!($Ty), "::new(99).unwrap().ilog10(), 1);")]
|
#[doc = concat!("assert_eq!(", stringify!($Ty), "::new(99).unwrap().ilog10(), 1);")]
|
||||||
#[doc = concat!("assert_eq!(", stringify!($Ty), "::new(100).unwrap().ilog10(), 2);")]
|
#[doc = concat!("assert_eq!(", stringify!($Ty), "::new(100).unwrap().ilog10(), 2);")]
|
||||||
#[doc = concat!("assert_eq!(", stringify!($Ty), "::new(101).unwrap().ilog10(), 2);")]
|
#[doc = concat!("assert_eq!(", stringify!($Ty), "::new(101).unwrap().ilog10(), 2);")]
|
||||||
/// ```
|
/// ```
|
||||||
#[unstable(feature = "int_log", issue = "70887")]
|
#[stable(feature = "int_log", since = "CURRENT_RUSTC_VERSION")]
|
||||||
|
#[rustc_const_stable(feature = "int_log", since = "CURRENT_RUSTC_VERSION")]
|
||||||
#[must_use = "this returns the result of the operation, \
|
#[must_use = "this returns the result of the operation, \
|
||||||
without modifying the original"]
|
without modifying the original"]
|
||||||
#[inline]
|
#[inline]
|
||||||
|
|
|
@ -692,15 +692,16 @@ macro_rules! uint_impl {
|
||||||
///
|
///
|
||||||
/// # Panics
|
/// # Panics
|
||||||
///
|
///
|
||||||
/// This function will panic if `self` is zero, or if `base` is less then 2.
|
/// This function will panic if `self` is zero, or if `base` is less than 2.
|
||||||
///
|
///
|
||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// #![feature(int_log)]
|
|
||||||
#[doc = concat!("assert_eq!(5", stringify!($SelfT), ".ilog(5), 1);")]
|
#[doc = concat!("assert_eq!(5", stringify!($SelfT), ".ilog(5), 1);")]
|
||||||
/// ```
|
/// ```
|
||||||
#[unstable(feature = "int_log", issue = "70887")]
|
#[stable(feature = "int_log", since = "CURRENT_RUSTC_VERSION")]
|
||||||
|
#[rustc_const_stable(feature = "int_log", since = "CURRENT_RUSTC_VERSION")]
|
||||||
|
#[rustc_allow_const_fn_unstable(const_option)]
|
||||||
#[must_use = "this returns the result of the operation, \
|
#[must_use = "this returns the result of the operation, \
|
||||||
without modifying the original"]
|
without modifying the original"]
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -719,10 +720,11 @@ macro_rules! uint_impl {
|
||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// #![feature(int_log)]
|
|
||||||
#[doc = concat!("assert_eq!(2", stringify!($SelfT), ".ilog2(), 1);")]
|
#[doc = concat!("assert_eq!(2", stringify!($SelfT), ".ilog2(), 1);")]
|
||||||
/// ```
|
/// ```
|
||||||
#[unstable(feature = "int_log", issue = "70887")]
|
#[stable(feature = "int_log", since = "CURRENT_RUSTC_VERSION")]
|
||||||
|
#[rustc_const_stable(feature = "int_log", since = "CURRENT_RUSTC_VERSION")]
|
||||||
|
#[rustc_allow_const_fn_unstable(const_option)]
|
||||||
#[must_use = "this returns the result of the operation, \
|
#[must_use = "this returns the result of the operation, \
|
||||||
without modifying the original"]
|
without modifying the original"]
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -740,10 +742,11 @@ macro_rules! uint_impl {
|
||||||
/// # Example
|
/// # Example
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// #![feature(int_log)]
|
|
||||||
#[doc = concat!("assert_eq!(10", stringify!($SelfT), ".ilog10(), 1);")]
|
#[doc = concat!("assert_eq!(10", stringify!($SelfT), ".ilog10(), 1);")]
|
||||||
/// ```
|
/// ```
|
||||||
#[unstable(feature = "int_log", issue = "70887")]
|
#[stable(feature = "int_log", since = "CURRENT_RUSTC_VERSION")]
|
||||||
|
#[rustc_const_stable(feature = "int_log", since = "CURRENT_RUSTC_VERSION")]
|
||||||
|
#[rustc_allow_const_fn_unstable(const_option)]
|
||||||
#[must_use = "this returns the result of the operation, \
|
#[must_use = "this returns the result of the operation, \
|
||||||
without modifying the original"]
|
without modifying the original"]
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -764,10 +767,10 @@ macro_rules! uint_impl {
|
||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// #![feature(int_log)]
|
|
||||||
#[doc = concat!("assert_eq!(5", stringify!($SelfT), ".checked_ilog(5), Some(1));")]
|
#[doc = concat!("assert_eq!(5", stringify!($SelfT), ".checked_ilog(5), Some(1));")]
|
||||||
/// ```
|
/// ```
|
||||||
#[unstable(feature = "int_log", issue = "70887")]
|
#[stable(feature = "int_log", since = "CURRENT_RUSTC_VERSION")]
|
||||||
|
#[rustc_const_stable(feature = "int_log", since = "CURRENT_RUSTC_VERSION")]
|
||||||
#[must_use = "this returns the result of the operation, \
|
#[must_use = "this returns the result of the operation, \
|
||||||
without modifying the original"]
|
without modifying the original"]
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -800,10 +803,10 @@ macro_rules! uint_impl {
|
||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// #![feature(int_log)]
|
|
||||||
#[doc = concat!("assert_eq!(2", stringify!($SelfT), ".checked_ilog2(), Some(1));")]
|
#[doc = concat!("assert_eq!(2", stringify!($SelfT), ".checked_ilog2(), Some(1));")]
|
||||||
/// ```
|
/// ```
|
||||||
#[unstable(feature = "int_log", issue = "70887")]
|
#[stable(feature = "int_log", since = "CURRENT_RUSTC_VERSION")]
|
||||||
|
#[rustc_const_stable(feature = "int_log", since = "CURRENT_RUSTC_VERSION")]
|
||||||
#[must_use = "this returns the result of the operation, \
|
#[must_use = "this returns the result of the operation, \
|
||||||
without modifying the original"]
|
without modifying the original"]
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -822,10 +825,10 @@ macro_rules! uint_impl {
|
||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// #![feature(int_log)]
|
|
||||||
#[doc = concat!("assert_eq!(10", stringify!($SelfT), ".checked_ilog10(), Some(1));")]
|
#[doc = concat!("assert_eq!(10", stringify!($SelfT), ".checked_ilog10(), Some(1));")]
|
||||||
/// ```
|
/// ```
|
||||||
#[unstable(feature = "int_log", issue = "70887")]
|
#[stable(feature = "int_log", since = "CURRENT_RUSTC_VERSION")]
|
||||||
|
#[rustc_const_stable(feature = "int_log", since = "CURRENT_RUSTC_VERSION")]
|
||||||
#[must_use = "this returns the result of the operation, \
|
#[must_use = "this returns the result of the operation, \
|
||||||
without modifying the original"]
|
without modifying the original"]
|
||||||
#[inline]
|
#[inline]
|
||||||
|
|
|
@ -568,6 +568,31 @@ impl<T: ?Sized> *const T {
|
||||||
///
|
///
|
||||||
/// For non-`Sized` pointees this operation changes only the data pointer,
|
/// For non-`Sized` pointees this operation changes only the data pointer,
|
||||||
/// leaving the metadata untouched.
|
/// leaving the metadata untouched.
|
||||||
|
///
|
||||||
|
/// ## Examples
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// #![feature(ptr_mask, strict_provenance)]
|
||||||
|
/// let v = 17_u32;
|
||||||
|
/// let ptr: *const u32 = &v;
|
||||||
|
///
|
||||||
|
/// // `u32` is 4 bytes aligned,
|
||||||
|
/// // which means that lower 2 bits are always 0.
|
||||||
|
/// let tag_mask = 0b11;
|
||||||
|
/// let ptr_mask = !tag_mask;
|
||||||
|
///
|
||||||
|
/// // We can store something in these lower bits
|
||||||
|
/// let tagged_ptr = ptr.map_addr(|a| a | 0b10);
|
||||||
|
///
|
||||||
|
/// // Get the "tag" back
|
||||||
|
/// let tag = tagged_ptr.addr() & tag_mask;
|
||||||
|
/// assert_eq!(tag, 0b10);
|
||||||
|
///
|
||||||
|
/// // Note that `tagged_ptr` is unaligned, it's UB to read from it.
|
||||||
|
/// // To get original pointer `mask` can be used:
|
||||||
|
/// let masked_ptr = tagged_ptr.mask(ptr_mask);
|
||||||
|
/// assert_eq!(unsafe { *masked_ptr }, 17);
|
||||||
|
/// ```
|
||||||
#[unstable(feature = "ptr_mask", issue = "98290")]
|
#[unstable(feature = "ptr_mask", issue = "98290")]
|
||||||
#[must_use = "returns a new pointer rather than modifying its argument"]
|
#[must_use = "returns a new pointer rather than modifying its argument"]
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
|
|
|
@ -588,6 +588,34 @@ impl<T: ?Sized> *mut T {
|
||||||
///
|
///
|
||||||
/// For non-`Sized` pointees this operation changes only the data pointer,
|
/// For non-`Sized` pointees this operation changes only the data pointer,
|
||||||
/// leaving the metadata untouched.
|
/// leaving the metadata untouched.
|
||||||
|
///
|
||||||
|
/// ## Examples
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// #![feature(ptr_mask, strict_provenance)]
|
||||||
|
/// let mut v = 17_u32;
|
||||||
|
/// let ptr: *mut u32 = &mut v;
|
||||||
|
///
|
||||||
|
/// // `u32` is 4 bytes aligned,
|
||||||
|
/// // which means that lower 2 bits are always 0.
|
||||||
|
/// let tag_mask = 0b11;
|
||||||
|
/// let ptr_mask = !tag_mask;
|
||||||
|
///
|
||||||
|
/// // We can store something in these lower bits
|
||||||
|
/// let tagged_ptr = ptr.map_addr(|a| a | 0b10);
|
||||||
|
///
|
||||||
|
/// // Get the "tag" back
|
||||||
|
/// let tag = tagged_ptr.addr() & tag_mask;
|
||||||
|
/// assert_eq!(tag, 0b10);
|
||||||
|
///
|
||||||
|
/// // Note that `tagged_ptr` is unaligned, it's UB to read from/write to it.
|
||||||
|
/// // To get original pointer `mask` can be used:
|
||||||
|
/// let masked_ptr = tagged_ptr.mask(ptr_mask);
|
||||||
|
/// assert_eq!(unsafe { *masked_ptr }, 17);
|
||||||
|
///
|
||||||
|
/// unsafe { *masked_ptr = 0 };
|
||||||
|
/// assert_eq!(v, 0);
|
||||||
|
/// ```
|
||||||
#[unstable(feature = "ptr_mask", issue = "98290")]
|
#[unstable(feature = "ptr_mask", issue = "98290")]
|
||||||
#[must_use = "returns a new pointer rather than modifying its argument"]
|
#[must_use = "returns a new pointer rather than modifying its argument"]
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
|
|
|
@ -3667,7 +3667,8 @@ impl<T> [T] {
|
||||||
unsafe { self.align_to() }
|
unsafe { self.align_to() }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Split a slice into a prefix, a middle of aligned SIMD types, and a suffix.
|
/// Split a mutable slice into a mutable prefix, a middle of aligned SIMD types,
|
||||||
|
/// and a mutable suffix.
|
||||||
///
|
///
|
||||||
/// This is a safe wrapper around [`slice::align_to_mut`], so has the same weak
|
/// This is a safe wrapper around [`slice::align_to_mut`], so has the same weak
|
||||||
/// postconditions as that method. You're only assured that
|
/// postconditions as that method. You're only assured that
|
||||||
|
|
|
@ -22,7 +22,8 @@ macro_rules! tuple_impls {
|
||||||
maybe_tuple_doc! {
|
maybe_tuple_doc! {
|
||||||
$($T)+ @
|
$($T)+ @
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
impl<$($T:PartialEq),+> PartialEq for ($($T,)+)
|
#[rustc_const_unstable(feature = "const_cmp", issue = "92391")]
|
||||||
|
impl<$($T: ~const PartialEq),+> const PartialEq for ($($T,)+)
|
||||||
where
|
where
|
||||||
last_type!($($T,)+): ?Sized
|
last_type!($($T,)+): ?Sized
|
||||||
{
|
{
|
||||||
|
@ -40,7 +41,7 @@ macro_rules! tuple_impls {
|
||||||
maybe_tuple_doc! {
|
maybe_tuple_doc! {
|
||||||
$($T)+ @
|
$($T)+ @
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
impl<$($T:Eq),+> Eq for ($($T,)+)
|
impl<$($T: Eq),+> Eq for ($($T,)+)
|
||||||
where
|
where
|
||||||
last_type!($($T,)+): ?Sized
|
last_type!($($T,)+): ?Sized
|
||||||
{}
|
{}
|
||||||
|
@ -49,7 +50,8 @@ macro_rules! tuple_impls {
|
||||||
maybe_tuple_doc! {
|
maybe_tuple_doc! {
|
||||||
$($T)+ @
|
$($T)+ @
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
impl<$($T:PartialOrd + PartialEq),+> PartialOrd for ($($T,)+)
|
#[rustc_const_unstable(feature = "const_cmp", issue = "92391")]
|
||||||
|
impl<$($T: ~const PartialOrd + ~const PartialEq),+> const PartialOrd for ($($T,)+)
|
||||||
where
|
where
|
||||||
last_type!($($T,)+): ?Sized
|
last_type!($($T,)+): ?Sized
|
||||||
{
|
{
|
||||||
|
@ -79,7 +81,8 @@ macro_rules! tuple_impls {
|
||||||
maybe_tuple_doc! {
|
maybe_tuple_doc! {
|
||||||
$($T)+ @
|
$($T)+ @
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
impl<$($T:Ord),+> Ord for ($($T,)+)
|
#[rustc_const_unstable(feature = "const_cmp", issue = "92391")]
|
||||||
|
impl<$($T: ~const Ord),+> const Ord for ($($T,)+)
|
||||||
where
|
where
|
||||||
last_type!($($T,)+): ?Sized
|
last_type!($($T,)+): ?Sized
|
||||||
{
|
{
|
||||||
|
|
|
@ -64,7 +64,6 @@
|
||||||
#![feature(try_trait_v2)]
|
#![feature(try_trait_v2)]
|
||||||
#![feature(slice_internals)]
|
#![feature(slice_internals)]
|
||||||
#![feature(slice_partition_dedup)]
|
#![feature(slice_partition_dedup)]
|
||||||
#![feature(int_log)]
|
|
||||||
#![feature(iter_advance_by)]
|
#![feature(iter_advance_by)]
|
||||||
#![feature(iter_array_chunks)]
|
#![feature(iter_array_chunks)]
|
||||||
#![feature(iter_collect_into)]
|
#![feature(iter_collect_into)]
|
||||||
|
|
|
@ -118,6 +118,9 @@ ENV TARGETS=$TARGETS,armv7-unknown-linux-gnueabi
|
||||||
ENV TARGETS=$TARGETS,armv7-unknown-linux-musleabi
|
ENV TARGETS=$TARGETS,armv7-unknown-linux-musleabi
|
||||||
ENV TARGETS=$TARGETS,i686-unknown-freebsd
|
ENV TARGETS=$TARGETS,i686-unknown-freebsd
|
||||||
ENV TARGETS=$TARGETS,x86_64-unknown-none
|
ENV TARGETS=$TARGETS,x86_64-unknown-none
|
||||||
|
ENV TARGETS=$TARGETS,aarch64-unknown-uefi
|
||||||
|
ENV TARGETS=$TARGETS,i686-unknown-uefi
|
||||||
|
ENV TARGETS=$TARGETS,x86_64-unknown-uefi
|
||||||
|
|
||||||
# As per https://bugs.launchpad.net/ubuntu/+source/gcc-defaults/+bug/1300211
|
# As per https://bugs.launchpad.net/ubuntu/+source/gcc-defaults/+bug/1300211
|
||||||
# we need asm in the search path for gcc-8 (for gnux32) but not in the search path of the
|
# we need asm in the search path for gcc-8 (for gnux32) but not in the search path of the
|
||||||
|
|
|
@ -128,6 +128,7 @@ target | std | notes
|
||||||
[`aarch64-linux-android`](platform-support/android.md) | ✓ | ARM64 Android
|
[`aarch64-linux-android`](platform-support/android.md) | ✓ | ARM64 Android
|
||||||
`aarch64-unknown-none-softfloat` | * | Bare ARM64, softfloat
|
`aarch64-unknown-none-softfloat` | * | Bare ARM64, softfloat
|
||||||
`aarch64-unknown-none` | * | Bare ARM64, hardfloat
|
`aarch64-unknown-none` | * | Bare ARM64, hardfloat
|
||||||
|
[`aarch64-unknown-uefi`](platform-support/unknown-uefi.md) | * | ARM64 UEFI
|
||||||
[`arm-linux-androideabi`](platform-support/android.md) | ✓ | ARMv7 Android
|
[`arm-linux-androideabi`](platform-support/android.md) | ✓ | ARMv7 Android
|
||||||
`arm-unknown-linux-musleabi` | ✓ | ARMv6 Linux with MUSL
|
`arm-unknown-linux-musleabi` | ✓ | ARMv6 Linux with MUSL
|
||||||
`arm-unknown-linux-musleabihf` | ✓ | ARMv6 Linux with MUSL, hardfloat
|
`arm-unknown-linux-musleabihf` | ✓ | ARMv6 Linux with MUSL, hardfloat
|
||||||
|
@ -149,6 +150,7 @@ target | std | notes
|
||||||
[`i686-linux-android`](platform-support/android.md) | ✓ | 32-bit x86 Android
|
[`i686-linux-android`](platform-support/android.md) | ✓ | 32-bit x86 Android
|
||||||
`i686-unknown-freebsd` | ✓ | 32-bit FreeBSD
|
`i686-unknown-freebsd` | ✓ | 32-bit FreeBSD
|
||||||
`i686-unknown-linux-musl` | ✓ | 32-bit Linux with MUSL
|
`i686-unknown-linux-musl` | ✓ | 32-bit Linux with MUSL
|
||||||
|
[`i686-unknown-uefi`](platform-support/unknown-uefi.md) | * | 32-bit UEFI
|
||||||
`mips-unknown-linux-musl` | ✓ | MIPS Linux with MUSL
|
`mips-unknown-linux-musl` | ✓ | MIPS Linux with MUSL
|
||||||
`mips64-unknown-linux-muslabi64` | ✓ | MIPS64 Linux, n64 ABI, MUSL
|
`mips64-unknown-linux-muslabi64` | ✓ | MIPS64 Linux, n64 ABI, MUSL
|
||||||
`mips64el-unknown-linux-muslabi64` | ✓ | MIPS64 (LE) Linux, n64 ABI, MUSL
|
`mips64el-unknown-linux-muslabi64` | ✓ | MIPS64 (LE) Linux, n64 ABI, MUSL
|
||||||
|
@ -181,6 +183,7 @@ target | std | notes
|
||||||
`x86_64-unknown-linux-gnux32` | ✓ | 64-bit Linux (x32 ABI) (kernel 4.15, glibc 2.27)
|
`x86_64-unknown-linux-gnux32` | ✓ | 64-bit Linux (x32 ABI) (kernel 4.15, glibc 2.27)
|
||||||
[`x86_64-unknown-none`](platform-support/x86_64-unknown-none.md) | * | Freestanding/bare-metal x86_64, softfloat
|
[`x86_64-unknown-none`](platform-support/x86_64-unknown-none.md) | * | Freestanding/bare-metal x86_64, softfloat
|
||||||
`x86_64-unknown-redox` | ✓ | Redox OS
|
`x86_64-unknown-redox` | ✓ | Redox OS
|
||||||
|
[`x86_64-unknown-uefi`](platform-support/unknown-uefi.md) | * | 64-bit UEFI
|
||||||
|
|
||||||
[Fortanix ABI]: https://edp.fortanix.com/
|
[Fortanix ABI]: https://edp.fortanix.com/
|
||||||
|
|
||||||
|
@ -213,7 +216,6 @@ target | std | host | notes
|
||||||
[`aarch64-pc-windows-gnullvm`](platform-support/pc-windows-gnullvm.md) | ✓ | ✓ |
|
[`aarch64-pc-windows-gnullvm`](platform-support/pc-windows-gnullvm.md) | ✓ | ✓ |
|
||||||
`aarch64-unknown-freebsd` | ✓ | ✓ | ARM64 FreeBSD
|
`aarch64-unknown-freebsd` | ✓ | ✓ | ARM64 FreeBSD
|
||||||
`aarch64-unknown-hermit` | ✓ | | ARM64 HermitCore
|
`aarch64-unknown-hermit` | ✓ | | ARM64 HermitCore
|
||||||
[`aarch64-unknown-uefi`](platform-support/unknown-uefi.md) | * | | ARM64 UEFI
|
|
||||||
`aarch64-unknown-linux-gnu_ilp32` | ✓ | ✓ | ARM64 Linux (ILP32 ABI)
|
`aarch64-unknown-linux-gnu_ilp32` | ✓ | ✓ | ARM64 Linux (ILP32 ABI)
|
||||||
`aarch64-unknown-netbsd` | ✓ | ✓ |
|
`aarch64-unknown-netbsd` | ✓ | ✓ |
|
||||||
[`aarch64-unknown-openbsd`](platform-support/openbsd.md) | ✓ | ✓ | ARM64 OpenBSD
|
[`aarch64-unknown-openbsd`](platform-support/openbsd.md) | ✓ | ✓ | ARM64 OpenBSD
|
||||||
|
@ -252,7 +254,6 @@ target | std | host | notes
|
||||||
`i686-unknown-haiku` | ✓ | ✓ | 32-bit Haiku
|
`i686-unknown-haiku` | ✓ | ✓ | 32-bit Haiku
|
||||||
`i686-unknown-netbsd` | ✓ | ✓ | NetBSD/i386 with SSE2
|
`i686-unknown-netbsd` | ✓ | ✓ | NetBSD/i386 with SSE2
|
||||||
[`i686-unknown-openbsd`](platform-support/openbsd.md) | ✓ | ✓ | 32-bit OpenBSD
|
[`i686-unknown-openbsd`](platform-support/openbsd.md) | ✓ | ✓ | 32-bit OpenBSD
|
||||||
[`i686-unknown-uefi`](platform-support/unknown-uefi.md) | * | | 32-bit UEFI
|
|
||||||
`i686-uwp-windows-gnu` | ? | |
|
`i686-uwp-windows-gnu` | ? | |
|
||||||
`i686-uwp-windows-msvc` | ? | |
|
`i686-uwp-windows-msvc` | ? | |
|
||||||
`i686-wrs-vxworks` | ? | |
|
`i686-wrs-vxworks` | ? | |
|
||||||
|
@ -311,7 +312,6 @@ target | std | host | notes
|
||||||
`x86_64-unknown-l4re-uclibc` | ? | |
|
`x86_64-unknown-l4re-uclibc` | ? | |
|
||||||
`x86_64-unknown-none-linuxkernel` | * | | Linux kernel modules
|
`x86_64-unknown-none-linuxkernel` | * | | Linux kernel modules
|
||||||
[`x86_64-unknown-openbsd`](platform-support/openbsd.md) | ✓ | ✓ | 64-bit OpenBSD
|
[`x86_64-unknown-openbsd`](platform-support/openbsd.md) | ✓ | ✓ | 64-bit OpenBSD
|
||||||
[`x86_64-unknown-uefi`](platform-support/unknown-uefi.md) | * | | 64-bit UEFI
|
|
||||||
`x86_64-uwp-windows-gnu` | ✓ | |
|
`x86_64-uwp-windows-gnu` | ✓ | |
|
||||||
`x86_64-uwp-windows-msvc` | ✓ | |
|
`x86_64-uwp-windows-msvc` | ✓ | |
|
||||||
`x86_64-wrs-vxworks` | ? | |
|
`x86_64-wrs-vxworks` | ? | |
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
# `*-unknown-uefi`
|
# `*-unknown-uefi`
|
||||||
|
|
||||||
**Tier: 3**
|
**Tier: 2**
|
||||||
|
|
||||||
Unified Extensible Firmware Interface (UEFI) targets for application, driver,
|
Unified Extensible Firmware Interface (UEFI) targets for application, driver,
|
||||||
and core UEFI binaries.
|
and core UEFI binaries.
|
||||||
|
@ -72,28 +72,14 @@ target = ["x86_64-unknown-uefi"]
|
||||||
|
|
||||||
## Building Rust programs
|
## Building Rust programs
|
||||||
|
|
||||||
Rust does not yet ship pre-compiled artifacts for this target. To compile for
|
Starting with Rust 1.67, precompiled artifacts are provided via
|
||||||
this target, you will either need to build Rust with the target enabled (see
|
`rustup`. For example, to use `x86_64-unknown-uefi`:
|
||||||
"Building rust for UEFI targets" above), or build your own copy of `core` by
|
|
||||||
using `build-std`, `cargo-buildx`, or similar.
|
|
||||||
|
|
||||||
A native build with the unstable `build-std`-feature can be achieved via:
|
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
cargo +nightly build \
|
# install cross-compile toolchain
|
||||||
-Zbuild-std=core,compiler_builtins \
|
rustup target add x86_64-unknown-uefi
|
||||||
-Zbuild-std-features=compiler-builtins-mem \
|
# target flag may be used with any cargo or rustc command
|
||||||
--target x86_64-unknown-uefi
|
cargo build --target x86_64-unknown-uefi
|
||||||
```
|
|
||||||
|
|
||||||
Alternatively, you can install `cargo-xbuild` via
|
|
||||||
`cargo install --force cargo-xbuild` and build for the UEFI targets via:
|
|
||||||
|
|
||||||
```sh
|
|
||||||
cargo \
|
|
||||||
+nightly \
|
|
||||||
xbuild \
|
|
||||||
--target x86_64-unknown-uefi
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## Testing
|
## Testing
|
||||||
|
@ -167,18 +153,10 @@ The following code is a valid UEFI application returning immediately upon
|
||||||
execution with an exit code of 0. A panic handler is provided. This is executed
|
execution with an exit code of 0. A panic handler is provided. This is executed
|
||||||
by rust on panic. For simplicity, we simply end up in an infinite loop.
|
by rust on panic. For simplicity, we simply end up in an infinite loop.
|
||||||
|
|
||||||
Note that as of rust-1.31.0, all features used here are stabilized. No unstable
|
|
||||||
features are required, nor do we rely on nightly compilers. However, if you do
|
|
||||||
not compile rustc for the UEFI targets, you need a nightly compiler to support
|
|
||||||
the `-Z build-std` flag.
|
|
||||||
|
|
||||||
This example can be compiled as binary crate via `cargo`:
|
This example can be compiled as binary crate via `cargo`:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
cargo +nightly build \
|
cargo build --target x86_64-unknown-uefi
|
||||||
-Zbuild-std=core,compiler_builtins \
|
|
||||||
-Zbuild-std-features=compiler-builtins-mem \
|
|
||||||
--target x86_64-unknown-uefi
|
|
||||||
```
|
```
|
||||||
|
|
||||||
```rust,ignore (platform-specific,eh-personality-is-unstable)
|
```rust,ignore (platform-specific,eh-personality-is-unstable)
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
#![feature(rustc_attrs)]
|
#![feature(rustc_attrs)]
|
||||||
|
|
||||||
#[rustc_dummy = b"ffi.rs"] //~ ERROR non-ASCII character in byte constant
|
#[rustc_dummy = b"ffi.rs"] //~ ERROR non-ASCII character in byte string literal
|
||||||
fn main() {}
|
fn main() {}
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
error: non-ASCII character in byte constant
|
error: non-ASCII character in byte string literal
|
||||||
--> $DIR/key-value-non-ascii.rs:3:19
|
--> $DIR/key-value-non-ascii.rs:3:19
|
||||||
|
|
|
|
||||||
LL | #[rustc_dummy = b"ffi.rs"]
|
LL | #[rustc_dummy = b"ffi.rs"]
|
||||||
| ^ byte constant must be ASCII
|
| ^ must be ASCII
|
||||||
|
|
|
|
||||||
help: if you meant to use the UTF-8 encoding of 'ffi', use \xHH escapes
|
help: if you meant to use the UTF-8 encoding of 'ffi', use \xHH escapes
|
||||||
|
|
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// build-pass
|
// check-pass
|
||||||
|
|
||||||
#![feature(const_fn_trait_ref_impls)]
|
#![feature(const_fn_trait_ref_impls)]
|
||||||
#![feature(fn_traits)]
|
#![feature(fn_traits)]
|
||||||
|
@ -60,21 +60,18 @@ const fn test(i: i32) -> i32 {
|
||||||
i + 1
|
i + 1
|
||||||
}
|
}
|
||||||
|
|
||||||
const fn main() {
|
fn main() {
|
||||||
const fn one() -> i32 {
|
const fn one() -> i32 {
|
||||||
1
|
1
|
||||||
};
|
};
|
||||||
const fn two() -> i32 {
|
const fn two() -> i32 {
|
||||||
2
|
2
|
||||||
};
|
};
|
||||||
|
const _: () = {
|
||||||
|
let test_one = test_fn(one);
|
||||||
|
assert!(test_one == (1, 1, 1));
|
||||||
|
|
||||||
// FIXME(const_cmp_tuple)
|
let test_two = test_fn_mut(two);
|
||||||
let test_one = test_fn(one);
|
assert!(test_two == (2, 2));
|
||||||
assert!(test_one.0 == 1);
|
};
|
||||||
assert!(test_one.1 == 1);
|
|
||||||
assert!(test_one.2 == 1);
|
|
||||||
|
|
||||||
let test_two = test_fn_mut(two);
|
|
||||||
assert!(test_two.0 == 1);
|
|
||||||
assert!(test_two.1 == 1);
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,6 +7,6 @@ pub fn main() {
|
||||||
b'\x0Z'; //~ ERROR invalid character in numeric character escape: `Z`
|
b'\x0Z'; //~ ERROR invalid character in numeric character escape: `Z`
|
||||||
b' '; //~ ERROR byte constant must be escaped
|
b' '; //~ ERROR byte constant must be escaped
|
||||||
b'''; //~ ERROR byte constant must be escaped
|
b'''; //~ ERROR byte constant must be escaped
|
||||||
b'é'; //~ ERROR non-ASCII character in byte constant
|
b'é'; //~ ERROR non-ASCII character in byte literal
|
||||||
b'a //~ ERROR unterminated byte constant [E0763]
|
b'a //~ ERROR unterminated byte constant [E0763]
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,11 +32,11 @@ error: byte constant must be escaped: `'`
|
||||||
LL | b''';
|
LL | b''';
|
||||||
| ^ help: escape the character: `\'`
|
| ^ help: escape the character: `\'`
|
||||||
|
|
||||||
error: non-ASCII character in byte constant
|
error: non-ASCII character in byte literal
|
||||||
--> $DIR/byte-literals.rs:10:7
|
--> $DIR/byte-literals.rs:10:7
|
||||||
|
|
|
|
||||||
LL | b'é';
|
LL | b'é';
|
||||||
| ^ byte constant must be ASCII
|
| ^ must be ASCII
|
||||||
|
|
|
|
||||||
help: if you meant to use the unicode code point for 'é', use a \xHH escape
|
help: if you meant to use the unicode code point for 'é', use a \xHH escape
|
||||||
|
|
|
|
||||||
|
|
|
@ -3,7 +3,7 @@ static FOO: &'static [u8] = b"\f"; //~ ERROR unknown byte escape
|
||||||
pub fn main() {
|
pub fn main() {
|
||||||
b"\f"; //~ ERROR unknown byte escape
|
b"\f"; //~ ERROR unknown byte escape
|
||||||
b"\x0Z"; //~ ERROR invalid character in numeric character escape: `Z`
|
b"\x0Z"; //~ ERROR invalid character in numeric character escape: `Z`
|
||||||
b"é"; //~ ERROR non-ASCII character in byte constant
|
b"é"; //~ ERROR non-ASCII character in byte string literal
|
||||||
br##"é"##; //~ ERROR raw byte string must be ASCII
|
br##"é"##; //~ ERROR non-ASCII character in raw byte string literal
|
||||||
b"a //~ ERROR unterminated double quote byte string
|
b"a //~ ERROR unterminated double quote byte string
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,18 +20,18 @@ error: invalid character in numeric character escape: `Z`
|
||||||
LL | b"\x0Z";
|
LL | b"\x0Z";
|
||||||
| ^ invalid character in numeric character escape
|
| ^ invalid character in numeric character escape
|
||||||
|
|
||||||
error: non-ASCII character in byte constant
|
error: non-ASCII character in byte string literal
|
||||||
--> $DIR/byte-string-literals.rs:6:7
|
--> $DIR/byte-string-literals.rs:6:7
|
||||||
|
|
|
|
||||||
LL | b"é";
|
LL | b"é";
|
||||||
| ^ byte constant must be ASCII
|
| ^ must be ASCII
|
||||||
|
|
|
|
||||||
help: if you meant to use the unicode code point for 'é', use a \xHH escape
|
help: if you meant to use the unicode code point for 'é', use a \xHH escape
|
||||||
|
|
|
|
||||||
LL | b"\xE9";
|
LL | b"\xE9";
|
||||||
| ~~~~
|
| ~~~~
|
||||||
|
|
||||||
error: raw byte string must be ASCII
|
error: non-ASCII character in raw byte string literal
|
||||||
--> $DIR/byte-string-literals.rs:7:10
|
--> $DIR/byte-string-literals.rs:7:10
|
||||||
|
|
|
|
||||||
LL | br##"é"##;
|
LL | br##"é"##;
|
||||||
|
|
|
@ -2,6 +2,6 @@
|
||||||
|
|
||||||
pub fn main() {
|
pub fn main() {
|
||||||
br"a
"; //~ ERROR bare CR not allowed in raw string
|
br"a
"; //~ ERROR bare CR not allowed in raw string
|
||||||
br"é"; //~ ERROR raw byte string must be ASCII
|
br"é"; //~ ERROR non-ASCII character in raw byte string literal
|
||||||
br##~"a"~##; //~ ERROR only `#` is allowed in raw string delimitation
|
br##~"a"~##; //~ ERROR only `#` is allowed in raw string delimitation
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,7 +4,7 @@ error: bare CR not allowed in raw string
|
||||||
LL | br"a
";
|
LL | br"a
";
|
||||||
| ^
|
| ^
|
||||||
|
|
||||||
error: raw byte string must be ASCII
|
error: non-ASCII character in raw byte string literal
|
||||||
--> $DIR/raw-byte-string-literals.rs:5:8
|
--> $DIR/raw-byte-string-literals.rs:5:8
|
||||||
|
|
|
|
||||||
LL | br"é";
|
LL | br"é";
|
||||||
|
|
|
@ -14,15 +14,15 @@ fn main() {
|
||||||
println!("{:?}", r##"/* } if isAdmin begin admins only "##);
|
println!("{:?}", r##"/* } if isAdmin begin admins only "##);
|
||||||
//~^ ERROR unicode codepoint changing visible direction of text present in literal
|
//~^ ERROR unicode codepoint changing visible direction of text present in literal
|
||||||
println!("{:?}", b"/* } if isAdmin begin admins only ");
|
println!("{:?}", b"/* } if isAdmin begin admins only ");
|
||||||
//~^ ERROR non-ASCII character in byte constant
|
//~^ ERROR non-ASCII character in byte string literal
|
||||||
//~| ERROR non-ASCII character in byte constant
|
//~| ERROR non-ASCII character in byte string literal
|
||||||
//~| ERROR non-ASCII character in byte constant
|
//~| ERROR non-ASCII character in byte string literal
|
||||||
//~| ERROR non-ASCII character in byte constant
|
//~| ERROR non-ASCII character in byte string literal
|
||||||
println!("{:?}", br##"/* } if isAdmin begin admins only "##);
|
println!("{:?}", br##"/* } if isAdmin begin admins only "##);
|
||||||
//~^ ERROR raw byte string must be ASCII
|
//~^ ERROR non-ASCII character in raw byte string literal
|
||||||
//~| ERROR raw byte string must be ASCII
|
//~| ERROR non-ASCII character in raw byte string literal
|
||||||
//~| ERROR raw byte string must be ASCII
|
//~| ERROR non-ASCII character in raw byte string literal
|
||||||
//~| ERROR raw byte string must be ASCII
|
//~| ERROR non-ASCII character in raw byte string literal
|
||||||
println!("{:?}", '');
|
println!("{:?}", '');
|
||||||
//~^ ERROR unicode codepoint changing visible direction of text present in literal
|
//~^ ERROR unicode codepoint changing visible direction of text present in literal
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,69 +14,69 @@ LL | println!("{:?}", b"us\u{202B}e\u{202A}r");
|
||||||
|
|
|
|
||||||
= help: unicode escape sequences cannot be used as a byte or in a byte string
|
= help: unicode escape sequences cannot be used as a byte or in a byte string
|
||||||
|
|
||||||
error: non-ASCII character in byte constant
|
error: non-ASCII character in byte string literal
|
||||||
--> $DIR/unicode-control-codepoints.rs:16:26
|
--> $DIR/unicode-control-codepoints.rs:16:26
|
||||||
|
|
|
|
||||||
LL | println!("{:?}", b"/* } if isAdmin begin admins only ");
|
LL | println!("{:?}", b"/* } if isAdmin begin admins only ");
|
||||||
| ^ byte constant must be ASCII but is '\u{202e}'
|
| ^ must be ASCII but is '\u{202e}'
|
||||||
|
|
|
|
||||||
help: if you meant to use the UTF-8 encoding of '\u{202e}', use \xHH escapes
|
help: if you meant to use the UTF-8 encoding of '\u{202e}', use \xHH escapes
|
||||||
|
|
|
|
||||||
LL | println!("{:?}", b"/*\xE2\x80\xAE } if isAdmin begin admins only ");
|
LL | println!("{:?}", b"/*\xE2\x80\xAE } if isAdmin begin admins only ");
|
||||||
| ~~~~~~~~~~~~
|
| ~~~~~~~~~~~~
|
||||||
|
|
||||||
error: non-ASCII character in byte constant
|
error: non-ASCII character in byte string literal
|
||||||
--> $DIR/unicode-control-codepoints.rs:16:30
|
--> $DIR/unicode-control-codepoints.rs:16:30
|
||||||
|
|
|
|
||||||
LL | println!("{:?}", b"/* } if isAdmin begin admins only ");
|
LL | println!("{:?}", b"/* } if isAdmin begin admins only ");
|
||||||
| ^ byte constant must be ASCII but is '\u{2066}'
|
| ^ must be ASCII but is '\u{2066}'
|
||||||
|
|
|
|
||||||
help: if you meant to use the UTF-8 encoding of '\u{2066}', use \xHH escapes
|
help: if you meant to use the UTF-8 encoding of '\u{2066}', use \xHH escapes
|
||||||
|
|
|
|
||||||
LL | println!("{:?}", b"/* } \xE2\x81\xA6if isAdmin begin admins only ");
|
LL | println!("{:?}", b"/* } \xE2\x81\xA6if isAdmin begin admins only ");
|
||||||
| ~~~~~~~~~~~~
|
| ~~~~~~~~~~~~
|
||||||
|
|
||||||
error: non-ASCII character in byte constant
|
error: non-ASCII character in byte string literal
|
||||||
--> $DIR/unicode-control-codepoints.rs:16:41
|
--> $DIR/unicode-control-codepoints.rs:16:41
|
||||||
|
|
|
|
||||||
LL | println!("{:?}", b"/* } if isAdmin begin admins only ");
|
LL | println!("{:?}", b"/* } if isAdmin begin admins only ");
|
||||||
| ^ byte constant must be ASCII but is '\u{2069}'
|
| ^ must be ASCII but is '\u{2069}'
|
||||||
|
|
|
|
||||||
help: if you meant to use the UTF-8 encoding of '\u{2069}', use \xHH escapes
|
help: if you meant to use the UTF-8 encoding of '\u{2069}', use \xHH escapes
|
||||||
|
|
|
|
||||||
LL | println!("{:?}", b"/* } if isAdmin\xE2\x81\xA9 begin admins only ");
|
LL | println!("{:?}", b"/* } if isAdmin\xE2\x81\xA9 begin admins only ");
|
||||||
| ~~~~~~~~~~~~
|
| ~~~~~~~~~~~~
|
||||||
|
|
||||||
error: non-ASCII character in byte constant
|
error: non-ASCII character in byte string literal
|
||||||
--> $DIR/unicode-control-codepoints.rs:16:43
|
--> $DIR/unicode-control-codepoints.rs:16:43
|
||||||
|
|
|
|
||||||
LL | println!("{:?}", b"/* } if isAdmin begin admins only ");
|
LL | println!("{:?}", b"/* } if isAdmin begin admins only ");
|
||||||
| ^ byte constant must be ASCII but is '\u{2066}'
|
| ^ must be ASCII but is '\u{2066}'
|
||||||
|
|
|
|
||||||
help: if you meant to use the UTF-8 encoding of '\u{2066}', use \xHH escapes
|
help: if you meant to use the UTF-8 encoding of '\u{2066}', use \xHH escapes
|
||||||
|
|
|
|
||||||
LL | println!("{:?}", b"/* } if isAdmin \xE2\x81\xA6 begin admins only ");
|
LL | println!("{:?}", b"/* } if isAdmin \xE2\x81\xA6 begin admins only ");
|
||||||
| ~~~~~~~~~~~~
|
| ~~~~~~~~~~~~
|
||||||
|
|
||||||
error: raw byte string must be ASCII
|
error: non-ASCII character in raw byte string literal
|
||||||
--> $DIR/unicode-control-codepoints.rs:21:29
|
--> $DIR/unicode-control-codepoints.rs:21:29
|
||||||
|
|
|
|
||||||
LL | println!("{:?}", br##"/* } if isAdmin begin admins only "##);
|
LL | println!("{:?}", br##"/* } if isAdmin begin admins only "##);
|
||||||
| ^ must be ASCII but is '\u{202e}'
|
| ^ must be ASCII but is '\u{202e}'
|
||||||
|
|
||||||
error: raw byte string must be ASCII
|
error: non-ASCII character in raw byte string literal
|
||||||
--> $DIR/unicode-control-codepoints.rs:21:33
|
--> $DIR/unicode-control-codepoints.rs:21:33
|
||||||
|
|
|
|
||||||
LL | println!("{:?}", br##"/* } if isAdmin begin admins only "##);
|
LL | println!("{:?}", br##"/* } if isAdmin begin admins only "##);
|
||||||
| ^ must be ASCII but is '\u{2066}'
|
| ^ must be ASCII but is '\u{2066}'
|
||||||
|
|
||||||
error: raw byte string must be ASCII
|
error: non-ASCII character in raw byte string literal
|
||||||
--> $DIR/unicode-control-codepoints.rs:21:44
|
--> $DIR/unicode-control-codepoints.rs:21:44
|
||||||
|
|
|
|
||||||
LL | println!("{:?}", br##"/* } if isAdmin begin admins only "##);
|
LL | println!("{:?}", br##"/* } if isAdmin begin admins only "##);
|
||||||
| ^ must be ASCII but is '\u{2069}'
|
| ^ must be ASCII but is '\u{2069}'
|
||||||
|
|
||||||
error: raw byte string must be ASCII
|
error: non-ASCII character in raw byte string literal
|
||||||
--> $DIR/unicode-control-codepoints.rs:21:46
|
--> $DIR/unicode-control-codepoints.rs:21:46
|
||||||
|
|
|
|
||||||
LL | println!("{:?}", br##"/* } if isAdmin begin admins only "##);
|
LL | println!("{:?}", br##"/* } if isAdmin begin admins only "##);
|
||||||
|
|
|
@ -2,17 +2,17 @@
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
b'µ';
|
b'µ';
|
||||||
//~^ ERROR: non-ASCII character in byte constant
|
//~^ ERROR: non-ASCII character in byte literal
|
||||||
//~| HELP: if you meant to use the unicode code point for 'µ', use a \xHH escape
|
//~| HELP: if you meant to use the unicode code point for 'µ', use a \xHH escape
|
||||||
//~| NOTE: byte constant must be ASCII
|
//~| NOTE: must be ASCII
|
||||||
|
|
||||||
b'字';
|
b'字';
|
||||||
//~^ ERROR: non-ASCII character in byte constant
|
//~^ ERROR: non-ASCII character in byte literal
|
||||||
//~| NOTE: this multibyte character does not fit into a single byte
|
//~| NOTE: this multibyte character does not fit into a single byte
|
||||||
//~| NOTE: byte constant must be ASCII
|
//~| NOTE: must be ASCII
|
||||||
|
|
||||||
b"字";
|
b"字";
|
||||||
//~^ ERROR: non-ASCII character in byte constant
|
//~^ ERROR: non-ASCII character in byte string literal
|
||||||
//~| HELP: if you meant to use the UTF-8 encoding of '字', use \xHH escapes
|
//~| HELP: if you meant to use the UTF-8 encoding of '字', use \xHH escapes
|
||||||
//~| NOTE: byte constant must be ASCII
|
//~| NOTE: must be ASCII
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,28 +1,28 @@
|
||||||
error: non-ASCII character in byte constant
|
error: non-ASCII character in byte literal
|
||||||
--> $DIR/multibyte-escapes.rs:4:7
|
--> $DIR/multibyte-escapes.rs:4:7
|
||||||
|
|
|
|
||||||
LL | b'µ';
|
LL | b'µ';
|
||||||
| ^ byte constant must be ASCII
|
| ^ must be ASCII
|
||||||
|
|
|
|
||||||
help: if you meant to use the unicode code point for 'µ', use a \xHH escape
|
help: if you meant to use the unicode code point for 'µ', use a \xHH escape
|
||||||
|
|
|
|
||||||
LL | b'\xB5';
|
LL | b'\xB5';
|
||||||
| ~~~~
|
| ~~~~
|
||||||
|
|
||||||
error: non-ASCII character in byte constant
|
error: non-ASCII character in byte literal
|
||||||
--> $DIR/multibyte-escapes.rs:9:7
|
--> $DIR/multibyte-escapes.rs:9:7
|
||||||
|
|
|
|
||||||
LL | b'字';
|
LL | b'字';
|
||||||
| ^^
|
| ^^
|
||||||
| |
|
| |
|
||||||
| byte constant must be ASCII
|
| must be ASCII
|
||||||
| this multibyte character does not fit into a single byte
|
| this multibyte character does not fit into a single byte
|
||||||
|
|
||||||
error: non-ASCII character in byte constant
|
error: non-ASCII character in byte string literal
|
||||||
--> $DIR/multibyte-escapes.rs:14:7
|
--> $DIR/multibyte-escapes.rs:14:7
|
||||||
|
|
|
|
||||||
LL | b"字";
|
LL | b"字";
|
||||||
| ^^ byte constant must be ASCII
|
| ^^ must be ASCII
|
||||||
|
|
|
|
||||||
help: if you meant to use the UTF-8 encoding of '字', use \xHH escapes
|
help: if you meant to use the UTF-8 encoding of '字', use \xHH escapes
|
||||||
|
|
|
|
||||||
|
|
|
@ -60,6 +60,7 @@ static TARGETS: &[&str] = &[
|
||||||
"aarch64-unknown-none",
|
"aarch64-unknown-none",
|
||||||
"aarch64-unknown-none-softfloat",
|
"aarch64-unknown-none-softfloat",
|
||||||
"aarch64-unknown-redox",
|
"aarch64-unknown-redox",
|
||||||
|
"aarch64-unknown-uefi",
|
||||||
"arm-linux-androideabi",
|
"arm-linux-androideabi",
|
||||||
"arm-unknown-linux-gnueabi",
|
"arm-unknown-linux-gnueabi",
|
||||||
"arm-unknown-linux-gnueabihf",
|
"arm-unknown-linux-gnueabihf",
|
||||||
|
@ -95,6 +96,7 @@ static TARGETS: &[&str] = &[
|
||||||
"i686-unknown-freebsd",
|
"i686-unknown-freebsd",
|
||||||
"i686-unknown-linux-gnu",
|
"i686-unknown-linux-gnu",
|
||||||
"i686-unknown-linux-musl",
|
"i686-unknown-linux-musl",
|
||||||
|
"i686-unknown-uefi",
|
||||||
"m68k-unknown-linux-gnu",
|
"m68k-unknown-linux-gnu",
|
||||||
"mips-unknown-linux-gnu",
|
"mips-unknown-linux-gnu",
|
||||||
"mips-unknown-linux-musl",
|
"mips-unknown-linux-musl",
|
||||||
|
@ -151,6 +153,7 @@ static TARGETS: &[&str] = &[
|
||||||
"x86_64-unknown-none",
|
"x86_64-unknown-none",
|
||||||
"x86_64-unknown-redox",
|
"x86_64-unknown-redox",
|
||||||
"x86_64-unknown-hermit",
|
"x86_64-unknown-hermit",
|
||||||
|
"x86_64-unknown-uefi",
|
||||||
];
|
];
|
||||||
|
|
||||||
/// This allows the manifest to contain rust-docs for hosts that don't build
|
/// This allows the manifest to contain rust-docs for hosts that don't build
|
||||||
|
|
|
@ -55,30 +55,6 @@ const LINKCHECK_EXCEPTIONS: &[(&str, &[&str])] = &[
|
||||||
|
|
||||||
#[rustfmt::skip]
|
#[rustfmt::skip]
|
||||||
const INTRA_DOC_LINK_EXCEPTIONS: &[(&str, &[&str])] = &[
|
const INTRA_DOC_LINK_EXCEPTIONS: &[(&str, &[&str])] = &[
|
||||||
// This will never have links that are not in other pages.
|
|
||||||
// To avoid repeating the exceptions twice, an empty list means all broken links are allowed.
|
|
||||||
("reference/print.html", &[]),
|
|
||||||
// All the reference 'links' are actually ENBF highlighted as code
|
|
||||||
("reference/comments.html", &[
|
|
||||||
"/</code> <code>!",
|
|
||||||
"*</code> <code>!",
|
|
||||||
]),
|
|
||||||
("reference/identifiers.html", &[
|
|
||||||
"a</code>-<code>z</code> <code>A</code>-<code>Z",
|
|
||||||
"a</code>-<code>z</code> <code>A</code>-<code>Z</code> <code>0</code>-<code>9</code> <code>_",
|
|
||||||
"a</code>-<code>z</code> <code>A</code>-<code>Z</code>] [<code>a</code>-<code>z</code> <code>A</code>-<code>Z</code> <code>0</code>-<code>9</code> <code>_",
|
|
||||||
]),
|
|
||||||
("reference/tokens.html", &[
|
|
||||||
"0</code>-<code>1",
|
|
||||||
"0</code>-<code>7",
|
|
||||||
"0</code>-<code>9",
|
|
||||||
"0</code>-<code>9",
|
|
||||||
"0</code>-<code>9</code> <code>a</code>-<code>f</code> <code>A</code>-<code>F",
|
|
||||||
]),
|
|
||||||
("reference/notation.html", &[
|
|
||||||
"b</code> <code>B",
|
|
||||||
"a</code>-<code>z",
|
|
||||||
]),
|
|
||||||
// This is being used in the sense of 'inclusive range', not a markdown link
|
// This is being used in the sense of 'inclusive range', not a markdown link
|
||||||
("core/ops/struct.RangeInclusive.html", &["begin</code>, <code>end"]),
|
("core/ops/struct.RangeInclusive.html", &["begin</code>, <code>end"]),
|
||||||
("std/ops/struct.RangeInclusive.html", &["begin</code>, <code>end"]),
|
("std/ops/struct.RangeInclusive.html", &["begin</code>, <code>end"]),
|
||||||
|
@ -365,6 +341,33 @@ impl Checker {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
self.check_intra_doc_links(file, &pretty_path, &source, report);
|
||||||
|
|
||||||
|
// we don't need the source anymore,
|
||||||
|
// so drop to reduce memory-usage
|
||||||
|
match self.cache.get_mut(&pretty_path).unwrap() {
|
||||||
|
FileEntry::HtmlFile { source, .. } => *source = Rc::new(String::new()),
|
||||||
|
_ => unreachable!("must be html file"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn check_intra_doc_links(
|
||||||
|
&mut self,
|
||||||
|
file: &Path,
|
||||||
|
pretty_path: &str,
|
||||||
|
source: &str,
|
||||||
|
report: &mut Report,
|
||||||
|
) {
|
||||||
|
let relative = file.strip_prefix(&self.root).expect("should always be relative to root");
|
||||||
|
// Don't check the reference. It has several legitimate things that
|
||||||
|
// look like [<code>…</code>]. The reference has its own broken link
|
||||||
|
// checker in its CI which handles this using pulldown_cmark.
|
||||||
|
//
|
||||||
|
// This checks both the end of the root (when checking just the
|
||||||
|
// reference directory) or the beginning (when checking all docs).
|
||||||
|
if self.root.ends_with("reference") || relative.starts_with("reference") {
|
||||||
|
return;
|
||||||
|
}
|
||||||
// Search for intra-doc links that rustdoc didn't warn about
|
// Search for intra-doc links that rustdoc didn't warn about
|
||||||
// FIXME(#77199, 77200) Rustdoc should just warn about these directly.
|
// FIXME(#77199, 77200) Rustdoc should just warn about these directly.
|
||||||
// NOTE: only looks at one line at a time; in practice this should find most links
|
// NOTE: only looks at one line at a time; in practice this should find most links
|
||||||
|
@ -379,12 +382,6 @@ impl Checker {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// we don't need the source anymore,
|
|
||||||
// so drop to reduce memory-usage
|
|
||||||
match self.cache.get_mut(&pretty_path).unwrap() {
|
|
||||||
FileEntry::HtmlFile { source, .. } => *source = Rc::new(String::new()),
|
|
||||||
_ => unreachable!("must be html file"),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Load a file from disk, or from the cache if available.
|
/// Load a file from disk, or from the cache if available.
|
||||||
|
|
|
@ -3,7 +3,6 @@
|
||||||
#![feature(never_type)]
|
#![feature(never_type)]
|
||||||
#![feature(try_blocks)]
|
#![feature(try_blocks)]
|
||||||
#![feature(io_error_more)]
|
#![feature(io_error_more)]
|
||||||
#![feature(int_log)]
|
|
||||||
#![feature(variant_count)]
|
#![feature(variant_count)]
|
||||||
#![feature(yeet_expr)]
|
#![feature(yeet_expr)]
|
||||||
#![feature(is_some_and)]
|
#![feature(is_some_and)]
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
//@compile-flags: -Coverflow-checks=off
|
//@compile-flags: -Coverflow-checks=off
|
||||||
#![feature(int_log)]
|
|
||||||
#![allow(arithmetic_overflow)]
|
#![allow(arithmetic_overflow)]
|
||||||
|
|
||||||
pub fn main() {
|
pub fn main() {
|
||||||
|
|
|
@ -5,9 +5,7 @@
|
||||||
mod block;
|
mod block;
|
||||||
|
|
||||||
use rowan::Direction;
|
use rowan::Direction;
|
||||||
use rustc_lexer::unescape::{
|
use rustc_lexer::unescape::{self, unescape_byte, unescape_char, unescape_literal, Mode};
|
||||||
self, unescape_byte, unescape_byte_literal, unescape_char, unescape_literal, Mode,
|
|
||||||
};
|
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
algo,
|
algo,
|
||||||
|
@ -143,7 +141,7 @@ fn validate_literal(literal: ast::Literal, acc: &mut Vec<SyntaxError>) {
|
||||||
ast::LiteralKind::ByteString(s) => {
|
ast::LiteralKind::ByteString(s) => {
|
||||||
if !s.is_raw() {
|
if !s.is_raw() {
|
||||||
if let Some(without_quotes) = unquote(text, 2, '"') {
|
if let Some(without_quotes) = unquote(text, 2, '"') {
|
||||||
unescape_byte_literal(without_quotes, Mode::ByteStr, &mut |range, char| {
|
unescape_literal(without_quotes, Mode::ByteStr, &mut |range, char| {
|
||||||
if let Err(err) = char {
|
if let Err(err) = char {
|
||||||
push_err(2, (range.start, err));
|
push_err(2, (range.start, err));
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue