diff options
Diffstat (limited to 'src/librustdoc/clean/auto_trait.rs')
| -rw-r--r-- | src/librustdoc/clean/auto_trait.rs | 370 |
1 files changed, 161 insertions, 209 deletions
diff --git a/src/librustdoc/clean/auto_trait.rs b/src/librustdoc/clean/auto_trait.rs index e198b008753..f3b0a683309 100644 --- a/src/librustdoc/clean/auto_trait.rs +++ b/src/librustdoc/clean/auto_trait.rs @@ -10,13 +10,13 @@ use super::*; #[derive(Eq, PartialEq, Hash, Copy, Clone, Debug)] enum RegionTarget<'tcx> { Region(Region<'tcx>), - RegionVid(RegionVid) + RegionVid(RegionVid), } #[derive(Default, Debug, Clone)] struct RegionDeps<'tcx> { larger: FxHashSet<RegionTarget<'tcx>>, - smaller: FxHashSet<RegionTarget<'tcx>> + smaller: FxHashSet<RegionTarget<'tcx>>, } pub struct AutoTraitFinder<'a, 'tcx> { @@ -33,128 +33,117 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> { // FIXME(eddyb) figure out a better way to pass information about // parametrization of `ty` than `param_env_def_id`. - pub fn get_auto_trait_impls( - &self, - ty: Ty<'tcx>, - param_env_def_id: DefId, - ) -> Vec<Item> { + pub fn get_auto_trait_impls(&self, ty: Ty<'tcx>, param_env_def_id: DefId) -> Vec<Item> { let param_env = self.cx.tcx.param_env(param_env_def_id); debug!("get_auto_trait_impls({:?})", ty); let auto_traits = self.cx.auto_traits.iter().cloned(); - auto_traits.filter_map(|trait_def_id| { - let trait_ref = ty::TraitRef { - def_id: trait_def_id, - substs: self.cx.tcx.mk_substs_trait(ty, &[]), - }; - if !self.cx - .generated_synthetics - .borrow_mut() - .insert((ty, trait_def_id)) - { - debug!( - "get_auto_trait_impl_for({:?}): already generated, aborting", - trait_ref - ); - return None; - } + auto_traits + .filter_map(|trait_def_id| { + let trait_ref = ty::TraitRef { + def_id: trait_def_id, + substs: self.cx.tcx.mk_substs_trait(ty, &[]), + }; + if !self.cx.generated_synthetics.borrow_mut().insert((ty, trait_def_id)) { + debug!("get_auto_trait_impl_for({:?}): already generated, aborting", trait_ref); + return None; + } - let result = self.f.find_auto_trait_generics( - ty, - param_env, - trait_def_id, - |infcx, info| { - let region_data = info.region_data; - - let names_map = self.cx.tcx.generics_of(param_env_def_id) - .params - .iter() - .filter_map(|param| match param.kind { - ty::GenericParamDefKind::Lifetime => Some(param.name.to_string()), - _ => None, - }) - .map(|name| (name.clone(), Lifetime(name))) - .collect(); - let lifetime_predicates = - self.handle_lifetimes(®ion_data, &names_map); - let new_generics = self.param_env_to_generics( - infcx.tcx, - param_env_def_id, - info.full_user_env, - lifetime_predicates, - info.vid_to_region, - ); - - debug!( - "find_auto_trait_generics(param_env_def_id={:?}, trait_def_id={:?}): \ + let result = + self.f.find_auto_trait_generics(ty, param_env, trait_def_id, |infcx, info| { + let region_data = info.region_data; + + let names_map = self + .cx + .tcx + .generics_of(param_env_def_id) + .params + .iter() + .filter_map(|param| match param.kind { + ty::GenericParamDefKind::Lifetime => Some(param.name.to_string()), + _ => None, + }) + .map(|name| (name.clone(), Lifetime(name))) + .collect(); + let lifetime_predicates = self.handle_lifetimes(®ion_data, &names_map); + let new_generics = self.param_env_to_generics( + infcx.tcx, + param_env_def_id, + info.full_user_env, + lifetime_predicates, + info.vid_to_region, + ); + + debug!( + "find_auto_trait_generics(param_env_def_id={:?}, trait_def_id={:?}): \ finished with {:?}", - param_env_def_id, trait_def_id, new_generics - ); - - new_generics - }, - ); - - let polarity; - let new_generics = match result { - AutoTraitResult::PositiveImpl(new_generics) => { - polarity = None; - new_generics - } - AutoTraitResult::NegativeImpl => { - polarity = Some(ImplPolarity::Negative); - - // For negative impls, we use the generic params, but *not* the predicates, - // from the original type. Otherwise, the displayed impl appears to be a - // conditional negative impl, when it's really unconditional. - // - // For example, consider the struct Foo<T: Copy>(*mut T). Using - // the original predicates in our impl would cause us to generate - // `impl !Send for Foo<T: Copy>`, which makes it appear that Foo - // implements Send where T is not copy. - // - // Instead, we generate `impl !Send for Foo<T>`, which better - // expresses the fact that `Foo<T>` never implements `Send`, - // regardless of the choice of `T`. - let params = ( - self.cx.tcx.generics_of(param_env_def_id), - ty::GenericPredicates::default(), - ).clean(self.cx).params; - - Generics { - params, - where_predicates: Vec::new(), - } - } - AutoTraitResult::ExplicitImpl => return None, - }; + param_env_def_id, trait_def_id, new_generics + ); + + new_generics + }); - Some(Item { - source: Span::empty(), - name: None, - attrs: Default::default(), - visibility: Inherited, - def_id: self.cx.next_def_id(param_env_def_id.krate), - stability: None, - deprecation: None, - inner: ImplItem(Impl { - unsafety: hir::Unsafety::Normal, - generics: new_generics, - provided_trait_methods: Default::default(), - trait_: Some(trait_ref.clean(self.cx).get_trait_type().unwrap()), - for_: ty.clean(self.cx), - items: Vec::new(), - polarity, - synthetic: true, - blanket_impl: None, - }), + let polarity; + let new_generics = match result { + AutoTraitResult::PositiveImpl(new_generics) => { + polarity = None; + new_generics + } + AutoTraitResult::NegativeImpl => { + polarity = Some(ImplPolarity::Negative); + + // For negative impls, we use the generic params, but *not* the predicates, + // from the original type. Otherwise, the displayed impl appears to be a + // conditional negative impl, when it's really unconditional. + // + // For example, consider the struct Foo<T: Copy>(*mut T). Using + // the original predicates in our impl would cause us to generate + // `impl !Send for Foo<T: Copy>`, which makes it appear that Foo + // implements Send where T is not copy. + // + // Instead, we generate `impl !Send for Foo<T>`, which better + // expresses the fact that `Foo<T>` never implements `Send`, + // regardless of the choice of `T`. + let params = ( + self.cx.tcx.generics_of(param_env_def_id), + ty::GenericPredicates::default(), + ) + .clean(self.cx) + .params; + + Generics { params, where_predicates: Vec::new() } + } + AutoTraitResult::ExplicitImpl => return None, + }; + + Some(Item { + source: Span::empty(), + name: None, + attrs: Default::default(), + visibility: Inherited, + def_id: self.cx.next_def_id(param_env_def_id.krate), + stability: None, + deprecation: None, + inner: ImplItem(Impl { + unsafety: hir::Unsafety::Normal, + generics: new_generics, + provided_trait_methods: Default::default(), + trait_: Some(trait_ref.clean(self.cx).get_trait_type().unwrap()), + for_: ty.clean(self.cx), + items: Vec::new(), + polarity, + synthetic: true, + blanket_impl: None, + }), + }) }) - }).collect() + .collect() } fn get_lifetime( - &self, region: Region<'_>, - names_map: &FxHashMap<String, Lifetime> + &self, + region: Region<'_>, + names_map: &FxHashMap<String, Lifetime>, ) -> Lifetime { self.region_name(region) .map(|name| { @@ -204,27 +193,19 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> { match constraint { &Constraint::VarSubVar(r1, r2) => { { - let deps1 = vid_map - .entry(RegionTarget::RegionVid(r1)) - .or_default(); + let deps1 = vid_map.entry(RegionTarget::RegionVid(r1)).or_default(); deps1.larger.insert(RegionTarget::RegionVid(r2)); } - let deps2 = vid_map - .entry(RegionTarget::RegionVid(r2)) - .or_default(); + let deps2 = vid_map.entry(RegionTarget::RegionVid(r2)).or_default(); deps2.smaller.insert(RegionTarget::RegionVid(r1)); } &Constraint::RegSubVar(region, vid) => { - let deps = vid_map - .entry(RegionTarget::RegionVid(vid)) - .or_default(); + let deps = vid_map.entry(RegionTarget::RegionVid(vid)).or_default(); deps.smaller.insert(RegionTarget::Region(region)); } &Constraint::VarSubReg(vid, region) => { - let deps = vid_map - .entry(RegionTarget::RegionVid(vid)) - .or_default(); + let deps = vid_map.entry(RegionTarget::RegionVid(vid)).or_default(); deps.larger.insert(RegionTarget::Region(region)); } &Constraint::RegSubReg(r1, r2) => { @@ -308,7 +289,10 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> { .iter() .flat_map(|(name, lifetime)| { let empty = Vec::new(); - let bounds: FxHashSet<GenericBound> = finished.get(name).unwrap_or(&empty).iter() + let bounds: FxHashSet<GenericBound> = finished + .get(name) + .unwrap_or(&empty) + .iter() .map(|region| GenericBound::Outlives(self.get_lifetime(region, names_map))) .collect(); @@ -344,7 +328,7 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> { name: name.to_string(), kind: GenericParamDefKind::Lifetime, }) - }, + } &ty::ReVar(_) | &ty::ReEarlyBound(_) | &ty::ReStatic => None, _ => panic!("Unexpected region type {:?}", r), } @@ -373,15 +357,18 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> { ref is_generic, } => { let mut new_path = path.clone(); - let last_segment = new_path.segments.pop() - .expect("segments were empty"); + let last_segment = + new_path.segments.pop().expect("segments were empty"); let (old_input, old_output) = match last_segment.args { GenericArgs::AngleBracketed { args, .. } => { - let types = args.iter().filter_map(|arg| match arg { - GenericArg::Type(ty) => Some(ty.clone()), - _ => None, - }).collect(); + let types = args + .iter() + .filter_map(|arg| match arg { + GenericArg::Type(ty) => Some(ty.clone()), + _ => None, + }) + .collect(); (types, None) } GenericArgs::Parenthesized { inputs, output, .. } => { @@ -396,15 +383,12 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> { ); } - let new_params = GenericArgs::Parenthesized { - inputs: old_input, - output, - }; + let new_params = + GenericArgs::Parenthesized { inputs: old_input, output }; - new_path.segments.push(PathSegment { - name: last_segment.name, - args: new_params, - }); + new_path + .segments + .push(PathSegment { name: last_segment.name, args: new_params }); Type::ResolvedPath { path: new_path, @@ -416,10 +400,7 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> { _ => panic!("Unexpected data: {:?}, {:?}", ty, data), }; bounds.insert(GenericBound::TraitBound( - PolyTrait { - trait_: new_ty, - generic_params: poly_trait.generic_params, - }, + PolyTrait { trait_: new_ty, generic_params: poly_trait.generic_params }, hir::TraitBoundModifier::None, )); } @@ -430,23 +411,16 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> { let mut bounds_vec = bounds.into_iter().collect(); self.sort_where_bounds(&mut bounds_vec); - Some(WherePredicate::BoundPredicate { - ty, - bounds: bounds_vec, - }) + Some(WherePredicate::BoundPredicate { ty, bounds: bounds_vec }) }) .chain( - lifetime_to_bounds - .into_iter() - .filter(|&(_, ref bounds)| !bounds.is_empty()) - .map(|(lifetime, bounds)| { + lifetime_to_bounds.into_iter().filter(|&(_, ref bounds)| !bounds.is_empty()).map( + |(lifetime, bounds)| { let mut bounds_vec = bounds.into_iter().collect(); self.sort_where_bounds(&mut bounds_vec); - WherePredicate::RegionPredicate { - lifetime, - bounds: bounds_vec, - } - }), + WherePredicate::RegionPredicate { lifetime, bounds: bounds_vec } + }, + ), ) .collect() } @@ -476,14 +450,9 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> { // The `Sized` trait must be handled specially, since we only display it when // it is *not* required (i.e., '?Sized') - let sized_trait = self.cx - .tcx - .require_lang_item(lang_items::SizedTraitLangItem, None); + let sized_trait = self.cx.tcx.require_lang_item(lang_items::SizedTraitLangItem, None); - let mut replacer = RegionReplacer { - vid_to_region: &vid_to_region, - tcx, - }; + let mut replacer = RegionReplacer { vid_to_region: &vid_to_region, tcx }; let orig_bounds: FxHashSet<_> = self.cx.tcx.param_env(param_env_def_id).caller_bounds.iter().collect(); @@ -491,20 +460,21 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> { .caller_bounds .iter() .filter(|p| { - !orig_bounds.contains(p) || match p { - &&ty::Predicate::Trait(pred) => pred.def_id() == sized_trait, - _ => false, - } + !orig_bounds.contains(p) + || match p { + &&ty::Predicate::Trait(pred) => pred.def_id() == sized_trait, + _ => false, + } }) .map(|p| { let replaced = p.fold_with(&mut replacer); (replaced.clone(), replaced.clean(self.cx)) }); - let mut generic_params = ( - tcx.generics_of(param_env_def_id), - tcx.explicit_predicates_of(param_env_def_id), - ).clean(self.cx).params; + let mut generic_params = + (tcx.generics_of(param_env_def_id), tcx.explicit_predicates_of(param_env_def_id)) + .clean(self.cx) + .params; let mut has_sized = FxHashSet::default(); let mut ty_to_bounds: FxHashMap<_, FxHashSet<_>> = Default::default(); @@ -545,7 +515,8 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> { if b.is_sized_bound(self.cx) { has_sized.insert(ty.clone()); - } else if !b.get_trait_type() + } else if !b + .get_trait_type() .and_then(|t| { ty_to_traits .get(&ty) @@ -579,30 +550,18 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> { .and_modify(|e| *e = (Some(poly_trait.clone()), e.1.clone())) .or_insert(((Some(poly_trait.clone())), None)); - ty_to_bounds - .entry(ty.clone()) - .or_default(); + ty_to_bounds.entry(ty.clone()).or_default(); } else { - ty_to_bounds - .entry(ty.clone()) - .or_default() - .insert(b.clone()); + ty_to_bounds.entry(ty.clone()).or_default().insert(b.clone()); } } } WherePredicate::RegionPredicate { lifetime, bounds } => { - lifetime_to_bounds - .entry(lifetime) - .or_default() - .extend(bounds); + lifetime_to_bounds.entry(lifetime).or_default().extend(bounds); } WherePredicate::EqPredicate { lhs, rhs } => { match &lhs { - &Type::QPath { - name: ref left_name, - ref self_type, - ref trait_, - } => { + &Type::QPath { name: ref left_name, ref self_type, ref trait_ } => { let ty = &*self_type; match **trait_ { Type::ResolvedPath { @@ -623,11 +582,11 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> { // FIXME: Remove this scope when NLL lands { - let args = - &mut new_trait_path.segments - .last_mut() - .expect("segments were empty") - .args; + let args = &mut new_trait_path + .segments + .last_mut() + .expect("segments were empty") + .args; match args { // Convert somethiung like '<T as Iterator::Item> = u8' @@ -638,9 +597,7 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> { } => { bindings.push(TypeBinding { name: left_name.clone(), - kind: TypeBindingKind::Equality { - ty: rhs, - }, + kind: TypeBindingKind::Equality { ty: rhs }, }); } &mut GenericArgs::Parenthesized { .. } => { @@ -651,14 +608,12 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> { }, ); continue; // If something other than a Fn ends up - // with parenthesis, leave it alone + // with parenthesis, leave it alone } } } - let bounds = ty_to_bounds - .entry(*ty.clone()) - .or_default(); + let bounds = ty_to_bounds.entry(*ty.clone()).or_default(); bounds.insert(GenericBound::TraitBound( PolyTrait { @@ -693,8 +648,7 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> { } _ => panic!( "Unexpected trait {:?} for {:?}", - trait_, - param_env_def_id, + trait_, param_env_def_id, ), } } @@ -725,10 +679,7 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> { self.sort_where_predicates(&mut existing_predicates); - Generics { - params: generic_params, - where_predicates: existing_predicates, - } + Generics { params: generic_params, where_predicates: existing_predicates } } // Ensure that the predicates are in a consistent order. The precise @@ -815,6 +766,7 @@ impl<'a, 'tcx> TypeFolder<'tcx> for RegionReplacer<'a, 'tcx> { (match r { &ty::ReVar(vid) => self.vid_to_region.get(&vid).cloned(), _ => None, - }).unwrap_or_else(|| r.super_fold_with(self)) + }) + .unwrap_or_else(|| r.super_fold_with(self)) } } |
