Skip to content

Commit 55fc165

Browse files
committed
introduce tcx.normalize_erasing_regions(..) operaton [VIC]
1 parent 3ee7e2b commit 55fc165

File tree

7 files changed

+140
-0
lines changed

7 files changed

+140
-0
lines changed

src/librustc/session/mod.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,8 @@ pub struct PerfStats {
166166
/// result had already been canonicalized.
167167
pub canonicalized_values_allocated: Cell<usize>,
168168
/// Number of times this query is invoked.
169+
pub normalize_ty_after_erasing_regions: Cell<usize>,
170+
/// Number of times this query is invoked.
169171
pub normalize_projection_ty: Cell<usize>,
170172
}
171173

@@ -775,6 +777,8 @@ impl Session {
775777
self.perf_stats.queries_canonicalized.get());
776778
println!("Total canonical values interned: {}",
777779
self.perf_stats.canonicalized_values_allocated.get());
780+
println!("normalize_ty_after_erasing_regions: {}",
781+
self.perf_stats.normalize_ty_after_erasing_regions.get());
778782
println!("normalize_projection_ty: {}",
779783
self.perf_stats.normalize_projection_ty.get());
780784
}
@@ -1041,6 +1045,7 @@ pub fn build_session_(sopts: config::Options,
10411045
decode_def_path_tables_time: Cell::new(Duration::from_secs(0)),
10421046
queries_canonicalized: Cell::new(0),
10431047
canonicalized_values_allocated: Cell::new(0),
1048+
normalize_ty_after_erasing_regions: Cell::new(0),
10441049
normalize_projection_ty: Cell::new(0),
10451050
},
10461051
code_stats: RefCell::new(CodeStats::new()),

src/librustc/traits/query/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
1818
pub mod dropck_outlives;
1919
pub mod normalize;
20+
pub mod normalize_erasing_regions;
2021

2122
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
2223
pub struct NoSolution;
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
//! Methods for normalizing when you don't care about regions (and
12+
//! aren't doing type inference). If either of those things don't
13+
//! apply to you, use `infcx.normalize(...)`.
14+
//!
15+
//! The methods in this file use a `TypeFolder` to recursively process
16+
//! contents, invoking the underlying
17+
//! `normalize_ty_after_erasing_regions` query for each type found
18+
//! within. (This underlying query is what is cached.)
19+
20+
use ty::{self, Ty, TyCtxt};
21+
use ty::fold::{TypeFoldable, TypeFolder};
22+
23+
impl<'cx, 'tcx> TyCtxt<'cx, 'tcx, 'tcx> {
24+
/// Erase the regions in `value` and then fully normalize all the
25+
/// types found within. The result will also have regions erased.
26+
///
27+
/// This is appropriate to use only after type-check: it assumes
28+
/// that normalization will succeed, for example.
29+
pub fn normalize_erasing_regions<T>(self, param_env: ty::ParamEnv<'tcx>, value: T) -> T
30+
where
31+
T: TypeFoldable<'tcx>,
32+
{
33+
// Erase first before we do the real query -- this keeps the
34+
// cache from being too polluted.
35+
let value = self.erase_regions(&value);
36+
if !value.has_projections() {
37+
value
38+
} else {
39+
value.fold_with(&mut NormalizeAfterErasingRegionsFolder {
40+
tcx: self,
41+
param_env: param_env,
42+
})
43+
}
44+
}
45+
46+
/// If you have a `Binder<T>`, you can do this to strip out the
47+
/// late-bound regions and then normalize the result, yielding up
48+
/// a `T` (with regions erased). This is appropriate when the
49+
/// binder is being instantiated at the call site.
50+
///
51+
/// NB. Currently, higher-ranked type bounds inhibit
52+
/// normalization. Therefore, each time we erase them in
53+
/// translation, we need to normalize the contents.
54+
pub fn normalize_erasing_late_bound_regions<T>(
55+
self,
56+
param_env: ty::ParamEnv<'tcx>,
57+
value: &ty::Binder<T>,
58+
) -> T
59+
where
60+
T: TypeFoldable<'tcx>,
61+
{
62+
assert!(!value.needs_subst());
63+
let value = self.erase_late_bound_regions(value);
64+
self.normalize_erasing_regions(param_env, value)
65+
}
66+
}
67+
68+
struct NormalizeAfterErasingRegionsFolder<'cx, 'tcx: 'cx> {
69+
tcx: TyCtxt<'cx, 'tcx, 'tcx>,
70+
param_env: ty::ParamEnv<'tcx>,
71+
}
72+
73+
impl<'cx, 'tcx> TypeFolder<'tcx, 'tcx> for NormalizeAfterErasingRegionsFolder<'cx, 'tcx> {
74+
fn tcx<'a>(&'a self) -> TyCtxt<'a, 'tcx, 'tcx> {
75+
self.tcx
76+
}
77+
78+
fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
79+
self.tcx.normalize_ty_after_erasing_regions(self.param_env.and(ty))
80+
}
81+
}

