diff --git a/src/librustc/ich/impls_ty.rs b/src/librustc/ich/impls_ty.rs index 388abc88cfd71..3ff0034fbbee7 100644 --- a/src/librustc/ich/impls_ty.rs +++ b/src/librustc/ich/impls_ty.rs @@ -131,7 +131,7 @@ for ty::RegionKind { } ty::ReLateBound(..) | ty::ReVar(..) | - ty::ReSkolemized(..) => { + ty::RePlaceholder(..) => { bug!("StableHasher: unexpected region {:?}", *self) } } diff --git a/src/librustc/infer/canonical/canonicalizer.rs b/src/librustc/infer/canonical/canonicalizer.rs index 6449227af4ab8..1119c928a89ae 100644 --- a/src/librustc/infer/canonical/canonicalizer.rs +++ b/src/librustc/infer/canonical/canonicalizer.rs @@ -224,7 +224,7 @@ impl<'cx, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for Canonicalizer<'cx, 'gcx, 'tcx> ty::ReEarlyBound(..) | ty::ReFree(_) | ty::ReScope(_) - | ty::ReSkolemized(..) + | ty::RePlaceholder(..) | ty::ReEmpty | ty::ReErased => { if self.canonicalize_region_mode.other_free_regions { diff --git a/src/librustc/infer/combine.rs b/src/librustc/infer/combine.rs index 4738a03cbd3ec..de8f57ee79666 100644 --- a/src/librustc/infer/combine.rs +++ b/src/librustc/infer/combine.rs @@ -458,9 +458,10 @@ impl<'cx, 'gcx, 'tcx> TypeRelation<'cx, 'gcx, 'tcx> for Generalizer<'cx, 'gcx, ' return Ok(r); } - // Always make a fresh region variable for skolemized regions; - // the higher-ranked decision procedures rely on this. - ty::ReSkolemized(..) => { } + // Always make a fresh region variable for placeholder + // regions; the higher-ranked decision procedures rely on + // this. + ty::RePlaceholder(..) => { } // For anything else, we make a region variable, unless we // are *equating*, in which case it's just wasteful. diff --git a/src/librustc/infer/error_reporting/mod.rs b/src/librustc/infer/error_reporting/mod.rs index a68241ff2c020..8b4669c89fe83 100644 --- a/src/librustc/infer/error_reporting/mod.rs +++ b/src/librustc/infer/error_reporting/mod.rs @@ -142,12 +142,12 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { ty::ReEmpty => ("the empty lifetime".to_owned(), None), - // FIXME(#13998) ReSkolemized should probably print like + // FIXME(#13998) RePlaceholder should probably print like // ReFree rather than dumping Debug output on the user. // // We shouldn't really be having unification failures with ReVar // and ReLateBound though. - ty::ReSkolemized(..) | ty::ReVar(_) | ty::ReLateBound(..) | ty::ReErased => { + ty::RePlaceholder(..) | ty::ReVar(_) | ty::ReLateBound(..) | ty::ReErased => { (format!("lifetime {:?}", region), None) } diff --git a/src/librustc/infer/freshen.rs b/src/librustc/infer/freshen.rs index e17e777332ec6..969d260d97e21 100644 --- a/src/librustc/infer/freshen.rs +++ b/src/librustc/infer/freshen.rs @@ -107,7 +107,7 @@ impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for TypeFreshener<'a, 'gcx, 'tcx> { ty::ReFree(_) | ty::ReScope(_) | ty::ReVar(_) | - ty::ReSkolemized(..) | + ty::RePlaceholder(..) | ty::ReEmpty | ty::ReErased => { // replace all free regions with 'erased diff --git a/src/librustc/infer/higher_ranked/README.md b/src/librustc/infer/higher_ranked/README.md index 57665b6d93923..b1ac8bae4fb98 100644 --- a/src/librustc/infer/higher_ranked/README.md +++ b/src/librustc/infer/higher_ranked/README.md @@ -72,11 +72,11 @@ the same lifetime, but not the reverse. Here is the algorithm we use to perform the subtyping check: 1. Replace all bound regions in the subtype with new variables -2. Replace all bound regions in the supertype with skolemized - equivalents. A "skolemized" region is just a new fresh region +2. Replace all bound regions in the supertype with placeholder + equivalents. A "placeholder" region is just a new fresh region name. 3. Check that the parameter and return types match as normal -4. Ensure that no skolemized regions 'leak' into region variables +4. Ensure that no placeholder regions 'leak' into region variables visible from "the outside" Let's walk through some examples and see how this algorithm plays out. @@ -95,7 +95,7 @@ like so: Here the upper case `&A` indicates a *region variable*, that is, a region whose value is being inferred by the system. I also replaced `&b` with `&x`---I'll use letters late in the alphabet (`x`, `y`, `z`) -to indicate skolemized region names. We can assume they don't appear +to indicate placeholder region names. We can assume they don't appear elsewhere. Note that neither the sub- nor the supertype bind any region names anymore (as indicated by the absence of `<` and `>`). @@ -133,7 +133,7 @@ match. This will ultimately require (as before) that `'a` <= `&x` must hold: but this does not hold. `self` and `x` are both distinct free regions. So the subtype check fails. -#### Checking for skolemization leaks +#### Checking for placeholder leaks You may be wondering about that mysterious last step in the algorithm. So far it has not been relevant. The purpose of that last step is to @@ -159,7 +159,7 @@ Now we compare the return types, which are covariant, and hence we have: fn(&'A T) <: for<'b> fn(&'b T)? -Here we skolemize the bound region in the supertype to yield: +Here we replace the bound region in the supertype with a placeholder to yield: fn(&'A T) <: fn(&'x T)? @@ -175,23 +175,23 @@ region `x` and think that everything is happy. In fact, this behavior is *necessary*, it was key to the first example we walked through. The difference between this example and the first one is that the variable -`A` already existed at the point where the skolemization occurred. In +`A` already existed at the point where the placeholders were added. In the first example, you had two functions: for<'a> fn(&'a T) <: for<'b> fn(&'b T) and hence `&A` and `&x` were created "together". In general, the -intention of the skolemized names is that they are supposed to be +intention of the placeholder names is that they are supposed to be fresh names that could never be equal to anything from the outside. But when inference comes into play, we might not be respecting this rule. So the way we solve this is to add a fourth step that examines the -constraints that refer to skolemized names. Basically, consider a +constraints that refer to placeholder names. Basically, consider a non-directed version of the constraint graph. Let `Tainted(x)` be the -set of all things reachable from a skolemized variable `x`. +set of all things reachable from a placeholder variable `x`. `Tainted(x)` should not contain any regions that existed before the -step at which the skolemization was performed. So this case here +step at which the placeholders were created. So this case here would fail because `&x` was created alone, but is relatable to `&A`. ## Computing the LUB and GLB diff --git a/src/librustc/infer/higher_ranked/mod.rs b/src/librustc/infer/higher_ranked/mod.rs index fae4832537156..e77d20665bf3b 100644 --- a/src/librustc/infer/higher_ranked/mod.rs +++ b/src/librustc/infer/higher_ranked/mod.rs @@ -15,7 +15,7 @@ use super::{CombinedSnapshot, InferCtxt, HigherRankedType, SubregionOrigin, - SkolemizationMap}; + PlaceholderMap}; use super::combine::CombineFields; use super::region_constraints::{TaintDirections}; @@ -51,19 +51,21 @@ impl<'a, 'gcx, 'tcx> CombineFields<'a, 'gcx, 'tcx> { return self.infcx.commit_if_ok(|snapshot| { let span = self.trace.cause.span; - // First, we instantiate each bound region in the subtype with a fresh - // region variable. + // First, we instantiate each bound region in the supertype with a + // fresh placeholder region. + let (b_prime, placeholder_map) = + self.infcx.replace_late_bound_regions_with_placeholders(b); + + // Next, we instantiate each bound region in the subtype + // with a fresh region variable. These region variables -- + // but no other pre-existing region variables -- can name + // the placeholders. let (a_prime, _) = self.infcx.replace_late_bound_regions_with_fresh_var( span, HigherRankedType, a); - // Second, we instantiate each bound region in the supertype with a - // fresh concrete region. - let (b_prime, skol_map) = - self.infcx.skolemize_late_bound_regions(b); - debug!("a_prime={:?}", a_prime); debug!("b_prime={:?}", b_prime); @@ -71,12 +73,12 @@ impl<'a, 'gcx, 'tcx> CombineFields<'a, 'gcx, 'tcx> { let result = self.sub(a_is_expected).relate(&a_prime, &b_prime)?; // Presuming type comparison succeeds, we need to check - // that the skolemized regions do not "leak". - self.infcx.leak_check(!a_is_expected, span, &skol_map, snapshot)?; + // that the placeholder regions do not "leak". + self.infcx.leak_check(!a_is_expected, span, &placeholder_map, snapshot)?; - // We are finished with the skolemized regions now so pop + // We are finished with the placeholder regions now so pop // them off. - self.infcx.pop_skolemized(skol_map, snapshot); + self.infcx.pop_placeholders(placeholder_map, snapshot); debug!("higher_ranked_sub: OK result={:?}", result); @@ -112,68 +114,68 @@ impl<'a, 'gcx, 'tcx> CombineFields<'a, 'gcx, 'tcx> { // created as part of this type comparison". return self.infcx.commit_if_ok(|snapshot| { // First, we instantiate each bound region in the matcher - // with a skolemized region. - let ((a_match, a_value), skol_map) = - self.infcx.skolemize_late_bound_regions(a_pair); + // with a placeholder region. + let ((a_match, a_value), placeholder_map) = + self.infcx.replace_late_bound_regions_with_placeholders(a_pair); debug!("higher_ranked_match: a_match={:?}", a_match); - debug!("higher_ranked_match: skol_map={:?}", skol_map); + debug!("higher_ranked_match: placeholder_map={:?}", placeholder_map); // Equate types now that bound regions have been replaced. self.equate(a_is_expected).relate(&a_match, &b_match)?; - // Map each skolemized region to a vector of other regions that it + // Map each placeholder region to a vector of other regions that it // must be equated with. (Note that this vector may include other - // skolemized regions from `skol_map`.) - let skol_resolution_map: FxHashMap<_, _> = - skol_map + // placeholder regions from `placeholder_map`.) + let placeholder_resolution_map: FxHashMap<_, _> = + placeholder_map .iter() - .map(|(&br, &skol)| { + .map(|(&br, &placeholder)| { let tainted_regions = self.infcx.tainted_regions(snapshot, - skol, + placeholder, TaintDirections::incoming()); // [1] - // [1] this routine executes after the skolemized + // [1] this routine executes after the placeholder // regions have been *equated* with something // else, so examining the incoming edges ought to // be enough to collect all constraints - (skol, (br, tainted_regions)) + (placeholder, (br, tainted_regions)) }) .collect(); - // For each skolemized region, pick a representative -- which can + // For each placeholder region, pick a representative -- which can // be any region from the sets above, except for other members of - // `skol_map`. There should always be a representative if things + // `placeholder_map`. There should always be a representative if things // are properly well-formed. - let skol_representatives: FxHashMap<_, _> = - skol_resolution_map + let placeholder_representatives: FxHashMap<_, _> = + placeholder_resolution_map .iter() - .map(|(&skol, &(_, ref regions))| { + .map(|(&placeholder, &(_, ref regions))| { let representative = regions.iter() - .filter(|&&r| !skol_resolution_map.contains_key(r)) + .filter(|&&r| !placeholder_resolution_map.contains_key(r)) .cloned() .next() .unwrap_or_else(|| { bug!("no representative region for `{:?}` in `{:?}`", - skol, regions) + placeholder, regions) }); - (skol, representative) + (placeholder, representative) }) .collect(); - // Equate all the members of each skolemization set with the + // Equate all the members of each placeholder set with the // representative. - for (skol, &(_br, ref regions)) in &skol_resolution_map { - let representative = &skol_representatives[skol]; + for (placeholder, &(_br, ref regions)) in &placeholder_resolution_map { + let representative = &placeholder_representatives[placeholder]; debug!("higher_ranked_match: \ - skol={:?} representative={:?} regions={:?}", - skol, representative, regions); + placeholder={:?} representative={:?} regions={:?}", + placeholder, representative, regions); for region in regions.iter() - .filter(|&r| !skol_resolution_map.contains_key(r)) + .filter(|&r| !placeholder_resolution_map.contains_key(r)) .filter(|&r| r != representative) { let origin = SubregionOrigin::Subtype(self.trace.clone()); @@ -184,18 +186,18 @@ impl<'a, 'gcx, 'tcx> CombineFields<'a, 'gcx, 'tcx> { } } - // Replace the skolemized regions appearing in value with + // Replace the placeholder regions appearing in value with // their representatives let a_value = fold_regions_in( self.tcx(), &a_value, - |r, _| skol_representatives.get(&r).cloned().unwrap_or(r)); + |r, _| placeholder_representatives.get(&r).cloned().unwrap_or(r)); debug!("higher_ranked_match: value={:?}", a_value); - // We are now done with these skolemized variables. - self.infcx.pop_skolemized(skol_map, snapshot); + // We are now done with these placeholder variables. + self.infcx.pop_placeholders(placeholder_map, snapshot); Ok(HrMatchResult { value: a_value }) }); @@ -500,7 +502,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { * started. This is used in the sub/lub/glb computations. The * idea here is that when we are computing lub/glb of two * regions, we sometimes create intermediate region variables. - * Those region variables may touch some of the skolemized or + * Those region variables may touch some of the placeholder or * other "forbidden" regions we created to replace bound * regions, but they don't really represent an "external" * constraint. @@ -527,10 +529,10 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { * we're not careful, it will succeed. * * The reason is that when we walk through the subtyping - * algorithm, we begin by replacing `'a` with a skolemized + * algorithm, we begin by replacing `'a` with a placeholder * variable `'1`. We then have `fn(_#0t) <: fn(&'1 int)`. This * can be made true by unifying `_#0t` with `&'1 int`. In the - * process, we create a fresh variable for the skolemized + * process, we create a fresh variable for the placeholder * region, `'$2`, and hence we have that `_#0t == &'$2 * int`. However, because `'$2` was created during the sub * computation, if we're not careful we will erroneously @@ -568,33 +570,39 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { region_vars } - /// Replace all regions bound by `binder` with skolemized regions and + /// Replace all regions bound by `binder` with placeholder regions and /// return a map indicating which bound-region was replaced with what - /// skolemized region. This is the first step of checking subtyping + /// placeholder region. This is the first step of checking subtyping /// when higher-ranked things are involved. /// /// **Important:** you must call this function from within a snapshot. /// Moreover, before committing the snapshot, you must eventually call - /// either `plug_leaks` or `pop_skolemized` to remove the skolemized + /// either `plug_leaks` or `pop_placeholders` to remove the placeholder /// regions. If you rollback the snapshot (or are using a probe), then /// the pop occurs as part of the rollback, so an explicit call is not /// needed (but is also permitted). /// - /// For more information about how skolemization for HRTBs works, see + /// For more information about how placeholders and HRTBs work, see /// the [rustc guide]. /// /// [rustc guide]: https://rust-lang-nursery.github.io/rustc-guide/traits/hrtb.html - pub fn skolemize_late_bound_regions(&self, - binder: &ty::Binder) - -> (T, SkolemizationMap<'tcx>) - where T : TypeFoldable<'tcx> + pub fn replace_late_bound_regions_with_placeholders( + &self, + binder: &ty::Binder, + ) -> (T, PlaceholderMap<'tcx>) + where + T : TypeFoldable<'tcx>, { + let new_universe = self.create_subuniverse(); + let (result, map) = self.tcx.replace_late_bound_regions(binder, |br| { - self.universe.set(self.universe().subuniverse()); - self.tcx.mk_region(ty::ReSkolemized(self.universe(), br)) + self.tcx.mk_region(ty::RePlaceholder(ty::Placeholder { + universe: new_universe, + name: br, + })) }); - debug!("skolemize_bound_regions(binder={:?}, result={:?}, map={:?})", + debug!("replace_late_bound_regions_with_placeholders(binder={:?}, result={:?}, map={:?})", binder, result, map); @@ -603,19 +611,19 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { } /// Searches the region constraints created since `snapshot` was started - /// and checks to determine whether any of the skolemized regions created - /// in `skol_map` would "escape" -- meaning that they are related to + /// and checks to determine whether any of the placeholder regions created + /// in `placeholder_map` would "escape" -- meaning that they are related to /// other regions in some way. If so, the higher-ranked subtyping doesn't /// hold. See `README.md` for more details. pub fn leak_check(&self, overly_polymorphic: bool, _span: Span, - skol_map: &SkolemizationMap<'tcx>, + placeholder_map: &PlaceholderMap<'tcx>, snapshot: &CombinedSnapshot<'a, 'tcx>) -> RelateResult<'tcx, ()> { - debug!("leak_check: skol_map={:?}", - skol_map); + debug!("leak_check: placeholder_map={:?}", + placeholder_map); // If the user gave `-Zno-leak-check`, then skip the leak // check completely. This is wildly unsound and also not @@ -630,14 +638,14 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { } let new_vars = self.region_vars_confined_to_snapshot(snapshot); - for (&skol_br, &skol) in skol_map { - // The inputs to a skolemized variable can only + for (&placeholder_br, &placeholder) in placeholder_map { + // The inputs to a placeholder variable can only // be itself or other new variables. let incoming_taints = self.tainted_regions(snapshot, - skol, + placeholder, TaintDirections::both()); for &tainted_region in &incoming_taints { - // Each skolemized should only be relatable to itself + // Each placeholder should only be relatable to itself // or new variables: match *tainted_region { ty::ReVar(vid) => { @@ -646,21 +654,21 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { } } _ => { - if tainted_region == skol { continue; } + if tainted_region == placeholder { continue; } } }; debug!("{:?} (which replaced {:?}) is tainted by {:?}", - skol, - skol_br, + placeholder, + placeholder_br, tainted_region); return Err(if overly_polymorphic { debug!("Overly polymorphic!"); - TypeError::RegionsOverlyPolymorphic(skol_br, tainted_region) + TypeError::RegionsOverlyPolymorphic(placeholder_br, tainted_region) } else { debug!("Not as polymorphic!"); - TypeError::RegionsInsufficientlyPolymorphic(skol_br, tainted_region) + TypeError::RegionsInsufficientlyPolymorphic(placeholder_br, tainted_region) }) } } @@ -668,9 +676,9 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { Ok(()) } - /// This code converts from skolemized regions back to late-bound + /// This code converts from placeholder regions back to late-bound /// regions. It works by replacing each region in the taint set of a - /// skolemized region with a bound-region. The bound region will be bound + /// placeholder region with a bound-region. The bound region will be bound /// by the outer-most binder in `value`; the caller must ensure that there is /// such a binder and it is the right place. /// @@ -687,7 +695,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { /// where A : Clone /// { ... } /// - /// Here we will have replaced `'a` with a skolemized region + /// Here we will have replaced `'a` with a placeholder region /// `'0`. This means that our substitution will be `{A=>&'0 /// int, R=>&'0 int}`. /// @@ -697,65 +705,65 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { /// to the depth of the predicate, in this case 1, so that the final /// predicate is `for<'a> &'a int : Clone`. pub fn plug_leaks(&self, - skol_map: SkolemizationMap<'tcx>, + placeholder_map: PlaceholderMap<'tcx>, snapshot: &CombinedSnapshot<'a, 'tcx>, value: T) -> T where T : TypeFoldable<'tcx> { - debug!("plug_leaks(skol_map={:?}, value={:?})", - skol_map, + debug!("plug_leaks(placeholder_map={:?}, value={:?})", + placeholder_map, value); - if skol_map.is_empty() { + if placeholder_map.is_empty() { return value; } - // Compute a mapping from the "taint set" of each skolemized + // Compute a mapping from the "taint set" of each placeholder // region back to the `ty::BoundRegion` that it originally // represented. Because `leak_check` passed, we know that // these taint sets are mutually disjoint. - let inv_skol_map: FxHashMap, ty::BoundRegion> = - skol_map + let inv_placeholder_map: FxHashMap, ty::BoundRegion> = + placeholder_map .iter() - .flat_map(|(&skol_br, &skol)| { - self.tainted_regions(snapshot, skol, TaintDirections::both()) + .flat_map(|(&placeholder_br, &placeholder)| { + self.tainted_regions(snapshot, placeholder, TaintDirections::both()) .into_iter() - .map(move |tainted_region| (tainted_region, skol_br)) + .map(move |tainted_region| (tainted_region, placeholder_br)) }) .collect(); - debug!("plug_leaks: inv_skol_map={:?}", - inv_skol_map); + debug!("plug_leaks: inv_placeholder_map={:?}", + inv_placeholder_map); // Remove any instantiated type variables from `value`; those can hide // references to regions from the `fold_regions` code below. let value = self.resolve_type_vars_if_possible(&value); - // Map any skolemization byproducts back to a late-bound + // Map any placeholder byproducts back to a late-bound // region. Put that late-bound region at whatever the outermost // binder is that we encountered in `value`. The caller is // responsible for ensuring that (a) `value` contains at least one // binder and (b) that binder is the one we want to use. let result = self.tcx.fold_regions(&value, &mut false, |r, current_depth| { - match inv_skol_map.get(&r) { + match inv_placeholder_map.get(&r) { None => r, Some(br) => { // It is the responsibility of the caller to ensure - // that each skolemized region appears within a + // that each placeholder region appears within a // binder. In practice, this routine is only used by - // trait checking, and all of the skolemized regions + // trait checking, and all of the placeholder regions // appear inside predicates, which always have // binders, so this assert is satisfied. assert!(current_depth > ty::INNERMOST); - // since leak-check passed, this skolemized region + // since leak-check passed, this placeholder region // should only have incoming edges from variables // (which ought not to escape the snapshot, but we // don't check that) or itself assert!( match *r { ty::ReVar(_) => true, - ty::ReSkolemized(_, ref br1) => br == br1, + ty::RePlaceholder(index) => index.name == *br, _ => false, }, "leak-check would have us replace {:?} with {:?}", @@ -769,31 +777,36 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { } }); - self.pop_skolemized(skol_map, snapshot); + self.pop_placeholders(placeholder_map, snapshot); debug!("plug_leaks: result={:?}", result); result } - /// Pops the skolemized regions found in `skol_map` from the region - /// inference context. Whenever you create skolemized regions via - /// `skolemize_late_bound_regions`, they must be popped before you + /// Pops the placeholder regions found in `placeholder_map` from the region + /// inference context. Whenever you create placeholder regions via + /// `replace_late_bound_regions_with_placeholders`, they must be popped before you /// commit the enclosing snapshot (if you do not commit, e.g. within a /// probe or as a result of an error, then this is not necessary, as /// popping happens as part of the rollback). /// /// Note: popping also occurs implicitly as part of `leak_check`. - pub fn pop_skolemized(&self, - skol_map: SkolemizationMap<'tcx>, - snapshot: &CombinedSnapshot<'a, 'tcx>) { - debug!("pop_skolemized({:?})", skol_map); - let skol_regions: FxHashSet<_> = skol_map.values().cloned().collect(); + pub fn pop_placeholders( + &self, + placeholder_map: PlaceholderMap<'tcx>, + snapshot: &CombinedSnapshot<'a, 'tcx>, + ) { + debug!("pop_placeholders({:?})", placeholder_map); + let placeholder_regions: FxHashSet<_> = placeholder_map.values().cloned().collect(); self.borrow_region_constraints() - .pop_skolemized(self.universe(), &skol_regions, &snapshot.region_constraints_snapshot); + .pop_placeholders( + &placeholder_regions, + &snapshot.region_constraints_snapshot, + ); self.universe.set(snapshot.universe); - if !skol_map.is_empty() { - self.projection_cache.borrow_mut().rollback_skolemized( + if !placeholder_map.is_empty() { + self.projection_cache.borrow_mut().rollback_placeholder( &snapshot.projection_cache_snapshot); } } diff --git a/src/librustc/infer/lexical_region_resolve/mod.rs b/src/librustc/infer/lexical_region_resolve/mod.rs index ca49d053210c7..caba8b514f797 100644 --- a/src/librustc/infer/lexical_region_resolve/mod.rs +++ b/src/librustc/infer/lexical_region_resolve/mod.rs @@ -28,7 +28,7 @@ use std::u32; use ty::fold::TypeFoldable; use ty::{self, Ty, TyCtxt}; use ty::{ReEarlyBound, ReEmpty, ReErased, ReFree, ReStatic}; -use ty::{ReLateBound, ReScope, ReSkolemized, ReVar}; +use ty::{ReLateBound, ReScope, RePlaceholder, ReVar}; use ty::{Region, RegionVid}; mod graphviz; @@ -341,7 +341,7 @@ impl<'cx, 'gcx, 'tcx> LexicalResolver<'cx, 'gcx, 'tcx> { // For these types, we cannot define any additional // relationship: - (&ReSkolemized(..), _) | (_, &ReSkolemized(..)) => if a == b { + (&RePlaceholder(..), _) | (_, &RePlaceholder(..)) => if a == b { a } else { tcx.types.re_static diff --git a/src/librustc/infer/mod.rs b/src/librustc/infer/mod.rs index 7722896b6eb4a..291b46edccfb2 100644 --- a/src/librustc/infer/mod.rs +++ b/src/librustc/infer/mod.rs @@ -229,9 +229,10 @@ pub struct InferCtxt<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> { universe: Cell, } -/// A map returned by `skolemize_late_bound_regions()` indicating the skolemized -/// region that each late-bound region was replaced with. -pub type SkolemizationMap<'tcx> = BTreeMap>; +/// A map returned by `replace_late_bound_regions_with_placeholders()` +/// indicating the placeholder region that each late-bound region was +/// replaced with. +pub type PlaceholderMap<'tcx> = BTreeMap>; /// See `error_reporting` module for more details #[derive(Clone, Debug)] @@ -405,12 +406,14 @@ pub enum RegionVariableOrigin { #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] pub enum NLLRegionVariableOrigin { - // During NLL region processing, we create variables for free - // regions that we encounter in the function signature and - // elsewhere. This origin indices we've got one of those. + /// During NLL region processing, we create variables for free + /// regions that we encounter in the function signature and + /// elsewhere. This origin indices we've got one of those. FreeRegion, - BoundRegion(ty::UniverseIndex), + /// "Universal" instantiation of a higher-ranked region (e.g., + /// from a `for<'a> T` binder). Meant to represent "any region". + Placeholder(ty::Placeholder), Existential, } @@ -419,7 +422,7 @@ impl NLLRegionVariableOrigin { pub fn is_universal(self) -> bool { match self { NLLRegionVariableOrigin::FreeRegion => true, - NLLRegionVariableOrigin::BoundRegion(..) => true, + NLLRegionVariableOrigin::Placeholder(..) => true, NLLRegionVariableOrigin::Existential => false, } } @@ -913,13 +916,13 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { a, b, }, - skol_map, - ) = self.skolemize_late_bound_regions(predicate); + placeholder_map, + ) = self.replace_late_bound_regions_with_placeholders(predicate); let cause_span = cause.span; let ok = self.at(cause, param_env).sub_exp(a_is_expected, a, b)?; - self.leak_check(false, cause_span, &skol_map, snapshot)?; - self.pop_skolemized(skol_map, snapshot); + self.leak_check(false, cause_span, &placeholder_map, snapshot)?; + self.pop_placeholders(placeholder_map, snapshot); Ok(ok.unit()) })) } @@ -930,14 +933,14 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { predicate: &ty::PolyRegionOutlivesPredicate<'tcx>, ) -> UnitResult<'tcx> { self.commit_if_ok(|snapshot| { - let (ty::OutlivesPredicate(r_a, r_b), skol_map) = - self.skolemize_late_bound_regions(predicate); + let (ty::OutlivesPredicate(r_a, r_b), placeholder_map) = + self.replace_late_bound_regions_with_placeholders(predicate); let origin = SubregionOrigin::from_obligation_cause(cause, || { RelateRegionParamBound(cause.span) }); self.sub_regions(origin, r_b, r_a); // `b : a` ==> `a <= b` - self.leak_check(false, cause.span, &skol_map, snapshot)?; - Ok(self.pop_skolemized(skol_map, snapshot)) + self.leak_check(false, cause.span, &placeholder_map, snapshot)?; + Ok(self.pop_placeholders(placeholder_map, snapshot)) }) } diff --git a/src/librustc/infer/region_constraints/mod.rs b/src/librustc/infer/region_constraints/mod.rs index 87bfbaef54c4e..525ae03dfaf93 100644 --- a/src/librustc/infer/region_constraints/mod.rs +++ b/src/librustc/infer/region_constraints/mod.rs @@ -10,19 +10,19 @@ //! See README.md -use self::UndoLogEntry::*; use self::CombineMapType::*; +use self::UndoLogEntry::*; -use super::{MiscVariable, RegionVariableOrigin, SubregionOrigin}; use super::unify_key; +use super::{MiscVariable, RegionVariableOrigin, SubregionOrigin}; -use rustc_data_structures::indexed_vec::IndexVec; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; +use rustc_data_structures::indexed_vec::IndexVec; use rustc_data_structures::unify as ut; -use ty::{self, Ty, TyCtxt}; -use ty::{Region, RegionVid}; use ty::ReStatic; +use ty::{self, Ty, TyCtxt}; use ty::{BrFresh, ReLateBound, ReVar}; +use ty::{Region, RegionVid}; use std::collections::BTreeMap; use std::{cmp, fmt, mem, u32}; @@ -306,10 +306,10 @@ pub struct RegionSnapshot { any_unifications: bool, } -/// When working with skolemized regions, we often wish to find all of -/// the regions that are either reachable from a skolemized region, or -/// which can reach a skolemized region, or both. We call such regions -/// *tained* regions. This struct allows you to decide what set of +/// When working with placeholder regions, we often wish to find all of +/// the regions that are either reachable from a placeholder region, or +/// which can reach a placeholder region, or both. We call such regions +/// *tainted* regions. This struct allows you to decide what set of /// tainted regions you want. #[derive(Debug)] pub struct TaintDirections { @@ -495,13 +495,12 @@ impl<'tcx> RegionConstraintCollector<'tcx> { } } - pub fn new_region_var(&mut self, - universe: ty::UniverseIndex, - origin: RegionVariableOrigin) -> RegionVid { - let vid = self.var_infos.push(RegionVariableInfo { - origin, - universe, - }); + pub fn new_region_var( + &mut self, + universe: ty::UniverseIndex, + origin: RegionVariableOrigin, + ) -> RegionVid { + let vid = self.var_infos.push(RegionVariableInfo { origin, universe }); let u_vid = self.unification_table .new_key(unify_key::RegionVidKey { min_vid: vid }); @@ -511,8 +510,7 @@ impl<'tcx> RegionConstraintCollector<'tcx> { } debug!( "created new region variable {:?} with origin {:?}", - vid, - origin + vid, origin ); return vid; } @@ -527,51 +525,25 @@ impl<'tcx> RegionConstraintCollector<'tcx> { self.var_infos[vid].origin } - /// Removes all the edges to/from the skolemized regions that are + /// Removes all the edges to/from the placeholder regions that are /// in `skols`. This is used after a higher-ranked operation - /// completes to remove all trace of the skolemized regions + /// completes to remove all trace of the placeholder regions /// created in that time. - pub fn pop_skolemized( + pub fn pop_placeholders( &mut self, - skolemization_count: ty::UniverseIndex, - skols: &FxHashSet>, + placeholders: &FxHashSet>, snapshot: &RegionSnapshot, ) { - debug!("pop_skolemized_regions(skols={:?})", skols); + debug!("pop_placeholders(placeholders={:?})", placeholders); assert!(self.in_snapshot()); assert!(self.undo_log[snapshot.length] == OpenSnapshot); - assert!( - skolemization_count.as_usize() >= skols.len(), - "popping more skolemized variables than actually exist, \ - sc now = {:?}, skols.len = {:?}", - skolemization_count, - skols.len() - ); - - let last_to_pop = skolemization_count.subuniverse(); - let first_to_pop = ty::UniverseIndex::from(last_to_pop.as_u32() - skols.len() as u32); - - debug_assert! { - skols.iter() - .all(|&k| match *k { - ty::ReSkolemized(universe, _) => - universe >= first_to_pop && - universe < last_to_pop, - _ => - false - }), - "invalid skolemization keys or keys out of range ({:?}..{:?}): {:?}", - first_to_pop, - last_to_pop, - skols - } let constraints_to_kill: Vec = self.undo_log .iter() .enumerate() .rev() - .filter(|&(_, undo_entry)| kill_constraint(skols, undo_entry)) + .filter(|&(_, undo_entry)| kill_constraint(placeholders, undo_entry)) .map(|(index, _)| index) .collect(); @@ -583,20 +555,20 @@ impl<'tcx> RegionConstraintCollector<'tcx> { return; fn kill_constraint<'tcx>( - skols: &FxHashSet>, + placeholders: &FxHashSet>, undo_entry: &UndoLogEntry<'tcx>, ) -> bool { match undo_entry { &AddConstraint(Constraint::VarSubVar(..)) => false, - &AddConstraint(Constraint::RegSubVar(a, _)) => skols.contains(&a), - &AddConstraint(Constraint::VarSubReg(_, b)) => skols.contains(&b), + &AddConstraint(Constraint::RegSubVar(a, _)) => placeholders.contains(&a), + &AddConstraint(Constraint::VarSubReg(_, b)) => placeholders.contains(&b), &AddConstraint(Constraint::RegSubReg(a, b)) => { - skols.contains(&a) || skols.contains(&b) + placeholders.contains(&a) || placeholders.contains(&b) } &AddGiven(..) => false, &AddVerify(_) => false, &AddCombination(_, ref two_regions) => { - skols.contains(&two_regions.a) || skols.contains(&two_regions.b) + placeholders.contains(&two_regions.a) || placeholders.contains(&two_regions.b) } &AddVar(..) | &OpenSnapshot | &Purged | &CommitedSnapshot => false, } @@ -713,9 +685,7 @@ impl<'tcx> RegionConstraintCollector<'tcx> { // cannot add constraints once regions are resolved debug!( "RegionConstraintCollector: make_subregion({:?}, {:?}) due to {:?}", - sub, - sup, - origin + sub, sup, origin ); match (sub, sup) { @@ -854,19 +824,19 @@ impl<'tcx> RegionConstraintCollector<'tcx> { fn universe(&self, region: Region<'tcx>) -> ty::UniverseIndex { match *region { - ty::ReScope(..) | - ty::ReStatic | - ty::ReEmpty | - ty::ReErased | - ty::ReFree(..) | - ty::ReEarlyBound(..) => ty::UniverseIndex::ROOT, - ty::ReSkolemized(universe, _) => universe, - ty::ReClosureBound(vid) | - ty::ReVar(vid) => self.var_universe(vid), - ty::ReLateBound(..) => - bug!("universe(): encountered bound region {:?}", region), - ty::ReCanonical(..) => - bug!("region_universe(): encountered canonical region {:?}", region), + ty::ReScope(..) + | ty::ReStatic + | ty::ReEmpty + | ty::ReErased + | ty::ReFree(..) + | ty::ReEarlyBound(..) => ty::UniverseIndex::ROOT, + ty::RePlaceholder(placeholder) => placeholder.universe, + ty::ReClosureBound(vid) | ty::ReVar(vid) => self.var_universe(vid), + ty::ReLateBound(..) => bug!("universe(): encountered bound region {:?}", region), + ty::ReCanonical(..) => bug!( + "region_universe(): encountered canonical region {:?}", + region + ), } } @@ -886,7 +856,7 @@ impl<'tcx> RegionConstraintCollector<'tcx> { /// relations are considered. For example, one can say that only /// "incoming" edges to `r0` are desired, in which case one will /// get the set of regions `{r|r <= r0}`. This is used when - /// checking whether skolemized regions are being improperly + /// checking whether placeholder regions are being improperly /// related to other regions. pub fn tainted( &self, @@ -897,9 +867,7 @@ impl<'tcx> RegionConstraintCollector<'tcx> { ) -> FxHashSet> { debug!( "tainted(mark={:?}, r0={:?}, directions={:?})", - mark, - r0, - directions + mark, r0, directions ); // `result_set` acts as a worklist: we explore all outgoing diff --git a/src/librustc/traits/coherence.rs b/src/librustc/traits/coherence.rs index caf549e37a907..7add8ef05ee78 100644 --- a/src/librustc/traits/coherence.rs +++ b/src/librustc/traits/coherence.rs @@ -117,7 +117,7 @@ fn overlap<'cx, 'gcx, 'tcx>(selcx: &mut SelectionContext<'cx, 'gcx, 'tcx>, { debug!("overlap(a_def_id={:?}, b_def_id={:?})", a_def_id, b_def_id); - // For the purposes of this check, we don't bring any skolemized + // For the purposes of this check, we don't bring any placeholder // types into scope; instead, we replace the generic types with // fresh type variables, and hence we do our evaluations in an // empty environment. diff --git a/src/librustc/traits/project.rs b/src/librustc/traits/project.rs index 5ea936f750e2e..7c1f87fbf3fef 100644 --- a/src/librustc/traits/project.rs +++ b/src/librustc/traits/project.rs @@ -206,15 +206,15 @@ pub fn poly_project_and_unify_type<'cx, 'gcx, 'tcx>( let infcx = selcx.infcx(); infcx.commit_if_ok(|snapshot| { - let (skol_predicate, skol_map) = - infcx.skolemize_late_bound_regions(&obligation.predicate); + let (placeholder_predicate, placeholder_map) = + infcx.replace_late_bound_regions_with_placeholders(&obligation.predicate); - let skol_obligation = obligation.with(skol_predicate); + let skol_obligation = obligation.with(placeholder_predicate); let r = match project_and_unify_type(selcx, &skol_obligation) { Ok(result) => { let span = obligation.cause.span; - match infcx.leak_check(false, span, &skol_map, snapshot) { - Ok(()) => Ok(infcx.plug_leaks(skol_map, snapshot, result)), + match infcx.leak_check(false, span, &placeholder_map, snapshot) { + Ok(()) => Ok(infcx.plug_leaks(placeholder_map, snapshot, result)), Err(e) => { debug!("poly_project_and_unify_type: leak check encountered error {:?}", e); Err(MismatchedProjectionTypes { err: e }) @@ -1571,11 +1571,11 @@ fn assoc_ty_def<'cx, 'gcx, 'tcx>( // # Cache -/// The projection cache. Unlike the standard caches, this can -/// include infcx-dependent type variables - therefore, we have to roll -/// the cache back each time we roll a snapshot back, to avoid assumptions -/// on yet-unresolved inference variables. Types with skolemized regions -/// also have to be removed when the respective snapshot ends. +/// The projection cache. Unlike the standard caches, this can include +/// infcx-dependent type variables - therefore, we have to roll the +/// cache back each time we roll a snapshot back, to avoid assumptions +/// on yet-unresolved inference variables. Types with placeholder +/// regions also have to be removed when the respective snapshot ends. /// /// Because of that, projection cache entries can be "stranded" and left /// inaccessible when type variables inside the key are resolved. We make no @@ -1661,7 +1661,7 @@ impl<'tcx> ProjectionCache<'tcx> { self.map.rollback_to(&snapshot.snapshot); } - pub fn rollback_skolemized(&mut self, snapshot: &ProjectionCacheSnapshot) { + pub fn rollback_placeholder(&mut self, snapshot: &ProjectionCacheSnapshot) { self.map.partial_rollback(&snapshot.snapshot, &|k| k.ty.has_re_skol()); } diff --git a/src/librustc/traits/select.rs b/src/librustc/traits/select.rs index c9fa960a36561..82d881e10b168 100644 --- a/src/librustc/traits/select.rs +++ b/src/librustc/traits/select.rs @@ -12,57 +12,61 @@ //! //! [rustc guide]: https://rust-lang-nursery.github.io/rustc-guide/traits/resolution.html#selection -use self::SelectionCandidate::*; use self::EvaluationResult::*; +use self::SelectionCandidate::*; use super::coherence::{self, Conflict}; -use super::DerivedObligationCause; -use super::{IntercrateMode, TraitQueryMode}; use super::project; use super::project::{normalize_with_depth, Normalized, ProjectionCacheKey}; -use super::{PredicateObligation, TraitObligation, ObligationCause}; -use super::{ObligationCauseCode, BuiltinDerivedObligation, ImplDerivedObligation}; -use super::{SelectionError, Unimplemented, OutputTypeParameterMismatch, Overflow}; -use super::{ObjectCastObligation, Obligation}; -use super::TraitNotObjectSafe; +use super::util; +use super::DerivedObligationCause; use super::Selection; use super::SelectionResult; -use super::{VtableBuiltin, VtableImpl, VtableParam, VtableClosure, VtableGenerator, - VtableFnPointer, VtableObject, VtableAutoImpl}; -use super::{VtableImplData, VtableObjectData, VtableBuiltinData, VtableGeneratorData, - VtableClosureData, VtableAutoImplData, VtableFnPointerData}; -use super::util; - -use dep_graph::{DepNodeIndex, DepKind}; +use super::TraitNotObjectSafe; +use super::{BuiltinDerivedObligation, ImplDerivedObligation, ObligationCauseCode}; +use super::{IntercrateMode, TraitQueryMode}; +use super::{ObjectCastObligation, Obligation}; +use super::{ObligationCause, PredicateObligation, TraitObligation}; +use super::{OutputTypeParameterMismatch, Overflow, SelectionError, Unimplemented}; +use super::{ + VtableAutoImpl, VtableBuiltin, VtableClosure, VtableFnPointer, VtableGenerator, VtableImpl, + VtableObject, VtableParam, +}; +use super::{ + VtableAutoImplData, VtableBuiltinData, VtableClosureData, VtableFnPointerData, + VtableGeneratorData, VtableImplData, VtableObjectData, +}; + +use dep_graph::{DepKind, DepNodeIndex}; use hir::def_id::DefId; use infer; use infer::{InferCtxt, InferOk, TypeFreshener}; -use ty::subst::{Subst, Substs}; -use ty::{self, ToPredicate, ToPolyTraitRef, Ty, TyCtxt, TypeFoldable}; +use middle::lang_items; +use mir::interpret::GlobalId; use ty::fast_reject; use ty::relate::TypeRelation; -use middle::lang_items; -use mir::interpret::{GlobalId}; +use ty::subst::{Subst, Substs}; +use ty::{self, ToPolyTraitRef, ToPredicate, Ty, TyCtxt, TypeFoldable}; +use hir; use rustc_data_structures::bit_set::GrowableBitSet; use rustc_data_structures::sync::Lock; -use std::iter; +use rustc_target::spec::abi::Abi; use std::cmp; use std::fmt; +use std::iter; use std::mem; use std::rc::Rc; -use rustc_target::spec::abi::Abi; -use hir; use util::nodemap::{FxHashMap, FxHashSet}; -pub struct SelectionContext<'cx, 'gcx: 'cx+'tcx, 'tcx: 'cx> { +pub struct SelectionContext<'cx, 'gcx: 'cx + 'tcx, 'tcx: 'cx> { infcx: &'cx InferCtxt<'cx, 'gcx, 'tcx>, - /// Freshener used specifically for skolemizing entries on the - /// obligation stack. This ensures that all entries on the stack - /// at one time will have the same set of skolemized entries, - /// which is important for checking for trait bounds that - /// recursively require themselves. + /// Freshener used specifically for entries on the obligation + /// stack. This ensures that all entries on the stack at one time + /// will have the same set of placeholder entries, which is + /// important for checking for trait bounds that recursively + /// require themselves. freshener: TypeFreshener<'cx, 'gcx, 'tcx>, /// If true, indicates that the evaluation should be conservative @@ -109,26 +113,43 @@ pub enum IntercrateAmbiguityCause { impl IntercrateAmbiguityCause { /// Emits notes when the overlap is caused by complex intercrate ambiguities. /// See #23980 for details. - pub fn add_intercrate_ambiguity_hint<'a, 'tcx>(&self, - err: &mut ::errors::DiagnosticBuilder<'_>) { + pub fn add_intercrate_ambiguity_hint<'a, 'tcx>( + &self, + err: &mut ::errors::DiagnosticBuilder<'_>, + ) { err.note(&self.intercrate_ambiguity_hint()); } pub fn intercrate_ambiguity_hint(&self) -> String { match self { - &IntercrateAmbiguityCause::DownstreamCrate { ref trait_desc, ref self_desc } => { + &IntercrateAmbiguityCause::DownstreamCrate { + ref trait_desc, + ref self_desc, + } => { let self_desc = if let &Some(ref ty) = self_desc { format!(" for type `{}`", ty) - } else { String::new() }; - format!("downstream crates may implement trait `{}`{}", trait_desc, self_desc) + } else { + String::new() + }; + format!( + "downstream crates may implement trait `{}`{}", + trait_desc, self_desc + ) } - &IntercrateAmbiguityCause::UpstreamCrateUpdate { ref trait_desc, ref self_desc } => { + &IntercrateAmbiguityCause::UpstreamCrateUpdate { + ref trait_desc, + ref self_desc, + } => { let self_desc = if let &Some(ref ty) = self_desc { format!(" for type `{}`", ty) - } else { String::new() }; - format!("upstream crates may add new impl of trait `{}`{} \ - in future versions", - trait_desc, self_desc) + } else { + String::new() + }; + format!( + "upstream crates may add new impl of trait `{}`{} \ + in future versions", + trait_desc, self_desc + ) } } } @@ -138,7 +159,7 @@ impl IntercrateAmbiguityCause { struct TraitObligationStack<'prev, 'tcx: 'prev> { obligation: &'prev TraitObligation<'tcx>, - /// Trait ref from `obligation` but skolemized with the + /// Trait ref from `obligation` but "freshened" with the /// selection-context's freshener. Used to check for recursion. fresh_trait_ref: ty::PolyTraitRef<'tcx>, @@ -147,8 +168,9 @@ struct TraitObligationStack<'prev, 'tcx: 'prev> { #[derive(Clone)] pub struct SelectionCache<'tcx> { - hashmap: Lock, - WithDepNode>>>>, + hashmap: Lock< + FxHashMap, WithDepNode>>>, + >, } /// The selection process begins by considering all impls, where @@ -223,10 +245,12 @@ pub struct SelectionCache<'tcx> { /// required for associated types to work in default impls, as the bounds /// are visible both as projection bounds and as where-clauses from the /// parameter environment. -#[derive(PartialEq,Eq,Debug,Clone)] +#[derive(PartialEq, Eq, Debug, Clone)] enum SelectionCandidate<'tcx> { /// If has_nested is false, there are no *further* obligations - BuiltinCandidate { has_nested: bool }, + BuiltinCandidate { + has_nested: bool, + }, ParamCandidate(ty::PolyTraitRef<'tcx>), ImplCandidate(DefId), AutoImplCandidate(DefId), @@ -258,11 +282,7 @@ impl<'a, 'tcx> ty::Lift<'tcx> for SelectionCandidate<'a> { type Lifted = SelectionCandidate<'tcx>; fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option { Some(match *self { - BuiltinCandidate { has_nested } => { - BuiltinCandidate { - has_nested, - } - } + BuiltinCandidate { has_nested } => BuiltinCandidate { has_nested }, ImplCandidate(def_id) => ImplCandidate(def_id), AutoImplCandidate(def_id) => AutoImplCandidate(def_id), ProjectionCandidate => ProjectionCandidate, @@ -292,7 +312,7 @@ struct SelectionCandidateSet<'tcx> { ambiguous: bool, } -#[derive(PartialEq,Eq,Debug,Clone)] +#[derive(PartialEq, Eq, Debug, Clone)] struct EvaluatedCandidate<'tcx> { candidate: SelectionCandidate<'tcx>, evaluation: EvaluationResult, @@ -306,7 +326,7 @@ enum BuiltinImplConditions<'tcx> { /// candidate (a where-clause or user-defined impl). None, /// It is unknown whether there is an impl. - Ambiguous + Ambiguous, } #[derive(Copy, Clone, Debug, PartialOrd, Ord, PartialEq, Eq)] @@ -389,23 +409,17 @@ pub enum EvaluationResult { impl EvaluationResult { pub fn may_apply(self) -> bool { match self { - EvaluatedToOk | - EvaluatedToAmbig | - EvaluatedToUnknown => true, + EvaluatedToOk | EvaluatedToAmbig | EvaluatedToUnknown => true, - EvaluatedToErr | - EvaluatedToRecur => false + EvaluatedToErr | EvaluatedToRecur => false, } } fn is_stack_dependent(self) -> bool { match self { - EvaluatedToUnknown | - EvaluatedToRecur => true, + EvaluatedToUnknown | EvaluatedToRecur => true, - EvaluatedToOk | - EvaluatedToAmbig | - EvaluatedToErr => false, + EvaluatedToOk | EvaluatedToAmbig | EvaluatedToErr => false, } } } @@ -422,7 +436,7 @@ impl_stable_hash_for!(enum self::EvaluationResult { /// Indicates that trait evaluation caused overflow. pub struct OverflowError; -impl_stable_hash_for!(struct OverflowError { }); +impl_stable_hash_for!(struct OverflowError {}); impl<'tcx> From for SelectionError<'tcx> { fn from(OverflowError: OverflowError) -> SelectionError<'tcx> { @@ -432,7 +446,7 @@ impl<'tcx> From for SelectionError<'tcx> { #[derive(Clone)] pub struct EvaluationCache<'tcx> { - hashmap: Lock, WithDepNode>> + hashmap: Lock, WithDepNode>>, } impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { @@ -447,8 +461,10 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { } } - pub fn intercrate(infcx: &'cx InferCtxt<'cx, 'gcx, 'tcx>, - mode: IntercrateMode) -> SelectionContext<'cx, 'gcx, 'tcx> { + pub fn intercrate( + infcx: &'cx InferCtxt<'cx, 'gcx, 'tcx>, + mode: IntercrateMode, + ) -> SelectionContext<'cx, 'gcx, 'tcx> { debug!("intercrate({:?})", mode); SelectionContext { infcx, @@ -460,8 +476,10 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { } } - pub fn with_negative(infcx: &'cx InferCtxt<'cx, 'gcx, 'tcx>, - allow_negative_impls: bool) -> SelectionContext<'cx, 'gcx, 'tcx> { + pub fn with_negative( + infcx: &'cx InferCtxt<'cx, 'gcx, 'tcx>, + allow_negative_impls: bool, + ) -> SelectionContext<'cx, 'gcx, 'tcx> { debug!("with_negative({:?})", allow_negative_impls); SelectionContext { infcx, @@ -473,8 +491,10 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { } } - pub fn with_query_mode(infcx: &'cx InferCtxt<'cx, 'gcx, 'tcx>, - query_mode: TraitQueryMode) -> SelectionContext<'cx, 'gcx, 'tcx> { + pub fn with_query_mode( + infcx: &'cx InferCtxt<'cx, 'gcx, 'tcx>, + query_mode: TraitQueryMode, + ) -> SelectionContext<'cx, 'gcx, 'tcx> { debug!("with_query_mode({:?})", query_mode); SelectionContext { infcx, @@ -521,7 +541,8 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { /// Wraps the inference context's in_snapshot s.t. snapshot handling is only from the selection /// context's self. fn in_snapshot(&mut self, f: F) -> R - where F: FnOnce(&mut Self, &infer::CombinedSnapshot<'cx, 'tcx>) -> R + where + F: FnOnce(&mut Self, &infer::CombinedSnapshot<'cx, 'tcx>) -> R, { self.infcx.in_snapshot(|snapshot| f(self, snapshot)) } @@ -529,20 +550,21 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { /// Wraps a probe s.t. obligations collected during it are ignored and old obligations are /// retained. fn probe(&mut self, f: F) -> R - where F: FnOnce(&mut Self, &infer::CombinedSnapshot<'cx, 'tcx>) -> R + where + F: FnOnce(&mut Self, &infer::CombinedSnapshot<'cx, 'tcx>) -> R, { self.infcx.probe(|snapshot| f(self, snapshot)) } /// Wraps a commit_if_ok s.t. obligations collected during it are not returned in selection if /// the transaction fails and s.t. old obligations are retained. - fn commit_if_ok(&mut self, f: F) -> Result where - F: FnOnce(&mut Self, &infer::CombinedSnapshot<'cx, 'tcx>) -> Result + fn commit_if_ok(&mut self, f: F) -> Result + where + F: FnOnce(&mut Self, &infer::CombinedSnapshot<'cx, 'tcx>) -> Result, { self.infcx.commit_if_ok(|snapshot| f(self, snapshot)) } - /////////////////////////////////////////////////////////////////////////// // Selection // @@ -560,8 +582,10 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { /// Attempts to satisfy the obligation. If successful, this will affect the surrounding /// type environment by performing unification. - pub fn select(&mut self, obligation: &TraitObligation<'tcx>) - -> SelectionResult<'tcx, Selection<'tcx>> { + pub fn select( + &mut self, + obligation: &TraitObligation<'tcx>, + ) -> SelectionResult<'tcx, Selection<'tcx>> { debug!("select({:?})", obligation); debug_assert!(!obligation.predicate.has_escaping_regions()); @@ -573,19 +597,23 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { // earlier. assert!(self.query_mode == TraitQueryMode::Canonical); return Err(SelectionError::Overflow); - }, - Err(e) => { return Err(e); }, - Ok(None) => { return Ok(None); }, - Ok(Some(candidate)) => candidate + } + Err(e) => { + return Err(e); + } + Ok(None) => { + return Ok(None); + } + Ok(Some(candidate)) => candidate, }; match self.confirm_candidate(obligation, candidate) { Err(SelectionError::Overflow) => { assert!(self.query_mode == TraitQueryMode::Canonical); Err(SelectionError::Overflow) - }, + } Err(e) => Err(e), - Ok(candidate) => Ok(Some(candidate)) + Ok(candidate) => Ok(Some(candidate)), } } @@ -600,12 +628,8 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { // we can be sure it does not. /// Evaluates whether the obligation `obligation` can be satisfied (by any means). - pub fn predicate_may_hold_fatal(&mut self, - obligation: &PredicateObligation<'tcx>) - -> bool - { - debug!("predicate_may_hold_fatal({:?})", - obligation); + pub fn predicate_may_hold_fatal(&mut self, obligation: &PredicateObligation<'tcx>) -> bool { + debug!("predicate_may_hold_fatal({:?})", obligation); // This fatal query is a stopgap that should only be used in standard mode, // where we do not expect overflow to be propagated. @@ -618,29 +642,34 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { /// Evaluates whether the obligation `obligation` can be satisfied and returns /// an `EvaluationResult`. - pub fn evaluate_obligation_recursively(&mut self, - obligation: &PredicateObligation<'tcx>) - -> Result - { - self.probe(|this, _| + pub fn evaluate_obligation_recursively( + &mut self, + obligation: &PredicateObligation<'tcx>, + ) -> Result { + self.probe(|this, _| { this.evaluate_predicate_recursively(TraitObligationStackList::empty(), obligation) - ) + }) } /// Evaluates the predicates in `predicates` recursively. Note that /// this applies projections in the predicates, and therefore /// is run within an inference probe. - fn evaluate_predicates_recursively<'a,'o,I>(&mut self, - stack: TraitObligationStackList<'o, 'tcx>, - predicates: I) - -> Result - where I : IntoIterator>, 'tcx:'a + fn evaluate_predicates_recursively<'a, 'o, I>( + &mut self, + stack: TraitObligationStackList<'o, 'tcx>, + predicates: I, + ) -> Result + where + I: IntoIterator>, + 'tcx: 'a, { let mut result = EvaluatedToOk; for obligation in predicates { let eval = self.evaluate_predicate_recursively(stack, obligation)?; - debug!("evaluate_predicate_recursively({:?}) = {:?}", - obligation, eval); + debug!( + "evaluate_predicate_recursively({:?}) = {:?}", + obligation, eval + ); if let EvaluatedToErr = eval { // fast-path - EvaluatedToErr is the top of the lattice, // so we don't need to look on the other predicates. @@ -652,13 +681,12 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { Ok(result) } - fn evaluate_predicate_recursively<'o>(&mut self, - previous_stack: TraitObligationStackList<'o, 'tcx>, - obligation: &PredicateObligation<'tcx>) - -> Result - { - debug!("evaluate_predicate_recursively({:?})", - obligation); + fn evaluate_predicate_recursively<'o>( + &mut self, + previous_stack: TraitObligationStackList<'o, 'tcx>, + obligation: &PredicateObligation<'tcx>, + ) -> Result { + debug!("evaluate_predicate_recursively({:?})", obligation); match obligation.predicate { ty::Predicate::Trait(ref t) => { @@ -669,26 +697,29 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { ty::Predicate::Subtype(ref p) => { // does this code ever run? - match self.infcx.subtype_predicate(&obligation.cause, obligation.param_env, p) { + match self.infcx + .subtype_predicate(&obligation.cause, obligation.param_env, p) + { Some(Ok(InferOk { obligations, .. })) => { self.evaluate_predicates_recursively(previous_stack, &obligations) - }, + } Some(Err(_)) => Ok(EvaluatedToErr), None => Ok(EvaluatedToAmbig), } } - ty::Predicate::WellFormed(ty) => { - match ty::wf::obligations(self.infcx, - obligation.param_env, - obligation.cause.body_id, - ty, obligation.cause.span) { - Some(obligations) => - self.evaluate_predicates_recursively(previous_stack, obligations.iter()), - None => - Ok(EvaluatedToAmbig), + ty::Predicate::WellFormed(ty) => match ty::wf::obligations( + self.infcx, + obligation.param_env, + obligation.cause.body_id, + ty, + obligation.cause.span, + ) { + Some(obligations) => { + self.evaluate_predicates_recursively(previous_stack, obligations.iter()) } - } + None => Ok(EvaluatedToAmbig), + }, ty::Predicate::TypeOutlives(ref binder) => { assert!(!binder.has_escaping_regions()); @@ -790,17 +821,19 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { let project_obligation = obligation.with(data.clone()); match project::poly_project_and_unify_type(self, &project_obligation) { Ok(Some(subobligations)) => { - let result = self.evaluate_predicates_recursively(previous_stack, - subobligations.iter()); + let result = self.evaluate_predicates_recursively( + previous_stack, + subobligations.iter(), + ); if let Some(key) = ProjectionCacheKey::from_poly_projection_predicate(self, data) { self.infcx.projection_cache.borrow_mut().complete(key); } result - }, + } Ok(None) => Ok(EvaluatedToAmbig), - Err(_) => Ok(EvaluatedToErr) + Err(_) => Ok(EvaluatedToErr), } } @@ -812,8 +845,8 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { } else { Ok(EvaluatedToErr) } - }, - None => Ok(EvaluatedToAmbig) + } + None => Ok(EvaluatedToAmbig), } } @@ -821,20 +854,16 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { let tcx = self.tcx(); match tcx.lift_to_global(&(obligation.param_env, substs)) { Some((param_env, substs)) => { - let instance = ty::Instance::resolve( - tcx.global_tcx(), - param_env, - def_id, - substs, - ); + let instance = + ty::Instance::resolve(tcx.global_tcx(), param_env, def_id, substs); if let Some(instance) = instance { let cid = GlobalId { instance, - promoted: None + promoted: None, }; match self.tcx().const_eval(param_env.and(cid)) { Ok(_) => Ok(EvaluatedToOk), - Err(_) => Ok(EvaluatedToErr) + Err(_) => Ok(EvaluatedToErr), } } else { Ok(EvaluatedToErr) @@ -849,46 +878,50 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { } } - fn evaluate_trait_predicate_recursively<'o>(&mut self, - previous_stack: TraitObligationStackList<'o, 'tcx>, - mut obligation: TraitObligation<'tcx>) - -> Result - { + fn evaluate_trait_predicate_recursively<'o>( + &mut self, + previous_stack: TraitObligationStackList<'o, 'tcx>, + mut obligation: TraitObligation<'tcx>, + ) -> Result { debug!("evaluate_trait_predicate_recursively({:?})", obligation); if self.intercrate.is_none() && obligation.is_global() - && obligation.param_env.caller_bounds.iter().all(|bound| bound.needs_subst()) { + && obligation + .param_env + .caller_bounds + .iter() + .all(|bound| bound.needs_subst()) + { // If a param env has no global bounds, global obligations do not // depend on its particular value in order to work, so we can clear // out the param env and get better caching. - debug!("evaluate_trait_predicate_recursively({:?}) - in global", obligation); + debug!( + "evaluate_trait_predicate_recursively({:?}) - in global", + obligation + ); obligation.param_env = obligation.param_env.without_caller_bounds(); } let stack = self.push_stack(previous_stack, &obligation); let fresh_trait_ref = stack.fresh_trait_ref; if let Some(result) = self.check_evaluation_cache(obligation.param_env, fresh_trait_ref) { - debug!("CACHE HIT: EVAL({:?})={:?}", - fresh_trait_ref, - result); + debug!("CACHE HIT: EVAL({:?})={:?}", fresh_trait_ref, result); return Ok(result); } let (result, dep_node) = self.in_task(|this| this.evaluate_stack(&stack)); let result = result?; - debug!("CACHE MISS: EVAL({:?})={:?}", - fresh_trait_ref, - result); + debug!("CACHE MISS: EVAL({:?})={:?}", fresh_trait_ref, result); self.insert_evaluation_cache(obligation.param_env, fresh_trait_ref, dep_node, result); Ok(result) } - fn evaluate_stack<'o>(&mut self, - stack: &TraitObligationStack<'o, 'tcx>) - -> Result - { + fn evaluate_stack<'o>( + &mut self, + stack: &TraitObligationStack<'o, 'tcx>, + ) -> Result { // In intercrate mode, whenever any of the types are unbound, // there can always be an impl. Even if there are no impls in // this crate, perhaps the type would be unified with @@ -913,15 +946,18 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { // This suffices to allow chains like `FnMut` implemented in // terms of `Fn` etc, but we could probably make this more // precise still. - let unbound_input_types = - stack.fresh_trait_ref.skip_binder().input_types().any(|ty| ty.is_fresh()); + let unbound_input_types = stack + .fresh_trait_ref + .skip_binder() + .input_types() + .any(|ty| ty.is_fresh()); // this check was an imperfect workaround for a bug n the old // intercrate mode, it should be removed when that goes away. - if unbound_input_types && - self.intercrate == Some(IntercrateMode::Issue43355) - { - debug!("evaluate_stack({:?}) --> unbound argument, intercrate --> ambiguous", - stack.fresh_trait_ref); + if unbound_input_types && self.intercrate == Some(IntercrateMode::Issue43355) { + debug!( + "evaluate_stack({:?}) --> unbound argument, intercrate --> ambiguous", + stack.fresh_trait_ref + ); // Heuristics: show the diagnostics when there are no candidates in crate. if self.intercrate_ambiguity_causes.is_some() { debug!("evaluate_stack: intercrate_ambiguity_causes is some"); @@ -938,20 +974,23 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { }, }; debug!("evaluate_stack: pushing cause = {:?}", cause); - self.intercrate_ambiguity_causes.as_mut().unwrap().push(cause); + self.intercrate_ambiguity_causes + .as_mut() + .unwrap() + .push(cause); } } } return Ok(EvaluatedToAmbig); } - if unbound_input_types && - stack.iter().skip(1).any( - |prev| stack.obligation.param_env == prev.obligation.param_env && - self.match_fresh_trait_refs(&stack.fresh_trait_ref, - &prev.fresh_trait_ref)) - { - debug!("evaluate_stack({:?}) --> unbound argument, recursive --> giving up", - stack.fresh_trait_ref); + if unbound_input_types && stack.iter().skip(1).any(|prev| { + stack.obligation.param_env == prev.obligation.param_env + && self.match_fresh_trait_refs(&stack.fresh_trait_ref, &prev.fresh_trait_ref) + }) { + debug!( + "evaluate_stack({:?}) --> unbound argument, recursive --> giving up", + stack.fresh_trait_ref + ); return Ok(EvaluatedToUnknown); } @@ -969,29 +1008,31 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { // `Send`. // // Note that we do this comparison using the `fresh_trait_ref` - // fields. Because these have all been skolemized using + // fields. Because these have all been freshened using // `self.freshener`, we can be sure that (a) this will not // affect the inferencer state and (b) that if we see two - // skolemized types with the same index, they refer to the - // same unbound type variable. - if let Some(rec_index) = - stack.iter() + // fresh regions with the same index, they refer to the same + // unbound type variable. + if let Some(rec_index) = stack.iter() .skip(1) // skip top-most frame .position(|prev| stack.obligation.param_env == prev.obligation.param_env && stack.fresh_trait_ref == prev.fresh_trait_ref) { - debug!("evaluate_stack({:?}) --> recursive", - stack.fresh_trait_ref); + debug!("evaluate_stack({:?}) --> recursive", stack.fresh_trait_ref); let cycle = stack.iter().skip(1).take(rec_index + 1); let cycle = cycle.map(|stack| ty::Predicate::Trait(stack.obligation.predicate)); if self.coinductive_match(cycle) { - debug!("evaluate_stack({:?}) --> recursive, coinductive", - stack.fresh_trait_ref); + debug!( + "evaluate_stack({:?}) --> recursive, coinductive", + stack.fresh_trait_ref + ); return Ok(EvaluatedToOk); } else { - debug!("evaluate_stack({:?}) --> recursive, inductive", - stack.fresh_trait_ref); + debug!( + "evaluate_stack({:?}) --> recursive, inductive", + stack.fresh_trait_ref + ); return Ok(EvaluatedToRecur); } } @@ -1000,7 +1041,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { Ok(Some(c)) => self.evaluate_candidate(stack, &c), Ok(None) => Ok(EvaluatedToAmbig), Err(Overflow) => Err(OverflowError), - Err(..) => Ok(EvaluatedToErr) + Err(..) => Ok(EvaluatedToErr), } } @@ -1013,7 +1054,8 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { /// - all the predicates at positions `X..` between `X` an the top are /// also defaulted traits. pub fn coinductive_match(&mut self, cycle: I) -> bool - where I: Iterator> + where + I: Iterator>, { let mut cycle = cycle; cycle.all(|predicate| self.coinductive_predicate(predicate)) @@ -1021,10 +1063,8 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { fn coinductive_predicate(&self, predicate: ty::Predicate<'tcx>) -> bool { let result = match predicate { - ty::Predicate::Trait(ref data) => { - self.tcx().trait_is_auto(data.def_id()) - }, - _ => false + ty::Predicate::Trait(ref data) => self.tcx().trait_is_auto(data.def_id()), + _ => false, }; debug!("coinductive_predicate({:?}) = {:?}", predicate, result); result @@ -1033,34 +1073,37 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { /// Further evaluate `candidate` to decide whether all type parameters match and whether nested /// obligations are met. Returns true if `candidate` remains viable after this further /// scrutiny. - fn evaluate_candidate<'o>(&mut self, - stack: &TraitObligationStack<'o, 'tcx>, - candidate: &SelectionCandidate<'tcx>) - -> Result - { - debug!("evaluate_candidate: depth={} candidate={:?}", - stack.obligation.recursion_depth, candidate); + fn evaluate_candidate<'o>( + &mut self, + stack: &TraitObligationStack<'o, 'tcx>, + candidate: &SelectionCandidate<'tcx>, + ) -> Result { + debug!( + "evaluate_candidate: depth={} candidate={:?}", + stack.obligation.recursion_depth, candidate + ); let result = self.probe(|this, _| { let candidate = (*candidate).clone(); match this.confirm_candidate(stack.obligation, candidate) { - Ok(selection) => { - this.evaluate_predicates_recursively( - stack.list(), - selection.nested_obligations().iter()) - } - Err(..) => Ok(EvaluatedToErr) + Ok(selection) => this.evaluate_predicates_recursively( + stack.list(), + selection.nested_obligations().iter(), + ), + Err(..) => Ok(EvaluatedToErr), } })?; - debug!("evaluate_candidate: depth={} result={:?}", - stack.obligation.recursion_depth, result); + debug!( + "evaluate_candidate: depth={} result={:?}", + stack.obligation.recursion_depth, result + ); Ok(result) } - fn check_evaluation_cache(&self, - param_env: ty::ParamEnv<'tcx>, - trait_ref: ty::PolyTraitRef<'tcx>) - -> Option - { + fn check_evaluation_cache( + &self, + param_env: ty::ParamEnv<'tcx>, + trait_ref: ty::PolyTraitRef<'tcx>, + ) -> Option { let tcx = self.tcx(); if self.can_use_global_caches(param_env) { let cache = tcx.evaluation_cache.hashmap.borrow(); @@ -1068,18 +1111,21 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { return Some(cached.get(tcx)); } } - self.infcx.evaluation_cache.hashmap - .borrow() - .get(&trait_ref) - .map(|v| v.get(tcx)) + self.infcx + .evaluation_cache + .hashmap + .borrow() + .get(&trait_ref) + .map(|v| v.get(tcx)) } - fn insert_evaluation_cache(&mut self, - param_env: ty::ParamEnv<'tcx>, - trait_ref: ty::PolyTraitRef<'tcx>, - dep_node: DepNodeIndex, - result: EvaluationResult) - { + fn insert_evaluation_cache( + &mut self, + param_env: ty::ParamEnv<'tcx>, + trait_ref: ty::PolyTraitRef<'tcx>, + dep_node: DepNodeIndex, + result: EvaluationResult, + ) { // Avoid caching results that depend on more than just the trait-ref // - the stack can create recursion. if result.is_stack_dependent() { @@ -1090,28 +1136,30 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { if let Some(trait_ref) = self.tcx().lift_to_global(&trait_ref) { debug!( "insert_evaluation_cache(trait_ref={:?}, candidate={:?}) global", - trait_ref, - result, + trait_ref, result, ); // This may overwrite the cache with the same value // FIXME: Due to #50507 this overwrites the different values // This should be changed to use HashMapExt::insert_same // when that is fixed - self.tcx().evaluation_cache - .hashmap.borrow_mut() - .insert(trait_ref, WithDepNode::new(dep_node, result)); + self.tcx() + .evaluation_cache + .hashmap + .borrow_mut() + .insert(trait_ref, WithDepNode::new(dep_node, result)); return; } } debug!( "insert_evaluation_cache(trait_ref={:?}, candidate={:?})", - trait_ref, - result, + trait_ref, result, ); - self.infcx.evaluation_cache.hashmap - .borrow_mut() - .insert(trait_ref, WithDepNode::new(dep_node, result)); + self.infcx + .evaluation_cache + .hashmap + .borrow_mut() + .insert(trait_ref, WithDepNode::new(dep_node, result)); } /////////////////////////////////////////////////////////////////////////// @@ -1124,10 +1172,10 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { // [rustc guide]: // https://rust-lang-nursery.github.io/rustc-guide/traits/resolution.html#candidate-assembly - fn candidate_from_obligation<'o>(&mut self, - stack: &TraitObligationStack<'o, 'tcx>) - -> SelectionResult<'tcx, SelectionCandidate<'tcx>> - { + fn candidate_from_obligation<'o>( + &mut self, + stack: &TraitObligationStack<'o, 'tcx>, + ) -> SelectionResult<'tcx, SelectionCandidate<'tcx>> { // Watch out for overflow. This intentionally bypasses (and does // not update) the cache. let recursion_limit = *self.infcx.tcx.sess.recursion_limit.get(); @@ -1135,72 +1183,78 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { match self.query_mode { TraitQueryMode::Standard => { self.infcx().report_overflow_error(&stack.obligation, true); - }, + } TraitQueryMode::Canonical => { return Err(Overflow); - }, + } } } - // Check the cache. Note that we skolemize the trait-ref - // separately rather than using `stack.fresh_trait_ref` -- this - // is because we want the unbound variables to be replaced - // with fresh skolemized types starting from index 0. - let cache_fresh_trait_pred = - self.infcx.freshen(stack.obligation.predicate.clone()); - debug!("candidate_from_obligation(cache_fresh_trait_pred={:?}, obligation={:?})", - cache_fresh_trait_pred, - stack); + // Check the cache. Note that we freshen the trait-ref + // separately rather than using `stack.fresh_trait_ref` -- + // this is because we want the unbound variables to be + // replaced with fresh types starting from index 0. + let cache_fresh_trait_pred = self.infcx.freshen(stack.obligation.predicate.clone()); + debug!( + "candidate_from_obligation(cache_fresh_trait_pred={:?}, obligation={:?})", + cache_fresh_trait_pred, stack + ); debug_assert!(!stack.obligation.predicate.has_escaping_regions()); - if let Some(c) = self.check_candidate_cache(stack.obligation.param_env, - &cache_fresh_trait_pred) { - debug!("CACHE HIT: SELECT({:?})={:?}", - cache_fresh_trait_pred, - c); + if let Some(c) = + self.check_candidate_cache(stack.obligation.param_env, &cache_fresh_trait_pred) + { + debug!("CACHE HIT: SELECT({:?})={:?}", cache_fresh_trait_pred, c); return c; } // If no match, compute result and insert into cache. - let (candidate, dep_node) = self.in_task(|this| - this.candidate_from_obligation_no_cache(stack) - ); + let (candidate, dep_node) = + self.in_task(|this| this.candidate_from_obligation_no_cache(stack)); - debug!("CACHE MISS: SELECT({:?})={:?}", - cache_fresh_trait_pred, candidate); - self.insert_candidate_cache(stack.obligation.param_env, - cache_fresh_trait_pred, - dep_node, - candidate.clone()); + debug!( + "CACHE MISS: SELECT({:?})={:?}", + cache_fresh_trait_pred, candidate + ); + self.insert_candidate_cache( + stack.obligation.param_env, + cache_fresh_trait_pred, + dep_node, + candidate.clone(), + ); candidate } fn in_task(&mut self, op: OP) -> (R, DepNodeIndex) - where OP: FnOnce(&mut Self) -> R + where + OP: FnOnce(&mut Self) -> R, { - let (result, dep_node) = self.tcx().dep_graph.with_anon_task(DepKind::TraitSelect, || - op(self) - ); + let (result, dep_node) = self.tcx() + .dep_graph + .with_anon_task(DepKind::TraitSelect, || op(self)); self.tcx().dep_graph.read_index(dep_node); (result, dep_node) } // Treat negative impls as unimplemented - fn filter_negative_impls(&self, candidate: SelectionCandidate<'tcx>) - -> SelectionResult<'tcx, SelectionCandidate<'tcx>> { + fn filter_negative_impls( + &self, + candidate: SelectionCandidate<'tcx>, + ) -> SelectionResult<'tcx, SelectionCandidate<'tcx>> { if let ImplCandidate(def_id) = candidate { - if !self.allow_negative_impls && - self.tcx().impl_polarity(def_id) == hir::ImplPolarity::Negative { - return Err(Unimplemented) + if !self.allow_negative_impls + && self.tcx().impl_polarity(def_id) == hir::ImplPolarity::Negative + { + return Err(Unimplemented); } } Ok(Some(candidate)) } - fn candidate_from_obligation_no_cache<'o>(&mut self, - stack: &TraitObligationStack<'o, 'tcx>) - -> SelectionResult<'tcx, SelectionCandidate<'tcx>> - { + fn candidate_from_obligation_no_cache<'o>( + &mut self, + stack: &TraitObligationStack<'o, 'tcx>, + ) -> SelectionResult<'tcx, SelectionCandidate<'tcx>> { if stack.obligation.predicate.references_error() { // If we encounter a `Error`, we generally prefer the // most "optimistic" result in response -- that is, the @@ -1220,18 +1274,20 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { if let Ok(candidate_set) = self.assemble_candidates(stack) { let mut no_candidates_apply = true; { - let evaluated_candidates = candidate_set.vec.iter().map(|c| - self.evaluate_candidate(stack, &c)); + let evaluated_candidates = candidate_set + .vec + .iter() + .map(|c| self.evaluate_candidate(stack, &c)); for ec in evaluated_candidates { match ec { Ok(c) => { if c.may_apply() { no_candidates_apply = false; - break + break; } - }, - Err(e) => return Err(e.into()) + } + Err(e) => return Err(e.into()), } } } @@ -1251,10 +1307,16 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { self_desc, } } else { - IntercrateAmbiguityCause::DownstreamCrate { trait_desc, self_desc } + IntercrateAmbiguityCause::DownstreamCrate { + trait_desc, + self_desc, + } }; debug!("evaluate_stack: pushing cause = {:?}", cause); - self.intercrate_ambiguity_causes.as_mut().unwrap().push(cause); + self.intercrate_ambiguity_causes + .as_mut() + .unwrap() + .push(cause); } } } @@ -1270,10 +1332,12 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { let mut candidates = candidate_set.vec; - debug!("assembled {} candidates for {:?}: {:?}", - candidates.len(), - stack, - candidates); + debug!( + "assembled {} candidates for {:?}: {:?}", + candidates.len(), + stack, + candidates + ); // At this point, we know that each of the entries in the // candidate set is *individually* applicable. Now we have to @@ -1319,10 +1383,12 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { let mut candidates: Vec> = candidates?.into_iter().filter_map(|c| c).collect(); - debug!("winnowed to {} candidates for {:?}: {:?}", - candidates.len(), - stack, - candidates); + debug!( + "winnowed to {} candidates for {:?}: {:?}", + candidates.len(), + stack, + candidates + ); // If there are STILL multiple candidate, we can further // reduce the list by dropping duplicates -- including @@ -1330,18 +1396,24 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { if candidates.len() > 1 { let mut i = 0; while i < candidates.len() { - let is_dup = - (0..candidates.len()) - .filter(|&j| i != j) - .any(|j| self.candidate_should_be_dropped_in_favor_of(&candidates[i], - &candidates[j])); + let is_dup = (0..candidates.len()).filter(|&j| i != j).any(|j| { + self.candidate_should_be_dropped_in_favor_of(&candidates[i], &candidates[j]) + }); if is_dup { - debug!("Dropping candidate #{}/{}: {:?}", - i, candidates.len(), candidates[i]); + debug!( + "Dropping candidate #{}/{}: {:?}", + i, + candidates.len(), + candidates[i] + ); candidates.swap_remove(i); } else { - debug!("Retaining candidate #{}/{}: {:?}", - i, candidates.len(), candidates[i]); + debug!( + "Retaining candidate #{}/{}: {:?}", + i, + candidates.len(), + candidates[i] + ); i += 1; // If there are *STILL* multiple candidates, give up @@ -1371,10 +1443,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { self.filter_negative_impls(candidates.pop().unwrap().candidate) } - fn is_knowable<'o>(&mut self, - stack: &TraitObligationStack<'o, 'tcx>) - -> Option - { + fn is_knowable<'o>(&mut self, stack: &TraitObligationStack<'o, 'tcx>) -> Option { debug!("is_knowable(intercrate={:?})", self.intercrate); if !self.intercrate.is_some() { @@ -1382,7 +1451,8 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { } let obligation = &stack.obligation; - let predicate = self.infcx().resolve_type_vars_if_possible(&obligation.predicate); + let predicate = self.infcx() + .resolve_type_vars_if_possible(&obligation.predicate); // ok to skip binder because of the nature of the // trait-ref-is-knowable check, which does not care about @@ -1390,8 +1460,13 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { let trait_ref = predicate.skip_binder().trait_ref; let result = coherence::trait_ref_is_knowable(self.tcx(), trait_ref); - if let (Some(Conflict::Downstream { used_to_be_broken: true }), - Some(IntercrateMode::Issue43355)) = (result, self.intercrate) { + if let ( + Some(Conflict::Downstream { + used_to_be_broken: true, + }), + Some(IntercrateMode::Issue43355), + ) = (result, self.intercrate) + { debug!("is_knowable: IGNORING conflict to be bug-compatible with #43355"); None } else { @@ -1429,11 +1504,11 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { true } - fn check_candidate_cache(&mut self, - param_env: ty::ParamEnv<'tcx>, - cache_fresh_trait_pred: &ty::PolyTraitPredicate<'tcx>) - -> Option>> - { + fn check_candidate_cache( + &mut self, + param_env: ty::ParamEnv<'tcx>, + cache_fresh_trait_pred: &ty::PolyTraitPredicate<'tcx>, + ) -> Option>> { let tcx = self.tcx(); let trait_ref = &cache_fresh_trait_pred.skip_binder().trait_ref; if self.can_use_global_caches(param_env) { @@ -1442,18 +1517,21 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { return Some(cached.get(tcx)); } } - self.infcx.selection_cache.hashmap - .borrow() - .get(trait_ref) - .map(|v| v.get(tcx)) + self.infcx + .selection_cache + .hashmap + .borrow() + .get(trait_ref) + .map(|v| v.get(tcx)) } - fn insert_candidate_cache(&mut self, - param_env: ty::ParamEnv<'tcx>, - cache_fresh_trait_pred: ty::PolyTraitPredicate<'tcx>, - dep_node: DepNodeIndex, - candidate: SelectionResult<'tcx, SelectionCandidate<'tcx>>) - { + fn insert_candidate_cache( + &mut self, + param_env: ty::ParamEnv<'tcx>, + cache_fresh_trait_pred: ty::PolyTraitPredicate<'tcx>, + dep_node: DepNodeIndex, + candidate: SelectionResult<'tcx, SelectionCandidate<'tcx>>, + ) { let tcx = self.tcx(); let trait_ref = cache_fresh_trait_pred.skip_binder().trait_ref; if self.can_use_global_caches(param_env) { @@ -1464,13 +1542,13 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { if let Some(candidate) = tcx.lift_to_global(&candidate) { debug!( "insert_candidate_cache(trait_ref={:?}, candidate={:?}) global", - trait_ref, - candidate, + trait_ref, candidate, ); // This may overwrite the cache with the same value tcx.selection_cache - .hashmap.borrow_mut() - .insert(trait_ref, WithDepNode::new(dep_node, candidate)); + .hashmap + .borrow_mut() + .insert(trait_ref, WithDepNode::new(dep_node, candidate)); return; } } @@ -1478,24 +1556,26 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { debug!( "insert_candidate_cache(trait_ref={:?}, candidate={:?}) local", - trait_ref, - candidate, + trait_ref, candidate, ); - self.infcx.selection_cache.hashmap - .borrow_mut() - .insert(trait_ref, WithDepNode::new(dep_node, candidate)); + self.infcx + .selection_cache + .hashmap + .borrow_mut() + .insert(trait_ref, WithDepNode::new(dep_node, candidate)); } - fn assemble_candidates<'o>(&mut self, - stack: &TraitObligationStack<'o, 'tcx>) - -> Result, SelectionError<'tcx>> - { - let obligation = stack.obligation; + fn assemble_candidates<'o>( + &mut self, + stack: &TraitObligationStack<'o, 'tcx>, + ) -> Result, SelectionError<'tcx>> { + let TraitObligationStack { obligation, .. } = *stack; let ref obligation = Obligation { param_env: obligation.param_env, cause: obligation.cause.clone(), recursion_depth: obligation.recursion_depth, - predicate: self.infcx().resolve_type_vars_if_possible(&obligation.predicate) + predicate: self.infcx() + .resolve_type_vars_if_possible(&obligation.predicate), }; if obligation.predicate.skip_binder().self_ty().is_ty_var() { @@ -1508,12 +1588,15 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { // Take the fast path out - this also improves // performance by preventing assemble_candidates_from_impls from // matching every impl for this trait. - return Ok(SelectionCandidateSet { vec: vec![], ambiguous: true }); + return Ok(SelectionCandidateSet { + vec: vec![], + ambiguous: true, + }); } let mut candidates = SelectionCandidateSet { vec: Vec::new(), - ambiguous: false + ambiguous: false, }; // Other bounds. Consider both in-scope bounds from fn decl @@ -1522,8 +1605,10 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { let lang_items = self.tcx().lang_items(); if lang_items.copy_trait() == Some(def_id) { - debug!("obligation self ty is {:?}", - obligation.predicate.skip_binder().self_ty()); + debug!( + "obligation self ty is {:?}", + obligation.predicate.skip_binder().self_ty() + ); // User-defined copy impls are permitted, but only for // structs and enums. @@ -1536,8 +1621,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { // Sized is never implementable by end-users, it is // always automatically computed. let sized_conditions = self.sized_conditions(obligation); - self.assemble_builtin_bound_candidates(sized_conditions, - &mut candidates)?; + self.assemble_builtin_bound_candidates(sized_conditions, &mut candidates)?; } else if lang_items.unsize_trait() == Some(def_id) { self.assemble_candidates_for_unsizing(obligation, &mut candidates); } else { @@ -1567,27 +1651,29 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { Ok(candidates) } - fn assemble_candidates_from_projected_tys(&mut self, - obligation: &TraitObligation<'tcx>, - candidates: &mut SelectionCandidateSet<'tcx>) - { + fn assemble_candidates_from_projected_tys( + &mut self, + obligation: &TraitObligation<'tcx>, + candidates: &mut SelectionCandidateSet<'tcx>, + ) { debug!("assemble_candidates_for_projected_tys({:?})", obligation); - // before we go into the whole skolemization thing, just + // before we go into the whole placeholder thing, just // quickly check if the self-type is a projection at all. match obligation.predicate.skip_binder().trait_ref.self_ty().sty { ty::Projection(_) | ty::Opaque(..) => {} ty::Infer(ty::TyVar(_)) => { - span_bug!(obligation.cause.span, - "Self=_ should have been handled by assemble_candidates"); + span_bug!( + obligation.cause.span, + "Self=_ should have been handled by assemble_candidates" + ); } - _ => return + _ => return, } - let result = self.probe(|this, snapshot| - this.match_projection_obligation_against_definition_bounds(obligation, - snapshot) - ); + let result = self.probe(|this, snapshot| { + this.match_projection_obligation_against_definition_bounds(obligation, snapshot) + }); if result { candidates.vec.push(ProjectionCandidate); @@ -1597,65 +1683,76 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { fn match_projection_obligation_against_definition_bounds( &mut self, obligation: &TraitObligation<'tcx>, - snapshot: &infer::CombinedSnapshot<'cx, 'tcx>) - -> bool - { - let poly_trait_predicate = - self.infcx().resolve_type_vars_if_possible(&obligation.predicate); - let (skol_trait_predicate, skol_map) = - self.infcx().skolemize_late_bound_regions(&poly_trait_predicate); - debug!("match_projection_obligation_against_definition_bounds: \ - skol_trait_predicate={:?} skol_map={:?}", - skol_trait_predicate, - skol_map); + snapshot: &infer::CombinedSnapshot<'cx, 'tcx>, + ) -> bool { + let poly_trait_predicate = self.infcx() + .resolve_type_vars_if_possible(&obligation.predicate); + let (skol_trait_predicate, placeholder_map) = self.infcx() + .replace_late_bound_regions_with_placeholders(&poly_trait_predicate); + debug!( + "match_projection_obligation_against_definition_bounds: \ + skol_trait_predicate={:?} placeholder_map={:?}", + skol_trait_predicate, placeholder_map + ); let (def_id, substs) = match skol_trait_predicate.trait_ref.self_ty().sty { - ty::Projection(ref data) => - (data.trait_ref(self.tcx()).def_id, data.substs), + ty::Projection(ref data) => (data.trait_ref(self.tcx()).def_id, data.substs), ty::Opaque(def_id, substs) => (def_id, substs), _ => { span_bug!( obligation.cause.span, "match_projection_obligation_against_definition_bounds() called \ but self-ty is not a projection: {:?}", - skol_trait_predicate.trait_ref.self_ty()); + skol_trait_predicate.trait_ref.self_ty() + ); } }; - debug!("match_projection_obligation_against_definition_bounds: \ - def_id={:?}, substs={:?}", - def_id, substs); + debug!( + "match_projection_obligation_against_definition_bounds: \ + def_id={:?}, substs={:?}", + def_id, substs + ); let predicates_of = self.tcx().predicates_of(def_id); let bounds = predicates_of.instantiate(self.tcx(), substs); - debug!("match_projection_obligation_against_definition_bounds: \ - bounds={:?}", - bounds); + debug!( + "match_projection_obligation_against_definition_bounds: \ + bounds={:?}", + bounds + ); - let matching_bound = - util::elaborate_predicates(self.tcx(), bounds.predicates) + let matching_bound = util::elaborate_predicates(self.tcx(), bounds.predicates) .filter_to_traits() - .find( - |bound| self.probe( - |this, _| this.match_projection(obligation, - bound.clone(), - skol_trait_predicate.trait_ref.clone(), - &skol_map, - snapshot))); - - debug!("match_projection_obligation_against_definition_bounds: \ - matching_bound={:?}", - matching_bound); + .find(|bound| { + self.probe(|this, _| { + this.match_projection( + obligation, + bound.clone(), + skol_trait_predicate.trait_ref.clone(), + &placeholder_map, + snapshot, + ) + }) + }); + + debug!( + "match_projection_obligation_against_definition_bounds: \ + matching_bound={:?}", + matching_bound + ); match matching_bound { None => false, Some(bound) => { // Repeat the successful match, if any, this time outside of a probe. - let result = self.match_projection(obligation, - bound, - skol_trait_predicate.trait_ref.clone(), - &skol_map, - snapshot); + let result = self.match_projection( + obligation, + bound, + skol_trait_predicate.trait_ref.clone(), + &placeholder_map, + snapshot, + ); - self.infcx.pop_skolemized(skol_map, snapshot); + self.infcx.pop_placeholders(placeholder_map, snapshot); assert!(result); true @@ -1663,39 +1760,48 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { } } - fn match_projection(&mut self, - obligation: &TraitObligation<'tcx>, - trait_bound: ty::PolyTraitRef<'tcx>, - skol_trait_ref: ty::TraitRef<'tcx>, - skol_map: &infer::SkolemizationMap<'tcx>, - snapshot: &infer::CombinedSnapshot<'cx, 'tcx>) - -> bool - { + fn match_projection( + &mut self, + obligation: &TraitObligation<'tcx>, + trait_bound: ty::PolyTraitRef<'tcx>, + skol_trait_ref: ty::TraitRef<'tcx>, + placeholder_map: &infer::PlaceholderMap<'tcx>, + snapshot: &infer::CombinedSnapshot<'cx, 'tcx>, + ) -> bool { debug_assert!(!skol_trait_ref.has_escaping_regions()); - if self.infcx.at(&obligation.cause, obligation.param_env) - .sup(ty::Binder::dummy(skol_trait_ref), trait_bound).is_err() { + if self.infcx + .at(&obligation.cause, obligation.param_env) + .sup(ty::Binder::dummy(skol_trait_ref), trait_bound) + .is_err() + { return false; } - self.infcx.leak_check(false, obligation.cause.span, skol_map, snapshot).is_ok() + self.infcx + .leak_check(false, obligation.cause.span, placeholder_map, snapshot) + .is_ok() } /// Given an obligation like ``, search the obligations that the caller /// supplied to find out whether it is listed among them. /// /// Never affects inference environment. - fn assemble_candidates_from_caller_bounds<'o>(&mut self, - stack: &TraitObligationStack<'o, 'tcx>, - candidates: &mut SelectionCandidateSet<'tcx>) - -> Result<(),SelectionError<'tcx>> - { - debug!("assemble_candidates_from_caller_bounds({:?})", - stack.obligation); + fn assemble_candidates_from_caller_bounds<'o>( + &mut self, + stack: &TraitObligationStack<'o, 'tcx>, + candidates: &mut SelectionCandidateSet<'tcx>, + ) -> Result<(), SelectionError<'tcx>> { + debug!( + "assemble_candidates_from_caller_bounds({:?})", + stack.obligation + ); - let all_bounds = - stack.obligation.param_env.caller_bounds - .iter() - .filter_map(|o| o.to_opt_poly_trait_ref()); + let all_bounds = stack + .obligation + .param_env + .caller_bounds + .iter() + .filter_map(|o| o.to_opt_poly_trait_ref()); // micro-optimization: filter out predicates relating to different // traits. @@ -1716,26 +1822,26 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { Ok(()) } - fn evaluate_where_clause<'o>(&mut self, - stack: &TraitObligationStack<'o, 'tcx>, - where_clause_trait_ref: ty::PolyTraitRef<'tcx>) - -> Result - { - self.probe(move |this, _| + fn evaluate_where_clause<'o>( + &mut self, + stack: &TraitObligationStack<'o, 'tcx>, + where_clause_trait_ref: ty::PolyTraitRef<'tcx>, + ) -> Result { + self.probe(move |this, _| { match this.match_where_clause_trait_ref(stack.obligation, where_clause_trait_ref) { Ok(obligations) => { this.evaluate_predicates_recursively(stack.list(), obligations.iter()) } - Err(()) => Ok(EvaluatedToErr) + Err(()) => Ok(EvaluatedToErr), } - ) + }) } - fn assemble_generator_candidates(&mut self, - obligation: &TraitObligation<'tcx>, - candidates: &mut SelectionCandidateSet<'tcx>) - -> Result<(),SelectionError<'tcx>> - { + fn assemble_generator_candidates( + &mut self, + obligation: &TraitObligation<'tcx>, + candidates: &mut SelectionCandidateSet<'tcx>, + ) -> Result<(), SelectionError<'tcx>> { if self.tcx().lang_items().gen_trait() != Some(obligation.predicate.def_id()) { return Ok(()); } @@ -1746,9 +1852,10 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { let self_ty = *obligation.self_ty().skip_binder(); match self_ty.sty { ty::Generator(..) => { - debug!("assemble_generator_candidates: self_ty={:?} obligation={:?}", - self_ty, - obligation); + debug!( + "assemble_generator_candidates: self_ty={:?} obligation={:?}", + self_ty, obligation + ); candidates.vec.push(GeneratorCandidate); } @@ -1768,14 +1875,19 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { /// Note: the type parameters on a closure candidate are modeled as *output* type /// parameters and hence do not affect whether this trait is a match or not. They will be /// unified during the confirmation step. - fn assemble_closure_candidates(&mut self, - obligation: &TraitObligation<'tcx>, - candidates: &mut SelectionCandidateSet<'tcx>) - -> Result<(),SelectionError<'tcx>> - { - let kind = match self.tcx().lang_items().fn_trait_kind(obligation.predicate.def_id()) { + fn assemble_closure_candidates( + &mut self, + obligation: &TraitObligation<'tcx>, + candidates: &mut SelectionCandidateSet<'tcx>, + ) -> Result<(), SelectionError<'tcx>> { + let kind = match self.tcx() + .lang_items() + .fn_trait_kind(obligation.predicate.def_id()) + { Some(k) => k, - None => { return Ok(()); } + None => { + return Ok(()); + } }; // ok to skip binder because the substs on closure types never @@ -1783,11 +1895,16 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { // type/region parameters match obligation.self_ty().skip_binder().sty { ty::Closure(closure_def_id, closure_substs) => { - debug!("assemble_unboxed_candidates: kind={:?} obligation={:?}", - kind, obligation); + debug!( + "assemble_unboxed_candidates: kind={:?} obligation={:?}", + kind, obligation + ); match self.infcx.closure_kind(closure_def_id, closure_substs) { Some(closure_kind) => { - debug!("assemble_unboxed_candidates: closure_kind = {:?}", closure_kind); + debug!( + "assemble_unboxed_candidates: closure_kind = {:?}", + closure_kind + ); if closure_kind.extends(kind) { candidates.vec.push(ClosureCandidate); } @@ -1809,13 +1926,17 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { } /// Implement one of the `Fn()` family for a fn pointer. - fn assemble_fn_pointer_candidates(&mut self, - obligation: &TraitObligation<'tcx>, - candidates: &mut SelectionCandidateSet<'tcx>) - -> Result<(),SelectionError<'tcx>> - { + fn assemble_fn_pointer_candidates( + &mut self, + obligation: &TraitObligation<'tcx>, + candidates: &mut SelectionCandidateSet<'tcx>, + ) -> Result<(), SelectionError<'tcx>> { // We provide impl of all fn traits for fn pointers. - if self.tcx().lang_items().fn_trait_kind(obligation.predicate.def_id()).is_none() { + if self.tcx() + .lang_items() + .fn_trait_kind(obligation.predicate.def_id()) + .is_none() + { return Ok(()); } @@ -1833,7 +1954,8 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { abi: Abi::Rust, variadic: false, .. - } = self_ty.fn_sig(self.tcx()).skip_binder() { + } = self_ty.fn_sig(self.tcx()).skip_binder() + { candidates.vec.push(FnPointerCandidate); } } @@ -1844,37 +1966,41 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { } /// Search for impls that might apply to `obligation`. - fn assemble_candidates_from_impls(&mut self, - obligation: &TraitObligation<'tcx>, - candidates: &mut SelectionCandidateSet<'tcx>) - -> Result<(), SelectionError<'tcx>> - { - debug!("assemble_candidates_from_impls(obligation={:?})", obligation); + fn assemble_candidates_from_impls( + &mut self, + obligation: &TraitObligation<'tcx>, + candidates: &mut SelectionCandidateSet<'tcx>, + ) -> Result<(), SelectionError<'tcx>> { + debug!( + "assemble_candidates_from_impls(obligation={:?})", + obligation + ); self.tcx().for_each_relevant_impl( obligation.predicate.def_id(), obligation.predicate.skip_binder().trait_ref.self_ty(), |impl_def_id| { - self.probe(|this, snapshot| /* [1] */ - if let Ok(skol_map) = this.match_impl(impl_def_id, obligation, snapshot) { + self.probe(|this, snapshot| { + if let Ok(placeholder_map) = this.match_impl(impl_def_id, obligation, snapshot) + { candidates.vec.push(ImplCandidate(impl_def_id)); - // NB: we can safely drop the skol map - // since we are in a probe [1] - mem::drop(skol_map); + // NB: we can safely drop the placeholder map + // since we are in a probe. + mem::drop(placeholder_map); } - ); - } + }); + }, ); Ok(()) } - fn assemble_candidates_from_auto_impls(&mut self, - obligation: &TraitObligation<'tcx>, - candidates: &mut SelectionCandidateSet<'tcx>) - -> Result<(), SelectionError<'tcx>> - { + fn assemble_candidates_from_auto_impls( + &mut self, + obligation: &TraitObligation<'tcx>, + candidates: &mut SelectionCandidateSet<'tcx>, + ) -> Result<(), SelectionError<'tcx>> { // OK to skip binder here because the tests we do below do not involve bound regions let self_ty = *obligation.self_ty().skip_binder(); debug!("assemble_candidates_from_auto_impls(self_ty={:?})", self_ty); @@ -1895,8 +2021,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { // still be provided by a manual implementation for // this trait and type. } - ty::Param(..) | - ty::Projection(..) => { + ty::Param(..) | ty::Projection(..) => { // In these cases, we don't know what the actual // type is. Therefore, we cannot break it down // into its constituent types. So we don't @@ -1915,9 +2040,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { // the auto impl might apply, we don't know candidates.ambiguous = true; } - _ => { - candidates.vec.push(AutoImplCandidate(def_id.clone())) - } + _ => candidates.vec.push(AutoImplCandidate(def_id.clone())), } } @@ -1925,12 +2048,15 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { } /// Search for impls that might apply to `obligation`. - fn assemble_candidates_from_object_ty(&mut self, - obligation: &TraitObligation<'tcx>, - candidates: &mut SelectionCandidateSet<'tcx>) - { - debug!("assemble_candidates_from_object_ty(self_ty={:?})", - obligation.self_ty().skip_binder()); + fn assemble_candidates_from_object_ty( + &mut self, + obligation: &TraitObligation<'tcx>, + candidates: &mut SelectionCandidateSet<'tcx>, + ) { + debug!( + "assemble_candidates_from_object_ty(self_ty={:?})", + obligation.self_ty().skip_binder() + ); // Object-safety candidates are only applicable to object-safe // traits. Including this check is useful because it helps @@ -1951,9 +2077,13 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { let self_ty = this.tcx().erase_late_bound_regions(&obligation.self_ty()); let poly_trait_ref = match self_ty.sty { ty::Dynamic(ref data, ..) => { - if data.auto_traits().any(|did| did == obligation.predicate.def_id()) { - debug!("assemble_candidates_from_object_ty: matched builtin bound, \ - pushing candidate"); + if data.auto_traits() + .any(|did| did == obligation.predicate.def_id()) + { + debug!( + "assemble_candidates_from_object_ty: matched builtin bound, \ + pushing candidate" + ); candidates.vec.push(BuiltinObjectCandidate); return; } @@ -1968,25 +2098,27 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { candidates.ambiguous = true; // could wind up being an object type return; } - _ => return + _ => return, }; - debug!("assemble_candidates_from_object_ty: poly_trait_ref={:?}", - poly_trait_ref); + debug!( + "assemble_candidates_from_object_ty: poly_trait_ref={:?}", + poly_trait_ref + ); // Count only those upcast versions that match the trait-ref // we are looking for. Specifically, do not only check for the // correct trait, but also the correct type parameters. // For example, we may be trying to upcast `Foo` to `Bar`, // but `Foo` is declared as `trait Foo : Bar`. - let upcast_trait_refs = - util::supertraits(this.tcx(), poly_trait_ref) - .filter(|upcast_trait_ref| + let upcast_trait_refs = util::supertraits(this.tcx(), poly_trait_ref) + .filter(|upcast_trait_ref| { this.probe(|this, _| { let upcast_trait_ref = upcast_trait_ref.clone(); - this.match_poly_trait_ref(obligation, upcast_trait_ref).is_ok() + this.match_poly_trait_ref(obligation, upcast_trait_ref) + .is_ok() }) - ) + }) .count(); if upcast_trait_refs > 1 { @@ -1999,9 +2131,11 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { } /// Search for unsizing that might apply to `obligation`. - fn assemble_candidates_for_unsizing(&mut self, - obligation: &TraitObligation<'tcx>, - candidates: &mut SelectionCandidateSet<'tcx>) { + fn assemble_candidates_for_unsizing( + &mut self, + obligation: &TraitObligation<'tcx>, + candidates: &mut SelectionCandidateSet<'tcx>, + ) { // We currently never consider higher-ranked obligations e.g. // `for<'a> &'a T: Unsize` to be implemented. This is not // because they are a priori invalid, and we could potentially add support @@ -2023,10 +2157,17 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { return; } }; - let target = obligation.predicate.skip_binder().trait_ref.substs.type_at(1); + let target = obligation + .predicate + .skip_binder() + .trait_ref + .substs + .type_at(1); - debug!("assemble_candidates_for_unsizing(source={:?}, target={:?})", - source, target); + debug!( + "assemble_candidates_for_unsizing(source={:?}, target={:?})", + source, target + ); let may_apply = match (&source.sty, &target.sty) { // Trait+Kx+'a -> Trait+Ky+'b (upcasts). @@ -2043,11 +2184,13 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { // We always upcast when we can because of reason // #2 (region bounds). match (data_a.principal(), data_b.principal()) { - (Some(a), Some(b)) => a.def_id() == b.def_id() && - data_b.auto_traits() + (Some(a), Some(b)) => { + a.def_id() == b.def_id() + && data_b.auto_traits() // All of a's auto traits need to be in b's auto traits. - .all(|b| data_a.auto_traits().any(|a| a == b)), - _ => false + .all(|b| data_a.auto_traits().any(|a| a == b)) + } + _ => false, } } @@ -2057,8 +2200,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { // Ambiguous handling is below T -> Trait, because inference // variables can still implement Unsize and nested // obligations will have the final say (likely deferred). - (&ty::Infer(ty::TyVar(_)), _) | - (_, &ty::Infer(ty::TyVar(_))) => { + (&ty::Infer(ty::TyVar(_)), _) | (_, &ty::Infer(ty::TyVar(_))) => { debug!("assemble_candidates_for_unsizing: ambiguous"); candidates.ambiguous = true; false @@ -2073,11 +2215,9 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { } // (.., T) -> (.., U). - (&ty::Tuple(tys_a), &ty::Tuple(tys_b)) => { - tys_a.len() == tys_b.len() - } + (&ty::Tuple(tys_a), &ty::Tuple(tys_b)) => tys_a.len() == tys_b.len(), - _ => false + _ => false, }; if may_apply { @@ -2090,9 +2230,8 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { // // Winnowing is the process of attempting to resolve ambiguity by // probing further. During the winnowing process, we unify all - // type variables (ignoring skolemization) and then we also - // attempt to evaluate recursive bounds to see if they are - // satisfied. + // type variables and then we also attempt to evaluate recursive + // bounds to see if they are satisfied. /// Returns true if `victim` should be dropped in favor of /// `other`. Generally speaking we will drop duplicate @@ -2102,9 +2241,8 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { fn candidate_should_be_dropped_in_favor_of<'o>( &mut self, victim: &EvaluatedCandidate<'tcx>, - other: &EvaluatedCandidate<'tcx>) - -> bool - { + other: &EvaluatedCandidate<'tcx>, + ) -> bool { if victim.candidate == other.candidate { return true; } @@ -2112,9 +2250,8 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { // Check if a bound would previously have been removed when normalizing // the param_env so that it can be given the lowest priority. See // #50825 for the motivation for this. - let is_global = |cand: &ty::PolyTraitRef<'_>| { - cand.is_global() && !cand.has_late_bound_regions() - }; + let is_global = + |cand: &ty::PolyTraitRef<'_>| cand.is_global() && !cand.has_late_bound_regions(); match other.candidate { // Prefer BuiltinCandidate { has_nested: false } to anything else. @@ -2123,58 +2260,57 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { BuiltinCandidate { has_nested: false } => true, ParamCandidate(ref cand) => match victim.candidate { AutoImplCandidate(..) => { - bug!("default implementations shouldn't be recorded \ - when there are other valid candidates"); + bug!( + "default implementations shouldn't be recorded \ + when there are other valid candidates" + ); } // Prefer BuiltinCandidate { has_nested: false } to anything else. // This is a fix for #53123 and prevents winnowing from accidentally extending the // lifetime of a variable. BuiltinCandidate { has_nested: false } => false, - ImplCandidate(..) | - ClosureCandidate | - GeneratorCandidate | - FnPointerCandidate | - BuiltinObjectCandidate | - BuiltinUnsizeCandidate | - BuiltinCandidate { .. } => { + ImplCandidate(..) + | ClosureCandidate + | GeneratorCandidate + | FnPointerCandidate + | BuiltinObjectCandidate + | BuiltinUnsizeCandidate + | BuiltinCandidate { .. } => { // Global bounds from the where clause should be ignored // here (see issue #50825). Otherwise, we have a where // clause so don't go around looking for impls. !is_global(cand) } - ObjectCandidate | - ProjectionCandidate => { + ObjectCandidate | ProjectionCandidate => { // Arbitrarily give param candidates priority // over projection and object candidates. !is_global(cand) - }, + } ParamCandidate(..) => false, }, - ObjectCandidate | - ProjectionCandidate => match victim.candidate { + ObjectCandidate | ProjectionCandidate => match victim.candidate { AutoImplCandidate(..) => { - bug!("default implementations shouldn't be recorded \ - when there are other valid candidates"); + bug!( + "default implementations shouldn't be recorded \ + when there are other valid candidates" + ); } // Prefer BuiltinCandidate { has_nested: false } to anything else. // This is a fix for #53123 and prevents winnowing from accidentally extending the // lifetime of a variable. BuiltinCandidate { has_nested: false } => false, - ImplCandidate(..) | - ClosureCandidate | - GeneratorCandidate | - FnPointerCandidate | - BuiltinObjectCandidate | - BuiltinUnsizeCandidate | - BuiltinCandidate { .. } => { - true - } - ObjectCandidate | - ProjectionCandidate => { + ImplCandidate(..) + | ClosureCandidate + | GeneratorCandidate + | FnPointerCandidate + | BuiltinObjectCandidate + | BuiltinUnsizeCandidate + | BuiltinCandidate { .. } => true, + ObjectCandidate | ProjectionCandidate => { // Arbitrarily give param candidates priority // over projection and object candidates. true - }, + } ParamCandidate(ref cand) => is_global(cand), }, ImplCandidate(other_def) => { @@ -2185,25 +2321,25 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { match victim.candidate { ImplCandidate(victim_def) => { let tcx = self.tcx().global_tcx(); - return tcx.specializes((other_def, victim_def)) || - tcx.impls_are_allowed_to_overlap(other_def, victim_def); + return tcx.specializes((other_def, victim_def)) + || tcx.impls_are_allowed_to_overlap(other_def, victim_def); } ParamCandidate(ref cand) => { // Prefer the impl to a global where clause candidate. return is_global(cand); } - _ => () + _ => (), } } false - }, - ClosureCandidate | - GeneratorCandidate | - FnPointerCandidate | - BuiltinObjectCandidate | - BuiltinUnsizeCandidate | - BuiltinCandidate { has_nested: true } => { + } + ClosureCandidate + | GeneratorCandidate + | FnPointerCandidate + | BuiltinObjectCandidate + | BuiltinUnsizeCandidate + | BuiltinCandidate { has_nested: true } => { match victim.candidate { ParamCandidate(ref cand) => { // Prefer these to a global where-clause bound @@ -2213,7 +2349,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { _ => false, } } - _ => false + _ => false, } } @@ -2223,16 +2359,16 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { // These cover the traits that are built-in to the language // itself: `Copy`, `Clone` and `Sized`. - fn assemble_builtin_bound_candidates<'o>(&mut self, - conditions: BuiltinImplConditions<'tcx>, - candidates: &mut SelectionCandidateSet<'tcx>) - -> Result<(), SelectionError<'tcx>> - { + fn assemble_builtin_bound_candidates<'o>( + &mut self, + conditions: BuiltinImplConditions<'tcx>, + candidates: &mut SelectionCandidateSet<'tcx>, + ) -> Result<(), SelectionError<'tcx>> { match conditions { BuiltinImplConditions::Where(nested) => { debug!("builtin_bound: nested={:?}", nested); candidates.vec.push(BuiltinCandidate { - has_nested: nested.skip_binder().len() > 0 + has_nested: nested.skip_binder().len() > 0, }); } BuiltinImplConditions::None => {} @@ -2245,83 +2381,105 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { Ok(()) } - fn sized_conditions(&mut self, - obligation: &TraitObligation<'tcx>) - -> BuiltinImplConditions<'tcx> - { + fn sized_conditions( + &mut self, + obligation: &TraitObligation<'tcx>, + ) -> BuiltinImplConditions<'tcx> { use self::BuiltinImplConditions::{Ambiguous, None, Where}; // NOTE: binder moved to (*) - let self_ty = self.infcx.shallow_resolve( - obligation.predicate.skip_binder().self_ty()); + let self_ty = self.infcx + .shallow_resolve(obligation.predicate.skip_binder().self_ty()); match self_ty.sty { - ty::Infer(ty::IntVar(_)) | ty::Infer(ty::FloatVar(_)) | - ty::Uint(_) | ty::Int(_) | ty::Bool | ty::Float(_) | - ty::FnDef(..) | ty::FnPtr(_) | ty::RawPtr(..) | - ty::Char | ty::Ref(..) | ty::Generator(..) | - ty::GeneratorWitness(..) | ty::Array(..) | ty::Closure(..) | - ty::Never | ty::Error => { + ty::Infer(ty::IntVar(_)) + | ty::Infer(ty::FloatVar(_)) + | ty::Uint(_) + | ty::Int(_) + | ty::Bool + | ty::Float(_) + | ty::FnDef(..) + | ty::FnPtr(_) + | ty::RawPtr(..) + | ty::Char + | ty::Ref(..) + | ty::Generator(..) + | ty::GeneratorWitness(..) + | ty::Array(..) + | ty::Closure(..) + | ty::Never + | ty::Error => { // safe for everything Where(ty::Binder::dummy(Vec::new())) } ty::Str | ty::Slice(_) | ty::Dynamic(..) | ty::Foreign(..) => None, - ty::Tuple(tys) => { - Where(ty::Binder::bind(tys.last().into_iter().cloned().collect())) - } + ty::Tuple(tys) => Where(ty::Binder::bind(tys.last().into_iter().cloned().collect())), ty::Adt(def, substs) => { let sized_crit = def.sized_constraint(self.tcx()); // (*) binder moved here Where(ty::Binder::bind( - sized_crit.iter().map(|ty| ty.subst(self.tcx(), substs)).collect() + sized_crit + .iter() + .map(|ty| ty.subst(self.tcx(), substs)) + .collect(), )) } ty::Projection(_) | ty::Param(_) | ty::Opaque(..) => None, ty::Infer(ty::TyVar(_)) => Ambiguous, - ty::UnnormalizedProjection(..) | - ty::Infer(ty::CanonicalTy(_)) | - ty::Infer(ty::FreshTy(_)) | - ty::Infer(ty::FreshIntTy(_)) | - ty::Infer(ty::FreshFloatTy(_)) => { - bug!("asked to assemble builtin bounds of unexpected type: {:?}", - self_ty); + ty::UnnormalizedProjection(..) + | ty::Infer(ty::CanonicalTy(_)) + | ty::Infer(ty::FreshTy(_)) + | ty::Infer(ty::FreshIntTy(_)) + | ty::Infer(ty::FreshFloatTy(_)) => { + bug!( + "asked to assemble builtin bounds of unexpected type: {:?}", + self_ty + ); } } } - fn copy_clone_conditions(&mut self, - obligation: &TraitObligation<'tcx>) - -> BuiltinImplConditions<'tcx> - { + fn copy_clone_conditions( + &mut self, + obligation: &TraitObligation<'tcx>, + ) -> BuiltinImplConditions<'tcx> { // NOTE: binder moved to (*) - let self_ty = self.infcx.shallow_resolve( - obligation.predicate.skip_binder().self_ty()); + let self_ty = self.infcx + .shallow_resolve(obligation.predicate.skip_binder().self_ty()); use self::BuiltinImplConditions::{Ambiguous, None, Where}; match self_ty.sty { - ty::Infer(ty::IntVar(_)) | ty::Infer(ty::FloatVar(_)) | - ty::FnDef(..) | ty::FnPtr(_) | ty::Error => { - Where(ty::Binder::dummy(Vec::new())) - } - - ty::Uint(_) | ty::Int(_) | ty::Bool | ty::Float(_) | - ty::Char | ty::RawPtr(..) | ty::Never | - ty::Ref(_, _, hir::MutImmutable) => { + ty::Infer(ty::IntVar(_)) + | ty::Infer(ty::FloatVar(_)) + | ty::FnDef(..) + | ty::FnPtr(_) + | ty::Error => Where(ty::Binder::dummy(Vec::new())), + + ty::Uint(_) + | ty::Int(_) + | ty::Bool + | ty::Float(_) + | ty::Char + | ty::RawPtr(..) + | ty::Never + | ty::Ref(_, _, hir::MutImmutable) => { // Implementations provided in libcore None } - ty::Dynamic(..) | ty::Str | ty::Slice(..) | - ty::Generator(..) | ty::GeneratorWitness(..) | ty::Foreign(..) | - ty::Ref(_, _, hir::MutMutable) => { - None - } + ty::Dynamic(..) + | ty::Str + | ty::Slice(..) + | ty::Generator(..) + | ty::GeneratorWitness(..) + | ty::Foreign(..) + | ty::Ref(_, _, hir::MutMutable) => None, ty::Array(element_ty, _) => { // (*) binder moved here @@ -2338,7 +2496,9 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { let is_copy_trait = Some(trait_id) == self.tcx().lang_items().copy_trait(); let is_clone_trait = Some(trait_id) == self.tcx().lang_items().clone_trait(); if is_copy_trait || is_clone_trait { - Where(ty::Binder::bind(substs.upvar_tys(def_id, self.tcx()).collect())) + Where(ty::Binder::bind( + substs.upvar_tys(def_id, self.tcx()).collect(), + )) } else { None } @@ -2356,13 +2516,15 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { Ambiguous } - ty::UnnormalizedProjection(..) | - ty::Infer(ty::CanonicalTy(_)) | - ty::Infer(ty::FreshTy(_)) | - ty::Infer(ty::FreshIntTy(_)) | - ty::Infer(ty::FreshFloatTy(_)) => { - bug!("asked to assemble builtin bounds of unexpected type: {:?}", - self_ty); + ty::UnnormalizedProjection(..) + | ty::Infer(ty::CanonicalTy(_)) + | ty::Infer(ty::FreshTy(_)) + | ty::Infer(ty::FreshIntTy(_)) + | ty::Infer(ty::FreshFloatTy(_)) => { + bug!( + "asked to assemble builtin bounds of unexpected type: {:?}", + self_ty + ); } } } @@ -2380,56 +2542,54 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { /// ``` fn constituent_types_for_ty(&self, t: Ty<'tcx>) -> Vec> { match t.sty { - ty::Uint(_) | - ty::Int(_) | - ty::Bool | - ty::Float(_) | - ty::FnDef(..) | - ty::FnPtr(_) | - ty::Str | - ty::Error | - ty::Infer(ty::IntVar(_)) | - ty::Infer(ty::FloatVar(_)) | - ty::Never | - ty::Char => { - Vec::new() - } - - ty::UnnormalizedProjection(..) | - ty::Dynamic(..) | - ty::Param(..) | - ty::Foreign(..) | - ty::Projection(..) | - ty::Infer(ty::CanonicalTy(_)) | - ty::Infer(ty::TyVar(_)) | - ty::Infer(ty::FreshTy(_)) | - ty::Infer(ty::FreshIntTy(_)) | - ty::Infer(ty::FreshFloatTy(_)) => { - bug!("asked to assemble constituent types of unexpected type: {:?}", - t); - } - - ty::RawPtr(ty::TypeAndMut { ty: element_ty, ..}) | - ty::Ref(_, element_ty, _) => { - vec![element_ty] - }, + ty::Uint(_) + | ty::Int(_) + | ty::Bool + | ty::Float(_) + | ty::FnDef(..) + | ty::FnPtr(_) + | ty::Str + | ty::Error + | ty::Infer(ty::IntVar(_)) + | ty::Infer(ty::FloatVar(_)) + | ty::Never + | ty::Char => Vec::new(), + + ty::UnnormalizedProjection(..) + | ty::Dynamic(..) + | ty::Param(..) + | ty::Foreign(..) + | ty::Projection(..) + | ty::Infer(ty::CanonicalTy(_)) + | ty::Infer(ty::TyVar(_)) + | ty::Infer(ty::FreshTy(_)) + | ty::Infer(ty::FreshIntTy(_)) + | ty::Infer(ty::FreshFloatTy(_)) => { + bug!( + "asked to assemble constituent types of unexpected type: {:?}", + t + ); + } - ty::Array(element_ty, _) | ty::Slice(element_ty) => { + ty::RawPtr(ty::TypeAndMut { ty: element_ty, .. }) | ty::Ref(_, element_ty, _) => { vec![element_ty] } + ty::Array(element_ty, _) | ty::Slice(element_ty) => vec![element_ty], + ty::Tuple(ref tys) => { // (T1, ..., Tn) -- meets any bound that all of T1...Tn meet tys.to_vec() } - ty::Closure(def_id, ref substs) => { - substs.upvar_tys(def_id, self.tcx()).collect() - } + ty::Closure(def_id, ref substs) => substs.upvar_tys(def_id, self.tcx()).collect(), ty::Generator(def_id, ref substs, _) => { let witness = substs.witness(def_id, self.tcx()); - substs.upvar_tys(def_id, self.tcx()).chain(iter::once(witness)).collect() + substs + .upvar_tys(def_id, self.tcx()) + .chain(iter::once(witness)) + .collect() } ty::GeneratorWitness(types) => { @@ -2440,15 +2600,9 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { } // for `PhantomData`, we pass `T` - ty::Adt(def, substs) if def.is_phantom_data() => { - substs.types().collect() - } + ty::Adt(def, substs) if def.is_phantom_data() => substs.types().collect(), - ty::Adt(def, substs) => { - def.all_fields() - .map(|f| f.ty(self.tcx(), substs)) - .collect() - } + ty::Adt(def, substs) => def.all_fields().map(|f| f.ty(self.tcx(), substs)).collect(), ty::Opaque(def_id, substs) => { // We can resolve the `impl Trait` to its concrete type, @@ -2459,14 +2613,14 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { } } - fn collect_predicates_for_types(&mut self, - param_env: ty::ParamEnv<'tcx>, - cause: ObligationCause<'tcx>, - recursion_depth: usize, - trait_def_id: DefId, - types: ty::Binder>>) - -> Vec> - { + fn collect_predicates_for_types( + &mut self, + param_env: ty::ParamEnv<'tcx>, + cause: ObligationCause<'tcx>, + recursion_depth: usize, + trait_def_id: DefId, + types: ty::Binder>>, + ) -> Vec> { // Because the types were potentially derived from // higher-ranked obligations they may reference late-bound // regions. For example, `for<'a> Foo<&'a int> : Copy` would @@ -2476,34 +2630,45 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { // // The strategy is to: // - // 1. Instantiate those regions to skolemized regions (e.g., + // 1. Instantiate those regions to placeholder regions (e.g., // `for<'a> &'a int` becomes `&0 int`. // 2. Produce something like `&'0 int : Copy` // 3. Re-bind the regions back to `for<'a> &'a int : Copy` - types.skip_binder().into_iter().flat_map(|ty| { // binder moved -\ - let ty: ty::Binder> = ty::Binder::bind(ty); // <----/ - - self.in_snapshot(|this, snapshot| { - let (skol_ty, skol_map) = - this.infcx().skolemize_late_bound_regions(&ty); - let Normalized { value: normalized_ty, mut obligations } = - project::normalize_with_depth(this, - param_env, - cause.clone(), - recursion_depth, - &skol_ty); - let skol_obligation = - this.tcx().predicate_for_trait_def(param_env, - cause.clone(), - trait_def_id, - recursion_depth, - normalized_ty, - &[]); - obligations.push(skol_obligation); - this.infcx().plug_leaks(skol_map, snapshot, obligations) + types + .skip_binder() + .into_iter() + .flat_map(|ty| { + // binder moved -\ + let ty: ty::Binder> = ty::Binder::bind(ty); // <----/ + + self.in_snapshot(|this, snapshot| { + let (skol_ty, placeholder_map) = this.infcx() + .replace_late_bound_regions_with_placeholders(&ty); + let Normalized { + value: normalized_ty, + mut obligations, + } = project::normalize_with_depth( + this, + param_env, + cause.clone(), + recursion_depth, + &skol_ty, + ); + let skol_obligation = this.tcx().predicate_for_trait_def( + param_env, + cause.clone(), + trait_def_id, + recursion_depth, + normalized_ty, + &[], + ); + obligations.push(skol_obligation); + this.infcx() + .plug_leaks(placeholder_map, snapshot, obligations) + }) }) - }).collect() + .collect() } /////////////////////////////////////////////////////////////////////////// @@ -2516,14 +2681,12 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { // [rustc guide]: // https://rust-lang-nursery.github.io/rustc-guide/traits/resolution.html#confirmation - fn confirm_candidate(&mut self, - obligation: &TraitObligation<'tcx>, - candidate: SelectionCandidate<'tcx>) - -> Result, SelectionError<'tcx>> - { - debug!("confirm_candidate({:?}, {:?})", - obligation, - candidate); + fn confirm_candidate( + &mut self, + obligation: &TraitObligation<'tcx>, + candidate: SelectionCandidate<'tcx>, + ) -> Result, SelectionError<'tcx>> { + debug!("confirm_candidate({:?}, {:?})", obligation, candidate); match candidate { BuiltinCandidate { has_nested } => { @@ -2541,9 +2704,10 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { Ok(VtableAutoImpl(data)) } - ImplCandidate(impl_def_id) => { - Ok(VtableImpl(self.confirm_impl_candidate(obligation, impl_def_id))) - } + ImplCandidate(impl_def_id) => Ok(VtableImpl(self.confirm_impl_candidate( + obligation, + impl_def_id, + ))), ClosureCandidate => { let vtable_closure = self.confirm_closure_candidate(obligation)?; @@ -2570,8 +2734,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { } FnPointerCandidate => { - let data = - self.confirm_fn_pointer_candidate(obligation)?; + let data = self.confirm_fn_pointer_candidate(obligation)?; Ok(VtableFnPointer(data)) } @@ -2587,25 +2750,20 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { } } - fn confirm_projection_candidate(&mut self, - obligation: &TraitObligation<'tcx>) - { + fn confirm_projection_candidate(&mut self, obligation: &TraitObligation<'tcx>) { self.in_snapshot(|this, snapshot| { let result = - this.match_projection_obligation_against_definition_bounds(obligation, - snapshot); + this.match_projection_obligation_against_definition_bounds(obligation, snapshot); assert!(result); }) } - fn confirm_param_candidate(&mut self, - obligation: &TraitObligation<'tcx>, - param: ty::PolyTraitRef<'tcx>) - -> Vec> - { - debug!("confirm_param_candidate({:?},{:?})", - obligation, - param); + fn confirm_param_candidate( + &mut self, + obligation: &TraitObligation<'tcx>, + param: ty::PolyTraitRef<'tcx>, + ) -> Vec> { + debug!("confirm_param_candidate({:?},{:?})", obligation, param); // During evaluation, we already checked that this // where-clause trait-ref could be unified with the obligation @@ -2614,54 +2772,62 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { match self.match_where_clause_trait_ref(obligation, param.clone()) { Ok(obligations) => obligations, Err(()) => { - bug!("Where clause `{:?}` was applicable to `{:?}` but now is not", - param, - obligation); + bug!( + "Where clause `{:?}` was applicable to `{:?}` but now is not", + param, + obligation + ); } } } - fn confirm_builtin_candidate(&mut self, - obligation: &TraitObligation<'tcx>, - has_nested: bool) - -> VtableBuiltinData> - { - debug!("confirm_builtin_candidate({:?}, {:?})", - obligation, has_nested); + fn confirm_builtin_candidate( + &mut self, + obligation: &TraitObligation<'tcx>, + has_nested: bool, + ) -> VtableBuiltinData> { + debug!( + "confirm_builtin_candidate({:?}, {:?})", + obligation, has_nested + ); let lang_items = self.tcx().lang_items(); let obligations = if has_nested { let trait_def = obligation.predicate.def_id(); - let conditions = - if Some(trait_def) == lang_items.sized_trait() { - self.sized_conditions(obligation) - } else if Some(trait_def) == lang_items.copy_trait() { - self.copy_clone_conditions(obligation) - } else if Some(trait_def) == lang_items.clone_trait() { - self.copy_clone_conditions(obligation) - } else { - bug!("unexpected builtin trait {:?}", trait_def) + let conditions = if Some(trait_def) == lang_items.sized_trait() { + self.sized_conditions(obligation) + } else if Some(trait_def) == lang_items.copy_trait() { + self.copy_clone_conditions(obligation) + } else if Some(trait_def) == lang_items.clone_trait() { + self.copy_clone_conditions(obligation) + } else { + bug!("unexpected builtin trait {:?}", trait_def) }; let nested = match conditions { BuiltinImplConditions::Where(nested) => nested, - _ => bug!("obligation {:?} had matched a builtin impl but now doesn't", - obligation) + _ => bug!( + "obligation {:?} had matched a builtin impl but now doesn't", + obligation + ), }; let cause = obligation.derived_cause(BuiltinDerivedObligation); - self.collect_predicates_for_types(obligation.param_env, - cause, - obligation.recursion_depth+1, - trait_def, - nested) + self.collect_predicates_for_types( + obligation.param_env, + cause, + obligation.recursion_depth + 1, + trait_def, + nested, + ) } else { vec![] }; - debug!("confirm_builtin_candidate: obligations={:?}", - obligations); + debug!("confirm_builtin_candidate: obligations={:?}", obligations); - VtableBuiltinData { nested: obligations } + VtableBuiltinData { + nested: obligations, + } } /// This handles the case where a `auto trait Foo` impl is being used. @@ -2669,14 +2835,15 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { /// /// 1. For each constituent type `Y` in `X`, `Y : Foo` holds /// 2. For each where-clause `C` declared on `Foo`, `[Self => X] C` holds. - fn confirm_auto_impl_candidate(&mut self, - obligation: &TraitObligation<'tcx>, - trait_def_id: DefId) - -> VtableAutoImplData> - { - debug!("confirm_auto_impl_candidate({:?}, {:?})", - obligation, - trait_def_id); + fn confirm_auto_impl_candidate( + &mut self, + obligation: &TraitObligation<'tcx>, + trait_def_id: DefId, + ) -> VtableAutoImplData> { + debug!( + "confirm_auto_impl_candidate({:?}, {:?})", + obligation, trait_def_id + ); let types = obligation.predicate.map_bound(|inner| { let self_ty = self.infcx.shallow_resolve(inner.self_ty()); @@ -2686,12 +2853,12 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { } /// See `confirm_auto_impl_candidate` - fn vtable_auto_impl(&mut self, - obligation: &TraitObligation<'tcx>, - trait_def_id: DefId, - nested: ty::Binder>>) - -> VtableAutoImplData> - { + fn vtable_auto_impl( + &mut self, + obligation: &TraitObligation<'tcx>, + trait_def_id: DefId, + nested: ty::Binder>>, + ) -> VtableAutoImplData> { debug!("vtable_auto_impl: nested={:?}", nested); let cause = obligation.derived_cause(BuiltinDerivedObligation); @@ -2700,20 +2867,23 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { cause, obligation.recursion_depth + 1, trait_def_id, - nested); + nested, + ); let trait_obligations: Vec> = self.in_snapshot(|this, snapshot| { let poly_trait_ref = obligation.predicate.to_poly_trait_ref(); - let (trait_ref, skol_map) = - this.infcx().skolemize_late_bound_regions(&poly_trait_ref); + let (trait_ref, placeholder_map) = this.infcx() + .replace_late_bound_regions_with_placeholders(&poly_trait_ref); let cause = obligation.derived_cause(ImplDerivedObligation); - this.impl_or_trait_obligations(cause, - obligation.recursion_depth + 1, - obligation.param_env, - trait_def_id, - &trait_ref.substs, - skol_map, - snapshot) + this.impl_or_trait_obligations( + cause, + obligation.recursion_depth + 1, + obligation.param_env, + trait_def_id, + &trait_ref.substs, + placeholder_map, + snapshot, + ) }); // Adds the predicates from the trait. Note that this contains a `Self: Trait` @@ -2724,65 +2894,64 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { VtableAutoImplData { trait_def_id, - nested: obligations + nested: obligations, } } - fn confirm_impl_candidate(&mut self, - obligation: &TraitObligation<'tcx>, - impl_def_id: DefId) - -> VtableImplData<'tcx, PredicateObligation<'tcx>> - { - debug!("confirm_impl_candidate({:?},{:?})", - obligation, - impl_def_id); + fn confirm_impl_candidate( + &mut self, + obligation: &TraitObligation<'tcx>, + impl_def_id: DefId, + ) -> VtableImplData<'tcx, PredicateObligation<'tcx>> { + debug!("confirm_impl_candidate({:?},{:?})", obligation, impl_def_id); // First, create the substitutions by matching the impl again, // this time not in a probe. self.in_snapshot(|this, snapshot| { - let (substs, skol_map) = - this.rematch_impl(impl_def_id, obligation, - snapshot); + let (substs, placeholder_map) = this.rematch_impl(impl_def_id, obligation, snapshot); debug!("confirm_impl_candidate substs={:?}", substs); let cause = obligation.derived_cause(ImplDerivedObligation); - this.vtable_impl(impl_def_id, - substs, - cause, - obligation.recursion_depth + 1, - obligation.param_env, - skol_map, - snapshot) + this.vtable_impl( + impl_def_id, + substs, + cause, + obligation.recursion_depth + 1, + obligation.param_env, + placeholder_map, + snapshot, + ) }) } - fn vtable_impl(&mut self, - impl_def_id: DefId, - mut substs: Normalized<'tcx, &'tcx Substs<'tcx>>, - cause: ObligationCause<'tcx>, - recursion_depth: usize, - param_env: ty::ParamEnv<'tcx>, - skol_map: infer::SkolemizationMap<'tcx>, - snapshot: &infer::CombinedSnapshot<'cx, 'tcx>) - -> VtableImplData<'tcx, PredicateObligation<'tcx>> - { - debug!("vtable_impl(impl_def_id={:?}, substs={:?}, recursion_depth={}, skol_map={:?})", - impl_def_id, - substs, - recursion_depth, - skol_map); - - let mut impl_obligations = - self.impl_or_trait_obligations(cause, - recursion_depth, - param_env, - impl_def_id, - &substs.value, - skol_map, - snapshot); - - debug!("vtable_impl: impl_def_id={:?} impl_obligations={:?}", - impl_def_id, - impl_obligations); + fn vtable_impl( + &mut self, + impl_def_id: DefId, + mut substs: Normalized<'tcx, &'tcx Substs<'tcx>>, + cause: ObligationCause<'tcx>, + recursion_depth: usize, + param_env: ty::ParamEnv<'tcx>, + placeholder_map: infer::PlaceholderMap<'tcx>, + snapshot: &infer::CombinedSnapshot<'cx, 'tcx>, + ) -> VtableImplData<'tcx, PredicateObligation<'tcx>> { + debug!( + "vtable_impl(impl_def_id={:?}, substs={:?}, recursion_depth={}, placeholder_map={:?})", + impl_def_id, substs, recursion_depth, placeholder_map + ); + + let mut impl_obligations = self.impl_or_trait_obligations( + cause, + recursion_depth, + param_env, + impl_def_id, + &substs.value, + placeholder_map, + snapshot, + ); + + debug!( + "vtable_impl: impl_def_id={:?} impl_obligations={:?}", + impl_def_id, impl_obligations + ); // Because of RFC447, the impl-trait-ref and obligations // are sufficient to determine the impl substs, without @@ -2791,29 +2960,30 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { // e.g. `impl> Foo<::T> for V` impl_obligations.append(&mut substs.obligations); - VtableImplData { impl_def_id, - substs: substs.value, - nested: impl_obligations } + VtableImplData { + impl_def_id, + substs: substs.value, + nested: impl_obligations, + } } - fn confirm_object_candidate(&mut self, - obligation: &TraitObligation<'tcx>) - -> VtableObjectData<'tcx, PredicateObligation<'tcx>> - { - debug!("confirm_object_candidate({:?})", - obligation); + fn confirm_object_candidate( + &mut self, + obligation: &TraitObligation<'tcx>, + ) -> VtableObjectData<'tcx, PredicateObligation<'tcx>> { + debug!("confirm_object_candidate({:?})", obligation); // FIXME skipping binder here seems wrong -- we should // probably flatten the binder from the obligation and the // binder from the object. Have to try to make a broken test // case that results. -nmatsakis - let self_ty = self.infcx.shallow_resolve(*obligation.self_ty().skip_binder()); + let self_ty = self.infcx + .shallow_resolve(*obligation.self_ty().skip_binder()); let poly_trait_ref = match self_ty.sty { ty::Dynamic(ref data, ..) => { data.principal().unwrap().with_self_ty(self.tcx(), self_ty) } - _ => span_bug!(obligation.cause.span, - "object candidate with non-object") + _ => span_bug!(obligation.cause.span, "object candidate with non-object"), }; let mut upcast_trait_ref = None; @@ -2829,20 +2999,16 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { // where we can unify because otherwise select would have // reported an ambiguity. (When we do find a match, also // record it for later.) - let nonmatching = - util::supertraits(tcx, poly_trait_ref) - .take_while(|&t| - match self.commit_if_ok(|this, _| - this.match_poly_trait_ref(obligation, t)) - { - Ok(obligations) => { - upcast_trait_ref = Some(t); - nested.extend(obligations); - false - } - Err(_) => { true } + let nonmatching = util::supertraits(tcx, poly_trait_ref).take_while( + |&t| match self.commit_if_ok(|this, _| this.match_poly_trait_ref(obligation, t)) { + Ok(obligations) => { + upcast_trait_ref = Some(t); + nested.extend(obligations); + false } - ); + Err(_) => true, + }, + ); // Additionally, for each of the nonmatching predicates that // we pass over, we sum up the set of number of vtable @@ -2858,138 +3024,154 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { } } - fn confirm_fn_pointer_candidate(&mut self, obligation: &TraitObligation<'tcx>) - -> Result>, SelectionError<'tcx>> - { - debug!("confirm_fn_pointer_candidate({:?})", - obligation); + fn confirm_fn_pointer_candidate( + &mut self, + obligation: &TraitObligation<'tcx>, + ) -> Result>, SelectionError<'tcx>> { + debug!("confirm_fn_pointer_candidate({:?})", obligation); // ok to skip binder; it is reintroduced below - let self_ty = self.infcx.shallow_resolve(*obligation.self_ty().skip_binder()); + let self_ty = self.infcx + .shallow_resolve(*obligation.self_ty().skip_binder()); let sig = self_ty.fn_sig(self.tcx()); - let trait_ref = - self.tcx().closure_trait_ref_and_return_type(obligation.predicate.def_id(), - self_ty, - sig, - util::TupleArgumentsFlag::Yes) + let trait_ref = self.tcx() + .closure_trait_ref_and_return_type( + obligation.predicate.def_id(), + self_ty, + sig, + util::TupleArgumentsFlag::Yes, + ) .map_bound(|(trait_ref, _)| trait_ref); - let Normalized { value: trait_ref, obligations } = - project::normalize_with_depth(self, - obligation.param_env, - obligation.cause.clone(), - obligation.recursion_depth + 1, - &trait_ref); + let Normalized { + value: trait_ref, + obligations, + } = project::normalize_with_depth( + self, + obligation.param_env, + obligation.cause.clone(), + obligation.recursion_depth + 1, + &trait_ref, + ); - self.confirm_poly_trait_refs(obligation.cause.clone(), - obligation.param_env, - obligation.predicate.to_poly_trait_ref(), - trait_ref)?; - Ok(VtableFnPointerData { fn_ty: self_ty, nested: obligations }) + self.confirm_poly_trait_refs( + obligation.cause.clone(), + obligation.param_env, + obligation.predicate.to_poly_trait_ref(), + trait_ref, + )?; + Ok(VtableFnPointerData { + fn_ty: self_ty, + nested: obligations, + }) } - fn confirm_generator_candidate(&mut self, - obligation: &TraitObligation<'tcx>) - -> Result>, - SelectionError<'tcx>> - { + fn confirm_generator_candidate( + &mut self, + obligation: &TraitObligation<'tcx>, + ) -> Result>, SelectionError<'tcx>> { // ok to skip binder because the substs on generator types never // touch bound regions, they just capture the in-scope // type/region parameters - let self_ty = self.infcx.shallow_resolve(obligation.self_ty().skip_binder()); + let self_ty = self.infcx + .shallow_resolve(obligation.self_ty().skip_binder()); let (generator_def_id, substs) = match self_ty.sty { ty::Generator(id, substs, _) => (id, substs), - _ => bug!("closure candidate for non-closure {:?}", obligation) + _ => bug!("closure candidate for non-closure {:?}", obligation), }; - debug!("confirm_generator_candidate({:?},{:?},{:?})", - obligation, - generator_def_id, - substs); + debug!( + "confirm_generator_candidate({:?},{:?},{:?})", + obligation, generator_def_id, substs + ); - let trait_ref = - self.generator_trait_ref_unnormalized(obligation, generator_def_id, substs); + let trait_ref = self.generator_trait_ref_unnormalized(obligation, generator_def_id, substs); let Normalized { value: trait_ref, - mut obligations - } = normalize_with_depth(self, - obligation.param_env, - obligation.cause.clone(), - obligation.recursion_depth+1, - &trait_ref); - - debug!("confirm_generator_candidate(generator_def_id={:?}, \ - trait_ref={:?}, obligations={:?})", - generator_def_id, - trait_ref, - obligations); - - obligations.extend( - self.confirm_poly_trait_refs(obligation.cause.clone(), - obligation.param_env, - obligation.predicate.to_poly_trait_ref(), - trait_ref)?); + mut obligations, + } = normalize_with_depth( + self, + obligation.param_env, + obligation.cause.clone(), + obligation.recursion_depth + 1, + &trait_ref, + ); + + debug!( + "confirm_generator_candidate(generator_def_id={:?}, \ + trait_ref={:?}, obligations={:?})", + generator_def_id, trait_ref, obligations + ); + + obligations.extend(self.confirm_poly_trait_refs( + obligation.cause.clone(), + obligation.param_env, + obligation.predicate.to_poly_trait_ref(), + trait_ref, + )?); Ok(VtableGeneratorData { generator_def_id: generator_def_id, substs: substs.clone(), - nested: obligations + nested: obligations, }) } - fn confirm_closure_candidate(&mut self, - obligation: &TraitObligation<'tcx>) - -> Result>, - SelectionError<'tcx>> - { + fn confirm_closure_candidate( + &mut self, + obligation: &TraitObligation<'tcx>, + ) -> Result>, SelectionError<'tcx>> { debug!("confirm_closure_candidate({:?})", obligation); let kind = self.tcx() - .lang_items() - .fn_trait_kind(obligation.predicate.def_id()) - .unwrap_or_else(|| bug!("closure candidate for non-fn trait {:?}", - obligation)); + .lang_items() + .fn_trait_kind(obligation.predicate.def_id()) + .unwrap_or_else(|| bug!("closure candidate for non-fn trait {:?}", obligation)); // ok to skip binder because the substs on closure types never // touch bound regions, they just capture the in-scope // type/region parameters - let self_ty = self.infcx.shallow_resolve(obligation.self_ty().skip_binder()); + let self_ty = self.infcx + .shallow_resolve(obligation.self_ty().skip_binder()); let (closure_def_id, substs) = match self_ty.sty { ty::Closure(id, substs) => (id, substs), - _ => bug!("closure candidate for non-closure {:?}", obligation) + _ => bug!("closure candidate for non-closure {:?}", obligation), }; - let trait_ref = - self.closure_trait_ref_unnormalized(obligation, closure_def_id, substs); + let trait_ref = self.closure_trait_ref_unnormalized(obligation, closure_def_id, substs); let Normalized { value: trait_ref, - mut obligations - } = normalize_with_depth(self, - obligation.param_env, - obligation.cause.clone(), - obligation.recursion_depth+1, - &trait_ref); - - debug!("confirm_closure_candidate(closure_def_id={:?}, trait_ref={:?}, obligations={:?})", - closure_def_id, - trait_ref, - obligations); - - obligations.extend( - self.confirm_poly_trait_refs(obligation.cause.clone(), - obligation.param_env, - obligation.predicate.to_poly_trait_ref(), - trait_ref)?); + mut obligations, + } = normalize_with_depth( + self, + obligation.param_env, + obligation.cause.clone(), + obligation.recursion_depth + 1, + &trait_ref, + ); + + debug!( + "confirm_closure_candidate(closure_def_id={:?}, trait_ref={:?}, obligations={:?})", + closure_def_id, trait_ref, obligations + ); + + obligations.extend(self.confirm_poly_trait_refs( + obligation.cause.clone(), + obligation.param_env, + obligation.predicate.to_poly_trait_ref(), + trait_ref, + )?); obligations.push(Obligation::new( obligation.cause.clone(), obligation.param_env, - ty::Predicate::ClosureKind(closure_def_id, substs, kind))); + ty::Predicate::ClosureKind(closure_def_id, substs, kind), + )); Ok(VtableClosureData { closure_def_id, substs: substs.clone(), - nested: obligations + nested: obligations, }) } @@ -3018,13 +3200,13 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { /// because these output type parameters should not affect the /// selection of the impl. Therefore, if there is a mismatch, we /// report an error to the user. - fn confirm_poly_trait_refs(&mut self, - obligation_cause: ObligationCause<'tcx>, - obligation_param_env: ty::ParamEnv<'tcx>, - obligation_trait_ref: ty::PolyTraitRef<'tcx>, - expected_trait_ref: ty::PolyTraitRef<'tcx>) - -> Result>, SelectionError<'tcx>> - { + fn confirm_poly_trait_refs( + &mut self, + obligation_cause: ObligationCause<'tcx>, + obligation_param_env: ty::ParamEnv<'tcx>, + obligation_trait_ref: ty::PolyTraitRef<'tcx>, + expected_trait_ref: ty::PolyTraitRef<'tcx>, + ) -> Result>, SelectionError<'tcx>> { let obligation_trait_ref = obligation_trait_ref.clone(); self.infcx .at(&obligation_cause, obligation_param_env) @@ -3033,21 +3215,28 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { .map_err(|e| OutputTypeParameterMismatch(expected_trait_ref, obligation_trait_ref, e)) } - fn confirm_builtin_unsize_candidate(&mut self, - obligation: &TraitObligation<'tcx>,) - -> Result>, SelectionError<'tcx>> - { + fn confirm_builtin_unsize_candidate( + &mut self, + obligation: &TraitObligation<'tcx>, + ) -> Result>, SelectionError<'tcx>> { let tcx = self.tcx(); // assemble_candidates_for_unsizing should ensure there are no late bound // regions here. See the comment there for more details. - let source = self.infcx.shallow_resolve( - obligation.self_ty().no_late_bound_regions().unwrap()); - let target = obligation.predicate.skip_binder().trait_ref.substs.type_at(1); + let source = self.infcx + .shallow_resolve(obligation.self_ty().no_late_bound_regions().unwrap()); + let target = obligation + .predicate + .skip_binder() + .trait_ref + .substs + .type_at(1); let target = self.infcx.shallow_resolve(target); - debug!("confirm_builtin_unsize_candidate(source={:?}, target={:?})", - source, target); + debug!( + "confirm_builtin_unsize_candidate(source={:?}, target={:?})", + source, target + ); let mut nested = vec![]; match (&source.sty, &target.sty) { @@ -3056,47 +3245,64 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { // See assemble_candidates_for_unsizing for more info. let existential_predicates = data_a.map_bound(|data_a| { let principal = data_a.principal(); - let iter = principal.into_iter().map(ty::ExistentialPredicate::Trait) - .chain(data_a.projection_bounds() - .map(|x| ty::ExistentialPredicate::Projection(x))) - .chain(data_b.auto_traits().map(ty::ExistentialPredicate::AutoTrait)); + let iter = principal + .into_iter() + .map(ty::ExistentialPredicate::Trait) + .chain( + data_a + .projection_bounds() + .map(|x| ty::ExistentialPredicate::Projection(x)), + ) + .chain( + data_b + .auto_traits() + .map(ty::ExistentialPredicate::AutoTrait), + ); tcx.mk_existential_predicates(iter) }); let new_trait = tcx.mk_dynamic(existential_predicates, r_b); - let InferOk { obligations, .. } = - self.infcx.at(&obligation.cause, obligation.param_env) - .eq(target, new_trait) - .map_err(|_| Unimplemented)?; + let InferOk { obligations, .. } = self.infcx + .at(&obligation.cause, obligation.param_env) + .eq(target, new_trait) + .map_err(|_| Unimplemented)?; nested.extend(obligations); // Register one obligation for 'a: 'b. - let cause = ObligationCause::new(obligation.cause.span, - obligation.cause.body_id, - ObjectCastObligation(target)); + let cause = ObligationCause::new( + obligation.cause.span, + obligation.cause.body_id, + ObjectCastObligation(target), + ); let outlives = ty::OutlivesPredicate(r_a, r_b); - nested.push(Obligation::with_depth(cause, - obligation.recursion_depth + 1, - obligation.param_env, - ty::Binder::bind(outlives).to_predicate())); + nested.push(Obligation::with_depth( + cause, + obligation.recursion_depth + 1, + obligation.param_env, + ty::Binder::bind(outlives).to_predicate(), + )); } // T -> Trait. (_, &ty::Dynamic(ref data, r)) => { - let mut object_dids = - data.auto_traits().chain(data.principal().map(|p| p.def_id())); + let mut object_dids = data.auto_traits() + .chain(data.principal().map(|p| p.def_id())); if let Some(did) = object_dids.find(|did| !tcx.is_object_safe(*did)) { - return Err(TraitNotObjectSafe(did)) + return Err(TraitNotObjectSafe(did)); } - let cause = ObligationCause::new(obligation.cause.span, - obligation.cause.body_id, - ObjectCastObligation(target)); + let cause = ObligationCause::new( + obligation.cause.span, + obligation.cause.body_id, + ObjectCastObligation(target), + ); let predicate_to_obligation = |predicate| { - Obligation::with_depth(cause.clone(), - obligation.recursion_depth + 1, - obligation.param_env, - predicate) + Obligation::with_depth( + cause.clone(), + obligation.recursion_depth + 1, + obligation.param_env, + predicate, + ) }; // Create obligations: @@ -3105,9 +3311,10 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { // words, if the object type is Foo+Send, this would create an obligation for the // Send check.) // - Projection predicates - nested.extend(data.iter().map(|d| - predicate_to_obligation(d.with_self_ty(tcx, source)) - )); + nested.extend( + data.iter() + .map(|d| predicate_to_obligation(d.with_self_ty(tcx, source))), + ); // We can only make objects from sized types. let tr = ty::TraitRef { @@ -3120,22 +3327,22 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { // being cast to `Foo+'a` outlives `'a`: let outlives = ty::OutlivesPredicate(source, r); nested.push(predicate_to_obligation( - ty::Binder::dummy(outlives).to_predicate())); + ty::Binder::dummy(outlives).to_predicate(), + )); } // [T; n] -> [T]. (&ty::Array(a, _), &ty::Slice(b)) => { - let InferOk { obligations, .. } = - self.infcx.at(&obligation.cause, obligation.param_env) - .eq(b, a) - .map_err(|_| Unimplemented)?; + let InferOk { obligations, .. } = self.infcx + .at(&obligation.cause, obligation.param_env) + .eq(b, a) + .map_err(|_| Unimplemented)?; nested.extend(obligations); } // Struct -> Struct. (&ty::Adt(def, substs_a), &ty::Adt(_, substs_b)) => { - let fields = def - .all_fields() + let fields = def.all_fields() .map(|f| tcx.type_of(f.did)) .collect::>(); @@ -3181,18 +3388,18 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { // Check that the source struct with the target's // unsized parameters is equal to the target. - let params = substs_a.iter().enumerate().map(|(i, &k)| + let params = substs_a.iter().enumerate().map(|(i, &k)| { if ty_params.contains(i) { substs_b.type_at(i).into() } else { k } - ); + }); let new_struct = tcx.mk_adt(def, tcx.mk_substs(params)); - let InferOk { obligations, .. } = - self.infcx.at(&obligation.cause, obligation.param_env) - .eq(target, new_struct) - .map_err(|_| Unimplemented)?; + let InferOk { obligations, .. } = self.infcx + .at(&obligation.cause, obligation.param_env) + .eq(target, new_struct) + .map_err(|_| Unimplemented)?; nested.extend(obligations); // Construct the nested Field: Unsize> predicate. @@ -3202,7 +3409,8 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { obligation.predicate.def_id(), obligation.recursion_depth + 1, inner_source, - &[inner_target.into()])); + &[inner_target.into()], + )); } // (.., T) -> (.., U). @@ -3220,10 +3428,10 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { // Check that the source tuple with the target's // last element is equal to the target. let new_tuple = tcx.mk_tup(a_mid.iter().cloned().chain(iter::once(b_last))); - let InferOk { obligations, .. } = - self.infcx.at(&obligation.cause, obligation.param_env) - .eq(target, new_tuple) - .map_err(|_| Unimplemented)?; + let InferOk { obligations, .. } = self.infcx + .at(&obligation.cause, obligation.param_env) + .eq(target, new_tuple) + .map_err(|_| Unimplemented)?; nested.extend(obligations); // Construct the nested T: Unsize predicate. @@ -3233,10 +3441,11 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { obligation.predicate.def_id(), obligation.recursion_depth + 1, a_last, - &[b_last.into()])); + &[b_last.into()], + )); } - _ => bug!() + _ => bug!(), }; Ok(VtableBuiltinData { nested: nested }) @@ -3252,30 +3461,39 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { // run inside of a `probe()` so that their side-effects are // contained. - fn rematch_impl(&mut self, - impl_def_id: DefId, - obligation: &TraitObligation<'tcx>, - snapshot: &infer::CombinedSnapshot<'cx, 'tcx>) - -> (Normalized<'tcx, &'tcx Substs<'tcx>>, - infer::SkolemizationMap<'tcx>) - { + fn rematch_impl( + &mut self, + impl_def_id: DefId, + obligation: &TraitObligation<'tcx>, + snapshot: &infer::CombinedSnapshot<'cx, 'tcx>, + ) -> ( + Normalized<'tcx, &'tcx Substs<'tcx>>, + infer::PlaceholderMap<'tcx>, + ) { match self.match_impl(impl_def_id, obligation, snapshot) { - Ok((substs, skol_map)) => (substs, skol_map), + Ok((substs, placeholder_map)) => (substs, placeholder_map), Err(()) => { - bug!("Impl {:?} was matchable against {:?} but now is not", - impl_def_id, - obligation); + bug!( + "Impl {:?} was matchable against {:?} but now is not", + impl_def_id, + obligation + ); } } } - fn match_impl(&mut self, - impl_def_id: DefId, - obligation: &TraitObligation<'tcx>, - snapshot: &infer::CombinedSnapshot<'cx, 'tcx>) - -> Result<(Normalized<'tcx, &'tcx Substs<'tcx>>, - infer::SkolemizationMap<'tcx>), ()> - { + fn match_impl( + &mut self, + impl_def_id: DefId, + obligation: &TraitObligation<'tcx>, + snapshot: &infer::CombinedSnapshot<'cx, 'tcx>, + ) -> Result< + ( + Normalized<'tcx, &'tcx Substs<'tcx>>, + infer::PlaceholderMap<'tcx>, + ), + (), + > { let impl_trait_ref = self.tcx().impl_trait_ref(impl_def_id).unwrap(); // Before we create the substitutions and everything, first @@ -3285,73 +3503,78 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { return Err(()); } - let (skol_obligation, skol_map) = self.infcx().skolemize_late_bound_regions( - &obligation.predicate); + let (skol_obligation, placeholder_map) = self.infcx() + .replace_late_bound_regions_with_placeholders(&obligation.predicate); let skol_obligation_trait_ref = skol_obligation.trait_ref; - let impl_substs = self.infcx.fresh_substs_for_item(obligation.cause.span, - impl_def_id); - - let impl_trait_ref = impl_trait_ref.subst(self.tcx(), - impl_substs); - - let Normalized { value: impl_trait_ref, obligations: mut nested_obligations } = - project::normalize_with_depth(self, - obligation.param_env, - obligation.cause.clone(), - obligation.recursion_depth + 1, - &impl_trait_ref); - - debug!("match_impl(impl_def_id={:?}, obligation={:?}, \ - impl_trait_ref={:?}, skol_obligation_trait_ref={:?})", - impl_def_id, - obligation, - impl_trait_ref, - skol_obligation_trait_ref); - - let InferOk { obligations, .. } = - self.infcx.at(&obligation.cause, obligation.param_env) - .eq(skol_obligation_trait_ref, impl_trait_ref) - .map_err(|e| - debug!("match_impl: failed eq_trait_refs due to `{}`", e) - )?; + let impl_substs = self.infcx + .fresh_substs_for_item(obligation.cause.span, impl_def_id); + + let impl_trait_ref = impl_trait_ref.subst(self.tcx(), impl_substs); + + let Normalized { + value: impl_trait_ref, + obligations: mut nested_obligations, + } = project::normalize_with_depth( + self, + obligation.param_env, + obligation.cause.clone(), + obligation.recursion_depth + 1, + &impl_trait_ref, + ); + + debug!( + "match_impl(impl_def_id={:?}, obligation={:?}, \ + impl_trait_ref={:?}, skol_obligation_trait_ref={:?})", + impl_def_id, obligation, impl_trait_ref, skol_obligation_trait_ref + ); + + let InferOk { obligations, .. } = self.infcx + .at(&obligation.cause, obligation.param_env) + .eq(skol_obligation_trait_ref, impl_trait_ref) + .map_err(|e| debug!("match_impl: failed eq_trait_refs due to `{}`", e))?; nested_obligations.extend(obligations); - if let Err(e) = self.infcx.leak_check(false, - obligation.cause.span, - &skol_map, - snapshot) { + if let Err(e) = + self.infcx + .leak_check(false, obligation.cause.span, &placeholder_map, snapshot) + { debug!("match_impl: failed leak check due to `{}`", e); return Err(()); } debug!("match_impl: success impl_substs={:?}", impl_substs); - Ok((Normalized { - value: impl_substs, - obligations: nested_obligations - }, skol_map)) + Ok(( + Normalized { + value: impl_substs, + obligations: nested_obligations, + }, + placeholder_map, + )) } - fn fast_reject_trait_refs(&mut self, - obligation: &TraitObligation<'_>, - impl_trait_ref: &ty::TraitRef<'_>) - -> bool - { + fn fast_reject_trait_refs( + &mut self, + obligation: &TraitObligation<'_>, + impl_trait_ref: &ty::TraitRef<'_>, + ) -> bool { // We can avoid creating type variables and doing the full // substitution if we find that any of the input types, when // simplified, do not match. - obligation.predicate.skip_binder().input_types() + obligation + .predicate + .skip_binder() + .input_types() .zip(impl_trait_ref.input_types()) .any(|(obligation_ty, impl_ty)| { let simplified_obligation_ty = fast_reject::simplify_type(self.tcx(), obligation_ty, true); - let simplified_impl_ty = - fast_reject::simplify_type(self.tcx(), impl_ty, false); + let simplified_impl_ty = fast_reject::simplify_type(self.tcx(), impl_ty, false); - simplified_obligation_ty.is_some() && - simplified_impl_ty.is_some() && - simplified_obligation_ty != simplified_impl_ty + simplified_obligation_ty.is_some() + && simplified_impl_ty.is_some() + && simplified_obligation_ty != simplified_impl_ty }) } @@ -3360,50 +3583,54 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { /// result from the normalization. Normalization is necessary /// because where-clauses are stored in the parameter environment /// unnormalized. - fn match_where_clause_trait_ref(&mut self, - obligation: &TraitObligation<'tcx>, - where_clause_trait_ref: ty::PolyTraitRef<'tcx>) - -> Result>, ()> - { + fn match_where_clause_trait_ref( + &mut self, + obligation: &TraitObligation<'tcx>, + where_clause_trait_ref: ty::PolyTraitRef<'tcx>, + ) -> Result>, ()> { self.match_poly_trait_ref(obligation, where_clause_trait_ref) } /// Returns `Ok` if `poly_trait_ref` being true implies that the /// obligation is satisfied. - fn match_poly_trait_ref(&mut self, - obligation: &TraitObligation<'tcx>, - poly_trait_ref: ty::PolyTraitRef<'tcx>) - -> Result>, ()> - { - debug!("match_poly_trait_ref: obligation={:?} poly_trait_ref={:?}", - obligation, - poly_trait_ref); + fn match_poly_trait_ref( + &mut self, + obligation: &TraitObligation<'tcx>, + poly_trait_ref: ty::PolyTraitRef<'tcx>, + ) -> Result>, ()> { + debug!( + "match_poly_trait_ref: obligation={:?} poly_trait_ref={:?}", + obligation, poly_trait_ref + ); - self.infcx.at(&obligation.cause, obligation.param_env) - .sup(obligation.predicate.to_poly_trait_ref(), poly_trait_ref) - .map(|InferOk { obligations, .. }| obligations) - .map_err(|_| ()) + self.infcx + .at(&obligation.cause, obligation.param_env) + .sup(obligation.predicate.to_poly_trait_ref(), poly_trait_ref) + .map(|InferOk { obligations, .. }| obligations) + .map_err(|_| ()) } /////////////////////////////////////////////////////////////////////////// // Miscellany - fn match_fresh_trait_refs(&self, - previous: &ty::PolyTraitRef<'tcx>, - current: &ty::PolyTraitRef<'tcx>) - -> bool - { + fn match_fresh_trait_refs( + &self, + previous: &ty::PolyTraitRef<'tcx>, + current: &ty::PolyTraitRef<'tcx>, + ) -> bool { let mut matcher = ty::_match::Match::new(self.tcx()); matcher.relate(previous, current).is_ok() } - fn push_stack<'o,'s:'o>(&mut self, - previous_stack: TraitObligationStackList<'s, 'tcx>, - obligation: &'o TraitObligation<'tcx>) - -> TraitObligationStack<'o, 'tcx> - { - let fresh_trait_ref = - obligation.predicate.to_poly_trait_ref().fold_with(&mut self.freshener); + fn push_stack<'o, 's: 'o>( + &mut self, + previous_stack: TraitObligationStackList<'s, 'tcx>, + obligation: &'o TraitObligation<'tcx>, + ) -> TraitObligationStack<'o, 'tcx> { + let fresh_trait_ref = obligation + .predicate + .to_poly_trait_ref() + .fold_with(&mut self.freshener); TraitObligationStack { obligation, @@ -3412,12 +3639,12 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { } } - fn closure_trait_ref_unnormalized(&mut self, - obligation: &TraitObligation<'tcx>, - closure_def_id: DefId, - substs: ty::ClosureSubsts<'tcx>) - -> ty::PolyTraitRef<'tcx> - { + fn closure_trait_ref_unnormalized( + &mut self, + obligation: &TraitObligation<'tcx>, + closure_def_id: DefId, + substs: ty::ClosureSubsts<'tcx>, + ) -> ty::PolyTraitRef<'tcx> { let closure_type = self.infcx.closure_sig(closure_def_id, substs); // (1) Feels icky to skip the binder here, but OTOH we know @@ -3425,21 +3652,22 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { // in fact unparameterized (or at least does not reference any // regions bound in the obligation). Still probably some // refactoring could make this nicer. - self.tcx().closure_trait_ref_and_return_type(obligation.predicate.def_id(), - obligation.predicate - .skip_binder() - .self_ty(), // (1) - closure_type, - util::TupleArgumentsFlag::No) + self.tcx() + .closure_trait_ref_and_return_type( + obligation.predicate.def_id(), + obligation.predicate.skip_binder().self_ty(), // (1) + closure_type, + util::TupleArgumentsFlag::No, + ) .map_bound(|(trait_ref, _)| trait_ref) } - fn generator_trait_ref_unnormalized(&mut self, - obligation: &TraitObligation<'tcx>, - closure_def_id: DefId, - substs: ty::GeneratorSubsts<'tcx>) - -> ty::PolyTraitRef<'tcx> - { + fn generator_trait_ref_unnormalized( + &mut self, + obligation: &TraitObligation<'tcx>, + closure_def_id: DefId, + substs: ty::GeneratorSubsts<'tcx>, + ) -> ty::PolyTraitRef<'tcx> { let gen_sig = substs.poly_sig(closure_def_id, self.tcx()); // (1) Feels icky to skip the binder here, but OTOH we know @@ -3448,11 +3676,12 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { // regions bound in the obligation). Still probably some // refactoring could make this nicer. - self.tcx().generator_trait_ref_and_outputs(obligation.predicate.def_id(), - obligation.predicate - .skip_binder() - .self_ty(), // (1) - gen_sig) + self.tcx() + .generator_trait_ref_and_outputs( + obligation.predicate.def_id(), + obligation.predicate.skip_binder().self_ty(), // (1) + gen_sig, + ) .map_bound(|(trait_ref, ..)| trait_ref) } @@ -3460,16 +3689,16 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { /// impl or trait. The obligations are substituted and fully /// normalized. This is used when confirming an impl or default /// impl. - fn impl_or_trait_obligations(&mut self, - cause: ObligationCause<'tcx>, - recursion_depth: usize, - param_env: ty::ParamEnv<'tcx>, - def_id: DefId, // of impl or trait - substs: &Substs<'tcx>, // for impl or trait - skol_map: infer::SkolemizationMap<'tcx>, - snapshot: &infer::CombinedSnapshot<'cx, 'tcx>) - -> Vec> - { + fn impl_or_trait_obligations( + &mut self, + cause: ObligationCause<'tcx>, + recursion_depth: usize, + param_env: ty::ParamEnv<'tcx>, + def_id: DefId, // of impl or trait + substs: &Substs<'tcx>, // for impl or trait + placeholder_map: infer::PlaceholderMap<'tcx>, + snapshot: &infer::CombinedSnapshot<'cx, 'tcx>, + ) -> Vec> { debug!("impl_or_trait_obligations(def_id={:?})", def_id); let tcx = self.tcx(); @@ -3489,17 +3718,25 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { // that order. let predicates = tcx.predicates_of(def_id); assert_eq!(predicates.parent, None); - let mut predicates: Vec<_> = predicates.predicates.iter().flat_map(|(predicate, _)| { - let predicate = normalize_with_depth(self, param_env, cause.clone(), recursion_depth, - &predicate.subst(tcx, substs)); - predicate.obligations.into_iter().chain( - Some(Obligation { + let mut predicates: Vec<_> = predicates + .predicates + .iter() + .flat_map(|(predicate, _)| { + let predicate = normalize_with_depth( + self, + param_env, + cause.clone(), + recursion_depth, + &predicate.subst(tcx, substs), + ); + predicate.obligations.into_iter().chain(Some(Obligation { cause: cause.clone(), recursion_depth, param_env, - predicate: predicate.value + predicate: predicate.value, })) - }).collect(); + }) + .collect(); // We are performing deduplication here to avoid exponential blowups // (#38528) from happening, but the real cause of the duplication is @@ -3522,16 +3759,17 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { let mut seen = FxHashSet(); predicates.retain(|i| seen.insert(i.clone())); } - self.infcx().plug_leaks(skol_map, snapshot, predicates) + self.infcx() + .plug_leaks(placeholder_map, snapshot, predicates) } } impl<'tcx> TraitObligation<'tcx> { #[allow(unused_comparisons)] - pub fn derived_cause(&self, - variant: fn(DerivedObligationCause<'tcx>) -> ObligationCauseCode<'tcx>) - -> ObligationCause<'tcx> - { + pub fn derived_cause( + &self, + variant: fn(DerivedObligationCause<'tcx>) -> ObligationCauseCode<'tcx>, + ) -> ObligationCause<'tcx> { /*! * Creates a cause for obligations that are derived from * `obligation` by a recursive search (e.g., for a builtin @@ -3550,10 +3788,14 @@ impl<'tcx> TraitObligation<'tcx> { if obligation.recursion_depth >= 0 { let derived_cause = DerivedObligationCause { parent_trait_ref: obligation.predicate.to_poly_trait_ref(), - parent_code: Rc::new(obligation.cause.code.clone()) + parent_code: Rc::new(obligation.cause.code.clone()), }; let derived_code = variant(derived_cause); - ObligationCause::new(obligation.cause.span, obligation.cause.body_id, derived_code) + ObligationCause::new( + obligation.cause.span, + obligation.cause.body_id, + derived_code, + ) } else { obligation.cause.clone() } @@ -3563,7 +3805,7 @@ impl<'tcx> TraitObligation<'tcx> { impl<'tcx> SelectionCache<'tcx> { pub fn new() -> SelectionCache<'tcx> { SelectionCache { - hashmap: Lock::new(FxHashMap()) + hashmap: Lock::new(FxHashMap()), } } @@ -3575,7 +3817,7 @@ impl<'tcx> SelectionCache<'tcx> { impl<'tcx> EvaluationCache<'tcx> { pub fn new() -> EvaluationCache<'tcx> { EvaluationCache { - hashmap: Lock::new(FxHashMap()) + hashmap: Lock::new(FxHashMap()), } } @@ -3584,46 +3826,46 @@ impl<'tcx> EvaluationCache<'tcx> { } } -impl<'o,'tcx> TraitObligationStack<'o,'tcx> { - fn list(&'o self) -> TraitObligationStackList<'o,'tcx> { +impl<'o, 'tcx> TraitObligationStack<'o, 'tcx> { + fn list(&'o self) -> TraitObligationStackList<'o, 'tcx> { TraitObligationStackList::with(self) } - fn iter(&'o self) -> TraitObligationStackList<'o,'tcx> { + fn iter(&'o self) -> TraitObligationStackList<'o, 'tcx> { self.list() } } #[derive(Copy, Clone)] -struct TraitObligationStackList<'o,'tcx:'o> { - head: Option<&'o TraitObligationStack<'o,'tcx>> +struct TraitObligationStackList<'o, 'tcx: 'o> { + head: Option<&'o TraitObligationStack<'o, 'tcx>>, } -impl<'o,'tcx> TraitObligationStackList<'o,'tcx> { - fn empty() -> TraitObligationStackList<'o,'tcx> { +impl<'o, 'tcx> TraitObligationStackList<'o, 'tcx> { + fn empty() -> TraitObligationStackList<'o, 'tcx> { TraitObligationStackList { head: None } } - fn with(r: &'o TraitObligationStack<'o,'tcx>) -> TraitObligationStackList<'o,'tcx> { + fn with(r: &'o TraitObligationStack<'o, 'tcx>) -> TraitObligationStackList<'o, 'tcx> { TraitObligationStackList { head: Some(r) } } } -impl<'o,'tcx> Iterator for TraitObligationStackList<'o,'tcx>{ - type Item = &'o TraitObligationStack<'o,'tcx>; +impl<'o, 'tcx> Iterator for TraitObligationStackList<'o, 'tcx> { + type Item = &'o TraitObligationStack<'o, 'tcx>; - fn next(&mut self) -> Option<&'o TraitObligationStack<'o,'tcx>> { + fn next(&mut self) -> Option<&'o TraitObligationStack<'o, 'tcx>> { match self.head { Some(o) => { *self = o.previous; Some(o) } - None => None + None => None, } } } -impl<'o,'tcx> fmt::Debug for TraitObligationStack<'o,'tcx> { +impl<'o, 'tcx> fmt::Debug for TraitObligationStack<'o, 'tcx> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "TraitObligationStack({:?})", self.obligation) } @@ -3632,12 +3874,15 @@ impl<'o,'tcx> fmt::Debug for TraitObligationStack<'o,'tcx> { #[derive(Clone, Eq, PartialEq)] pub struct WithDepNode { dep_node: DepNodeIndex, - cached_value: T + cached_value: T, } impl WithDepNode { pub fn new(dep_node: DepNodeIndex, cached_value: T) -> Self { - WithDepNode { dep_node, cached_value } + WithDepNode { + dep_node, + cached_value, + } } pub fn get(&self, tcx: TyCtxt<'_, '_, '_>) -> T { diff --git a/src/librustc/traits/specialize/mod.rs b/src/librustc/traits/specialize/mod.rs index 84ffa22e5dd2e..2c713c0f7f1aa 100644 --- a/src/librustc/traits/specialize/mod.rs +++ b/src/librustc/traits/specialize/mod.rs @@ -184,7 +184,7 @@ pub(super) fn specializes<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, return false; } - // create a parameter environment corresponding to a (skolemized) instantiation of impl1 + // create a parameter environment corresponding to a (placeholder) instantiation of impl1 let penv = tcx.param_env(impl1_def_id); let impl1_trait_ref = tcx.impl_trait_ref(impl1_def_id).unwrap(); diff --git a/src/librustc/ty/error.rs b/src/librustc/ty/error.rs index b3a1b312ca1d3..a1edf67e47552 100644 --- a/src/librustc/ty/error.rs +++ b/src/librustc/ty/error.rs @@ -218,9 +218,9 @@ impl<'a, 'gcx, 'lcx, 'tcx> ty::TyS<'tcx> { ty::Infer(ty::IntVar(_)) => "integral variable".to_string(), ty::Infer(ty::FloatVar(_)) => "floating-point variable".to_string(), ty::Infer(ty::CanonicalTy(_)) | - ty::Infer(ty::FreshTy(_)) => "skolemized type".to_string(), - ty::Infer(ty::FreshIntTy(_)) => "skolemized integral type".to_string(), - ty::Infer(ty::FreshFloatTy(_)) => "skolemized floating-point type".to_string(), + ty::Infer(ty::FreshTy(_)) => "fresh type".to_string(), + ty::Infer(ty::FreshIntTy(_)) => "fresh integral type".to_string(), + ty::Infer(ty::FreshFloatTy(_)) => "fresh floating-point type".to_string(), ty::Projection(_) => "associated type".to_string(), ty::UnnormalizedProjection(_) => "non-normalized associated type".to_string(), ty::Param(ref p) => { diff --git a/src/librustc/ty/fold.rs b/src/librustc/ty/fold.rs index 6bf493b496c8b..1c5ff85d69ba6 100644 --- a/src/librustc/ty/fold.rs +++ b/src/librustc/ty/fold.rs @@ -667,12 +667,14 @@ pub fn shift_regions<'a, 'gcx, 'tcx, T>(tcx: TyCtxt<'a, 'gcx, 'tcx>, /// we already use the term "free region". It refers to the regions that we use to represent bound /// regions on a fn definition while we are typechecking its body. /// -/// To clarify, conceptually there is no particular difference between an "escaping" region and a -/// "free" region. However, there is a big difference in practice. Basically, when "entering" a -/// binding level, one is generally required to do some sort of processing to a bound region, such -/// as replacing it with a fresh/skolemized region, or making an entry in the environment to -/// represent the scope to which it is attached, etc. An escaping region represents a bound region -/// for which this processing has not yet been done. +/// To clarify, conceptually there is no particular difference between +/// an "escaping" region and a "free" region. However, there is a big +/// difference in practice. Basically, when "entering" a binding +/// level, one is generally required to do some sort of processing to +/// a bound region, such as replacing it with a fresh/placeholder +/// region, or making an entry in the environment to represent the +/// scope to which it is attached, etc. An escaping region represents +/// a bound region for which this processing has not yet been done. struct HasEscapingRegionsVisitor { /// Anything bound by `outer_index` or "above" is escaping outer_index: ty::DebruijnIndex, diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index 72232084bf7ea..08a9f08519b7e 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -1479,18 +1479,17 @@ impl<'tcx> InstantiatedPredicates<'tcx> { /// region `'a` is in a subuniverse U2 of U1, because we can name it /// inside the fn type but not outside. /// -/// Universes are related to **skolemization** -- which is a way of -/// doing type- and trait-checking around these "forall" binders (also -/// called **universal quantification**). The idea is that when, in -/// the body of `bar`, we refer to `T` as a type, we aren't referring -/// to any type in particular, but rather a kind of "fresh" type that -/// is distinct from all other types we have actually declared. This -/// is called a **skolemized** type, and we use universes to talk -/// about this. In other words, a type name in universe 0 always -/// corresponds to some "ground" type that the user declared, but a -/// type name in a non-zero universe is a skolemized type -- an -/// idealized representative of "types in general" that we use for -/// checking generic functions. +/// Universes are used to do type- and trait-checking around these +/// "forall" binders (also called **universal quantification**). The +/// idea is that when, in the body of `bar`, we refer to `T` as a +/// type, we aren't referring to any type in particular, but rather a +/// kind of "fresh" type that is distinct from all other types we have +/// actually declared. This is called a **placeholder** type, and we +/// use universes to talk about this. In other words, a type name in +/// universe 0 always corresponds to some "ground" type that the user +/// declared, but a type name in a non-zero universe is a placeholder +/// type -- an idealized representative of "types in general" that we +/// use for checking generic functions. #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable)] pub struct UniverseIndex(u32); @@ -1553,6 +1552,18 @@ impl From for UniverseIndex { } } +/// The "placeholder index" fully defines a placeholder region. +/// Placeholder regions are identified by both a **universe** as well +/// as a "bound-region" within that universe. The `bound_region` is +/// basically a name -- distinct bound regions within the same +/// universe are just two regions with an unknown relationship to one +/// another. +#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable, PartialOrd, Ord)] +pub struct Placeholder { + pub universe: UniverseIndex, + pub name: BoundRegion, +} + /// When type checking, we use the `ParamEnv` to track /// details about the set of where-clauses that are in scope at this /// particular point. diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs index 06d559fd9dbea..db0756fb19053 100644 --- a/src/librustc/ty/sty.rs +++ b/src/librustc/ty/sty.rs @@ -709,7 +709,7 @@ impl<'a, 'gcx, 'tcx> ExistentialTraitRef<'tcx> { /// Object types don't have a self-type specified. Therefore, when /// we convert the principal trait-ref into a normal trait-ref, /// you must give *some* self-type. A common choice is `mk_err()` - /// or some skolemized type. + /// or some placeholder type. pub fn with_self_ty(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>, self_ty: Ty<'tcx>) -> ty::TraitRef<'tcx> { // otherwise the escaping regions would be captured by the binder @@ -732,7 +732,7 @@ impl<'tcx> PolyExistentialTraitRef<'tcx> { /// Object types don't have a self-type specified. Therefore, when /// we convert the principal trait-ref into a normal trait-ref, /// you must give *some* self-type. A common choice is `mk_err()` - /// or some skolemized type. + /// or some placeholder type. pub fn with_self_ty(&self, tcx: TyCtxt<'_, '_, 'tcx>, self_ty: Ty<'tcx>) -> ty::PolyTraitRef<'tcx> { @@ -743,7 +743,7 @@ impl<'tcx> PolyExistentialTraitRef<'tcx> { /// Binder is a binder for higher-ranked lifetimes. It is part of the /// compiler's representation for things like `for<'a> Fn(&'a isize)` /// (which would be represented by the type `PolyTraitRef == -/// Binder`). Note that when we skolemize, instantiate, +/// Binder`). Note that when we instantiate, /// erase, or otherwise "discharge" these bound regions, we change the /// type from `Binder` to just `T` (see /// e.g. `liberate_late_bound_regions`). @@ -1066,10 +1066,10 @@ pub type Region<'tcx> = &'tcx RegionKind; /// /// Unlike Param-s, bound regions are not supposed to exist "in the wild" /// outside their binder, e.g. in types passed to type inference, and -/// should first be substituted (by skolemized regions, free regions, +/// should first be substituted (by placeholder regions, free regions, /// or region variables). /// -/// ## Skolemized and Free Regions +/// ## Placeholder and Free Regions /// /// One often wants to work with bound regions without knowing their precise /// identity. For example, when checking a function, the lifetime of a borrow @@ -1077,12 +1077,11 @@ pub type Region<'tcx> = &'tcx RegionKind; /// it must be ensured that bounds on the region can't be accidentally /// assumed without being checked. /// -/// The process of doing that is called "skolemization". The bound regions -/// are replaced by skolemized markers, which don't satisfy any relation -/// not explicitly provided. +/// To do this, we replace the bound regions with placeholder markers, +/// which don't satisfy any relation not explicitly provided. /// -/// There are 2 kinds of skolemized regions in rustc: `ReFree` and -/// `ReSkolemized`. When checking an item's body, `ReFree` is supposed +/// There are 2 kinds of placeholder regions in rustc: `ReFree` and +/// `RePlaceholder`. When checking an item's body, `ReFree` is supposed /// to be used. These also support explicit bounds: both the internally-stored /// *scope*, which the region is assumed to outlive, as well as other /// relations stored in the `FreeRegionMap`. Note that these relations @@ -1091,14 +1090,14 @@ pub type Region<'tcx> = &'tcx RegionKind; /// /// When working with higher-ranked types, some region relations aren't /// yet known, so you can't just call `resolve_regions_and_report_errors`. -/// `ReSkolemized` is designed for this purpose. In these contexts, +/// `RePlaceholder` is designed for this purpose. In these contexts, /// there's also the risk that some inference variable laying around will -/// get unified with your skolemized region: if you want to check whether +/// get unified with your placeholder region: if you want to check whether /// `for<'a> Foo<'_>: 'a`, and you substitute your bound region `'a` -/// with a skolemized region `'%a`, the variable `'_` would just be -/// instantiated to the skolemized region `'%a`, which is wrong because +/// with a placeholder region `'%a`, the variable `'_` would just be +/// instantiated to the placeholder region `'%a`, which is wrong because /// the inference variable is supposed to satisfy the relation -/// *for every value of the skolemized region*. To ensure that doesn't +/// *for every value of the placeholder region*. To ensure that doesn't /// happen, you can use `leak_check`. This is more clearly explained /// by the [rustc guide]. /// @@ -1132,9 +1131,9 @@ pub enum RegionKind { /// A region variable. Should not exist after typeck. ReVar(RegionVid), - /// A skolemized region - basically the higher-ranked version of ReFree. + /// A placeholder region - basically the higher-ranked version of ReFree. /// Should not exist after typeck. - ReSkolemized(ty::UniverseIndex, BoundRegion), + RePlaceholder(ty::Placeholder), /// Empty lifetime is for data that is never accessed. /// Bottom in the region lattice. We treat ReEmpty somewhat @@ -1338,7 +1337,7 @@ impl RegionKind { RegionKind::ReScope(..) => false, RegionKind::ReStatic => true, RegionKind::ReVar(..) => false, - RegionKind::ReSkolemized(_, br) => br.is_named(), + RegionKind::RePlaceholder(placeholder) => placeholder.name.is_named(), RegionKind::ReEmpty => false, RegionKind::ReErased => false, RegionKind::ReClosureBound(..) => false, @@ -1410,7 +1409,7 @@ impl RegionKind { flags = flags | TypeFlags::HAS_FREE_REGIONS; flags = flags | TypeFlags::HAS_RE_INFER; } - ty::ReSkolemized(..) => { + ty::RePlaceholder(..) => { flags = flags | TypeFlags::HAS_FREE_REGIONS; flags = flags | TypeFlags::HAS_RE_SKOL; } diff --git a/src/librustc/ty/wf.rs b/src/librustc/ty/wf.rs index 397c63a149a4c..8c1482652ee29 100644 --- a/src/librustc/ty/wf.rs +++ b/src/librustc/ty/wf.rs @@ -520,7 +520,7 @@ pub fn object_region_bounds<'a, 'gcx, 'tcx>( { // Since we don't actually *know* the self type for an object, // this "open(err)" serves as a kind of dummy standin -- basically - // a skolemized type. + // a placeholder type. let open_ty = tcx.mk_infer(ty::FreshTy(0)); let predicates = existential_predicates.iter().filter_map(|predicate| { diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs index 814f8880bbf2f..33534ab27f147 100644 --- a/src/librustc/util/ppaux.rs +++ b/src/librustc/util/ppaux.rs @@ -803,7 +803,7 @@ define_print! { } ty::ReLateBound(_, br) | ty::ReFree(ty::FreeRegion { bound_region: br, .. }) | - ty::ReSkolemized(_, br) => { + ty::RePlaceholder(ty::Placeholder { name: br, .. }) => { write!(f, "{}", br) } ty::ReScope(scope) if cx.identify_regions => { @@ -872,8 +872,8 @@ define_print! { write!(f, "'?{}", c.index()) } - ty::ReSkolemized(universe, ref bound_region) => { - write!(f, "ReSkolemized({:?}, {:?})", universe, bound_region) + ty::RePlaceholder(placeholder) => { + write!(f, "RePlaceholder({:?})", placeholder) } ty::ReEmpty => write!(f, "ReEmpty"), diff --git a/src/librustc_borrowck/borrowck/check_loans.rs b/src/librustc_borrowck/borrowck/check_loans.rs index 40bfbf1596a47..34ee03b895f9f 100644 --- a/src/librustc_borrowck/borrowck/check_loans.rs +++ b/src/librustc_borrowck/borrowck/check_loans.rs @@ -426,7 +426,7 @@ impl<'a, 'tcx> CheckLoanCtxt<'a, 'tcx> { // These cannot exist in borrowck RegionKind::ReVar(..) | RegionKind::ReCanonical(..) | - RegionKind::ReSkolemized(..) | + RegionKind::RePlaceholder(..) | RegionKind::ReClosureBound(..) | RegionKind::ReErased => span_bug!(borrow_span, "unexpected region in borrowck {:?}", diff --git a/src/librustc_borrowck/borrowck/gather_loans/mod.rs b/src/librustc_borrowck/borrowck/gather_loans/mod.rs index dc400c6ef3ead..1f83c30a3876a 100644 --- a/src/librustc_borrowck/borrowck/gather_loans/mod.rs +++ b/src/librustc_borrowck/borrowck/gather_loans/mod.rs @@ -368,7 +368,7 @@ impl<'a, 'tcx> GatherLoanCtxt<'a, 'tcx> { ty::ReClosureBound(..) | ty::ReLateBound(..) | ty::ReVar(..) | - ty::ReSkolemized(..) | + ty::RePlaceholder(..) | ty::ReErased => { span_bug!( cmt.span, diff --git a/src/librustc_mir/borrow_check/error_reporting.rs b/src/librustc_mir/borrow_check/error_reporting.rs index 260e6ee5e2be8..1589d62300cab 100644 --- a/src/librustc_mir/borrow_check/error_reporting.rs +++ b/src/librustc_mir/borrow_check/error_reporting.rs @@ -1789,9 +1789,11 @@ impl<'tcx> AnnotatedBorrowFnSignature<'tcx> { // lifetimes without names with the value `'0`. match ty.sty { ty::TyKind::Ref(ty::RegionKind::ReLateBound(_, br), _, _) - | ty::TyKind::Ref(ty::RegionKind::ReSkolemized(_, br), _, _) => { - with_highlight_region_for_bound_region(*br, counter, || format!("{}", ty)) - } + | ty::TyKind::Ref( + ty::RegionKind::RePlaceholder(ty::Placeholder { name: br, .. }), + _, + _, + ) => with_highlight_region_for_bound_region(*br, counter, || format!("{}", ty)), _ => format!("{}", ty), } } @@ -1801,7 +1803,8 @@ impl<'tcx> AnnotatedBorrowFnSignature<'tcx> { fn get_region_name_for_ty(&self, ty: ty::Ty<'tcx>, counter: usize) -> String { match ty.sty { ty::TyKind::Ref(region, _, _) => match region { - ty::RegionKind::ReLateBound(_, br) | ty::RegionKind::ReSkolemized(_, br) => { + ty::RegionKind::ReLateBound(_, br) + | ty::RegionKind::RePlaceholder(ty::Placeholder { name: br, .. }) => { with_highlight_region_for_bound_region(*br, counter, || format!("{}", region)) } _ => format!("{}", region), diff --git a/src/librustc_mir/borrow_check/nll/mod.rs b/src/librustc_mir/borrow_check/nll/mod.rs index b9f22c7402a07..723b0e6fff6f8 100644 --- a/src/librustc_mir/borrow_check/nll/mod.rs +++ b/src/librustc_mir/borrow_check/nll/mod.rs @@ -107,6 +107,7 @@ pub(in borrow_check) fn compute_regions<'cx, 'gcx, 'tcx>( // Run the MIR type-checker. let MirTypeckResults { constraints, + placeholder_indices, universal_region_relations, } = type_check::type_check( infcx, @@ -122,6 +123,8 @@ pub(in borrow_check) fn compute_regions<'cx, 'gcx, 'tcx>( elements, ); + let placeholder_indices = Rc::new(placeholder_indices); + if let Some(all_facts) = &mut all_facts { all_facts .universal_region @@ -150,6 +153,7 @@ pub(in borrow_check) fn compute_regions<'cx, 'gcx, 'tcx>( let mut regioncx = RegionInferenceContext::new( var_origins, universal_regions, + placeholder_indices, universal_region_relations, mir, outlives_constraints, diff --git a/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/region_name.rs b/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/region_name.rs index be05e006608a2..3a545d9adbfce 100644 --- a/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/region_name.rs +++ b/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/region_name.rs @@ -274,7 +274,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { ty::ReLateBound(..) | ty::ReScope(..) | ty::ReVar(..) - | ty::ReSkolemized(..) + | ty::RePlaceholder(..) | ty::ReEmpty | ty::ReErased | ty::ReClosureBound(..) diff --git a/src/librustc_mir/borrow_check/nll/region_infer/mod.rs b/src/librustc_mir/borrow_check/nll/region_infer/mod.rs index 2dbb5cd9deb14..4a8f011b606b7 100644 --- a/src/librustc_mir/borrow_check/nll/region_infer/mod.rs +++ b/src/librustc_mir/borrow_check/nll/region_infer/mod.rs @@ -11,7 +11,7 @@ use super::universal_regions::UniversalRegions; use borrow_check::nll::constraints::graph::NormalConstraintGraph; use borrow_check::nll::constraints::{ConstraintSccIndex, ConstraintSet, OutlivesConstraint}; -use borrow_check::nll::region_infer::values::{RegionElement, ToElementIndex}; +use borrow_check::nll::region_infer::values::{PlaceholderIndices, RegionElement, ToElementIndex}; use borrow_check::nll::type_check::free_region_relations::UniversalRegionRelations; use borrow_check::nll::type_check::Locations; use rustc::hir::def_id::DefId; @@ -183,6 +183,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { pub(crate) fn new( var_infos: VarInfos, universal_regions: Rc>, + placeholder_indices: Rc, universal_region_relations: Rc>, _mir: &Mir<'tcx>, outlives_constraints: ConstraintSet, @@ -196,19 +197,13 @@ impl<'tcx> RegionInferenceContext<'tcx> { .map(|info| RegionDefinition::new(info.universe, info.origin)) .collect(); - // Compute the max universe used anywhere amongst the regions. - let max_universe = definitions - .iter() - .map(|d| d.universe) - .max() - .unwrap_or(ty::UniverseIndex::ROOT); - let constraints = Rc::new(outlives_constraints); // freeze constraints let constraint_graph = Rc::new(constraints.graph(definitions.len())); let fr_static = universal_regions.fr_static; let constraint_sccs = Rc::new(constraints.compute_sccs(&constraint_graph, fr_static)); - let mut scc_values = RegionValues::new(elements, universal_regions.len(), max_universe); + let mut scc_values = + RegionValues::new(elements, universal_regions.len(), &placeholder_indices); for region in liveness_constraints.rows() { let scc = constraint_sccs.scc(region); @@ -329,17 +324,14 @@ impl<'tcx> RegionInferenceContext<'tcx> { self.scc_values.add_element(scc, variable); } - NLLRegionVariableOrigin::BoundRegion(ui) => { - // Each placeholder region X outlives its - // associated universe but nothing else. Every - // placeholder region is always in a universe that - // contains `ui` -- but when placeholder regions - // are placed into an SCC, that SCC may include - // things from other universes that do not include - // `ui`. + NLLRegionVariableOrigin::Placeholder(placeholder) => { + // Each placeholder region is only visible from + // its universe `ui` and its superuniverses. So we + // can't just add it into `scc` unless the + // universe of the scc can name this region. let scc_universe = self.scc_universes[scc]; - if ui.is_subset_of(scc_universe) { - self.scc_values.add_element(scc, ui); + if placeholder.universe.is_subset_of(scc_universe) { + self.scc_values.add_element(scc, placeholder); } else { self.add_incompatible_universe(scc); } @@ -544,8 +536,8 @@ impl<'tcx> RegionInferenceContext<'tcx> { // B's value, and check whether all of them are nameable // from universe_a self.scc_values - .subuniverses_contained_in(scc_b) - .all(|u| u.is_subset_of(universe_a)) + .placeholders_contained_in(scc_b) + .all(|p| p.universe.is_subset_of(universe_a)) } /// Extend `scc` so that it can outlive some placeholder region @@ -1076,8 +1068,8 @@ impl<'tcx> RegionInferenceContext<'tcx> { ); } - NLLRegionVariableOrigin::BoundRegion(universe) => { - self.check_bound_universal_region(infcx, mir, mir_def_id, fr, universe); + NLLRegionVariableOrigin::Placeholder(placeholder) => { + self.check_bound_universal_region(infcx, mir, mir_def_id, fr, placeholder); } NLLRegionVariableOrigin::Existential => { @@ -1113,7 +1105,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { assert!(self.scc_universes[longer_fr_scc] == ty::UniverseIndex::ROOT); debug_assert!( self.scc_values - .subuniverses_contained_in(longer_fr_scc) + .placeholders_contained_in(longer_fr_scc) .next() .is_none() ); @@ -1181,9 +1173,12 @@ impl<'tcx> RegionInferenceContext<'tcx> { mir: &Mir<'tcx>, _mir_def_id: DefId, longer_fr: RegionVid, - universe: ty::UniverseIndex, + placeholder: ty::Placeholder, ) { - debug!("check_bound_universal_region(fr={:?})", longer_fr); + debug!( + "check_bound_universal_region(fr={:?}, placeholder={:?})", + longer_fr, placeholder, + ); let longer_fr_scc = self.constraint_sccs.scc(longer_fr); @@ -1196,7 +1191,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { .find(|element| match element { RegionElement::Location(_) => true, RegionElement::RootUniversalRegion(_) => true, - RegionElement::SubUniversalRegion(ui) => *ui != universe, + RegionElement::PlaceholderRegion(placeholder1) => placeholder != *placeholder1, }) } { Some(v) => v, @@ -1207,10 +1202,10 @@ impl<'tcx> RegionInferenceContext<'tcx> { let error_region = match error_element { RegionElement::Location(l) => self.find_sub_region_live_at(longer_fr, l), RegionElement::RootUniversalRegion(r) => r, - RegionElement::SubUniversalRegion(error_ui) => self.definitions + RegionElement::PlaceholderRegion(error_placeholder) => self.definitions .iter_enumerated() .filter_map(|(r, definition)| match definition.origin { - NLLRegionVariableOrigin::BoundRegion(ui) if error_ui == ui => Some(r), + NLLRegionVariableOrigin::Placeholder(p) if p == error_placeholder => Some(r), _ => None, }) .next() diff --git a/src/librustc_mir/borrow_check/nll/region_infer/values.rs b/src/librustc_mir/borrow_check/nll/region_infer/values.rs index 8dc41a9b2d32d..07372c19c46c9 100644 --- a/src/librustc_mir/borrow_check/nll/region_infer/values.rs +++ b/src/librustc_mir/borrow_check/nll/region_infer/values.rs @@ -11,6 +11,7 @@ use rustc::mir::{BasicBlock, Location, Mir}; use rustc::ty::{self, RegionVid}; use rustc_data_structures::bit_set::{HybridBitSet, SparseBitMatrix}; +use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::indexed_vec::Idx; use rustc_data_structures::indexed_vec::IndexVec; use std::fmt::Debug; @@ -31,8 +32,7 @@ crate struct RegionValueElements { impl RegionValueElements { crate fn new(mir: &Mir<'_>) -> Self { let mut num_points = 0; - let statements_before_block: IndexVec = mir - .basic_blocks() + let statements_before_block: IndexVec = mir.basic_blocks() .iter() .map(|block_data| { let v = num_points; @@ -48,7 +48,7 @@ impl RegionValueElements { let mut basic_blocks = IndexVec::with_capacity(num_points); for (bb, bb_data) in mir.basic_blocks().iter_enumerated() { - basic_blocks.extend((0 .. bb_data.statements.len() + 1).map(|_| bb)); + basic_blocks.extend((0..bb_data.statements.len() + 1).map(|_| bb)); } Self { @@ -85,7 +85,10 @@ impl RegionValueElements { let block = self.basic_blocks[index]; let start_index = self.statements_before_block[block]; let statement_index = index.index() - start_index; - Location { block, statement_index } + Location { + block, + statement_index, + } } /// Sometimes we get point-indices back from bitsets that may be @@ -103,13 +106,15 @@ impl RegionValueElements { index: PointIndex, stack: &mut Vec, ) { - let Location { block, statement_index } = self.to_location(index); + let Location { + block, + statement_index, + } = self.to_location(index); if statement_index == 0 { // If this is a basic block head, then the predecessors are // the the terminators of other basic blocks stack.extend( - mir - .predecessors_for(block) + mir.predecessors_for(block) .iter() .map(|&pred_bb| mir.terminator_loc(pred_bb)) .map(|pred_loc| self.point_from_location(pred_loc)), @@ -127,10 +132,7 @@ newtype_index! { pub struct PointIndex { DEBUG_FORMAT = "PointIndex({})" } } -/// A single integer representing a (non-zero) `UniverseIndex`. -/// Computed just by subtracting one from `UniverseIndex`; this is -/// because the `0` value for `UniverseIndex` represents the root -/// universe, and we don't need/want a bit for that one. +/// A single integer representing a `ty::Placeholder`. newtype_index! { pub struct PlaceholderIndex { DEBUG_FORMAT = "PlaceholderIndex({})" } } @@ -148,7 +150,7 @@ crate enum RegionElement { /// A subuniverse from a subuniverse (e.g., instantiated from a /// `for<'a> fn(&'a u32)` type). - SubUniversalRegion(ty::UniverseIndex), + PlaceholderRegion(ty::Placeholder), } /// When we initially compute liveness, we use a bit matrix storing @@ -185,7 +187,10 @@ impl LivenessValues { /// Adds all the elements in the given bit array into the given /// region. Returns true if any of them are newly added. crate fn add_elements(&mut self, row: N, locations: &HybridBitSet) -> bool { - debug!("LivenessValues::add_elements(row={:?}, locations={:?})", row, locations); + debug!( + "LivenessValues::add_elements(row={:?}, locations={:?})", + row, locations + ); self.points.union_into_row(row, locations) } @@ -214,6 +219,52 @@ impl LivenessValues { } } +/// Maps from `ty::Placeholder` values that are used in the rest of +/// rustc to the internal `PlaceholderIndex` values that are used in +/// NLL. +#[derive(Default)] +crate struct PlaceholderIndices { + to_index: FxHashMap, + from_index: IndexVec, +} + +impl PlaceholderIndices { + crate fn insert(&mut self, placeholder: ty::Placeholder) -> PlaceholderIndex { + let PlaceholderIndices { + to_index, + from_index, + } = self; + *to_index + .entry(placeholder) + .or_insert_with(|| from_index.push(placeholder)) + } + + crate fn lookup_index(&self, placeholder: ty::Placeholder) -> PlaceholderIndex { + self.to_index[&placeholder] + } + + crate fn lookup_placeholder(&self, placeholder: PlaceholderIndex) -> ty::Placeholder { + self.from_index[placeholder] + } + + crate fn len(&self) -> usize { + self.from_index.len() + } +} + +impl ::std::iter::FromIterator for PlaceholderIndices { + fn from_iter(iter: I) -> Self + where + I: IntoIterator, + { + let mut result = Self::default(); + iter.into_iter().for_each(|p| { + result.insert(p); + }); + result + } +} + /// Stores the full values for a set of regions (in contrast to /// `LivenessValues`, which only stores those points in the where a /// region is live). The full value for a region may contain points in @@ -235,6 +286,7 @@ impl LivenessValues { #[derive(Clone)] crate struct RegionValues { elements: Rc, + placeholder_indices: Rc, points: SparseBitMatrix, free_regions: SparseBitMatrix, @@ -250,12 +302,13 @@ impl RegionValues { crate fn new( elements: &Rc, num_universal_regions: usize, - max_universe: ty::UniverseIndex, + placeholder_indices: &Rc, ) -> Self { - let num_placeholders = max_universe.as_usize(); + let num_placeholders = placeholder_indices.len(); Self { elements: elements.clone(), points: SparseBitMatrix::new(elements.num_points), + placeholder_indices: placeholder_indices.clone(), free_regions: SparseBitMatrix::new(num_universal_regions), placeholders: SparseBitMatrix::new(num_placeholders), } @@ -313,14 +366,11 @@ impl RegionValues { /// Returns the locations contained within a given region `r`. crate fn locations_outlived_by<'a>(&'a self, r: N) -> impl Iterator + 'a { - self.points - .row(r) - .into_iter() - .flat_map(move |set| { - set.iter() - .take_while(move |&p| self.elements.point_in_range(p)) - .map(move |p| self.elements.to_location(p)) - }) + self.points.row(r).into_iter().flat_map(move |set| { + set.iter() + .take_while(move |&p| self.elements.point_in_range(p)) + .map(move |p| self.elements.to_location(p)) + }) } /// Returns just the universal regions that are contained in a given region's value. @@ -335,32 +385,30 @@ impl RegionValues { } /// Returns all the elements contained in a given region's value. - crate fn subuniverses_contained_in<'a>( + crate fn placeholders_contained_in<'a>( &'a self, r: N, - ) -> impl Iterator + 'a { + ) -> impl Iterator + 'a { self.placeholders .row(r) .into_iter() .flat_map(|set| set.iter()) - .map(|p| ty::UniverseIndex::from_u32((p.index() + 1) as u32)) + .map(move |p| self.placeholder_indices.lookup_placeholder(p)) } /// Returns all the elements contained in a given region's value. crate fn elements_contained_in<'a>(&'a self, r: N) -> impl Iterator + 'a { let points_iter = self.locations_outlived_by(r).map(RegionElement::Location); - let free_regions_iter = self - .universal_regions_outlived_by(r) + let free_regions_iter = self.universal_regions_outlived_by(r) .map(RegionElement::RootUniversalRegion); - let subuniverses_iter = self - .subuniverses_contained_in(r) - .map(RegionElement::SubUniversalRegion); + let placeholder_universes_iter = self.placeholders_contained_in(r) + .map(RegionElement::PlaceholderRegion); points_iter .chain(free_regions_iter) - .chain(subuniverses_iter) + .chain(placeholder_universes_iter) } /// Returns a "pretty" string value of the region. Meant for debugging. @@ -397,14 +445,14 @@ impl ToElementIndex for RegionVid { } } -impl ToElementIndex for ty::UniverseIndex { +impl ToElementIndex for ty::Placeholder { fn add_to_row(self, values: &mut RegionValues, row: N) -> bool { - let index = PlaceholderIndex::new(self.as_usize() - 1); + let index = values.placeholder_indices.lookup_index(self); values.placeholders.insert(row, index) } fn contained_in_row(self, values: &RegionValues, row: N) -> bool { - let index = PlaceholderIndex::new(self.as_usize() - 1); + let index = values.placeholder_indices.lookup_index(self); values.placeholders.contains(row, index) } } @@ -467,7 +515,7 @@ fn region_value_str(elements: impl IntoIterator) -> String result.push_str(&format!("{:?}", fr)); } - RegionElement::SubUniversalRegion(ur) => { + RegionElement::PlaceholderRegion(placeholder) => { if let Some((location1, location2)) = open_location { push_sep(&mut result); push_location_range(&mut result, location1, location2); @@ -475,7 +523,7 @@ fn region_value_str(elements: impl IntoIterator) -> String } push_sep(&mut result); - result.push_str(&format!("{:?}", ur)); + result.push_str(&format!("{:?}", placeholder)); } } } diff --git a/src/librustc_mir/borrow_check/nll/type_check/mod.rs b/src/librustc_mir/borrow_check/nll/type_check/mod.rs index ef4cc3452b1ef..99ac80862b13e 100644 --- a/src/librustc_mir/borrow_check/nll/type_check/mod.rs +++ b/src/librustc_mir/borrow_check/nll/type_check/mod.rs @@ -15,7 +15,9 @@ use borrow_check::borrow_set::BorrowSet; use borrow_check::location::LocationTable; use borrow_check::nll::constraints::{ConstraintCategory, ConstraintSet, OutlivesConstraint}; use borrow_check::nll::facts::AllFacts; -use borrow_check::nll::region_infer::values::{LivenessValues, RegionValueElements}; +use borrow_check::nll::region_infer::values::LivenessValues; +use borrow_check::nll::region_infer::values::PlaceholderIndices; +use borrow_check::nll::region_infer::values::RegionValueElements; use borrow_check::nll::region_infer::{ClosureRegionRequirementsExt, TypeTest}; use borrow_check::nll::renumber; use borrow_check::nll::type_check::free_region_relations::{ @@ -42,13 +44,13 @@ use rustc::traits::{ObligationCause, PredicateObligations}; use rustc::ty::fold::TypeFoldable; use rustc::ty::subst::Subst; use rustc::ty::{self, CanonicalTy, RegionVid, ToPolyTraitRef, Ty, TyCtxt, TyKind}; -use std::{fmt, iter}; use std::rc::Rc; +use std::{fmt, iter}; use syntax_pos::{Span, DUMMY_SP}; use transform::{MirPass, MirSource}; -use rustc_data_structures::fx::FxHashSet; use either::Either; +use rustc_data_structures::fx::FxHashSet; macro_rules! span_mirbug { ($context:expr, $elem:expr, $($message:tt)*) => ({ @@ -128,6 +130,7 @@ pub(crate) fn type_check<'gcx, 'tcx>( outlives_constraints: ConstraintSet::default(), type_tests: Vec::default(), }; + let mut placeholder_indices = PlaceholderIndices::default(); let CreateResult { universal_region_relations, @@ -147,6 +150,7 @@ pub(crate) fn type_check<'gcx, 'tcx>( borrow_set, all_facts, constraints: &mut constraints, + placeholder_indices: &mut placeholder_indices, }; type_check_internal( @@ -162,12 +166,15 @@ pub(crate) fn type_check<'gcx, 'tcx>( cx.equate_inputs_and_outputs(mir, universal_regions, &normalized_inputs_and_output); liveness::generate(cx, mir, elements, flow_inits, move_data, location_table); - cx.borrowck_context.as_mut().map(|bcx| translate_outlives_facts(bcx)); + cx.borrowck_context + .as_mut() + .map(|bcx| translate_outlives_facts(bcx)); }, ); MirTypeckResults { constraints, + placeholder_indices, universal_region_relations, } } @@ -210,21 +217,25 @@ fn type_check_internal<'a, 'gcx, 'tcx, R>( fn translate_outlives_facts(cx: &mut BorrowCheckContext) { if let Some(facts) = cx.all_facts { let location_table = cx.location_table; - facts.outlives.extend( - cx.constraints.outlives_constraints.iter().flat_map(|constraint: &OutlivesConstraint| { - if let Some(from_location) = constraint.locations.from_location() { - Either::Left(iter::once(( - constraint.sup, - constraint.sub, - location_table.mid_index(from_location), - ))) - } else { - Either::Right(location_table.all_points().map(move |location| { - (constraint.sup, constraint.sub, location) - })) - } - }) - ); + facts + .outlives + .extend(cx.constraints.outlives_constraints.iter().flat_map( + |constraint: &OutlivesConstraint| { + if let Some(from_location) = constraint.locations.from_location() { + Either::Left(iter::once(( + constraint.sup, + constraint.sub, + location_table.mid_index(from_location), + ))) + } else { + Either::Right( + location_table + .all_points() + .map(move |location| (constraint.sup, constraint.sub, location)), + ) + } + }, + )); } } @@ -718,10 +729,12 @@ struct BorrowCheckContext<'a, 'tcx: 'a> { all_facts: &'a mut Option, borrow_set: &'a BorrowSet<'tcx>, constraints: &'a mut MirTypeckRegionConstraints<'tcx>, + placeholder_indices: &'a mut PlaceholderIndices, } crate struct MirTypeckResults<'tcx> { crate constraints: MirTypeckRegionConstraints<'tcx>, + crate placeholder_indices: PlaceholderIndices, crate universal_region_relations: Rc>, } diff --git a/src/librustc_mir/borrow_check/nll/type_check/relate_tys.rs b/src/librustc_mir/borrow_check/nll/type_check/relate_tys.rs index 13d59c3ba29c6..4e8dbf8498e2a 100644 --- a/src/librustc_mir/borrow_check/nll/type_check/relate_tys.rs +++ b/src/librustc_mir/borrow_check/nll/type_check/relate_tys.rs @@ -146,18 +146,27 @@ trait TypeRelatingDelegate<'tcx> { /// delegate. fn push_outlives(&mut self, sup: ty::Region<'tcx>, sub: ty::Region<'tcx>); - /// Creates a new region variable representing an instantiated - /// higher-ranked region; this will be either existential or - /// universal depending on the context. So e.g. if you have - /// `for<'a> fn(..) <: for<'b> fn(..)`, then we will first - /// instantiate `'b` with a universally quantitifed region and - /// then `'a` with an existentially quantified region (the order - /// is important so that the existential region `'a` can see the - /// universal one). - fn next_region_var( - &mut self, - universally_quantified: UniversallyQuantified, - ) -> ty::Region<'tcx>; + /// Creates a new universe index. Used when instantiating placeholders. + fn next_subuniverse(&mut self) -> ty::UniverseIndex; + + /// Creates a new region variable representing a higher-ranked + /// region that is instantiated existentially. This creates an + /// inference variable, typically. + /// + /// So e.g. if you have `for<'a> fn(..) <: for<'b> fn(..)`, then + /// we will invoke this method to instantiate `'a` with an + /// inference variable (though `'b` would be instantiated first, + /// as a placeholder). + fn next_existential_region_var(&mut self) -> ty::Region<'tcx>; + + /// Creates a new region variable representing a + /// higher-ranked region that is instantiated universally. + /// This creates a new region placeholder, typically. + /// + /// So e.g. if you have `for<'a> fn(..) <: for<'b> fn(..)`, then + /// we will invoke this method to instantiate `'b` with a + /// placeholder region. + fn next_placeholder_region(&mut self, placeholder: ty::Placeholder) -> ty::Region<'tcx>; /// Creates a new existential region in the given universe. This /// is used when handling subtyping and type variables -- if we @@ -197,15 +206,20 @@ impl NllTypeRelatingDelegate<'me, 'bccx, 'gcx, 'tcx> { } impl TypeRelatingDelegate<'tcx> for NllTypeRelatingDelegate<'_, '_, '_, 'tcx> { - fn next_region_var( - &mut self, - universally_quantified: UniversallyQuantified, - ) -> ty::Region<'tcx> { - let origin = if universally_quantified.0 { - NLLRegionVariableOrigin::BoundRegion(self.infcx.create_subuniverse()) - } else { - NLLRegionVariableOrigin::Existential - }; + fn next_subuniverse(&mut self) -> ty::UniverseIndex { + self.infcx.create_subuniverse() + } + + fn next_existential_region_var(&mut self) -> ty::Region<'tcx> { + let origin = NLLRegionVariableOrigin::Existential; + self.infcx.next_nll_region_var(origin) + } + + fn next_placeholder_region(&mut self, placeholder: ty::Placeholder) -> ty::Region<'tcx> { + let origin = NLLRegionVariableOrigin::Placeholder(placeholder); + if let Some(borrowck_context) = &mut self.borrowck_context { + borrowck_context.placeholder_indices.insert(placeholder); + } self.infcx.next_nll_region_var(origin) } @@ -286,12 +300,37 @@ where universally_quantified: UniversallyQuantified, ) -> BoundRegionScope<'tcx> { let mut scope = BoundRegionScope::default(); + + // Create a callback that creates (via the delegate) either an + // existential or placeholder region as needed. + let mut next_region = { + let delegate = &mut self.delegate; + let mut lazy_universe = None; + move |br: ty::BoundRegion| { + if universally_quantified.0 { + // The first time this closure is called, create a + // new universe for the placeholders we will make + // from here out. + let universe = lazy_universe.unwrap_or_else(|| { + let universe = delegate.next_subuniverse(); + lazy_universe = Some(universe); + universe + }); + + let placeholder = ty::Placeholder { universe, name: br }; + delegate.next_placeholder_region(placeholder) + } else { + delegate.next_existential_region_var() + } + } + }; + value.skip_binder().visit_with(&mut ScopeInstantiator { - delegate: &mut self.delegate, + next_region: &mut next_region, target_index: ty::INNERMOST, - universally_quantified, bound_region_scope: &mut scope, }); + scope } @@ -604,21 +643,14 @@ where /// binder depth, and finds late-bound regions targeting the /// `for<..`>. For each of those, it creates an entry in /// `bound_region_scope`. -struct ScopeInstantiator<'me, 'tcx: 'me, D> -where - D: TypeRelatingDelegate<'tcx> + 'me, -{ - delegate: &'me mut D, +struct ScopeInstantiator<'me, 'tcx: 'me> { + next_region: &'me mut dyn FnMut(ty::BoundRegion) -> ty::Region<'tcx>, // The debruijn index of the scope we are instantiating. target_index: ty::DebruijnIndex, - universally_quantified: UniversallyQuantified, bound_region_scope: &'me mut BoundRegionScope<'tcx>, } -impl<'me, 'tcx, D> TypeVisitor<'tcx> for ScopeInstantiator<'me, 'tcx, D> -where - D: TypeRelatingDelegate<'tcx>, -{ +impl<'me, 'tcx> TypeVisitor<'tcx> for ScopeInstantiator<'me, 'tcx> { fn visit_binder>(&mut self, t: &ty::Binder) -> bool { self.target_index.shift_in(1); t.super_visit_with(self); @@ -629,9 +661,8 @@ where fn visit_region(&mut self, r: ty::Region<'tcx>) -> bool { let ScopeInstantiator { - universally_quantified, bound_region_scope, - delegate, + next_region, .. } = self; @@ -640,7 +671,7 @@ where bound_region_scope .map .entry(*br) - .or_insert_with(|| delegate.next_region_var(*universally_quantified)); + .or_insert_with(|| next_region(*br)); } _ => {} diff --git a/src/librustc_typeck/check/compare_method.rs b/src/librustc_typeck/check/compare_method.rs index 29770dc12eb33..695812faafff1 100644 --- a/src/librustc_typeck/check/compare_method.rs +++ b/src/librustc_typeck/check/compare_method.rs @@ -128,14 +128,14 @@ fn compare_predicate_entailment<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, // We create a mapping `dummy_substs` that maps from the impl type // parameters to fresh types and regions. For type parameters, // this is the identity transform, but we could as well use any - // skolemized types. For regions, we convert from bound to free + // placeholder types. For regions, we convert from bound to free // regions (Note: but only early-bound regions, i.e., those // declared on the impl or used in type parameter bounds). // // impl_to_skol_substs = {'i => 'i0, U => U0, N => N0 } // // Now we can apply skol_substs to the type of the impl method - // to yield a new function type in terms of our fresh, skolemized + // to yield a new function type in terms of our fresh, placeholder // types: // // <'b> fn(t: &'i0 U0, m: &'b) -> Foo @@ -163,15 +163,15 @@ fn compare_predicate_entailment<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, // We do this by creating a parameter environment which contains a // substitution corresponding to impl_to_skol_substs. We then build // trait_to_skol_substs and use it to convert the predicates contained - // in the trait_m.generics to the skolemized form. + // in the trait_m.generics to the placeholder form. // // Finally we register each of these predicates as an obligation in // a fresh FulfillmentCtxt, and invoke select_all_or_error. - // Create mapping from impl to skolemized. + // Create mapping from impl to placeholder. let impl_to_skol_substs = Substs::identity_for_item(tcx, impl_m.def_id); - // Create mapping from trait to skolemized. + // Create mapping from trait to placeholder. let trait_to_skol_substs = impl_to_skol_substs.rebase_onto(tcx, impl_m.container.id(), trait_to_impl_substs); @@ -212,7 +212,7 @@ fn compare_predicate_entailment<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, hybrid_preds.predicates.extend( trait_m_predicates.instantiate_own(tcx, trait_to_skol_substs).predicates); - // Construct trait parameter environment and then shift it into the skolemized viewpoint. + // Construct trait parameter environment and then shift it into the placeholder viewpoint. // The key step here is to update the caller_bounds's predicates to be // the new hybrid bounds we computed. let normalize_cause = traits::ObligationCause::misc(impl_m_span, impl_m_node_id); @@ -259,7 +259,7 @@ fn compare_predicate_entailment<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, // any associated types appearing in the fn arguments or return // type. - // Compute skolemized form of impl and trait method tys. + // Compute placeholder form of impl and trait method tys. let tcx = infcx.tcx; let (impl_sig, _) = @@ -894,7 +894,7 @@ pub fn compare_const_impl<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, // method. let impl_c_node_id = tcx.hir.as_local_node_id(impl_c.def_id).unwrap(); - // Compute skolemized form of impl and trait const tys. + // Compute placeholder form of impl and trait const tys. let impl_ty = tcx.type_of(impl_c.def_id); let trait_ty = tcx.type_of(trait_c.def_id).subst(tcx, trait_to_impl_substs); let mut cause = ObligationCause::misc(impl_c_span, impl_c_node_id); diff --git a/src/librustc_typeck/outlives/utils.rs b/src/librustc_typeck/outlives/utils.rs index 6bf7a3501bed9..96b75c4792d75 100644 --- a/src/librustc_typeck/outlives/utils.rs +++ b/src/librustc_typeck/outlives/utils.rs @@ -170,7 +170,7 @@ fn is_free_region<'tcx>(tcx: TyCtxt<'_, 'tcx, 'tcx>, region: Region<'_>) -> bool | RegionKind::ReCanonical(..) | RegionKind::ReScope(..) | RegionKind::ReVar(..) - | RegionKind::ReSkolemized(..) + | RegionKind::RePlaceholder(..) | RegionKind::ReFree(..) => { bug!("unexpected region in outlives inference: {:?}", region); } diff --git a/src/librustc_typeck/variance/constraints.rs b/src/librustc_typeck/variance/constraints.rs index 1125de55a0668..32a591777db5b 100644 --- a/src/librustc_typeck/variance/constraints.rs +++ b/src/librustc_typeck/variance/constraints.rs @@ -431,7 +431,7 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> { ty::ReClosureBound(..) | ty::ReScope(..) | ty::ReVar(..) | - ty::ReSkolemized(..) | + ty::RePlaceholder(..) | ty::ReEmpty | ty::ReErased => { // We don't expect to see anything but 'static or bound diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 9b305ad03b056..28f8ebff6ffdd 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -1258,7 +1258,7 @@ impl Clean> for ty::RegionKind { ty::ReFree(..) | ty::ReScope(..) | ty::ReVar(..) | - ty::ReSkolemized(..) | + ty::RePlaceholder(..) | ty::ReEmpty | ty::ReClosureBound(_) | ty::ReCanonical(_) | diff --git a/src/test/run-pass/project-cache-issue-37154.rs b/src/test/run-pass/project-cache-issue-37154.rs index 24fb400150aa8..3dac45139ac0f 100644 --- a/src/test/run-pass/project-cache-issue-37154.rs +++ b/src/test/run-pass/project-cache-issue-37154.rs @@ -10,8 +10,8 @@ #![allow(dead_code)] // Regression test for #37154: the problem here was that the cache -// results in a false error because it was caching skolemized results -// even after those skolemized regions had been popped. +// results in a false error because it was caching placeholder results +// even after those placeholder regions had been popped. trait Foo { fn method(&self) {}