diff options
| author | bors <bors@rust-lang.org> | 2022-08-31 13:01:38 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2022-08-31 13:01:38 +0000 |
| commit | 4fd4de7ea358ad6fc28c5780533ea8ccc09e1006 (patch) | |
| tree | 375f93b95d1d9c9b54cab9683797a6f1d45731a7 /src | |
| parent | 12e4fd0755d7d976d4ee0f2004dc938290752ff7 (diff) | |
| parent | 2a0288266749800e621cfeb8e5404f0a8e6f9185 (diff) | |
| download | rust-4fd4de7ea358ad6fc28c5780533ea8ccc09e1006.tar.gz rust-4fd4de7ea358ad6fc28c5780533ea8ccc09e1006.zip | |
Auto merge of #101238 - RalfJung:rollup-bzcmobj, r=RalfJung
Rollup of 7 pull requests Successful merges: - #90946 (Ignore `reference`s in "Type::inner_def_id") - #100730 (Migrate rustc_monomorphize to use SessionDiagnostic) - #100753 (translations(rustc_session): migrates `rustc_session` to use `SessionDiagnostic` - Pt. 1) - #100831 (Migrate `symbol_mangling` module to new diagnostics structs) - #101204 (rustdoc: Resugar async fn return type in `clean`, not `html`) - #101216 (Use in-page links for sanitizer docs.) - #101237 (fix into_iter on ZST) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
Diffstat (limited to 'src')
| -rw-r--r-- | src/doc/unstable-book/src/compiler-flags/sanitizer.md | 36 | ||||
| -rw-r--r-- | src/librustdoc/clean/mod.rs | 5 | ||||
| -rw-r--r-- | src/librustdoc/html/format.rs | 17 | ||||
| -rw-r--r-- | src/librustdoc/html/render/mod.rs | 282 | ||||
| -rw-r--r-- | src/librustdoc/html/render/print_item.rs | 22 | ||||
| -rw-r--r-- | src/test/rustdoc-json/fns/async_return.rs | 36 | ||||
| -rw-r--r-- | src/test/rustdoc/primitive-reference.rs | 37 | ||||
| -rw-r--r-- | src/test/ui/type_length_limit.stderr | 4 |
8 files changed, 293 insertions, 146 deletions
diff --git a/src/doc/unstable-book/src/compiler-flags/sanitizer.md b/src/doc/unstable-book/src/compiler-flags/sanitizer.md index 7f7549aaf5a..b33405f18e9 100644 --- a/src/doc/unstable-book/src/compiler-flags/sanitizer.md +++ b/src/doc/unstable-book/src/compiler-flags/sanitizer.md @@ -9,17 +9,17 @@ The tracking issues for this feature are: This feature allows for use of one of following sanitizers: -* [AddressSanitizer][clang-asan] a fast memory error detector. -* [ControlFlowIntegrity][clang-cfi] LLVM Control Flow Integrity (CFI) provides +* [AddressSanitizer](#addresssanitizer) a fast memory error detector. +* [ControlFlowIntegrity](#controlflowintegrity) LLVM Control Flow Integrity (CFI) provides forward-edge control flow protection. -* [HWAddressSanitizer][clang-hwasan] a memory error detector similar to +* [HWAddressSanitizer](#hwaddresssanitizer) a memory error detector similar to AddressSanitizer, but based on partial hardware assistance. -* [LeakSanitizer][clang-lsan] a run-time memory leak detector. -* [MemorySanitizer][clang-msan] a detector of uninitialized reads. -* [MemTagSanitizer][clang-memtag] fast memory error detector based on +* [LeakSanitizer](#leaksanitizer) a run-time memory leak detector. +* [MemorySanitizer](#memorysanitizer) a detector of uninitialized reads. +* [MemTagSanitizer](#memtagsanitizer) fast memory error detector based on Armv8.5-A Memory Tagging Extension. -* [ShadowCallStack][clang-scs] provides backward-edge control flow protection. -* [ThreadSanitizer][clang-tsan] a fast data race detector. +* [ShadowCallStack](#shadowcallstack) provides backward-edge control flow protection. +* [ThreadSanitizer](#threadsanitizer) a fast data race detector. To enable a sanitizer compile with `-Zsanitizer=address`,`-Zsanitizer=cfi`, `-Zsanitizer=hwaddress`, `-Zsanitizer=leak`, `-Zsanitizer=memory`, @@ -58,6 +58,8 @@ AddressSanitizer works with non-instrumented code although it will impede its ability to detect some bugs. It is not expected to produce false positive reports. +See the [Clang AddressSanitizer documentation][clang-asan] for more details. + ## Examples Stack buffer overflow: @@ -204,6 +206,8 @@ tracking issue [#89653](https://github.com/rust-lang/rust/issues/89653)). LLVM CFI can be enabled with -Zsanitizer=cfi and requires LTO (i.e., -Clto). +See the [Clang ControlFlowIntegrity documentation][clang-cfi] for more details. + ## Example ```text @@ -430,6 +434,8 @@ HWAddressSanitizer requires `tagged-globals` target feature to instrument globals. To enable this target feature compile with `-C target-feature=+tagged-globals` +See the [Clang HWAddressSanitizer documentation][clang-hwasan] for more details. + ## Example Heap buffer overflow: @@ -507,6 +513,8 @@ LeakSanitizer is supported on the following targets: * `x86_64-apple-darwin` * `x86_64-unknown-linux-gnu` +See the [Clang LeakSanitizer documentation][clang-lsan] for more details. + # MemorySanitizer MemorySanitizer is detector of uninitialized reads. @@ -521,6 +529,8 @@ MemorySanitizer requires all program code to be instrumented. C/C++ dependencies need to be recompiled using Clang with `-fsanitize=memory` option. Failing to achieve that will result in false positive reports. +See the [Clang MemorySanitizer documentation][clang-msan] for more details. + ## Example Detecting the use of uninitialized memory. The `-Zbuild-std` flag rebuilds and @@ -569,7 +579,7 @@ MemTagSanitizer is supported on the following targets: MemTagSanitizer requires hardware support and the `mte` target feature. To enable this target feature compile with `-C target-feature="+mte"`. -More information can be found in the associated [LLVM documentation](https://llvm.org/docs/MemTagSanitizer.html). +See the [LLVM MemTagSanitizer documentation][llvm-memtag] for more details. # ShadowCallStack @@ -581,7 +591,9 @@ ShadowCallStack can be enabled with `-Zsanitizer=shadow-call-stack` option and i * `aarch64-linux-android` -A runtime must be provided by the application or operating system. See the [LLVM documentation][clang-scs] for further details. +A runtime must be provided by the application or operating system. + +See the [Clang ShadowCallStack documentation][clang-scs] for more details. # ThreadSanitizer @@ -604,6 +616,8 @@ can lead to false positive reports. ThreadSanitizer does not support atomic fences `std::sync::atomic::fence`, nor synchronization performed using inline assembly code. +See the [Clang ThreadSanitizer documentation][clang-tsan] for more details. + ## Example ```rust @@ -673,6 +687,7 @@ Sanitizers produce symbolized stacktraces when llvm-symbolizer binary is in `PAT * [HWAddressSanitizer in Clang][clang-hwasan] * [LeakSanitizer in Clang][clang-lsan] * [MemorySanitizer in Clang][clang-msan] +* [MemTagSanitizer in LLVM][llvm-memtag] * [ThreadSanitizer in Clang][clang-tsan] [clang-asan]: https://clang.llvm.org/docs/AddressSanitizer.html @@ -682,3 +697,4 @@ Sanitizers produce symbolized stacktraces when llvm-symbolizer binary is in `PAT [clang-msan]: https://clang.llvm.org/docs/MemorySanitizer.html [clang-scs]: https://clang.llvm.org/docs/ShadowCallStack.html [clang-tsan]: https://clang.llvm.org/docs/ThreadSanitizer.html +[llvm-memtag]: https://llvm.org/docs/MemTagSanitizer.html diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index c425de081a6..41f9eb3cdf6 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -886,7 +886,10 @@ fn clean_function<'tcx>( // NOTE: generics must be cleaned before args let generics = clean_generics(generics, cx); let args = clean_args_from_types_and_body_id(cx, sig.decl.inputs, body_id); - let decl = clean_fn_decl_with_args(cx, sig.decl, args); + let mut decl = clean_fn_decl_with_args(cx, sig.decl, args); + if sig.header.is_async() { + decl.output = decl.sugared_async_return_type(); + } (generics, decl) }); Box::new(Function { decl, generics }) diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs index b023792e95a..6f49f00f93e 100644 --- a/src/librustdoc/html/format.rs +++ b/src/librustdoc/html/format.rs @@ -1310,22 +1310,19 @@ impl clean::FnDecl { /// <br>Used to determine line-wrapping. /// * `indent`: The number of spaces to indent each successive line with, if line-wrapping is /// necessary. - /// * `asyncness`: Whether the function is async or not. pub(crate) fn full_print<'a, 'tcx: 'a>( &'a self, header_len: usize, indent: usize, - asyncness: hir::IsAsync, cx: &'a Context<'tcx>, ) -> impl fmt::Display + 'a + Captures<'tcx> { - display_fn(move |f| self.inner_full_print(header_len, indent, asyncness, f, cx)) + display_fn(move |f| self.inner_full_print(header_len, indent, f, cx)) } fn inner_full_print( &self, header_len: usize, indent: usize, - asyncness: hir::IsAsync, f: &mut fmt::Formatter<'_>, cx: &Context<'_>, ) -> fmt::Result { @@ -1390,15 +1387,9 @@ impl clean::FnDecl { args_plain.push_str(", ..."); } - let arrow_plain; - let arrow = if let hir::IsAsync::Async = asyncness { - let output = self.sugared_async_return_type(); - arrow_plain = format!("{:#}", output.print(cx)); - if f.alternate() { arrow_plain.clone() } else { format!("{}", output.print(cx)) } - } else { - arrow_plain = format!("{:#}", self.output.print(cx)); - if f.alternate() { arrow_plain.clone() } else { format!("{}", self.output.print(cx)) } - }; + let arrow_plain = format!("{:#}", self.output.print(cx)); + let arrow = + if f.alternate() { arrow_plain.clone() } else { format!("{}", self.output.print(cx)) }; let declaration_len = header_len + args_plain.len() + arrow_plain.len(); let output = if declaration_len > 80 { diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs index 6272f47f460..eff34047e3c 100644 --- a/src/librustdoc/html/render/mod.rs +++ b/src/librustdoc/html/render/mod.rs @@ -613,10 +613,10 @@ fn short_item_info( // Render the list of items inside one of the sections "Trait Implementations", // "Auto Trait Implementations," "Blanket Trait Implementations" (on struct/enum pages). -fn render_impls( +pub(crate) fn render_impls( cx: &mut Context<'_>, w: &mut Buffer, - impls: &[&&Impl], + impls: &[&Impl], containing_item: &clean::Item, toggle_open_by_default: bool, ) { @@ -821,7 +821,7 @@ fn assoc_method( href = href, name = name, generics = g.print(cx), - decl = d.full_print(header_len, indent, header.asyncness, cx), + decl = d.full_print(header_len, indent, cx), notable_traits = notable_traits_decl(d, cx), where_clause = print_where_clause(g, cx, indent, end_newline), ) @@ -1025,6 +1025,47 @@ impl<'a> AssocItemLink<'a> { } } +fn write_impl_section_heading(w: &mut Buffer, title: &str, id: &str) { + write!( + w, + "<h2 id=\"{id}\" class=\"small-section-header\">\ + {title}\ + <a href=\"#{id}\" class=\"anchor\"></a>\ + </h2>" + ); +} + +pub(crate) fn render_all_impls( + w: &mut Buffer, + cx: &mut Context<'_>, + containing_item: &clean::Item, + concrete: &[&Impl], + synthetic: &[&Impl], + blanket_impl: &[&Impl], +) { + let mut impls = Buffer::empty_from(w); + render_impls(cx, &mut impls, concrete, containing_item, true); + let impls = impls.into_inner(); + if !impls.is_empty() { + write_impl_section_heading(w, "Trait Implementations", "trait-implementations"); + write!(w, "<div id=\"trait-implementations-list\">{}</div>", impls); + } + + if !synthetic.is_empty() { + write_impl_section_heading(w, "Auto Trait Implementations", "synthetic-implementations"); + w.write_str("<div id=\"synthetic-implementations-list\">"); + render_impls(cx, w, synthetic, containing_item, false); + w.write_str("</div>"); + } + + if !blanket_impl.is_empty() { + write_impl_section_heading(w, "Blanket Implementations", "blanket-implementations"); + w.write_str("<div id=\"blanket-implementations-list\">"); + render_impls(cx, w, blanket_impl, containing_item, false); + w.write_str("</div>"); + } +} + fn render_assoc_items( w: &mut Buffer, cx: &mut Context<'_>, @@ -1054,12 +1095,7 @@ fn render_assoc_items_inner( let mut tmp_buf = Buffer::empty_from(w); let (render_mode, id) = match what { AssocItemRender::All => { - tmp_buf.write_str( - "<h2 id=\"implementations\" class=\"small-section-header\">\ - Implementations\ - <a href=\"#implementations\" class=\"anchor\"></a>\ - </h2>", - ); + write_impl_section_heading(&mut tmp_buf, "Implementations", "implementations"); (RenderMode::Normal, "implementations-list".to_owned()) } AssocItemRender::DerefFor { trait_, type_, deref_mut_ } => { @@ -1068,15 +1104,14 @@ fn render_assoc_items_inner( if let Some(def_id) = type_.def_id(cx.cache()) { cx.deref_id_map.insert(def_id, id.clone()); } - write!( - tmp_buf, - "<h2 id=\"{id}\" class=\"small-section-header\">\ - <span>Methods from {trait_}<Target = {type_}></span>\ - <a href=\"#{id}\" class=\"anchor\"></a>\ - </h2>", - id = id, - trait_ = trait_.print(cx), - type_ = type_.print(cx), + write_impl_section_heading( + &mut tmp_buf, + &format!( + "<span>Methods from {trait_}<Target = {type_}></span>", + trait_ = trait_.print(cx), + type_ = type_.print(cx), + ), + &id, ); (RenderMode::ForDeref { mut_: deref_mut_ }, cx.derive_id(id)) } @@ -1123,49 +1158,12 @@ fn render_assoc_items_inner( return; } - let (synthetic, concrete): (Vec<&&Impl>, Vec<&&Impl>) = - traits.iter().partition(|t| t.inner_impl().kind.is_auto()); - let (blanket_impl, concrete): (Vec<&&Impl>, _) = + let (synthetic, concrete): (Vec<&Impl>, Vec<&Impl>) = + traits.into_iter().partition(|t| t.inner_impl().kind.is_auto()); + let (blanket_impl, concrete): (Vec<&Impl>, _) = concrete.into_iter().partition(|t| t.inner_impl().kind.is_blanket()); - let mut impls = Buffer::empty_from(w); - render_impls(cx, &mut impls, &concrete, containing_item, true); - let impls = impls.into_inner(); - if !impls.is_empty() { - write!( - w, - "<h2 id=\"trait-implementations\" class=\"small-section-header\">\ - Trait Implementations\ - <a href=\"#trait-implementations\" class=\"anchor\"></a>\ - </h2>\ - <div id=\"trait-implementations-list\">{}</div>", - impls - ); - } - - if !synthetic.is_empty() { - w.write_str( - "<h2 id=\"synthetic-implementations\" class=\"small-section-header\">\ - Auto Trait Implementations\ - <a href=\"#synthetic-implementations\" class=\"anchor\"></a>\ - </h2>\ - <div id=\"synthetic-implementations-list\">", - ); - render_impls(cx, w, &synthetic, containing_item, false); - w.write_str("</div>"); - } - - if !blanket_impl.is_empty() { - w.write_str( - "<h2 id=\"blanket-implementations\" class=\"small-section-header\">\ - Blanket Implementations\ - <a href=\"#blanket-implementations\" class=\"anchor\"></a>\ - </h2>\ - <div id=\"blanket-implementations-list\">", - ); - render_impls(cx, w, &blanket_impl, containing_item, false); - w.write_str("</div>"); - } + render_all_impls(w, cx, containing_item, &concrete, &synthetic, &blanket_impl); } } @@ -1970,6 +1968,70 @@ fn small_url_encode(s: String) -> String { } } +pub(crate) fn sidebar_render_assoc_items( + cx: &Context<'_>, + out: &mut Buffer, + id_map: &mut IdMap, + concrete: Vec<&Impl>, + synthetic: Vec<&Impl>, + blanket_impl: Vec<&Impl>, +) { + let format_impls = |impls: Vec<&Impl>, id_map: &mut IdMap| { + let mut links = FxHashSet::default(); + + let mut ret = impls + .iter() + .filter_map(|it| { + let trait_ = it.inner_impl().trait_.as_ref()?; + let encoded = + id_map.derive(get_id_for_impl(&it.inner_impl().for_, Some(trait_), cx)); + + let i_display = format!("{:#}", trait_.print(cx)); + let out = Escape(&i_display); + let prefix = match it.inner_impl().polarity { + ty::ImplPolarity::Positive | ty::ImplPolarity::Reservation => "", + ty::ImplPolarity::Negative => "!", + }; + let generated = format!("<a href=\"#{}\">{}{}</a>", encoded, prefix, out); + if links.insert(generated.clone()) { Some(generated) } else { None } + }) + .collect::<Vec<String>>(); + ret.sort(); + ret + }; + + let concrete_format = format_impls(concrete, id_map); + let synthetic_format = format_impls(synthetic, id_map); + let blanket_format = format_impls(blanket_impl, id_map); + + if !concrete_format.is_empty() { + print_sidebar_block( + out, + "trait-implementations", + "Trait Implementations", + concrete_format.iter(), + ); + } + + if !synthetic_format.is_empty() { + print_sidebar_block( + out, + "synthetic-implementations", + "Auto Trait Implementations", + synthetic_format.iter(), + ); + } + + if !blanket_format.is_empty() { + print_sidebar_block( + out, + "blanket-implementations", + "Blanket Implementations", + blanket_format.iter(), + ); + } +} + fn sidebar_assoc_items(cx: &Context<'_>, out: &mut Buffer, it: &clean::Item) { let did = it.item_id.expect_def_id(); let cache = cx.cache(); @@ -2018,65 +2080,12 @@ fn sidebar_assoc_items(cx: &Context<'_>, out: &mut Buffer, it: &clean::Item) { sidebar_deref_methods(cx, out, impl_, v, &mut derefs, &mut used_links); } - let format_impls = |impls: Vec<&Impl>, id_map: &mut IdMap| { - let mut links = FxHashSet::default(); - - let mut ret = impls - .iter() - .filter_map(|it| { - let trait_ = it.inner_impl().trait_.as_ref()?; - let encoded = - id_map.derive(get_id_for_impl(&it.inner_impl().for_, Some(trait_), cx)); - - let i_display = format!("{:#}", trait_.print(cx)); - let out = Escape(&i_display); - let prefix = match it.inner_impl().polarity { - ty::ImplPolarity::Positive | ty::ImplPolarity::Reservation => "", - ty::ImplPolarity::Negative => "!", - }; - let generated = format!("<a href=\"#{}\">{}{}</a>", encoded, prefix, out); - if links.insert(generated.clone()) { Some(generated) } else { None } - }) - .collect::<Vec<String>>(); - ret.sort(); - ret - }; - let (synthetic, concrete): (Vec<&Impl>, Vec<&Impl>) = v.iter().partition::<Vec<_>, _>(|i| i.inner_impl().kind.is_auto()); let (blanket_impl, concrete): (Vec<&Impl>, Vec<&Impl>) = concrete.into_iter().partition::<Vec<_>, _>(|i| i.inner_impl().kind.is_blanket()); - let concrete_format = format_impls(concrete, &mut id_map); - let synthetic_format = format_impls(synthetic, &mut id_map); - let blanket_format = format_impls(blanket_impl, &mut id_map); - - if !concrete_format.is_empty() { - print_sidebar_block( - out, - "trait-implementations", - "Trait Implementations", - concrete_format.iter(), - ); - } - - if !synthetic_format.is_empty() { - print_sidebar_block( - out, - "synthetic-implementations", - "Auto Trait Implementations", - synthetic_format.iter(), - ); - } - - if !blanket_format.is_empty() { - print_sidebar_block( - out, - "blanket-implementations", - "Blanket Implementations", - blanket_format.iter(), - ); - } + sidebar_render_assoc_items(cx, out, &mut id_map, concrete, synthetic, blanket_impl); } } } @@ -2346,9 +2355,54 @@ fn sidebar_trait(cx: &Context<'_>, buf: &mut Buffer, it: &clean::Item, t: &clean buf.push_str("</section>") } +/// Returns the list of implementations for the primitive reference type, filtering out any +/// implementations that are on concrete or partially generic types, only keeping implementations +/// of the form `impl<T> Trait for &T`. +pub(crate) fn get_filtered_impls_for_reference<'a>( + shared: &'a Rc<SharedContext<'_>>, + it: &clean::Item, +) -> (Vec<&'a Impl>, Vec<&'a Impl>, Vec<&'a Impl>) { + let def_id = it.item_id.expect_def_id(); + // If the reference primitive is somehow not defined, exit early. + let Some(v) = shared.cache.impls.get(&def_id) else { return (Vec::new(), Vec::new(), Vec::new()) }; + // Since there is no "direct implementation" on the reference primitive type, we filter out + // every implementation which isn't a trait implementation. + let traits: Vec<_> = v.iter().filter(|i| i.inner_impl().trait_.is_some()).collect(); + let (synthetic, concrete): (Vec<&Impl>, Vec<&Impl>) = + traits.into_iter().partition(|t| t.inner_impl().kind.is_auto()); + + let (blanket_impl, concrete): (Vec<&Impl>, _) = + concrete.into_iter().partition(|t| t.inner_impl().kind.is_blanket()); + // Now we keep only references over full generic types. + let concrete: Vec<_> = concrete + .into_iter() + .filter(|t| match t.inner_impl().for_ { + clean::Type::BorrowedRef { ref type_, .. } => type_.is_full_generic(), + _ => false, + }) + .collect(); + + (concrete, synthetic, blanket_impl) +} + fn sidebar_primitive(cx: &Context<'_>, buf: &mut Buffer, it: &clean::Item) { let mut sidebar = Buffer::new(); - sidebar_assoc_items(cx, &mut sidebar, it); + + if it.name.map(|n| n.as_str() != "reference").unwrap_or(false) { + sidebar_assoc_items(cx, &mut sidebar, it); + } else { + let shared = Rc::clone(&cx.shared); + let (concrete, synthetic, blanket_impl) = get_filtered_impls_for_reference(&shared, it); + + sidebar_render_assoc_items( + cx, + &mut sidebar, + &mut IdMap::new(), + concrete, + synthetic, + blanket_impl, + ); + } if !sidebar.is_empty() { write!(buf, "<section>{}</section>", sidebar.into_inner()); diff --git a/src/librustdoc/html/render/print_item.rs b/src/librustdoc/html/render/print_item.rs index 710064a37d0..d63d4c2d159 100644 --- a/src/librustdoc/html/render/print_item.rs +++ b/src/librustdoc/html/render/print_item.rs @@ -16,10 +16,10 @@ use std::fmt; use std::rc::Rc; use super::{ - collect_paths_for_type, document, ensure_trailing_slash, item_ty_to_section, - notable_traits_decl, render_assoc_item, render_assoc_items, render_attributes_in_code, - render_attributes_in_pre, render_impl, render_rightside, render_stability_since_raw, - AssocItemLink, Context, ImplRenderingParameters, + collect_paths_for_type, document, ensure_trailing_slash, get_filtered_impls_for_reference, + item_ty_to_section, notable_traits_decl, render_all_impls, render_assoc_item, + render_assoc_items, render_attributes_in_code, render_attributes_in_pre, render_impl, + render_rightside, render_stability_since_raw, AssocItemLink, Context, ImplRenderingParameters, }; use crate::clean; use crate::config::ModuleSorting; @@ -530,7 +530,7 @@ fn item_function(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, f: &cle name = name, generics = f.generics.print(cx), where_clause = print_where_clause(&f.generics, cx, 0, Ending::Newline), - decl = f.decl.full_print(header_len, 0, header.asyncness, cx), + decl = f.decl.full_print(header_len, 0, cx), notable_traits = notable_traits_decl(&f.decl, cx), ); }); @@ -1371,8 +1371,18 @@ fn item_proc_macro(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, m: &c } fn item_primitive(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item) { + let def_id = it.item_id.expect_def_id(); document(w, cx, it, None, HeadingOffset::H2); - render_assoc_items(w, cx, it, it.item_id.expect_def_id(), AssocItemRender::All) + if it.name.map(|n| n.as_str() != "reference").unwrap_or(false) { + render_assoc_items(w, cx, it, def_id, AssocItemRender::All); + } else { + // We handle the "reference" primitive type on its own because we only want to list + // implementations on generic types. + let shared = Rc::clone(&cx.shared); + let (concrete, synthetic, blanket_impl) = get_filtered_impls_for_reference(&shared, it); + + render_all_impls(w, cx, it, &concrete, &synthetic, &blanket_impl); + } } fn item_constant(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, c: &clean::Constant) { diff --git a/src/test/rustdoc-json/fns/async_return.rs b/src/test/rustdoc-json/fns/async_return.rs new file mode 100644 index 00000000000..b89781ca92d --- /dev/null +++ b/src/test/rustdoc-json/fns/async_return.rs @@ -0,0 +1,36 @@ +// edition:2021 +// ignore-tidy-linelength + +// Regression test for <https://github.com/rust-lang/rust/issues/101199> + +use std::future::Future; + +// @is "$.index[*][?(@.name=='get_int')].inner.decl.output" '{"inner": "i32", "kind": "primitive"}' +// @is "$.index[*][?(@.name=='get_int')].inner.header.async" false +pub fn get_int() -> i32 { + 42 +} + +// @is "$.index[*][?(@.name=='get_int_async')].inner.decl.output" '{"inner": "i32", "kind": "primitive"}' +// @is "$.index[*][?(@.name=='get_int_async')].inner.header.async" true +pub async fn get_int_async() -> i32 { + 42 +} + +// @is "$.index[*][?(@.name=='get_int_future')].inner.decl.output.kind" '"impl_trait"' +// @is "$.index[*][?(@.name=='get_int_future')].inner.decl.output.inner[0].trait_bound.trait.name" '"Future"' +// @is "$.index[*][?(@.name=='get_int_future')].inner.decl.output.inner[0].trait_bound.trait.args.angle_bracketed.bindings[0].name" '"Output"' +// @is "$.index[*][?(@.name=='get_int_future')].inner.decl.output.inner[0].trait_bound.trait.args.angle_bracketed.bindings[0].binding.equality.type" '{"inner": "i32", "kind": "primitive"}' +// @is "$.index[*][?(@.name=='get_int_future')].inner.header.async" false +pub fn get_int_future() -> impl Future<Output = i32> { + async { 42 } +} + +// @is "$.index[*][?(@.name=='get_int_future_async')].inner.decl.output.kind" '"impl_trait"' +// @is "$.index[*][?(@.name=='get_int_future_async')].inner.decl.output.inner[0].trait_bound.trait.name" '"Future"' +// @is "$.index[*][?(@.name=='get_int_future_async')].inner.decl.output.inner[0].trait_bound.trait.args.angle_bracketed.bindings[0].name" '"Output"' +// @is "$.index[*][?(@.name=='get_int_future_async')].inner.decl.output.inner[0].trait_bound.trait.args.angle_bracketed.bindings[0].binding.equality.type" '{"inner": "i32", "kind": "primitive"}' +// @is "$.index[*][?(@.name=='get_int_future_async')].inner.header.async" true +pub async fn get_int_future_async() -> impl Future<Output = i32> { + async { 42 } +} diff --git a/src/test/rustdoc/primitive-reference.rs b/src/test/rustdoc/primitive-reference.rs new file mode 100644 index 00000000000..5c119340609 --- /dev/null +++ b/src/test/rustdoc/primitive-reference.rs @@ -0,0 +1,37 @@ +#![crate_name = "foo"] + +#![feature(rustdoc_internals)] + +// @has foo/index.html +// @has - '//h2[@id="primitives"]' 'Primitive Types' +// @has - '//a[@href="primitive.reference.html"]' 'reference' +// @has - '//div[@class="sidebar-elems"]//li/a' 'Primitive Types' +// @has - '//div[@class="sidebar-elems"]//li/a/@href' '#primitives' +// @has foo/primitive.reference.html +// @has - '//a[@class="primitive"]' 'reference' +// @has - '//span[@class="in-band"]' 'Primitive Type reference' +// @has - '//section[@id="main-content"]//div[@class="docblock"]//p' 'this is a test!' + +// There should be only one implementation listed. +// @count - '//*[@class="impl has-srclink"]' 1 +// @has - '//*[@id="impl-Foo%3C%26A%3E-for-%26B"]/*[@class="code-header in-band"]' \ +// 'impl<A, B> Foo<&A> for &B' +#[doc(primitive = "reference")] +/// this is a test! +mod reference {} + +pub struct Bar; + +// This implementation should **not** show up. +impl<T> From<&T> for Bar { + fn from(s: &T) -> Self { + Bar + } +} + +pub trait Foo<T> { + fn stuff(&self, other: &T) {} +} + +// This implementation should show up. +impl<A, B> Foo<&A> for &B {} diff --git a/src/test/ui/type_length_limit.stderr b/src/test/ui/type_length_limit.stderr index 1508b84c1b6..84ac48b1e77 100644 --- a/src/test/ui/type_length_limit.stderr +++ b/src/test/ui/type_length_limit.stderr @@ -4,8 +4,8 @@ error: reached the type-length limit while instantiating `std::mem::drop::<Optio LL | pub fn drop<T>(_x: T) {} | ^^^^^^^^^^^^^^^^^^^^^ | - = note: the full type name has been written to '$TEST_BUILD_DIR/type_length_limit/type_length_limit.long-type.txt' = help: consider adding a `#![type_length_limit="8"]` attribute to your crate + = note: the full type name has been written to '$TEST_BUILD_DIR/type_length_limit/type_length_limit.long-type.txt' error: reached the type-length limit while instantiating `<[closure@std::rt::lang_start<()...e<()>>::call_once - shim(vtable)` --> $SRC_DIR/core/src/ops/function.rs:LL:COL @@ -13,8 +13,8 @@ error: reached the type-length limit while instantiating `<[closure@std::rt::lan LL | extern "rust-call" fn call_once(self, args: Args) -> Self::Output; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: the full type name has been written to '$TEST_BUILD_DIR/type_length_limit/type_length_limit.long-type.txt' = help: consider adding a `#![type_length_limit="8"]` attribute to your crate + = note: the full type name has been written to '$TEST_BUILD_DIR/type_length_limit/type_length_limit.long-type.txt' error: aborting due to 2 previous errors |