src/librustc/ty/maps/config.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,12 @@ impl<'tcx> QueryDescription<'tcx> for queries::dropck_outlives<'tcx> {
6666
}
6767
}
6868

69+
impl<'tcx> QueryDescription<'tcx> for queries::normalize_ty_after_erasing_regions<'tcx> {
70+
fn describe(_tcx: TyCtxt, goal: ParamEnvAnd<'tcx, Ty<'tcx>>) -> String {
71+
format!("normalizing `{:?}`", goal)
72+
}
73+
}
74+
6975
impl<'tcx> QueryDescription<'tcx> for queries::is_copy_raw<'tcx> {
7076
fn describe(_tcx: TyCtxt, env: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> String {
7177
format!("computing whether `{}` is `Copy`", env.value)

src/librustc/ty/maps/mod.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -375,6 +375,11 @@ define_maps! { <'tcx>
375375
&'tcx Canonical<ParamEnvAnd<'tcx, ty::ProjectionTy<'tcx>>>
376376
) -> Result<Rc<Canonical<QueryResult<'tcx, NormalizationResult<'tcx>>>>, NoSolution>,
377377

378+
/// Do not call this query directly: invoke `normalize_erasing_regions` instead.
379+
[] fn normalize_ty_after_erasing_regions: normalize_ty_node(
380+
ParamEnvAnd<'tcx, Ty<'tcx>>
381+
) -> Ty<'tcx>,
382+
378383
/// Do not call this query directly: invoke `infcx.at().dropck_outlives()` instead.
379384
[] fn dropck_outlives: normalize_ty_node(
380385
&'tcx Canonical<ParamEnvAnd<'tcx, Ty<'tcx>>>
@@ -527,6 +532,7 @@ fn output_filenames_node<'tcx>(_: CrateNum) -> DepConstructor<'tcx> {
527532
fn vtable_methods_node<'tcx>(trait_ref: ty::PolyTraitRef<'tcx>) -> DepConstructor<'tcx> {
528533
DepConstructor::VtableMethods{ trait_ref }
529534
}
535+
530536
fn normalize_ty_node<'tcx, T>(_: T) -> DepConstructor<'tcx> {
531537
DepConstructor::NormalizeTy
532538
}

src/librustc_traits/lib.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,15 @@
1919

2020
#[macro_use]
2121
extern crate log;
22+
#[macro_use]
2223
extern crate rustc;
2324
extern crate rustc_data_structures;
2425
extern crate syntax;
2526
extern crate syntax_pos;
2627

2728
mod dropck_outlives;
2829
mod normalize_projection_ty;
30+
mod normalize_erasing_regions;
2931
mod util;
3032

3133
use rustc::ty::maps::Providers;
@@ -35,6 +37,8 @@ pub fn provide(p: &mut Providers) {
3537
dropck_outlives: dropck_outlives::dropck_outlives,
3638
adt_dtorck_constraint: dropck_outlives::adt_dtorck_constraint,
3739
normalize_projection_ty: normalize_projection_ty::normalize_projection_ty,
40+
normalize_ty_after_erasing_regions:
41+
normalize_erasing_regions::normalize_ty_after_erasing_regions,
3842
..*p
3943
};
4044
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
use rustc::traits::{Normalized, ObligationCause};
12+
use rustc::traits::query::NoSolution;
13+
use rustc::ty::{ParamEnvAnd, Ty, TyCtxt};
14+
use rustc::util::common::CellUsizeExt;
15+
16+
crate fn normalize_ty_after_erasing_regions<'tcx>(
17+
tcx: TyCtxt<'_, 'tcx, 'tcx>,
18+
goal: ParamEnvAnd<'tcx, Ty<'tcx>>,
19+
) -> Ty<'tcx> {
20+
let ParamEnvAnd { param_env, value } = goal;
21+
tcx.sess.perf_stats.normalize_ty_after_erasing_regions.increment();
22+
tcx.infer_ctxt().enter(|infcx| {
23+
let cause = ObligationCause::dummy();
24+
match infcx.at(&cause, param_env).normalize(&value) {
25+
Ok(Normalized { value: normalized_value, obligations: _ }) => {
26+
// ^^^^^^^^^^^
27+
// We don't care about the `obligations`,
28+
// they are always only region relations,
29+
// and we are about to erase those anyway.
30+
let normalized_value = infcx.resolve_type_vars_if_possible(&normalized_value);
31+
let normalized_value = infcx.tcx.erase_regions(&normalized_value);
32+
tcx.lift_to_global(&normalized_value).unwrap()
33+
}
34+
Err(NoSolution) => bug!("could not fully normalize `{:?}`", value),
35+
}
36+
})
37+
}

0 commit comments

Comments
 (0)