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
6 use rustc_infer
::infer
::{DefiningAnchor, TyCtxtInferExt}
;
7 use rustc_infer
::traits
::FulfillmentErrorCode
;
8 use rustc_middle
::traits
::CodegenObligationError
;
9 use rustc_middle
::ty
::{self, TyCtxt}
;
10 use rustc_trait_selection
::traits
::error_reporting
::TypeErrCtxtExt
;
11 use rustc_trait_selection
::traits
::{
12 ImplSource
, Obligation
, ObligationCause
, SelectionContext
, TraitEngine
, TraitEngineExt
,
16 /// Attempts to resolve an obligation to an `ImplSource`. The result is
17 /// a shallow `ImplSource` resolution, meaning that we do not
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.
22 /// This also expects that `trait_ref` is fully normalized.
23 pub fn codegen_select_candidate
<'tcx
>(
25 (param_env
, trait_ref
): (ty
::ParamEnv
<'tcx
>, ty
::PolyTraitRef
<'tcx
>),
26 ) -> Result
<&'tcx ImplSource
<'tcx
, ()>, CodegenObligationError
> {
27 // We expect the input to be fully normalized.
28 debug_assert_eq
!(trait_ref
, tcx
.normalize_erasing_regions(param_env
, trait_ref
));
30 // Do the initial selection for the obligation. This yields the
31 // shallow result we are looking for -- that is, what specific impl.
35 .with_opaque_type_inference(DefiningAnchor
::Bubble
)
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
);
41 let obligation_cause
= ObligationCause
::dummy();
42 let obligation
= Obligation
::new(tcx
, obligation_cause
, param_env
, trait_ref
);
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
),
49 bug
!("Encountered error `{:?}` selecting `{:?}` during codegen", e
, trait_ref
)
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
);
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.
72 if let FulfillmentErrorCode
::CodeCycle(cycle
) = err
.code
{
73 infcx
.err_ctxt().report_overflow_obligation_cycle(&cycle
);
76 return Err(CodegenObligationError
::FulfillmentError
);
79 let impl_source
= infcx
.resolve_vars_if_possible(impl_source
);
80 let impl_source
= infcx
.tcx
.erase_regions(impl_source
);
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
.take_opaque_types();
87 Ok(&*tcx
.arena
.alloc(impl_source
))