Skip to content

Commit 211d9ad

Browse files
committed
introduce tcx.normalize_erasing_regions(..) operaton [VIC]
1 parent ca87d24 commit 211d9ad

File tree

8 files changed

+143
-3
lines changed

8 files changed

+143
-3
lines changed

src/librustc/session/mod.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,8 @@ pub struct PerfStats {
179179
/// result had already been canonicalized.
180180
pub canonicalized_values_allocated: Cell<usize>,
181181
/// Number of times this query is invoked.
182+
pub normalize_ty_after_erasing_regions: Cell<usize>,
183+
/// Number of times this query is invoked.
182184
pub normalize_projection_ty: Cell<usize>,
183185
}
184186

@@ -869,6 +871,8 @@ impl Session {
869871
self.perf_stats.queries_canonicalized.get());
870872
println!("Total canonical values interned: {}",
871873
self.perf_stats.canonicalized_values_allocated.get());
874+
println!("normalize_ty_after_erasing_regions: {}",
875+
self.perf_stats.normalize_ty_after_erasing_regions.get());
872876
println!("normalize_projection_ty: {}",
873877
self.perf_stats.normalize_projection_ty.get());
874878
}
@@ -1159,6 +1163,7 @@ pub fn build_session_(
11591163
decode_def_path_tables_time: Cell::new(Duration::from_secs(0)),
11601164
queries_canonicalized: Cell::new(0),
11611165
canonicalized_values_allocated: Cell::new(0),
1166+
normalize_ty_after_erasing_regions: Cell::new(0),
11621167
normalize_projection_ty: Cell::new(0),
11631168
},
11641169
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
@@ -20,6 +20,7 @@ use ty::{self, Ty};
2020

2121
pub mod dropck_outlives;
2222
pub mod normalize;
23+
pub mod normalize_erasing_regions;
2324

2425
pub type CanonicalProjectionGoal<'tcx> =
2526
Canonical<'tcx, ty::ParamEnvAnd<'tcx, ty::ProjectionTy<'tcx>>>;
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: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ use dep_graph::SerializedDepNodeIndex;
1212
use hir::def_id::{CrateNum, DefId, DefIndex};
1313
use mir::interpret::{GlobalId};
1414
use traits::query::{CanonicalProjectionGoal, CanonicalTyGoal};
15-
use ty::{self, Ty, TyCtxt};
15+
use ty::{self, ParamEnvAnd, Ty, TyCtxt};
1616
use ty::subst::Substs;
1717
use ty::maps::queries;
1818

@@ -67,6 +67,12 @@ impl<'tcx> QueryDescription<'tcx> for queries::dropck_outlives<'tcx> {
6767
}
6868
}
6969

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

src/librustc/ty/maps/mod.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ use traits::query::{CanonicalProjectionGoal, CanonicalTyGoal, NoSolution};
3838
use traits::query::dropck_outlives::{DtorckConstraint, DropckOutlivesResult};
3939
use traits::query::normalize::NormalizationResult;
4040
use traits::specialization_graph;
41-
use ty::{self, CrateInherentImpls, Ty, TyCtxt};
41+
use ty::{self, CrateInherentImpls, ParamEnvAnd, Ty, TyCtxt};
4242
use ty::steal::Steal;
4343
use ty::subst::Substs;
4444
use util::nodemap::{DefIdSet, DefIdMap, ItemLocalSet};
@@ -394,6 +394,11 @@ define_maps! { <'tcx>
394394
NoSolution,
395395
>,
396396

397+
/// Do not call this query directly: invoke `normalize_erasing_regions` instead.
398+
[] fn normalize_ty_after_erasing_regions: NormalizeTyAfterErasingRegions(
399+
ParamEnvAnd<'tcx, Ty<'tcx>>
400+
) -> Ty<'tcx>,
401+
397402
/// Do not call this query directly: invoke `infcx.at().dropck_outlives()` instead.
398403
[] fn dropck_outlives: DropckOutlives(
399404
CanonicalTyGoal<'tcx>

src/librustc/ty/maps/plumbing.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -772,8 +772,9 @@ pub fn force_from_dep_node<'a, 'gcx, 'lcx>(tcx: TyCtxt<'a, 'gcx, 'lcx>,
772772
DepKind::FulfillObligation |
773773
DepKind::VtableMethods |
774774
DepKind::EraseRegionsTy |
775-
DepKind::NormalizeTy |
776775
DepKind::NormalizeProjectionTy |
776+
DepKind::NormalizeTyAfterErasingRegions |
777+
DepKind::NormalizeTy |
777778
DepKind::DropckOutlives |
778779
DepKind::SubstituteNormalizeAndTestPredicates |
779780
DepKind::InstanceDefSizeEstimate |

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)