Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
introduce
tcx.normalize_erasing_regions(..)
operaton [VIC]
- Loading branch information
1 parent
ca87d24
commit 211d9ad
Showing
8 changed files
with
143 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,81 @@ | ||
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT | ||
// file at the top-level directory of this distribution and at | ||
// http://rust-lang.org/COPYRIGHT. | ||
// | ||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or | ||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license | ||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your | ||
// option. This file may not be copied, modified, or distributed | ||
// except according to those terms. | ||
|
||
//! Methods for normalizing when you don't care about regions (and | ||
//! aren't doing type inference). If either of those things don't | ||
//! apply to you, use `infcx.normalize(...)`. | ||
//! | ||
//! The methods in this file use a `TypeFolder` to recursively process | ||
//! contents, invoking the underlying | ||
//! `normalize_ty_after_erasing_regions` query for each type found | ||
//! within. (This underlying query is what is cached.) | ||
|
||
use ty::{self, Ty, TyCtxt}; | ||
use ty::fold::{TypeFoldable, TypeFolder}; | ||
|
||
impl<'cx, 'tcx> TyCtxt<'cx, 'tcx, 'tcx> { | ||
/// Erase the regions in `value` and then fully normalize all the | ||
/// types found within. The result will also have regions erased. | ||
/// | ||
/// This is appropriate to use only after type-check: it assumes | ||
/// that normalization will succeed, for example. | ||
pub fn normalize_erasing_regions<T>(self, param_env: ty::ParamEnv<'tcx>, value: T) -> T | ||
where | ||
T: TypeFoldable<'tcx>, | ||
{ | ||
// Erase first before we do the real query -- this keeps the | ||
// cache from being too polluted. | ||
let value = self.erase_regions(&value); | ||
if !value.has_projections() { | ||
value | ||
} else { | ||
value.fold_with(&mut NormalizeAfterErasingRegionsFolder { | ||
tcx: self, | ||
param_env: param_env, | ||
}) | ||
} | ||
} | ||
|
||
/// If you have a `Binder<T>`, you can do this to strip out the | ||
/// late-bound regions and then normalize the result, yielding up | ||
/// a `T` (with regions erased). This is appropriate when the | ||
/// binder is being instantiated at the call site. | ||
/// | ||
/// NB. Currently, higher-ranked type bounds inhibit | ||
/// normalization. Therefore, each time we erase them in | ||
/// translation, we need to normalize the contents. | ||
pub fn normalize_erasing_late_bound_regions<T>( | ||
self, | ||
param_env: ty::ParamEnv<'tcx>, | ||
value: &ty::Binder<T>, | ||
) -> T | ||
where | ||
T: TypeFoldable<'tcx>, | ||
{ | ||
assert!(!value.needs_subst()); | ||
let value = self.erase_late_bound_regions(value); | ||
self.normalize_erasing_regions(param_env, value) | ||
} | ||
} | ||
|
||
struct NormalizeAfterErasingRegionsFolder<'cx, 'tcx: 'cx> { | ||
tcx: TyCtxt<'cx, 'tcx, 'tcx>, | ||
param_env: ty::ParamEnv<'tcx>, | ||
} | ||
|
||
impl<'cx, 'tcx> TypeFolder<'tcx, 'tcx> for NormalizeAfterErasingRegionsFolder<'cx, 'tcx> { | ||
fn tcx<'a>(&'a self) -> TyCtxt<'a, 'tcx, 'tcx> { | ||
self.tcx | ||
} | ||
|
||
fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> { | ||
self.tcx.normalize_ty_after_erasing_regions(self.param_env.and(ty)) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT | ||
// file at the top-level directory of this distribution and at | ||
// http://rust-lang.org/COPYRIGHT. | ||
// | ||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or | ||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license | ||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your | ||
// option. This file may not be copied, modified, or distributed | ||
// except according to those terms. | ||
|
||
use rustc::traits::{Normalized, ObligationCause}; | ||
use rustc::traits::query::NoSolution; | ||
use rustc::ty::{ParamEnvAnd, Ty, TyCtxt}; | ||
use rustc::util::common::CellUsizeExt; | ||
|
||
crate fn normalize_ty_after_erasing_regions<'tcx>( | ||
tcx: TyCtxt<'_, 'tcx, 'tcx>, | ||
goal: ParamEnvAnd<'tcx, Ty<'tcx>>, | ||
) -> Ty<'tcx> { | ||
let ParamEnvAnd { param_env, value } = goal; | ||
tcx.sess.perf_stats.normalize_ty_after_erasing_regions.increment(); | ||
tcx.infer_ctxt().enter(|infcx| { | ||
let cause = ObligationCause::dummy(); | ||
match infcx.at(&cause, param_env).normalize(&value) { | ||
Ok(Normalized { value: normalized_value, obligations: _ }) => { | ||
// ^^^^^^^^^^^ | ||
// We don't care about the `obligations`, | ||
// they are always only region relations, | ||
// and we are about to erase those anyway. | ||
let normalized_value = infcx.resolve_type_vars_if_possible(&normalized_value); | ||
let normalized_value = infcx.tcx.erase_regions(&normalized_value); | ||
tcx.lift_to_global(&normalized_value).unwrap() | ||
} | ||
Err(NoSolution) => bug!("could not fully normalize `{:?}`", value), | ||
} | ||
}) | ||
} |