]>
Commit | Line | Data |
---|---|---|
94b46f34 | 1 | // This file contains various trait resolution methods used by codegen. |
cc61c64b XL |
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 | ||
487cf647 | 6 | use rustc_infer::infer::{DefiningAnchor, TyCtxtInferExt}; |
2b03887a | 7 | use rustc_infer::traits::FulfillmentErrorCode; |
04454e1e | 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>, |
dc9dc135 | 25 | (param_env, trait_ref): (ty::ParamEnv<'tcx>, ty::PolyTraitRef<'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. | |
2b03887a FG |
32 | let infcx = tcx |
33 | .infer_ctxt() | |
34 | .ignoring_regions() | |
35 | .with_opaque_type_inference(DefiningAnchor::Bubble) | |
36 | .build(); | |
37 | //~^ HACK `Bubble` is required for | |
38 | // this test to pass: type-alias-impl-trait/assoc-projection-ice.rs | |
39 | let mut selcx = SelectionContext::new(&infcx); | |
abe05a73 | 40 | |
2b03887a | 41 | let obligation_cause = ObligationCause::dummy(); |
487cf647 | 42 | let obligation = Obligation::new(tcx, obligation_cause, param_env, trait_ref); |
abe05a73 | 43 | |
2b03887a FG |
44 | let selection = match selcx.select(&obligation) { |
45 | Ok(Some(selection)) => selection, | |
46 | Ok(None) => return Err(CodegenObligationError::Ambiguity), | |
47 | Err(Unimplemented) => return Err(CodegenObligationError::Unimplemented), | |
48 | Err(e) => { | |
49 | bug!("Encountered error `{:?}` selecting `{:?}` during codegen", e, trait_ref) | |
50 | } | |
51 | }; | |
abe05a73 | 52 | |
2b03887a | 53 | debug!(?selection); |
abe05a73 | 54 | |
2b03887a FG |
55 | // Currently, we use a fulfillment context to completely resolve |
56 | // all nested obligations. This is because they can inform the | |
57 | // inference of the impl's type parameters. | |
58 | let mut fulfill_cx = <dyn TraitEngine<'tcx>>::new(tcx); | |
59 | let impl_source = selection.map(|predicate| { | |
60 | fulfill_cx.register_predicate_obligation(&infcx, predicate); | |
61 | }); | |
04454e1e | 62 | |
2b03887a FG |
63 | // In principle, we only need to do this so long as `impl_source` |
64 | // contains unbound type parameters. It could be a slight | |
65 | // optimization to stop iterating early. | |
66 | let errors = fulfill_cx.select_all_or_error(&infcx); | |
67 | if !errors.is_empty() { | |
68 | // `rustc_monomorphize::collector` assumes there are no type errors. | |
69 | // Cycle errors are the only post-monomorphization errors possible; emit them now so | |
70 | // `rustc_ty_utils::resolve_associated_item` doesn't return `None` post-monomorphization. | |
71 | for err in errors { | |
72 | if let FulfillmentErrorCode::CodeCycle(cycle) = err.code { | |
487cf647 | 73 | infcx.err_ctxt().report_overflow_obligation_cycle(&cycle); |
2b03887a | 74 | } |
04454e1e | 75 | } |
2b03887a FG |
76 | return Err(CodegenObligationError::FulfillmentError); |
77 | } | |
04454e1e | 78 | |
2b03887a FG |
79 | let impl_source = infcx.resolve_vars_if_possible(impl_source); |
80 | let impl_source = infcx.tcx.erase_regions(impl_source); | |
abe05a73 | 81 | |
2b03887a FG |
82 | // Opaque types may have gotten their hidden types constrained, but we can ignore them safely |
83 | // as they will get constrained elsewhere, too. | |
84 | // (ouz-a) This is required for `type-alias-impl-trait/assoc-projection-ice.rs` to pass | |
85 | let _ = infcx.inner.borrow_mut().opaque_type_storage.take_opaque_types(); | |
5e7ed085 | 86 | |
2b03887a | 87 | Ok(&*tcx.arena.alloc(impl_source)) |
abe05a73 | 88 | } |