]> git.proxmox.com Git - rustc.git/blame - compiler/rustc_trait_selection/src/traits/chalk_fulfill.rs
New upstream version 1.59.0+dfsg1
[rustc.git] / compiler / rustc_trait_selection / src / traits / chalk_fulfill.rs
CommitLineData
1b1a35ee
XL
1//! Defines a Chalk-based `TraitEngine`
2
3use crate::infer::canonical::OriginalQueryValues;
4use crate::infer::InferCtxt;
5use crate::traits::query::NoSolution;
6use crate::traits::{
7 ChalkEnvironmentAndGoal, FulfillmentError, FulfillmentErrorCode, ObligationCause,
8 PredicateObligation, SelectionError, TraitEngine,
9};
c295e0f8 10use rustc_data_structures::fx::{FxHashMap, FxIndexSet};
1b1a35ee
XL
11use rustc_middle::ty::{self, Ty};
12
13pub struct FulfillmentContext<'tcx> {
14 obligations: FxIndexSet<PredicateObligation<'tcx>>,
c295e0f8
XL
15
16 relationships: FxHashMap<ty::TyVid, ty::FoundRelationships>,
1b1a35ee
XL
17}
18
a2a8927a 19impl FulfillmentContext<'_> {
1b1a35ee 20 crate fn new() -> Self {
c295e0f8
XL
21 FulfillmentContext {
22 obligations: FxIndexSet::default(),
23 relationships: FxHashMap::default(),
24 }
1b1a35ee
XL
25 }
26}
27
a2a8927a 28impl<'tcx> TraitEngine<'tcx> for FulfillmentContext<'tcx> {
1b1a35ee
XL
29 fn normalize_projection_type(
30 &mut self,
31 infcx: &InferCtxt<'_, 'tcx>,
32 _param_env: ty::ParamEnv<'tcx>,
33 projection_ty: ty::ProjectionTy<'tcx>,
34 _cause: ObligationCause<'tcx>,
35 ) -> Ty<'tcx> {
36 infcx.tcx.mk_ty(ty::Projection(projection_ty))
37 }
38
39 fn register_predicate_obligation(
40 &mut self,
41 infcx: &InferCtxt<'_, 'tcx>,
42 obligation: PredicateObligation<'tcx>,
43 ) {
44 assert!(!infcx.is_in_snapshot());
fc512014 45 let obligation = infcx.resolve_vars_if_possible(obligation);
1b1a35ee 46
c295e0f8
XL
47 super::relationships::update(self, infcx, &obligation);
48
1b1a35ee
XL
49 self.obligations.insert(obligation);
50 }
51
3c0e092e
XL
52 fn select_all_or_error(&mut self, infcx: &InferCtxt<'_, 'tcx>) -> Vec<FulfillmentError<'tcx>> {
53 {
54 let errors = self.select_where_possible(infcx);
55
56 if !errors.is_empty() {
57 return errors;
58 }
1b1a35ee 59 }
3c0e092e
XL
60
61 // any remaining obligations are errors
62 self.obligations
63 .iter()
64 .map(|obligation| FulfillmentError {
65 obligation: obligation.clone(),
66 code: FulfillmentErrorCode::CodeAmbiguity,
67 // FIXME - does Chalk have a notation of 'root obligation'?
68 // This is just for diagnostics, so it's okay if this is wrong
69 root_obligation: obligation.clone(),
70 })
71 .collect()
1b1a35ee
XL
72 }
73
74 fn select_where_possible(
75 &mut self,
76 infcx: &InferCtxt<'_, 'tcx>,
3c0e092e 77 ) -> Vec<FulfillmentError<'tcx>> {
1b1a35ee
XL
78 assert!(!infcx.is_in_snapshot());
79
80 let mut errors = Vec::new();
81 let mut next_round = FxIndexSet::default();
82 let mut making_progress;
83
84 loop {
85 making_progress = false;
86
87 // We iterate over all obligations, and record if we are able
88 // to unambiguously prove at least one obligation.
89 for obligation in self.obligations.drain(..) {
fc512014 90 let obligation = infcx.resolve_vars_if_possible(obligation);
1b1a35ee
XL
91 let environment = obligation.param_env.caller_bounds();
92 let goal = ChalkEnvironmentAndGoal { environment, goal: obligation.predicate };
93 let mut orig_values = OriginalQueryValues::default();
fc512014 94 let canonical_goal = infcx.canonicalize_query(goal, &mut orig_values);
1b1a35ee
XL
95
96 match infcx.tcx.evaluate_goal(canonical_goal) {
97 Ok(response) => {
98 if response.is_proven() {
99 making_progress = true;
100
101 match infcx.instantiate_query_response_and_region_obligations(
102 &obligation.cause,
103 obligation.param_env,
104 &orig_values,
105 &response,
106 ) {
107 Ok(infer_ok) => next_round.extend(
108 infer_ok.obligations.into_iter().map(|obligation| {
109 assert!(!infcx.is_in_snapshot());
fc512014 110 infcx.resolve_vars_if_possible(obligation)
1b1a35ee
XL
111 }),
112 ),
113
114 Err(_err) => errors.push(FulfillmentError {
136023e0 115 obligation: obligation.clone(),
1b1a35ee
XL
116 code: FulfillmentErrorCode::CodeSelectionError(
117 SelectionError::Unimplemented,
118 ),
136023e0
XL
119 // FIXME - does Chalk have a notation of 'root obligation'?
120 // This is just for diagnostics, so it's okay if this is wrong
121 root_obligation: obligation,
1b1a35ee
XL
122 }),
123 }
124 } else {
125 // Ambiguous: retry at next round.
126 next_round.insert(obligation);
127 }
128 }
129
130 Err(NoSolution) => errors.push(FulfillmentError {
136023e0 131 obligation: obligation.clone(),
1b1a35ee
XL
132 code: FulfillmentErrorCode::CodeSelectionError(
133 SelectionError::Unimplemented,
134 ),
136023e0
XL
135 // FIXME - does Chalk have a notation of 'root obligation'?
136 // This is just for diagnostics, so it's okay if this is wrong
137 root_obligation: obligation,
1b1a35ee
XL
138 }),
139 }
140 }
141 next_round = std::mem::replace(&mut self.obligations, next_round);
142
143 if !making_progress {
144 break;
145 }
146 }
147
3c0e092e 148 errors
1b1a35ee
XL
149 }
150
151 fn pending_obligations(&self) -> Vec<PredicateObligation<'tcx>> {
152 self.obligations.iter().cloned().collect()
153 }
c295e0f8
XL
154
155 fn relationships(&mut self) -> &mut FxHashMap<ty::TyVid, ty::FoundRelationships> {
156 &mut self.relationships
157 }
1b1a35ee 158}