mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-22 06:44:35 +00:00
rustdoc: Create SelfTy
to replace Generic(kw::SelfUpper)
Rustdoc often has to special-case `Self` because it is, well, a special type of generic parameter (although it also behaves as an alias in concrete impls). Instead of spreading this special-casing throughout the code base, create a new variant of the `clean::Type` enum that is for `Self` types. This is a refactoring that has almost no impact on rustdoc's behavior, except that `&Self`, `(Self,)`, `&[Self]`, and other similar occurrences of `Self` no longer link to the wrapping type (reference primitive, tuple primitive, etc.) as regular generics do. I felt this made more sense since users would expect `Self` to link to the containing trait or aliased type (though those are usually expanded), not the primitive that is wrapping it. For an example of the change, see the docs for `std::alloc::Allocator::by_ref`.
This commit is contained in:
parent
249d686c70
commit
664b3ffbe9
@ -12,7 +12,7 @@ use rustc_middle::ty::fast_reject::SimplifiedType;
|
||||
use rustc_middle::ty::{self, TyCtxt};
|
||||
use rustc_span::def_id::LOCAL_CRATE;
|
||||
use rustc_span::hygiene::MacroKind;
|
||||
use rustc_span::symbol::{kw, sym, Symbol};
|
||||
use rustc_span::symbol::{sym, Symbol};
|
||||
use thin_vec::{thin_vec, ThinVec};
|
||||
use {rustc_ast as ast, rustc_hir as hir};
|
||||
|
||||
@ -792,11 +792,7 @@ fn build_macro(
|
||||
fn filter_non_trait_generics(trait_did: DefId, mut g: clean::Generics) -> clean::Generics {
|
||||
for pred in &mut g.where_predicates {
|
||||
match *pred {
|
||||
clean::WherePredicate::BoundPredicate {
|
||||
ty: clean::Generic(ref s),
|
||||
ref mut bounds,
|
||||
..
|
||||
} if *s == kw::SelfUpper => {
|
||||
clean::WherePredicate::BoundPredicate { ty: clean::SelfTy, ref mut bounds, .. } => {
|
||||
bounds.retain(|bound| match bound {
|
||||
clean::GenericBound::TraitBound(clean::PolyTrait { trait_, .. }, _) => {
|
||||
trait_.def_id() != trait_did
|
||||
@ -812,13 +808,13 @@ fn filter_non_trait_generics(trait_did: DefId, mut g: clean::Generics) -> clean:
|
||||
clean::WherePredicate::BoundPredicate {
|
||||
ty:
|
||||
clean::QPath(box clean::QPathData {
|
||||
self_type: clean::Generic(ref s),
|
||||
self_type: clean::Generic(_),
|
||||
trait_: Some(trait_),
|
||||
..
|
||||
}),
|
||||
bounds,
|
||||
..
|
||||
} => !(bounds.is_empty() || *s == kw::SelfUpper && trait_.def_id() == trait_did),
|
||||
} => !bounds.is_empty() && trait_.def_id() != trait_did,
|
||||
_ => true,
|
||||
});
|
||||
g
|
||||
@ -832,9 +828,7 @@ fn separate_supertrait_bounds(
|
||||
) -> (clean::Generics, Vec<clean::GenericBound>) {
|
||||
let mut ty_bounds = Vec::new();
|
||||
g.where_predicates.retain(|pred| match *pred {
|
||||
clean::WherePredicate::BoundPredicate { ty: clean::Generic(ref s), ref bounds, .. }
|
||||
if *s == kw::SelfUpper =>
|
||||
{
|
||||
clean::WherePredicate::BoundPredicate { ty: clean::SelfTy, ref bounds, .. } => {
|
||||
ty_bounds.extend(bounds.iter().cloned());
|
||||
false
|
||||
}
|
||||
|
@ -1351,11 +1351,11 @@ pub(crate) fn clean_middle_assoc_item<'tcx>(
|
||||
let self_arg_ty =
|
||||
tcx.fn_sig(assoc_item.def_id).instantiate_identity().input(0).skip_binder();
|
||||
if self_arg_ty == self_ty {
|
||||
item.decl.inputs.values[0].type_ = Generic(kw::SelfUpper);
|
||||
item.decl.inputs.values[0].type_ = SelfTy;
|
||||
} else if let ty::Ref(_, ty, _) = *self_arg_ty.kind() {
|
||||
if ty == self_ty {
|
||||
match item.decl.inputs.values[0].type_ {
|
||||
BorrowedRef { ref mut type_, .. } => **type_ = Generic(kw::SelfUpper),
|
||||
BorrowedRef { ref mut type_, .. } => **type_ = SelfTy,
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
@ -1439,9 +1439,8 @@ pub(crate) fn clean_middle_assoc_item<'tcx>(
|
||||
if trait_.def_id() != assoc_item.container_id(tcx) {
|
||||
return true;
|
||||
}
|
||||
match *self_type {
|
||||
Generic(ref s) if *s == kw::SelfUpper => {}
|
||||
_ => return true,
|
||||
if *self_type != SelfTy {
|
||||
return true;
|
||||
}
|
||||
match &assoc.args {
|
||||
GenericArgs::AngleBracketed { args, constraints } => {
|
||||
@ -2228,6 +2227,8 @@ pub(crate) fn clean_middle_ty<'tcx>(
|
||||
ty::Param(ref p) => {
|
||||
if let Some(bounds) = cx.impl_trait_bounds.remove(&p.index.into()) {
|
||||
ImplTrait(bounds)
|
||||
} else if p.name == kw::SelfUpper {
|
||||
SelfTy
|
||||
} else {
|
||||
Generic(p.name)
|
||||
}
|
||||
|
@ -145,7 +145,6 @@ pub(crate) fn sized_bounds(cx: &mut DocContext<'_>, generics: &mut clean::Generi
|
||||
// should be handled when cleaning associated types.
|
||||
generics.where_predicates.retain(|pred| {
|
||||
if let WP::BoundPredicate { ty: clean::Generic(param), bounds, .. } = pred
|
||||
&& *param != rustc_span::symbol::kw::SelfUpper
|
||||
&& bounds.iter().any(|b| b.is_sized_bound(cx))
|
||||
{
|
||||
sized_params.insert(*param);
|
||||
|
@ -37,7 +37,7 @@ pub(crate) use self::ItemKind::*;
|
||||
pub(crate) use self::ReceiverTy::*;
|
||||
pub(crate) use self::Type::{
|
||||
Array, BareFunction, BorrowedRef, DynTrait, Generic, ImplTrait, Infer, Primitive, QPath,
|
||||
RawPointer, Slice, Tuple,
|
||||
RawPointer, SelfTy, Slice, Tuple,
|
||||
};
|
||||
use crate::clean::cfg::Cfg;
|
||||
use crate::clean::clean_middle_path;
|
||||
@ -1477,6 +1477,8 @@ pub(crate) enum Type {
|
||||
DynTrait(Vec<PolyTrait>, Option<Lifetime>),
|
||||
/// A type parameter.
|
||||
Generic(Symbol),
|
||||
/// The `Self` type.
|
||||
SelfTy,
|
||||
/// A primitive (aka, builtin) type.
|
||||
Primitive(PrimitiveType),
|
||||
/// A function pointer: `extern "ABI" fn(...) -> ...`
|
||||
@ -1571,6 +1573,8 @@ impl Type {
|
||||
// If both sides are generic, this returns true.
|
||||
(_, Type::Generic(_)) => true,
|
||||
(Type::Generic(_), _) => false,
|
||||
// `Self` only matches itself.
|
||||
(Type::SelfTy, Type::SelfTy) => true,
|
||||
// Paths account for both the path itself and its generics.
|
||||
(Type::Path { path: a }, Type::Path { path: b }) => {
|
||||
a.def_id() == b.def_id()
|
||||
@ -1642,7 +1646,7 @@ impl Type {
|
||||
|
||||
pub(crate) fn is_self_type(&self) -> bool {
|
||||
match *self {
|
||||
Generic(name) => name == kw::SelfUpper,
|
||||
SelfTy => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
@ -1700,7 +1704,7 @@ impl Type {
|
||||
Type::Pat(..) => PrimitiveType::Pat,
|
||||
RawPointer(..) => PrimitiveType::RawPointer,
|
||||
QPath(box QPathData { ref self_type, .. }) => return self_type.def_id(cache),
|
||||
Generic(_) | Infer | ImplTrait(_) => return None,
|
||||
Generic(_) | SelfTy | Infer | ImplTrait(_) => return None,
|
||||
};
|
||||
Primitive(t).def_id(cache)
|
||||
}
|
||||
|
@ -468,7 +468,7 @@ pub(crate) fn resolve_type(cx: &mut DocContext<'_>, path: Path) -> Type {
|
||||
match path.res {
|
||||
Res::PrimTy(p) => Primitive(PrimitiveType::from(p)),
|
||||
Res::SelfTyParam { .. } | Res::SelfTyAlias { .. } if path.segments.len() == 1 => {
|
||||
Generic(kw::SelfUpper)
|
||||
Type::SelfTy
|
||||
}
|
||||
Res::Def(DefKind::TyParam, _) if path.segments.len() == 1 => Generic(path.segments[0].name),
|
||||
_ => {
|
||||
|
@ -1006,6 +1006,7 @@ fn fmt_type<'cx>(
|
||||
|
||||
match *t {
|
||||
clean::Generic(name) => f.write_str(name.as_str()),
|
||||
clean::SelfTy => f.write_str("Self"),
|
||||
clean::Type::Path { ref path } => {
|
||||
// Paths like `T::Output` and `Self::Output` should be rendered with all segments.
|
||||
let did = path.def_id();
|
||||
|
@ -797,7 +797,11 @@ fn get_index_type_id(
|
||||
}
|
||||
}
|
||||
// Not supported yet
|
||||
clean::Type::Pat(..) | clean::Generic(_) | clean::ImplTrait(_) | clean::Infer => None,
|
||||
clean::Type::Pat(..)
|
||||
| clean::Generic(_)
|
||||
| clean::SelfTy
|
||||
| clean::ImplTrait(_)
|
||||
| clean::Infer => None,
|
||||
}
|
||||
}
|
||||
|
||||
@ -848,13 +852,18 @@ fn simplify_fn_type<'tcx, 'a>(
|
||||
(false, arg)
|
||||
};
|
||||
|
||||
let as_arg_s = |t: &Type| match *t {
|
||||
Type::Generic(arg_s) => Some(arg_s),
|
||||
Type::SelfTy => Some(kw::SelfUpper),
|
||||
_ => None,
|
||||
};
|
||||
// If this argument is a type parameter and not a trait bound or a type, we need to look
|
||||
// for its bounds.
|
||||
if let Type::Generic(arg_s) = *arg {
|
||||
if let Some(arg_s) = as_arg_s(arg) {
|
||||
// First we check if the bounds are in a `where` predicate...
|
||||
let mut type_bounds = Vec::new();
|
||||
for where_pred in generics.where_predicates.iter().filter(|g| match g {
|
||||
WherePredicate::BoundPredicate { ty: Type::Generic(ty_s), .. } => *ty_s == arg_s,
|
||||
WherePredicate::BoundPredicate { ty, .. } => *ty == *arg,
|
||||
_ => false,
|
||||
}) {
|
||||
let bounds = where_pred.get_bounds().unwrap_or_else(|| &[]);
|
||||
|
@ -578,7 +578,7 @@ impl FromWithTcx<clean::Type> for Type {
|
||||
fn from_tcx(ty: clean::Type, tcx: TyCtxt<'_>) -> Self {
|
||||
use clean::Type::{
|
||||
Array, BareFunction, BorrowedRef, Generic, ImplTrait, Infer, Primitive, QPath,
|
||||
RawPointer, Slice, Tuple,
|
||||
RawPointer, SelfTy, Slice, Tuple,
|
||||
};
|
||||
|
||||
match ty {
|
||||
@ -588,6 +588,8 @@ impl FromWithTcx<clean::Type> for Type {
|
||||
traits: bounds.into_tcx(tcx),
|
||||
}),
|
||||
Generic(s) => Type::Generic(s.to_string()),
|
||||
// FIXME: add dedicated variant to json Type?
|
||||
SelfTy => Type::Generic("Self".to_owned()),
|
||||
Primitive(p) => Type::Primitive(p.as_sym().to_string()),
|
||||
BareFunction(f) => Type::FunctionPointer(Box::new((*f).into_tcx(tcx))),
|
||||
Tuple(t) => Type::Tuple(t.into_tcx(tcx)),
|
||||
|
Loading…
Reference in New Issue
Block a user