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