Skip to content

Commit e85c7bb

Browse files
authored
Unrolled build for rust-lang#115201
Rollup merge of rust-lang#115201 - notriddle:notriddle/type-alias-impl-list, r=GuillaumeGomez rustdoc: list matching impls on type aliases Fixes rust-lang#32077 Fixes rust-lang#99952 Remake of rust-lang#112429 Partially reverts rust-lang#112543, but keeps the test case. This version of the PR avoids the infinite loop by structurally matching types instead of using full unification. This version does not support type alias trait bounds, but the compiler does not enforce those anyway (rust-lang#21903). r? `@GuillaumeGomez` CC `@lcnr`
2 parents cd71a37 + b3686c2 commit e85c7bb

File tree

3 files changed

+111
-13
lines changed

3 files changed

+111
-13
lines changed

library/core/src/ptr/mut_ptr.rs

+9-9
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ impl<T: ?Sized> *mut T {
109109
/// with [`cast_mut`] on `*const T` and may have documentation value if used instead of implicit
110110
/// coercion.
111111
///
112-
/// [`cast_mut`]: #method.cast_mut
112+
/// [`cast_mut`]: pointer::cast_mut
113113
#[stable(feature = "ptr_const_cast", since = "1.65.0")]
114114
#[rustc_const_stable(feature = "ptr_const_cast", since = "1.65.0")]
115115
#[rustc_diagnostic_item = "ptr_cast_const"]
@@ -121,7 +121,7 @@ impl<T: ?Sized> *mut T {
121121
/// Casts a pointer to its raw bits.
122122
///
123123
/// This is equivalent to `as usize`, but is more specific to enhance readability.
124-
/// The inverse method is [`from_bits`](#method.from_bits-1).
124+
/// The inverse method is [`from_bits`](pointer#method.from_bits-1).
125125
///
126126
/// In particular, `*p as usize` and `p as usize` will both compile for
127127
/// pointers to numeric types but do very different things, so using this
@@ -157,7 +157,7 @@ impl<T: ?Sized> *mut T {
157157
/// Creates a pointer from its raw bits.
158158
///
159159
/// This is equivalent to `as *mut T`, but is more specific to enhance readability.
160-
/// The inverse method is [`to_bits`](#method.to_bits-1).
160+
/// The inverse method is [`to_bits`](pointer#method.to_bits-1).
161161
///
162162
/// # Examples
163163
///
@@ -307,7 +307,7 @@ impl<T: ?Sized> *mut T {
307307
///
308308
/// For the mutable counterpart see [`as_mut`].
309309
///
310-
/// [`as_uninit_ref`]: #method.as_uninit_ref-1
310+
/// [`as_uninit_ref`]: pointer#method.as_uninit_ref-1
311311
/// [`as_mut`]: #method.as_mut
312312
///
313313
/// # Safety
@@ -373,7 +373,7 @@ impl<T: ?Sized> *mut T {
373373
///
374374
/// For the mutable counterpart see [`as_uninit_mut`].
375375
///
376-
/// [`as_ref`]: #method.as_ref-1
376+
/// [`as_ref`]: pointer#method.as_ref-1
377377
/// [`as_uninit_mut`]: #method.as_uninit_mut
378378
///
379379
/// # Safety
@@ -628,7 +628,7 @@ impl<T: ?Sized> *mut T {
628628
/// For the shared counterpart see [`as_ref`].
629629
///
630630
/// [`as_uninit_mut`]: #method.as_uninit_mut
631-
/// [`as_ref`]: #method.as_ref-1
631+
/// [`as_ref`]: pointer#method.as_ref-1
632632
///
633633
/// # Safety
634634
///
@@ -693,7 +693,7 @@ impl<T: ?Sized> *mut T {
693693
/// For the shared counterpart see [`as_uninit_ref`].
694694
///
695695
/// [`as_mut`]: #method.as_mut
696-
/// [`as_uninit_ref`]: #method.as_uninit_ref-1
696+
/// [`as_uninit_ref`]: pointer#method.as_uninit_ref-1
697697
///
698698
/// # Safety
699699
///
@@ -783,7 +783,7 @@ impl<T: ?Sized> *mut T {
783783
///
784784
/// This function is the inverse of [`offset`].
785785
///
786-
/// [`offset`]: #method.offset-1
786+
/// [`offset`]: pointer#method.offset-1
787787
///
788788
/// # Safety
789789
///
@@ -2064,7 +2064,7 @@ impl<T> *mut [T] {
20642064
///
20652065
/// For the mutable counterpart see [`as_uninit_slice_mut`].
20662066
///
2067-
/// [`as_ref`]: #method.as_ref-1
2067+
/// [`as_ref`]: pointer#method.as_ref-1
20682068
/// [`as_uninit_slice_mut`]: #method.as_uninit_slice_mut
20692069
///
20702070
/// # Safety

src/librustdoc/html/render/mod.rs

+43-4
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet};
5454
use rustc_hir::def_id::{DefId, DefIdSet};
5555
use rustc_hir::Mutability;
5656
use rustc_middle::middle::stability;
57+
use rustc_middle::ty::fast_reject::{DeepRejectCtxt, TreatParams};
5758
use rustc_middle::ty::TyCtxt;
5859
use rustc_span::{
5960
symbol::{sym, Symbol},
@@ -62,6 +63,7 @@ use rustc_span::{
6263
use serde::ser::{SerializeMap, SerializeSeq};
6364
use serde::{Serialize, Serializer};
6465

66+
use crate::clean::types::TypeAliasItem;
6567
use crate::clean::{self, ItemId, RenderedLink, SelfTy};
6668
use crate::error::Error;
6769
use crate::formats::cache::Cache;
@@ -1139,8 +1141,40 @@ fn render_assoc_items_inner(
11391141
info!("Documenting associated items of {:?}", containing_item.name);
11401142
let shared = Rc::clone(&cx.shared);
11411143
let cache = &shared.cache;
1142-
let Some(v) = cache.impls.get(&it) else { return };
1143-
let (non_trait, traits): (Vec<_>, _) = v.iter().partition(|i| i.inner_impl().trait_.is_none());
1144+
let tcx = cx.tcx();
1145+
let av = if let TypeAliasItem(ait) = &*containing_item.kind &&
1146+
let aliased_clean_type = ait.item_type.as_ref().unwrap_or(&ait.type_) &&
1147+
let Some(aliased_type_defid) = aliased_clean_type.def_id(cache) &&
1148+
let Some(mut av) = cache.impls.get(&aliased_type_defid).cloned() &&
1149+
let Some(alias_def_id) = containing_item.item_id.as_def_id()
1150+
{
1151+
// This branch of the compiler compares types structually, but does
1152+
// not check trait bounds. That's probably fine, since type aliases
1153+
// don't normally constrain on them anyway.
1154+
// https://github.com/rust-lang/rust/issues/21903
1155+
//
1156+
// FIXME(lazy_type_alias): Once the feature is complete or stable, rewrite this to use type unification.
1157+
// Be aware of `tests/rustdoc/issue-112515-impl-ty-alias.rs` which might regress.
1158+
let aliased_ty = tcx.type_of(alias_def_id).skip_binder();
1159+
let reject_cx = DeepRejectCtxt {
1160+
treat_obligation_params: TreatParams::AsCandidateKey,
1161+
};
1162+
av.retain(|impl_| {
1163+
if let Some(impl_def_id) = impl_.impl_item.item_id.as_def_id() {
1164+
reject_cx.types_may_unify(aliased_ty, tcx.type_of(impl_def_id).skip_binder())
1165+
} else {
1166+
false
1167+
}
1168+
});
1169+
av
1170+
} else {
1171+
Vec::new()
1172+
};
1173+
let blank = Vec::new();
1174+
let v = cache.impls.get(&it).unwrap_or(&blank);
1175+
let (non_trait, traits): (Vec<_>, _) =
1176+
v.iter().chain(&av[..]).partition(|i| i.inner_impl().trait_.is_none());
1177+
let mut saw_impls = FxHashSet::default();
11441178
if !non_trait.is_empty() {
11451179
let mut tmp_buf = Buffer::html();
11461180
let (render_mode, id, class_html) = match what {
@@ -1169,6 +1203,9 @@ fn render_assoc_items_inner(
11691203
};
11701204
let mut impls_buf = Buffer::html();
11711205
for i in &non_trait {
1206+
if !saw_impls.insert(i.def_id()) {
1207+
continue;
1208+
}
11721209
render_impl(
11731210
&mut impls_buf,
11741211
cx,
@@ -1214,8 +1251,10 @@ fn render_assoc_items_inner(
12141251

12151252
let (synthetic, concrete): (Vec<&Impl>, Vec<&Impl>) =
12161253
traits.into_iter().partition(|t| t.inner_impl().kind.is_auto());
1217-
let (blanket_impl, concrete): (Vec<&Impl>, _) =
1218-
concrete.into_iter().partition(|t| t.inner_impl().kind.is_blanket());
1254+
let (blanket_impl, concrete): (Vec<&Impl>, _) = concrete
1255+
.into_iter()
1256+
.filter(|t| saw_impls.insert(t.def_id()))
1257+
.partition(|t| t.inner_impl().kind.is_blanket());
12191258

12201259
render_all_impls(w, cx, containing_item, &concrete, &synthetic, &blanket_impl);
12211260
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
// Regression test for <https://github.com/rust-lang/rust/issues/32077>.
2+
3+
#![crate_name = "foo"]
4+
5+
pub struct GenericStruct<T>(T);
6+
7+
impl<T> GenericStruct<T> {
8+
pub fn on_gen(arg: T) {}
9+
}
10+
11+
impl GenericStruct<u32> {
12+
pub fn on_u32(arg: u32) {}
13+
}
14+
15+
pub trait Foo {}
16+
pub trait Bar {}
17+
18+
impl<T> Foo for GenericStruct<T> {}
19+
impl Bar for GenericStruct<u32> {}
20+
21+
// @has 'foo/type.TypedefStruct.html'
22+
// We check that we have the implementation of the type alias itself.
23+
// @has - '//*[@id="impl-TypedefStruct"]/h3' 'impl TypedefStruct'
24+
// @has - '//*[@id="method.on_alias"]/h4' 'pub fn on_alias()'
25+
// @has - '//*[@id="impl-GenericStruct%3CT%3E"]/h3' 'impl<T> GenericStruct<T>'
26+
// @has - '//*[@id="method.on_gen"]/h4' 'pub fn on_gen(arg: T)'
27+
// @has - '//*[@id="impl-Foo-for-GenericStruct%3CT%3E"]/h3' 'impl<T> Foo for GenericStruct<T>'
28+
// This trait implementation doesn't match the type alias parameters so shouldn't appear in docs.
29+
// @!has - '//h3' 'impl Bar for GenericStruct<u32> {}'
30+
// Same goes for the `Deref` impl.
31+
// @!has - '//h2' 'Methods from Deref<Target = u32>'
32+
pub type TypedefStruct = GenericStruct<u8>;
33+
34+
impl TypedefStruct {
35+
pub fn on_alias() {}
36+
}
37+
38+
impl std::ops::Deref for GenericStruct<u32> {
39+
type Target = u32;
40+
41+
fn deref(&self) -> &Self::Target {
42+
&self.0
43+
}
44+
}
45+
46+
pub struct Wrap<T>(GenericStruct<T>);
47+
48+
// @has 'foo/type.Alias.html'
49+
// @has - '//h2' 'Methods from Deref<Target = u32>'
50+
// @has - '//*[@id="impl-Deref-for-Wrap%3CT%3E"]/h3' 'impl<T> Deref for Wrap<T>'
51+
pub type Alias = Wrap<u32>;
52+
53+
impl<T> std::ops::Deref for Wrap<T> {
54+
type Target = GenericStruct<T>;
55+
56+
fn deref(&self) -> &Self::Target {
57+
&self.0
58+
}
59+
}

0 commit comments

Comments
 (0)