]>
Commit | Line | Data |
---|---|---|
1a4d82fc JJ |
1 | //! This module contains the "cleaned" pieces of the AST, and the functions |
2 | //! that clean them. | |
3 | ||
0731742a XL |
4 | mod auto_trait; |
5 | mod blanket_impl; | |
fc512014 XL |
6 | crate mod cfg; |
7 | crate mod inline; | |
60c5eb7d | 8 | mod simplify; |
fc512014 XL |
9 | crate mod types; |
10 | crate mod utils; | |
1a4d82fc | 11 | |
3dfed10e | 12 | use rustc_ast as ast; |
74b04a01 | 13 | use rustc_attr as attr; |
dfeec247 XL |
14 | use rustc_data_structures::fx::{FxHashMap, FxHashSet}; |
15 | use rustc_hir as hir; | |
16 | use rustc_hir::def::{CtorKind, DefKind, Res}; | |
136023e0 | 17 | use rustc_hir::def_id::{DefId, CRATE_DEF_INDEX, LOCAL_CRATE}; |
dfeec247 | 18 | use rustc_index::vec::{Idx, IndexVec}; |
74b04a01 | 19 | use rustc_infer::infer::region_constraints::{Constraint, RegionConstraintData}; |
ba9703b0 | 20 | use rustc_middle::middle::resolve_lifetime as rl; |
ba9703b0 | 21 | use rustc_middle::ty::fold::TypeFolder; |
29967ef6 | 22 | use rustc_middle::ty::subst::{InternalSubsts, Subst}; |
136023e0 | 23 | use rustc_middle::ty::{self, AdtKind, DefIdTree, Lift, Ty, TyCtxt}; |
17df50a5 | 24 | use rustc_middle::{bug, span_bug}; |
cdc7bbd5 | 25 | use rustc_mir::const_eval::{is_const_fn, is_unstable_const_fn}; |
29967ef6 | 26 | use rustc_span::hygiene::{AstPass, MacroKind}; |
f9f354fc | 27 | use rustc_span::symbol::{kw, sym, Ident, Symbol}; |
fc512014 | 28 | use rustc_span::{self, ExpnKind}; |
136023e0 XL |
29 | use rustc_target::spec::abi::Abi; |
30 | use rustc_typeck::check::intrinsic::intrinsic_operation_unsafety; | |
dfeec247 | 31 | use rustc_typeck::hir_ty_to_ty; |
94b46f34 | 32 | |
0531ce1d | 33 | use std::collections::hash_map::Entry; |
ff7c6d11 | 34 | use std::default::Default; |
dfeec247 | 35 | use std::hash::Hash; |
1a4d82fc | 36 | use std::rc::Rc; |
dfeec247 | 37 | use std::{mem, vec}; |
1a4d82fc | 38 | |
e1599b0c | 39 | use crate::core::{self, DocContext, ImplTraitParam}; |
9fa01778 | 40 | use crate::doctree; |
cdc7bbd5 | 41 | use crate::formats::item_type::ItemType; |
9fa01778 | 42 | |
60c5eb7d | 43 | use utils::*; |
1a4d82fc | 44 | |
fc512014 | 45 | crate use utils::{get_auto_trait_and_blanket_impls, krate, register_res}; |
0531ce1d | 46 | |
fc512014 XL |
47 | crate use self::types::FnRetTy::*; |
48 | crate use self::types::ItemKind::*; | |
49 | crate use self::types::SelfTy::*; | |
50 | crate use self::types::Type::*; | |
51 | crate use self::types::Visibility::{Inherited, Public}; | |
52 | crate use self::types::*; | |
0531ce1d | 53 | |
fc512014 | 54 | crate trait Clean<T> { |
6a06907d | 55 | fn clean(&self, cx: &mut DocContext<'_>) -> T; |
1a4d82fc JJ |
56 | } |
57 | ||
c34b1796 | 58 | impl<T: Clean<U>, U> Clean<Vec<U>> for [T] { |
6a06907d | 59 | fn clean(&self, cx: &mut DocContext<'_>) -> Vec<U> { |
1a4d82fc JJ |
60 | self.iter().map(|x| x.clean(cx)).collect() |
61 | } | |
62 | } | |
63 | ||
a1dfa0c6 | 64 | impl<T: Clean<U>, U, V: Idx> Clean<IndexVec<V, U>> for IndexVec<V, T> { |
6a06907d | 65 | fn clean(&self, cx: &mut DocContext<'_>) -> IndexVec<V, U> { |
a1dfa0c6 XL |
66 | self.iter().map(|x| x.clean(cx)).collect() |
67 | } | |
68 | } | |
69 | ||
dfeec247 | 70 | impl<T: Clean<U>, U> Clean<U> for &T { |
6a06907d | 71 | fn clean(&self, cx: &mut DocContext<'_>) -> U { |
1a4d82fc JJ |
72 | (**self).clean(cx) |
73 | } | |
74 | } | |
75 | ||
76 | impl<T: Clean<U>, U> Clean<U> for Rc<T> { | |
6a06907d | 77 | fn clean(&self, cx: &mut DocContext<'_>) -> U { |
1a4d82fc JJ |
78 | (**self).clean(cx) |
79 | } | |
80 | } | |
81 | ||
82 | impl<T: Clean<U>, U> Clean<Option<U>> for Option<T> { | |
6a06907d | 83 | fn clean(&self, cx: &mut DocContext<'_>) -> Option<U> { |
54a0048b | 84 | self.as_ref().map(|v| v.clean(cx)) |
1a4d82fc JJ |
85 | } |
86 | } | |
87 | ||
dc9dc135 | 88 | impl Clean<Item> for doctree::Module<'_> { |
6a06907d | 89 | fn clean(&self, cx: &mut DocContext<'_>) -> Item { |
85aaf69f | 90 | let mut items: Vec<Item> = vec![]; |
dc9dc135 | 91 | items.extend(self.foreigns.iter().map(|x| x.clean(cx))); |
85aaf69f | 92 | items.extend(self.mods.iter().map(|x| x.clean(cx))); |
fc512014 | 93 | items.extend(self.items.iter().map(|x| x.clean(cx)).flatten()); |
85aaf69f | 94 | items.extend(self.macros.iter().map(|x| x.clean(cx))); |
2c00a5a8 | 95 | |
1a4d82fc JJ |
96 | // determine if we should display the inner contents or |
97 | // the outer `mod` item for the source code. | |
cdc7bbd5 | 98 | let span = Span::from_rustc_span({ |
17df50a5 | 99 | let where_outer = self.where_outer(cx.tcx); |
74b04a01 | 100 | let sm = cx.sess().source_map(); |
17df50a5 | 101 | let outer = sm.lookup_char_pos(where_outer.lo()); |
74b04a01 | 102 | let inner = sm.lookup_char_pos(self.where_inner.lo()); |
1a4d82fc JJ |
103 | if outer.file.start_pos == inner.file.start_pos { |
104 | // mod foo { ... } | |
17df50a5 | 105 | where_outer |
1a4d82fc | 106 | } else { |
b7449926 | 107 | // mod foo; (and a separate SourceFile for the contents) |
1a4d82fc JJ |
108 | self.where_inner |
109 | } | |
cdc7bbd5 | 110 | }); |
1a4d82fc | 111 | |
cdc7bbd5 | 112 | Item::from_hir_id_and_parts( |
fc512014 | 113 | self.id, |
cdc7bbd5 XL |
114 | Some(self.name), |
115 | ModuleItem(Module { items, span }), | |
fc512014 | 116 | cx, |
cdc7bbd5 | 117 | ) |
1a4d82fc JJ |
118 | } |
119 | } | |
120 | ||
476ff2be | 121 | impl Clean<Attributes> for [ast::Attribute] { |
cdc7bbd5 XL |
122 | fn clean(&self, _cx: &mut DocContext<'_>) -> Attributes { |
123 | Attributes::from_ast(self, None) | |
1a4d82fc JJ |
124 | } |
125 | } | |
126 | ||
dfeec247 | 127 | impl Clean<GenericBound> for hir::GenericBound<'_> { |
6a06907d | 128 | fn clean(&self, cx: &mut DocContext<'_>) -> GenericBound { |
1a4d82fc | 129 | match *self { |
8faf50e0 | 130 | hir::GenericBound::Outlives(lt) => GenericBound::Outlives(lt.clean(cx)), |
3dfed10e XL |
131 | hir::GenericBound::LangItemTrait(lang_item, span, _, generic_args) => { |
132 | let def_id = cx.tcx.require_lang_item(lang_item, Some(span)); | |
133 | ||
134 | let trait_ref = ty::TraitRef::identity(cx.tcx, def_id); | |
135 | ||
136 | let generic_args = generic_args.clean(cx); | |
137 | let bindings = match generic_args { | |
138 | GenericArgs::AngleBracketed { bindings, .. } => bindings, | |
139 | _ => bug!("clean: parenthesized `GenericBound::LangItemTrait`"), | |
140 | }; | |
141 | ||
142 | GenericBound::TraitBound( | |
143 | PolyTrait { trait_: (trait_ref, &*bindings).clean(cx), generic_params: vec![] }, | |
144 | hir::TraitBoundModifier::None, | |
145 | ) | |
146 | } | |
8faf50e0 XL |
147 | hir::GenericBound::Trait(ref t, modifier) => { |
148 | GenericBound::TraitBound(t.clean(cx), modifier) | |
149 | } | |
1a4d82fc JJ |
150 | } |
151 | } | |
152 | } | |
153 | ||
ba9703b0 | 154 | impl Clean<Type> for (ty::TraitRef<'_>, &[TypeBinding]) { |
6a06907d | 155 | fn clean(&self, cx: &mut DocContext<'_>) -> Type { |
ba9703b0 | 156 | let (trait_ref, bounds) = *self; |
17df50a5 XL |
157 | let kind = cx.tcx.def_kind(trait_ref.def_id).into(); |
158 | if !matches!(kind, ItemType::Trait | ItemType::TraitAlias) { | |
159 | span_bug!( | |
160 | cx.tcx.def_span(trait_ref.def_id), | |
161 | "`TraitRef` had unexpected kind {:?}", | |
162 | kind | |
163 | ); | |
164 | } | |
165 | inline::record_extern_fqn(cx, trait_ref.def_id, kind); | |
dfeec247 XL |
166 | let path = external_path( |
167 | cx, | |
168 | cx.tcx.item_name(trait_ref.def_id), | |
169 | Some(trait_ref.def_id), | |
170 | true, | |
ba9703b0 | 171 | bounds.to_vec(), |
dfeec247 XL |
172 | trait_ref.substs, |
173 | ); | |
1a4d82fc | 174 | |
0531ce1d | 175 | debug!("ty::TraitRef\n subst: {:?}\n", trait_ref.substs); |
1a4d82fc | 176 | |
136023e0 | 177 | ResolvedPath { path, did: trait_ref.def_id, is_generic: false } |
ba9703b0 XL |
178 | } |
179 | } | |
180 | ||
181 | impl<'tcx> Clean<GenericBound> for ty::TraitRef<'tcx> { | |
6a06907d | 182 | fn clean(&self, cx: &mut DocContext<'_>) -> GenericBound { |
ba9703b0 XL |
183 | GenericBound::TraitBound( |
184 | PolyTrait { trait_: (*self, &[][..]).clean(cx), generic_params: vec![] }, | |
185 | hir::TraitBoundModifier::None, | |
186 | ) | |
187 | } | |
188 | } | |
189 | ||
190 | impl Clean<GenericBound> for (ty::PolyTraitRef<'_>, &[TypeBinding]) { | |
6a06907d | 191 | fn clean(&self, cx: &mut DocContext<'_>) -> GenericBound { |
ba9703b0 XL |
192 | let (poly_trait_ref, bounds) = *self; |
193 | let poly_trait_ref = poly_trait_ref.lift_to_tcx(cx.tcx).unwrap(); | |
194 | ||
1a4d82fc | 195 | // collect any late bound regions |
ba9703b0 XL |
196 | let late_bound_regions: Vec<_> = cx |
197 | .tcx | |
198 | .collect_referenced_late_bound_regions(&poly_trait_ref) | |
199 | .into_iter() | |
200 | .filter_map(|br| match br { | |
fc512014 XL |
201 | ty::BrNamed(_, name) => { |
202 | Some(GenericParamDef { name, kind: GenericParamDefKind::Lifetime }) | |
203 | } | |
ba9703b0 XL |
204 | _ => None, |
205 | }) | |
206 | .collect(); | |
1a4d82fc | 207 | |
8faf50e0 | 208 | GenericBound::TraitBound( |
54a0048b | 209 | PolyTrait { |
f035d41b | 210 | trait_: (poly_trait_ref.skip_binder(), bounds).clean(cx), |
ba9703b0 | 211 | generic_params: late_bound_regions, |
62682a34 | 212 | }, |
dfeec247 | 213 | hir::TraitBoundModifier::None, |
54a0048b | 214 | ) |
1a4d82fc JJ |
215 | } |
216 | } | |
217 | ||
ba9703b0 | 218 | impl<'tcx> Clean<GenericBound> for ty::PolyTraitRef<'tcx> { |
6a06907d | 219 | fn clean(&self, cx: &mut DocContext<'_>) -> GenericBound { |
ba9703b0 | 220 | (*self, &[][..]).clean(cx) |
0531ce1d XL |
221 | } |
222 | } | |
223 | ||
e9174d1e | 224 | impl Clean<Lifetime> for hir::Lifetime { |
6a06907d | 225 | fn clean(&self, cx: &mut DocContext<'_>) -> Lifetime { |
ba9703b0 XL |
226 | let def = cx.tcx.named_region(self.hir_id); |
227 | match def { | |
228 | Some( | |
229 | rl::Region::EarlyBound(_, node_id, _) | |
cdc7bbd5 | 230 | | rl::Region::LateBound(_, _, node_id, _) |
ba9703b0 XL |
231 | | rl::Region::Free(_, node_id), |
232 | ) => { | |
6a06907d | 233 | if let Some(lt) = cx.lt_substs.get(&node_id).cloned() { |
ba9703b0 | 234 | return lt; |
9e0c209e | 235 | } |
9e0c209e | 236 | } |
ba9703b0 | 237 | _ => {} |
9e0c209e | 238 | } |
fc512014 | 239 | Lifetime(self.name.ident().name) |
1a4d82fc JJ |
240 | } |
241 | } | |
242 | ||
dfeec247 | 243 | impl Clean<Lifetime> for hir::GenericParam<'_> { |
6a06907d | 244 | fn clean(&self, _: &mut DocContext<'_>) -> Lifetime { |
8faf50e0 XL |
245 | match self.kind { |
246 | hir::GenericParamKind::Lifetime { .. } => { | |
74b04a01 | 247 | if !self.bounds.is_empty() { |
8faf50e0 XL |
248 | let mut bounds = self.bounds.iter().map(|bound| match bound { |
249 | hir::GenericBound::Outlives(lt) => lt, | |
250 | _ => panic!(), | |
251 | }); | |
b7449926 | 252 | let name = bounds.next().expect("no more bounds").name.ident(); |
8faf50e0 XL |
253 | let mut s = format!("{}: {}", self.name.ident(), name); |
254 | for bound in bounds { | |
255 | s.push_str(&format!(" + {}", bound.name.ident())); | |
256 | } | |
fc512014 | 257 | Lifetime(Symbol::intern(&s)) |
8faf50e0 | 258 | } else { |
fc512014 | 259 | Lifetime(self.name.ident().name) |
8faf50e0 | 260 | } |
a7813a04 | 261 | } |
8faf50e0 | 262 | _ => panic!(), |
a7813a04 | 263 | } |
1a4d82fc JJ |
264 | } |
265 | } | |
266 | ||
9fa01778 | 267 | impl Clean<Constant> for hir::ConstArg { |
6a06907d | 268 | fn clean(&self, cx: &mut DocContext<'_>) -> Constant { |
9fa01778 | 269 | Constant { |
ba9703b0 XL |
270 | type_: cx |
271 | .tcx | |
272 | .type_of(cx.tcx.hir().body_owner_def_id(self.value.body).to_def_id()) | |
273 | .clean(cx), | |
cdc7bbd5 | 274 | kind: ConstantKind::Anonymous { body: self.value.body }, |
9fa01778 XL |
275 | } |
276 | } | |
277 | } | |
278 | ||
7cac9316 | 279 | impl Clean<Option<Lifetime>> for ty::RegionKind { |
6a06907d | 280 | fn clean(&self, _cx: &mut DocContext<'_>) -> Option<Lifetime> { |
1a4d82fc JJ |
281 | match *self { |
282 | ty::ReStatic => Some(Lifetime::statik()), | |
cdc7bbd5 | 283 | ty::ReLateBound(_, ty::BoundRegion { kind: ty::BrNamed(_, name), .. }) => { |
fc512014 XL |
284 | Some(Lifetime(name)) |
285 | } | |
286 | ty::ReEarlyBound(ref data) => Some(Lifetime(data.name)), | |
1a4d82fc | 287 | |
dfeec247 XL |
288 | ty::ReLateBound(..) |
289 | | ty::ReFree(..) | |
dfeec247 XL |
290 | | ty::ReVar(..) |
291 | | ty::RePlaceholder(..) | |
74b04a01 | 292 | | ty::ReEmpty(_) |
dfeec247 | 293 | | ty::ReErased => { |
416331ca | 294 | debug!("cannot clean region {:?}", self); |
9fa01778 XL |
295 | None |
296 | } | |
1a4d82fc JJ |
297 | } |
298 | } | |
299 | } | |
300 | ||
dfeec247 | 301 | impl Clean<WherePredicate> for hir::WherePredicate<'_> { |
6a06907d | 302 | fn clean(&self, cx: &mut DocContext<'_>) -> WherePredicate { |
1a4d82fc | 303 | match *self { |
dfeec247 XL |
304 | hir::WherePredicate::BoundPredicate(ref wbp) => WherePredicate::BoundPredicate { |
305 | ty: wbp.bounded_ty.clean(cx), | |
306 | bounds: wbp.bounds.clean(cx), | |
136023e0 | 307 | bound_params: wbp.bound_generic_params.into_iter().map(|x| x.clean(cx)).collect(), |
dfeec247 | 308 | }, |
1a4d82fc | 309 | |
dfeec247 XL |
310 | hir::WherePredicate::RegionPredicate(ref wrp) => WherePredicate::RegionPredicate { |
311 | lifetime: wrp.lifetime.clean(cx), | |
312 | bounds: wrp.bounds.clean(cx), | |
313 | }, | |
1a4d82fc | 314 | |
32a655c1 | 315 | hir::WherePredicate::EqPredicate(ref wrp) => { |
dfeec247 | 316 | WherePredicate::EqPredicate { lhs: wrp.lhs_ty.clean(cx), rhs: wrp.rhs_ty.clean(cx) } |
1a4d82fc JJ |
317 | } |
318 | } | |
319 | } | |
320 | } | |
321 | ||
9fa01778 | 322 | impl<'a> Clean<Option<WherePredicate>> for ty::Predicate<'a> { |
6a06907d | 323 | fn clean(&self, cx: &mut DocContext<'_>) -> Option<WherePredicate> { |
5869c6ff | 324 | let bound_predicate = self.kind(); |
fc512014 | 325 | match bound_predicate.skip_binder() { |
5869c6ff XL |
326 | ty::PredicateKind::Trait(pred, _) => Some(bound_predicate.rebind(pred).clean(cx)), |
327 | ty::PredicateKind::RegionOutlives(pred) => pred.clean(cx), | |
328 | ty::PredicateKind::TypeOutlives(pred) => pred.clean(cx), | |
329 | ty::PredicateKind::Projection(pred) => Some(pred.clean(cx)), | |
136023e0 | 330 | ty::PredicateKind::ConstEvaluatable(..) => None, |
5869c6ff XL |
331 | |
332 | ty::PredicateKind::Subtype(..) | |
333 | | ty::PredicateKind::WellFormed(..) | |
334 | | ty::PredicateKind::ObjectSafe(..) | |
335 | | ty::PredicateKind::ClosureKind(..) | |
5869c6ff XL |
336 | | ty::PredicateKind::ConstEquate(..) |
337 | | ty::PredicateKind::TypeWellFormedFromEnv(..) => panic!("not user writable"), | |
85aaf69f SL |
338 | } |
339 | } | |
340 | } | |
341 | ||
ba9703b0 | 342 | impl<'a> Clean<WherePredicate> for ty::PolyTraitPredicate<'a> { |
6a06907d | 343 | fn clean(&self, cx: &mut DocContext<'_>) -> WherePredicate { |
ba9703b0 | 344 | let poly_trait_ref = self.map_bound(|pred| pred.trait_ref); |
85aaf69f | 345 | WherePredicate::BoundPredicate { |
f035d41b | 346 | ty: poly_trait_ref.skip_binder().self_ty().clean(cx), |
ba9703b0 | 347 | bounds: vec![poly_trait_ref.clean(cx)], |
136023e0 | 348 | bound_params: Vec::new(), |
85aaf69f SL |
349 | } |
350 | } | |
351 | } | |
352 | ||
dfeec247 | 353 | impl<'tcx> Clean<Option<WherePredicate>> |
3dfed10e | 354 | for ty::OutlivesPredicate<ty::Region<'tcx>, ty::Region<'tcx>> |
dfeec247 | 355 | { |
6a06907d | 356 | fn clean(&self, cx: &mut DocContext<'_>) -> Option<WherePredicate> { |
3dfed10e | 357 | let ty::OutlivesPredicate(a, b) = self; |
9fa01778 | 358 | |
ba9703b0 XL |
359 | if let (ty::ReEmpty(_), ty::ReEmpty(_)) = (a, b) { |
360 | return None; | |
9fa01778 XL |
361 | } |
362 | ||
363 | Some(WherePredicate::RegionPredicate { | |
b7449926 | 364 | lifetime: a.clean(cx).expect("failed to clean lifetime"), |
dfeec247 | 365 | bounds: vec![GenericBound::Outlives(b.clean(cx).expect("failed to clean bounds"))], |
9fa01778 | 366 | }) |
85aaf69f SL |
367 | } |
368 | } | |
369 | ||
3dfed10e | 370 | impl<'tcx> Clean<Option<WherePredicate>> for ty::OutlivesPredicate<Ty<'tcx>, ty::Region<'tcx>> { |
6a06907d | 371 | fn clean(&self, cx: &mut DocContext<'_>) -> Option<WherePredicate> { |
3dfed10e | 372 | let ty::OutlivesPredicate(ty, lt) = self; |
85aaf69f | 373 | |
ba9703b0 XL |
374 | if let ty::ReEmpty(_) = lt { |
375 | return None; | |
9fa01778 XL |
376 | } |
377 | ||
378 | Some(WherePredicate::BoundPredicate { | |
85aaf69f | 379 | ty: ty.clean(cx), |
dfeec247 | 380 | bounds: vec![GenericBound::Outlives(lt.clean(cx).expect("failed to clean lifetimes"))], |
136023e0 | 381 | bound_params: Vec::new(), |
9fa01778 | 382 | }) |
85aaf69f SL |
383 | } |
384 | } | |
385 | ||
3dfed10e | 386 | impl<'tcx> Clean<WherePredicate> for ty::ProjectionPredicate<'tcx> { |
6a06907d | 387 | fn clean(&self, cx: &mut DocContext<'_>) -> WherePredicate { |
3dfed10e | 388 | let ty::ProjectionPredicate { projection_ty, ty } = self; |
ba9703b0 | 389 | WherePredicate::EqPredicate { lhs: projection_ty.clean(cx), rhs: ty.clean(cx) } |
85aaf69f SL |
390 | } |
391 | } | |
392 | ||
393 | impl<'tcx> Clean<Type> for ty::ProjectionTy<'tcx> { | |
6a06907d | 394 | fn clean(&self, cx: &mut DocContext<'_>) -> Type { |
dfeec247 XL |
395 | let lifted = self.lift_to_tcx(cx.tcx).unwrap(); |
396 | let trait_ = match lifted.trait_ref(cx.tcx).clean(cx) { | |
8faf50e0 XL |
397 | GenericBound::TraitBound(t, _) => t.trait_, |
398 | GenericBound::Outlives(_) => panic!("cleaning a trait got a lifetime"), | |
85aaf69f | 399 | }; |
17df50a5 | 400 | let self_type = self.self_ty().clean(cx); |
85aaf69f | 401 | Type::QPath { |
fc512014 | 402 | name: cx.tcx.associated_item(self.item_def_id).ident.name, |
17df50a5 XL |
403 | self_def_id: self_type.def_id(), |
404 | self_type: box self_type, | |
dfeec247 | 405 | trait_: box trait_, |
85aaf69f SL |
406 | } |
407 | } | |
408 | } | |
409 | ||
532ac7d7 | 410 | impl Clean<GenericParamDef> for ty::GenericParamDef { |
6a06907d | 411 | fn clean(&self, cx: &mut DocContext<'_>) -> GenericParamDef { |
8faf50e0 | 412 | let (name, kind) = match self.kind { |
fc512014 | 413 | ty::GenericParamDefKind::Lifetime => (self.name, GenericParamDefKind::Lifetime), |
e1599b0c | 414 | ty::GenericParamDefKind::Type { has_default, synthetic, .. } => { |
136023e0 XL |
415 | let default = if has_default { |
416 | let mut default = cx.tcx.type_of(self.def_id).clean(cx); | |
417 | ||
418 | // We need to reassign the `self_def_id`, if there's a parent (which is the | |
419 | // `Self` type), so we can properly render `<Self as X>` casts, because the | |
420 | // information about which type `Self` is, is only present here, but not in | |
421 | // the cleaning process of the type itself. To resolve this and have the | |
422 | // `self_def_id` set, we override it here. | |
423 | // See https://github.com/rust-lang/rust/issues/85454 | |
424 | if let QPath { ref mut self_def_id, .. } = default { | |
425 | *self_def_id = cx.tcx.parent(self.def_id); | |
426 | } | |
427 | ||
428 | Some(default) | |
429 | } else { | |
430 | None | |
431 | }; | |
dfeec247 | 432 | ( |
fc512014 | 433 | self.name, |
dfeec247 XL |
434 | GenericParamDefKind::Type { |
435 | did: self.def_id, | |
436 | bounds: vec![], // These are filled in from the where-clauses. | |
437 | default, | |
438 | synthetic, | |
439 | }, | |
440 | ) | |
8faf50e0 | 441 | } |
17df50a5 | 442 | ty::GenericParamDefKind::Const { has_default, .. } => ( |
fc512014 | 443 | self.name, |
dfeec247 | 444 | GenericParamDefKind::Const { |
532ac7d7 XL |
445 | did: self.def_id, |
446 | ty: cx.tcx.type_of(self.def_id).clean(cx), | |
17df50a5 XL |
447 | default: match has_default { |
448 | true => Some(cx.tcx.const_param_default(self.def_id).to_string()), | |
449 | false => None, | |
450 | }, | |
dfeec247 XL |
451 | }, |
452 | ), | |
8faf50e0 XL |
453 | }; |
454 | ||
dfeec247 | 455 | GenericParamDef { name, kind } |
0531ce1d XL |
456 | } |
457 | } | |
458 | ||
dfeec247 | 459 | impl Clean<GenericParamDef> for hir::GenericParam<'_> { |
6a06907d | 460 | fn clean(&self, cx: &mut DocContext<'_>) -> GenericParamDef { |
8faf50e0 XL |
461 | let (name, kind) = match self.kind { |
462 | hir::GenericParamKind::Lifetime { .. } => { | |
74b04a01 | 463 | let name = if !self.bounds.is_empty() { |
8faf50e0 XL |
464 | let mut bounds = self.bounds.iter().map(|bound| match bound { |
465 | hir::GenericBound::Outlives(lt) => lt, | |
466 | _ => panic!(), | |
467 | }); | |
b7449926 | 468 | let name = bounds.next().expect("no more bounds").name.ident(); |
8faf50e0 XL |
469 | let mut s = format!("{}: {}", self.name.ident(), name); |
470 | for bound in bounds { | |
471 | s.push_str(&format!(" + {}", bound.name.ident())); | |
472 | } | |
fc512014 | 473 | Symbol::intern(&s) |
8faf50e0 | 474 | } else { |
fc512014 | 475 | self.name.ident().name |
8faf50e0 XL |
476 | }; |
477 | (name, GenericParamDefKind::Lifetime) | |
478 | } | |
dfeec247 | 479 | hir::GenericParamKind::Type { ref default, synthetic } => ( |
fc512014 | 480 | self.name.ident().name, |
dfeec247 | 481 | GenericParamDefKind::Type { |
f9f354fc | 482 | did: cx.tcx.hir().local_def_id(self.hir_id).to_def_id(), |
8faf50e0 XL |
483 | bounds: self.bounds.clean(cx), |
484 | default: default.clean(cx), | |
e74abb32 | 485 | synthetic, |
dfeec247 XL |
486 | }, |
487 | ), | |
17df50a5 | 488 | hir::GenericParamKind::Const { ref ty, default } => ( |
fc512014 | 489 | self.name.ident().name, |
dfeec247 | 490 | GenericParamDefKind::Const { |
f9f354fc | 491 | did: cx.tcx.hir().local_def_id(self.hir_id).to_def_id(), |
9fa01778 | 492 | ty: ty.clean(cx), |
17df50a5 XL |
493 | default: default.map(|ct| { |
494 | let def_id = cx.tcx.hir().local_def_id(ct.hir_id); | |
495 | ty::Const::from_anon_const(cx.tcx, def_id).to_string() | |
496 | }), | |
dfeec247 XL |
497 | }, |
498 | ), | |
8faf50e0 XL |
499 | }; |
500 | ||
dfeec247 | 501 | GenericParamDef { name, kind } |
ff7c6d11 XL |
502 | } |
503 | } | |
504 | ||
dfeec247 | 505 | impl Clean<Generics> for hir::Generics<'_> { |
6a06907d | 506 | fn clean(&self, cx: &mut DocContext<'_>) -> Generics { |
94b46f34 XL |
507 | // Synthetic type-parameters are inserted after normal ones. |
508 | // In order for normal parameters to be able to refer to synthetic ones, | |
509 | // scans them first. | |
dfeec247 | 510 | fn is_impl_trait(param: &hir::GenericParam<'_>) -> bool { |
8faf50e0 XL |
511 | match param.kind { |
512 | hir::GenericParamKind::Type { synthetic, .. } => { | |
513 | synthetic == Some(hir::SyntheticTyParamKind::ImplTrait) | |
514 | } | |
515 | _ => false, | |
94b46f34 XL |
516 | } |
517 | } | |
fc512014 XL |
518 | /// This can happen for `async fn`, e.g. `async fn f<'_>(&'_ self)`. |
519 | /// | |
520 | /// See [`lifetime_to_generic_param`] in [`rustc_ast_lowering`] for more information. | |
521 | /// | |
522 | /// [`lifetime_to_generic_param`]: rustc_ast_lowering::LoweringContext::lifetime_to_generic_param | |
523 | fn is_elided_lifetime(param: &hir::GenericParam<'_>) -> bool { | |
5869c6ff XL |
524 | matches!( |
525 | param.kind, | |
526 | hir::GenericParamKind::Lifetime { kind: hir::LifetimeParamKind::Elided } | |
527 | ) | |
fc512014 XL |
528 | } |
529 | ||
dfeec247 XL |
530 | let impl_trait_params = self |
531 | .params | |
94b46f34 | 532 | .iter() |
8faf50e0 XL |
533 | .filter(|param| is_impl_trait(param)) |
534 | .map(|param| { | |
535 | let param: GenericParamDef = param.clean(cx); | |
536 | match param.kind { | |
537 | GenericParamDefKind::Lifetime => unreachable!(), | |
538 | GenericParamDefKind::Type { did, ref bounds, .. } => { | |
6a06907d | 539 | cx.impl_trait_bounds.insert(did.into(), bounds.clone()); |
8faf50e0 | 540 | } |
9fa01778 | 541 | GenericParamDefKind::Const { .. } => unreachable!(), |
94b46f34 | 542 | } |
8faf50e0 | 543 | param |
94b46f34 XL |
544 | }) |
545 | .collect::<Vec<_>>(); | |
546 | ||
0531ce1d | 547 | let mut params = Vec::with_capacity(self.params.len()); |
fc512014 | 548 | for p in self.params.iter().filter(|p| !is_impl_trait(p) && !is_elided_lifetime(p)) { |
0531ce1d | 549 | let p = p.clean(cx); |
0531ce1d XL |
550 | params.push(p); |
551 | } | |
94b46f34 XL |
552 | params.extend(impl_trait_params); |
553 | ||
dfeec247 XL |
554 | let mut generics = |
555 | Generics { params, where_predicates: self.where_clause.predicates.clean(cx) }; | |
ff7c6d11 XL |
556 | |
557 | // Some duplicates are generated for ?Sized bounds between type params and where | |
558 | // predicates. The point in here is to move the bounds definitions from type params | |
559 | // to where predicates when such cases occur. | |
8faf50e0 | 560 | for where_pred in &mut generics.where_predicates { |
ff7c6d11 | 561 | match *where_pred { |
136023e0 XL |
562 | WherePredicate::BoundPredicate { |
563 | ty: Generic(ref name), ref mut bounds, .. | |
564 | } => { | |
ff7c6d11 | 565 | if bounds.is_empty() { |
8faf50e0 XL |
566 | for param in &mut generics.params { |
567 | match param.kind { | |
568 | GenericParamDefKind::Lifetime => {} | |
569 | GenericParamDefKind::Type { bounds: ref mut ty_bounds, .. } => { | |
570 | if ¶m.name == name { | |
571 | mem::swap(bounds, ty_bounds); | |
dfeec247 | 572 | break; |
8faf50e0 | 573 | } |
ff7c6d11 | 574 | } |
9fa01778 | 575 | GenericParamDefKind::Const { .. } => {} |
ff7c6d11 XL |
576 | } |
577 | } | |
578 | } | |
579 | } | |
580 | _ => continue, | |
581 | } | |
1a4d82fc | 582 | } |
8faf50e0 | 583 | generics |
1a4d82fc JJ |
584 | } |
585 | } | |
586 | ||
e74abb32 | 587 | impl<'a, 'tcx> Clean<Generics> for (&'a ty::Generics, ty::GenericPredicates<'tcx>) { |
6a06907d | 588 | fn clean(&self, cx: &mut DocContext<'_>) -> Generics { |
85aaf69f | 589 | use self::WherePredicate as WP; |
e1599b0c | 590 | use std::collections::BTreeMap; |
85aaf69f | 591 | |
9e0c209e | 592 | let (gens, preds) = *self; |
85aaf69f | 593 | |
e1599b0c XL |
594 | // Don't populate `cx.impl_trait_bounds` before `clean`ning `where` clauses, |
595 | // since `Clean for ty::Predicate` would consume them. | |
596 | let mut impl_trait = BTreeMap::<ImplTraitParam, Vec<GenericBound>>::default(); | |
597 | ||
9346a6ac AL |
598 | // Bounds in the type_params and lifetimes fields are repeated in the |
599 | // predicates field (see rustc_typeck::collect::ty_generics), so remove | |
600 | // them. | |
3dfed10e | 601 | let stripped_params = gens |
dfeec247 XL |
602 | .params |
603 | .iter() | |
e1599b0c | 604 | .filter_map(|param| match param.kind { |
3dfed10e | 605 | ty::GenericParamDefKind::Lifetime => Some(param.clean(cx)), |
e1599b0c | 606 | ty::GenericParamDefKind::Type { synthetic, .. } => { |
e74abb32 | 607 | if param.name == kw::SelfUpper { |
e1599b0c XL |
608 | assert_eq!(param.index, 0); |
609 | return None; | |
610 | } | |
611 | if synthetic == Some(hir::SyntheticTyParamKind::ImplTrait) { | |
612 | impl_trait.insert(param.index.into(), vec![]); | |
613 | return None; | |
614 | } | |
615 | Some(param.clean(cx)) | |
616 | } | |
3dfed10e | 617 | ty::GenericParamDefKind::Const { .. } => Some(param.clean(cx)), |
dfeec247 XL |
618 | }) |
619 | .collect::<Vec<GenericParamDef>>(); | |
e1599b0c XL |
620 | |
621 | // param index -> [(DefId of trait, associated type name, type)] | |
fc512014 | 622 | let mut impl_trait_proj = FxHashMap::<u32, Vec<(DefId, Symbol, Ty<'tcx>)>>::default(); |
e1599b0c | 623 | |
dfeec247 XL |
624 | let where_predicates = preds |
625 | .predicates | |
626 | .iter() | |
e1599b0c XL |
627 | .flat_map(|(p, _)| { |
628 | let mut projection = None; | |
629 | let param_idx = (|| { | |
5869c6ff | 630 | let bound_p = p.kind(); |
fc512014 | 631 | match bound_p.skip_binder() { |
5869c6ff | 632 | ty::PredicateKind::Trait(pred, _constness) => { |
1b1a35ee | 633 | if let ty::Param(param) = pred.self_ty().kind() { |
3dfed10e XL |
634 | return Some(param.index); |
635 | } | |
e1599b0c | 636 | } |
5869c6ff | 637 | ty::PredicateKind::TypeOutlives(ty::OutlivesPredicate(ty, _reg)) => { |
1b1a35ee | 638 | if let ty::Param(param) = ty.kind() { |
3dfed10e XL |
639 | return Some(param.index); |
640 | } | |
e1599b0c | 641 | } |
5869c6ff | 642 | ty::PredicateKind::Projection(p) => { |
1b1a35ee | 643 | if let ty::Param(param) = p.projection_ty.self_ty().kind() { |
fc512014 | 644 | projection = Some(bound_p.rebind(p)); |
3dfed10e XL |
645 | return Some(param.index); |
646 | } | |
e1599b0c | 647 | } |
3dfed10e | 648 | _ => (), |
e1599b0c XL |
649 | } |
650 | ||
651 | None | |
652 | })(); | |
653 | ||
654 | if let Some(param_idx) = param_idx { | |
655 | if let Some(b) = impl_trait.get_mut(¶m_idx.into()) { | |
656 | let p = p.clean(cx)?; | |
657 | ||
658 | b.extend( | |
659 | p.get_bounds() | |
660 | .into_iter() | |
661 | .flatten() | |
662 | .cloned() | |
dfeec247 | 663 | .filter(|b| !b.is_sized_bound(cx)), |
e1599b0c XL |
664 | ); |
665 | ||
666 | let proj = projection | |
667 | .map(|p| (p.skip_binder().projection_ty.clean(cx), p.skip_binder().ty)); | |
668 | if let Some(((_, trait_did, name), rhs)) = | |
669 | proj.as_ref().and_then(|(lhs, rhs)| Some((lhs.projection()?, rhs))) | |
670 | { | |
17df50a5 XL |
671 | impl_trait_proj.entry(param_idx).or_default().push(( |
672 | trait_did.into(), | |
673 | name, | |
674 | rhs, | |
675 | )); | |
e1599b0c XL |
676 | } |
677 | ||
678 | return None; | |
679 | } | |
680 | } | |
681 | ||
682 | Some(p) | |
683 | }) | |
684 | .collect::<Vec<_>>(); | |
685 | ||
686 | for (param, mut bounds) in impl_trait { | |
687 | // Move trait bounds to the front. | |
5869c6ff | 688 | bounds.sort_by_key(|b| !matches!(b, GenericBound::TraitBound(..))); |
e1599b0c XL |
689 | |
690 | if let crate::core::ImplTraitParam::ParamIndex(idx) = param { | |
691 | if let Some(proj) = impl_trait_proj.remove(&idx) { | |
692 | for (trait_did, name, rhs) in proj { | |
6a06907d XL |
693 | let rhs = rhs.clean(cx); |
694 | simplify::merge_bounds(cx, &mut bounds, trait_did, name, &rhs); | |
e1599b0c | 695 | } |
94b46f34 | 696 | } |
e1599b0c XL |
697 | } else { |
698 | unreachable!(); | |
9e0c209e | 699 | } |
85aaf69f | 700 | |
6a06907d | 701 | cx.impl_trait_bounds.insert(param, bounds); |
e1599b0c XL |
702 | } |
703 | ||
704 | // Now that `cx.impl_trait_bounds` is populated, we can process | |
705 | // remaining predicates which could contain `impl Trait`. | |
dfeec247 XL |
706 | let mut where_predicates = |
707 | where_predicates.into_iter().flat_map(|p| p.clean(cx)).collect::<Vec<_>>(); | |
85aaf69f | 708 | |
1b1a35ee | 709 | // Type parameters have a Sized bound by default unless removed with |
ff7c6d11 | 710 | // ?Sized. Scan through the predicates and mark any type parameter with |
9346a6ac AL |
711 | // a Sized bound, removing the bounds as we find them. |
712 | // | |
713 | // Note that associated types also have a sized bound by default, but we | |
d9579d0f | 714 | // don't actually know the set of associated types right here so that's |
9346a6ac | 715 | // handled in cleaning associated types |
0bf4aa26 | 716 | let mut sized_params = FxHashSet::default(); |
dfeec247 | 717 | where_predicates.retain(|pred| match *pred { |
136023e0 | 718 | WP::BoundPredicate { ty: Generic(ref g), ref bounds, .. } => { |
dfeec247 | 719 | if bounds.iter().any(|b| b.is_sized_bound(cx)) { |
5869c6ff | 720 | sized_params.insert(*g); |
dfeec247 XL |
721 | false |
722 | } else { | |
723 | true | |
85aaf69f SL |
724 | } |
725 | } | |
dfeec247 | 726 | _ => true, |
9346a6ac | 727 | }); |
85aaf69f | 728 | |
9346a6ac AL |
729 | // Run through the type parameters again and insert a ?Sized |
730 | // unbound for any we didn't find to be Sized. | |
3dfed10e XL |
731 | for tp in &stripped_params { |
732 | if matches!(tp.kind, types::GenericParamDefKind::Type { .. }) | |
733 | && !sized_params.contains(&tp.name) | |
734 | { | |
85aaf69f | 735 | where_predicates.push(WP::BoundPredicate { |
5869c6ff | 736 | ty: Type::Generic(tp.name), |
8faf50e0 | 737 | bounds: vec![GenericBound::maybe_sized(cx)], |
136023e0 | 738 | bound_params: Vec::new(), |
85aaf69f SL |
739 | }) |
740 | } | |
741 | } | |
742 | ||
743 | // It would be nice to collect all of the bounds on a type and recombine | |
0731742a | 744 | // them if possible, to avoid e.g., `where T: Foo, T: Bar, T: Sized, T: 'a` |
85aaf69f SL |
745 | // and instead see `where T: Foo + Bar + Sized + 'a` |
746 | ||
1a4d82fc | 747 | Generics { |
3dfed10e | 748 | params: stripped_params, |
9346a6ac | 749 | where_predicates: simplify::where_clauses(cx, where_predicates), |
1a4d82fc JJ |
750 | } |
751 | } | |
752 | } | |
753 | ||
fc512014 XL |
754 | fn clean_fn_or_proc_macro( |
755 | item: &hir::Item<'_>, | |
756 | sig: &'a hir::FnSig<'a>, | |
757 | generics: &'a hir::Generics<'a>, | |
758 | body_id: hir::BodyId, | |
759 | name: &mut Symbol, | |
6a06907d | 760 | cx: &mut DocContext<'_>, |
fc512014 | 761 | ) -> ItemKind { |
6a06907d XL |
762 | let attrs = cx.tcx.hir().attrs(item.hir_id()); |
763 | let macro_kind = attrs.iter().find_map(|a| { | |
fc512014 XL |
764 | if a.has_name(sym::proc_macro) { |
765 | Some(MacroKind::Bang) | |
766 | } else if a.has_name(sym::proc_macro_derive) { | |
767 | Some(MacroKind::Derive) | |
768 | } else if a.has_name(sym::proc_macro_attribute) { | |
769 | Some(MacroKind::Attr) | |
770 | } else { | |
771 | None | |
772 | } | |
773 | }); | |
774 | match macro_kind { | |
775 | Some(kind) => { | |
776 | if kind == MacroKind::Derive { | |
6a06907d | 777 | *name = attrs |
fc512014 XL |
778 | .lists(sym::proc_macro_derive) |
779 | .find_map(|mi| mi.ident()) | |
780 | .expect("proc-macro derives require a name") | |
781 | .name; | |
782 | } | |
783 | ||
784 | let mut helpers = Vec::new(); | |
6a06907d | 785 | for mi in attrs.lists(sym::proc_macro_derive) { |
fc512014 XL |
786 | if !mi.has_name(sym::attributes) { |
787 | continue; | |
788 | } | |
789 | ||
790 | if let Some(list) = mi.meta_item_list() { | |
791 | for inner_mi in list { | |
792 | if let Some(ident) = inner_mi.ident() { | |
793 | helpers.push(ident.name); | |
794 | } | |
795 | } | |
796 | } | |
797 | } | |
798 | ProcMacroItem(ProcMacro { kind, helpers }) | |
799 | } | |
800 | None => { | |
801 | let mut func = (sig, generics, body_id).clean(cx); | |
6a06907d | 802 | let def_id = item.def_id.to_def_id(); |
fc512014 XL |
803 | func.header.constness = |
804 | if is_const_fn(cx.tcx, def_id) && is_unstable_const_fn(cx.tcx, def_id).is_none() { | |
805 | hir::Constness::Const | |
806 | } else { | |
807 | hir::Constness::NotConst | |
808 | }; | |
809 | FunctionItem(func) | |
810 | } | |
1a4d82fc JJ |
811 | } |
812 | } | |
813 | ||
fc512014 | 814 | impl<'a> Clean<Function> for (&'a hir::FnSig<'a>, &'a hir::Generics<'a>, hir::BodyId) { |
6a06907d | 815 | fn clean(&self, cx: &mut DocContext<'_>) -> Function { |
dfeec247 | 816 | let (generics, decl) = |
6a06907d XL |
817 | enter_impl_trait(cx, |cx| (self.1.clean(cx), (&*self.0.decl, self.2).clean(cx))); |
818 | Function { decl, generics, header: self.0.header } | |
60c5eb7d | 819 | } |
1a4d82fc JJ |
820 | } |
821 | ||
f9f354fc | 822 | impl<'a> Clean<Arguments> for (&'a [hir::Ty<'a>], &'a [Ident]) { |
6a06907d | 823 | fn clean(&self, cx: &mut DocContext<'_>) -> Arguments { |
32a655c1 | 824 | Arguments { |
dfeec247 XL |
825 | values: self |
826 | .0 | |
827 | .iter() | |
828 | .enumerate() | |
829 | .map(|(i, ty)| { | |
5869c6ff | 830 | let mut name = self.1.get(i).map_or(kw::Empty, |ident| ident.name); |
dfeec247 | 831 | if name.is_empty() { |
fc512014 | 832 | name = kw::Underscore; |
dfeec247 XL |
833 | } |
834 | Argument { name, type_: ty.clean(cx) } | |
835 | }) | |
836 | .collect(), | |
32a655c1 SL |
837 | } |
838 | } | |
839 | } | |
840 | ||
dfeec247 | 841 | impl<'a> Clean<Arguments> for (&'a [hir::Ty<'a>], hir::BodyId) { |
6a06907d | 842 | fn clean(&self, cx: &mut DocContext<'_>) -> Arguments { |
0731742a | 843 | let body = cx.tcx.hir().body(self.1); |
32a655c1 SL |
844 | |
845 | Arguments { | |
dfeec247 XL |
846 | values: self |
847 | .0 | |
848 | .iter() | |
849 | .enumerate() | |
850 | .map(|(i, ty)| Argument { | |
e1599b0c | 851 | name: name_from_pat(&body.params[i].pat), |
32a655c1 | 852 | type_: ty.clean(cx), |
dfeec247 XL |
853 | }) |
854 | .collect(), | |
32a655c1 SL |
855 | } |
856 | } | |
857 | } | |
858 | ||
dfeec247 XL |
859 | impl<'a, A: Copy> Clean<FnDecl> for (&'a hir::FnDecl<'a>, A) |
860 | where | |
861 | (&'a [hir::Ty<'a>], A): Clean<Arguments>, | |
32a655c1 | 862 | { |
6a06907d | 863 | fn clean(&self, cx: &mut DocContext<'_>) -> FnDecl { |
1a4d82fc | 864 | FnDecl { |
6a06907d | 865 | inputs: (self.0.inputs, self.1).clean(cx), |
32a655c1 | 866 | output: self.0.output.clean(cx), |
e74abb32 | 867 | c_variadic: self.0.c_variadic, |
1a4d82fc JJ |
868 | } |
869 | } | |
870 | } | |
871 | ||
dc9dc135 | 872 | impl<'tcx> Clean<FnDecl> for (DefId, ty::PolyFnSig<'tcx>) { |
6a06907d | 873 | fn clean(&self, cx: &mut DocContext<'_>) -> FnDecl { |
1a4d82fc | 874 | let (did, sig) = *self; |
f9f354fc | 875 | let mut names = if did.is_local() { &[] } else { cx.tcx.fn_arg_names(did) }.iter(); |
0531ce1d | 876 | |
1a4d82fc | 877 | FnDecl { |
476ff2be | 878 | output: Return(sig.skip_binder().output().clean(cx)), |
e74abb32 | 879 | c_variadic: sig.skip_binder().c_variadic, |
1a4d82fc | 880 | inputs: Arguments { |
dfeec247 XL |
881 | values: sig |
882 | .skip_binder() | |
883 | .inputs() | |
884 | .iter() | |
885 | .map(|t| Argument { | |
1a4d82fc | 886 | type_: t.clean(cx), |
5869c6ff | 887 | name: names.next().map_or(kw::Empty, |i| i.name), |
dfeec247 XL |
888 | }) |
889 | .collect(), | |
1a4d82fc JJ |
890 | }, |
891 | } | |
892 | } | |
893 | } | |
894 | ||
74b04a01 | 895 | impl Clean<FnRetTy> for hir::FnRetTy<'_> { |
6a06907d | 896 | fn clean(&self, cx: &mut DocContext<'_>) -> FnRetTy { |
1a4d82fc | 897 | match *self { |
dfeec247 XL |
898 | Self::Return(ref typ) => Return(typ.clean(cx)), |
899 | Self::DefaultReturn(..) => DefaultReturn, | |
1a4d82fc JJ |
900 | } |
901 | } | |
902 | } | |
903 | ||
2c00a5a8 | 904 | impl Clean<bool> for hir::IsAuto { |
6a06907d | 905 | fn clean(&self, _: &mut DocContext<'_>) -> bool { |
2c00a5a8 XL |
906 | match *self { |
907 | hir::IsAuto::Yes => true, | |
908 | hir::IsAuto::No => false, | |
909 | } | |
910 | } | |
911 | } | |
912 | ||
dfeec247 | 913 | impl Clean<Type> for hir::TraitRef<'_> { |
6a06907d XL |
914 | fn clean(&self, cx: &mut DocContext<'_>) -> Type { |
915 | let path = self.path.clean(cx); | |
916 | resolve_type(cx, path, self.hir_ref_id) | |
1a4d82fc JJ |
917 | } |
918 | } | |
919 | ||
dfeec247 | 920 | impl Clean<PolyTrait> for hir::PolyTraitRef<'_> { |
6a06907d | 921 | fn clean(&self, cx: &mut DocContext<'_>) -> PolyTrait { |
1a4d82fc JJ |
922 | PolyTrait { |
923 | trait_: self.trait_ref.clean(cx), | |
dfeec247 | 924 | generic_params: self.bound_generic_params.clean(cx), |
1a4d82fc JJ |
925 | } |
926 | } | |
927 | } | |
928 | ||
dfeec247 | 929 | impl Clean<Item> for hir::TraitItem<'_> { |
6a06907d XL |
930 | fn clean(&self, cx: &mut DocContext<'_>) -> Item { |
931 | let local_did = self.def_id.to_def_id(); | |
932 | cx.with_param_env(local_did, |cx| { | |
fc512014 XL |
933 | let inner = match self.kind { |
934 | hir::TraitItemKind::Const(ref ty, default) => { | |
6a06907d | 935 | AssocConstItem(ty.clean(cx), default.map(|e| print_const_expr(cx.tcx, e))) |
3dfed10e | 936 | } |
fc512014 XL |
937 | hir::TraitItemKind::Fn(ref sig, hir::TraitFn::Provided(body)) => { |
938 | let mut m = (sig, &self.generics, body).clean(cx); | |
939 | if m.header.constness == hir::Constness::Const | |
940 | && is_unstable_const_fn(cx.tcx, local_did).is_some() | |
941 | { | |
942 | m.header.constness = hir::Constness::NotConst; | |
943 | } | |
944 | MethodItem(m, None) | |
3dfed10e | 945 | } |
fc512014 | 946 | hir::TraitItemKind::Fn(ref sig, hir::TraitFn::Required(ref names)) => { |
6a06907d | 947 | let (generics, decl) = enter_impl_trait(cx, |cx| { |
fc512014 XL |
948 | (self.generics.clean(cx), (&*sig.decl, &names[..]).clean(cx)) |
949 | }); | |
6a06907d | 950 | let mut t = Function { header: sig.header, decl, generics }; |
fc512014 XL |
951 | if t.header.constness == hir::Constness::Const |
952 | && is_unstable_const_fn(cx.tcx, local_did).is_some() | |
953 | { | |
954 | t.header.constness = hir::Constness::NotConst; | |
955 | } | |
956 | TyMethodItem(t) | |
957 | } | |
958 | hir::TraitItemKind::Type(ref bounds, ref default) => { | |
959 | AssocTypeItem(bounds.clean(cx), default.clean(cx)) | |
960 | } | |
961 | }; | |
962 | let what_rustc_thinks = | |
963 | Item::from_def_id_and_parts(local_did, Some(self.ident.name), inner, cx); | |
964 | // Trait items always inherit the trait's visibility -- we don't want to show `pub`. | |
965 | Item { visibility: Inherited, ..what_rustc_thinks } | |
966 | }) | |
1a4d82fc JJ |
967 | } |
968 | } | |
969 | ||
dfeec247 | 970 | impl Clean<Item> for hir::ImplItem<'_> { |
6a06907d XL |
971 | fn clean(&self, cx: &mut DocContext<'_>) -> Item { |
972 | let local_did = self.def_id.to_def_id(); | |
973 | cx.with_param_env(local_did, |cx| { | |
fc512014 XL |
974 | let inner = match self.kind { |
975 | hir::ImplItemKind::Const(ref ty, expr) => { | |
6a06907d | 976 | AssocConstItem(ty.clean(cx), Some(print_const_expr(cx.tcx, expr))) |
3dfed10e | 977 | } |
fc512014 XL |
978 | hir::ImplItemKind::Fn(ref sig, body) => { |
979 | let mut m = (sig, &self.generics, body).clean(cx); | |
980 | if m.header.constness == hir::Constness::Const | |
981 | && is_unstable_const_fn(cx.tcx, local_did).is_some() | |
982 | { | |
983 | m.header.constness = hir::Constness::NotConst; | |
984 | } | |
985 | MethodItem(m, Some(self.defaultness)) | |
986 | } | |
5869c6ff XL |
987 | hir::ImplItemKind::TyAlias(ref hir_ty) => { |
988 | let type_ = hir_ty.clean(cx); | |
989 | let item_type = hir_ty_to_ty(cx.tcx, hir_ty).clean(cx); | |
990 | TypedefItem( | |
991 | Typedef { | |
992 | type_, | |
993 | generics: Generics::default(), | |
994 | item_type: Some(item_type), | |
995 | }, | |
996 | true, | |
997 | ) | |
fc512014 XL |
998 | } |
999 | }; | |
1000 | ||
1001 | let what_rustc_thinks = | |
1002 | Item::from_def_id_and_parts(local_did, Some(self.ident.name), inner, cx); | |
6a06907d | 1003 | let parent_item = cx.tcx.hir().expect_item(cx.tcx.hir().get_parent_item(self.hir_id())); |
5869c6ff XL |
1004 | if let hir::ItemKind::Impl(impl_) = &parent_item.kind { |
1005 | if impl_.of_trait.is_some() { | |
fc512014 XL |
1006 | // Trait impl items always inherit the impl's visibility -- |
1007 | // we don't want to show `pub`. | |
1008 | Item { visibility: Inherited, ..what_rustc_thinks } | |
1009 | } else { | |
1010 | what_rustc_thinks | |
1011 | } | |
1012 | } else { | |
1013 | panic!("found impl item with non-impl parent {:?}", parent_item); | |
dfeec247 | 1014 | } |
fc512014 | 1015 | }) |
1a4d82fc JJ |
1016 | } |
1017 | } | |
1018 | ||
dc9dc135 | 1019 | impl Clean<Item> for ty::AssocItem { |
6a06907d XL |
1020 | fn clean(&self, cx: &mut DocContext<'_>) -> Item { |
1021 | let tcx = cx.tcx; | |
fc512014 | 1022 | let kind = match self.kind { |
dc9dc135 | 1023 | ty::AssocKind::Const => { |
6a06907d | 1024 | let ty = tcx.type_of(self.def_id); |
ff7c6d11 | 1025 | let default = if self.defaultness.has_value() { |
cdc7bbd5 | 1026 | Some(inline::print_inlined_const(tcx, self.def_id)) |
ff7c6d11 XL |
1027 | } else { |
1028 | None | |
1029 | }; | |
dc9dc135 | 1030 | AssocConstItem(ty.clean(cx), default) |
a7813a04 | 1031 | } |
ba9703b0 | 1032 | ty::AssocKind::Fn => { |
dfeec247 | 1033 | let generics = |
6a06907d | 1034 | (tcx.generics_of(self.def_id), tcx.explicit_predicates_of(self.def_id)) |
dfeec247 | 1035 | .clean(cx); |
6a06907d | 1036 | let sig = tcx.fn_sig(self.def_id); |
8bb4bdeb | 1037 | let mut decl = (self.def_id, sig).clean(cx); |
476ff2be | 1038 | |
ba9703b0 | 1039 | if self.fn_has_self_parameter { |
476ff2be | 1040 | let self_ty = match self.container { |
6a06907d XL |
1041 | ty::ImplContainer(def_id) => tcx.type_of(def_id), |
1042 | ty::TraitContainer(_) => tcx.types.self_param, | |
476ff2be | 1043 | }; |
f035d41b | 1044 | let self_arg_ty = sig.input(0).skip_binder(); |
476ff2be | 1045 | if self_arg_ty == self_ty { |
fc512014 | 1046 | decl.inputs.values[0].type_ = Generic(kw::SelfUpper); |
1b1a35ee | 1047 | } else if let ty::Ref(_, ty, _) = *self_arg_ty.kind() { |
94b46f34 | 1048 | if ty == self_ty { |
476ff2be | 1049 | match decl.inputs.values[0].type_ { |
dfeec247 | 1050 | BorrowedRef { ref mut type_, .. } => { |
fc512014 | 1051 | **type_ = Generic(kw::SelfUpper) |
32a655c1 | 1052 | } |
476ff2be SL |
1053 | _ => unreachable!(), |
1054 | } | |
1055 | } | |
1056 | } | |
1057 | } | |
1058 | ||
1059 | let provided = match self.container { | |
ff7c6d11 | 1060 | ty::ImplContainer(_) => true, |
dfeec247 | 1061 | ty::TraitContainer(_) => self.defaultness.has_value(), |
476ff2be SL |
1062 | }; |
1063 | if provided { | |
cdc7bbd5 | 1064 | let constness = if tcx.is_const_fn_raw(self.def_id) { |
ff7c6d11 XL |
1065 | hir::Constness::Const |
1066 | } else { | |
1067 | hir::Constness::NotConst | |
1068 | }; | |
6a06907d | 1069 | let asyncness = tcx.asyncness(self.def_id); |
532ac7d7 XL |
1070 | let defaultness = match self.container { |
1071 | ty::ImplContainer(_) => Some(self.defaultness), | |
1072 | ty::TraitContainer(_) => None, | |
1073 | }; | |
fc512014 XL |
1074 | MethodItem( |
1075 | Function { | |
1076 | generics, | |
1077 | decl, | |
1078 | header: hir::FnHeader { | |
1079 | unsafety: sig.unsafety(), | |
1080 | abi: sig.abi(), | |
1081 | constness, | |
1082 | asyncness, | |
1083 | }, | |
532ac7d7 XL |
1084 | }, |
1085 | defaultness, | |
fc512014 | 1086 | ) |
476ff2be | 1087 | } else { |
fc512014 | 1088 | TyMethodItem(Function { |
3b2f2976 XL |
1089 | generics, |
1090 | decl, | |
8faf50e0 XL |
1091 | header: hir::FnHeader { |
1092 | unsafety: sig.unsafety(), | |
1093 | abi: sig.abi(), | |
1094 | constness: hir::Constness::NotConst, | |
1095 | asyncness: hir::IsAsync::NotAsync, | |
532ac7d7 | 1096 | }, |
476ff2be | 1097 | }) |
a7813a04 XL |
1098 | } |
1099 | } | |
dc9dc135 | 1100 | ty::AssocKind::Type => { |
fc512014 | 1101 | let my_name = self.ident.name; |
476ff2be | 1102 | |
29967ef6 | 1103 | if let ty::TraitContainer(_) = self.container { |
6a06907d | 1104 | let bounds = tcx.explicit_item_bounds(self.def_id); |
29967ef6 | 1105 | let predicates = ty::GenericPredicates { parent: None, predicates: bounds }; |
6a06907d | 1106 | let generics = (tcx.generics_of(self.def_id), predicates).clean(cx); |
dfeec247 XL |
1107 | let mut bounds = generics |
1108 | .where_predicates | |
1109 | .iter() | |
1110 | .filter_map(|pred| { | |
1111 | let (name, self_type, trait_, bounds) = match *pred { | |
1112 | WherePredicate::BoundPredicate { | |
17df50a5 | 1113 | ty: QPath { ref name, ref self_type, ref trait_, .. }, |
dfeec247 | 1114 | ref bounds, |
136023e0 | 1115 | .. |
dfeec247 XL |
1116 | } => (name, self_type, trait_, bounds), |
1117 | _ => return None, | |
1118 | }; | |
1119 | if *name != my_name { | |
1120 | return None; | |
1121 | } | |
1122 | match **trait_ { | |
1123 | ResolvedPath { did, .. } if did == self.container.id() => {} | |
1124 | _ => return None, | |
1125 | } | |
1126 | match **self_type { | |
fc512014 | 1127 | Generic(ref s) if *s == kw::SelfUpper => {} |
dfeec247 XL |
1128 | _ => return None, |
1129 | } | |
1130 | Some(bounds) | |
1131 | }) | |
1132 | .flat_map(|i| i.iter().cloned()) | |
1133 | .collect::<Vec<_>>(); | |
ff7c6d11 XL |
1134 | // Our Sized/?Sized bound didn't get handled when creating the generics |
1135 | // because we didn't actually get our whole set of bounds until just now | |
1136 | // (some of them may have come from the trait). If we do have a sized | |
1137 | // bound, we remove it, and if we don't then we add the `?Sized` bound | |
1138 | // at the end. | |
1139 | match bounds.iter().position(|b| b.is_sized_bound(cx)) { | |
dfeec247 XL |
1140 | Some(i) => { |
1141 | bounds.remove(i); | |
1142 | } | |
8faf50e0 | 1143 | None => bounds.push(GenericBound::maybe_sized(cx)), |
ff7c6d11 | 1144 | } |
476ff2be | 1145 | |
ff7c6d11 | 1146 | let ty = if self.defaultness.has_value() { |
6a06907d | 1147 | Some(tcx.type_of(self.def_id)) |
ff7c6d11 XL |
1148 | } else { |
1149 | None | |
1150 | }; | |
476ff2be | 1151 | |
dc9dc135 | 1152 | AssocTypeItem(bounds, ty.clean(cx)) |
476ff2be | 1153 | } else { |
6a06907d XL |
1154 | // FIXME: when could this happen? Associated items in inherent impls? |
1155 | let type_ = tcx.type_of(self.def_id).clean(cx); | |
dfeec247 XL |
1156 | TypedefItem( |
1157 | Typedef { | |
1158 | type_, | |
1159 | generics: Generics { params: Vec::new(), where_predicates: Vec::new() }, | |
5869c6ff | 1160 | item_type: None, |
ff7c6d11 | 1161 | }, |
dfeec247 XL |
1162 | true, |
1163 | ) | |
ff7c6d11 | 1164 | } |
9346a6ac AL |
1165 | } |
1166 | }; | |
9346a6ac | 1167 | |
fc512014 XL |
1168 | Item::from_def_id_and_parts(self.def_id, Some(self.ident.name), kind, cx) |
1169 | } | |
1170 | } | |
ff7c6d11 | 1171 | |
6a06907d | 1172 | fn clean_qpath(hir_ty: &hir::Ty<'_>, cx: &mut DocContext<'_>) -> Type { |
fc512014 XL |
1173 | use rustc_hir::GenericParamCount; |
1174 | let hir::Ty { hir_id, span, ref kind } = *hir_ty; | |
1175 | let qpath = match kind { | |
1176 | hir::TyKind::Path(qpath) => qpath, | |
1177 | _ => unreachable!(), | |
1178 | }; | |
1179 | ||
1180 | match qpath { | |
1181 | hir::QPath::Resolved(None, ref path) => { | |
1182 | if let Res::Def(DefKind::TyParam, did) = path.res { | |
6a06907d | 1183 | if let Some(new_ty) = cx.ty_substs.get(&did).cloned() { |
fc512014 XL |
1184 | return new_ty; |
1185 | } | |
6a06907d | 1186 | if let Some(bounds) = cx.impl_trait_bounds.remove(&did.into()) { |
fc512014 XL |
1187 | return ImplTrait(bounds); |
1188 | } | |
1189 | } | |
1190 | ||
1191 | let mut alias = None; | |
1192 | if let Res::Def(DefKind::TyAlias, def_id) = path.res { | |
1193 | // Substitute private type aliases | |
1194 | if let Some(def_id) = def_id.as_local() { | |
1195 | let hir_id = cx.tcx.hir().local_def_id_to_hir_id(def_id); | |
6a06907d | 1196 | if !cx.cache.access_levels.is_exported(def_id.to_def_id()) { |
fc512014 XL |
1197 | alias = Some(&cx.tcx.hir().expect_item(hir_id).kind); |
1198 | } | |
1199 | } | |
1200 | }; | |
1201 | ||
1202 | if let Some(&hir::ItemKind::TyAlias(ref ty, ref generics)) = alias { | |
1203 | let provided_params = &path.segments.last().expect("segments were empty"); | |
1204 | let mut ty_substs = FxHashMap::default(); | |
1205 | let mut lt_substs = FxHashMap::default(); | |
1206 | let mut ct_substs = FxHashMap::default(); | |
5869c6ff | 1207 | let generic_args = provided_params.args(); |
fc512014 XL |
1208 | { |
1209 | let mut indices: GenericParamCount = Default::default(); | |
1210 | for param in generics.params.iter() { | |
1211 | match param.kind { | |
1212 | hir::GenericParamKind::Lifetime { .. } => { | |
1213 | let mut j = 0; | |
1214 | let lifetime = generic_args.args.iter().find_map(|arg| match arg { | |
1215 | hir::GenericArg::Lifetime(lt) => { | |
1216 | if indices.lifetimes == j { | |
1217 | return Some(lt); | |
1218 | } | |
1219 | j += 1; | |
1220 | None | |
1221 | } | |
1222 | _ => None, | |
1223 | }); | |
1224 | if let Some(lt) = lifetime.cloned() { | |
1225 | let lt_def_id = cx.tcx.hir().local_def_id(param.hir_id); | |
1226 | let cleaned = if !lt.is_elided() { | |
1227 | lt.clean(cx) | |
1228 | } else { | |
1229 | self::types::Lifetime::elided() | |
1230 | }; | |
1231 | lt_substs.insert(lt_def_id.to_def_id(), cleaned); | |
1232 | } | |
1233 | indices.lifetimes += 1; | |
1234 | } | |
1235 | hir::GenericParamKind::Type { ref default, .. } => { | |
1236 | let ty_param_def_id = cx.tcx.hir().local_def_id(param.hir_id); | |
1237 | let mut j = 0; | |
1238 | let type_ = generic_args.args.iter().find_map(|arg| match arg { | |
1239 | hir::GenericArg::Type(ty) => { | |
1240 | if indices.types == j { | |
1241 | return Some(ty); | |
1242 | } | |
1243 | j += 1; | |
1244 | None | |
1245 | } | |
1246 | _ => None, | |
1247 | }); | |
1248 | if let Some(ty) = type_ { | |
1249 | ty_substs.insert(ty_param_def_id.to_def_id(), ty.clean(cx)); | |
1250 | } else if let Some(default) = *default { | |
1251 | ty_substs | |
1252 | .insert(ty_param_def_id.to_def_id(), default.clean(cx)); | |
1253 | } | |
1254 | indices.types += 1; | |
1255 | } | |
1256 | hir::GenericParamKind::Const { .. } => { | |
1257 | let const_param_def_id = cx.tcx.hir().local_def_id(param.hir_id); | |
1258 | let mut j = 0; | |
1259 | let const_ = generic_args.args.iter().find_map(|arg| match arg { | |
1260 | hir::GenericArg::Const(ct) => { | |
1261 | if indices.consts == j { | |
1262 | return Some(ct); | |
1263 | } | |
1264 | j += 1; | |
1265 | None | |
1266 | } | |
1267 | _ => None, | |
1268 | }); | |
1269 | if let Some(ct) = const_ { | |
1270 | ct_substs.insert(const_param_def_id.to_def_id(), ct.clean(cx)); | |
1271 | } | |
5869c6ff | 1272 | // FIXME(const_generics_defaults) |
fc512014 XL |
1273 | indices.consts += 1; |
1274 | } | |
1275 | } | |
1276 | } | |
1277 | } | |
6a06907d | 1278 | return cx.enter_alias(ty_substs, lt_substs, ct_substs, |cx| ty.clean(cx)); |
fc512014 | 1279 | } |
6a06907d XL |
1280 | let path = path.clean(cx); |
1281 | resolve_type(cx, path, hir_id) | |
1a4d82fc | 1282 | } |
fc512014 XL |
1283 | hir::QPath::Resolved(Some(ref qself), ref p) => { |
1284 | // Try to normalize `<X as Y>::T` to a type | |
1285 | let ty = hir_ty_to_ty(cx.tcx, hir_ty); | |
1286 | if let Some(normalized_value) = normalize(cx, ty) { | |
1287 | return normalized_value.clean(cx); | |
1288 | } | |
1289 | ||
1290 | let segments = if p.is_global() { &p.segments[1..] } else { &p.segments }; | |
1291 | let trait_segments = &segments[..segments.len() - 1]; | |
17df50a5 | 1292 | let trait_def = cx.tcx.associated_item(p.res.def_id()).container.id(); |
fc512014 XL |
1293 | let trait_path = self::Path { |
1294 | global: p.is_global(), | |
17df50a5 | 1295 | res: Res::Def(DefKind::Trait, trait_def), |
fc512014 XL |
1296 | segments: trait_segments.clean(cx), |
1297 | }; | |
1298 | Type::QPath { | |
1299 | name: p.segments.last().expect("segments were empty").ident.name, | |
17df50a5 | 1300 | self_def_id: Some(DefId::local(qself.hir_id.owner.local_def_index)), |
fc512014 XL |
1301 | self_type: box qself.clean(cx), |
1302 | trait_: box resolve_type(cx, trait_path, hir_id), | |
1303 | } | |
1304 | } | |
1305 | hir::QPath::TypeRelative(ref qself, ref segment) => { | |
1306 | let ty = hir_ty_to_ty(cx.tcx, hir_ty); | |
1307 | let res = if let ty::Projection(proj) = ty.kind() { | |
1308 | Res::Def(DefKind::Trait, proj.trait_ref(cx.tcx).def_id) | |
1309 | } else { | |
1310 | Res::Err | |
1311 | }; | |
6a06907d | 1312 | let trait_path = hir::Path { span, res, segments: &[] }.clean(cx); |
fc512014 XL |
1313 | Type::QPath { |
1314 | name: segment.ident.name, | |
17df50a5 | 1315 | self_def_id: res.opt_def_id(), |
fc512014 | 1316 | self_type: box qself.clean(cx), |
6a06907d | 1317 | trait_: box resolve_type(cx, trait_path, hir_id), |
fc512014 XL |
1318 | } |
1319 | } | |
1320 | hir::QPath::LangItem(..) => bug!("clean: requiring documentation of lang item"), | |
1a4d82fc JJ |
1321 | } |
1322 | } | |
1323 | ||
dfeec247 | 1324 | impl Clean<Type> for hir::Ty<'_> { |
6a06907d | 1325 | fn clean(&self, cx: &mut DocContext<'_>) -> Type { |
dfeec247 | 1326 | use rustc_hir::*; |
b7449926 | 1327 | |
e74abb32 | 1328 | match self.kind { |
8faf50e0 | 1329 | TyKind::Never => Never, |
dfeec247 | 1330 | TyKind::Ptr(ref m) => RawPointer(m.mutbl, box m.ty.clean(cx)), |
8faf50e0 | 1331 | TyKind::Rptr(ref l, ref m) => { |
fc512014 XL |
1332 | // There are two times a `Fresh` lifetime can be created: |
1333 | // 1. For `&'_ x`, written by the user. This corresponds to `lower_lifetime` in `rustc_ast_lowering`. | |
1334 | // 2. For `&x` as a parameter to an `async fn`. This corresponds to `elided_ref_lifetime in `rustc_ast_lowering`. | |
1335 | // See #59286 for more information. | |
1336 | // Ideally we would only hide the `'_` for case 2., but I don't know a way to distinguish it. | |
1337 | // Turning `fn f(&'_ self)` into `fn f(&self)` isn't the worst thing in the world, though; | |
1338 | // there's no case where it could cause the function to fail to compile. | |
1339 | let elided = | |
1340 | l.is_elided() || matches!(l.name, LifetimeName::Param(ParamName::Fresh(_))); | |
1341 | let lifetime = if elided { None } else { Some(l.clean(cx)) }; | |
dfeec247 | 1342 | BorrowedRef { lifetime, mutability: m.mutbl, type_: box m.ty.clean(cx) } |
32a655c1 | 1343 | } |
8faf50e0 XL |
1344 | TyKind::Slice(ref ty) => Slice(box ty.clean(cx)), |
1345 | TyKind::Array(ref ty, ref length) => { | |
416331ca | 1346 | let def_id = cx.tcx.hir().local_def_id(length.hir_id); |
1b1a35ee XL |
1347 | // NOTE(min_const_generics): We can't use `const_eval_poly` for constants |
1348 | // as we currently do not supply the parent generics to anonymous constants | |
1349 | // but do allow `ConstKind::Param`. | |
1350 | // | |
1351 | // `const_eval_poly` tries to to first substitute generic parameters which | |
1352 | // results in an ICE while manually constructing the constant and using `eval` | |
1353 | // does nothing for `ConstKind::Param`. | |
1354 | let ct = ty::Const::from_anon_const(cx.tcx, def_id); | |
1355 | let param_env = cx.tcx.param_env(def_id); | |
1356 | let length = print_const(cx, ct.eval(cx.tcx, param_env)); | |
94b46f34 | 1357 | Array(box ty.clean(cx), length) |
dfeec247 | 1358 | } |
8faf50e0 | 1359 | TyKind::Tup(ref tys) => Tuple(tys.clean(cx)), |
f035d41b | 1360 | TyKind::OpaqueDef(item_id, _) => { |
6a06907d | 1361 | let item = cx.tcx.hir().item(item_id); |
e74abb32 | 1362 | if let hir::ItemKind::OpaqueTy(ref ty) = item.kind { |
0bf4aa26 XL |
1363 | ImplTrait(ty.bounds.clean(cx)) |
1364 | } else { | |
1365 | unreachable!() | |
1366 | } | |
1367 | } | |
fc512014 | 1368 | TyKind::Path(_) => clean_qpath(&self, cx), |
6a06907d | 1369 | TyKind::TraitObject(ref bounds, ref lifetime, _) => { |
136023e0 XL |
1370 | let bounds = bounds.iter().map(|bound| bound.clean(cx)).collect(); |
1371 | let lifetime = if !lifetime.is_elided() { Some(lifetime.clean(cx)) } else { None }; | |
1372 | DynTrait(bounds, lifetime) | |
1a4d82fc | 1373 | } |
8faf50e0 XL |
1374 | TyKind::BareFn(ref barefn) => BareFunction(box barefn.clean(cx)), |
1375 | TyKind::Infer | TyKind::Err => Infer, | |
e74abb32 | 1376 | TyKind::Typeof(..) => panic!("unimplemented type {:?}", self.kind), |
1a4d82fc JJ |
1377 | } |
1378 | } | |
1379 | } | |
1380 | ||
fc512014 | 1381 | /// Returns `None` if the type could not be normalized |
6a06907d | 1382 | fn normalize(cx: &mut DocContext<'tcx>, ty: Ty<'_>) -> Option<Ty<'tcx>> { |
fc512014 XL |
1383 | // HACK: low-churn fix for #79459 while we wait for a trait normalization fix |
1384 | if !cx.tcx.sess.opts.debugging_opts.normalize_docs { | |
1385 | return None; | |
1386 | } | |
1387 | ||
1388 | use crate::rustc_trait_selection::infer::TyCtxtInferExt; | |
1389 | use crate::rustc_trait_selection::traits::query::normalize::AtExt; | |
1390 | use rustc_middle::traits::ObligationCause; | |
1391 | ||
1392 | // Try to normalize `<X as Y>::T` to a type | |
1393 | let lifted = ty.lift_to_tcx(cx.tcx).unwrap(); | |
1394 | let normalized = cx.tcx.infer_ctxt().enter(|infcx| { | |
1395 | infcx | |
6a06907d | 1396 | .at(&ObligationCause::dummy(), cx.param_env) |
fc512014 XL |
1397 | .normalize(lifted) |
1398 | .map(|resolved| infcx.resolve_vars_if_possible(resolved.value)) | |
1399 | }); | |
1400 | match normalized { | |
1401 | Ok(normalized_value) => { | |
1402 | debug!("normalized {:?} to {:?}", ty, normalized_value); | |
1403 | Some(normalized_value) | |
1404 | } | |
1405 | Err(err) => { | |
1406 | debug!("failed to normalize {:?}: {:?}", ty, err); | |
1407 | None | |
1408 | } | |
1409 | } | |
1410 | } | |
1411 | ||
ea8adc8c | 1412 | impl<'tcx> Clean<Type> for Ty<'tcx> { |
6a06907d | 1413 | fn clean(&self, cx: &mut DocContext<'_>) -> Type { |
48663c56 | 1414 | debug!("cleaning type: {:?}", self); |
fc512014 XL |
1415 | let ty = normalize(cx, self).unwrap_or(self); |
1416 | match *ty.kind() { | |
b7449926 XL |
1417 | ty::Never => Never, |
1418 | ty::Bool => Primitive(PrimitiveType::Bool), | |
1419 | ty::Char => Primitive(PrimitiveType::Char), | |
1420 | ty::Int(int_ty) => Primitive(int_ty.into()), | |
1421 | ty::Uint(uint_ty) => Primitive(uint_ty.into()), | |
1422 | ty::Float(float_ty) => Primitive(float_ty.into()), | |
1423 | ty::Str => Primitive(PrimitiveType::Str), | |
1424 | ty::Slice(ty) => Slice(box ty.clean(cx)), | |
1425 | ty::Array(ty, n) => { | |
29967ef6 | 1426 | let mut n = cx.tcx.lift(n).expect("array lift failed"); |
dfeec247 | 1427 | n = n.eval(cx.tcx, ty::ParamEnv::reveal_all()); |
0531ce1d | 1428 | let n = print_const(cx, n); |
ea8adc8c XL |
1429 | Array(box ty.clean(cx), n) |
1430 | } | |
dfeec247 XL |
1431 | ty::RawPtr(mt) => RawPointer(mt.mutbl, box mt.ty.clean(cx)), |
1432 | ty::Ref(r, ty, mutbl) => { | |
1433 | BorrowedRef { lifetime: r.clean(cx), mutability: mutbl, type_: box ty.clean(cx) } | |
1434 | } | |
1435 | ty::FnDef(..) | ty::FnPtr(_) => { | |
29967ef6 | 1436 | let ty = cx.tcx.lift(*self).expect("FnPtr lift failed"); |
041b39d2 | 1437 | let sig = ty.fn_sig(cx.tcx); |
f9f354fc | 1438 | let def_id = DefId::local(CRATE_DEF_INDEX); |
041b39d2 XL |
1439 | BareFunction(box BareFunctionDecl { |
1440 | unsafety: sig.unsafety(), | |
ff7c6d11 | 1441 | generic_params: Vec::new(), |
f9f354fc | 1442 | decl: (def_id, sig).clean(cx), |
041b39d2 XL |
1443 | abi: sig.abi(), |
1444 | }) | |
1445 | } | |
b7449926 | 1446 | ty::Adt(def, substs) => { |
e9174d1e | 1447 | let did = def.did; |
9e0c209e | 1448 | let kind = match def.adt_kind() { |
cdc7bbd5 XL |
1449 | AdtKind::Struct => ItemType::Struct, |
1450 | AdtKind::Union => ItemType::Union, | |
1451 | AdtKind::Enum => ItemType::Enum, | |
1a4d82fc | 1452 | }; |
92a42be0 | 1453 | inline::record_extern_fqn(cx, did, kind); |
e1599b0c | 1454 | let path = external_path(cx, cx.tcx.item_name(did), None, false, vec![], substs); |
136023e0 | 1455 | ResolvedPath { path, did, is_generic: false } |
1a4d82fc | 1456 | } |
b7449926 | 1457 | ty::Foreign(did) => { |
cdc7bbd5 | 1458 | inline::record_extern_fqn(cx, did, ItemType::ForeignType); |
dfeec247 XL |
1459 | let path = external_path( |
1460 | cx, | |
1461 | cx.tcx.item_name(did), | |
1462 | None, | |
1463 | false, | |
1464 | vec![], | |
1465 | InternalSubsts::empty(), | |
1466 | ); | |
136023e0 | 1467 | ResolvedPath { path, did, is_generic: false } |
abe05a73 | 1468 | } |
b7449926 | 1469 | ty::Dynamic(ref obj, ref reg) => { |
0731742a XL |
1470 | // HACK: pick the first `did` as the `did` of the trait object. Someone |
1471 | // might want to implement "native" support for marker-trait-only | |
1472 | // trait objects. | |
1473 | let mut dids = obj.principal_def_id().into_iter().chain(obj.auto_traits()); | |
dfeec247 XL |
1474 | let did = dids |
1475 | .next() | |
1476 | .unwrap_or_else(|| panic!("found trait object `{:?}` with no traits?", self)); | |
0731742a XL |
1477 | let substs = match obj.principal() { |
1478 | Some(principal) => principal.skip_binder().substs, | |
1479 | // marker traits have no substs. | |
dfeec247 | 1480 | _ => cx.tcx.intern_substs(&[]), |
0731742a XL |
1481 | }; |
1482 | ||
cdc7bbd5 | 1483 | inline::record_extern_fqn(cx, did, ItemType::Trait); |
0bf4aa26 | 1484 | |
136023e0 XL |
1485 | let lifetime = reg.clean(cx); |
1486 | let mut bounds = vec![]; | |
1487 | ||
0731742a | 1488 | for did in dids { |
0bf4aa26 | 1489 | let empty = cx.tcx.intern_substs(&[]); |
dfeec247 XL |
1490 | let path = |
1491 | external_path(cx, cx.tcx.item_name(did), Some(did), false, vec![], empty); | |
cdc7bbd5 | 1492 | inline::record_extern_fqn(cx, did, ItemType::Trait); |
136023e0 XL |
1493 | let bound = PolyTrait { |
1494 | trait_: ResolvedPath { path, did, is_generic: false }, | |
1495 | generic_params: Vec::new(), | |
1496 | }; | |
1497 | bounds.push(bound); | |
0bf4aa26 | 1498 | } |
476ff2be | 1499 | |
0bf4aa26 XL |
1500 | let mut bindings = vec![]; |
1501 | for pb in obj.projection_bounds() { | |
1502 | bindings.push(TypeBinding { | |
fc512014 | 1503 | name: cx.tcx.associated_item(pb.item_def_id()).ident.name, |
dfeec247 | 1504 | kind: TypeBindingKind::Equality { ty: pb.skip_binder().ty.clean(cx) }, |
0bf4aa26 XL |
1505 | }); |
1506 | } | |
9e0c209e | 1507 | |
dfeec247 XL |
1508 | let path = |
1509 | external_path(cx, cx.tcx.item_name(did), Some(did), false, bindings, substs); | |
136023e0 XL |
1510 | bounds.insert( |
1511 | 0, | |
1512 | PolyTrait { | |
1513 | trait_: ResolvedPath { path, did, is_generic: false }, | |
1514 | generic_params: Vec::new(), | |
1515 | }, | |
1516 | ); | |
1517 | ||
1518 | DynTrait(bounds, lifetime) | |
1a4d82fc | 1519 | } |
48663c56 XL |
1520 | ty::Tuple(ref t) => { |
1521 | Tuple(t.iter().map(|t| t.expect_ty()).collect::<Vec<_>>().clean(cx)) | |
1522 | } | |
1a4d82fc | 1523 | |
b7449926 | 1524 | ty::Projection(ref data) => data.clean(cx), |
1a4d82fc | 1525 | |
e1599b0c | 1526 | ty::Param(ref p) => { |
6a06907d | 1527 | if let Some(bounds) = cx.impl_trait_bounds.remove(&p.index.into()) { |
e1599b0c XL |
1528 | ImplTrait(bounds) |
1529 | } else { | |
fc512014 | 1530 | Generic(p.name) |
e1599b0c XL |
1531 | } |
1532 | } | |
1a4d82fc | 1533 | |
b7449926 | 1534 | ty::Opaque(def_id, substs) => { |
5bcae85e | 1535 | // Grab the "TraitA + TraitB" from `impl TraitA + TraitB`, |
29967ef6 XL |
1536 | // by looking up the bounds associated with the def_id. |
1537 | let substs = cx.tcx.lift(substs).expect("Opaque lift failed"); | |
1538 | let bounds = cx | |
1539 | .tcx | |
1540 | .explicit_item_bounds(def_id) | |
1541 | .iter() | |
1542 | .map(|(bound, _)| bound.subst(cx.tcx, substs)) | |
1543 | .collect::<Vec<_>>(); | |
0531ce1d XL |
1544 | let mut regions = vec![]; |
1545 | let mut has_sized = false; | |
dfeec247 | 1546 | let mut bounds = bounds |
dfeec247 | 1547 | .iter() |
29967ef6 | 1548 | .filter_map(|bound| { |
5869c6ff | 1549 | let bound_predicate = bound.kind(); |
fc512014 | 1550 | let trait_ref = match bound_predicate.skip_binder() { |
5869c6ff | 1551 | ty::PredicateKind::Trait(tr, _constness) => { |
fc512014 | 1552 | bound_predicate.rebind(tr.trait_ref) |
3dfed10e | 1553 | } |
5869c6ff | 1554 | ty::PredicateKind::TypeOutlives(ty::OutlivesPredicate(_ty, reg)) => { |
3dfed10e XL |
1555 | if let Some(r) = reg.clean(cx) { |
1556 | regions.push(GenericBound::Outlives(r)); | |
1557 | } | |
1558 | return None; | |
f9f354fc | 1559 | } |
3dfed10e | 1560 | _ => return None, |
dfeec247 | 1561 | }; |
0531ce1d | 1562 | |
dfeec247 XL |
1563 | if let Some(sized) = cx.tcx.lang_items().sized_trait() { |
1564 | if trait_ref.def_id() == sized { | |
1565 | has_sized = true; | |
1566 | return None; | |
0531ce1d | 1567 | } |
0531ce1d | 1568 | } |
0531ce1d | 1569 | |
ba9703b0 | 1570 | let bounds: Vec<_> = bounds |
dfeec247 | 1571 | .iter() |
29967ef6 | 1572 | .filter_map(|bound| { |
5869c6ff XL |
1573 | if let ty::PredicateKind::Projection(proj) = |
1574 | bound.kind().skip_binder() | |
3dfed10e | 1575 | { |
dfeec247 | 1576 | if proj.projection_ty.trait_ref(cx.tcx) |
f035d41b | 1577 | == trait_ref.skip_binder() |
dfeec247 XL |
1578 | { |
1579 | Some(TypeBinding { | |
1580 | name: cx | |
1581 | .tcx | |
1582 | .associated_item(proj.projection_ty.item_def_id) | |
1583 | .ident | |
fc512014 | 1584 | .name, |
dfeec247 XL |
1585 | kind: TypeBindingKind::Equality { |
1586 | ty: proj.ty.clean(cx), | |
1587 | }, | |
1588 | }) | |
1589 | } else { | |
1590 | None | |
1591 | } | |
1592 | } else { | |
1593 | None | |
1594 | } | |
1595 | }) | |
1596 | .collect(); | |
1597 | ||
ba9703b0 | 1598 | Some((trait_ref, &bounds[..]).clean(cx)) |
dfeec247 XL |
1599 | }) |
1600 | .collect::<Vec<_>>(); | |
0531ce1d XL |
1601 | bounds.extend(regions); |
1602 | if !has_sized && !bounds.is_empty() { | |
8faf50e0 | 1603 | bounds.insert(0, GenericBound::maybe_sized(cx)); |
0531ce1d XL |
1604 | } |
1605 | ImplTrait(bounds) | |
5bcae85e SL |
1606 | } |
1607 | ||
b7449926 | 1608 | ty::Closure(..) | ty::Generator(..) => Tuple(vec![]), // FIXME(pcwalton) |
1a4d82fc | 1609 | |
a1dfa0c6 XL |
1610 | ty::Bound(..) => panic!("Bound"), |
1611 | ty::Placeholder(..) => panic!("Placeholder"), | |
b7449926 XL |
1612 | ty::GeneratorWitness(..) => panic!("GeneratorWitness"), |
1613 | ty::Infer(..) => panic!("Infer"), | |
f035d41b | 1614 | ty::Error(_) => panic!("Error"), |
1a4d82fc JJ |
1615 | } |
1616 | } | |
1617 | } | |
1618 | ||
532ac7d7 | 1619 | impl<'tcx> Clean<Constant> for ty::Const<'tcx> { |
6a06907d | 1620 | fn clean(&self, cx: &mut DocContext<'_>) -> Constant { |
cdc7bbd5 | 1621 | // FIXME: instead of storing the stringified expression, store `self` directly instead. |
532ac7d7 XL |
1622 | Constant { |
1623 | type_: self.ty.clean(cx), | |
cdc7bbd5 | 1624 | kind: ConstantKind::TyConst { expr: self.to_string() }, |
532ac7d7 XL |
1625 | } |
1626 | } | |
1627 | } | |
1628 | ||
6a06907d XL |
1629 | impl Clean<Item> for hir::FieldDef<'_> { |
1630 | fn clean(&self, cx: &mut DocContext<'_>) -> Item { | |
fc512014 XL |
1631 | let what_rustc_thinks = Item::from_hir_id_and_parts( |
1632 | self.hir_id, | |
1633 | Some(self.ident.name), | |
1634 | StructFieldItem(self.ty.clean(cx)), | |
1635 | cx, | |
1636 | ); | |
1637 | // Don't show `pub` for fields on enum variants; they are always public | |
1638 | Item { visibility: self.vis.clean(cx), ..what_rustc_thinks } | |
1a4d82fc JJ |
1639 | } |
1640 | } | |
1641 | ||
dc9dc135 | 1642 | impl Clean<Item> for ty::FieldDef { |
6a06907d | 1643 | fn clean(&self, cx: &mut DocContext<'_>) -> Item { |
fc512014 XL |
1644 | let what_rustc_thinks = Item::from_def_id_and_parts( |
1645 | self.did, | |
1646 | Some(self.ident.name), | |
1647 | StructFieldItem(cx.tcx.type_of(self.did).clean(cx)), | |
1648 | cx, | |
1649 | ); | |
1650 | // Don't show `pub` for fields on enum variants; they are always public | |
1651 | Item { visibility: self.vis.clean(cx), ..what_rustc_thinks } | |
1a4d82fc JJ |
1652 | } |
1653 | } | |
1654 | ||
dfeec247 | 1655 | impl Clean<Visibility> for hir::Visibility<'_> { |
6a06907d | 1656 | fn clean(&self, cx: &mut DocContext<'_>) -> Visibility { |
e74abb32 | 1657 | match self.node { |
8faf50e0 XL |
1658 | hir::VisibilityKind::Public => Visibility::Public, |
1659 | hir::VisibilityKind::Inherited => Visibility::Inherited, | |
fc512014 XL |
1660 | hir::VisibilityKind::Crate(_) => { |
1661 | let krate = DefId::local(CRATE_DEF_INDEX); | |
1662 | Visibility::Restricted(krate) | |
1663 | } | |
8faf50e0 | 1664 | hir::VisibilityKind::Restricted { ref path, .. } => { |
94b46f34 | 1665 | let path = path.clean(cx); |
48663c56 | 1666 | let did = register_res(cx, path.res); |
fc512014 | 1667 | Visibility::Restricted(did) |
94b46f34 | 1668 | } |
e74abb32 | 1669 | } |
54a0048b SL |
1670 | } |
1671 | } | |
1672 | ||
e74abb32 | 1673 | impl Clean<Visibility> for ty::Visibility { |
6a06907d | 1674 | fn clean(&self, _cx: &mut DocContext<'_>) -> Visibility { |
fc512014 XL |
1675 | match *self { |
1676 | ty::Visibility::Public => Visibility::Public, | |
1677 | // NOTE: this is not quite right: `ty` uses `Invisible` to mean 'private', | |
1678 | // while rustdoc really does mean inherited. That means that for enum variants, such as | |
1679 | // `pub enum E { V }`, `V` will be marked as `Public` by `ty`, but as `Inherited` by rustdoc. | |
1680 | // This is the main reason `impl Clean for hir::Visibility` still exists; various parts of clean | |
1681 | // override `tcx.visibility` explicitly to make sure this distinction is captured. | |
1682 | ty::Visibility::Invisible => Visibility::Inherited, | |
1683 | ty::Visibility::Restricted(module) => Visibility::Restricted(module), | |
0bf4aa26 | 1684 | } |
9e0c209e SL |
1685 | } |
1686 | } | |
1687 | ||
dfeec247 | 1688 | impl Clean<VariantStruct> for rustc_hir::VariantData<'_> { |
6a06907d | 1689 | fn clean(&self, cx: &mut DocContext<'_>) -> VariantStruct { |
1a4d82fc | 1690 | VariantStruct { |
5869c6ff | 1691 | struct_type: CtorKind::from_hir(self), |
b039eaaf | 1692 | fields: self.fields().iter().map(|x| x.clean(cx)).collect(), |
1a4d82fc JJ |
1693 | fields_stripped: false, |
1694 | } | |
1695 | } | |
1696 | } | |
1697 | ||
dc9dc135 | 1698 | impl Clean<Item> for ty::VariantDef { |
6a06907d | 1699 | fn clean(&self, cx: &mut DocContext<'_>) -> Item { |
c30ab7b3 | 1700 | let kind = match self.ctor_kind { |
5869c6ff XL |
1701 | CtorKind::Const => Variant::CLike, |
1702 | CtorKind::Fn => Variant::Tuple( | |
dfeec247 XL |
1703 | self.fields.iter().map(|f| cx.tcx.type_of(f.did).clean(cx)).collect(), |
1704 | ), | |
5869c6ff XL |
1705 | CtorKind::Fictive => Variant::Struct(VariantStruct { |
1706 | struct_type: CtorKind::Fictive, | |
dfeec247 XL |
1707 | fields_stripped: false, |
1708 | fields: self | |
1709 | .fields | |
1710 | .iter() | |
fc512014 XL |
1711 | .map(|field| { |
1712 | let name = Some(field.ident.name); | |
1713 | let kind = StructFieldItem(cx.tcx.type_of(field.did).clean(cx)); | |
1714 | let what_rustc_thinks = | |
1715 | Item::from_def_id_and_parts(field.did, name, kind, cx); | |
1716 | // don't show `pub` for fields, which are always public | |
1717 | Item { visibility: Visibility::Inherited, ..what_rustc_thinks } | |
dfeec247 XL |
1718 | }) |
1719 | .collect(), | |
1720 | }), | |
1a4d82fc | 1721 | }; |
5869c6ff XL |
1722 | let what_rustc_thinks = |
1723 | Item::from_def_id_and_parts(self.def_id, Some(self.ident.name), VariantItem(kind), cx); | |
fc512014 XL |
1724 | // don't show `pub` for fields, which are always public |
1725 | Item { visibility: Inherited, ..what_rustc_thinks } | |
1a4d82fc JJ |
1726 | } |
1727 | } | |
1728 | ||
5869c6ff | 1729 | impl Clean<Variant> for hir::VariantData<'_> { |
6a06907d | 1730 | fn clean(&self, cx: &mut DocContext<'_>) -> Variant { |
532ac7d7 | 1731 | match self { |
5869c6ff | 1732 | hir::VariantData::Struct(..) => Variant::Struct(self.clean(cx)), |
dfeec247 | 1733 | hir::VariantData::Tuple(..) => { |
5869c6ff | 1734 | Variant::Tuple(self.fields().iter().map(|x| x.ty.clean(cx)).collect()) |
dfeec247 | 1735 | } |
5869c6ff | 1736 | hir::VariantData::Unit(..) => Variant::CLike, |
c30ab7b3 | 1737 | } |
1a4d82fc JJ |
1738 | } |
1739 | } | |
1740 | ||
dfeec247 | 1741 | impl Clean<Path> for hir::Path<'_> { |
6a06907d | 1742 | fn clean(&self, cx: &mut DocContext<'_>) -> Path { |
1a4d82fc | 1743 | Path { |
32a655c1 | 1744 | global: self.is_global(), |
48663c56 | 1745 | res: self.res, |
32a655c1 | 1746 | segments: if self.is_global() { &self.segments[1..] } else { &self.segments }.clean(cx), |
1a4d82fc JJ |
1747 | } |
1748 | } | |
1749 | } | |
1750 | ||
dfeec247 | 1751 | impl Clean<GenericArgs> for hir::GenericArgs<'_> { |
6a06907d | 1752 | fn clean(&self, cx: &mut DocContext<'_>) -> GenericArgs { |
3b2f2976 | 1753 | if self.parenthesized { |
dc9dc135 | 1754 | let output = self.bindings[0].ty().clean(cx); |
8faf50e0 | 1755 | GenericArgs::Parenthesized { |
3b2f2976 | 1756 | inputs: self.inputs().clean(cx), |
dfeec247 | 1757 | output: if output != Type::Tuple(Vec::new()) { Some(output) } else { None }, |
1a4d82fc | 1758 | } |
3b2f2976 | 1759 | } else { |
8faf50e0 | 1760 | GenericArgs::AngleBracketed { |
dfeec247 XL |
1761 | args: self |
1762 | .args | |
1763 | .iter() | |
3dfed10e XL |
1764 | .map(|arg| match arg { |
1765 | hir::GenericArg::Lifetime(lt) if !lt.is_elided() => { | |
1766 | GenericArg::Lifetime(lt.clean(cx)) | |
dfeec247 | 1767 | } |
3dfed10e XL |
1768 | hir::GenericArg::Lifetime(_) => GenericArg::Lifetime(Lifetime::elided()), |
1769 | hir::GenericArg::Type(ty) => GenericArg::Type(ty.clean(cx)), | |
1770 | hir::GenericArg::Const(ct) => GenericArg::Const(ct.clean(cx)), | |
dfeec247 XL |
1771 | }) |
1772 | .collect(), | |
3b2f2976 | 1773 | bindings: self.bindings.clean(cx), |
1a4d82fc JJ |
1774 | } |
1775 | } | |
1776 | } | |
1777 | } | |
1778 | ||
dfeec247 | 1779 | impl Clean<PathSegment> for hir::PathSegment<'_> { |
6a06907d | 1780 | fn clean(&self, cx: &mut DocContext<'_>) -> PathSegment { |
5869c6ff | 1781 | PathSegment { name: self.ident.name, args: self.args().clean(cx) } |
1a4d82fc JJ |
1782 | } |
1783 | } | |
1784 | ||
dfeec247 | 1785 | impl Clean<BareFunctionDecl> for hir::BareFnTy<'_> { |
6a06907d XL |
1786 | fn clean(&self, cx: &mut DocContext<'_>) -> BareFunctionDecl { |
1787 | let (generic_params, decl) = enter_impl_trait(cx, |cx| { | |
1788 | (self.generic_params.clean(cx), (&*self.decl, self.param_names).clean(cx)) | |
0531ce1d | 1789 | }); |
dfeec247 | 1790 | BareFunctionDecl { unsafety: self.unsafety, abi: self.abi, decl, generic_params } |
1a4d82fc JJ |
1791 | } |
1792 | } | |
1793 | ||
fc512014 | 1794 | impl Clean<Vec<Item>> for (&hir::Item<'_>, Option<Symbol>) { |
6a06907d | 1795 | fn clean(&self, cx: &mut DocContext<'_>) -> Vec<Item> { |
fc512014 XL |
1796 | use hir::ItemKind; |
1797 | ||
1798 | let (item, renamed) = self; | |
6a06907d XL |
1799 | let def_id = item.def_id.to_def_id(); |
1800 | let mut name = renamed.unwrap_or_else(|| cx.tcx.hir().name(item.hir_id())); | |
1801 | cx.with_param_env(def_id, |cx| { | |
fc512014 | 1802 | let kind = match item.kind { |
6a06907d XL |
1803 | ItemKind::Static(ty, mutability, body_id) => { |
1804 | StaticItem(Static { type_: ty.clean(cx), mutability, expr: Some(body_id) }) | |
1805 | } | |
fc512014 XL |
1806 | ItemKind::Const(ty, body_id) => ConstantItem(Constant { |
1807 | type_: ty.clean(cx), | |
cdc7bbd5 | 1808 | kind: ConstantKind::Local { body: body_id, def_id }, |
fc512014 XL |
1809 | }), |
1810 | ItemKind::OpaqueTy(ref ty) => OpaqueTyItem(OpaqueTy { | |
1811 | bounds: ty.bounds.clean(cx), | |
1812 | generics: ty.generics.clean(cx), | |
1813 | }), | |
5869c6ff XL |
1814 | ItemKind::TyAlias(hir_ty, ref generics) => { |
1815 | let rustdoc_ty = hir_ty.clean(cx); | |
1816 | let ty = hir_ty_to_ty(cx.tcx, hir_ty).clean(cx); | |
fc512014 | 1817 | TypedefItem( |
5869c6ff XL |
1818 | Typedef { |
1819 | type_: rustdoc_ty, | |
1820 | generics: generics.clean(cx), | |
1821 | item_type: Some(ty), | |
1822 | }, | |
fc512014 XL |
1823 | false, |
1824 | ) | |
1825 | } | |
1826 | ItemKind::Enum(ref def, ref generics) => EnumItem(Enum { | |
1827 | variants: def.variants.iter().map(|v| v.clean(cx)).collect(), | |
1828 | generics: generics.clean(cx), | |
1829 | variants_stripped: false, | |
1830 | }), | |
1831 | ItemKind::TraitAlias(ref generics, bounds) => TraitAliasItem(TraitAlias { | |
1832 | generics: generics.clean(cx), | |
1833 | bounds: bounds.clean(cx), | |
1834 | }), | |
1835 | ItemKind::Union(ref variant_data, ref generics) => UnionItem(Union { | |
fc512014 XL |
1836 | generics: generics.clean(cx), |
1837 | fields: variant_data.fields().clean(cx), | |
1838 | fields_stripped: false, | |
1839 | }), | |
1840 | ItemKind::Struct(ref variant_data, ref generics) => StructItem(Struct { | |
5869c6ff | 1841 | struct_type: CtorKind::from_hir(variant_data), |
fc512014 XL |
1842 | generics: generics.clean(cx), |
1843 | fields: variant_data.fields().clean(cx), | |
1844 | fields_stripped: false, | |
1845 | }), | |
6a06907d | 1846 | ItemKind::Impl(ref impl_) => return clean_impl(impl_, item.hir_id(), cx), |
fc512014 XL |
1847 | // proc macros can have a name set by attributes |
1848 | ItemKind::Fn(ref sig, ref generics, body_id) => { | |
1849 | clean_fn_or_proc_macro(item, sig, generics, body_id, &mut name, cx) | |
1850 | } | |
5869c6ff | 1851 | ItemKind::Trait(is_auto, unsafety, ref generics, ref bounds, ref item_ids) => { |
fc512014 XL |
1852 | let items = item_ids |
1853 | .iter() | |
1854 | .map(|ti| cx.tcx.hir().trait_item(ti.id).clean(cx)) | |
1855 | .collect(); | |
fc512014 XL |
1856 | TraitItem(Trait { |
1857 | unsafety, | |
1858 | items, | |
1859 | generics: generics.clean(cx), | |
1860 | bounds: bounds.clean(cx), | |
fc512014 XL |
1861 | is_auto: is_auto.clean(cx), |
1862 | }) | |
1863 | } | |
1864 | ItemKind::ExternCrate(orig_name) => { | |
1865 | return clean_extern_crate(item, name, orig_name, cx); | |
1866 | } | |
5869c6ff XL |
1867 | ItemKind::Use(path, kind) => { |
1868 | return clean_use_statement(item, name, path, kind, cx); | |
1869 | } | |
fc512014 XL |
1870 | _ => unreachable!("not yet converted"), |
1871 | }; | |
1872 | ||
1873 | vec![Item::from_def_id_and_parts(def_id, Some(name), kind, cx)] | |
1874 | }) | |
1a4d82fc JJ |
1875 | } |
1876 | } | |
1877 | ||
fc512014 | 1878 | impl Clean<Item> for hir::Variant<'_> { |
6a06907d | 1879 | fn clean(&self, cx: &mut DocContext<'_>) -> Item { |
5869c6ff | 1880 | let kind = VariantItem(self.data.clean(cx)); |
fc512014 XL |
1881 | let what_rustc_thinks = |
1882 | Item::from_hir_id_and_parts(self.id, Some(self.ident.name), kind, cx); | |
1883 | // don't show `pub` for variants, which are always public | |
1884 | Item { visibility: Inherited, ..what_rustc_thinks } | |
1a4d82fc JJ |
1885 | } |
1886 | } | |
1887 | ||
5869c6ff XL |
1888 | impl Clean<bool> for ty::ImplPolarity { |
1889 | /// Returns whether the impl has negative polarity. | |
6a06907d | 1890 | fn clean(&self, _: &mut DocContext<'_>) -> bool { |
85aaf69f | 1891 | match self { |
e74abb32 XL |
1892 | &ty::ImplPolarity::Positive | |
1893 | // FIXME: do we want to do something else here? | |
5869c6ff XL |
1894 | &ty::ImplPolarity::Reservation => false, |
1895 | &ty::ImplPolarity::Negative => true, | |
85aaf69f SL |
1896 | } |
1897 | } | |
1898 | } | |
1899 | ||
6a06907d XL |
1900 | fn clean_impl(impl_: &hir::Impl<'_>, hir_id: hir::HirId, cx: &mut DocContext<'_>) -> Vec<Item> { |
1901 | let tcx = cx.tcx; | |
fc512014 | 1902 | let mut ret = Vec::new(); |
5869c6ff XL |
1903 | let trait_ = impl_.of_trait.clean(cx); |
1904 | let items = | |
6a06907d XL |
1905 | impl_.items.iter().map(|ii| tcx.hir().impl_item(ii.id).clean(cx)).collect::<Vec<_>>(); |
1906 | let def_id = tcx.hir().local_def_id(hir_id); | |
fc512014 XL |
1907 | |
1908 | // If this impl block is an implementation of the Deref trait, then we | |
1909 | // need to try inlining the target's inherent impl blocks as well. | |
6a06907d | 1910 | if trait_.def_id() == tcx.lang_items().deref_trait() { |
fc512014 XL |
1911 | build_deref_target_impls(cx, &items, &mut ret); |
1912 | } | |
1913 | ||
5869c6ff | 1914 | let for_ = impl_.self_ty.clean(cx); |
6a06907d XL |
1915 | let type_alias = for_.def_id().and_then(|did| match tcx.def_kind(did) { |
1916 | DefKind::TyAlias => Some(tcx.type_of(did).clean(cx)), | |
fc512014 XL |
1917 | _ => None, |
1918 | }); | |
6a06907d | 1919 | let mut make_item = |trait_: Option<Type>, for_: Type, items: Vec<Item>| { |
fc512014 | 1920 | let kind = ImplItem(Impl { |
cdc7bbd5 | 1921 | span: types::rustc_span(tcx.hir().local_def_id(hir_id).to_def_id(), tcx), |
5869c6ff XL |
1922 | unsafety: impl_.unsafety, |
1923 | generics: impl_.generics.clean(cx), | |
fc512014 XL |
1924 | trait_, |
1925 | for_, | |
1926 | items, | |
6a06907d | 1927 | negative_polarity: tcx.impl_polarity(def_id).clean(cx), |
fc512014 XL |
1928 | synthetic: false, |
1929 | blanket_impl: None, | |
1930 | }); | |
5869c6ff | 1931 | Item::from_hir_id_and_parts(hir_id, None, kind, cx) |
fc512014 XL |
1932 | }; |
1933 | if let Some(type_alias) = type_alias { | |
1934 | ret.push(make_item(trait_.clone(), type_alias, items.clone())); | |
1935 | } | |
1936 | ret.push(make_item(trait_, for_, items)); | |
1937 | ret | |
1938 | } | |
1939 | ||
1940 | fn clean_extern_crate( | |
1941 | krate: &hir::Item<'_>, | |
1942 | name: Symbol, | |
1943 | orig_name: Option<Symbol>, | |
6a06907d | 1944 | cx: &mut DocContext<'_>, |
fc512014 XL |
1945 | ) -> Vec<Item> { |
1946 | // this is the ID of the `extern crate` statement | |
6a06907d | 1947 | let cnum = cx.tcx.extern_mod_stmt_cnum(krate.def_id).unwrap_or(LOCAL_CRATE); |
fc512014 XL |
1948 | // this is the ID of the crate itself |
1949 | let crate_def_id = DefId { krate: cnum, index: CRATE_DEF_INDEX }; | |
6a06907d | 1950 | let attrs = cx.tcx.hir().attrs(krate.hir_id()); |
fc512014 | 1951 | let please_inline = krate.vis.node.is_pub() |
6a06907d | 1952 | && attrs.iter().any(|a| { |
fc512014 XL |
1953 | a.has_name(sym::doc) |
1954 | && match a.meta_item_list() { | |
1955 | Some(l) => attr::list_contains_name(&l, sym::inline), | |
1956 | None => false, | |
1957 | } | |
dfeec247 | 1958 | }); |
0731742a | 1959 | |
fc512014 XL |
1960 | if please_inline { |
1961 | let mut visited = FxHashSet::default(); | |
0731742a | 1962 | |
fc512014 | 1963 | let res = Res::Def(DefKind::Mod, crate_def_id); |
0731742a | 1964 | |
fc512014 XL |
1965 | if let Some(items) = inline::try_inline( |
1966 | cx, | |
6a06907d | 1967 | cx.tcx.parent_module(krate.hir_id()).to_def_id(), |
136023e0 | 1968 | Some(krate.def_id.to_def_id()), |
fc512014 XL |
1969 | res, |
1970 | name, | |
6a06907d | 1971 | Some(attrs), |
fc512014 XL |
1972 | &mut visited, |
1973 | ) { | |
1974 | return items; | |
0731742a | 1975 | } |
85aaf69f | 1976 | } |
cdc7bbd5 | 1977 | |
fc512014 XL |
1978 | // FIXME: using `from_def_id_and_kind` breaks `rustdoc/masked` for some reason |
1979 | vec![Item { | |
6a06907d XL |
1980 | name: Some(name), |
1981 | attrs: box attrs.clean(cx), | |
17df50a5 | 1982 | def_id: crate_def_id.into(), |
fc512014 | 1983 | visibility: krate.vis.clean(cx), |
6a06907d | 1984 | kind: box ExternCrateItem { src: orig_name }, |
17df50a5 | 1985 | cfg: attrs.cfg(cx.sess()), |
fc512014 | 1986 | }] |
1a4d82fc JJ |
1987 | } |
1988 | ||
5869c6ff XL |
1989 | fn clean_use_statement( |
1990 | import: &hir::Item<'_>, | |
1991 | name: Symbol, | |
1992 | path: &hir::Path<'_>, | |
1993 | kind: hir::UseKind, | |
6a06907d | 1994 | cx: &mut DocContext<'_>, |
5869c6ff XL |
1995 | ) -> Vec<Item> { |
1996 | // We need this comparison because some imports (for std types for example) | |
1997 | // are "inserted" as well but directly by the compiler and they should not be | |
1998 | // taken into account. | |
1999 | if import.span.ctxt().outer_expn_data().kind == ExpnKind::AstPass(AstPass::StdImports) { | |
2000 | return Vec::new(); | |
2001 | } | |
2002 | ||
6a06907d XL |
2003 | let attrs = cx.tcx.hir().attrs(import.hir_id()); |
2004 | let inline_attr = attrs.lists(sym::doc).get_word_attr(sym::inline); | |
5869c6ff XL |
2005 | let pub_underscore = import.vis.node.is_pub() && name == kw::Underscore; |
2006 | ||
6a06907d XL |
2007 | if pub_underscore { |
2008 | if let Some(ref inline) = inline_attr { | |
2009 | rustc_errors::struct_span_err!( | |
2010 | cx.tcx.sess, | |
2011 | inline.span(), | |
2012 | E0780, | |
2013 | "anonymous imports cannot be inlined" | |
2014 | ) | |
2015 | .span_label(import.span, "anonymous import") | |
2016 | .emit(); | |
2017 | } | |
5869c6ff | 2018 | } |
29967ef6 | 2019 | |
5869c6ff XL |
2020 | // We consider inlining the documentation of `pub use` statements, but we |
2021 | // forcefully don't inline if this is not public or if the | |
2022 | // #[doc(no_inline)] attribute is present. | |
2023 | // Don't inline doc(hidden) imports so they can be stripped at a later stage. | |
136023e0 XL |
2024 | let mut denied = !(import.vis.node.is_pub() |
2025 | || (cx.render_options.document_private && import.vis.node.is_pub_restricted())) | |
5869c6ff | 2026 | || pub_underscore |
6a06907d | 2027 | || attrs.iter().any(|a| { |
5869c6ff XL |
2028 | a.has_name(sym::doc) |
2029 | && match a.meta_item_list() { | |
2030 | Some(l) => { | |
2031 | attr::list_contains_name(&l, sym::no_inline) | |
2032 | || attr::list_contains_name(&l, sym::hidden) | |
dfeec247 | 2033 | } |
5869c6ff | 2034 | None => false, |
94b46f34 | 2035 | } |
5869c6ff XL |
2036 | }); |
2037 | ||
2038 | // Also check whether imports were asked to be inlined, in case we're trying to re-export a | |
2039 | // crate in Rust 2018+ | |
5869c6ff XL |
2040 | let path = path.clean(cx); |
2041 | let inner = if kind == hir::UseKind::Glob { | |
2042 | if !denied { | |
2043 | let mut visited = FxHashSet::default(); | |
2044 | if let Some(items) = inline::try_inline_glob(cx, path.res, &mut visited) { | |
2045 | return items; | |
94b46f34 | 2046 | } |
5869c6ff XL |
2047 | } |
2048 | Import::new_glob(resolve_use_source(cx, path), true) | |
2049 | } else { | |
6a06907d | 2050 | if inline_attr.is_none() { |
5869c6ff XL |
2051 | if let Res::Def(DefKind::Mod, did) = path.res { |
2052 | if !did.is_local() && did.index == CRATE_DEF_INDEX { | |
2053 | // if we're `pub use`ing an extern crate root, don't inline it unless we | |
2054 | // were specifically asked for it | |
2055 | denied = true; | |
13cf67c4 XL |
2056 | } |
2057 | } | |
5869c6ff XL |
2058 | } |
2059 | if !denied { | |
2060 | let mut visited = FxHashSet::default(); | |
136023e0 | 2061 | let import_def_id = import.def_id.to_def_id(); |
29967ef6 | 2062 | |
5869c6ff XL |
2063 | if let Some(mut items) = inline::try_inline( |
2064 | cx, | |
6a06907d | 2065 | cx.tcx.parent_module(import.hir_id()).to_def_id(), |
136023e0 | 2066 | Some(import_def_id), |
5869c6ff XL |
2067 | path.res, |
2068 | name, | |
6a06907d | 2069 | Some(attrs), |
5869c6ff XL |
2070 | &mut visited, |
2071 | ) { | |
2072 | items.push(Item::from_def_id_and_parts( | |
136023e0 | 2073 | import_def_id, |
5869c6ff XL |
2074 | None, |
2075 | ImportItem(Import::new_simple(name, resolve_use_source(cx, path), false)), | |
29967ef6 | 2076 | cx, |
5869c6ff XL |
2077 | )); |
2078 | return items; | |
1a4d82fc | 2079 | } |
5869c6ff XL |
2080 | } |
2081 | Import::new_simple(name, resolve_use_source(cx, path), true) | |
2082 | }; | |
8faf50e0 | 2083 | |
6a06907d | 2084 | vec![Item::from_def_id_and_parts(import.def_id.to_def_id(), None, ImportItem(inner), cx)] |
1a4d82fc JJ |
2085 | } |
2086 | ||
fc512014 | 2087 | impl Clean<Item> for (&hir::ForeignItem<'_>, Option<Symbol>) { |
6a06907d | 2088 | fn clean(&self, cx: &mut DocContext<'_>) -> Item { |
fc512014 | 2089 | let (item, renamed) = self; |
6a06907d | 2090 | cx.with_param_env(item.def_id.to_def_id(), |cx| { |
fc512014 XL |
2091 | let kind = match item.kind { |
2092 | hir::ForeignItemKind::Fn(ref decl, ref names, ref generics) => { | |
6a06907d XL |
2093 | let abi = cx.tcx.hir().get_foreign_abi(item.hir_id()); |
2094 | let (generics, decl) = enter_impl_trait(cx, |cx| { | |
fc512014 XL |
2095 | (generics.clean(cx), (&**decl, &names[..]).clean(cx)) |
2096 | }); | |
fc512014 XL |
2097 | ForeignFunctionItem(Function { |
2098 | decl, | |
2099 | generics, | |
2100 | header: hir::FnHeader { | |
136023e0 XL |
2101 | unsafety: if abi == Abi::RustIntrinsic { |
2102 | intrinsic_operation_unsafety(item.ident.name) | |
2103 | } else { | |
2104 | hir::Unsafety::Unsafe | |
2105 | }, | |
fc512014 XL |
2106 | abi, |
2107 | constness: hir::Constness::NotConst, | |
2108 | asyncness: hir::IsAsync::NotAsync, | |
2109 | }, | |
fc512014 XL |
2110 | }) |
2111 | } | |
6a06907d XL |
2112 | hir::ForeignItemKind::Static(ref ty, mutability) => { |
2113 | ForeignStaticItem(Static { type_: ty.clean(cx), mutability, expr: None }) | |
2114 | } | |
fc512014 XL |
2115 | hir::ForeignItemKind::Type => ForeignTypeItem, |
2116 | }; | |
8faf50e0 | 2117 | |
fc512014 | 2118 | Item::from_hir_id_and_parts( |
6a06907d | 2119 | item.hir_id(), |
fc512014 XL |
2120 | Some(renamed.unwrap_or(item.ident.name)), |
2121 | kind, | |
2122 | cx, | |
2123 | ) | |
2124 | }) | |
1a4d82fc JJ |
2125 | } |
2126 | } | |
2127 | ||
fc512014 | 2128 | impl Clean<Item> for (&hir::MacroDef<'_>, Option<Symbol>) { |
6a06907d | 2129 | fn clean(&self, cx: &mut DocContext<'_>) -> Item { |
fc512014 XL |
2130 | let (item, renamed) = self; |
2131 | let name = renamed.unwrap_or(item.ident.name); | |
136023e0 | 2132 | let def_id = item.def_id.to_def_id(); |
0bf4aa26 | 2133 | |
fc512014 | 2134 | Item::from_hir_id_and_parts( |
6a06907d | 2135 | item.hir_id(), |
fc512014 | 2136 | Some(name), |
136023e0 XL |
2137 | MacroItem(Macro { |
2138 | source: display_macro_source(cx, name, &item.ast, def_id, &item.vis), | |
2139 | imported_from: None, | |
2140 | }), | |
fc512014 XL |
2141 | cx, |
2142 | ) | |
9cc50fc6 SL |
2143 | } |
2144 | } | |
2145 | ||
dfeec247 | 2146 | impl Clean<TypeBinding> for hir::TypeBinding<'_> { |
6a06907d | 2147 | fn clean(&self, cx: &mut DocContext<'_>) -> TypeBinding { |
fc512014 | 2148 | TypeBinding { name: self.ident.name, kind: self.kind.clean(cx) } |
dc9dc135 XL |
2149 | } |
2150 | } | |
2151 | ||
dfeec247 | 2152 | impl Clean<TypeBindingKind> for hir::TypeBindingKind<'_> { |
6a06907d | 2153 | fn clean(&self, cx: &mut DocContext<'_>) -> TypeBindingKind { |
dc9dc135 | 2154 | match *self { |
dfeec247 XL |
2155 | hir::TypeBindingKind::Equality { ref ty } => { |
2156 | TypeBindingKind::Equality { ty: ty.clean(cx) } | |
2157 | } | |
74b04a01 XL |
2158 | hir::TypeBindingKind::Constraint { ref bounds } => { |
2159 | TypeBindingKind::Constraint { bounds: bounds.iter().map(|b| b.clean(cx)).collect() } | |
2160 | } | |
1a4d82fc JJ |
2161 | } |
2162 | } | |
2163 | } |