diff --git a/Cargo.lock b/Cargo.lock index cde73166babb7..a6fd8a4938c28 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3980,6 +3980,7 @@ name = "rustc_lexer" version = "0.1.0" dependencies = [ "expect-test", + "unic-emoji-char", "unicode-xid", ] @@ -5443,6 +5444,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_errors/src/emitter.rs b/compiler/rustc_errors/src/emitter.rs index 29f352ae58559..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 { @@ -2054,8 +2054,17 @@ fn num_decimal_digits(num: usize) -> usize { MAX_DIGITS } -fn replace_tabs(str: &str) -> String { - str.replace('\t', " ") +const REPLACEMENTS: &[(char, &str)] = &[ + ('\t', " "), + ('\u{200D}', ""), // Replace ZWJ with nothing for consistent terminal output of grapheme clusters. +]; + +fn normalize_whitespace(str: &str) -> String { + 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/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs index 1f3d6f70ff837..aa87a4f53a41c 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 emoji: `{}`", 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..44b002fa93f42 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,10 @@ impl Cursor<'_> { let kind = Str { terminated }; Literal { kind, suffix_start } } + // 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() + } _ => Unknown, }; Token::new(token_kind, self.len_consumed()) @@ -492,10 +498,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_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 { diff --git a/compiler/rustc_parse/src/lexer/mod.rs b/compiler/rustc_parse/src/lexer/mod.rs index 1e65cc27154a8..b0552dda1177d 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,6 +192,22 @@ impl<'a> StringReader<'a> { } token::Ident(sym, is_raw_ident) } + rustc_lexer::TokenKind::InvalidIdent + // Do not recover an identifier with emoji 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); + 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); @@ -262,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/compiler/rustc_session/src/parse.rs b/compiler/rustc_session/src/parse.rs index a007b53030271..24e0cd1862ff3 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 emoji. 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/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index f5be8bf0949e6..8adf9015933c3 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/library/core/src/cell.rs b/library/core/src/cell.rs index 2adf6a549e641..e56b631dbaf8d 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 = "88836")] + pub const fn get_mut(&mut self) -> &mut T { &mut self.value } 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/librustdoc/html/highlight.rs b/src/librustdoc/html/highlight.rs index f8fc9243e14b9..3128d97922515 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; @@ -488,7 +489,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, @@ -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)); } } } 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), 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 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) {} 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 {} diff --git a/src/test/ui/parser/emoji-identifiers.rs b/src/test/ui/parser/emoji-identifiers.rs new file mode 100644 index 0000000000000..ef18939bbb80c --- /dev/null +++ b/src/test/ui/parser/emoji-identifiers.rs @@ -0,0 +1,16 @@ +struct ABig๐Ÿ‘ฉโ€๐Ÿ‘ฉโ€๐Ÿ‘งโ€๐Ÿ‘งFamily; //~ ERROR identifiers cannot contain emoji +struct ๐Ÿ‘€; //~ ERROR identifiers cannot contain emoji +impl ๐Ÿ‘€ { + fn full_of_โœจ() -> ๐Ÿ‘€ { //~ ERROR identifiers cannot contain emoji + ๐Ÿ‘€ + } +} +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 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 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 new file mode 100644 index 0000000000000..a69a9c542d6e9 --- /dev/null +++ b/src/test/ui/parser/emoji-identifiers.stderr @@ -0,0 +1,83 @@ +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() โž– 4; + | ^^^^^^^^^^^^^^^^^^ help: a function with a similar name exists: `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 emoji: `full_of_โœจ` + --> $DIR/emoji-identifiers.rs:4:8 + | +LL | fn full_of_โœจ() -> ๐Ÿ‘€ { + | ^^^^^^^^^^ + +error: identifiers cannot contain emoji: `full_ofโœจ` + --> $DIR/emoji-identifiers.rs:9:8 + | +LL | ๐Ÿ‘€::full_ofโœจ() + | ^^^^^^^^^ + +error: identifiers cannot contain emoji: `๐Ÿ‘€` + --> $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 emoji: `i_like_to_๐Ÿ˜…_a_lot` + --> $DIR/emoji-identifiers.rs:8:4 + | +LL | fn i_like_to_๐Ÿ˜…_a_lot() -> ๐Ÿ‘€ { + | ^^^^^^^^^^^^^^^^^^ + +error: identifiers cannot contain emoji: `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 9 previous errors + +Some errors have detailed explanations: E0425, E0599. +For more information about an error, try `rustc --explain E0425`. 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() {} 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",