]> git.lizzy.rs Git - rust.git/blob - src/librustc_infer/traits/codegen/mod.rs
Update const_forget.rs
[rust.git] / src / librustc_infer / traits / codegen / mod.rs
1 // This file contains various trait resolution methods used by codegen.
2 // They all assume regions can be erased and monomorphic types.  It
3 // seems likely that they should eventually be merged into more
4 // general routines.
5
6 use crate::infer::{InferCtxt, TyCtxtInferExt};
7 use crate::traits::{
8     FulfillmentContext, Obligation, ObligationCause, SelectionContext, TraitEngine, Vtable,
9 };
10 use rustc::ty::fold::TypeFoldable;
11 use rustc::ty::{self, TyCtxt};
12
13 /// Attempts to resolve an obligation to a vtable. The result is
14 /// a shallow vtable resolution, meaning that we do not
15 /// (necessarily) resolve all nested obligations on the impl. Note
16 /// that type check should guarantee to us that all nested
17 /// obligations *could be* resolved if we wanted to.
18 /// Assumes that this is run after the entire crate has been successfully type-checked.
19 pub fn codegen_fulfill_obligation<'tcx>(
20     ty: TyCtxt<'tcx>,
21     (param_env, trait_ref): (ty::ParamEnv<'tcx>, ty::PolyTraitRef<'tcx>),
22 ) -> Vtable<'tcx, ()> {
23     // Remove any references to regions; this helps improve caching.
24     let trait_ref = ty.erase_regions(&trait_ref);
25
26     debug!(
27         "codegen_fulfill_obligation(trait_ref={:?}, def_id={:?})",
28         (param_env, trait_ref),
29         trait_ref.def_id()
30     );
31
32     // Do the initial selection for the obligation. This yields the
33     // shallow result we are looking for -- that is, what specific impl.
34     ty.infer_ctxt().enter(|infcx| {
35         let mut selcx = SelectionContext::new(&infcx);
36
37         let obligation_cause = ObligationCause::dummy();
38         let obligation =
39             Obligation::new(obligation_cause, param_env, trait_ref.to_poly_trait_predicate());
40
41         let selection = match selcx.select(&obligation) {
42             Ok(Some(selection)) => selection,
43             Ok(None) => {
44                 // Ambiguity can happen when monomorphizing during trans
45                 // expands to some humongo type that never occurred
46                 // statically -- this humongo type can then overflow,
47                 // leading to an ambiguous result. So report this as an
48                 // overflow bug, since I believe this is the only case
49                 // where ambiguity can result.
50                 bug!(
51                     "Encountered ambiguity selecting `{:?}` during codegen, \
52                       presuming due to overflow",
53                     trait_ref
54                 )
55             }
56             Err(e) => {
57                 bug!("Encountered error `{:?}` selecting `{:?}` during codegen", e, trait_ref)
58             }
59         };
60
61         debug!("fulfill_obligation: selection={:?}", selection);
62
63         // Currently, we use a fulfillment context to completely resolve
64         // all nested obligations. This is because they can inform the
65         // inference of the impl's type parameters.
66         let mut fulfill_cx = FulfillmentContext::new();
67         let vtable = selection.map(|predicate| {
68             debug!("fulfill_obligation: register_predicate_obligation {:?}", predicate);
69             fulfill_cx.register_predicate_obligation(&infcx, predicate);
70         });
71         let vtable = infcx.drain_fulfillment_cx_or_panic(&mut fulfill_cx, &vtable);
72
73         info!("Cache miss: {:?} => {:?}", trait_ref, vtable);
74         vtable
75     })
76 }
77
78 // # Global Cache
79
80 impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
81     /// Finishes processes any obligations that remain in the
82     /// fulfillment context, and then returns the result with all type
83     /// variables removed and regions erased. Because this is intended
84     /// for use after type-check has completed, if any errors occur,
85     /// it will panic. It is used during normalization and other cases
86     /// where processing the obligations in `fulfill_cx` may cause
87     /// type inference variables that appear in `result` to be
88     /// unified, and hence we need to process those obligations to get
89     /// the complete picture of the type.
90     fn drain_fulfillment_cx_or_panic<T>(
91         &self,
92         fulfill_cx: &mut FulfillmentContext<'tcx>,
93         result: &T,
94     ) -> T
95     where
96         T: TypeFoldable<'tcx>,
97     {
98         debug!("drain_fulfillment_cx_or_panic()");
99
100         // In principle, we only need to do this so long as `result`
101         // contains unbound type parameters. It could be a slight
102         // optimization to stop iterating early.
103         if let Err(errors) = fulfill_cx.select_all_or_error(self) {
104             bug!("Encountered errors `{:?}` resolving bounds after type-checking", errors);
105         }
106
107         let result = self.resolve_vars_if_possible(result);
108         self.tcx.erase_regions(&result)
109     }
110 }