]>
Commit | Line | Data |
---|---|---|
94b46f34 | 1 | // This file contains various trait resolution methods used by codegen. |
9c376795 | 2 | // They all assume regions can be erased and monomorphic types. It |
cc61c64b XL |
3 | // seems likely that they should eventually be merged into more |
4 | // general routines. | |
5 | ||
49aad941 | 6 | use rustc_infer::infer::TyCtxtInferExt; |
9ffffee4 | 7 | use rustc_infer::traits::{FulfillmentErrorCode, TraitEngineExt as _}; |
fe692bf9 | 8 | use rustc_middle::traits::CodegenObligationError; |
ba9703b0 | 9 | use rustc_middle::ty::{self, TyCtxt}; |
487cf647 FG |
10 | use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt; |
11 | use rustc_trait_selection::traits::{ | |
12 | ImplSource, Obligation, ObligationCause, SelectionContext, TraitEngine, TraitEngineExt, | |
13 | Unimplemented, | |
14 | }; | |
cc61c64b | 15 | |
94222f64 | 16 | /// Attempts to resolve an obligation to an `ImplSource`. The result is |
f035d41b | 17 | /// a shallow `ImplSource` resolution, meaning that we do not |
abe05a73 XL |
18 | /// (necessarily) resolve all nested obligations on the impl. Note |
19 | /// that type check should guarantee to us that all nested | |
20 | /// obligations *could be* resolved if we wanted to. | |
29967ef6 | 21 | /// |
29967ef6 | 22 | /// This also expects that `trait_ref` is fully normalized. |
f2b60f7d | 23 | pub fn codegen_select_candidate<'tcx>( |
29967ef6 | 24 | tcx: TyCtxt<'tcx>, |
fe692bf9 | 25 | (param_env, trait_ref): (ty::ParamEnv<'tcx>, ty::TraitRef<'tcx>), |
04454e1e | 26 | ) -> Result<&'tcx ImplSource<'tcx, ()>, CodegenObligationError> { |
29967ef6 XL |
27 | // We expect the input to be fully normalized. |
28 | debug_assert_eq!(trait_ref, tcx.normalize_erasing_regions(param_env, trait_ref)); | |
abe05a73 XL |
29 | |
30 | // Do the initial selection for the obligation. This yields the | |
31 | // shallow result we are looking for -- that is, what specific impl. | |
fe692bf9 | 32 | let infcx = tcx.infer_ctxt().ignoring_regions().build(); |
2b03887a | 33 | let mut selcx = SelectionContext::new(&infcx); |
abe05a73 | 34 | |
2b03887a | 35 | let obligation_cause = ObligationCause::dummy(); |
487cf647 | 36 | let obligation = Obligation::new(tcx, obligation_cause, param_env, trait_ref); |
abe05a73 | 37 | |
2b03887a FG |
38 | let selection = match selcx.select(&obligation) { |
39 | Ok(Some(selection)) => selection, | |
40 | Ok(None) => return Err(CodegenObligationError::Ambiguity), | |
41 | Err(Unimplemented) => return Err(CodegenObligationError::Unimplemented), | |
42 | Err(e) => { | |
43 | bug!("Encountered error `{:?}` selecting `{:?}` during codegen", e, trait_ref) | |
44 | } | |
45 | }; | |
abe05a73 | 46 | |
2b03887a | 47 | debug!(?selection); |
abe05a73 | 48 | |
2b03887a FG |
49 | // Currently, we use a fulfillment context to completely resolve |
50 | // all nested obligations. This is because they can inform the | |
51 | // inference of the impl's type parameters. | |
fe692bf9 | 52 | let mut fulfill_cx = <dyn TraitEngine<'tcx>>::new(&infcx); |
2b03887a FG |
53 | let impl_source = selection.map(|predicate| { |
54 | fulfill_cx.register_predicate_obligation(&infcx, predicate); | |
55 | }); | |
04454e1e | 56 | |
2b03887a FG |
57 | // In principle, we only need to do this so long as `impl_source` |
58 | // contains unbound type parameters. It could be a slight | |
59 | // optimization to stop iterating early. | |
60 | let errors = fulfill_cx.select_all_or_error(&infcx); | |
61 | if !errors.is_empty() { | |
62 | // `rustc_monomorphize::collector` assumes there are no type errors. | |
63 | // Cycle errors are the only post-monomorphization errors possible; emit them now so | |
64 | // `rustc_ty_utils::resolve_associated_item` doesn't return `None` post-monomorphization. | |
65 | for err in errors { | |
66 | if let FulfillmentErrorCode::CodeCycle(cycle) = err.code { | |
487cf647 | 67 | infcx.err_ctxt().report_overflow_obligation_cycle(&cycle); |
2b03887a | 68 | } |
04454e1e | 69 | } |
2b03887a FG |
70 | return Err(CodegenObligationError::FulfillmentError); |
71 | } | |
04454e1e | 72 | |
2b03887a FG |
73 | let impl_source = infcx.resolve_vars_if_possible(impl_source); |
74 | let impl_source = infcx.tcx.erase_regions(impl_source); | |
abe05a73 | 75 | |
2b03887a | 76 | Ok(&*tcx.arena.alloc(impl_source)) |
abe05a73 | 77 | } |