diff options
| author | Niko Matsakis <niko@alum.mit.edu> | 2018-09-26 10:18:33 -0400 |
|---|---|---|
| committer | Niko Matsakis <niko@alum.mit.edu> | 2018-10-15 11:42:07 -0400 |
| commit | 28df2bf7b5093bb45845bfaadfcfb91eef5d00d5 (patch) | |
| tree | d958310e4d4af0ab914b1a004bc29693804e82a0 /src | |
| parent | 42a661843c9ce01370afc6c6cf02d075eac5d174 (diff) | |
| download | rust-28df2bf7b5093bb45845bfaadfcfb91eef5d00d5.tar.gz rust-28df2bf7b5093bb45845bfaadfcfb91eef5d00d5.zip | |
control canonicalization with a trait vs bools
Diffstat (limited to 'src')
| -rw-r--r-- | src/librustc/infer/canonical/canonicalizer.rs | 125 |
1 files changed, 83 insertions, 42 deletions
diff --git a/src/librustc/infer/canonical/canonicalizer.rs b/src/librustc/infer/canonical/canonicalizer.rs index 99a25f6c702..95822eb1855 100644 --- a/src/librustc/infer/canonical/canonicalizer.rs +++ b/src/librustc/infer/canonical/canonicalizer.rs @@ -63,10 +63,7 @@ impl<'cx, 'gcx, 'tcx> InferCtxt<'cx, 'gcx, 'tcx> { value, Some(self), self.tcx, - CanonicalizeRegionMode { - static_region: true, - other_free_regions: true, - }, + &CanonicalizeAllFreeRegions, var_values, ) } @@ -105,10 +102,7 @@ impl<'cx, 'gcx, 'tcx> InferCtxt<'cx, 'gcx, 'tcx> { value, Some(self), self.tcx, - CanonicalizeRegionMode { - static_region: false, - other_free_regions: false, - }, + &CanonicalizeQueryResponse, &mut var_values, ) } @@ -140,27 +134,87 @@ impl<'cx, 'gcx, 'tcx> InferCtxt<'cx, 'gcx, 'tcx> { value, Some(self), self.tcx, - CanonicalizeRegionMode { - static_region: false, - other_free_regions: true, - }, + &CanonicalizeFreeRegionsOtherThanStatic, var_values, ) } } -/// If this flag is true, then all free regions will be replaced with -/// a canonical var. This is used to make queries as generic as -/// possible. For example, the query `F: Foo<'static>` would be -/// canonicalized to `F: Foo<'0>`. -struct CanonicalizeRegionMode { - static_region: bool, - other_free_regions: bool, +/// Controls how we canonicalize "free regions" that are not inference +/// variables. This depends on what we are canonicalizing *for* -- +/// e.g., if we are canonicalizing to create a query, we want to +/// replace those with inference variables, since we want to make a +/// maximally general query. But if we are canonicalizing a *query +/// response*, then we don't typically replace free regions, as they +/// must have been introduced from other parts of the system. +trait CanonicalizeRegionMode { + fn canonicalize_free_region( + &self, + canonicalizer: &mut Canonicalizer<'_, '_, 'tcx>, + r: ty::Region<'tcx>, + ) -> ty::Region<'tcx>; + + fn any(&self) -> bool; +} + +struct CanonicalizeQueryResponse; + +impl CanonicalizeRegionMode for CanonicalizeQueryResponse { + fn canonicalize_free_region( + &self, + _canonicalizer: &mut Canonicalizer<'_, '_, 'tcx>, + r: ty::Region<'tcx>, + ) -> ty::Region<'tcx> { + match r { + ty::ReFree(_) | ty::ReEmpty | ty::ReErased | ty::ReStatic | ty::ReEarlyBound(..) => r, + _ => { + // Other than `'static` or `'empty`, the query + // response should be executing in a fully + // canonicalized environment, so there shouldn't be + // any other region names it can come up. + bug!("unexpected region in query response: `{:?}`", r) + } + } + } + + fn any(&self) -> bool { + false + } +} + +struct CanonicalizeAllFreeRegions; + +impl CanonicalizeRegionMode for CanonicalizeAllFreeRegions { + fn canonicalize_free_region( + &self, + canonicalizer: &mut Canonicalizer<'_, '_, 'tcx>, + r: ty::Region<'tcx>, + ) -> ty::Region<'tcx> { + canonicalizer.canonical_var_for_region(r) + } + + fn any(&self) -> bool { + true + } } -impl CanonicalizeRegionMode { +struct CanonicalizeFreeRegionsOtherThanStatic; + +impl CanonicalizeRegionMode for CanonicalizeFreeRegionsOtherThanStatic { + fn canonicalize_free_region( + &self, + canonicalizer: &mut Canonicalizer<'_, '_, 'tcx>, + r: ty::Region<'tcx>, + ) -> ty::Region<'tcx> { + if let ty::ReStatic = r { + r + } else { + canonicalizer.canonical_var_for_region(r) + } + } + fn any(&self) -> bool { - self.static_region || self.other_free_regions + true } } @@ -172,7 +226,7 @@ struct Canonicalizer<'cx, 'gcx: 'tcx, 'tcx: 'cx> { // Note that indices is only used once `var_values` is big enough to be // heap-allocated. indices: FxHashMap<Kind<'tcx>, CanonicalVar>, - canonicalize_region_mode: CanonicalizeRegionMode, + canonicalize_region_mode: &'cx dyn CanonicalizeRegionMode, needs_canonical_flags: TypeFlags, } @@ -201,26 +255,13 @@ impl<'cx, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for Canonicalizer<'cx, 'gcx, 'tcx> self.canonical_var_for_region(r) } - ty::ReStatic => { - if self.canonicalize_region_mode.static_region { - self.canonical_var_for_region(r) - } else { - r - } - } - - ty::ReEarlyBound(..) + ty::ReStatic + | ty::ReEarlyBound(..) | ty::ReFree(_) | ty::ReScope(_) | ty::RePlaceholder(..) | ty::ReEmpty - | ty::ReErased => { - if self.canonicalize_region_mode.other_free_regions { - self.canonical_var_for_region(r) - } else { - r - } - } + | ty::ReErased => self.canonicalize_region_mode.canonicalize_free_region(self, r), ty::ReClosureBound(..) | ty::ReCanonical(_) => { bug!("canonical region encountered during canonicalization") @@ -286,10 +327,10 @@ impl<'cx, 'gcx, 'tcx> Canonicalizer<'cx, 'gcx, 'tcx> { /// `canonicalize_query` and `canonicalize_response`. fn canonicalize<V>( value: &V, - infcx: Option<&'cx InferCtxt<'cx, 'gcx, 'tcx>>, - tcx: TyCtxt<'cx, 'gcx, 'tcx>, - canonicalize_region_mode: CanonicalizeRegionMode, - var_values: &'cx mut SmallCanonicalVarValues<'tcx>, + infcx: Option<&InferCtxt<'_, 'gcx, 'tcx>>, + tcx: TyCtxt<'_, 'gcx, 'tcx>, + canonicalize_region_mode: &dyn CanonicalizeRegionMode, + var_values: &mut SmallCanonicalVarValues<'tcx>, ) -> Canonicalized<'gcx, V> where V: TypeFoldable<'tcx> + Lift<'gcx>, |
