From efeb46187398199dd9ac1b1e0c1ba43180de9b4f Mon Sep 17 00:00:00 2001 From: Waffle Date: Tue, 7 Sep 2021 16:41:15 +0300 Subject: [PATCH 01/18] Make `UnsafeCell::get_mut` const --- library/core/src/cell.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/library/core/src/cell.rs b/library/core/src/cell.rs index 2adf6a549e641..25c153dae04e3 100644 --- a/library/core/src/cell.rs +++ b/library/core/src/cell.rs @@ -1916,7 +1916,8 @@ impl UnsafeCell { /// ``` #[inline(always)] #[stable(feature = "unsafe_cell_get_mut", since = "1.50.0")] - pub fn get_mut(&mut self) -> &mut T { + #[rustc_const_unstable(feature = "const_unsafecell_get_mut", issue = "none")] + pub const fn get_mut(&mut self) -> &mut T { &mut self.value } From 9d64a8dbd440cce59ff92696ed075646df84cb99 Mon Sep 17 00:00:00 2001 From: Esteban Kuber Date: Sun, 29 Aug 2021 08:34:23 +0000 Subject: [PATCH 02/18] Tokenize emoji as if they were valid indentifiers In the lexer, consider emojis to be valid identifiers and reject them later to avoid knock down parse errors. --- Cargo.lock | 42 ++++++++++++ compiler/rustc_interface/src/passes.rs | 12 +++- compiler/rustc_lexer/Cargo.toml | 1 + compiler/rustc_lexer/src/lib.rs | 25 +++++++ compiler/rustc_parse/src/lexer/mod.rs | 6 ++ compiler/rustc_session/src/parse.rs | 8 ++- src/test/ui/parser/emoji-identifiers.rs | 16 +++++ src/test/ui/parser/emoji-identifiers.stderr | 72 +++++++++++++++++++++ 8 files changed, 180 insertions(+), 2 deletions(-) create mode 100644 src/test/ui/parser/emoji-identifiers.rs create mode 100644 src/test/ui/parser/emoji-identifiers.stderr diff --git a/Cargo.lock b/Cargo.lock index 80acf227698e9..ca3f44da79663 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4003,6 +4003,7 @@ name = "rustc_lexer" version = "0.1.0" dependencies = [ "expect-test", + "unic-emoji-char", "unicode-xid", ] @@ -5466,6 +5467,47 @@ version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "56dee185309b50d1f11bfedef0fe6d036842e3fb77413abef29f8f8d1c5d4c1c" +[[package]] +name = "unic-char-property" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8c57a407d9b6fa02b4795eb81c5b6652060a15a7903ea981f3d723e6c0be221" +dependencies = [ + "unic-char-range", +] + +[[package]] +name = "unic-char-range" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0398022d5f700414f6b899e10b8348231abf9173fa93144cbc1a43b9793c1fbc" + +[[package]] +name = "unic-common" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "80d7ff825a6a654ee85a63e80f92f054f904f21e7d12da4e22f9834a4aaa35bc" + +[[package]] +name = "unic-emoji-char" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b07221e68897210270a38bde4babb655869637af0f69407f96053a34f76494d" +dependencies = [ + "unic-char-property", + "unic-char-range", + "unic-ucd-version", +] + +[[package]] +name = "unic-ucd-version" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96bd2f2237fe450fcd0a1d2f5f4e91711124f7857ba2e964247776ebeeb7b0c4" +dependencies = [ + "unic-common", +] + [[package]] name = "unicase" version = "2.6.0" diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs index 1f3d6f70ff837..f631b46e565d2 100644 --- a/compiler/rustc_interface/src/passes.rs +++ b/compiler/rustc_interface/src/passes.rs @@ -35,7 +35,7 @@ use rustc_session::output::{filename_for_input, filename_for_metadata}; use rustc_session::search_paths::PathKind; use rustc_session::Session; use rustc_span::symbol::{Ident, Symbol}; -use rustc_span::FileName; +use rustc_span::{FileName, MultiSpan}; use rustc_trait_selection::traits; use rustc_typeck as typeck; use tempfile::Builder as TempFileBuilder; @@ -445,6 +445,16 @@ pub fn configure_and_expand( } }); + // Gate identifiers containing invalid Unicode codepoints that were recovered during lexing. + sess.parse_sess.bad_unicode_identifiers.with_lock(|identifiers| { + for (ident, spans) in identifiers.drain() { + sess.diagnostic().span_err( + MultiSpan::from(spans), + &format!("identifiers cannot contain emojis: `{}`", ident), + ); + } + }); + Ok(krate) } diff --git a/compiler/rustc_lexer/Cargo.toml b/compiler/rustc_lexer/Cargo.toml index 7e05fe545cabe..a43333339543e 100644 --- a/compiler/rustc_lexer/Cargo.toml +++ b/compiler/rustc_lexer/Cargo.toml @@ -17,6 +17,7 @@ doctest = false # Note that this crate purposefully does not depend on other rustc crates [dependencies] unicode-xid = "0.2.0" +unic-emoji-char = "0.9.0" [dev-dependencies] expect-test = "1.0" diff --git a/compiler/rustc_lexer/src/lib.rs b/compiler/rustc_lexer/src/lib.rs index b64a891cb2526..a729c0c0bbea3 100644 --- a/compiler/rustc_lexer/src/lib.rs +++ b/compiler/rustc_lexer/src/lib.rs @@ -64,6 +64,8 @@ pub enum TokenKind { /// "ident" or "continue" /// At this step keywords are also considered identifiers. Ident, + /// Like the above, but containing invalid unicode codepoints. + InvalidIdent, /// "r#ident" RawIdent, /// An unknown prefix like `foo#`, `foo'`, `foo"`. Note that only the @@ -411,6 +413,11 @@ impl Cursor<'_> { let kind = Str { terminated }; Literal { kind, suffix_start } } + // Identifier (this should be checked after other variant that can + // start as identifier). + c if !c.is_ascii() && unic_emoji_char::is_emoji(c) => { + self.fake_ident_or_unknown_prefix() + } _ => Unknown, }; Token::new(token_kind, self.len_consumed()) @@ -492,10 +499,28 @@ impl Cursor<'_> { // we see a prefix here, it is definitely an unknown prefix. match self.first() { '#' | '"' | '\'' => UnknownPrefix, + c if !c.is_ascii() && unic_emoji_char::is_emoji(c) => { + self.fake_ident_or_unknown_prefix() + } _ => Ident, } } + fn fake_ident_or_unknown_prefix(&mut self) -> TokenKind { + // Start is already eaten, eat the rest of identifier. + self.eat_while(|c| { + unicode_xid::UnicodeXID::is_xid_continue(c) + || (!c.is_ascii() && unic_emoji_char::is_emoji(c)) + || c == '\u{200d}' + }); + // Known prefixes must have been handled earlier. So if + // we see a prefix here, it is definitely an unknown prefix. + match self.first() { + '#' | '"' | '\'' => UnknownPrefix, + _ => InvalidIdent, + } + } + fn number(&mut self, first_digit: char) -> LiteralKind { debug_assert!('0' <= self.prev() && self.prev() <= '9'); let mut base = Base::Decimal; diff --git a/compiler/rustc_parse/src/lexer/mod.rs b/compiler/rustc_parse/src/lexer/mod.rs index 1e65cc27154a8..46501fc2e5956 100644 --- a/compiler/rustc_parse/src/lexer/mod.rs +++ b/compiler/rustc_parse/src/lexer/mod.rs @@ -191,6 +191,12 @@ impl<'a> StringReader<'a> { } token::Ident(sym, is_raw_ident) } + rustc_lexer::TokenKind::InvalidIdent => { + let sym = nfc_normalize(self.str_from(start)); + let span = self.mk_sp(start, self.pos); + self.sess.bad_unicode_identifiers.borrow_mut().entry(sym).or_default().push(span); + token::Ident(sym, false) + } rustc_lexer::TokenKind::Literal { kind, suffix_start } => { let suffix_start = start + BytePos(suffix_start as u32); let (kind, symbol) = self.cook_lexer_literal(start, suffix_start, kind); diff --git a/compiler/rustc_session/src/parse.rs b/compiler/rustc_session/src/parse.rs index a007b53030271..69d02e6c1ae93 100644 --- a/compiler/rustc_session/src/parse.rs +++ b/compiler/rustc_session/src/parse.rs @@ -119,8 +119,13 @@ pub struct ParseSess { pub config: CrateConfig, pub edition: Edition, pub missing_fragment_specifiers: Lock>, - /// Places where raw identifiers were used. This is used for feature-gating raw identifiers. + /// Places where raw identifiers were used. This is used to avoid complaining about idents + /// clashing with keywords in new editions. pub raw_identifier_spans: Lock>, + /// Places where identifiers that contain invalid Unicode codepoints but that look like they + /// should be. Useful to avoid bad tokenization when encountering emojis. We group them to + /// provide a single error per unique incorrect identifier. + pub bad_unicode_identifiers: Lock>>, source_map: Lrc, pub buffered_lints: Lock>, /// Contains the spans of block expressions that could have been incomplete based on the @@ -160,6 +165,7 @@ impl ParseSess { edition: ExpnId::root().expn_data().edition, missing_fragment_specifiers: Default::default(), raw_identifier_spans: Lock::new(Vec::new()), + bad_unicode_identifiers: Lock::new(Default::default()), source_map, buffered_lints: Lock::new(vec![]), ambiguous_block_expr_parse: Lock::new(FxHashMap::default()), diff --git a/src/test/ui/parser/emoji-identifiers.rs b/src/test/ui/parser/emoji-identifiers.rs new file mode 100644 index 0000000000000..2f4df4cf21619 --- /dev/null +++ b/src/test/ui/parser/emoji-identifiers.rs @@ -0,0 +1,16 @@ +struct ABig๐Ÿ‘ฉโ€๐Ÿ‘ฉโ€๐Ÿ‘งโ€๐Ÿ‘งFamily; //~ ERROR identifiers cannot contain emojis +struct ๐Ÿ‘€; //~ ERROR identifiers cannot contain emojis +impl ๐Ÿ‘€ { + fn full_of_โœจ() -> ๐Ÿ‘€ { //~ ERROR identifiers cannot contain emojis + ๐Ÿ‘€ + } +} +fn i_like_to_๐Ÿ˜…_a_lot() -> ๐Ÿ‘€ { //~ ERROR identifiers cannot contain emojis + ๐Ÿ‘€::full_ofโœจ() //~ ERROR no function or associated item named `full_ofโœจ` found for struct `๐Ÿ‘€` + //~^ ERROR identifiers cannot contain emojis +} +fn main() { + let _ = i_like_to_๐Ÿ˜„_a_lot(); //~ ERROR cannot find function `i_like_to_๐Ÿ˜„_a_lot` in this scope + //~^ ERROR identifiers cannot contain emojis +} + diff --git a/src/test/ui/parser/emoji-identifiers.stderr b/src/test/ui/parser/emoji-identifiers.stderr new file mode 100644 index 0000000000000..3b17bb01de953 --- /dev/null +++ b/src/test/ui/parser/emoji-identifiers.stderr @@ -0,0 +1,72 @@ +error[E0425]: cannot find function `i_like_to_๐Ÿ˜„_a_lot` in this scope + --> $DIR/emoji-identifiers.rs:13:13 + | +LL | fn i_like_to_๐Ÿ˜…_a_lot() -> ๐Ÿ‘€ { + | ----------------------------- similarly named function `i_like_to_๐Ÿ˜…_a_lot` defined here +... +LL | let _ = i_like_to_๐Ÿ˜„_a_lot(); + | ^^^^^^^^^^^^^^^^^^ help: a function with a similar name exists: `i_like_to_๐Ÿ˜…_a_lot` + +error: identifiers cannot contain emojis: `i_like_to_๐Ÿ˜„_a_lot` + --> $DIR/emoji-identifiers.rs:13:13 + | +LL | let _ = i_like_to_๐Ÿ˜„_a_lot(); + | ^^^^^^^^^^^^^^^^^^ + +error: identifiers cannot contain emojis: `full_of_โœจ` + --> $DIR/emoji-identifiers.rs:4:8 + | +LL | fn full_of_โœจ() -> ๐Ÿ‘€ { + | ^^^^^^^^^^ + +error: identifiers cannot contain emojis: `full_ofโœจ` + --> $DIR/emoji-identifiers.rs:9:8 + | +LL | ๐Ÿ‘€::full_ofโœจ() + | ^^^^^^^^^ + +error: identifiers cannot contain emojis: `๐Ÿ‘€` + --> $DIR/emoji-identifiers.rs:2:8 + | +LL | struct ๐Ÿ‘€; + | ^^ +LL | impl ๐Ÿ‘€ { + | ^^ +LL | fn full_of_โœจ() -> ๐Ÿ‘€ { + | ^^ +LL | ๐Ÿ‘€ + | ^^ +... +LL | fn i_like_to_๐Ÿ˜…_a_lot() -> ๐Ÿ‘€ { + | ^^ +LL | ๐Ÿ‘€::full_ofโœจ() + | ^^ + +error: identifiers cannot contain emojis: `i_like_to_๐Ÿ˜…_a_lot` + --> $DIR/emoji-identifiers.rs:8:4 + | +LL | fn i_like_to_๐Ÿ˜…_a_lot() -> ๐Ÿ‘€ { + | ^^^^^^^^^^^^^^^^^^ + +error: identifiers cannot contain emojis: `ABig๐Ÿ‘ฉโ€๐Ÿ‘ฉโ€๐Ÿ‘งโ€๐Ÿ‘งFamily` + --> $DIR/emoji-identifiers.rs:1:8 + | +LL | struct ABig๐Ÿ‘ฉโ€๐Ÿ‘ฉโ€๐Ÿ‘งโ€๐Ÿ‘งFamily; + | ^^^^^^^^^^^^^^^^^^ + +error[E0599]: no function or associated item named `full_ofโœจ` found for struct `๐Ÿ‘€` in the current scope + --> $DIR/emoji-identifiers.rs:9:8 + | +LL | struct ๐Ÿ‘€; + | ---------- function or associated item `full_ofโœจ` not found for this +... +LL | ๐Ÿ‘€::full_ofโœจ() + | ^^^^^^^^^ + | | + | function or associated item not found in `๐Ÿ‘€` + | help: there is an associated function with a similar name: `full_of_โœจ` + +error: aborting due to 8 previous errors + +Some errors have detailed explanations: E0425, E0599. +For more information about an error, try `rustc --explain E0425`. From 01e2d299dc0e8d3ba5e4e6db0321cd8d2a4e3e27 Mon Sep 17 00:00:00 2001 From: Esteban Kuber Date: Thu, 9 Sep 2021 15:01:43 +0000 Subject: [PATCH 03/18] Replace ZWJ with nothing in terminal output --- compiler/rustc_errors/src/emitter.rs | 11 ++++++++++- src/test/ui/parser/emoji-identifiers.stderr | 4 ++-- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_errors/src/emitter.rs b/compiler/rustc_errors/src/emitter.rs index 29f352ae58559..0dc3f184dc601 100644 --- a/compiler/rustc_errors/src/emitter.rs +++ b/compiler/rustc_errors/src/emitter.rs @@ -2054,8 +2054,17 @@ fn num_decimal_digits(num: usize) -> usize { MAX_DIGITS } +const REPLACEMENTS: &[(char, &str)] = &[ + ('\t', " "), + ('\u{200D}', ""), // Replace ZWJ with nothing for consistent terminal output of grapheme clusters. +]; + fn replace_tabs(str: &str) -> String { - str.replace('\t', " ") + let mut output = str.to_string(); + for (c, replacement) in REPLACEMENTS { + output = output.replace(*c, replacement); + } + output } fn draw_col_separator(buffer: &mut StyledBuffer, line: usize, col: usize) { diff --git a/src/test/ui/parser/emoji-identifiers.stderr b/src/test/ui/parser/emoji-identifiers.stderr index 3b17bb01de953..84c3e3962ffec 100644 --- a/src/test/ui/parser/emoji-identifiers.stderr +++ b/src/test/ui/parser/emoji-identifiers.stderr @@ -48,10 +48,10 @@ error: identifiers cannot contain emojis: `i_like_to_๐Ÿ˜…_a_lot` LL | fn i_like_to_๐Ÿ˜…_a_lot() -> ๐Ÿ‘€ { | ^^^^^^^^^^^^^^^^^^ -error: identifiers cannot contain emojis: `ABig๐Ÿ‘ฉโ€๐Ÿ‘ฉโ€๐Ÿ‘งโ€๐Ÿ‘งFamily` +error: identifiers cannot contain emojis: `ABig๐Ÿ‘ฉ๐Ÿ‘ฉ๐Ÿ‘ง๐Ÿ‘งFamily` --> $DIR/emoji-identifiers.rs:1:8 | -LL | struct ABig๐Ÿ‘ฉโ€๐Ÿ‘ฉโ€๐Ÿ‘งโ€๐Ÿ‘งFamily; +LL | struct ABig๐Ÿ‘ฉ๐Ÿ‘ฉ๐Ÿ‘ง๐Ÿ‘งFamily; | ^^^^^^^^^^^^^^^^^^ error[E0599]: no function or associated item named `full_ofโœจ` found for struct `๐Ÿ‘€` in the current scope From afb6f8d5ac3dcf762c3fa69a23d7f5a4b2098837 Mon Sep 17 00:00:00 2001 From: Esteban Kuber Date: Thu, 9 Sep 2021 15:22:29 +0000 Subject: [PATCH 04/18] Fix RustDoc --- src/librustdoc/html/highlight.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustdoc/html/highlight.rs b/src/librustdoc/html/highlight.rs index f8fc9243e14b9..22cea66652ba5 100644 --- a/src/librustdoc/html/highlight.rs +++ b/src/librustdoc/html/highlight.rs @@ -488,7 +488,7 @@ impl<'a> Classifier<'a> { }, Some(c) => c, }, - TokenKind::RawIdent | TokenKind::UnknownPrefix => { + TokenKind::RawIdent | TokenKind::UnknownPrefix | TokenKind::InvalidIdent => { Class::Ident(self.new_span(before, text)) } TokenKind::Lifetime { .. } => Class::Lifetime, From 19f1d0d50a185a7f6545e918c183817c895d50a4 Mon Sep 17 00:00:00 2001 From: Esteban Kuber Date: Thu, 9 Sep 2021 15:41:15 +0000 Subject: [PATCH 05/18] Add `unic-emoji-char` and its dependencies to the allow list --- src/tools/tidy/src/deps.rs | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/tools/tidy/src/deps.rs b/src/tools/tidy/src/deps.rs index 5f1267fc3d250..30438ccc9385e 100644 --- a/src/tools/tidy/src/deps.rs +++ b/src/tools/tidy/src/deps.rs @@ -82,8 +82,8 @@ const PERMITTED_DEPENDENCIES: &[&str] = &[ "bitflags", "block-buffer", "block-padding", - "byteorder", "byte-tools", + "byteorder", "cc", "cfg-if", "chalk-derive", @@ -140,9 +140,9 @@ const PERMITTED_DEPENDENCIES: &[&str] = &[ "memmap2", "memoffset", "miniz_oxide", - "num_cpus", "num-integer", "num-traits", + "num_cpus", "object", "once_cell", "opaque-debug", @@ -188,8 +188,8 @@ const PERMITTED_DEPENDENCIES: &[&str] = &[ "serde_json", "sha-1", "sha2", - "smallvec", "sharded-slab", + "smallvec", "snap", "stable_deref_trait", "stacker", @@ -209,6 +209,11 @@ const PERMITTED_DEPENDENCIES: &[&str] = &[ "tracing-subscriber", "tracing-tree", "typenum", + "unic-char-property", + "unic-char-range", + "unic-common", + "unic-emoji-char", + "unic-ucd-version", "unicode-normalization", "unicode-script", "unicode-security", From e0aedde170652fec895166a2e4e315a1d8adf146 Mon Sep 17 00:00:00 2001 From: Esteban Kuber Date: Thu, 9 Sep 2021 15:55:21 +0000 Subject: [PATCH 06/18] fix fmt --- src/test/ui/parser/emoji-identifiers.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/test/ui/parser/emoji-identifiers.rs b/src/test/ui/parser/emoji-identifiers.rs index 2f4df4cf21619..485fb29af9cdf 100644 --- a/src/test/ui/parser/emoji-identifiers.rs +++ b/src/test/ui/parser/emoji-identifiers.rs @@ -13,4 +13,3 @@ fn main() { let _ = i_like_to_๐Ÿ˜„_a_lot(); //~ ERROR cannot find function `i_like_to_๐Ÿ˜„_a_lot` in this scope //~^ ERROR identifiers cannot contain emojis } - From 07cec2c39da81fc5081cab25a4cd3c53731c5c26 Mon Sep 17 00:00:00 2001 From: Esteban Kuber Date: Thu, 9 Sep 2021 17:05:03 +0000 Subject: [PATCH 07/18] Account for confusable codepoints when recovering emoji identifiers --- compiler/rustc_parse/src/lexer/mod.rs | 15 +++++++++++++-- compiler/rustc_parse/src/lexer/unicode_chars.rs | 2 +- src/test/ui/parser/emoji-identifiers.rs | 3 ++- src/test/ui/parser/emoji-identifiers.stderr | 17 ++++++++++++++--- 4 files changed, 30 insertions(+), 7 deletions(-) diff --git a/compiler/rustc_parse/src/lexer/mod.rs b/compiler/rustc_parse/src/lexer/mod.rs index 46501fc2e5956..4ee1b839d839a 100644 --- a/compiler/rustc_parse/src/lexer/mod.rs +++ b/compiler/rustc_parse/src/lexer/mod.rs @@ -1,3 +1,4 @@ +use crate::lexer::unicode_chars::UNICODE_ARRAY; use rustc_ast::ast::{self, AttrStyle}; use rustc_ast::token::{self, CommentKind, Token, TokenKind}; use rustc_ast::tokenstream::{Spacing, TokenStream}; @@ -191,7 +192,17 @@ impl<'a> StringReader<'a> { } token::Ident(sym, is_raw_ident) } - rustc_lexer::TokenKind::InvalidIdent => { + rustc_lexer::TokenKind::InvalidIdent + // Do not recover an identifier with emojis if the codepoint is a confusable + // with a recoverable substitution token, like `โž–`. + if UNICODE_ARRAY + .iter() + .find(|&&(c, _, _)| { + let sym = self.str_from(start); + sym.chars().count() == 1 && c == sym.chars().next().unwrap() + }) + .is_none() => + { let sym = nfc_normalize(self.str_from(start)); let span = self.mk_sp(start, self.pos); self.sess.bad_unicode_identifiers.borrow_mut().entry(sym).or_default().push(span); @@ -268,7 +279,7 @@ impl<'a> StringReader<'a> { rustc_lexer::TokenKind::Caret => token::BinOp(token::Caret), rustc_lexer::TokenKind::Percent => token::BinOp(token::Percent), - rustc_lexer::TokenKind::Unknown => { + rustc_lexer::TokenKind::Unknown | rustc_lexer::TokenKind::InvalidIdent => { let c = self.str_from(start).chars().next().unwrap(); let mut err = self.struct_fatal_span_char(start, self.pos, "unknown start of token", c); diff --git a/compiler/rustc_parse/src/lexer/unicode_chars.rs b/compiler/rustc_parse/src/lexer/unicode_chars.rs index 3eebc088f3fb7..ccd11f06bc582 100644 --- a/compiler/rustc_parse/src/lexer/unicode_chars.rs +++ b/compiler/rustc_parse/src/lexer/unicode_chars.rs @@ -7,7 +7,7 @@ use rustc_errors::{Applicability, DiagnosticBuilder}; use rustc_span::{symbol::kw, BytePos, Pos, Span}; #[rustfmt::skip] // for line breaks -const UNICODE_ARRAY: &[(char, &str, char)] = &[ +pub(crate) const UNICODE_ARRAY: &[(char, &str, char)] = &[ ('โ€จ', "Line Separator", ' '), ('โ€ฉ', "Paragraph Separator", ' '), ('แš€', "Ogham Space mark", ' '), diff --git a/src/test/ui/parser/emoji-identifiers.rs b/src/test/ui/parser/emoji-identifiers.rs index 485fb29af9cdf..e07e0573e7594 100644 --- a/src/test/ui/parser/emoji-identifiers.rs +++ b/src/test/ui/parser/emoji-identifiers.rs @@ -10,6 +10,7 @@ fn i_like_to_๐Ÿ˜…_a_lot() -> ๐Ÿ‘€ { //~ ERROR identifiers cannot contain emojis //~^ ERROR identifiers cannot contain emojis } fn main() { - let _ = i_like_to_๐Ÿ˜„_a_lot(); //~ ERROR cannot find function `i_like_to_๐Ÿ˜„_a_lot` in this scope + let _ = i_like_to_๐Ÿ˜„_a_lot() โž– 4; //~ ERROR cannot find function `i_like_to_๐Ÿ˜„_a_lot` in this scope //~^ ERROR identifiers cannot contain emojis + //~| ERROR unknown start of token: \u{2796} } diff --git a/src/test/ui/parser/emoji-identifiers.stderr b/src/test/ui/parser/emoji-identifiers.stderr index 84c3e3962ffec..a73681d91966b 100644 --- a/src/test/ui/parser/emoji-identifiers.stderr +++ b/src/test/ui/parser/emoji-identifiers.stderr @@ -1,16 +1,27 @@ +error: unknown start of token: \u{2796} + --> $DIR/emoji-identifiers.rs:13:33 + | +LL | let _ = i_like_to_๐Ÿ˜„_a_lot() โž– 4; + | ^^ + | +help: Unicode character 'โž–' (Heavy Minus Sign) looks like '-' (Minus/Hyphen), but it is not + | +LL | let _ = i_like_to_๐Ÿ˜„_a_lot() - 4; + | ~ + error[E0425]: cannot find function `i_like_to_๐Ÿ˜„_a_lot` in this scope --> $DIR/emoji-identifiers.rs:13:13 | LL | fn i_like_to_๐Ÿ˜…_a_lot() -> ๐Ÿ‘€ { | ----------------------------- similarly named function `i_like_to_๐Ÿ˜…_a_lot` defined here ... -LL | let _ = i_like_to_๐Ÿ˜„_a_lot(); +LL | let _ = i_like_to_๐Ÿ˜„_a_lot() โž– 4; | ^^^^^^^^^^^^^^^^^^ help: a function with a similar name exists: `i_like_to_๐Ÿ˜…_a_lot` error: identifiers cannot contain emojis: `i_like_to_๐Ÿ˜„_a_lot` --> $DIR/emoji-identifiers.rs:13:13 | -LL | let _ = i_like_to_๐Ÿ˜„_a_lot(); +LL | let _ = i_like_to_๐Ÿ˜„_a_lot() โž– 4; | ^^^^^^^^^^^^^^^^^^ error: identifiers cannot contain emojis: `full_of_โœจ` @@ -66,7 +77,7 @@ LL | ๐Ÿ‘€::full_ofโœจ() | function or associated item not found in `๐Ÿ‘€` | help: there is an associated function with a similar name: `full_of_โœจ` -error: aborting due to 8 previous errors +error: aborting due to 9 previous errors Some errors have detailed explanations: E0425, E0599. For more information about an error, try `rustc --explain E0425`. From aaa5c4e33c4b1cb044190ec51f6f1746c54e1d76 Mon Sep 17 00:00:00 2001 From: Esteban Kuber Date: Fri, 10 Sep 2021 07:30:58 +0000 Subject: [PATCH 08/18] review comment: plural of emoji is emoji --- compiler/rustc_interface/src/passes.rs | 2 +- compiler/rustc_parse/src/lexer/mod.rs | 2 +- compiler/rustc_session/src/parse.rs | 2 +- src/test/ui/parser/emoji-identifiers.rs | 12 ++++++------ src/test/ui/parser/emoji-identifiers.stderr | 12 ++++++------ 5 files changed, 15 insertions(+), 15 deletions(-) diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs index f631b46e565d2..aa87a4f53a41c 100644 --- a/compiler/rustc_interface/src/passes.rs +++ b/compiler/rustc_interface/src/passes.rs @@ -450,7 +450,7 @@ pub fn configure_and_expand( for (ident, spans) in identifiers.drain() { sess.diagnostic().span_err( MultiSpan::from(spans), - &format!("identifiers cannot contain emojis: `{}`", ident), + &format!("identifiers cannot contain emoji: `{}`", ident), ); } }); diff --git a/compiler/rustc_parse/src/lexer/mod.rs b/compiler/rustc_parse/src/lexer/mod.rs index 4ee1b839d839a..b0552dda1177d 100644 --- a/compiler/rustc_parse/src/lexer/mod.rs +++ b/compiler/rustc_parse/src/lexer/mod.rs @@ -193,7 +193,7 @@ impl<'a> StringReader<'a> { token::Ident(sym, is_raw_ident) } rustc_lexer::TokenKind::InvalidIdent - // Do not recover an identifier with emojis if the codepoint is a confusable + // Do not recover an identifier with emoji if the codepoint is a confusable // with a recoverable substitution token, like `โž–`. if UNICODE_ARRAY .iter() diff --git a/compiler/rustc_session/src/parse.rs b/compiler/rustc_session/src/parse.rs index 69d02e6c1ae93..24e0cd1862ff3 100644 --- a/compiler/rustc_session/src/parse.rs +++ b/compiler/rustc_session/src/parse.rs @@ -123,7 +123,7 @@ pub struct ParseSess { /// clashing with keywords in new editions. pub raw_identifier_spans: Lock>, /// Places where identifiers that contain invalid Unicode codepoints but that look like they - /// should be. Useful to avoid bad tokenization when encountering emojis. We group them to + /// should be. Useful to avoid bad tokenization when encountering emoji. We group them to /// provide a single error per unique incorrect identifier. pub bad_unicode_identifiers: Lock>>, source_map: Lrc, diff --git a/src/test/ui/parser/emoji-identifiers.rs b/src/test/ui/parser/emoji-identifiers.rs index e07e0573e7594..ef18939bbb80c 100644 --- a/src/test/ui/parser/emoji-identifiers.rs +++ b/src/test/ui/parser/emoji-identifiers.rs @@ -1,16 +1,16 @@ -struct ABig๐Ÿ‘ฉโ€๐Ÿ‘ฉโ€๐Ÿ‘งโ€๐Ÿ‘งFamily; //~ ERROR identifiers cannot contain emojis -struct ๐Ÿ‘€; //~ ERROR identifiers cannot contain emojis +struct ABig๐Ÿ‘ฉโ€๐Ÿ‘ฉโ€๐Ÿ‘งโ€๐Ÿ‘งFamily; //~ ERROR identifiers cannot contain emoji +struct ๐Ÿ‘€; //~ ERROR identifiers cannot contain emoji impl ๐Ÿ‘€ { - fn full_of_โœจ() -> ๐Ÿ‘€ { //~ ERROR identifiers cannot contain emojis + fn full_of_โœจ() -> ๐Ÿ‘€ { //~ ERROR identifiers cannot contain emoji ๐Ÿ‘€ } } -fn i_like_to_๐Ÿ˜…_a_lot() -> ๐Ÿ‘€ { //~ ERROR identifiers cannot contain emojis +fn i_like_to_๐Ÿ˜…_a_lot() -> ๐Ÿ‘€ { //~ ERROR identifiers cannot contain emoji ๐Ÿ‘€::full_ofโœจ() //~ ERROR no function or associated item named `full_ofโœจ` found for struct `๐Ÿ‘€` - //~^ ERROR identifiers cannot contain emojis + //~^ ERROR identifiers cannot contain emoji } fn main() { let _ = i_like_to_๐Ÿ˜„_a_lot() โž– 4; //~ ERROR cannot find function `i_like_to_๐Ÿ˜„_a_lot` in this scope - //~^ ERROR identifiers cannot contain emojis + //~^ ERROR identifiers cannot contain emoji //~| ERROR unknown start of token: \u{2796} } diff --git a/src/test/ui/parser/emoji-identifiers.stderr b/src/test/ui/parser/emoji-identifiers.stderr index a73681d91966b..a69a9c542d6e9 100644 --- a/src/test/ui/parser/emoji-identifiers.stderr +++ b/src/test/ui/parser/emoji-identifiers.stderr @@ -18,25 +18,25 @@ LL | fn i_like_to_๐Ÿ˜…_a_lot() -> ๐Ÿ‘€ { LL | let _ = i_like_to_๐Ÿ˜„_a_lot() โž– 4; | ^^^^^^^^^^^^^^^^^^ help: a function with a similar name exists: `i_like_to_๐Ÿ˜…_a_lot` -error: identifiers cannot contain emojis: `i_like_to_๐Ÿ˜„_a_lot` +error: identifiers cannot contain emoji: `i_like_to_๐Ÿ˜„_a_lot` --> $DIR/emoji-identifiers.rs:13:13 | LL | let _ = i_like_to_๐Ÿ˜„_a_lot() โž– 4; | ^^^^^^^^^^^^^^^^^^ -error: identifiers cannot contain emojis: `full_of_โœจ` +error: identifiers cannot contain emoji: `full_of_โœจ` --> $DIR/emoji-identifiers.rs:4:8 | LL | fn full_of_โœจ() -> ๐Ÿ‘€ { | ^^^^^^^^^^ -error: identifiers cannot contain emojis: `full_ofโœจ` +error: identifiers cannot contain emoji: `full_ofโœจ` --> $DIR/emoji-identifiers.rs:9:8 | LL | ๐Ÿ‘€::full_ofโœจ() | ^^^^^^^^^ -error: identifiers cannot contain emojis: `๐Ÿ‘€` +error: identifiers cannot contain emoji: `๐Ÿ‘€` --> $DIR/emoji-identifiers.rs:2:8 | LL | struct ๐Ÿ‘€; @@ -53,13 +53,13 @@ LL | fn i_like_to_๐Ÿ˜…_a_lot() -> ๐Ÿ‘€ { LL | ๐Ÿ‘€::full_ofโœจ() | ^^ -error: identifiers cannot contain emojis: `i_like_to_๐Ÿ˜…_a_lot` +error: identifiers cannot contain emoji: `i_like_to_๐Ÿ˜…_a_lot` --> $DIR/emoji-identifiers.rs:8:4 | LL | fn i_like_to_๐Ÿ˜…_a_lot() -> ๐Ÿ‘€ { | ^^^^^^^^^^^^^^^^^^ -error: identifiers cannot contain emojis: `ABig๐Ÿ‘ฉ๐Ÿ‘ฉ๐Ÿ‘ง๐Ÿ‘งFamily` +error: identifiers cannot contain emoji: `ABig๐Ÿ‘ฉ๐Ÿ‘ฉ๐Ÿ‘ง๐Ÿ‘งFamily` --> $DIR/emoji-identifiers.rs:1:8 | LL | struct ABig๐Ÿ‘ฉ๐Ÿ‘ฉ๐Ÿ‘ง๐Ÿ‘งFamily; From 2b5cbb2db0610c257bf0447cbe589b9dcaa604b5 Mon Sep 17 00:00:00 2001 From: Esteban Kuber Date: Fri, 10 Sep 2021 07:32:07 +0000 Subject: [PATCH 09/18] `replace_tabs` -> `normalize_whitespace` --- compiler/rustc_errors/src/emitter.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/compiler/rustc_errors/src/emitter.rs b/compiler/rustc_errors/src/emitter.rs index 0dc3f184dc601..47d240b389d64 100644 --- a/compiler/rustc_errors/src/emitter.rs +++ b/compiler/rustc_errors/src/emitter.rs @@ -721,7 +721,7 @@ impl EmitterWriter { } let source_string = match file.get_line(line.line_index - 1) { - Some(s) => replace_tabs(&*s), + Some(s) => normalize_whitespace(&*s), None => return Vec::new(), }; @@ -1272,7 +1272,7 @@ impl EmitterWriter { buffer.append(0, ": ", header_style); } for &(ref text, _) in msg.iter() { - buffer.append(0, &replace_tabs(text), header_style); + buffer.append(0, &normalize_whitespace(text), header_style); } } @@ -1526,7 +1526,7 @@ impl EmitterWriter { self.draw_line( &mut buffer, - &replace_tabs(&unannotated_line), + &normalize_whitespace(&unannotated_line), annotated_file.lines[line_idx + 1].line_index - 1, last_buffer_line_num, width_offset, @@ -1648,7 +1648,7 @@ impl EmitterWriter { buffer.puts( row_num - 1, max_line_num_len + 3, - &replace_tabs( + &normalize_whitespace( &*file_lines .file .get_line(file_lines.lines[line_pos].line_index) @@ -1674,7 +1674,7 @@ impl EmitterWriter { } // print the suggestion - buffer.append(row_num, &replace_tabs(line), Style::NoStyle); + buffer.append(row_num, &normalize_whitespace(line), Style::NoStyle); // Colorize addition/replacements with green. for &SubstitutionHighlight { start, end } in highlight_parts { @@ -2059,7 +2059,7 @@ const REPLACEMENTS: &[(char, &str)] = &[ ('\u{200D}', ""), // Replace ZWJ with nothing for consistent terminal output of grapheme clusters. ]; -fn replace_tabs(str: &str) -> String { +fn normalize_whitespace(str: &str) -> String { let mut output = str.to_string(); for (c, replacement) in REPLACEMENTS { output = output.replace(*c, replacement); From 5979ed5e37fad5f0696875e8abf72c982f5d60af Mon Sep 17 00:00:00 2001 From: Esteban Kuber Date: Fri, 10 Sep 2021 07:36:01 +0000 Subject: [PATCH 10/18] udpate comment to be more accurate --- compiler/rustc_lexer/src/lib.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/compiler/rustc_lexer/src/lib.rs b/compiler/rustc_lexer/src/lib.rs index a729c0c0bbea3..44b002fa93f42 100644 --- a/compiler/rustc_lexer/src/lib.rs +++ b/compiler/rustc_lexer/src/lib.rs @@ -413,8 +413,7 @@ impl Cursor<'_> { let kind = Str { terminated }; Literal { kind, suffix_start } } - // Identifier (this should be checked after other variant that can - // start as identifier). + // Identifier starting with an emoji. Only lexed for graceful error recovery. c if !c.is_ascii() && unic_emoji_char::is_emoji(c) => { self.fake_ident_or_unknown_prefix() } From 2c30162380ac06e5e6b084164ee6ba596a9398f0 Mon Sep 17 00:00:00 2001 From: Waffle Lapkin Date: Sat, 11 Sep 2021 00:07:14 +0300 Subject: [PATCH 11/18] Fill in the tracking issue for `#![feature(const_unsafecell_get_mut)]` --- library/core/src/cell.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/core/src/cell.rs b/library/core/src/cell.rs index 25c153dae04e3..e56b631dbaf8d 100644 --- a/library/core/src/cell.rs +++ b/library/core/src/cell.rs @@ -1916,7 +1916,7 @@ impl UnsafeCell { /// ``` #[inline(always)] #[stable(feature = "unsafe_cell_get_mut", since = "1.50.0")] - #[rustc_const_unstable(feature = "const_unsafecell_get_mut", issue = "none")] + #[rustc_const_unstable(feature = "const_unsafecell_get_mut", issue = "88836")] pub const fn get_mut(&mut self) -> &mut T { &mut self.value } From a0b83f542f91699838c65d772b0eb6aeb276fb67 Mon Sep 17 00:00:00 2001 From: Deadbeef Date: Sat, 11 Sep 2021 09:40:19 +0000 Subject: [PATCH 12/18] Fix duplicate bounds for const_trait_impl --- .../rustc_trait_selection/src/traits/select/mod.rs | 5 +++-- .../call-generic-method-dup-bound.rs | 13 +++++++++---- 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index 22013fb79cf79..3c83938ce43ee 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -1487,10 +1487,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { ) => false, (ParamCandidate(other), ParamCandidate(victim)) => { - let value_same_except_bound_vars = other.value.skip_binder() + let same_except_bound_vars = other.value.skip_binder() == victim.value.skip_binder() + && other.constness == victim.constness && !other.value.skip_binder().has_escaping_bound_vars(); - if value_same_except_bound_vars { + if same_except_bound_vars { // See issue #84398. In short, we can generate multiple ParamCandidates which are // the same except for unused bound vars. Just pick the one with the fewest bound vars // or the current one if tied (they should both evaluate to the same answer). This is diff --git a/src/test/ui/rfc-2632-const-trait-impl/call-generic-method-dup-bound.rs b/src/test/ui/rfc-2632-const-trait-impl/call-generic-method-dup-bound.rs index 7185376b440c8..cc24dbd96d253 100644 --- a/src/test/ui/rfc-2632-const-trait-impl/call-generic-method-dup-bound.rs +++ b/src/test/ui/rfc-2632-const-trait-impl/call-generic-method-dup-bound.rs @@ -16,12 +16,17 @@ impl const PartialEq for S { // This duplicate bound should not result in ambiguities. It should be equivalent to a single ~const // bound. -// const fn equals_self(t: &T) -> bool { -// FIXME(fee1-dead)^ why should the order matter here? -const fn equals_self(t: &T) -> bool { +const fn equals_self(t: &T) -> bool { *t == *t } -pub const EQ: bool = equals_self(&S); +trait A: PartialEq {} +impl A for T {} + +const fn equals_self2(t: &T) -> bool { + *t == *t +} + +pub const EQ: bool = equals_self(&S) && equals_self2(&S); fn main() {} From 07b64bfd3a292cda71f7e0e2211691feef649a75 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 11 Sep 2021 11:58:08 -0400 Subject: [PATCH 13/18] interpreter PointerArithmetic: use new Size helper methods --- compiler/rustc_middle/src/mir/interpret/pointer.rs | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/compiler/rustc_middle/src/mir/interpret/pointer.rs b/compiler/rustc_middle/src/mir/interpret/pointer.rs index 3eee45a9230d1..c9dc5a0f3b5ec 100644 --- a/compiler/rustc_middle/src/mir/interpret/pointer.rs +++ b/compiler/rustc_middle/src/mir/interpret/pointer.rs @@ -3,7 +3,7 @@ use super::{AllocId, InterpResult}; use rustc_macros::HashStable; use rustc_target::abi::{HasDataLayout, Size}; -use std::convert::TryFrom; +use std::convert::{TryFrom, TryInto}; use std::fmt; //////////////////////////////////////////////////////////////////////////////// @@ -20,29 +20,27 @@ pub trait PointerArithmetic: HasDataLayout { #[inline] fn machine_usize_max(&self) -> u64 { - let max_usize_plus_1 = 1u128 << self.pointer_size().bits(); - u64::try_from(max_usize_plus_1 - 1).unwrap() + self.pointer_size().unsigned_int_max().try_into().unwrap() } #[inline] fn machine_isize_min(&self) -> i64 { - let max_isize_plus_1 = 1i128 << (self.pointer_size().bits() - 1); - i64::try_from(-max_isize_plus_1).unwrap() + self.pointer_size().signed_int_min().try_into().unwrap() } #[inline] fn machine_isize_max(&self) -> i64 { - let max_isize_plus_1 = 1u128 << (self.pointer_size().bits() - 1); - i64::try_from(max_isize_plus_1 - 1).unwrap() + self.pointer_size().signed_int_max().try_into().unwrap() } #[inline] fn machine_usize_to_isize(&self, val: u64) -> i64 { let val = val as i64; - // Now clamp into the machine_isize range. + // Now wrap-around into the machine_isize range. if val > self.machine_isize_max() { // This can only happen the the ptr size is < 64, so we know max_usize_plus_1 fits into // i64. + debug_assert!(self.pointer_size().bits() < 64); let max_usize_plus_1 = 1u128 << self.pointer_size().bits(); val - i64::try_from(max_usize_plus_1).unwrap() } else { From 6a2f500d8711b642d412ee7ce4d29af24f702223 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sun, 12 Sep 2021 16:33:57 +0200 Subject: [PATCH 14/18] Fix invalid background for jump-to-def links in source code pages --- src/librustdoc/html/static/css/themes/ayu.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustdoc/html/static/css/themes/ayu.css b/src/librustdoc/html/static/css/themes/ayu.css index f9ddef4120bbe..eada8f4a04dae 100644 --- a/src/librustdoc/html/static/css/themes/ayu.css +++ b/src/librustdoc/html/static/css/themes/ayu.css @@ -217,7 +217,7 @@ a { color: #c5c5c5; } body.source .example-wrap pre.rust a { - background: #c5c5c5; + background: #333; } .docblock:not(.type-decl) a:not(.srclink):not(.test-arrow), From cefa900a0f060c96f8763d95b54fc2fe29ebc073 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sun, 12 Sep 2021 16:34:18 +0200 Subject: [PATCH 15/18] Reduce possibility of flaky tests --- src/test/rustdoc-gui/code-sidebar-toggle.goml | 1 + 1 file changed, 1 insertion(+) diff --git a/src/test/rustdoc-gui/code-sidebar-toggle.goml b/src/test/rustdoc-gui/code-sidebar-toggle.goml index 00326e9bbc4cc..6fb92e196602e 100644 --- a/src/test/rustdoc-gui/code-sidebar-toggle.goml +++ b/src/test/rustdoc-gui/code-sidebar-toggle.goml @@ -1,5 +1,6 @@ goto: file://|DOC_PATH|/test_docs/index.html click: ".srclink" +wait-for: "#sidebar-toggle" click: "#sidebar-toggle" wait-for: 500 fail: true From 8f3fd3d08c540d361dc70f48cb6ad51b904b1277 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sat, 14 Aug 2021 20:17:28 +0200 Subject: [PATCH 16/18] Add support for primitives in "jump to definition" feature --- src/librustdoc/html/highlight.rs | 8 ++++++++ src/librustdoc/html/render/span_map.rs | 18 +++++++++++------- 2 files changed, 19 insertions(+), 7 deletions(-) diff --git a/src/librustdoc/html/highlight.rs b/src/librustdoc/html/highlight.rs index f8fc9243e14b9..ece3ee640e2a6 100644 --- a/src/librustdoc/html/highlight.rs +++ b/src/librustdoc/html/highlight.rs @@ -5,6 +5,7 @@ //! //! Use the `render_with_highlighting` to highlight some rust code. +use crate::clean::PrimitiveType; use crate::html::escape::Escape; use crate::html::render::Context; @@ -584,6 +585,13 @@ fn string( .ok() .map(|(url, _, _)| url) } + LinkFromSrc::Primitive(prim) => format::href_with_root_path( + PrimitiveType::primitive_locations(context.tcx())[&prim], + context, + Some(context_info.root_path), + ) + .ok() + .map(|(url, _, _)| url), } }) { diff --git a/src/librustdoc/html/render/span_map.rs b/src/librustdoc/html/render/span_map.rs index 54476d9c9a459..d517f3ac0e3a9 100644 --- a/src/librustdoc/html/render/span_map.rs +++ b/src/librustdoc/html/render/span_map.rs @@ -1,4 +1,4 @@ -use crate::clean; +use crate::clean::{self, PrimitiveType}; use crate::html::sources; use rustc_data_structures::fx::FxHashMap; @@ -22,6 +22,7 @@ use std::path::{Path, PathBuf}; crate enum LinkFromSrc { Local(clean::Span), External(DefId), + Primitive(PrimitiveType), } /// This function will do at most two things: @@ -73,17 +74,20 @@ impl<'tcx> SpanMapVisitor<'tcx> { Some(def_id) } Res::Local(_) => None, + Res::PrimTy(p) => { + // FIXME: Doesn't handle "path-like" primitives like arrays or tuples. + let span = path_span.unwrap_or(path.span); + self.matches.insert(span, LinkFromSrc::Primitive(PrimitiveType::from(p))); + return; + } Res::Err => return, _ => return, }; if let Some(span) = self.tcx.hir().res_span(path.res) { - self.matches.insert( - path_span.unwrap_or_else(|| path.span), - LinkFromSrc::Local(clean::Span::new(span)), - ); - } else if let Some(def_id) = info { self.matches - .insert(path_span.unwrap_or_else(|| path.span), LinkFromSrc::External(def_id)); + .insert(path_span.unwrap_or(path.span), LinkFromSrc::Local(clean::Span::new(span))); + } else if let Some(def_id) = info { + self.matches.insert(path_span.unwrap_or(path.span), LinkFromSrc::External(def_id)); } } } From d73c0a3d6905a1c6cba7a78c2a5dd7b922f39a8f Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sat, 14 Aug 2021 20:17:43 +0200 Subject: [PATCH 17/18] Add test for primitive in "jump to definition" feature --- .../check-source-code-urls-to-def-std.rs | 17 +++++++++++++++++ .../rustdoc/check-source-code-urls-to-def.rs | 8 +++++++- 2 files changed, 24 insertions(+), 1 deletion(-) create mode 100644 src/test/rustdoc/check-source-code-urls-to-def-std.rs diff --git a/src/test/rustdoc/check-source-code-urls-to-def-std.rs b/src/test/rustdoc/check-source-code-urls-to-def-std.rs new file mode 100644 index 0000000000000..b129ceb5b7302 --- /dev/null +++ b/src/test/rustdoc/check-source-code-urls-to-def-std.rs @@ -0,0 +1,17 @@ +// compile-flags: -Zunstable-options --generate-link-to-definition + +#![crate_name = "foo"] + +// @has 'src/foo/check-source-code-urls-to-def-std.rs.html' + +fn babar() {} + +// @has - '//a[@href="{{channel}}/std/primitive.u32.html"]' 'u32' +// @has - '//a[@href="{{channel}}/std/primitive.str.html"]' 'str' +// @has - '//a[@href="{{channel}}/std/primitive.bool.html"]' 'bool' +// @has - '//a[@href="../../src/foo/check-source-code-urls-to-def-std.rs.html#7"]' 'babar' +pub fn foo(a: u32, b: &str, c: String) { + let x = 12; + let y: bool = true; + babar(); +} diff --git a/src/test/rustdoc/check-source-code-urls-to-def.rs b/src/test/rustdoc/check-source-code-urls-to-def.rs index e3ae79ccdb17a..0cb8e4230166f 100644 --- a/src/test/rustdoc/check-source-code-urls-to-def.rs +++ b/src/test/rustdoc/check-source-code-urls-to-def.rs @@ -27,6 +27,8 @@ impl Foo { fn babar() {} // @has - '//a/@href' '/struct.String.html' +// @has - '//a/@href' '/primitive.u32.html' +// @has - '//a/@href' '/primitive.str.html' // @count - '//a[@href="../../src/foo/check-source-code-urls-to-def.rs.html#21"]' 5 // @has - '//a[@href="../../source_code/struct.SourceCode.html"]' 'source_code::SourceCode' pub fn foo(a: u32, b: &str, c: String, d: Foo, e: bar::Bar, f: source_code::SourceCode) { @@ -40,5 +42,9 @@ pub fn foo(a: u32, b: &str, c: String, d: Foo, e: bar::Bar, f: source_code::Sour // @has - '//a[@href="../../src/foo/auxiliary/source-code-bar.rs.html#14-16"]' 'bar::sub::Trait' // @has - '//a[@href="../../src/foo/auxiliary/source-code-bar.rs.html#14-16"]' 'Trait' -pub fn foo2(t: &T, v: &V) { +pub fn foo2(t: &T, v: &V, b: bool) { } + +// @has - '//a[@href="../../foo/primitive.bool.html"]' 'bool' +#[doc(primitive = "bool")] +mod whatever {} From 9e482c1add7e02ef3367caa96909e32bf8cdcaf6 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sun, 12 Sep 2021 15:43:30 +0200 Subject: [PATCH 18/18] * Enable generate-link-to-def feature on a rustdoc GUI test * Add test for jump-to-def links background color --- src/bootstrap/test.rs | 5 ++++ .../rustdoc-gui/jump-to-def-background.goml | 23 +++++++++++++++++++ .../src/link_to_definition/Cargo.lock | 7 ++++++ .../src/link_to_definition/Cargo.toml | 7 ++++++ .../rustdoc-gui/src/link_to_definition/lib.rs | 6 +++++ 5 files changed, 48 insertions(+) create mode 100644 src/test/rustdoc-gui/jump-to-def-background.goml create mode 100644 src/test/rustdoc-gui/src/link_to_definition/Cargo.lock create mode 100644 src/test/rustdoc-gui/src/link_to_definition/Cargo.toml create mode 100644 src/test/rustdoc-gui/src/link_to_definition/lib.rs diff --git a/src/bootstrap/test.rs b/src/bootstrap/test.rs index d12e86b7c1deb..386ffb384a81e 100644 --- a/src/bootstrap/test.rs +++ b/src/bootstrap/test.rs @@ -925,6 +925,11 @@ impl Step for RustdocGUI { .env("RUSTDOC", builder.rustdoc(self.compiler)) .env("RUSTC", builder.rustc(self.compiler)) .current_dir(path); + // FIXME: implement a `// compile-flags` command or similar + // instead of hard-coding this test + if entry.file_name() == "link_to_definition" { + cargo.env("RUSTDOCFLAGS", "-Zunstable-options --generate-link-to-definition"); + } builder.run(&mut cargo); } } diff --git a/src/test/rustdoc-gui/jump-to-def-background.goml b/src/test/rustdoc-gui/jump-to-def-background.goml new file mode 100644 index 0000000000000..3df899e0f2618 --- /dev/null +++ b/src/test/rustdoc-gui/jump-to-def-background.goml @@ -0,0 +1,23 @@ +// We check the background color on the jump to definition links in the source code page. +goto: file://|DOC_PATH|/src/link_to_definition/lib.rs.html + +// Set the theme to dark. +local-storage: {"rustdoc-theme": "dark", "rustdoc-preferred-dark-theme": "dark", "rustdoc-use-system-theme": "false"} +// We reload the page so the local storage settings are being used. +reload: + +assert-css: ("body.source .example-wrap pre.rust a", {"background-color": "rgb(51, 51, 51)"}, ALL) + +// Set the theme to ayu. +local-storage: {"rustdoc-theme": "ayu", "rustdoc-preferred-dark-theme": "ayu", "rustdoc-use-system-theme": "false"} +// We reload the page so the local storage settings are being used. +reload: + +assert-css: ("body.source .example-wrap pre.rust a", {"background-color": "rgb(51, 51, 51)"}, ALL) + +// Set the theme to light. +local-storage: {"rustdoc-theme": "light", "rustdoc-use-system-theme": "false"} +// We reload the page so the local storage settings are being used. +reload: + +assert-css: ("body.source .example-wrap pre.rust a", {"background-color": "rgb(238, 238, 238)"}, ALL) diff --git a/src/test/rustdoc-gui/src/link_to_definition/Cargo.lock b/src/test/rustdoc-gui/src/link_to_definition/Cargo.lock new file mode 100644 index 0000000000000..e4b4e52d028e5 --- /dev/null +++ b/src/test/rustdoc-gui/src/link_to_definition/Cargo.lock @@ -0,0 +1,7 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "link_to_definition" +version = "0.1.0" diff --git a/src/test/rustdoc-gui/src/link_to_definition/Cargo.toml b/src/test/rustdoc-gui/src/link_to_definition/Cargo.toml new file mode 100644 index 0000000000000..cdd294d74d3ae --- /dev/null +++ b/src/test/rustdoc-gui/src/link_to_definition/Cargo.toml @@ -0,0 +1,7 @@ +[package] +name = "link_to_definition" +version = "0.1.0" +edition = "2018" + +[lib] +path = "lib.rs" diff --git a/src/test/rustdoc-gui/src/link_to_definition/lib.rs b/src/test/rustdoc-gui/src/link_to_definition/lib.rs new file mode 100644 index 0000000000000..de9ee66a2bad0 --- /dev/null +++ b/src/test/rustdoc-gui/src/link_to_definition/lib.rs @@ -0,0 +1,6 @@ +pub struct Bar { + pub a: String, + pub b: u32, +} + +pub fn foo(_b: &Bar) {}