diff --git a/src/librustc/traits/auto_trait.rs b/src/librustc/traits/auto_trait.rs
index 7e4d45050221..a4beb6fab123 100644
--- a/src/librustc/traits/auto_trait.rs
+++ b/src/librustc/traits/auto_trait.rs
@@ -10,16 +10,16 @@
use super::*;
-use std::collections::VecDeque;
use std::collections::hash_map::Entry;
+use std::collections::VecDeque;
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
-use infer::{InferCtxt, RegionObligation};
use infer::region_constraints::{Constraint, RegionConstraintData};
+use infer::{InferCtxt, RegionObligation};
-use ty::{Region, RegionVid};
use ty::fold::TypeFolder;
+use ty::{Region, RegionVid};
// FIXME(twk): this is obviously not nice to duplicate like that
#[derive(Eq, PartialEq, Hash, Copy, Clone, Debug)]
@@ -43,8 +43,7 @@ pub enum AutoTraitResult {
impl AutoTraitResult {
fn is_auto(&self) -> bool {
match *self {
- AutoTraitResult::PositiveImpl(_) |
- AutoTraitResult::NegativeImpl => true,
+ AutoTraitResult::PositiveImpl(_) | AutoTraitResult::NegativeImpl => true,
_ => false,
}
}
@@ -69,14 +68,13 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> {
/// 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(&self,
- did: DefId,
- trait_did: DefId,
- generics: &ty::Generics,
- auto_trait_callback:
- impl for<'i> Fn(&InferCtxt<'_, 'tcx, 'i>,
- AutoTraitInfo<'i>) -> A)
- -> AutoTraitResult {
+ pub fn find_auto_trait_generics(
+ &self,
+ did: DefId,
+ trait_did: DefId,
+ generics: &ty::Generics,
+ auto_trait_callback: impl for<'i> Fn(&InferCtxt<'_, 'tcx, 'i>, AutoTraitInfo<'i>) -> A,
+ ) -> AutoTraitResult {
let tcx = self.tcx;
let ty = self.tcx.type_of(did);
@@ -89,33 +87,32 @@ 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
@@ -151,59 +148,60 @@ 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 (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)
- });
+ 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 \
+ 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 = generics
.regions
@@ -281,16 +279,17 @@ 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>,
- 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>,
+ only_projections: bool,
+ ) -> Option<(ty::ParamEnv<'c>, ty::ParamEnv<'c>)> {
let tcx = infcx.tcx;
let mut select = SelectionContext::new(&infcx);
@@ -298,11 +297,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<_> =
@@ -324,13 +323,15 @@ 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;
}
}
@@ -341,11 +342,13 @@ 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: \
+ debug!(
+ "evaluate_nested_obligations: Unimplemented found, bailing: \
{:?} {:?} {:?}",
- ty,
- pred,
- pred.skip_binder().trait_ref.substs);
+ ty,
+ pred,
+ pred.skip_binder().trait_ref.substs
+ );
return None;
}
}
@@ -358,14 +361,15 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> {
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,13 +384,9 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> {
pub fn get_lifetime(&self, region: Region, names_map: &FxHashMap) -> 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()
@@ -394,9 +394,10 @@ 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> {
+ pub fn map_vid_to_region<'cx>(
+ &self,
+ regions: &RegionConstraintData<'cx>,
+ ) -> FxHashMap> {
let mut vid_map: FxHashMap, RegionDeps<'cx>> = FxHashMap();
let mut finished_map = FxHashMap();
@@ -499,34 +500,36 @@ 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- >>>
- (&self,
- ty: ty::Ty,
- nested: T,
- computed_preds: &'b mut FxHashSet>,
- fresh_preds: &'b mut FxHashSet>,
- predicates: &'b mut VecDeque>,
- select: &mut SelectionContext<'c, 'd, 'cx>,
- only_projections: bool)
- -> bool {
+ pub fn evaluate_nested_obligations<
+ 'b,
+ 'c,
+ 'd,
+ 'cx,
+ T: Iterator
- >>,
+ >(
+ &self,
+ ty: ty::Ty,
+ nested: T,
+ computed_preds: &'b mut FxHashSet>,
+ fresh_preds: &'b mut FxHashSet>,
+ predicates: &'b mut VecDeque>,
+ 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) => {
@@ -545,20 +548,23 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> {
} else {
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,37 +576,36 @@ 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(),
+ },
+ );
}
_ => {}
};
@@ -611,10 +616,11 @@ 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,9 +638,8 @@ 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))
}
}