1use tracing::debug;
2
3use super::{
4 ExpectedFound, RelateResult, StructurallyRelateAliases, TypeRelation,
5 structurally_relate_consts, structurally_relate_tys,
6};
7use crate::error::TypeError;
8use crate::inherent::*;
9use crate::solve::Goal;
10use crate::visit::TypeVisitableExt as _;
11use crate::{self as ty, InferCtxtLike, Interner, TypingMode, Upcast};
12
13pub trait PredicateEmittingRelation<Infcx, I = <Infcx as InferCtxtLike>::Interner>:
14 TypeRelation<I>
15where
16 Infcx: InferCtxtLike<Interner = I>,
17 I: Interner,
18{
19 fn span(&self) -> I::Span;
20
21 fn param_env(&self) -> I::ParamEnv;
22
23 fn structurally_relate_aliases(&self) -> StructurallyRelateAliases;
27
28 fn register_goals(&mut self, obligations: impl IntoIterator<Item = Goal<I, I::Predicate>>);
30
31 fn register_predicates(
34 &mut self,
35 obligations: impl IntoIterator<Item: Upcast<I, I::Predicate>>,
36 );
37
38 fn register_alias_relate_predicate(&mut self, a: I::Ty, b: I::Ty);
40}
41
42pub fn super_combine_tys<Infcx, I, R>(
43 infcx: &Infcx,
44 relation: &mut R,
45 a: I::Ty,
46 b: I::Ty,
47) -> RelateResult<I, I::Ty>
48where
49 Infcx: InferCtxtLike<Interner = I>,
50 I: Interner,
51 R: PredicateEmittingRelation<Infcx>,
52{
53 debug!("super_combine_tys::<{}>({:?}, {:?})", std::any::type_name::<R>(), a, b);
54 debug_assert!(!a.has_escaping_bound_vars());
55 debug_assert!(!b.has_escaping_bound_vars());
56
57 match (a.kind(), b.kind()) {
58 (ty::Error(e), _) | (_, ty::Error(e)) => {
59 infcx.set_tainted_by_errors(e);
60 return Ok(Ty::new_error(infcx.cx(), e));
61 }
62
63 (ty::Infer(ty::IntVar(a_id)), ty::Infer(ty::IntVar(b_id))) => {
65 infcx.equate_int_vids_raw(a_id, b_id);
66 Ok(a)
67 }
68 (ty::Infer(ty::IntVar(v_id)), ty::Int(v)) => {
69 infcx.instantiate_int_var_raw(v_id, ty::IntVarValue::IntType(v));
70 Ok(b)
71 }
72 (ty::Int(v), ty::Infer(ty::IntVar(v_id))) => {
73 infcx.instantiate_int_var_raw(v_id, ty::IntVarValue::IntType(v));
74 Ok(a)
75 }
76 (ty::Infer(ty::IntVar(v_id)), ty::Uint(v)) => {
77 infcx.instantiate_int_var_raw(v_id, ty::IntVarValue::UintType(v));
78 Ok(b)
79 }
80 (ty::Uint(v), ty::Infer(ty::IntVar(v_id))) => {
81 infcx.instantiate_int_var_raw(v_id, ty::IntVarValue::UintType(v));
82 Ok(a)
83 }
84
85 (ty::Infer(ty::FloatVar(a_id)), ty::Infer(ty::FloatVar(b_id))) => {
87 infcx.equate_float_vids_raw(a_id, b_id);
88 Ok(a)
89 }
90 (ty::Infer(ty::FloatVar(v_id)), ty::Float(v)) => {
91 infcx.instantiate_float_var_raw(v_id, ty::FloatVarValue::Known(v));
92 Ok(b)
93 }
94 (ty::Float(v), ty::Infer(ty::FloatVar(v_id))) => {
95 infcx.instantiate_float_var_raw(v_id, ty::FloatVarValue::Known(v));
96 Ok(a)
97 }
98
99 (ty::Alias(..), ty::Infer(ty::TyVar(_))) | (ty::Infer(ty::TyVar(_)), ty::Alias(..))
101 if infcx.next_trait_solver() =>
102 {
103 panic!(
104 "We do not expect to encounter `TyVar` this late in combine \
105 -- they should have been handled earlier"
106 )
107 }
108 (_, ty::Infer(ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)))
109 | (ty::Infer(ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)), _)
110 if infcx.next_trait_solver() =>
111 {
112 panic!("We do not expect to encounter `Fresh` variables in the new solver")
113 }
114
115 (_, ty::Alias(..)) | (ty::Alias(..), _) if infcx.next_trait_solver() => {
116 match relation.structurally_relate_aliases() {
117 StructurallyRelateAliases::Yes => structurally_relate_tys(relation, a, b),
118 StructurallyRelateAliases::No => {
119 relation.register_alias_relate_predicate(a, b);
120 Ok(a)
121 }
122 }
123 }
124
125 (ty::Infer(_), _) | (_, ty::Infer(_)) => Err(TypeError::Sorts(ExpectedFound::new(a, b))),
127
128 (ty::Alias(ty::Opaque, _), _) | (_, ty::Alias(ty::Opaque, _)) => {
129 assert!(!infcx.next_trait_solver());
130 match infcx.typing_mode() {
131 TypingMode::Coherence => {
136 relation.register_predicates([ty::Binder::dummy(ty::PredicateKind::Ambiguous)]);
137 Ok(a)
138 }
139 TypingMode::Analysis { .. }
140 | TypingMode::Borrowck { .. }
141 | TypingMode::PostBorrowckAnalysis { .. }
142 | TypingMode::PostAnalysis => structurally_relate_tys(relation, a, b),
143 }
144 }
145
146 _ => structurally_relate_tys(relation, a, b),
147 }
148}
149
150pub fn super_combine_consts<Infcx, I, R>(
151 infcx: &Infcx,
152 relation: &mut R,
153 a: I::Const,
154 b: I::Const,
155) -> RelateResult<I, I::Const>
156where
157 Infcx: InferCtxtLike<Interner = I>,
158 I: Interner,
159 R: PredicateEmittingRelation<Infcx>,
160{
161 debug!("super_combine_consts::<{}>({:?}, {:?})", std::any::type_name::<R>(), a, b);
162 debug_assert!(!a.has_escaping_bound_vars());
163 debug_assert!(!b.has_escaping_bound_vars());
164
165 if a == b {
166 return Ok(a);
167 }
168
169 let a = infcx.shallow_resolve_const(a);
170 let b = infcx.shallow_resolve_const(b);
171
172 match (a.kind(), b.kind()) {
173 (
174 ty::ConstKind::Infer(ty::InferConst::Var(a_vid)),
175 ty::ConstKind::Infer(ty::InferConst::Var(b_vid)),
176 ) => {
177 infcx.equate_const_vids_raw(a_vid, b_vid);
178 Ok(a)
179 }
180
181 (ty::ConstKind::Infer(ty::InferConst::Var(_)), ty::ConstKind::Infer(_))
183 | (ty::ConstKind::Infer(_), ty::ConstKind::Infer(ty::InferConst::Var(_))) => {
184 panic!(
185 "tried to combine ConstKind::Infer/ConstKind::Infer(InferConst::Var): {a:?} and {b:?}"
186 )
187 }
188
189 (ty::ConstKind::Infer(ty::InferConst::Var(vid)), _) => {
190 infcx.instantiate_const_var_raw(relation, true, vid, b)?;
191 Ok(b)
192 }
193
194 (_, ty::ConstKind::Infer(ty::InferConst::Var(vid))) => {
195 infcx.instantiate_const_var_raw(relation, false, vid, a)?;
196 Ok(a)
197 }
198
199 (ty::ConstKind::Unevaluated(..), _) | (_, ty::ConstKind::Unevaluated(..))
200 if infcx.cx().features().generic_const_exprs() || infcx.next_trait_solver() =>
201 {
202 match relation.structurally_relate_aliases() {
203 StructurallyRelateAliases::No => {
204 relation.register_predicates([if infcx.next_trait_solver() {
205 ty::PredicateKind::AliasRelate(
206 a.into(),
207 b.into(),
208 ty::AliasRelationDirection::Equate,
209 )
210 } else {
211 ty::PredicateKind::ConstEquate(a, b)
212 }]);
213
214 Ok(b)
215 }
216 StructurallyRelateAliases::Yes => structurally_relate_consts(relation, a, b),
217 }
218 }
219 _ => structurally_relate_consts(relation, a, b),
220 }
221}