]> git.proxmox.com Git - rustc.git/blame - compiler/rustc_trait_selection/src/traits/codegen.rs
New upstream version 1.61.0+dfsg1
[rustc.git] / compiler / rustc_trait_selection / src / traits / codegen.rs
CommitLineData
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
74b04a01 6use crate::infer::{InferCtxt, TyCtxtInferExt};
dfeec247 7use crate::traits::{
f035d41b 8 FulfillmentContext, ImplSource, Obligation, ObligationCause, SelectionContext, TraitEngine,
3dfed10e 9 Unimplemented,
dfeec247 10};
5e7ed085 11use rustc_errors::ErrorGuaranteed;
ba9703b0
XL
12use rustc_middle::ty::fold::TypeFoldable;
13use rustc_middle::ty::{self, TyCtxt};
cc61c64b 14
94222f64 15/// Attempts to resolve an obligation to an `ImplSource`. The result is
f035d41b 16/// a shallow `ImplSource` resolution, meaning that we do not
abe05a73
XL
17/// (necessarily) resolve all nested obligations on the impl. Note
18/// that type check should guarantee to us that all nested
19/// obligations *could be* resolved if we wanted to.
29967ef6 20///
29967ef6 21/// This also expects that `trait_ref` is fully normalized.
5e7ed085 22#[instrument(level = "debug", skip(tcx))]
dc9dc135 23pub fn codegen_fulfill_obligation<'tcx>(
29967ef6 24 tcx: TyCtxt<'tcx>,
dc9dc135 25 (param_env, trait_ref): (ty::ParamEnv<'tcx>, ty::PolyTraitRef<'tcx>),
5e7ed085 26) -> Result<&'tcx ImplSource<'tcx, ()>, ErrorGuaranteed> {
abe05a73 27 // Remove any references to regions; this helps improve caching.
fc512014 28 let trait_ref = tcx.erase_regions(trait_ref);
29967ef6
XL
29 // We expect the input to be fully normalized.
30 debug_assert_eq!(trait_ref, tcx.normalize_erasing_regions(param_env, trait_ref));
abe05a73
XL
31
32 // Do the initial selection for the obligation. This yields the
33 // shallow result we are looking for -- that is, what specific impl.
29967ef6 34 tcx.infer_ctxt().enter(|infcx| {
abe05a73
XL
35 let mut selcx = SelectionContext::new(&infcx);
36
37 let obligation_cause = ObligationCause::dummy();
dfeec247
XL
38 let obligation =
39 Obligation::new(obligation_cause, param_env, trait_ref.to_poly_trait_predicate());
abe05a73
XL
40
41 let selection = match selcx.select(&obligation) {
42 Ok(Some(selection)) => selection,
43 Ok(None) => {
44 // Ambiguity can happen when monomorphizing during trans
5e7ed085
FG
45 // expands to some humongous type that never occurred
46 // statically -- this humongous type can then overflow,
abe05a73
XL
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.
5e7ed085 50 let reported = infcx.tcx.sess.delay_span_bug(
74b04a01
XL
51 rustc_span::DUMMY_SP,
52 &format!(
53 "encountered ambiguity selecting `{:?}` during codegen, presuming due to \
54 overflow or prior type error",
55 trait_ref
56 ),
57 );
5e7ed085 58 return Err(reported);
abe05a73 59 }
3dfed10e
XL
60 Err(Unimplemented) => {
61 // This can trigger when we probe for the source of a `'static` lifetime requirement
62 // on a trait object: `impl Foo for dyn Trait {}` has an implicit `'static` bound.
5099ac24
FG
63 // This can also trigger when we have a global bound that is not actually satisfied,
64 // but was included during typeck due to the trivial_bounds feature.
5e7ed085 65 let guar = infcx.tcx.sess.delay_span_bug(
3dfed10e
XL
66 rustc_span::DUMMY_SP,
67 &format!(
68 "Encountered error `Unimplemented` selecting `{:?}` during codegen",
69 trait_ref
70 ),
71 );
5e7ed085 72 return Err(guar);
3dfed10e 73 }
abe05a73 74 Err(e) => {
0bf4aa26 75 bug!("Encountered error `{:?}` selecting `{:?}` during codegen", e, trait_ref)
abe05a73
XL
76 }
77 };
78
5e7ed085 79 debug!(?selection);
abe05a73
XL
80
81 // Currently, we use a fulfillment context to completely resolve
82 // all nested obligations. This is because they can inform the
83 // inference of the impl's type parameters.
84 let mut fulfill_cx = FulfillmentContext::new();
f035d41b 85 let impl_source = selection.map(|predicate| {
abe05a73
XL
86 fulfill_cx.register_predicate_obligation(&infcx, predicate);
87 });
fc512014 88 let impl_source = drain_fulfillment_cx_or_panic(&infcx, &mut fulfill_cx, impl_source);
abe05a73 89
5e7ed085
FG
90 // Opaque types may have gotten their hidden types constrained, but we can ignore them safely
91 // as they will get constrained elsewhere, too.
92 let _opaque_types = infcx.inner.borrow_mut().opaque_type_storage.take_opaque_types();
93
94 debug!("Cache miss: {trait_ref:?} => {impl_source:?}");
5099ac24 95 Ok(&*tcx.arena.alloc(impl_source))
abe05a73
XL
96 })
97}
cc61c64b 98
cc61c64b
XL
99// # Global Cache
100
ba9703b0
XL
101/// Finishes processes any obligations that remain in the
102/// fulfillment context, and then returns the result with all type
103/// variables removed and regions erased. Because this is intended
5099ac24 104/// for use outside of type inference, if any errors occur,
ba9703b0
XL
105/// it will panic. It is used during normalization and other cases
106/// where processing the obligations in `fulfill_cx` may cause
107/// type inference variables that appear in `result` to be
108/// unified, and hence we need to process those obligations to get
109/// the complete picture of the type.
a2a8927a 110fn drain_fulfillment_cx_or_panic<'tcx, T>(
ba9703b0
XL
111 infcx: &InferCtxt<'_, 'tcx>,
112 fulfill_cx: &mut FulfillmentContext<'tcx>,
fc512014 113 result: T,
ba9703b0
XL
114) -> T
115where
116 T: TypeFoldable<'tcx>,
117{
118 debug!("drain_fulfillment_cx_or_panic()");
0531ce1d 119
ba9703b0
XL
120 // In principle, we only need to do this so long as `result`
121 // contains unbound type parameters. It could be a slight
122 // optimization to stop iterating early.
3c0e092e
XL
123 let errors = fulfill_cx.select_all_or_error(infcx);
124 if !errors.is_empty() {
1b1a35ee
XL
125 infcx.tcx.sess.delay_span_bug(
126 rustc_span::DUMMY_SP,
5099ac24
FG
127 &format!(
128 "Encountered errors `{:?}` resolving bounds outside of type inference",
129 errors
130 ),
1b1a35ee 131 );
0531ce1d 132 }
ba9703b0
XL
133
134 let result = infcx.resolve_vars_if_possible(result);
fc512014 135 infcx.tcx.erase_regions(result)
0531ce1d 136}