diff --git a/Cargo.lock b/Cargo.lock index 5530541cdd0f1..74bb3c8e6c285 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2287,6 +2287,7 @@ dependencies = [ "anyhow", "clap 4.1.4", "fs-err", + "rustc-hash", "rustdoc-json-types", "serde", "serde_json", @@ -4850,6 +4851,7 @@ dependencies = [ name = "rustdoc-json-types" version = "0.1.0" dependencies = [ + "rustc-hash", "serde", "serde_json", ] diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs index 2cc009410f407..539c822ea0977 100644 --- a/compiler/rustc_ast_passes/src/ast_validation.rs +++ b/compiler/rustc_ast_passes/src/ast_validation.rs @@ -12,7 +12,7 @@ use rustc_ast::visit::{self, AssocCtxt, BoundKind, FnCtxt, FnKind, Visitor}; use rustc_ast::walk_list; use rustc_ast::*; use rustc_ast_pretty::pprust::{self, State}; -use rustc_data_structures::fx::FxHashMap; +use rustc_data_structures::fx::FxIndexMap; use rustc_macros::Subdiagnostic; use rustc_parse::validate_attr; use rustc_session::lint::builtin::{ @@ -643,7 +643,7 @@ fn validate_generic_param_order( span: Span, ) { let mut max_param: Option = None; - let mut out_of_order = FxHashMap::default(); + let mut out_of_order = FxIndexMap::default(); let mut param_idents = Vec::with_capacity(generics.len()); for (idx, param) in generics.iter().enumerate() { diff --git a/compiler/rustc_ast_passes/src/lib.rs b/compiler/rustc_ast_passes/src/lib.rs index b9dcaee2373d2..6207a32b28de6 100644 --- a/compiler/rustc_ast_passes/src/lib.rs +++ b/compiler/rustc_ast_passes/src/lib.rs @@ -4,7 +4,6 @@ //! //! The crate also contains other misc AST visitors, e.g. `node_count` and `show_span`. -#![allow(rustc::potential_query_instability)] #![feature(box_patterns)] #![feature(if_let_guard)] #![feature(iter_is_partitioned)] diff --git a/compiler/rustc_errors/src/emitter.rs b/compiler/rustc_errors/src/emitter.rs index 211bbf4f50e68..1b2e7b7e083b4 100644 --- a/compiler/rustc_errors/src/emitter.rs +++ b/compiler/rustc_errors/src/emitter.rs @@ -1895,7 +1895,7 @@ impl EmitterWriter { self.draw_code_line( &mut buffer, &mut row_num, - &Vec::new(), + &[], p + line_start, l, show_code_change, @@ -1919,7 +1919,7 @@ impl EmitterWriter { self.draw_code_line( &mut buffer, &mut row_num, - &Vec::new(), + &[], p + line_start, l, show_code_change, @@ -1936,7 +1936,7 @@ impl EmitterWriter { self.draw_code_line( &mut buffer, &mut row_num, - &Vec::new(), + &[], p + line_start, l, show_code_change, @@ -1951,7 +1951,7 @@ impl EmitterWriter { self.draw_code_line( &mut buffer, &mut row_num, - highlight_parts, + &highlight_parts, line_pos + line_start, line, show_code_change, @@ -2176,7 +2176,7 @@ impl EmitterWriter { &self, buffer: &mut StyledBuffer, row_num: &mut usize, - highlight_parts: &Vec, + highlight_parts: &[SubstitutionHighlight], line_num: usize, line_to_add: &str, show_code_change: DisplaySuggestion, diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index cbf595089ccc6..99af872f07f30 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -331,7 +331,7 @@ impl CodeSuggestion { }); buf.push_str(&part.snippet); let cur_hi = sm.lookup_char_pos(part.span.hi()); - if prev_hi.line == cur_lo.line && cur_hi.line == cur_lo.line { + if cur_hi.line == cur_lo.line { // Account for the difference between the width of the current code and the // snippet being suggested, so that the *later* suggestions are correctly // aligned on the screen. diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs index a051dbe9ff5b9..0a65c37ea7b79 100644 --- a/compiler/rustc_parse/src/parser/diagnostics.rs +++ b/compiler/rustc_parse/src/parser/diagnostics.rs @@ -19,7 +19,6 @@ use crate::errors::{ }; use crate::fluent_generated as fluent; -use crate::lexer::UnmatchedDelim; use crate::parser; use rustc_ast as ast; use rustc_ast::ptr::P; @@ -220,7 +219,6 @@ impl MultiSugg { /// is dropped. pub struct SnapshotParser<'a> { parser: Parser<'a>, - unclosed_delims: Vec, } impl<'a> Deref for SnapshotParser<'a> { @@ -255,27 +253,15 @@ impl<'a> Parser<'a> { &self.sess.span_diagnostic } - /// Replace `self` with `snapshot.parser` and extend `unclosed_delims` with `snapshot.unclosed_delims`. - /// This is to avoid losing unclosed delims errors `create_snapshot_for_diagnostic` clears. + /// Replace `self` with `snapshot.parser`. pub(super) fn restore_snapshot(&mut self, snapshot: SnapshotParser<'a>) { *self = snapshot.parser; - self.unclosed_delims.extend(snapshot.unclosed_delims); - } - - pub fn unclosed_delims(&self) -> &[UnmatchedDelim] { - &self.unclosed_delims } /// Create a snapshot of the `Parser`. pub fn create_snapshot_for_diagnostic(&self) -> SnapshotParser<'a> { - let mut snapshot = self.clone(); - let unclosed_delims = self.unclosed_delims.clone(); - // Clear `unclosed_delims` in snapshot to avoid - // duplicate errors being emitted when the `Parser` - // is dropped (which may or may not happen, depending - // if the parsing the snapshot is created for is successful) - snapshot.unclosed_delims.clear(); - SnapshotParser { parser: snapshot, unclosed_delims } + let snapshot = self.clone(); + SnapshotParser { parser: snapshot } } pub(super) fn span_to_snippet(&self, span: Span) -> Result { @@ -579,21 +565,6 @@ impl<'a> Parser<'a> { } else { label_sp }; - match self.recover_closing_delimiter( - &expected - .iter() - .filter_map(|tt| match tt { - TokenType::Token(t) => Some(t.clone()), - _ => None, - }) - .collect::>(), - err, - ) { - Err(e) => err = e, - Ok(recovered) => { - return Ok(recovered); - } - } if self.check_too_many_raw_str_terminators(&mut err) { if expected.contains(&TokenType::Token(token::Semi)) && self.eat(&token::Semi) { @@ -1573,12 +1544,6 @@ impl<'a> Parser<'a> { ); let mut err = self.struct_span_err(sp, &msg); let label_exp = format!("expected `{token_str}`"); - match self.recover_closing_delimiter(&[t.clone()], err) { - Err(e) => err = e, - Ok(recovered) => { - return Ok(recovered); - } - } let sm = self.sess.source_map(); if !sm.is_multiline(prev_sp.until(sp)) { // When the spans are in the same line, it means that the only content @@ -1795,81 +1760,6 @@ impl<'a> Parser<'a> { } } - pub(super) fn recover_closing_delimiter( - &mut self, - tokens: &[TokenKind], - mut err: DiagnosticBuilder<'a, ErrorGuaranteed>, - ) -> PResult<'a, bool> { - let mut pos = None; - // We want to use the last closing delim that would apply. - for (i, unmatched) in self.unclosed_delims.iter().enumerate().rev() { - if tokens.contains(&token::CloseDelim(unmatched.expected_delim)) - && Some(self.token.span) > unmatched.unclosed_span - { - pos = Some(i); - } - } - match pos { - Some(pos) => { - // Recover and assume that the detected unclosed delimiter was meant for - // this location. Emit the diagnostic and act as if the delimiter was - // present for the parser's sake. - - // Don't attempt to recover from this unclosed delimiter more than once. - let unmatched = self.unclosed_delims.remove(pos); - let delim = TokenType::Token(token::CloseDelim(unmatched.expected_delim)); - if unmatched.found_delim.is_none() { - // We encountered `Eof`, set this fact here to avoid complaining about missing - // `fn main()` when we found place to suggest the closing brace. - *self.sess.reached_eof.borrow_mut() = true; - } - - // We want to suggest the inclusion of the closing delimiter where it makes - // the most sense, which is immediately after the last token: - // - // {foo(bar {}} - // ^ ^ - // | | - // | help: `)` may belong here - // | - // unclosed delimiter - if let Some(sp) = unmatched.unclosed_span { - let mut primary_span: Vec = - err.span.primary_spans().iter().cloned().collect(); - primary_span.push(sp); - let mut primary_span: MultiSpan = primary_span.into(); - for span_label in err.span.span_labels() { - if let Some(label) = span_label.label { - primary_span.push_span_label(span_label.span, label); - } - } - err.set_span(primary_span); - err.span_label(sp, "unclosed delimiter"); - } - // Backticks should be removed to apply suggestions. - let mut delim = delim.to_string(); - delim.retain(|c| c != '`'); - err.span_suggestion_short( - self.prev_token.span.shrink_to_hi(), - &format!("`{delim}` may belong here"), - delim, - Applicability::MaybeIncorrect, - ); - if unmatched.found_delim.is_none() { - // Encountered `Eof` when lexing blocks. Do not recover here to avoid knockdown - // errors which would be emitted elsewhere in the parser and let other error - // recovery consume the rest of the file. - Err(err) - } else { - err.emit(); - self.expected_tokens.clear(); // Reduce the number of errors. - Ok(true) - } - } - _ => Err(err), - } - } - /// Eats tokens until we can be relatively sure we reached the end of the /// statement. This is something of a best-effort heuristic. /// diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index 95a7ca80d5d73..e00eda47c663e 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -1394,19 +1394,6 @@ impl<'a> Parser<'a> { self.parse_expr_let() } else if self.eat_keyword(kw::Underscore) { Ok(self.mk_expr(self.prev_token.span, ExprKind::Underscore)) - } else if !self.unclosed_delims.is_empty() && self.check(&token::Semi) { - // Don't complain about bare semicolons after unclosed braces - // recovery in order to keep the error count down. Fixing the - // delimiters will possibly also fix the bare semicolon found in - // expression context. For example, silence the following error: - // - // error: expected expression, found `;` - // --> file.rs:2:13 - // | - // 2 | foo(bar(; - // | ^ expected expression - self.bump(); - Ok(self.mk_expr_err(self.token.span)) } else if self.token.uninterpolated_span().rust_2018() { // `Span::rust_2018()` is somewhat expensive; don't get it repeatedly. if self.check_keyword(kw::Async) { diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs index 9d9ae154ad42e..85cc8ca02a977 100644 --- a/compiler/rustc_parse/src/parser/item.rs +++ b/compiler/rustc_parse/src/parser/item.rs @@ -125,16 +125,13 @@ impl<'a> Parser<'a> { return Ok(Some(item.into_inner())); }; - let mut unclosed_delims = vec![]; let item = self.collect_tokens_trailing_token(attrs, force_collect, |this: &mut Self, attrs| { let item = this.parse_item_common_(attrs, mac_allowed, attrs_allowed, fn_parse_mode); - unclosed_delims.append(&mut this.unclosed_delims); Ok((item?, TrailingToken::None)) })?; - self.unclosed_delims.append(&mut unclosed_delims); Ok(item) } @@ -1960,21 +1957,12 @@ impl<'a> Parser<'a> { // FIXME: This will make us not emit the help even for declarative // macros within the same crate (that we can fix), which is sad. if !span.from_expansion() { - if self.unclosed_delims.is_empty() { - let DelimSpan { open, close } = args.dspan; - err.multipart_suggestion( - "change the delimiters to curly braces", - vec![(open, "{".to_string()), (close, '}'.to_string())], - Applicability::MaybeIncorrect, - ); - } else { - err.span_suggestion( - span, - "change the delimiters to curly braces", - " { /* items */ }", - Applicability::HasPlaceholders, - ); - } + let DelimSpan { open, close } = args.dspan; + err.multipart_suggestion( + "change the delimiters to curly braces", + vec![(open, "{".to_string()), (close, '}'.to_string())], + Applicability::MaybeIncorrect, + ); err.span_suggestion( span.shrink_to_hi(), "add a semicolon", diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs index da82e4724d1b5..6e9b447fa61a9 100644 --- a/compiler/rustc_parse/src/parser/mod.rs +++ b/compiler/rustc_parse/src/parser/mod.rs @@ -146,10 +146,7 @@ pub struct Parser<'a> { /// See the comments in the `parse_path_segment` function for more details. unmatched_angle_bracket_count: u32, max_angle_bracket_count: u32, - /// A list of all unclosed delimiters found by the lexer. If an entry is used for error recovery - /// it gets removed from here. Every entry left at the end gets emitted as an independent - /// error. - pub(super) unclosed_delims: Vec, + last_unexpected_token_span: Option, /// Span pointing at the `:` for the last type ascription the parser has seen, and whether it /// looked like it could have been a mistyped path or literal `Option:Some(42)`). @@ -168,7 +165,7 @@ pub struct Parser<'a> { // This type is used a lot, e.g. it's cloned when matching many declarative macro rules with nonterminals. Make sure // it doesn't unintentionally get bigger. #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] -rustc_data_structures::static_assert_size!(Parser<'_>, 312); +rustc_data_structures::static_assert_size!(Parser<'_>, 288); /// Stores span information about a closure. #[derive(Clone)] @@ -215,12 +212,6 @@ struct CaptureState { inner_attr_ranges: FxHashMap, } -impl<'a> Drop for Parser<'a> { - fn drop(&mut self) { - emit_unclosed_delims(&mut self.unclosed_delims, &self.sess); - } -} - /// Iterator over a `TokenStream` that produces `Token`s. It's a bit odd that /// we (a) lex tokens into a nice tree structure (`TokenStream`), and then (b) /// use this type to emit them as a linear sequence. But a linear sequence is @@ -478,7 +469,6 @@ impl<'a> Parser<'a> { desugar_doc_comments, unmatched_angle_bracket_count: 0, max_angle_bracket_count: 0, - unclosed_delims: Vec::new(), last_unexpected_token_span: None, last_type_ascription: None, subparser_name, @@ -859,7 +849,6 @@ impl<'a> Parser<'a> { let mut recovered = false; let mut trailing = false; let mut v = ThinVec::new(); - let unclosed_delims = !self.unclosed_delims.is_empty(); while !self.expect_any_with_type(kets, expect) { if let token::CloseDelim(..) | token::Eof = self.token.kind { @@ -901,7 +890,7 @@ impl<'a> Parser<'a> { _ => { // Attempt to keep parsing if it was a similar separator. if let Some(tokens) = t.similar_tokens() { - if tokens.contains(&self.token.kind) && !unclosed_delims { + if tokens.contains(&self.token.kind) { self.bump(); } } diff --git a/config.toml.example b/config.toml.example index 69eb228a2d5a0..3aaeb09d4c005 100644 --- a/config.toml.example +++ b/config.toml.example @@ -164,6 +164,7 @@ changelog-seen = 2 # General build configuration options # ============================================================================= [build] + # The default stage to use for the `check` subcommand #check-stage = 0 diff --git a/src/bootstrap/configure.py b/src/bootstrap/configure.py index ab3d08292961f..c0d382d8a503b 100755 --- a/src/bootstrap/configure.py +++ b/src/bootstrap/configure.py @@ -488,6 +488,22 @@ def configure_top_level_key(lines, top_level_key, value): else: configure_section(sections[section_key], section_config) +def write_uncommented(target, f): + block = [] + is_comment = True + + for line in target: + block.append(line) + if len(line) == 0: + if not is_comment: + for l in block: + f.write(l + "\n") + block = [] + is_comment = True + continue + is_comment = is_comment and line.startswith('#') + return f + # Now that we've built up our `config.toml`, write it all out in the same # order that we read it in. p("") @@ -496,11 +512,9 @@ def configure_top_level_key(lines, top_level_key, value): for section in section_order: if section == 'target': for target in targets: - for line in targets[target]: - f.write(line + "\n") + f = write_uncommented(targets[target], f) else: - for line in sections[section]: - f.write(line + "\n") + f = write_uncommented(sections[section], f) with bootstrap.output('Makefile') as f: contents = os.path.join(rust_dir, 'src', 'bootstrap', 'mk', 'Makefile.in') diff --git a/src/librustdoc/html/render/print_item.rs b/src/librustdoc/html/render/print_item.rs index 2869a39613fa1..08796f10d9238 100644 --- a/src/librustdoc/html/render/print_item.rs +++ b/src/librustdoc/html/render/print_item.rs @@ -1839,6 +1839,12 @@ fn document_type_layout(w: &mut Buffer, cx: &Context<'_>, ty_def_id: DefId) { } else { let size = layout.size.bytes() - tag_size; write!(w, "{size} byte{pl}", pl = if size == 1 { "" } else { "s" },); + if layout.abi.is_uninhabited() { + write!( + w, + " (uninhabited)" + ); + } } } diff --git a/src/librustdoc/html/render/search_index.rs b/src/librustdoc/html/render/search_index.rs index 090ea2cb15763..e22ac6ec19b00 100644 --- a/src/librustdoc/html/render/search_index.rs +++ b/src/librustdoc/html/render/search_index.rs @@ -7,9 +7,7 @@ use rustc_span::symbol::Symbol; use serde::ser::{Serialize, SerializeStruct, Serializer}; use crate::clean; -use crate::clean::types::{ - FnRetTy, Function, GenericBound, Generics, ItemId, Type, WherePredicate, -}; +use crate::clean::types::{FnRetTy, Function, Generics, ItemId, Type, WherePredicate}; use crate::formats::cache::{Cache, OrphanImplItem}; use crate::formats::item_type::ItemType; use crate::html::format::join_with_double_colon; @@ -482,29 +480,23 @@ fn add_generics_and_bounds_as_types<'tcx, 'a>( if let Type::Generic(arg_s) = *arg { // First we check if the bounds are in a `where` predicate... if let Some(where_pred) = generics.where_predicates.iter().find(|g| match g { - WherePredicate::BoundPredicate { ty, .. } => ty.def_id(cache) == arg.def_id(cache), + WherePredicate::BoundPredicate { ty: Type::Generic(ty_s), .. } => *ty_s == arg_s, _ => false, }) { let mut ty_generics = Vec::new(); let bounds = where_pred.get_bounds().unwrap_or_else(|| &[]); for bound in bounds.iter() { - if let GenericBound::TraitBound(poly_trait, _) = bound { - for param_def in poly_trait.generic_params.iter() { - match ¶m_def.kind { - clean::GenericParamDefKind::Type { default: Some(ty), .. } => { - add_generics_and_bounds_as_types( - self_, - generics, - ty, - tcx, - recurse + 1, - &mut ty_generics, - cache, - ) - } - _ => {} - } - } + if let Some(path) = bound.get_trait_path() { + let ty = Type::Path { path }; + add_generics_and_bounds_as_types( + self_, + generics, + &ty, + tcx, + recurse + 1, + &mut ty_generics, + cache, + ); } } insert_ty(res, arg.clone(), ty_generics); diff --git a/src/rustdoc-json-types/Cargo.toml b/src/rustdoc-json-types/Cargo.toml index d60699efd36cb..d63caa7ad7010 100644 --- a/src/rustdoc-json-types/Cargo.toml +++ b/src/rustdoc-json-types/Cargo.toml @@ -8,6 +8,7 @@ path = "lib.rs" [dependencies] serde = { version = "1.0", features = ["derive"] } +rustc-hash = "1.1.0" [dev-dependencies] serde_json = "1.0" diff --git a/src/rustdoc-json-types/lib.rs b/src/rustdoc-json-types/lib.rs index 387d5787dfcb2..570002320038e 100644 --- a/src/rustdoc-json-types/lib.rs +++ b/src/rustdoc-json-types/lib.rs @@ -3,10 +3,9 @@ //! These types are the public API exposed through the `--output-format json` flag. The [`Crate`] //! struct is the root of the JSON blob and all other items are contained within. -use std::collections::HashMap; -use std::path::PathBuf; - +use rustc_hash::FxHashMap; use serde::{Deserialize, Serialize}; +use std::path::PathBuf; /// rustdoc format-version. pub const FORMAT_VERSION: u32 = 24; @@ -24,11 +23,11 @@ pub struct Crate { pub includes_private: bool, /// A collection of all items in the local crate as well as some external traits and their /// items that are referenced locally. - pub index: HashMap, + pub index: FxHashMap, /// Maps IDs to fully qualified paths and other info helpful for generating links. - pub paths: HashMap, + pub paths: FxHashMap, /// Maps `crate_id` of items to a crate name and html_root_url if it exists. - pub external_crates: HashMap, + pub external_crates: FxHashMap, /// A single version number to be used in the future when making backwards incompatible changes /// to the JSON output. pub format_version: u32, @@ -80,7 +79,7 @@ pub struct Item { /// Some("") if there is some documentation but it is empty (EG `#[doc = ""]`). pub docs: Option, /// This mapping resolves [intra-doc links](https://github.com/rust-lang/rfcs/blob/master/text/1946-intra-rustdoc-links.md) from the docstring to their IDs - pub links: HashMap, + pub links: FxHashMap, /// Stringified versions of the attributes on this item (e.g. `"#[inline]"`) pub attrs: Vec, pub deprecation: Option, diff --git a/src/tools/jsondoclint/Cargo.toml b/src/tools/jsondoclint/Cargo.toml index 8990310a4f474..1318a1f447620 100644 --- a/src/tools/jsondoclint/Cargo.toml +++ b/src/tools/jsondoclint/Cargo.toml @@ -9,6 +9,7 @@ edition = "2021" anyhow = "1.0.62" clap = { version = "4.0.15", features = ["derive"] } fs-err = "2.8.1" +rustc-hash = "1.1.0" rustdoc-json-types = { version = "0.1.0", path = "../../rustdoc-json-types" } serde = { version = "1.0", features = ["derive"] } serde_json = "1.0.85" diff --git a/src/tools/jsondoclint/src/validator/tests.rs b/src/tools/jsondoclint/src/validator/tests.rs index 1ef41ff123abf..95a56a9dfac45 100644 --- a/src/tools/jsondoclint/src/validator/tests.rs +++ b/src/tools/jsondoclint/src/validator/tests.rs @@ -1,5 +1,4 @@ -use std::collections::HashMap; - +use rustc_hash::FxHashMap; use rustdoc_json_types::{Crate, Item, ItemKind, ItemSummary, Visibility, FORMAT_VERSION}; use crate::json_find::SelectorPart; @@ -27,7 +26,7 @@ fn errors_on_missing_links() { root: id("0"), crate_version: None, includes_private: false, - index: HashMap::from_iter([( + index: FxHashMap::from_iter([( id("0"), Item { name: Some("root".to_owned()), @@ -36,7 +35,7 @@ fn errors_on_missing_links() { span: None, visibility: Visibility::Public, docs: None, - links: HashMap::from_iter([("Not Found".to_owned(), id("1"))]), + links: FxHashMap::from_iter([("Not Found".to_owned(), id("1"))]), attrs: vec![], deprecation: None, inner: ItemEnum::Module(Module { @@ -46,8 +45,8 @@ fn errors_on_missing_links() { }), }, )]), - paths: HashMap::new(), - external_crates: HashMap::new(), + paths: FxHashMap::default(), + external_crates: FxHashMap::default(), format_version: rustdoc_json_types::FORMAT_VERSION, }; @@ -73,7 +72,7 @@ fn errors_on_local_in_paths_and_not_index() { root: id("0:0:1572"), crate_version: None, includes_private: false, - index: HashMap::from_iter([ + index: FxHashMap::from_iter([ ( id("0:0:1572"), Item { @@ -83,7 +82,7 @@ fn errors_on_local_in_paths_and_not_index() { span: None, visibility: Visibility::Public, docs: None, - links: HashMap::from_iter([(("prim@i32".to_owned(), id("0:1:1571")))]), + links: FxHashMap::from_iter([(("prim@i32".to_owned(), id("0:1:1571")))]), attrs: Vec::new(), deprecation: None, inner: ItemEnum::Module(Module { @@ -102,14 +101,14 @@ fn errors_on_local_in_paths_and_not_index() { span: None, visibility: Visibility::Public, docs: None, - links: HashMap::default(), + links: FxHashMap::default(), attrs: Vec::new(), deprecation: None, inner: ItemEnum::Primitive(Primitive { name: "i32".to_owned(), impls: vec![] }), }, ), ]), - paths: HashMap::from_iter([( + paths: FxHashMap::from_iter([( id("0:1:1571"), ItemSummary { crate_id: 0, @@ -117,7 +116,7 @@ fn errors_on_local_in_paths_and_not_index() { kind: ItemKind::Primitive, }, )]), - external_crates: HashMap::default(), + external_crates: FxHashMap::default(), format_version: rustdoc_json_types::FORMAT_VERSION, }; @@ -137,7 +136,7 @@ fn checks_local_crate_id_is_correct() { root: id("root"), crate_version: None, includes_private: false, - index: HashMap::from_iter([( + index: FxHashMap::from_iter([( id("root"), Item { id: id("root"), @@ -146,7 +145,7 @@ fn checks_local_crate_id_is_correct() { span: None, visibility: Visibility::Public, docs: None, - links: HashMap::default(), + links: FxHashMap::default(), attrs: Vec::new(), deprecation: None, inner: ItemEnum::Module(Module { @@ -156,8 +155,8 @@ fn checks_local_crate_id_is_correct() { }), }, )]), - paths: HashMap::default(), - external_crates: HashMap::default(), + paths: FxHashMap::default(), + external_crates: FxHashMap::default(), format_version: FORMAT_VERSION, }; check(&krate, &[]); diff --git a/tests/run-make/rustdoc-verify-output-files/Makefile b/tests/run-make/rustdoc-verify-output-files/Makefile index bfabbbc65862f..0666122e8abc6 100644 --- a/tests/run-make/rustdoc-verify-output-files/Makefile +++ b/tests/run-make/rustdoc-verify-output-files/Makefile @@ -22,15 +22,11 @@ all: # Check if expected json file is generated [ -e $(OUTPUT_DIR)/foobar.json ] - # TODO - # We should re-generate json doc once again and compare the diff with previously - # generated one. Because layout of json docs changes in each compilation, we can't - # do that currently. - # - # See https://github.com/rust-lang/rust/issues/103785#issuecomment-1307425590 for details. + # Copy first json output to check if it's exactly same after second compilation + cp -R $(OUTPUT_DIR)/foobar.json $(TMP_OUTPUT_DIR)/foobar.json - # remove generated json doc - rm $(OUTPUT_DIR)/foobar.json + # Generate json doc on the same output + $(RUSTDOC) src/lib.rs --crate-name foobar --crate-type lib --out-dir $(OUTPUT_DIR) -Z unstable-options --output-format json - # Check if json doc compilation broke any of the html files generated previously + # Check if all docs(including both json and html formats) are still the same after multiple compilations $(DIFF) -r -q $(OUTPUT_DIR) $(TMP_OUTPUT_DIR) diff --git a/tests/rustdoc-js-std/option-type-signatures.js b/tests/rustdoc-js-std/option-type-signatures.js new file mode 100644 index 0000000000000..dee4819e81a9f --- /dev/null +++ b/tests/rustdoc-js-std/option-type-signatures.js @@ -0,0 +1,7 @@ +const QUERY = 'option, fnonce -> option'; + +const EXPECTED = { + 'others': [ + { 'path': 'std::option::Option', 'name': 'map' }, + ], +}; diff --git a/tests/rustdoc-js/where-clause.js b/tests/rustdoc-js/where-clause.js new file mode 100644 index 0000000000000..6cb42a455a369 --- /dev/null +++ b/tests/rustdoc-js/where-clause.js @@ -0,0 +1,19 @@ +const QUERY = ['trait', '-> trait', 't1, t2']; + +const EXPECTED = [ + { + 'in_args': [ + { 'path': 'where_clause', 'name': 'abracadabra' }, + ], + }, + { + 'others': [ + { 'path': 'where_clause', 'name': 'alacazam' }, + ], + }, + { + 'others': [ + { 'path': 'where_clause', 'name': 'presto' }, + ], + }, +]; diff --git a/tests/rustdoc-js/where-clause.rs b/tests/rustdoc-js/where-clause.rs new file mode 100644 index 0000000000000..808561feee227 --- /dev/null +++ b/tests/rustdoc-js/where-clause.rs @@ -0,0 +1,16 @@ +pub struct Nested; + +pub trait Trait { + fn thank_you(x: T); +} + +pub fn abracadabra(_: X) where X: Trait {} + +pub fn alacazam() -> X where X: Trait {} + +pub trait T1 {} +pub trait T2<'a, T> { + fn please(_: &'a T); +} + +pub fn presto(_: A, _: B) where A: T1, B: for <'b> T2<'b, Nested> {} diff --git a/tests/rustdoc/type-layout.rs b/tests/rustdoc/type-layout.rs index 5e0a0411a62b6..bd88e73af5cbf 100644 --- a/tests/rustdoc/type-layout.rs +++ b/tests/rustdoc/type-layout.rs @@ -83,3 +83,11 @@ pub enum WithNiche { None, Some(std::num::NonZeroU32), } + +// @hasraw type_layout/enum.Uninhabited.html 'Size: ' +// @hasraw - '0 bytes (uninhabited)' +pub enum Uninhabited {} + +// @hasraw type_layout/struct.Uninhabited2.html 'Size: ' +// @hasraw - '8 bytes (uninhabited)' +pub struct Uninhabited2(std::convert::Infallible, u64); diff --git a/tests/ui/suggestions/multiline-multipart-suggestion.rs b/tests/ui/suggestions/multiline-multipart-suggestion.rs new file mode 100644 index 0000000000000..77d0322d05fcf --- /dev/null +++ b/tests/ui/suggestions/multiline-multipart-suggestion.rs @@ -0,0 +1,19 @@ +// compile-flags: --error-format=human --color=always +// ignore-windows + +fn short(foo_bar: &Vec<&i32>) -> &i32 { //~ ERROR missing lifetime specifier + &12 +} + +fn long( //~ ERROR missing lifetime specifier + foo_bar: &Vec<&i32>, + something_very_long_so_that_the_line_will_wrap_around__________: i32, +) -> &i32 { + &12 +} + +fn long2( //~ ERROR missing lifetime specifier + foo_bar: &Vec<&i32>) -> &i32 { + &12 +} +fn main() {} diff --git a/tests/ui/suggestions/multiline-multipart-suggestion.stderr b/tests/ui/suggestions/multiline-multipart-suggestion.stderr new file mode 100644 index 0000000000000..045a86b4f541f --- /dev/null +++ b/tests/ui/suggestions/multiline-multipart-suggestion.stderr @@ -0,0 +1,46 @@ +error[E0106]: missing lifetime specifier + --> $DIR/multiline-multipart-suggestion.rs:4:34 + | +LL | fn short(foo_bar: &Vec<&i32>) -> &i32 { + |  ---------- ^ expected named lifetime parameter + | + = help: this function's return type contains a borrowed value, but the signature does not say which one of `foo_bar`'s 2 lifetimes it is borrowed from +help: consider introducing a named lifetime parameter + | +LL | fn short<'a>(foo_bar: &'a Vec<&'a i32>) -> &'a i32 { + | ++++ ++ ++ ++ + +error[E0106]: missing lifetime specifier + --> $DIR/multiline-multipart-suggestion.rs:11:6 + | +LL |  foo_bar: &Vec<&i32>, + |  ---------- +LL |  something_very_long_so_that_the_line_will_wrap_around__________: i32, +LL | ) -> &i32 { + |  ^ expected named lifetime parameter + | + = help: this function's return type contains a borrowed value, but the signature does not say which one of `foo_bar`'s 2 lifetimes it is borrowed from +help: consider introducing a named lifetime parameter + | +LL ~ fn long<'a>( +LL ~  foo_bar: &'a Vec<&'a i32>, +LL |  something_very_long_so_that_the_line_will_wrap_around__________: i32, +LL ~ ) -> &'a i32 { + | + +error[E0106]: missing lifetime specifier + --> $DIR/multiline-multipart-suggestion.rs:16:29 + | +LL |  foo_bar: &Vec<&i32>) -> &i32 { + |  ---------- ^ expected named lifetime parameter + | + = help: this function's return type contains a borrowed value, but the signature does not say which one of `foo_bar`'s 2 lifetimes it is borrowed from +help: consider introducing a named lifetime parameter + | +LL ~ fn long2<'a>( +LL ~  foo_bar: &'a Vec<&'a i32>) -> &'a i32 { + | + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0106`.