]> git.lizzy.rs Git - rust.git/blob - src/librustdoc/clean/auto_trait.rs
Add new tests and fix old ones
[rust.git] / src / librustdoc / clean / auto_trait.rs
1 // Copyright 2018 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
4 //
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
10
11 use rustc::hir;
12 use rustc::traits::{self, auto_trait as auto};
13 use rustc::ty::{ToPredicate, TypeFoldable};
14 use rustc::ty::subst::Subst;
15 use rustc::infer::InferOk;
16 use std::fmt::Debug;
17 use syntax_pos::DUMMY_SP;
18
19 use core::DocAccessLevels;
20
21 use super::*;
22
23 pub struct AutoTraitFinder<'a, 'tcx: 'a, 'rcx: 'a> {
24     pub cx: &'a core::DocContext<'a, 'tcx, 'rcx>,
25     pub f: auto::AutoTraitFinder<'a, 'tcx>,
26 }
27
28 impl<'a, 'tcx, 'rcx> AutoTraitFinder<'a, 'tcx, 'rcx> {
29     pub fn new(cx: &'a core::DocContext<'a, 'tcx, 'rcx>) -> Self {
30         let f = auto::AutoTraitFinder::new(&cx.tcx);
31
32         AutoTraitFinder { cx, f }
33     }
34
35     pub fn get_with_def_id(&self, def_id: DefId) -> Vec<Item> {
36         let ty = self.cx.tcx.type_of(def_id);
37
38         let def_ctor: fn(DefId) -> Def = match ty.sty {
39             ty::TyAdt(adt, _) => match adt.adt_kind() {
40                 AdtKind::Struct => Def::Struct,
41                 AdtKind::Enum => Def::Enum,
42                 AdtKind::Union => Def::Union,
43             }
44             ty::TyInt(_) |
45             ty::TyUint(_) |
46             ty::TyFloat(_) |
47             ty::TyStr |
48             ty::TyBool |
49             ty::TyChar => return self.get_auto_trait_impls(def_id, &move |_: DefId| {
50                 match ty.sty {
51                     ty::TyInt(x) => Def::PrimTy(hir::TyInt(x)),
52                     ty::TyUint(x) => Def::PrimTy(hir::TyUint(x)),
53                     ty::TyFloat(x) => Def::PrimTy(hir::TyFloat(x)),
54                     ty::TyStr => Def::PrimTy(hir::TyStr),
55                     ty::TyBool => Def::PrimTy(hir::TyBool),
56                     ty::TyChar => Def::PrimTy(hir::TyChar),
57                     _ => unreachable!(),
58                 }
59             }, None),
60             _ => {
61                 debug!("Unexpected type {:?}", def_id);
62                 return Vec::new()
63             }
64         };
65
66         self.get_auto_trait_impls(def_id, &def_ctor, None)
67     }
68
69     pub fn get_with_node_id(&self, id: ast::NodeId, name: String) -> Vec<Item> {
70         let item = &self.cx.tcx.hir.expect_item(id).node;
71         let did = self.cx.tcx.hir.local_def_id(id);
72
73         let def_ctor = match *item {
74             hir::ItemKind::Struct(_, _) => Def::Struct,
75             hir::ItemKind::Union(_, _) => Def::Union,
76             hir::ItemKind::Enum(_, _) => Def::Enum,
77             _ => panic!("Unexpected type {:?} {:?}", item, id),
78         };
79
80         self.get_auto_trait_impls(did, &def_ctor, Some(name))
81     }
82
83     pub fn get_auto_trait_impls<F>(
84         &self,
85         def_id: DefId,
86         def_ctor: &F,
87         name: Option<String>,
88     ) -> Vec<Item>
89     where F: Fn(DefId) -> Def {
90         if self.cx
91             .tcx
92             .get_attrs(def_id)
93             .lists("doc")
94             .has_word("hidden")
95         {
96             debug!(
97                 "get_auto_trait_impls(def_id={:?}, def_ctor=...): item has doc('hidden'), \
98                  aborting",
99                 def_id
100             );
101             return Vec::new();
102         }
103
104         let tcx = self.cx.tcx;
105         let generics = self.cx.tcx.generics_of(def_id);
106
107         let ty = self.cx.tcx.type_of(def_id);
108         let mut traits = Vec::new();
109         if self.cx.crate_name != Some("core".to_string()) {
110             if let ty::TyAdt(_adt, _) = ty.sty {
111                 let real_name = name.clone().map(|name| Ident::from_str(&name));
112                 let param_env = self.cx.tcx.param_env(def_id);
113                 for &trait_def_id in self.cx.all_traits.iter() {
114                     if !self.cx.access_levels.borrow().is_doc_reachable(trait_def_id) ||
115                        self.cx.generated_synthetics
116                               .borrow_mut()
117                               .get(&(def_id, trait_def_id))
118                               .is_some() {
119                         continue
120                     }
121                     self.cx.tcx.for_each_relevant_impl(trait_def_id, ty, |impl_def_id| {
122                         self.cx.tcx.infer_ctxt().enter(|infcx| {
123                             let generics = infcx.tcx.generics_of(impl_def_id);
124                             let trait_ref = infcx.tcx.impl_trait_ref(impl_def_id).unwrap();
125
126                             if !match infcx.tcx.type_of(impl_def_id).sty {
127                                 ::rustc::ty::TypeVariants::TyParam(_) => true,
128                                 _ => false,
129                             } {
130                                 return
131                             }
132
133                             let substs = infcx.fresh_substs_for_item(DUMMY_SP, def_id);
134                             let ty2 = ty.subst(infcx.tcx, substs);
135                             let param_env = param_env.subst(infcx.tcx, substs);
136
137                             let impl_substs = infcx.fresh_substs_for_item(DUMMY_SP, impl_def_id);
138                             let trait_ref = trait_ref.subst(infcx.tcx, impl_substs);
139
140                             // Require the type the impl is implemented on to match
141                             // our type, and ignore the impl if there was a mismatch.
142                             let cause = traits::ObligationCause::dummy();
143                             let eq_result = infcx.at(&cause, param_env).eq(trait_ref.self_ty(), ty2);
144                             if let Ok(InferOk { value: (), obligations }) = eq_result {
145                                 // FIXME(eddyb) ignoring `obligations` might cause false positives.
146                                 drop(obligations);
147
148                                 let may_apply = infcx.predicate_may_hold(&traits::Obligation::new(
149                                     cause.clone(),
150                                     param_env,
151                                     trait_ref.to_predicate(),
152                                 ));
153                                 if !may_apply {
154                                     return
155                                 }
156                                 self.cx.generated_synthetics.borrow_mut()
157                                                             .insert((def_id, trait_def_id));
158                                 let trait_ = hir::TraitRef {
159                                     path: get_path_for_type(infcx.tcx, trait_def_id, hir::def::Def::Trait),
160                                     ref_id: ast::DUMMY_NODE_ID,
161                                 };
162                                 let provided_trait_methods = infcx.tcx.provided_trait_methods(impl_def_id)
163                                                                       .into_iter()
164                                                                       .map(|meth| meth.ident.to_string())
165                                                                       .collect();
166
167                                 let path = get_path_for_type(self.cx.tcx, def_id, def_ctor);
168                                 let mut segments = path.segments.into_vec();
169                                 let last = segments.pop().unwrap();
170
171                                 segments.push(hir::PathSegment::new(
172                                     real_name.unwrap_or(last.ident),
173                                     self.generics_to_path_params(generics.clone()),
174                                     false,
175                                 ));
176
177                                 let new_path = hir::Path {
178                                     span: path.span,
179                                     def: path.def,
180                                     segments: HirVec::from_vec(segments),
181                                 };
182
183                                 let ty = hir::Ty {
184                                     id: ast::DUMMY_NODE_ID,
185                                     node: hir::Ty_::TyPath(hir::QPath::Resolved(None, P(new_path))),
186                                     span: DUMMY_SP,
187                                     hir_id: hir::DUMMY_HIR_ID,
188                                 };
189
190                                 traits.push(Item {
191                                     source: Span::empty(),
192                                     name: None,
193                                     attrs: Default::default(),
194                                     visibility: None,
195                                     def_id: self.next_def_id(impl_def_id.krate),
196                                     stability: None,
197                                     deprecation: None,
198                                     inner: ImplItem(Impl {
199                                         unsafety: hir::Unsafety::Normal,
200                                         generics: (generics,
201                                                    &tcx.predicates_of(impl_def_id)).clean(self.cx),
202                                         provided_trait_methods,
203                                         trait_: Some(trait_.clean(self.cx)),
204                                         for_: ty.clean(self.cx),
205                                         items: infcx.tcx.associated_items(impl_def_id).collect::<Vec<_>>().clean(self.cx),
206                                         polarity: None,
207                                         synthetic: true,
208                                     }),
209                                 });
210                                 debug!("{:?} => {}", trait_ref, may_apply);
211                             }
212                         });
213                     });
214                 }
215             }
216         }
217
218         debug!(
219             "get_auto_trait_impls(def_id={:?}, def_ctor=..., generics={:?}",
220             def_id, generics
221         );
222         let auto_traits: Vec<_> =
223             self.cx.send_trait
224                           .and_then(|send_trait| {
225                     self.get_auto_trait_impl_for(
226                         def_id,
227                         name.clone(),
228                         generics.clone(),
229                         def_ctor,
230                         send_trait,
231                     )
232                 }).into_iter()
233             .chain(self.get_auto_trait_impl_for(
234                 def_id,
235                 name.clone(),
236                 generics.clone(),
237                 def_ctor,
238                 tcx.require_lang_item(lang_items::SyncTraitLangItem),
239             ).into_iter())
240             .chain(traits.into_iter())
241             .collect();
242
243         debug!(
244             "get_auto_traits: type {:?} auto_traits {:?}",
245             def_id, auto_traits
246         );
247         auto_traits
248     }
249
250     fn get_auto_trait_impl_for<F>(
251         &self,
252         def_id: DefId,
253         name: Option<String>,
254         generics: ty::Generics,
255         def_ctor: &F,
256         trait_def_id: DefId,
257     ) -> Option<Item>
258     where F: Fn(DefId) -> Def {
259         if !self.cx
260             .generated_synthetics
261             .borrow_mut()
262             .insert((def_id, trait_def_id))
263         {
264             debug!(
265                 "get_auto_trait_impl_for(def_id={:?}, generics={:?}, def_ctor=..., \
266                  trait_def_id={:?}): already generated, aborting",
267                 def_id, generics, trait_def_id
268             );
269             return None;
270         }
271
272         let result = self.find_auto_trait_generics(def_id, trait_def_id, &generics);
273
274         if result.is_auto() {
275             let trait_ = hir::TraitRef {
276                 path: get_path_for_type(self.cx.tcx, trait_def_id, hir::def::Def::Trait),
277                 ref_id: ast::DUMMY_NODE_ID,
278             };
279
280             let polarity;
281
282             let new_generics = match result {
283                 AutoTraitResult::PositiveImpl(new_generics) => {
284                     polarity = None;
285                     new_generics
286                 }
287                 AutoTraitResult::NegativeImpl => {
288                     polarity = Some(ImplPolarity::Negative);
289
290                     // For negative impls, we use the generic params, but *not* the predicates,
291                     // from the original type. Otherwise, the displayed impl appears to be a
292                     // conditional negative impl, when it's really unconditional.
293                     //
294                     // For example, consider the struct Foo<T: Copy>(*mut T). Using
295                     // the original predicates in our impl would cause us to generate
296                     // `impl !Send for Foo<T: Copy>`, which makes it appear that Foo
297                     // implements Send where T is not copy.
298                     //
299                     // Instead, we generate `impl !Send for Foo<T>`, which better
300                     // expresses the fact that `Foo<T>` never implements `Send`,
301                     // regardless of the choice of `T`.
302                     let real_generics = (&generics, &Default::default());
303
304                     // Clean the generics, but ignore the '?Sized' bounds generated
305                     // by the `Clean` impl
306                     let clean_generics = real_generics.clean(self.cx);
307
308                     Generics {
309                         params: clean_generics.params,
310                         where_predicates: Vec::new(),
311                     }
312                 }
313                 _ => unreachable!(),
314             };
315
316             let path = get_path_for_type(self.cx.tcx, def_id, def_ctor);
317             let mut segments = path.segments.into_vec();
318             let last = segments.pop().unwrap();
319
320             let real_name = name.map(|name| Ident::from_str(&name));
321
322             segments.push(hir::PathSegment::new(
323                 real_name.unwrap_or(last.ident),
324                 self.generics_to_path_params(generics.clone()),
325                 false,
326             ));
327
328             let new_path = hir::Path {
329                 span: path.span,
330                 def: path.def,
331                 segments: HirVec::from_vec(segments),
332             };
333
334             let ty = hir::Ty {
335                 id: ast::DUMMY_NODE_ID,
336                 node: hir::TyKind::Path(hir::QPath::Resolved(None, P(new_path))),
337                 span: DUMMY_SP,
338                 hir_id: hir::DUMMY_HIR_ID,
339             };
340
341             return Some(Item {
342                 source: Span::empty(),
343                 name: None,
344                 attrs: Default::default(),
345                 visibility: None,
346                 def_id: self.next_def_id(def_id.krate),
347                 stability: None,
348                 deprecation: None,
349                 inner: ImplItem(Impl {
350                     unsafety: hir::Unsafety::Normal,
351                     generics: new_generics,
352                     provided_trait_methods: FxHashSet(),
353                     trait_: Some(trait_.clean(self.cx)),
354                     for_: ty.clean(self.cx),
355                     items: Vec::new(),
356                     polarity,
357                     synthetic: true,
358                 }),
359             });
360         }
361         None
362     }
363
364     fn generics_to_path_params(&self, generics: ty::Generics) -> hir::GenericArgs {
365         let mut args = vec![];
366
367         for param in generics.params.iter() {
368             match param.kind {
369                 ty::GenericParamDefKind::Lifetime => {
370                     let name = if param.name == "" {
371                         hir::ParamName::Plain(keywords::StaticLifetime.ident())
372                     } else {
373                         hir::ParamName::Plain(ast::Ident::from_interned_str(param.name))
374                     };
375
376                     args.push(hir::GenericArg::Lifetime(hir::Lifetime {
377                         id: ast::DUMMY_NODE_ID,
378                         span: DUMMY_SP,
379                         name: hir::LifetimeName::Param(name),
380                     }));
381                 }
382                 ty::GenericParamDefKind::Type {..} => {
383                     args.push(hir::GenericArg::Type(self.ty_param_to_ty(param.clone())));
384                 }
385             }
386         }
387
388         hir::GenericArgs {
389             args: HirVec::from_vec(args),
390             bindings: HirVec::new(),
391             parenthesized: false,
392         }
393     }
394
395     fn ty_param_to_ty(&self, param: ty::GenericParamDef) -> hir::Ty {
396         debug!("ty_param_to_ty({:?}) {:?}", param, param.def_id);
397         hir::Ty {
398             id: ast::DUMMY_NODE_ID,
399             node: hir::TyKind::Path(hir::QPath::Resolved(
400                 None,
401                 P(hir::Path {
402                     span: DUMMY_SP,
403                     def: Def::TyParam(param.def_id),
404                     segments: HirVec::from_vec(vec![
405                         hir::PathSegment::from_ident(Ident::from_interned_str(param.name))
406                     ]),
407                 }),
408             )),
409             span: DUMMY_SP,
410             hir_id: hir::DUMMY_HIR_ID,
411         }
412     }
413
414     fn find_auto_trait_generics(
415         &self,
416         did: DefId,
417         trait_did: DefId,
418         generics: &ty::Generics,
419     ) -> AutoTraitResult {
420         match self.f.find_auto_trait_generics(did, trait_did, generics,
421                 |infcx, mut info| {
422                     let region_data = info.region_data;
423                     let names_map =
424                         info.names_map
425                             .drain()
426                             .map(|name| (name.clone(), Lifetime(name)))
427                             .collect();
428                     let lifetime_predicates =
429                         self.handle_lifetimes(&region_data, &names_map);
430                     let new_generics = self.param_env_to_generics(
431                         infcx.tcx,
432                         did,
433                         info.full_user_env,
434                         generics.clone(),
435                         lifetime_predicates,
436                         info.vid_to_region,
437                     );
438
439                     debug!(
440                         "find_auto_trait_generics(did={:?}, trait_did={:?}, generics={:?}): \
441                          finished with {:?}",
442                         did, trait_did, generics, new_generics
443                     );
444
445                     new_generics
446                 }) {
447             auto::AutoTraitResult::ExplicitImpl => AutoTraitResult::ExplicitImpl,
448             auto::AutoTraitResult::NegativeImpl => AutoTraitResult::NegativeImpl,
449             auto::AutoTraitResult::PositiveImpl(res) => AutoTraitResult::PositiveImpl(res),
450         }
451     }
452
453     fn get_lifetime(&self, region: Region, names_map: &FxHashMap<String, Lifetime>) -> Lifetime {
454         self.region_name(region)
455             .map(|name| {
456                 names_map.get(&name).unwrap_or_else(|| {
457                     panic!("Missing lifetime with name {:?} for {:?}", name, region)
458                 })
459             })
460             .unwrap_or(&Lifetime::statik())
461             .clone()
462     }
463
464     fn region_name(&self, region: Region) -> Option<String> {
465         match region {
466             &ty::ReEarlyBound(r) => Some(r.name.to_string()),
467             _ => None,
468         }
469     }
470
471     // This method calculates two things: Lifetime constraints of the form 'a: 'b,
472     // and region constraints of the form ReVar: 'a
473     //
474     // This is essentially a simplified version of lexical_region_resolve. However,
475     // handle_lifetimes determines what *needs be* true in order for an impl to hold.
476     // lexical_region_resolve, along with much of the rest of the compiler, is concerned
477     // with determining if a given set up constraints/predicates *are* met, given some
478     // starting conditions (e.g. user-provided code). For this reason, it's easier
479     // to perform the calculations we need on our own, rather than trying to make
480     // existing inference/solver code do what we want.
481     fn handle_lifetimes<'cx>(
482         &self,
483         regions: &RegionConstraintData<'cx>,
484         names_map: &FxHashMap<String, Lifetime>,
485     ) -> Vec<WherePredicate> {
486         // Our goal is to 'flatten' the list of constraints by eliminating
487         // all intermediate RegionVids. At the end, all constraints should
488         // be between Regions (aka region variables). This gives us the information
489         // we need to create the Generics.
490         let mut finished = FxHashMap();
491
492         let mut vid_map: FxHashMap<RegionTarget, RegionDeps> = FxHashMap();
493
494         // Flattening is done in two parts. First, we insert all of the constraints
495         // into a map. Each RegionTarget (either a RegionVid or a Region) maps
496         // to its smaller and larger regions. Note that 'larger' regions correspond
497         // to sub-regions in Rust code (e.g. in 'a: 'b, 'a is the larger region).
498         for constraint in regions.constraints.keys() {
499             match constraint {
500                 &Constraint::VarSubVar(r1, r2) => {
501                     {
502                         let deps1 = vid_map
503                             .entry(RegionTarget::RegionVid(r1))
504                             .or_insert_with(|| Default::default());
505                         deps1.larger.insert(RegionTarget::RegionVid(r2));
506                     }
507
508                     let deps2 = vid_map
509                         .entry(RegionTarget::RegionVid(r2))
510                         .or_insert_with(|| Default::default());
511                     deps2.smaller.insert(RegionTarget::RegionVid(r1));
512                 }
513                 &Constraint::RegSubVar(region, vid) => {
514                     let deps = vid_map
515                         .entry(RegionTarget::RegionVid(vid))
516                         .or_insert_with(|| Default::default());
517                     deps.smaller.insert(RegionTarget::Region(region));
518                 }
519                 &Constraint::VarSubReg(vid, region) => {
520                     let deps = vid_map
521                         .entry(RegionTarget::RegionVid(vid))
522                         .or_insert_with(|| Default::default());
523                     deps.larger.insert(RegionTarget::Region(region));
524                 }
525                 &Constraint::RegSubReg(r1, r2) => {
526                     // The constraint is already in the form that we want, so we're done with it
527                     // Desired order is 'larger, smaller', so flip then
528                     if self.region_name(r1) != self.region_name(r2) {
529                         finished
530                             .entry(self.region_name(r2).unwrap())
531                             .or_insert_with(|| Vec::new())
532                             .push(r1);
533                     }
534                 }
535             }
536         }
537
538         // Here, we 'flatten' the map one element at a time.
539         // All of the element's sub and super regions are connected
540         // to each other. For example, if we have a graph that looks like this:
541         //
542         // (A, B) - C - (D, E)
543         // Where (A, B) are subregions, and (D,E) are super-regions
544         //
545         // then after deleting 'C', the graph will look like this:
546         //  ... - A - (D, E ...)
547         //  ... - B - (D, E, ...)
548         //  (A, B, ...) - D - ...
549         //  (A, B, ...) - E - ...
550         //
551         //  where '...' signifies the existing sub and super regions of an entry
552         //  When two adjacent ty::Regions are encountered, we've computed a final
553         //  constraint, and add it to our list. Since we make sure to never re-add
554         //  deleted items, this process will always finish.
555         while !vid_map.is_empty() {
556             let target = vid_map.keys().next().expect("Keys somehow empty").clone();
557             let deps = vid_map.remove(&target).expect("Entry somehow missing");
558
559             for smaller in deps.smaller.iter() {
560                 for larger in deps.larger.iter() {
561                     match (smaller, larger) {
562                         (&RegionTarget::Region(r1), &RegionTarget::Region(r2)) => {
563                             if self.region_name(r1) != self.region_name(r2) {
564                                 finished
565                                     .entry(self.region_name(r2).unwrap())
566                                     .or_insert_with(|| Vec::new())
567                                     .push(r1) // Larger, smaller
568                             }
569                         }
570                         (&RegionTarget::RegionVid(_), &RegionTarget::Region(_)) => {
571                             if let Entry::Occupied(v) = vid_map.entry(*smaller) {
572                                 let smaller_deps = v.into_mut();
573                                 smaller_deps.larger.insert(*larger);
574                                 smaller_deps.larger.remove(&target);
575                             }
576                         }
577                         (&RegionTarget::Region(_), &RegionTarget::RegionVid(_)) => {
578                             if let Entry::Occupied(v) = vid_map.entry(*larger) {
579                                 let deps = v.into_mut();
580                                 deps.smaller.insert(*smaller);
581                                 deps.smaller.remove(&target);
582                             }
583                         }
584                         (&RegionTarget::RegionVid(_), &RegionTarget::RegionVid(_)) => {
585                             if let Entry::Occupied(v) = vid_map.entry(*smaller) {
586                                 let smaller_deps = v.into_mut();
587                                 smaller_deps.larger.insert(*larger);
588                                 smaller_deps.larger.remove(&target);
589                             }
590
591                             if let Entry::Occupied(v) = vid_map.entry(*larger) {
592                                 let larger_deps = v.into_mut();
593                                 larger_deps.smaller.insert(*smaller);
594                                 larger_deps.smaller.remove(&target);
595                             }
596                         }
597                     }
598                 }
599             }
600         }
601
602         let lifetime_predicates = names_map
603             .iter()
604             .flat_map(|(name, lifetime)| {
605                 let empty = Vec::new();
606                 let bounds: FxHashSet<GenericBound> = finished.get(name).unwrap_or(&empty).iter()
607                     .map(|region| GenericBound::Outlives(self.get_lifetime(region, names_map)))
608                     .collect();
609
610                 if bounds.is_empty() {
611                     return None;
612                 }
613                 Some(WherePredicate::RegionPredicate {
614                     lifetime: lifetime.clone(),
615                     bounds: bounds.into_iter().collect(),
616                 })
617             })
618             .collect();
619
620         lifetime_predicates
621     }
622
623     fn extract_for_generics<'b, 'c, 'd>(
624         &self,
625         tcx: TyCtxt<'b, 'c, 'd>,
626         pred: ty::Predicate<'d>,
627     ) -> FxHashSet<GenericParamDef> {
628         pred.walk_tys()
629             .flat_map(|t| {
630                 let mut regions = FxHashSet();
631                 tcx.collect_regions(&t, &mut regions);
632
633                 regions.into_iter().flat_map(|r| {
634                     match r {
635                         // We only care about late bound regions, as we need to add them
636                         // to the 'for<>' section
637                         &ty::ReLateBound(_, ty::BoundRegion::BrNamed(_, name)) => {
638                             Some(GenericParamDef {
639                                 name: name.to_string(),
640                                 kind: GenericParamDefKind::Lifetime,
641                             })
642                         }
643                         &ty::ReVar(_) | &ty::ReEarlyBound(_) => None,
644                         _ => panic!("Unexpected region type {:?}", r),
645                     }
646                 })
647             })
648             .collect()
649     }
650
651     fn make_final_bounds<'b, 'c, 'cx>(
652         &self,
653         ty_to_bounds: FxHashMap<Type, FxHashSet<GenericBound>>,
654         ty_to_fn: FxHashMap<Type, (Option<PolyTrait>, Option<Type>)>,
655         lifetime_to_bounds: FxHashMap<Lifetime, FxHashSet<GenericBound>>,
656     ) -> Vec<WherePredicate> {
657         ty_to_bounds
658             .into_iter()
659             .flat_map(|(ty, mut bounds)| {
660                 if let Some(data) = ty_to_fn.get(&ty) {
661                     let (poly_trait, output) =
662                         (data.0.as_ref().unwrap().clone(), data.1.as_ref().cloned());
663                     let new_ty = match &poly_trait.trait_ {
664                         &Type::ResolvedPath {
665                             ref path,
666                             ref typarams,
667                             ref did,
668                             ref is_generic,
669                         } => {
670                             let mut new_path = path.clone();
671                             let last_segment = new_path.segments.pop().unwrap();
672
673                             let (old_input, old_output) = match last_segment.args {
674                                 GenericArgs::AngleBracketed { types, .. } => (types, None),
675                                 GenericArgs::Parenthesized { inputs, output, .. } => {
676                                     (inputs, output)
677                                 }
678                             };
679
680                             if old_output.is_some() && old_output != output {
681                                 panic!(
682                                     "Output mismatch for {:?} {:?} {:?}",
683                                     ty, old_output, data.1
684                                 );
685                             }
686
687                             let new_params = GenericArgs::Parenthesized {
688                                 inputs: old_input,
689                                 output,
690                             };
691
692                             new_path.segments.push(PathSegment {
693                                 name: last_segment.name,
694                                 args: new_params,
695                             });
696
697                             Type::ResolvedPath {
698                                 path: new_path,
699                                 typarams: typarams.clone(),
700                                 did: did.clone(),
701                                 is_generic: *is_generic,
702                             }
703                         }
704                         _ => panic!("Unexpected data: {:?}, {:?}", ty, data),
705                     };
706                     bounds.insert(GenericBound::TraitBound(
707                         PolyTrait {
708                             trait_: new_ty,
709                             generic_params: poly_trait.generic_params,
710                         },
711                         hir::TraitBoundModifier::None,
712                     ));
713                 }
714                 if bounds.is_empty() {
715                     return None;
716                 }
717
718                 let mut bounds_vec = bounds.into_iter().collect();
719                 self.sort_where_bounds(&mut bounds_vec);
720
721                 Some(WherePredicate::BoundPredicate {
722                     ty,
723                     bounds: bounds_vec,
724                 })
725             })
726             .chain(
727                 lifetime_to_bounds
728                     .into_iter()
729                     .filter(|&(_, ref bounds)| !bounds.is_empty())
730                     .map(|(lifetime, bounds)| {
731                         let mut bounds_vec = bounds.into_iter().collect();
732                         self.sort_where_bounds(&mut bounds_vec);
733                         WherePredicate::RegionPredicate {
734                             lifetime,
735                             bounds: bounds_vec,
736                         }
737                     }),
738             )
739             .collect()
740     }
741
742     // Converts the calculated ParamEnv and lifetime information to a clean::Generics, suitable for
743     // display on the docs page. Cleaning the Predicates produces sub-optimal WherePredicate's,
744     // so we fix them up:
745     //
746     // * Multiple bounds for the same type are coalesced into one: e.g. 'T: Copy', 'T: Debug'
747     // becomes 'T: Copy + Debug'
748     // * Fn bounds are handled specially - instead of leaving it as 'T: Fn(), <T as Fn::Output> =
749     // K', we use the dedicated syntax 'T: Fn() -> K'
750     // * We explcitly add a '?Sized' bound if we didn't find any 'Sized' predicates for a type
751     fn param_env_to_generics<'b, 'c, 'cx>(
752         &self,
753         tcx: TyCtxt<'b, 'c, 'cx>,
754         did: DefId,
755         param_env: ty::ParamEnv<'cx>,
756         type_generics: ty::Generics,
757         mut existing_predicates: Vec<WherePredicate>,
758         vid_to_region: FxHashMap<ty::RegionVid, ty::Region<'cx>>,
759     ) -> Generics {
760         debug!(
761             "param_env_to_generics(did={:?}, param_env={:?}, type_generics={:?}, \
762              existing_predicates={:?})",
763             did, param_env, type_generics, existing_predicates
764         );
765
766         // The `Sized` trait must be handled specially, since we only only display it when
767         // it is *not* required (i.e. '?Sized')
768         let sized_trait = self.cx
769             .tcx
770             .require_lang_item(lang_items::SizedTraitLangItem);
771
772         let mut replacer = RegionReplacer {
773             vid_to_region: &vid_to_region,
774             tcx,
775         };
776
777         let orig_bounds: FxHashSet<_> = self.cx.tcx.param_env(did).caller_bounds.iter().collect();
778         let clean_where_predicates = param_env
779             .caller_bounds
780             .iter()
781             .filter(|p| {
782                 !orig_bounds.contains(p) || match p {
783                     &&ty::Predicate::Trait(pred) => pred.def_id() == sized_trait,
784                     _ => false,
785                 }
786             })
787             .map(|p| {
788                 let replaced = p.fold_with(&mut replacer);
789                 (replaced.clone(), replaced.clean(self.cx))
790             });
791
792         let full_generics = (&type_generics, &tcx.predicates_of(did));
793         let Generics {
794             params: mut generic_params,
795             ..
796         } = full_generics.clean(self.cx);
797
798         let mut has_sized = FxHashSet();
799         let mut ty_to_bounds = FxHashMap();
800         let mut lifetime_to_bounds = FxHashMap();
801         let mut ty_to_traits: FxHashMap<Type, FxHashSet<Type>> = FxHashMap();
802
803         let mut ty_to_fn: FxHashMap<Type, (Option<PolyTrait>, Option<Type>)> = FxHashMap();
804
805         for (orig_p, p) in clean_where_predicates {
806             match p {
807                 WherePredicate::BoundPredicate { ty, mut bounds } => {
808                     // Writing a projection trait bound of the form
809                     // <T as Trait>::Name : ?Sized
810                     // is illegal, because ?Sized bounds can only
811                     // be written in the (here, nonexistant) definition
812                     // of the type.
813                     // Therefore, we make sure that we never add a ?Sized
814                     // bound for projections
815                     match &ty {
816                         &Type::QPath { .. } => {
817                             has_sized.insert(ty.clone());
818                         }
819                         _ => {}
820                     }
821
822                     if bounds.is_empty() {
823                         continue;
824                     }
825
826                     let mut for_generics = self.extract_for_generics(tcx, orig_p.clone());
827
828                     assert!(bounds.len() == 1);
829                     let mut b = bounds.pop().unwrap();
830
831                     if b.is_sized_bound(self.cx) {
832                         has_sized.insert(ty.clone());
833                     } else if !b.get_trait_type()
834                         .and_then(|t| {
835                             ty_to_traits
836                                 .get(&ty)
837                                 .map(|bounds| bounds.contains(&strip_type(t.clone())))
838                         })
839                         .unwrap_or(false)
840                     {
841                         // If we've already added a projection bound for the same type, don't add
842                         // this, as it would be a duplicate
843
844                         // Handle any 'Fn/FnOnce/FnMut' bounds specially,
845                         // as we want to combine them with any 'Output' qpaths
846                         // later
847
848                         let is_fn = match &mut b {
849                             &mut GenericBound::TraitBound(ref mut p, _) => {
850                                 // Insert regions into the for_generics hash map first, to ensure
851                                 // that we don't end up with duplicate bounds (e.g. for<'b, 'b>)
852                                 for_generics.extend(p.generic_params.clone());
853                                 p.generic_params = for_generics.into_iter().collect();
854                                 self.is_fn_ty(&tcx, &p.trait_)
855                             }
856                             _ => false,
857                         };
858
859                         let poly_trait = b.get_poly_trait().unwrap();
860
861                         if is_fn {
862                             ty_to_fn
863                                 .entry(ty.clone())
864                                 .and_modify(|e| *e = (Some(poly_trait.clone()), e.1.clone()))
865                                 .or_insert(((Some(poly_trait.clone())), None));
866
867                             ty_to_bounds
868                                 .entry(ty.clone())
869                                 .or_insert_with(|| FxHashSet());
870                         } else {
871                             ty_to_bounds
872                                 .entry(ty.clone())
873                                 .or_insert_with(|| FxHashSet())
874                                 .insert(b.clone());
875                         }
876                     }
877                 }
878                 WherePredicate::RegionPredicate { lifetime, bounds } => {
879                     lifetime_to_bounds
880                         .entry(lifetime)
881                         .or_insert_with(|| FxHashSet())
882                         .extend(bounds);
883                 }
884                 WherePredicate::EqPredicate { lhs, rhs } => {
885                     match &lhs {
886                         &Type::QPath {
887                             name: ref left_name,
888                             ref self_type,
889                             ref trait_,
890                         } => {
891                             let ty = &*self_type;
892                             match **trait_ {
893                                 Type::ResolvedPath {
894                                     path: ref trait_path,
895                                     ref typarams,
896                                     ref did,
897                                     ref is_generic,
898                                 } => {
899                                     let mut new_trait_path = trait_path.clone();
900
901                                     if self.is_fn_ty(&tcx, trait_) && left_name == FN_OUTPUT_NAME {
902                                         ty_to_fn
903                                             .entry(*ty.clone())
904                                             .and_modify(|e| *e = (e.0.clone(), Some(rhs.clone())))
905                                             .or_insert((None, Some(rhs)));
906                                         continue;
907                                     }
908
909                                     // FIXME: Remove this scope when NLL lands
910                                     {
911                                         let args =
912                                             &mut new_trait_path.segments.last_mut().unwrap().args;
913
914                                         match args {
915                                             // Convert somethiung like '<T as Iterator::Item> = u8'
916                                             // to 'T: Iterator<Item=u8>'
917                                             &mut GenericArgs::AngleBracketed {
918                                                 ref mut bindings,
919                                                 ..
920                                             } => {
921                                                 bindings.push(TypeBinding {
922                                                     name: left_name.clone(),
923                                                     ty: rhs,
924                                                 });
925                                             }
926                                             &mut GenericArgs::Parenthesized { .. } => {
927                                                 existing_predicates.push(
928                                                     WherePredicate::EqPredicate {
929                                                         lhs: lhs.clone(),
930                                                         rhs,
931                                                     },
932                                                 );
933                                                 continue; // If something other than a Fn ends up
934                                                           // with parenthesis, leave it alone
935                                             }
936                                         }
937                                     }
938
939                                     let bounds = ty_to_bounds
940                                         .entry(*ty.clone())
941                                         .or_insert_with(|| FxHashSet());
942
943                                     bounds.insert(GenericBound::TraitBound(
944                                         PolyTrait {
945                                             trait_: Type::ResolvedPath {
946                                                 path: new_trait_path,
947                                                 typarams: typarams.clone(),
948                                                 did: did.clone(),
949                                                 is_generic: *is_generic,
950                                             },
951                                             generic_params: Vec::new(),
952                                         },
953                                         hir::TraitBoundModifier::None,
954                                     ));
955
956                                     // Remove any existing 'plain' bound (e.g. 'T: Iterator`) so
957                                     // that we don't see a
958                                     // duplicate bound like `T: Iterator + Iterator<Item=u8>`
959                                     // on the docs page.
960                                     bounds.remove(&GenericBound::TraitBound(
961                                         PolyTrait {
962                                             trait_: *trait_.clone(),
963                                             generic_params: Vec::new(),
964                                         },
965                                         hir::TraitBoundModifier::None,
966                                     ));
967                                     // Avoid creating any new duplicate bounds later in the outer
968                                     // loop
969                                     ty_to_traits
970                                         .entry(*ty.clone())
971                                         .or_insert_with(|| FxHashSet())
972                                         .insert(*trait_.clone());
973                                 }
974                                 _ => panic!("Unexpected trait {:?} for {:?}", trait_, did),
975                             }
976                         }
977                         _ => panic!("Unexpected LHS {:?} for {:?}", lhs, did),
978                     }
979                 }
980             };
981         }
982
983         let final_bounds = self.make_final_bounds(ty_to_bounds, ty_to_fn, lifetime_to_bounds);
984
985         existing_predicates.extend(final_bounds);
986
987         for param in generic_params.iter_mut() {
988             match param.kind {
989                 GenericParamDefKind::Type { ref mut default, ref mut bounds, .. } => {
990                     // We never want something like `impl<T=Foo>`.
991                     default.take();
992                     let generic_ty = Type::Generic(param.name.clone());
993                     if !has_sized.contains(&generic_ty) {
994                         bounds.insert(0, GenericBound::maybe_sized(self.cx));
995                     }
996                 }
997                 GenericParamDefKind::Lifetime => {}
998             }
999         }
1000
1001         self.sort_where_predicates(&mut existing_predicates);
1002
1003         Generics {
1004             params: generic_params,
1005             where_predicates: existing_predicates,
1006         }
1007     }
1008
1009     // Ensure that the predicates are in a consistent order. The precise
1010     // ordering doesn't actually matter, but it's important that
1011     // a given set of predicates always appears in the same order -
1012     // both for visual consistency between 'rustdoc' runs, and to
1013     // make writing tests much easier
1014     #[inline]
1015     fn sort_where_predicates(&self, mut predicates: &mut Vec<WherePredicate>) {
1016         // We should never have identical bounds - and if we do,
1017         // they're visually identical as well. Therefore, using
1018         // an unstable sort is fine.
1019         self.unstable_debug_sort(&mut predicates);
1020     }
1021
1022     // Ensure that the bounds are in a consistent order. The precise
1023     // ordering doesn't actually matter, but it's important that
1024     // a given set of bounds always appears in the same order -
1025     // both for visual consistency between 'rustdoc' runs, and to
1026     // make writing tests much easier
1027     #[inline]
1028     fn sort_where_bounds(&self, mut bounds: &mut Vec<GenericBound>) {
1029         // We should never have identical bounds - and if we do,
1030         // they're visually identical as well. Therefore, using
1031         // an unstable sort is fine.
1032         self.unstable_debug_sort(&mut bounds);
1033     }
1034
1035     // This might look horrendously hacky, but it's actually not that bad.
1036     //
1037     // For performance reasons, we use several different FxHashMaps
1038     // in the process of computing the final set of where predicates.
1039     // However, the iteration order of a HashMap is completely unspecified.
1040     // In fact, the iteration of an FxHashMap can even vary between platforms,
1041     // since FxHasher has different behavior for 32-bit and 64-bit platforms.
1042     //
1043     // Obviously, it's extremely undesireable for documentation rendering
1044     // to be depndent on the platform it's run on. Apart from being confusing
1045     // to end users, it makes writing tests much more difficult, as predicates
1046     // can appear in any order in the final result.
1047     //
1048     // To solve this problem, we sort WherePredicates and GenericBounds
1049     // by their Debug string. The thing to keep in mind is that we don't really
1050     // care what the final order is - we're synthesizing an impl or bound
1051     // ourselves, so any order can be considered equally valid. By sorting the
1052     // predicates and bounds, however, we ensure that for a given codebase, all
1053     // auto-trait impls always render in exactly the same way.
1054     //
1055     // Using the Debug impementation for sorting prevents us from needing to
1056     // write quite a bit of almost entirely useless code (e.g. how should two
1057     // Types be sorted relative to each other). It also allows us to solve the
1058     // problem for both WherePredicates and GenericBounds at the same time. This
1059     // approach is probably somewhat slower, but the small number of items
1060     // involved (impls rarely have more than a few bounds) means that it
1061     // shouldn't matter in practice.
1062     fn unstable_debug_sort<T: Debug>(&self, vec: &mut Vec<T>) {
1063         vec.sort_by_cached_key(|x| format!("{:?}", x))
1064     }
1065
1066     fn is_fn_ty(&self, tcx: &TyCtxt, ty: &Type) -> bool {
1067         match &ty {
1068             &&Type::ResolvedPath { ref did, .. } => {
1069                 *did == tcx.require_lang_item(lang_items::FnTraitLangItem)
1070                     || *did == tcx.require_lang_item(lang_items::FnMutTraitLangItem)
1071                     || *did == tcx.require_lang_item(lang_items::FnOnceTraitLangItem)
1072             }
1073             _ => false,
1074         }
1075     }
1076
1077     // This is an ugly hack, but it's the simplest way to handle synthetic impls without greatly
1078     // refactoring either librustdoc or librustc. In particular, allowing new DefIds to be
1079     // registered after the AST is constructed would require storing the defid mapping in a
1080     // RefCell, decreasing the performance for normal compilation for very little gain.
1081     //
1082     // Instead, we construct 'fake' def ids, which start immediately after the last DefId in
1083     // DefIndexAddressSpace::Low. In the Debug impl for clean::Item, we explicitly check for fake
1084     // def ids, as we'll end up with a panic if we use the DefId Debug impl for fake DefIds
1085     fn next_def_id(&self, crate_num: CrateNum) -> DefId {
1086         let start_def_id = {
1087             let next_id = if crate_num == LOCAL_CRATE {
1088                 self.cx
1089                     .tcx
1090                     .hir
1091                     .definitions()
1092                     .def_path_table()
1093                     .next_id(DefIndexAddressSpace::Low)
1094             } else {
1095                 self.cx
1096                     .cstore
1097                     .def_path_table(crate_num)
1098                     .next_id(DefIndexAddressSpace::Low)
1099             };
1100
1101             DefId {
1102                 krate: crate_num,
1103                 index: next_id,
1104             }
1105         };
1106
1107         let mut fake_ids = self.cx.fake_def_ids.borrow_mut();
1108
1109         let def_id = fake_ids.entry(crate_num).or_insert(start_def_id).clone();
1110         fake_ids.insert(
1111             crate_num,
1112             DefId {
1113                 krate: crate_num,
1114                 index: DefIndex::from_array_index(
1115                     def_id.index.as_array_index() + 1,
1116                     def_id.index.address_space(),
1117                 ),
1118             },
1119         );
1120
1121         MAX_DEF_ID.with(|m| {
1122             m.borrow_mut()
1123                 .entry(def_id.krate.clone())
1124                 .or_insert(start_def_id);
1125         });
1126
1127         self.cx.all_fake_def_ids.borrow_mut().insert(def_id);
1128
1129         def_id.clone()
1130     }
1131 }
1132
1133 // Replaces all ReVars in a type with ty::Region's, using the provided map
1134 struct RegionReplacer<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> {
1135     vid_to_region: &'a FxHashMap<ty::RegionVid, ty::Region<'tcx>>,
1136     tcx: TyCtxt<'a, 'gcx, 'tcx>,
1137 }
1138
1139 impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for RegionReplacer<'a, 'gcx, 'tcx> {
1140     fn tcx<'b>(&'b self) -> TyCtxt<'b, 'gcx, 'tcx> {
1141         self.tcx
1142     }
1143
1144     fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
1145         (match r {
1146             &ty::ReVar(vid) => self.vid_to_region.get(&vid).cloned(),
1147             _ => None,
1148         }).unwrap_or_else(|| r.super_fold_with(self))
1149     }
1150 }