mirror of
https://github.com/rust-lang/rust.git
synced 2026-04-27 18:57:42 +03:00
Rollup merge of #154444 - jakubadamw:issue-128801, r=fmease
rustdoc ICE fix: When collecting `Deref` impls with their targets, skip the negative ones
rustdoc assumed every `Deref` impl has an associated `Target` type, but negative impls (e.g. `impl !Deref for T {}`) have none.
Skip them in both the trait-impl collection pass and the HTML render pass to avoid panicking on the missing `Target`.
Closes rust-lang/rust#128801.
This commit is contained in:
@@ -580,7 +580,9 @@ pub(crate) fn build_impl(
|
||||
};
|
||||
let trait_ = associated_trait
|
||||
.map(|t| clean_trait_ref_with_constraints(cx, ty::Binder::dummy(t), ThinVec::new()));
|
||||
if trait_.as_ref().map(|t| t.def_id()) == tcx.lang_items().deref_trait() {
|
||||
if trait_.as_ref().map(|t| t.def_id()) == tcx.lang_items().deref_trait()
|
||||
&& polarity != ty::ImplPolarity::Negative
|
||||
{
|
||||
super::build_deref_target_impls(cx, &trait_items, ret);
|
||||
}
|
||||
|
||||
|
||||
@@ -2942,9 +2942,11 @@ fn clean_impl<'tcx>(
|
||||
.map(|&ii| clean_impl_item(tcx.hir_impl_item(ii), cx))
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
// If this impl block is an implementation of the Deref trait, then we
|
||||
// If this impl block is a positive implementation of the Deref trait, then we
|
||||
// need to try inlining the target's inherent impl blocks as well.
|
||||
if trait_.as_ref().map(|t| t.def_id()) == tcx.lang_items().deref_trait() {
|
||||
if trait_.as_ref().is_some_and(|t| tcx.lang_items().deref_trait() == Some(t.def_id()))
|
||||
&& tcx.impl_polarity(def_id) != ty::ImplPolarity::Negative
|
||||
{
|
||||
build_deref_target_impls(cx, &items, &mut ret);
|
||||
}
|
||||
|
||||
|
||||
@@ -1517,8 +1517,9 @@ fn render_assoc_items_inner(
|
||||
}
|
||||
|
||||
if !traits.is_empty() {
|
||||
let deref_impl =
|
||||
traits.iter().find(|t| t.trait_did() == cx.tcx().lang_items().deref_trait());
|
||||
let deref_impl = traits.iter().find(|t| {
|
||||
t.trait_did() == cx.tcx().lang_items().deref_trait() && !t.is_negative_trait_impl()
|
||||
});
|
||||
if let Some(impl_) = deref_impl {
|
||||
let has_deref_mut =
|
||||
traits.iter().any(|t| t.trait_did() == cx.tcx().lang_items().deref_mut_trait());
|
||||
|
||||
@@ -477,9 +477,9 @@ fn sidebar_assoc_items<'a>(
|
||||
];
|
||||
|
||||
if v.iter().any(|i| i.inner_impl().trait_.is_some()) {
|
||||
if let Some(impl_) =
|
||||
v.iter().find(|i| i.trait_did() == cx.tcx().lang_items().deref_trait())
|
||||
{
|
||||
if let Some(impl_) = v.iter().find(|i| {
|
||||
i.trait_did() == cx.tcx().lang_items().deref_trait() && !i.is_negative_trait_impl()
|
||||
}) {
|
||||
let mut derefs = DefIdSet::default();
|
||||
derefs.insert(did);
|
||||
sidebar_deref_methods(
|
||||
@@ -598,6 +598,7 @@ fn sidebar_deref_methods<'a>(
|
||||
.as_ref()
|
||||
.map(|t| Some(t.def_id()) == cx.tcx().lang_items().deref_trait())
|
||||
.unwrap_or(false)
|
||||
&& !i.is_negative_trait_impl()
|
||||
})
|
||||
{
|
||||
sidebar_deref_methods(
|
||||
|
||||
@@ -155,8 +155,9 @@ fn add_deref_target(
|
||||
|
||||
// scan through included items ahead of time to splice in Deref targets to the "valid" sets
|
||||
for it in new_items_external.iter().chain(new_items_local.iter()) {
|
||||
if let ImplItem(box Impl { ref for_, ref trait_, ref items, .. }) = it.kind
|
||||
if let ImplItem(box Impl { ref for_, ref trait_, ref items, polarity, .. }) = it.kind
|
||||
&& trait_.as_ref().map(|t| t.def_id()) == tcx.lang_items().deref_trait()
|
||||
&& polarity != ty::ImplPolarity::Negative
|
||||
&& cleaner.keep_impl(for_, true)
|
||||
{
|
||||
let target = items
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
#![feature(negative_impls)]
|
||||
#![crate_name = "foo"]
|
||||
|
||||
// Regression test for https://github.com/rust-lang/rust/issues/128801
|
||||
// Negative `Deref`/`DerefMut` impls should not cause an ICE and should still be rendered.
|
||||
|
||||
pub struct Source;
|
||||
|
||||
//@ has foo/struct.Source.html
|
||||
|
||||
// Verify negative Deref impl is rendered in the main content.
|
||||
//@ has - '//*[@class="impl"]//h3[@class="code-header"]' 'impl !Deref for Source'
|
||||
|
||||
// Verify negative DerefMut impl is rendered in the main content.
|
||||
//@ has - '//*[@class="impl"]//h3[@class="code-header"]' 'impl !DerefMut for Source'
|
||||
|
||||
// Verify negative impls appear in the sidebar.
|
||||
//@ has - '//div[@class="sidebar-elems"]//h3/a[@href="#trait-implementations"]' 'Trait Implementations'
|
||||
//@ has - '//*[@class="sidebar-elems"]//section//a' '!Deref'
|
||||
//@ has - '//*[@class="sidebar-elems"]//section//a' '!DerefMut'
|
||||
|
||||
impl !std::ops::Deref for Source {}
|
||||
impl !std::ops::DerefMut for Source {}
|
||||
@@ -0,0 +1,11 @@
|
||||
//@ check-pass
|
||||
|
||||
// Regression test for https://github.com/rust-lang/rust/issues/128801
|
||||
// Negative `Deref`/`DerefMut` impls should not cause an ICE.
|
||||
|
||||
#![feature(negative_impls)]
|
||||
|
||||
pub struct Source;
|
||||
|
||||
impl !std::ops::Deref for Source {}
|
||||
impl !std::ops::DerefMut for Source {}
|
||||
Reference in New Issue
Block a user