mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-22 14:55:26 +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_middle::ty::{self, TyCtxt};
|
||||||
use rustc_span::def_id::LOCAL_CRATE;
|
use rustc_span::def_id::LOCAL_CRATE;
|
||||||
use rustc_span::hygiene::MacroKind;
|
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 thin_vec::{thin_vec, ThinVec};
|
||||||
use {rustc_ast as ast, rustc_hir as hir};
|
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 {
|
fn filter_non_trait_generics(trait_did: DefId, mut g: clean::Generics) -> clean::Generics {
|
||||||
for pred in &mut g.where_predicates {
|
for pred in &mut g.where_predicates {
|
||||||
match *pred {
|
match *pred {
|
||||||
clean::WherePredicate::BoundPredicate {
|
clean::WherePredicate::BoundPredicate { ty: clean::SelfTy, ref mut bounds, .. } => {
|
||||||
ty: clean::Generic(ref s),
|
|
||||||
ref mut bounds,
|
|
||||||
..
|
|
||||||
} if *s == kw::SelfUpper => {
|
|
||||||
bounds.retain(|bound| match bound {
|
bounds.retain(|bound| match bound {
|
||||||
clean::GenericBound::TraitBound(clean::PolyTrait { trait_, .. }, _) => {
|
clean::GenericBound::TraitBound(clean::PolyTrait { trait_, .. }, _) => {
|
||||||
trait_.def_id() != trait_did
|
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 {
|
clean::WherePredicate::BoundPredicate {
|
||||||
ty:
|
ty:
|
||||||
clean::QPath(box clean::QPathData {
|
clean::QPath(box clean::QPathData {
|
||||||
self_type: clean::Generic(ref s),
|
self_type: clean::Generic(_),
|
||||||
trait_: Some(trait_),
|
trait_: Some(trait_),
|
||||||
..
|
..
|
||||||
}),
|
}),
|
||||||
bounds,
|
bounds,
|
||||||
..
|
..
|
||||||
} => !(bounds.is_empty() || *s == kw::SelfUpper && trait_.def_id() == trait_did),
|
} => !bounds.is_empty() && trait_.def_id() != trait_did,
|
||||||
_ => true,
|
_ => true,
|
||||||
});
|
});
|
||||||
g
|
g
|
||||||
@ -832,9 +828,7 @@ fn separate_supertrait_bounds(
|
|||||||
) -> (clean::Generics, Vec<clean::GenericBound>) {
|
) -> (clean::Generics, Vec<clean::GenericBound>) {
|
||||||
let mut ty_bounds = Vec::new();
|
let mut ty_bounds = Vec::new();
|
||||||
g.where_predicates.retain(|pred| match *pred {
|
g.where_predicates.retain(|pred| match *pred {
|
||||||
clean::WherePredicate::BoundPredicate { ty: clean::Generic(ref s), ref bounds, .. }
|
clean::WherePredicate::BoundPredicate { ty: clean::SelfTy, ref bounds, .. } => {
|
||||||
if *s == kw::SelfUpper =>
|
|
||||||
{
|
|
||||||
ty_bounds.extend(bounds.iter().cloned());
|
ty_bounds.extend(bounds.iter().cloned());
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
@ -1351,11 +1351,11 @@ pub(crate) fn clean_middle_assoc_item<'tcx>(
|
|||||||
let self_arg_ty =
|
let self_arg_ty =
|
||||||
tcx.fn_sig(assoc_item.def_id).instantiate_identity().input(0).skip_binder();
|
tcx.fn_sig(assoc_item.def_id).instantiate_identity().input(0).skip_binder();
|
||||||
if self_arg_ty == self_ty {
|
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() {
|
} else if let ty::Ref(_, ty, _) = *self_arg_ty.kind() {
|
||||||
if ty == self_ty {
|
if ty == self_ty {
|
||||||
match item.decl.inputs.values[0].type_ {
|
match item.decl.inputs.values[0].type_ {
|
||||||
BorrowedRef { ref mut type_, .. } => **type_ = Generic(kw::SelfUpper),
|
BorrowedRef { ref mut type_, .. } => **type_ = SelfTy,
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1439,9 +1439,8 @@ pub(crate) fn clean_middle_assoc_item<'tcx>(
|
|||||||
if trait_.def_id() != assoc_item.container_id(tcx) {
|
if trait_.def_id() != assoc_item.container_id(tcx) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
match *self_type {
|
if *self_type != SelfTy {
|
||||||
Generic(ref s) if *s == kw::SelfUpper => {}
|
return true;
|
||||||
_ => return true,
|
|
||||||
}
|
}
|
||||||
match &assoc.args {
|
match &assoc.args {
|
||||||
GenericArgs::AngleBracketed { args, constraints } => {
|
GenericArgs::AngleBracketed { args, constraints } => {
|
||||||
@ -2228,6 +2227,8 @@ pub(crate) fn clean_middle_ty<'tcx>(
|
|||||||
ty::Param(ref p) => {
|
ty::Param(ref p) => {
|
||||||
if let Some(bounds) = cx.impl_trait_bounds.remove(&p.index.into()) {
|
if let Some(bounds) = cx.impl_trait_bounds.remove(&p.index.into()) {
|
||||||
ImplTrait(bounds)
|
ImplTrait(bounds)
|
||||||
|
} else if p.name == kw::SelfUpper {
|
||||||
|
SelfTy
|
||||||
} else {
|
} else {
|
||||||
Generic(p.name)
|
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.
|
// should be handled when cleaning associated types.
|
||||||
generics.where_predicates.retain(|pred| {
|
generics.where_predicates.retain(|pred| {
|
||||||
if let WP::BoundPredicate { ty: clean::Generic(param), bounds, .. } = 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))
|
&& bounds.iter().any(|b| b.is_sized_bound(cx))
|
||||||
{
|
{
|
||||||
sized_params.insert(*param);
|
sized_params.insert(*param);
|
||||||
|
@ -37,7 +37,7 @@ pub(crate) use self::ItemKind::*;
|
|||||||
pub(crate) use self::ReceiverTy::*;
|
pub(crate) use self::ReceiverTy::*;
|
||||||
pub(crate) use self::Type::{
|
pub(crate) use self::Type::{
|
||||||
Array, BareFunction, BorrowedRef, DynTrait, Generic, ImplTrait, Infer, Primitive, QPath,
|
Array, BareFunction, BorrowedRef, DynTrait, Generic, ImplTrait, Infer, Primitive, QPath,
|
||||||
RawPointer, Slice, Tuple,
|
RawPointer, SelfTy, Slice, Tuple,
|
||||||
};
|
};
|
||||||
use crate::clean::cfg::Cfg;
|
use crate::clean::cfg::Cfg;
|
||||||
use crate::clean::clean_middle_path;
|
use crate::clean::clean_middle_path;
|
||||||
@ -1477,6 +1477,8 @@ pub(crate) enum Type {
|
|||||||
DynTrait(Vec<PolyTrait>, Option<Lifetime>),
|
DynTrait(Vec<PolyTrait>, Option<Lifetime>),
|
||||||
/// A type parameter.
|
/// A type parameter.
|
||||||
Generic(Symbol),
|
Generic(Symbol),
|
||||||
|
/// The `Self` type.
|
||||||
|
SelfTy,
|
||||||
/// A primitive (aka, builtin) type.
|
/// A primitive (aka, builtin) type.
|
||||||
Primitive(PrimitiveType),
|
Primitive(PrimitiveType),
|
||||||
/// A function pointer: `extern "ABI" fn(...) -> ...`
|
/// A function pointer: `extern "ABI" fn(...) -> ...`
|
||||||
@ -1571,6 +1573,8 @@ impl Type {
|
|||||||
// If both sides are generic, this returns true.
|
// If both sides are generic, this returns true.
|
||||||
(_, Type::Generic(_)) => true,
|
(_, Type::Generic(_)) => true,
|
||||||
(Type::Generic(_), _) => false,
|
(Type::Generic(_), _) => false,
|
||||||
|
// `Self` only matches itself.
|
||||||
|
(Type::SelfTy, Type::SelfTy) => true,
|
||||||
// Paths account for both the path itself and its generics.
|
// Paths account for both the path itself and its generics.
|
||||||
(Type::Path { path: a }, Type::Path { path: b }) => {
|
(Type::Path { path: a }, Type::Path { path: b }) => {
|
||||||
a.def_id() == b.def_id()
|
a.def_id() == b.def_id()
|
||||||
@ -1642,7 +1646,7 @@ impl Type {
|
|||||||
|
|
||||||
pub(crate) fn is_self_type(&self) -> bool {
|
pub(crate) fn is_self_type(&self) -> bool {
|
||||||
match *self {
|
match *self {
|
||||||
Generic(name) => name == kw::SelfUpper,
|
SelfTy => true,
|
||||||
_ => false,
|
_ => false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1700,7 +1704,7 @@ impl Type {
|
|||||||
Type::Pat(..) => PrimitiveType::Pat,
|
Type::Pat(..) => PrimitiveType::Pat,
|
||||||
RawPointer(..) => PrimitiveType::RawPointer,
|
RawPointer(..) => PrimitiveType::RawPointer,
|
||||||
QPath(box QPathData { ref self_type, .. }) => return self_type.def_id(cache),
|
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)
|
Primitive(t).def_id(cache)
|
||||||
}
|
}
|
||||||
|
@ -468,7 +468,7 @@ pub(crate) fn resolve_type(cx: &mut DocContext<'_>, path: Path) -> Type {
|
|||||||
match path.res {
|
match path.res {
|
||||||
Res::PrimTy(p) => Primitive(PrimitiveType::from(p)),
|
Res::PrimTy(p) => Primitive(PrimitiveType::from(p)),
|
||||||
Res::SelfTyParam { .. } | Res::SelfTyAlias { .. } if path.segments.len() == 1 => {
|
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),
|
Res::Def(DefKind::TyParam, _) if path.segments.len() == 1 => Generic(path.segments[0].name),
|
||||||
_ => {
|
_ => {
|
||||||
|
@ -1006,6 +1006,7 @@ fn fmt_type<'cx>(
|
|||||||
|
|
||||||
match *t {
|
match *t {
|
||||||
clean::Generic(name) => f.write_str(name.as_str()),
|
clean::Generic(name) => f.write_str(name.as_str()),
|
||||||
|
clean::SelfTy => f.write_str("Self"),
|
||||||
clean::Type::Path { ref path } => {
|
clean::Type::Path { ref path } => {
|
||||||
// Paths like `T::Output` and `Self::Output` should be rendered with all segments.
|
// Paths like `T::Output` and `Self::Output` should be rendered with all segments.
|
||||||
let did = path.def_id();
|
let did = path.def_id();
|
||||||
|
@ -797,7 +797,11 @@ fn get_index_type_id(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Not supported yet
|
// 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)
|
(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
|
// If this argument is a type parameter and not a trait bound or a type, we need to look
|
||||||
// for its bounds.
|
// 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...
|
// First we check if the bounds are in a `where` predicate...
|
||||||
let mut type_bounds = Vec::new();
|
let mut type_bounds = Vec::new();
|
||||||
for where_pred in generics.where_predicates.iter().filter(|g| match g {
|
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,
|
_ => false,
|
||||||
}) {
|
}) {
|
||||||
let bounds = where_pred.get_bounds().unwrap_or_else(|| &[]);
|
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 {
|
fn from_tcx(ty: clean::Type, tcx: TyCtxt<'_>) -> Self {
|
||||||
use clean::Type::{
|
use clean::Type::{
|
||||||
Array, BareFunction, BorrowedRef, Generic, ImplTrait, Infer, Primitive, QPath,
|
Array, BareFunction, BorrowedRef, Generic, ImplTrait, Infer, Primitive, QPath,
|
||||||
RawPointer, Slice, Tuple,
|
RawPointer, SelfTy, Slice, Tuple,
|
||||||
};
|
};
|
||||||
|
|
||||||
match ty {
|
match ty {
|
||||||
@ -588,6 +588,8 @@ impl FromWithTcx<clean::Type> for Type {
|
|||||||
traits: bounds.into_tcx(tcx),
|
traits: bounds.into_tcx(tcx),
|
||||||
}),
|
}),
|
||||||
Generic(s) => Type::Generic(s.to_string()),
|
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()),
|
Primitive(p) => Type::Primitive(p.as_sym().to_string()),
|
||||||
BareFunction(f) => Type::FunctionPointer(Box::new((*f).into_tcx(tcx))),
|
BareFunction(f) => Type::FunctionPointer(Box::new((*f).into_tcx(tcx))),
|
||||||
Tuple(t) => Type::Tuple(t.into_tcx(tcx)),
|
Tuple(t) => Type::Tuple(t.into_tcx(tcx)),
|
||||||
|
Loading…
Reference in New Issue
Block a user