about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/librustc/traits/auto_trait.rs397
1 files changed, 199 insertions, 198 deletions
diff --git a/src/librustc/traits/auto_trait.rs b/src/librustc/traits/auto_trait.rs
index 2ee22d494e1..7e4d4505022 100644
--- a/src/librustc/traits/auto_trait.rs
+++ b/src/librustc/traits/auto_trait.rs
@@ -25,13 +25,13 @@ use ty::fold::TypeFolder;
 #[derive(Eq, PartialEq, Hash, Copy, Clone, Debug)]
 pub enum RegionTarget<'tcx> {
     Region(Region<'tcx>),
-    RegionVid(RegionVid)
+    RegionVid(RegionVid),
 }
 
 #[derive(Default, Debug, Clone)]
 pub struct RegionDeps<'tcx> {
     larger: FxHashSet<RegionTarget<'tcx>>,
-    smaller: FxHashSet<RegionTarget<'tcx>>
+    smaller: FxHashSet<RegionTarget<'tcx>>,
 }
 
 pub enum AutoTraitResult<A> {
@@ -43,7 +43,8 @@ pub enum AutoTraitResult<A> {
 impl<A> AutoTraitResult<A> {
     fn is_auto(&self) -> bool {
         match *self {
-            AutoTraitResult::PositiveImpl(_) | AutoTraitResult::NegativeImpl => true,
+            AutoTraitResult::PositiveImpl(_) |
+            AutoTraitResult::NegativeImpl => true,
             _ => false,
         }
     }
@@ -65,14 +66,17 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> {
         AutoTraitFinder { tcx }
     }
 
-    pub fn find_auto_trait_generics<A>(
-        &self,
-        did: DefId,
-        trait_did: DefId,
-        generics: &ty::Generics,
-        auto_trait_callback: impl for<'i> Fn(&InferCtxt<'_, 'tcx, 'i>, AutoTraitInfo<'i>) -> A)
-        -> AutoTraitResult<A>
-    {
+    /// Determine whether an auto trait is implemented for a type, and if this is the case if
+    /// non-trivial bounds need to be fulfilled, invoke a callback to compute a value representing
+    /// these in a fashion suitable for the caller.
+    pub fn find_auto_trait_generics<A>(&self,
+                                       did: DefId,
+                                       trait_did: DefId,
+                                       generics: &ty::Generics,
+                                       auto_trait_callback:
+                                           impl for<'i> Fn(&InferCtxt<'_, 'tcx, 'i>,
+                                                           AutoTraitInfo<'i>) -> A)
+                                       -> AutoTraitResult<A> {
         let tcx = self.tcx;
         let ty = self.tcx.type_of(did);
 
@@ -85,32 +89,33 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> {
 
         let trait_pred = ty::Binder::bind(trait_ref);
 
-        let bail_out = tcx.infer_ctxt().enter(|infcx| {
-            let mut selcx = SelectionContext::with_negative(&infcx, true);
-            let result = selcx.select(&Obligation::new(
-                ObligationCause::dummy(),
-                orig_params,
-                trait_pred.to_poly_trait_predicate(),
-            ));
-            match result {
-                Ok(Some(Vtable::VtableImpl(_))) => {
-                    debug!(
-                        "find_auto_trait_generics(did={:?}, trait_did={:?}, generics={:?}): \
+        let bail_out = tcx.infer_ctxt()
+            .enter(|infcx| {
+                let mut selcx = SelectionContext::with_negative(&infcx, true);
+                let result =
+                    selcx.select(&Obligation::new(ObligationCause::dummy(),
+                                                  orig_params,
+                                                  trait_pred.to_poly_trait_predicate()));
+                match result {
+                    Ok(Some(Vtable::VtableImpl(_))) => {
+                        debug!("find_auto_trait_generics(did={:?}, trait_did={:?}, generics={:?}): \
                          manual impl found, bailing out",
-                        did, trait_did, generics
-                    );
-                    return true;
-                }
-                _ => return false,
-            };
-        });
+                               did,
+                               trait_did,
+                               generics);
+                        return true;
+                    }
+                    _ => return false,
+                };
+            });
 
         // If an explicit impl exists, it always takes priority over an auto impl
         if bail_out {
             return AutoTraitResult::ExplicitImpl;
         }
 
-        return tcx.infer_ctxt().enter(|mut infcx| {
+        return tcx.infer_ctxt()
+                   .enter(|mut infcx| {
             let mut fresh_preds = FxHashSet();
 
             // Due to the way projections are handled by SelectionContext, we need to run
@@ -146,60 +151,59 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> {
             // traits::project will see that 'T: SomeTrait' is in our ParamEnv, allowing
             // SelectionContext to return it back to us.
 
-            let (new_env, user_env) = match self.evaluate_predicates(
-                &mut infcx,
-                did,
-                trait_did,
-                ty,
-                orig_params.clone(),
-                orig_params,
-                &mut fresh_preds,
-                false,
-            ) {
-                Some(e) => e,
-                None => return AutoTraitResult::NegativeImpl,
-            };
-
-            let (full_env, full_user_env) = self.evaluate_predicates(
-                &mut infcx,
-                did,
-                trait_did,
-                ty,
-                new_env.clone(),
-                user_env,
-                &mut fresh_preds,
-                true,
-            ).unwrap_or_else(|| {
-                panic!(
-                    "Failed to fully process: {:?} {:?} {:?}",
-                    ty, trait_did, orig_params
-                )
-            });
-
-            debug!(
-                "find_auto_trait_generics(did={:?}, trait_did={:?}, generics={:?}): fulfilling \
+            let (new_env, user_env) =
+                match self.evaluate_predicates(&mut infcx,
+                                               did,
+                                               trait_did,
+                                               ty,
+                                               orig_params.clone(),
+                                               orig_params,
+                                               &mut fresh_preds,
+                                               false) {
+                    Some(e) => e,
+                    None => return AutoTraitResult::NegativeImpl,
+                };
+
+            let (full_env, full_user_env) = self.evaluate_predicates(&mut infcx,
+                                                                     did,
+                                                                     trait_did,
+                                                                     ty,
+                                                                     new_env.clone(),
+                                                                     user_env,
+                                                                     &mut fresh_preds,
+                                                                     true)
+                .unwrap_or_else(|| {
+                                    panic!("Failed to fully process: {:?} {:?} {:?}",
+                                           ty,
+                                           trait_did,
+                                           orig_params)
+                                });
+
+            debug!("find_auto_trait_generics(did={:?}, trait_did={:?}, generics={:?}): fulfilling \
                  with {:?}",
-                did, trait_did, generics, full_env
-            );
+                   did,
+                   trait_did,
+                   generics,
+                   full_env);
             infcx.clear_caches();
 
             // At this point, we already have all of the bounds we need. FulfillmentContext is used
             // to store all of the necessary region/lifetime bounds in the InferContext, as well as
             // an additional sanity check.
             let mut fulfill = FulfillmentContext::new();
-            fulfill.register_bound(
-                &infcx,
-                full_env,
-                ty,
-                trait_did,
-                ObligationCause::misc(DUMMY_SP, ast::DUMMY_NODE_ID),
-            );
-            fulfill.select_all_or_error(&infcx).unwrap_or_else(|e| {
-                panic!(
-                    "Unable to fulfill trait {:?} for '{:?}': {:?}",
-                    trait_did, ty, e
-                )
-            });
+            fulfill.register_bound(&infcx,
+                                   full_env,
+                                   ty,
+                                   trait_did,
+                                   ObligationCause::misc(DUMMY_SP, ast::DUMMY_NODE_ID));
+            fulfill
+                .select_all_or_error(&infcx)
+                .unwrap_or_else(|e| {
+                                    panic!("Unable to fulfill trait {:?} for '{:?}': {:?}",
+                                           trait_did,
+                                           ty,
+                                           e)
+                                });
 
             let names_map: FxHashMap<String, String> = generics
                 .regions
@@ -227,7 +231,12 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> {
 
             let vid_to_region = self.map_vid_to_region(&region_data);
 
-            let info = AutoTraitInfo { full_user_env, region_data, names_map, vid_to_region };
+            let info = AutoTraitInfo {
+                full_user_env,
+                region_data,
+                names_map,
+                vid_to_region,
+            };
 
             return AutoTraitResult::PositiveImpl(auto_trait_callback(&infcx, info));
         });
@@ -272,17 +281,16 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> {
     // the final synthesized generics: we don't want our generated docs page to contain something
     // like 'T: Copy + Clone', as that's redundant. Therefore, we keep track of a separate
     // 'user_env', which only holds the predicates that will actually be displayed to the user.
-    pub fn evaluate_predicates<'b, 'gcx, 'c>(
-        &self,
-        infcx: & InferCtxt<'b, 'tcx, 'c>,
-        ty_did: DefId,
-        trait_did: DefId,
-        ty: ty::Ty<'c>,
-        param_env: ty::ParamEnv<'c>,
-        user_env: ty::ParamEnv<'c>,
-        fresh_preds: &mut FxHashSet<ty::Predicate<'c>>,
-        only_projections: bool,
-    ) -> Option<(ty::ParamEnv<'c>, ty::ParamEnv<'c>)> {
+    pub fn evaluate_predicates<'b, 'gcx, 'c>(&self,
+                                             infcx: &InferCtxt<'b, 'tcx, 'c>,
+                                             ty_did: DefId,
+                                             trait_did: DefId,
+                                             ty: ty::Ty<'c>,
+                                             param_env: ty::ParamEnv<'c>,
+                                             user_env: ty::ParamEnv<'c>,
+                                             fresh_preds: &mut FxHashSet<ty::Predicate<'c>>,
+                                             only_projections: bool)
+                                             -> Option<(ty::ParamEnv<'c>, ty::ParamEnv<'c>)> {
         let tcx = infcx.tcx;
 
         let mut select = SelectionContext::new(&infcx);
@@ -290,11 +298,11 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> {
         let mut already_visited = FxHashSet();
         let mut predicates = VecDeque::new();
         predicates.push_back(ty::Binder::bind(ty::TraitPredicate {
-            trait_ref: ty::TraitRef {
-                def_id: trait_did,
-                substs: infcx.tcx.mk_substs_trait(ty, &[]),
-            },
-        }));
+                                                  trait_ref: ty::TraitRef {
+                                                      def_id: trait_did,
+                                                      substs: infcx.tcx.mk_substs_trait(ty, &[]),
+                                                  },
+                                              }));
 
         let mut computed_preds: FxHashSet<_> = param_env.caller_bounds.iter().cloned().collect();
         let mut user_computed_preds: FxHashSet<_> =
@@ -316,15 +324,13 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> {
                 &Ok(Some(ref vtable)) => {
                     let obligations = vtable.clone().nested_obligations().into_iter();
 
-                    if !self.evaluate_nested_obligations(
-                        ty,
-                        obligations,
-                        &mut user_computed_preds,
-                        fresh_preds,
-                        &mut predicates,
-                        &mut select,
-                        only_projections,
-                    ) {
+                    if !self.evaluate_nested_obligations(ty,
+                                                         obligations,
+                                                         &mut user_computed_preds,
+                                                         fresh_preds,
+                                                         &mut predicates,
+                                                         &mut select,
+                                                         only_projections) {
                         return None;
                     }
                 }
@@ -335,13 +341,11 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> {
                         user_computed_preds.insert(ty::Predicate::Trait(pred.clone()));
                         predicates.push_back(pred);
                     } else {
-                        debug!(
-                            "evaluate_nested_obligations: Unimplemented found, bailing: {:?} {:?} \
-                             {:?}",
-                            ty,
-                            pred,
-                            pred.skip_binder().trait_ref.substs
-                        );
+                        debug!("evaluate_nested_obligations: Unimplemented found, bailing: \
+                             {:?} {:?} {:?}",
+                               ty,
+                               pred,
+                               pred.skip_binder().trait_ref.substs);
                         return None;
                     }
                 }
@@ -351,21 +355,17 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> {
             computed_preds.extend(user_computed_preds.iter().cloned());
             let normalized_preds =
                 elaborate_predicates(tcx, computed_preds.clone().into_iter().collect());
-            new_env = ty::ParamEnv::new(
-                tcx.mk_predicates(normalized_preds),
-                param_env.reveal,
-            );
+            new_env = ty::ParamEnv::new(tcx.mk_predicates(normalized_preds), param_env.reveal);
         }
 
-        let final_user_env = ty::ParamEnv::new(
-            tcx.mk_predicates(user_computed_preds.into_iter()),
-            user_env.reveal,
-        );
-        debug!(
-            "evaluate_nested_obligations(ty_did={:?}, trait_did={:?}): succeeded with '{:?}' \
+        let final_user_env = ty::ParamEnv::new(tcx.mk_predicates(user_computed_preds.into_iter()),
+                                               user_env.reveal);
+        debug!("evaluate_nested_obligations(ty_did={:?}, trait_did={:?}): succeeded with '{:?}' \
              '{:?}'",
-            ty_did, trait_did, new_env, final_user_env
-        );
+               ty_did,
+               trait_did,
+               new_env,
+               final_user_env);
 
         return Some((new_env, final_user_env));
     }
@@ -380,9 +380,13 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> {
     pub fn get_lifetime(&self, region: Region, names_map: &FxHashMap<String, String>) -> String {
         self.region_name(region)
             .map(|name| {
-                names_map.get(&name).unwrap_or_else(|| {
-                    panic!("Missing lifetime with name {:?} for {:?}", name, region)
-                })
+                names_map
+                    .get(&name)
+                    .unwrap_or_else(|| {
+                                        panic!("Missing lifetime with name {:?} for {:?}",
+                                               name,
+                                               region)
+                                    })
             })
             .unwrap_or(&"'static".to_string())
             .clone()
@@ -390,10 +394,9 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> {
 
     // This is very similar to handle_lifetimes. However, instead of matching ty::Region's
     // to each other, we match ty::RegionVid's to ty::Region's
-    pub fn map_vid_to_region<'cx>(
-        &self,
-        regions: &RegionConstraintData<'cx>,
-    ) -> FxHashMap<ty::RegionVid, ty::Region<'cx>> {
+    pub fn map_vid_to_region<'cx>(&self,
+                                  regions: &RegionConstraintData<'cx>)
+                                  -> FxHashMap<ty::RegionVid, ty::Region<'cx>> {
         let mut vid_map: FxHashMap<RegionTarget<'cx>, RegionDeps<'cx>> = FxHashMap();
         let mut finished_map = FxHashMap();
 
@@ -496,31 +499,34 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> {
         }
 
         return match substs.type_at(0).sty {
-            ty::TyParam(_) => true,
-            ty::TyProjection(p) => self.is_of_param(p.substs),
-            _ => false,
-        };
+                   ty::TyParam(_) => true,
+                   ty::TyProjection(p) => self.is_of_param(p.substs),
+                   _ => false,
+               };
     }
 
-    pub fn evaluate_nested_obligations<'b, 'c, 'd, 'cx,
-                                    T: Iterator<Item = Obligation<'cx, ty::Predicate<'cx>>>>(
-        &self,
-        ty: ty::Ty,
-        nested: T,
-        computed_preds: &'b mut FxHashSet<ty::Predicate<'cx>>,
-        fresh_preds: &'b mut FxHashSet<ty::Predicate<'cx>>,
-        predicates: &'b mut VecDeque<ty::PolyTraitPredicate<'cx>>,
-        select: &mut SelectionContext<'c, 'd, 'cx>,
-        only_projections: bool,
-    ) -> bool {
+    pub fn evaluate_nested_obligations<'b,
+                                       'c,
+                                       'd,
+                                       'cx,
+                                       T: Iterator<Item = Obligation<'cx, ty::Predicate<'cx>>>>
+        (&self,
+         ty: ty::Ty,
+         nested: T,
+         computed_preds: &'b mut FxHashSet<ty::Predicate<'cx>>,
+         fresh_preds: &'b mut FxHashSet<ty::Predicate<'cx>>,
+         predicates: &'b mut VecDeque<ty::PolyTraitPredicate<'cx>>,
+         select: &mut SelectionContext<'c, 'd, 'cx>,
+         only_projections: bool)
+         -> bool {
         let dummy_cause = ObligationCause::misc(DUMMY_SP, ast::DUMMY_NODE_ID);
 
-        for (obligation, predicate) in nested
-            .filter(|o| o.recursion_depth == 1)
-            .map(|o| (o.clone(), o.predicate.clone()))
-        {
-            let is_new_pred =
-                fresh_preds.insert(self.clean_pred(select.infcx(), predicate.clone()));
+        for (obligation, predicate) in
+            nested
+                .filter(|o| o.recursion_depth == 1)
+                .map(|o| (o.clone(), o.predicate.clone())) {
+            let is_new_pred = fresh_preds
+                .insert(self.clean_pred(select.infcx(), predicate.clone()));
 
             match &predicate {
                 &ty::Predicate::Trait(ref p) => {
@@ -537,28 +543,22 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> {
                     if self.is_of_param(p.skip_binder().projection_ty.substs) && is_new_pred {
                         computed_preds.insert(predicate);
                     } else {
-                        match poly_project_and_unify_type(
-                            select,
-                            &obligation.with(p.clone()),
-                        ) {
+                        match poly_project_and_unify_type(select, &obligation.with(p.clone())) {
                             Err(e) => {
-                                debug!(
-                                    "evaluate_nested_obligations: Unable to unify predicate \
+                                debug!("evaluate_nested_obligations: Unable to unify predicate \
                                      '{:?}' '{:?}', bailing out",
-                                    ty, e
-                                );
+                                       ty,
+                                       e);
                                 return false;
                             }
                             Ok(Some(v)) => {
-                                if !self.evaluate_nested_obligations(
-                                    ty,
-                                    v.clone().iter().cloned(),
-                                    computed_preds,
-                                    fresh_preds,
-                                    predicates,
-                                    select,
-                                    only_projections,
-                                ) {
+                                if !self.evaluate_nested_obligations(ty,
+                                                                     v.clone().iter().cloned(),
+                                                                     computed_preds,
+                                                                     fresh_preds,
+                                                                     predicates,
+                                                                     select,
+                                                                     only_projections) {
                                     return false;
                                 }
                             }
@@ -570,36 +570,37 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> {
                 }
                 &ty::Predicate::RegionOutlives(ref binder) => {
                     if let Err(_) = select
-                        .infcx()
-                        .region_outlives_predicate(&dummy_cause, binder)
-                    {
+                           .infcx()
+                           .region_outlives_predicate(&dummy_cause, binder) {
                         return false;
                     }
                 }
                 &ty::Predicate::TypeOutlives(ref binder) => {
-                    match (
-                        binder.no_late_bound_regions(),
-                        binder.map_bound_ref(|pred| pred.0).no_late_bound_regions(),
-                    ) {
+                    match (binder.no_late_bound_regions(),
+                           binder.map_bound_ref(|pred| pred.0).no_late_bound_regions()) {
                         (None, Some(t_a)) => {
-                            select.infcx().register_region_obligation(
-                                ast::DUMMY_NODE_ID,
-                                RegionObligation {
-                                    sup_type: t_a,
-                                    sub_region: select.infcx().tcx.types.re_static,
-                                    cause: dummy_cause.clone(),
-                                },
-                            );
+                            select
+                                .infcx()
+                                .register_region_obligation(ast::DUMMY_NODE_ID,
+                                                            RegionObligation {
+                                                                sup_type: t_a,
+                                                                sub_region: select
+                                                                    .infcx()
+                                                                    .tcx
+                                                                    .types
+                                                                    .re_static,
+                                                                cause: dummy_cause.clone(),
+                                                            });
                         }
                         (Some(ty::OutlivesPredicate(t_a, r_b)), _) => {
-                            select.infcx().register_region_obligation(
-                                ast::DUMMY_NODE_ID,
-                                RegionObligation {
-                                    sup_type: t_a,
-                                    sub_region: r_b,
-                                    cause: dummy_cause.clone(),
-                                },
-                            );
+                            select
+                                .infcx()
+                                .register_region_obligation(ast::DUMMY_NODE_ID,
+                                                            RegionObligation {
+                                                                sup_type: t_a,
+                                                                sub_region: r_b,
+                                                                cause: dummy_cause.clone(),
+                                                            });
                         }
                         _ => {}
                     };
@@ -610,11 +611,10 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> {
         return true;
     }
 
-    pub fn clean_pred<'c, 'd, 'cx>(
-        &self,
-        infcx: &InferCtxt<'c, 'd, 'cx>,
-        p: ty::Predicate<'cx>,
-    ) -> ty::Predicate<'cx> {
+    pub fn clean_pred<'c, 'd, 'cx>(&self,
+                                   infcx: &InferCtxt<'c, 'd, 'cx>,
+                                   p: ty::Predicate<'cx>)
+                                   -> ty::Predicate<'cx> {
         infcx.freshen(p)
     }
 }
@@ -632,8 +632,9 @@ impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for RegionReplacer<'a, 'gcx, 'tcx> {
 
     fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
         (match r {
-            &ty::ReVar(vid) => self.vid_to_region.get(&vid).cloned(),
-            _ => None,
-        }).unwrap_or_else(|| r.super_fold_with(self))
+                 &ty::ReVar(vid) => self.vid_to_region.get(&vid).cloned(),
+                 _ => None,
+             })
+            .unwrap_or_else(|| r.super_fold_with(self))
     }
 }