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::PostBorrowckAnalysis { .. }
141 | TypingMode::PostAnalysis => structurally_relate_tys(relation, a, b),
142 }
143 }
144
145 _ => structurally_relate_tys(relation, a, b),
146 }
147}
148
149pub fn super_combine_consts<Infcx, I, R>(
150 infcx: &Infcx,
151 relation: &mut R,
152 a: I::Const,
153 b: I::Const,
154) -> RelateResult<I, I::Const>
155where
156 Infcx: InferCtxtLike<Interner = I>,
157 I: Interner,
158 R: PredicateEmittingRelation<Infcx>,
159{
160 debug!("super_combine_consts::<{}>({:?}, {:?})", std::any::type_name::<R>(), a, b);
161 debug_assert!(!a.has_escaping_bound_vars());
162 debug_assert!(!b.has_escaping_bound_vars());
163
164 if a == b {
165 return Ok(a);
166 }
167
168 let a = infcx.shallow_resolve_const(a);
169 let b = infcx.shallow_resolve_const(b);
170
171 match (a.kind(), b.kind()) {
172 (
173 ty::ConstKind::Infer(ty::InferConst::Var(a_vid)),
174 ty::ConstKind::Infer(ty::InferConst::Var(b_vid)),
175 ) => {
176 infcx.equate_const_vids_raw(a_vid, b_vid);
177 Ok(a)
178 }
179
180 (ty::ConstKind::Infer(ty::InferConst::Var(_)), ty::ConstKind::Infer(_))
182 | (ty::ConstKind::Infer(_), ty::ConstKind::Infer(ty::InferConst::Var(_))) => {
183 panic!(
184 "tried to combine ConstKind::Infer/ConstKind::Infer(InferConst::Var): {a:?} and {b:?}"
185 )
186 }
187
188 (ty::ConstKind::Infer(ty::InferConst::Var(vid)), _) => {
189 infcx.instantiate_const_var_raw(relation, true, vid, b)?;
190 Ok(b)
191 }
192
193 (_, ty::ConstKind::Infer(ty::InferConst::Var(vid))) => {
194 infcx.instantiate_const_var_raw(relation, false, vid, a)?;
195 Ok(a)
196 }
197
198 (ty::ConstKind::Unevaluated(..), _) | (_, ty::ConstKind::Unevaluated(..))
199 if infcx.cx().features().generic_const_exprs() || infcx.next_trait_solver() =>
200 {
201 match relation.structurally_relate_aliases() {
202 StructurallyRelateAliases::No => {
203 relation.register_predicates([if infcx.next_trait_solver() {
204 ty::PredicateKind::AliasRelate(
205 a.into(),
206 b.into(),
207 ty::AliasRelationDirection::Equate,
208 )
209 } else {
210 ty::PredicateKind::ConstEquate(a, b)
211 }]);
212
213 Ok(b)
214 }
215 StructurallyRelateAliases::Yes => structurally_relate_consts(relation, a, b),
216 }
217 }
218 _ => structurally_relate_consts(relation, a, b),
219 }
220}