1
Fork 0

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:
bors 2022-11-09 16:54:02 +00:00
commit c71658706f
36 changed files with 340 additions and 366 deletions

View file

@ -2,12 +2,9 @@
use crate::ast::{self, Lit, LitKind};
use crate::token::{self, Token};
use rustc_lexer::unescape::{unescape_byte, unescape_char};
use rustc_lexer::unescape::{unescape_byte_literal, unescape_literal, Mode};
use rustc_lexer::unescape::{byte_from_char, unescape_byte, unescape_char, unescape_literal, Mode};
use rustc_span::symbol::{kw, sym, Symbol};
use rustc_span::Span;
use std::ascii;
pub enum LitError {
@ -109,13 +106,11 @@ impl LitKind {
let s = symbol.as_str();
let mut buf = Vec::with_capacity(s.len());
let mut error = Ok(());
unescape_byte_literal(&s, Mode::ByteStr, &mut |_, unescaped_byte| {
match unescaped_byte {
Ok(c) => buf.push(c),
Err(err) => {
if err.is_fatal() {
error = Err(LitError::LexerError);
}
unescape_literal(&s, Mode::ByteStr, &mut |_, c| match c {
Ok(c) => buf.push(byte_from_char(c)),
Err(err) => {
if err.is_fatal() {
error = Err(LitError::LexerError);
}
}
});
@ -127,13 +122,11 @@ impl LitKind {
let bytes = if s.contains('\r') {
let mut buf = Vec::with_capacity(s.len());
let mut error = Ok(());
unescape_byte_literal(&s, Mode::RawByteStr, &mut |_, unescaped_byte| {
match unescaped_byte {
Ok(c) => buf.push(c),
Err(err) => {
if err.is_fatal() {
error = Err(LitError::LexerError);
}
unescape_literal(&s, Mode::RawByteStr, &mut |_, c| match c {
Ok(c) => buf.push(byte_from_char(c)),
Err(err) => {
if err.is_fatal() {
error = Err(LitError::LexerError);
}
}
});

View file

@ -205,13 +205,13 @@ pub enum RawStrError {
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)]
pub enum Base {
/// Literal starts with "0b".
Binary,
Binary = 2,
/// Literal starts with "0o".
Octal,
/// Literal starts with "0x".
Hexadecimal,
Octal = 8,
/// 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",

View file

@ -52,10 +52,8 @@ pub enum EscapeError {
/// Unicode escape code in byte literal.
UnicodeEscapeInByte,
/// Non-ascii character in byte literal.
/// Non-ascii character in byte literal, byte string literal, or raw byte string literal.
NonAsciiCharInByte,
/// Non-ascii character in byte string literal.
NonAsciiCharInByteString,
/// After a line ending with '\', the next line contains whitespace
/// characters that are not skipped.
@ -78,54 +76,33 @@ impl EscapeError {
/// Takes a contents of a literal (without quotes) and produces a
/// sequence of escaped characters or errors.
/// 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
F: FnMut(Range<usize>, Result<char, EscapeError>),
{
match mode {
Mode::Char | Mode::Byte => {
let mut chars = literal_text.chars();
let result = unescape_char_or_byte(&mut chars, mode);
// The Chars iterator moved forward.
callback(0..(literal_text.len() - chars.as_str().len()), result);
let mut chars = src.chars();
let res = unescape_char_or_byte(&mut chars, mode == Mode::Byte);
callback(0..(src.len() - chars.as_str().len()), res);
}
Mode::Str | Mode::ByteStr => unescape_str_or_byte_str(literal_text, mode, 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::Str | Mode::ByteStr => unescape_str_or_byte_str(src, mode == Mode::ByteStr, callback),
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
/// unescaped char or an error
pub fn unescape_char(literal_text: &str) -> Result<char, (usize, EscapeError)> {
let mut chars = literal_text.chars();
unescape_char_or_byte(&mut chars, Mode::Char)
.map_err(|err| (literal_text.len() - chars.as_str().len(), err))
/// unescaped char or an error.
pub fn unescape_char(src: &str) -> Result<char, EscapeError> {
unescape_char_or_byte(&mut src.chars(), false)
}
/// Takes a contents of a byte literal (without quotes), and returns an
/// unescaped byte or an error.
pub fn unescape_byte(literal_text: &str) -> Result<u8, (usize, EscapeError)> {
let mut chars = literal_text.chars();
unescape_char_or_byte(&mut chars, Mode::Byte)
.map(byte_from_char)
.map_err(|err| (literal_text.len() - chars.as_str().len(), err))
pub fn unescape_byte(src: &str) -> Result<u8, EscapeError> {
unescape_char_or_byte(&mut src.chars(), true).map(byte_from_char)
}
/// 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 {
Mode::Byte | Mode::ByteStr | Mode::RawByteStr => true,
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.
let second_char = chars.next().ok_or(EscapeError::LoneSlash)?;
let res = match second_char {
let res = match chars.next().ok_or(EscapeError::LoneSlash)? {
'"' => '"',
'n' => '\n',
'r' => '\r',
@ -181,7 +155,7 @@ fn scan_escape(chars: &mut Chars<'_>, mode: Mode) -> Result<char, EscapeError> {
let value = hi * 16 + lo;
// 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);
}
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
// than unallowed value for a literal.
if mode.is_bytes() {
if is_byte {
return Err(EscapeError::UnicodeEscapeInByte);
}
@ -249,23 +223,22 @@ fn scan_escape(chars: &mut Chars<'_>, mode: Mode) -> Result<char, EscapeError> {
}
#[inline]
fn ascii_check(first_char: char, mode: Mode) -> Result<char, EscapeError> {
if mode.is_bytes() && !first_char.is_ascii() {
fn ascii_check(c: char, is_byte: bool) -> Result<char, EscapeError> {
if is_byte && !c.is_ascii() {
// Byte literal can't be a non-ascii character.
Err(EscapeError::NonAsciiCharInByte)
} else {
Ok(first_char)
Ok(c)
}
}
fn unescape_char_or_byte(chars: &mut Chars<'_>, mode: Mode) -> Result<char, EscapeError> {
debug_assert!(mode == Mode::Char || mode == Mode::Byte);
let first_char = chars.next().ok_or(EscapeError::ZeroChars)?;
let res = match first_char {
'\\' => scan_escape(chars, mode),
fn unescape_char_or_byte(chars: &mut Chars<'_>, is_byte: bool) -> Result<char, EscapeError> {
let c = chars.next().ok_or(EscapeError::ZeroChars)?;
let res = match c {
'\\' => scan_escape(chars, is_byte),
'\n' | '\t' | '\'' => Err(EscapeError::EscapeOnlyChar),
'\r' => Err(EscapeError::BareCarriageReturn),
_ => ascii_check(first_char, mode),
_ => ascii_check(c, is_byte),
}?;
if chars.next().is_some() {
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
/// 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
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();
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 second_char {
match chars.clone().next() {
Some('\n') => {
// Rust language specification requires us to skip whitespaces
// if unescaped '\' character is followed by '\n'.
@ -297,17 +270,17 @@ where
skip_ascii_whitespace(&mut chars, start, callback);
continue;
}
_ => scan_escape(&mut chars, mode),
_ => scan_escape(&mut chars, is_byte),
}
}
'\n' => Ok('\n'),
'\t' => Ok('\t'),
'"' => Err(EscapeError::EscapeOnlyChar),
'\r' => Err(EscapeError::BareCarriageReturn),
_ => ascii_check(first_char, mode),
_ => ascii_check(c, is_byte),
};
let end = initial_len - chars.as_str().len();
callback(start..end, unescaped_char);
let end = src.len() - chars.as_str().len();
callback(start..end, res);
}
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
/// sequence of characters or errors.
/// NOTE: Raw strings do not perform any explicit character escaping, here we
/// only translate CRLF to LF and produce errors on bare CR.
fn unescape_raw_str_or_raw_byte_str<F>(literal_text: &str, mode: Mode, callback: &mut F)
/// only produce errors on bare CR.
fn unescape_raw_str_or_raw_byte_str<F>(src: &str, is_byte: bool, callback: &mut F)
where
F: FnMut(Range<usize>, Result<char, EscapeError>),
{
debug_assert!(mode == Mode::RawStr || mode == Mode::RawByteStr);
let initial_len = literal_text.len();
let mut chars = src.chars();
let mut chars = literal_text.chars();
while let Some(curr) = chars.next() {
let start = initial_len - chars.as_str().len() - curr.len_utf8();
let result = match curr {
// The `start` and `end` computation here matches the one in
// `unescape_str_or_byte_str` for consistency, even though this function
// doesn't have to worry about skipping any chars.
while let Some(c) = chars.next() {
let start = src.len() - chars.as_str().len() - c.len_utf8();
let res = match c {
'\r' => Err(EscapeError::BareCarriageReturnInRawString),
c if mode.is_bytes() && !c.is_ascii() => Err(EscapeError::NonAsciiCharInByteString),
c => Ok(c),
_ => ascii_check(c, is_byte),
};
let end = initial_len - chars.as_str().len();
callback(start..end, result);
let end = src.len() - chars.as_str().len();
callback(start..end, res);
}
}
fn byte_from_char(c: char) -> u8 {
#[inline]
pub fn byte_from_char(c: char) -> u8 {
let res = c as u32;
debug_assert!(res <= u8::MAX as u32, "guaranteed because of Mode::ByteStr");
res as u8

View file

@ -3,8 +3,7 @@ use super::*;
#[test]
fn test_unescape_char_bad() {
fn check(literal_text: &str, expected_error: EscapeError) {
let actual_result = unescape_char(literal_text).map_err(|(_offset, err)| err);
assert_eq!(actual_result, Err(expected_error));
assert_eq!(unescape_char(literal_text), Err(expected_error));
}
check("", EscapeError::ZeroChars);
@ -68,8 +67,7 @@ fn test_unescape_char_bad() {
#[test]
fn test_unescape_char_good() {
fn check(literal_text: &str, expected_char: char) {
let actual_result = unescape_char(literal_text);
assert_eq!(actual_result, Ok(expected_char));
assert_eq!(unescape_char(literal_text), Ok(expected_char));
}
check("a", 'a');
@ -149,8 +147,7 @@ fn test_unescape_str_good() {
#[test]
fn test_unescape_byte_bad() {
fn check(literal_text: &str, expected_error: EscapeError) {
let actual_result = unescape_byte(literal_text).map_err(|(_offset, err)| err);
assert_eq!(actual_result, Err(expected_error));
assert_eq!(unescape_byte(literal_text), Err(expected_error));
}
check("", EscapeError::ZeroChars);
@ -219,8 +216,7 @@ fn test_unescape_byte_bad() {
#[test]
fn test_unescape_byte_good() {
fn check(literal_text: &str, expected_byte: u8) {
let actual_result = unescape_byte(literal_text);
assert_eq!(actual_result, Ok(expected_byte));
assert_eq!(unescape_byte(literal_text), Ok(expected_byte));
}
check("a", b'a');
@ -246,10 +242,10 @@ fn test_unescape_byte_good() {
fn test_unescape_byte_str_good() {
fn check(literal_text: &str, expected: &[u8]) {
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 {
match c {
Ok(c) => b.push(c),
Ok(c) => b.push(byte_from_char(c)),
Err(e) => buf = Err((range, e)),
}
}
@ -280,18 +276,13 @@ fn test_unescape_raw_str() {
#[test]
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());
unescape_byte_literal(literal, Mode::RawByteStr, &mut |range, res| {
unescaped.push((range, res))
});
unescape_literal(literal, Mode::RawByteStr, &mut |range, res| unescaped.push((range, res)));
assert_eq!(unescaped, expected);
}
check("\r", &[(0..1, Err(EscapeError::BareCarriageReturnInRawString))]);
check("🦀", &[(0..4, Err(EscapeError::NonAsciiCharInByteString))]);
check(
"🦀a",
&[(0..4, Err(EscapeError::NonAsciiCharInByteString)), (4..5, Ok(byte_from_char('a')))],
);
check("🦀", &[(0..4, Err(EscapeError::NonAsciiCharInByte))]);
check("🦀a", &[(0..4, Err(EscapeError::NonAsciiCharInByte)), (4..5, Ok('a'))]);
}

View file

@ -353,55 +353,55 @@ impl<'a> StringReader<'a> {
fn cook_lexer_literal(
&self,
start: BytePos,
suffix_start: BytePos,
end: BytePos,
kind: rustc_lexer::LiteralKind,
) -> (token::LitKind, Symbol) {
// prefix means `"` or `br"` or `r###"`, ...
let (lit_kind, mode, prefix_len, postfix_len) = match kind {
match kind {
rustc_lexer::LiteralKind::Char { terminated } => {
if !terminated {
self.sess.span_diagnostic.span_fatal_with_code(
self.mk_sp(start, suffix_start),
self.mk_sp(start, end),
"unterminated character literal",
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 } => {
if !terminated {
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",
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 } => {
if !terminated {
self.sess.span_diagnostic.span_fatal_with_code(
self.mk_sp(start, suffix_start),
self.mk_sp(start, end),
"unterminated double quote string",
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 } => {
if !terminated {
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",
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 } => {
if let Some(n_hashes) = 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 {
self.report_raw_str_error(start, 1);
}
@ -409,56 +409,59 @@ impl<'a> StringReader<'a> {
rustc_lexer::LiteralKind::RawByteStr { n_hashes } => {
if let Some(n_hashes) = 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 {
self.report_raw_str_error(start, 2);
}
}
rustc_lexer::LiteralKind::Int { base, empty_int } => {
return if empty_int {
if empty_int {
self.sess
.span_diagnostic
.struct_span_err_with_code(
self.mk_sp(start, suffix_start),
self.mk_sp(start, end),
"no valid digits found for number",
error_code!(E0768),
)
.emit();
(token::Integer, sym::integer(0))
} else {
self.validate_int_literal(base, start, suffix_start);
(token::Integer, self.symbol_from_to(start, suffix_start))
};
if matches!(base, Base::Binary | Base::Octal) {
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 } => {
if empty_exponent {
self.err_span_(start, self.pos, "expected at least one digit in exponent");
}
match base {
Base::Hexadecimal => self.err_span_(
start,
suffix_start,
"hexadecimal float literal is not supported",
),
Base::Hexadecimal => {
self.err_span_(start, end, "hexadecimal float literal is not supported")
}
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 => {
self.err_span_(start, suffix_start, "binary float literal is not supported")
self.err_span_(start, end, "binary float literal is not supported")
}
_ => (),
_ => {}
}
let id = self.symbol_from_to(start, suffix_start);
return (token::Float, id);
(token::Float, self.symbol_from_to(start, end))
}
};
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]
@ -649,20 +652,22 @@ impl<'a> StringReader<'a> {
)
}
fn validate_literal_escape(
fn cook_quoted(
&self,
kind: token::LitKind,
mode: Mode,
content_start: BytePos,
content_end: BytePos,
start: BytePos,
end: BytePos,
prefix_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);
unescape::unescape_literal(lit_content, mode, &mut |range, result| {
// Here we only check for errors. The actual unescaping is done later.
if let Err(err) = result {
let span_with_quotes = self
.mk_sp(content_start - BytePos(prefix_len), content_end + BytePos(postfix_len));
let span_with_quotes = self.mk_sp(start, end);
let (start, end) = (range.start as u32, range.end as u32);
let lo = content_start + BytePos(start);
let hi = lo + BytePos(end - start);
@ -678,23 +683,7 @@ impl<'a> StringReader<'a> {
);
}
});
}
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));
}
}
(kind, Symbol::intern(lit_content))
}
}

View file

@ -108,7 +108,7 @@ pub(crate) fn emit_unescape_error(
}
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")
} else {
("", "if you meant to write a `str` literal, use double quotes")
@ -142,7 +142,7 @@ pub(crate) fn emit_unescape_error(
EscapeError::EscapeOnlyChar => {
let (c, char_span) = last_char();
let msg = if mode.is_bytes() {
let msg = if mode.is_byte() {
"byte constant must be escaped"
} else {
"character constant must be escaped"
@ -182,11 +182,11 @@ pub(crate) fn emit_unescape_error(
let (c, span) = last_char();
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 mut diag = handler.struct_span_err(span, &format!("{}: `{}`", label, ec));
diag.span_label(span, label);
if c == '{' || c == '}' && !mode.is_bytes() {
if c == '{' || c == '}' && !mode.is_byte() {
diag.help(
"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",
);
} else {
if !mode.is_bytes() {
if !mode.is_byte() {
diag.span_suggestion(
span_with_quotes,
"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();
}
EscapeError::NonAsciiCharInByte => {
assert!(mode.is_bytes());
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 {
format!(" but is {:?}", c)
} else {
String::new()
};
err.span_label(span, &format!("byte constant must be ASCII{}", postfix));
if (c as u32) <= 0xFF {
err.span_label(span, &format!("must be ASCII{}", postfix));
// 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(
span,
&format!(
@ -250,9 +257,9 @@ pub(crate) fn emit_unescape_error(
format!("\\x{:X}", c as u32),
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");
} else if matches!(mode, Mode::ByteStr) {
} else if mode != Mode::RawByteStr {
let mut utf8 = String::new();
utf8.push(c);
err.span_suggestion(
@ -270,19 +277,6 @@ pub(crate) fn emit_unescape_error(
}
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 => {
handler
.struct_span_err(span, "out of range hex escape")

View file

@ -1,7 +1,6 @@
// wasm32 does not support benches (no time).
#![cfg(not(target_arch = "wasm32"))]
#![feature(flt2dec)]
#![feature(int_log)]
#![feature(test)]
#![feature(trusted_random_access)]
#![feature(iter_array_chunks)]

View file

@ -2271,15 +2271,16 @@ macro_rules! int_impl {
/// # Panics
///
/// 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
///
/// ```
/// #![feature(int_log)]
#[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, \
without modifying the original"]
#[inline]
@ -2298,10 +2299,11 @@ macro_rules! int_impl {
/// # Examples
///
/// ```
/// #![feature(int_log)]
#[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, \
without modifying the original"]
#[inline]
@ -2319,10 +2321,11 @@ macro_rules! int_impl {
/// # Example
///
/// ```
/// #![feature(int_log)]
#[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, \
without modifying the original"]
#[inline]
@ -2343,10 +2346,10 @@ macro_rules! int_impl {
/// # Examples
///
/// ```
/// #![feature(int_log)]
#[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, \
without modifying the original"]
#[inline]
@ -2379,10 +2382,10 @@ macro_rules! int_impl {
/// # Examples
///
/// ```
/// #![feature(int_log)]
#[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, \
without modifying the original"]
#[inline]
@ -2403,10 +2406,10 @@ macro_rules! int_impl {
/// # Example
///
/// ```
/// #![feature(int_log)]
#[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, \
without modifying the original"]
#[inline]

View file

@ -460,14 +460,14 @@ macro_rules! nonzero_unsigned_operations {
/// # Examples
///
/// ```
/// #![feature(int_log)]
#[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(8).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, \
without modifying the original"]
#[inline]
@ -485,14 +485,14 @@ macro_rules! nonzero_unsigned_operations {
/// # Examples
///
/// ```
/// #![feature(int_log)]
#[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(100).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, \
without modifying the original"]
#[inline]

View file

@ -692,15 +692,16 @@ macro_rules! uint_impl {
///
/// # 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
///
/// ```
/// #![feature(int_log)]
#[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, \
without modifying the original"]
#[inline]
@ -719,10 +720,11 @@ macro_rules! uint_impl {
/// # Examples
///
/// ```
/// #![feature(int_log)]
#[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, \
without modifying the original"]
#[inline]
@ -740,10 +742,11 @@ macro_rules! uint_impl {
/// # Example
///
/// ```
/// #![feature(int_log)]
#[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, \
without modifying the original"]
#[inline]
@ -764,10 +767,10 @@ macro_rules! uint_impl {
/// # Examples
///
/// ```
/// #![feature(int_log)]
#[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, \
without modifying the original"]
#[inline]
@ -800,10 +803,10 @@ macro_rules! uint_impl {
/// # Examples
///
/// ```
/// #![feature(int_log)]
#[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, \
without modifying the original"]
#[inline]
@ -822,10 +825,10 @@ macro_rules! uint_impl {
/// # Examples
///
/// ```
/// #![feature(int_log)]
#[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, \
without modifying the original"]
#[inline]

View file

@ -568,6 +568,31 @@ impl<T: ?Sized> *const T {
///
/// For non-`Sized` pointees this operation changes only the data pointer,
/// 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")]
#[must_use = "returns a new pointer rather than modifying its argument"]
#[inline(always)]

View file

@ -588,6 +588,34 @@ impl<T: ?Sized> *mut T {
///
/// For non-`Sized` pointees this operation changes only the data pointer,
/// 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")]
#[must_use = "returns a new pointer rather than modifying its argument"]
#[inline(always)]

View file

@ -3667,7 +3667,8 @@ impl<T> [T] {
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
/// postconditions as that method. You're only assured that

View file

@ -22,7 +22,8 @@ macro_rules! tuple_impls {
maybe_tuple_doc! {
$($T)+ @
#[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
last_type!($($T,)+): ?Sized
{
@ -40,7 +41,7 @@ macro_rules! tuple_impls {
maybe_tuple_doc! {
$($T)+ @
#[stable(feature = "rust1", since = "1.0.0")]
impl<$($T:Eq),+> Eq for ($($T,)+)
impl<$($T: Eq),+> Eq for ($($T,)+)
where
last_type!($($T,)+): ?Sized
{}
@ -49,7 +50,8 @@ macro_rules! tuple_impls {
maybe_tuple_doc! {
$($T)+ @
#[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
last_type!($($T,)+): ?Sized
{
@ -79,7 +81,8 @@ macro_rules! tuple_impls {
maybe_tuple_doc! {
$($T)+ @
#[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
last_type!($($T,)+): ?Sized
{

View file

@ -64,7 +64,6 @@
#![feature(try_trait_v2)]
#![feature(slice_internals)]
#![feature(slice_partition_dedup)]
#![feature(int_log)]
#![feature(iter_advance_by)]
#![feature(iter_array_chunks)]
#![feature(iter_collect_into)]

View file

@ -118,6 +118,9 @@ ENV TARGETS=$TARGETS,armv7-unknown-linux-gnueabi
ENV TARGETS=$TARGETS,armv7-unknown-linux-musleabi
ENV TARGETS=$TARGETS,i686-unknown-freebsd
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
# we need asm in the search path for gcc-8 (for gnux32) but not in the search path of the

View file

@ -128,6 +128,7 @@ target | std | notes
[`aarch64-linux-android`](platform-support/android.md) | ✓ | ARM64 Android
`aarch64-unknown-none-softfloat` | * | Bare ARM64, softfloat
`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-unknown-linux-musleabi` | ✓ | ARMv6 Linux with MUSL
`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-unknown-freebsd` | ✓ | 32-bit FreeBSD
`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
`mips64-unknown-linux-muslabi64` | ✓ | MIPS64 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-none`](platform-support/x86_64-unknown-none.md) | * | Freestanding/bare-metal x86_64, softfloat
`x86_64-unknown-redox` | ✓ | Redox OS
[`x86_64-unknown-uefi`](platform-support/unknown-uefi.md) | * | 64-bit UEFI
[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-unknown-freebsd` | ✓ | ✓ | ARM64 FreeBSD
`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-netbsd` | ✓ | ✓ |
[`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-netbsd` | ✓ | ✓ | NetBSD/i386 with SSE2
[`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-msvc` | ? | |
`i686-wrs-vxworks` | ? | |
@ -311,7 +312,6 @@ target | std | host | notes
`x86_64-unknown-l4re-uclibc` | ? | |
`x86_64-unknown-none-linuxkernel` | * | | Linux kernel modules
[`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-msvc` | ✓ | |
`x86_64-wrs-vxworks` | ? | |

View file

@ -1,6 +1,6 @@
# `*-unknown-uefi`
**Tier: 3**
**Tier: 2**
Unified Extensible Firmware Interface (UEFI) targets for application, driver,
and core UEFI binaries.
@ -72,28 +72,14 @@ target = ["x86_64-unknown-uefi"]
## Building Rust programs
Rust does not yet ship pre-compiled artifacts for this target. To compile for
this target, you will either need to build Rust with the target enabled (see
"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:
Starting with Rust 1.67, precompiled artifacts are provided via
`rustup`. For example, to use `x86_64-unknown-uefi`:
```sh
cargo +nightly build \
-Zbuild-std=core,compiler_builtins \
-Zbuild-std-features=compiler-builtins-mem \
--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
# install cross-compile toolchain
rustup target add x86_64-unknown-uefi
# target flag may be used with any cargo or rustc command
cargo build --target x86_64-unknown-uefi
```
## 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
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`:
```sh
cargo +nightly build \
-Zbuild-std=core,compiler_builtins \
-Zbuild-std-features=compiler-builtins-mem \
--target x86_64-unknown-uefi
cargo build --target x86_64-unknown-uefi
```
```rust,ignore (platform-specific,eh-personality-is-unstable)

View file

@ -1,4 +1,4 @@
#![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() {}

View file

@ -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
|
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
|

View file

@ -1,4 +1,4 @@
// build-pass
// check-pass
#![feature(const_fn_trait_ref_impls)]
#![feature(fn_traits)]
@ -60,21 +60,18 @@ const fn test(i: i32) -> i32 {
i + 1
}
const fn main() {
fn main() {
const fn one() -> i32 {
1
};
const fn two() -> i32 {
2
};
const _: () = {
let test_one = test_fn(one);
assert!(test_one == (1, 1, 1));
// FIXME(const_cmp_tuple)
let test_one = test_fn(one);
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);
let test_two = test_fn_mut(two);
assert!(test_two == (2, 2));
};
}

View file

@ -7,6 +7,6 @@ pub fn main() {
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 non-ASCII character in byte constant
b'é'; //~ ERROR non-ASCII character in byte literal
b'a //~ ERROR unterminated byte constant [E0763]
}

View file

@ -32,11 +32,11 @@ error: byte constant must be escaped: `'`
LL | b''';
| ^ help: escape the character: `\'`
error: non-ASCII character in byte constant
error: non-ASCII character in byte literal
--> $DIR/byte-literals.rs:10:7
|
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
|

View file

@ -3,7 +3,7 @@ static FOO: &'static [u8] = b"\f"; //~ ERROR unknown byte escape
pub fn main() {
b"\f"; //~ ERROR unknown byte escape
b"\x0Z"; //~ ERROR invalid character in numeric character escape: `Z`
b"é"; //~ ERROR non-ASCII character in byte constant
br##"é"##; //~ ERROR raw byte string must be ASCII
b"é"; //~ ERROR non-ASCII character in byte string literal
br##"é"##; //~ ERROR non-ASCII character in raw byte string literal
b"a //~ ERROR unterminated double quote byte string
}

View file

@ -20,18 +20,18 @@ error: invalid character in numeric character escape: `Z`
LL | b"\x0Z";
| ^ 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
|
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
|
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
|
LL | br##"é"##;

View file

@ -2,6 +2,6 @@
pub fn main() {
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
}

View file

@ -4,7 +4,7 @@ error: bare CR not allowed in raw string
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
|
LL | br"é";

View file

@ -14,15 +14,15 @@ fn main() {
println!("{:?}", r##"/* } if isAdmin begin admins only "##);
//~^ ERROR unicode codepoint changing visible direction of text present in literal
println!("{:?}", b"/* } if isAdmin begin admins only ");
//~^ ERROR non-ASCII character in byte constant
//~| ERROR non-ASCII character in byte constant
//~| ERROR non-ASCII character in byte constant
//~| ERROR non-ASCII character in byte constant
//~^ ERROR non-ASCII character in byte string literal
//~| ERROR non-ASCII character in byte string literal
//~| ERROR non-ASCII character in byte string literal
//~| ERROR non-ASCII character in byte string literal
println!("{:?}", br##"/* } if isAdmin begin admins only "##);
//~^ ERROR raw byte string must be ASCII
//~| ERROR raw byte string must be ASCII
//~| ERROR raw byte string must be ASCII
//~| ERROR raw byte string must be ASCII
//~^ ERROR non-ASCII character in raw byte string literal
//~| ERROR non-ASCII character in raw byte string literal
//~| ERROR non-ASCII character in raw byte string literal
//~| ERROR non-ASCII character in raw byte string literal
println!("{:?}", '');
//~^ ERROR unicode codepoint changing visible direction of text present in literal
}

View file

@ -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
error: non-ASCII character in byte constant
error: non-ASCII character in byte string literal
--> $DIR/unicode-control-codepoints.rs:16:26
|
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
|
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
|
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
|
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
|
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
|
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
|
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
|
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
|
LL | println!("{:?}", br##"/* } if isAdmin begin admins only "##);
| ^ 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
|
LL | println!("{:?}", br##"/* } if isAdmin begin admins only "##);
| ^ 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
|
LL | println!("{:?}", br##"/* } if isAdmin begin admins only "##);
| ^ 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
|
LL | println!("{:?}", br##"/* } if isAdmin begin admins only "##);

View file

@ -2,17 +2,17 @@
fn main() {
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
//~| NOTE: byte constant must be ASCII
//~| NOTE: must be ASCII
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: byte constant must be ASCII
//~| NOTE: must be ASCII
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
//~| NOTE: byte constant must be ASCII
//~| NOTE: must be ASCII
}

View file

@ -1,28 +1,28 @@
error: non-ASCII character in byte constant
error: non-ASCII character in byte literal
--> $DIR/multibyte-escapes.rs:4:7
|
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
|
LL | b'\xB5';
| ~~~~
error: non-ASCII character in byte constant
error: non-ASCII character in byte literal
--> $DIR/multibyte-escapes.rs:9:7
|
LL | b'字';
| ^^
| |
| byte constant must be ASCII
| must be ASCII
| 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
|
LL | b"字";
| ^^ byte constant must be ASCII
| ^^ must be ASCII
|
help: if you meant to use the UTF-8 encoding of '字', use \xHH escapes
|

View file

@ -60,6 +60,7 @@ static TARGETS: &[&str] = &[
"aarch64-unknown-none",
"aarch64-unknown-none-softfloat",
"aarch64-unknown-redox",
"aarch64-unknown-uefi",
"arm-linux-androideabi",
"arm-unknown-linux-gnueabi",
"arm-unknown-linux-gnueabihf",
@ -95,6 +96,7 @@ static TARGETS: &[&str] = &[
"i686-unknown-freebsd",
"i686-unknown-linux-gnu",
"i686-unknown-linux-musl",
"i686-unknown-uefi",
"m68k-unknown-linux-gnu",
"mips-unknown-linux-gnu",
"mips-unknown-linux-musl",
@ -151,6 +153,7 @@ static TARGETS: &[&str] = &[
"x86_64-unknown-none",
"x86_64-unknown-redox",
"x86_64-unknown-hermit",
"x86_64-unknown-uefi",
];
/// This allows the manifest to contain rust-docs for hosts that don't build

View file

@ -55,30 +55,6 @@ const LINKCHECK_EXCEPTIONS: &[(&str, &[&str])] = &[
#[rustfmt::skip]
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
("core/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
// 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
@ -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.

View file

@ -3,7 +3,6 @@
#![feature(never_type)]
#![feature(try_blocks)]
#![feature(io_error_more)]
#![feature(int_log)]
#![feature(variant_count)]
#![feature(yeet_expr)]
#![feature(is_some_and)]

View file

@ -1,5 +1,4 @@
//@compile-flags: -Coverflow-checks=off
#![feature(int_log)]
#![allow(arithmetic_overflow)]
pub fn main() {

View file

@ -5,9 +5,7 @@
mod block;
use rowan::Direction;
use rustc_lexer::unescape::{
self, unescape_byte, unescape_byte_literal, unescape_char, unescape_literal, Mode,
};
use rustc_lexer::unescape::{self, unescape_byte, unescape_char, unescape_literal, Mode};
use crate::{
algo,
@ -143,7 +141,7 @@ fn validate_literal(literal: ast::Literal, acc: &mut Vec<SyntaxError>) {
ast::LiteralKind::ByteString(s) => {
if !s.is_raw() {
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 {
push_err(2, (range.start, err));
}