]> git.proxmox.com Git - rustc.git/blob - src/librustc/traits/query/normalize_erasing_regions.rs
New upstream version 1.28.0~beta.14+dfsg1
[rustc.git] / src / librustc / traits / query / normalize_erasing_regions.rs
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 debug!(
34 "normalize_erasing_regions::<{}>(value={:?}, param_env={:?})",
35 unsafe { ::std::intrinsics::type_name::<T>() },
36 value,
37 param_env,
38 );
39
40 // Erase first before we do the real query -- this keeps the
41 // cache from being too polluted.
42 let value = self.erase_regions(&value);
43 if !value.has_projections() {
44 value
45 } else {
46 value.fold_with(&mut NormalizeAfterErasingRegionsFolder {
47 tcx: self,
48 param_env: param_env,
49 })
50 }
51 }
52
53 /// If you have a `Binder<T>`, you can do this to strip out the
54 /// late-bound regions and then normalize the result, yielding up
55 /// a `T` (with regions erased). This is appropriate when the
56 /// binder is being instantiated at the call site.
57 ///
58 /// NB. Currently, higher-ranked type bounds inhibit
59 /// normalization. Therefore, each time we erase them in
60 /// codegen, we need to normalize the contents.
61 pub fn normalize_erasing_late_bound_regions<T>(
62 self,
63 param_env: ty::ParamEnv<'tcx>,
64 value: &ty::Binder<T>,
65 ) -> T
66 where
67 T: TypeFoldable<'tcx>,
68 {
69 assert!(!value.needs_subst());
70 let value = self.erase_late_bound_regions(value);
71 self.normalize_erasing_regions(param_env, value)
72 }
73 }
74
75 struct NormalizeAfterErasingRegionsFolder<'cx, 'tcx: 'cx> {
76 tcx: TyCtxt<'cx, 'tcx, 'tcx>,
77 param_env: ty::ParamEnv<'tcx>,
78 }
79
80 impl<'cx, 'tcx> TypeFolder<'tcx, 'tcx> for NormalizeAfterErasingRegionsFolder<'cx, 'tcx> {
81 fn tcx<'a>(&'a self) -> TyCtxt<'a, 'tcx, 'tcx> {
82 self.tcx
83 }
84
85 fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
86 self.tcx.normalize_ty_after_erasing_regions(self.param_env.and(ty))
87 }
88 }