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