1use std::iter;
2
3use tracing::debug;
4
5use super::{
6 ExpectedFound, RelateResult, TypeRelation, structurally_relate_consts, structurally_relate_tys,
7};
8use crate::error::TypeError;
9use crate::inherent::*;
10use crate::relate::VarianceDiagInfo;
11use crate::solve::Goal;
12use crate::visit::TypeVisitableExt as _;
13use crate::{self as ty, InferCtxtLike, Interner, TypingMode, Upcast};
14
15pub trait PredicateEmittingRelation<Infcx, I = <Infcx as InferCtxtLike>::Interner>:
16 TypeRelation<I>
17where
18 Infcx: InferCtxtLike<Interner = I>,
19 I: Interner,
20{
21 fn span(&self) -> I::Span;
22
23 fn param_env(&self) -> I::ParamEnv;
24
25 fn register_goals(&mut self, obligations: impl IntoIterator<Item = Goal<I, I::Predicate>>);
27
28 fn register_predicates(
31 &mut self,
32 obligations: impl IntoIterator<Item: Upcast<I, I::Predicate>>,
33 );
34}
35
36pub fn super_combine_tys<Infcx, I, R>(
37 infcx: &Infcx,
38 relation: &mut R,
39 a: I::Ty,
40 b: I::Ty,
41) -> RelateResult<I, I::Ty>
42where
43 Infcx: InferCtxtLike<Interner = I>,
44 I: Interner,
45 R: PredicateEmittingRelation<Infcx>,
46{
47 {
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event compiler/rustc_type_ir/src/relate/combine.rs:47",
"rustc_type_ir::relate::combine", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_type_ir/src/relate/combine.rs"),
::tracing_core::__macro_support::Option::Some(47u32),
::tracing_core::__macro_support::Option::Some("rustc_type_ir::relate::combine"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("super_combine_tys::<{0}>({1:?}, {2:?})",
std::any::type_name::<R>(), a, b) as
&dyn ::tracing::field::Value))])
});
} else { ; }
};debug!("super_combine_tys::<{}>({:?}, {:?})", std::any::type_name::<R>(), a, b);
48 if true {
if !!a.has_escaping_bound_vars() {
::core::panicking::panic("assertion failed: !a.has_escaping_bound_vars()")
};
};debug_assert!(!a.has_escaping_bound_vars());
49 if true {
if !!b.has_escaping_bound_vars() {
::core::panicking::panic("assertion failed: !b.has_escaping_bound_vars()")
};
};debug_assert!(!b.has_escaping_bound_vars());
50
51 match (a.kind(), b.kind()) {
52 (ty::Error(e), _) | (_, ty::Error(e)) => {
53 infcx.set_tainted_by_errors(e);
54 return Ok(Ty::new_error(infcx.cx(), e));
55 }
56
57 (ty::Infer(ty::IntVar(a_id)), ty::Infer(ty::IntVar(b_id))) => {
59 infcx.equate_int_vids_raw(a_id, b_id);
60 Ok(a)
61 }
62 (ty::Infer(ty::IntVar(v_id)), ty::Int(v)) => {
63 infcx.instantiate_int_var_raw(v_id, ty::IntVarValue::IntType(v));
64 Ok(b)
65 }
66 (ty::Int(v), ty::Infer(ty::IntVar(v_id))) => {
67 infcx.instantiate_int_var_raw(v_id, ty::IntVarValue::IntType(v));
68 Ok(a)
69 }
70 (ty::Infer(ty::IntVar(v_id)), ty::Uint(v)) => {
71 infcx.instantiate_int_var_raw(v_id, ty::IntVarValue::UintType(v));
72 Ok(b)
73 }
74 (ty::Uint(v), ty::Infer(ty::IntVar(v_id))) => {
75 infcx.instantiate_int_var_raw(v_id, ty::IntVarValue::UintType(v));
76 Ok(a)
77 }
78
79 (ty::Infer(ty::FloatVar(a_id)), ty::Infer(ty::FloatVar(b_id))) => {
81 infcx.equate_float_vids_raw(a_id, b_id);
82 Ok(a)
83 }
84 (ty::Infer(ty::FloatVar(v_id)), ty::Float(v)) => {
85 infcx.instantiate_float_var_raw(v_id, ty::FloatVarValue::Known(v));
86 Ok(b)
87 }
88 (ty::Float(v), ty::Infer(ty::FloatVar(v_id))) => {
89 infcx.instantiate_float_var_raw(v_id, ty::FloatVarValue::Known(v));
90 Ok(a)
91 }
92
93 (ty::Alias(..), ty::Infer(ty::TyVar(_))) | (ty::Infer(ty::TyVar(_)), ty::Alias(..))
95 if infcx.next_trait_solver() =>
96 {
97 {
::core::panicking::panic_fmt(format_args!("We do not expect to encounter `TyVar` this late in combine -- they should have been handled earlier"));
}panic!(
98 "We do not expect to encounter `TyVar` this late in combine \
99 -- they should have been handled earlier"
100 )
101 }
102 (_, ty::Infer(ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)))
103 | (ty::Infer(ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)), _)
104 if infcx.next_trait_solver() =>
105 {
106 {
::core::panicking::panic_fmt(format_args!("We do not expect to encounter `Fresh` variables in the new solver"));
}panic!("We do not expect to encounter `Fresh` variables in the new solver")
107 }
108 (ty::Alias(ty::IsRigid::No, _), _) | (_, ty::Alias(ty::IsRigid::No, _))
109 if infcx.next_trait_solver() =>
110 {
111 {
::core::panicking::panic_fmt(format_args!("non-rigid aliases should be handled in the caller of super_combine_tys"));
}panic!("non-rigid aliases should be handled in the caller of super_combine_tys")
112 }
113
114 (ty::Infer(_), _) | (_, ty::Infer(_)) => Err(TypeError::Sorts(ExpectedFound::new(a, b))),
116
117 (ty::Alias(_, ty::AliasTy { kind: ty::Opaque { .. }, .. }), _)
118 | (_, ty::Alias(_, ty::AliasTy { kind: ty::Opaque { .. }, .. }))
119 if !infcx.next_trait_solver() =>
120 {
121 match infcx.typing_mode_raw().assert_not_erased() {
122 TypingMode::Coherence => {
127 relation.register_predicates([ty::Binder::dummy(ty::PredicateKind::Ambiguous)]);
128 Ok(a)
129 }
130 TypingMode::Typeck { .. }
131 | TypingMode::Reflection
132 | TypingMode::PostTypeckUntilBorrowck { .. }
133 | TypingMode::PostBorrowck { .. }
134 | TypingMode::PostAnalysis
135 | TypingMode::Codegen => structurally_relate_tys(relation, a, b),
136 }
137 }
138
139 _ => structurally_relate_tys(relation, a, b),
140 }
141}
142
143pub fn super_combine_consts<Infcx, I, R>(
144 infcx: &Infcx,
145 relation: &mut R,
146 a: I::Const,
147 b: I::Const,
148) -> RelateResult<I, I::Const>
149where
150 Infcx: InferCtxtLike<Interner = I>,
151 I: Interner,
152 R: PredicateEmittingRelation<Infcx>,
153{
154 {
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event compiler/rustc_type_ir/src/relate/combine.rs:154",
"rustc_type_ir::relate::combine", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_type_ir/src/relate/combine.rs"),
::tracing_core::__macro_support::Option::Some(154u32),
::tracing_core::__macro_support::Option::Some("rustc_type_ir::relate::combine"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("super_combine_consts::<{0}>({1:?}, {2:?})",
std::any::type_name::<R>(), a, b) as
&dyn ::tracing::field::Value))])
});
} else { ; }
};debug!("super_combine_consts::<{}>({:?}, {:?})", std::any::type_name::<R>(), a, b);
155 if true {
if !!a.has_escaping_bound_vars() {
::core::panicking::panic("assertion failed: !a.has_escaping_bound_vars()")
};
};debug_assert!(!a.has_escaping_bound_vars());
156 if true {
if !!b.has_escaping_bound_vars() {
::core::panicking::panic("assertion failed: !b.has_escaping_bound_vars()")
};
};debug_assert!(!b.has_escaping_bound_vars());
157
158 if a == b {
159 return Ok(a);
160 }
161
162 let a = infcx.shallow_resolve_const(a);
163 let b = infcx.shallow_resolve_const(b);
164
165 match (a.kind(), b.kind()) {
166 (
167 ty::ConstKind::Infer(ty::InferConst::Var(a_vid)),
168 ty::ConstKind::Infer(ty::InferConst::Var(b_vid)),
169 ) => {
170 infcx.equate_const_vids_raw(a_vid, b_vid);
171 Ok(a)
172 }
173
174 (ty::ConstKind::Infer(ty::InferConst::Var(_)), ty::ConstKind::Infer(_))
176 | (ty::ConstKind::Infer(_), ty::ConstKind::Infer(ty::InferConst::Var(_))) => {
177 {
::core::panicking::panic_fmt(format_args!("tried to combine ConstKind::Infer/ConstKind::Infer(InferConst::Var): {0:?} and {1:?}",
a, b));
}panic!(
178 "tried to combine ConstKind::Infer/ConstKind::Infer(InferConst::Var): {a:?} and {b:?}"
179 )
180 }
181
182 (ty::ConstKind::Alias(ty::IsRigid::No, alias), _) if infcx.next_trait_solver() => {
183 relation.register_predicates([ty::ProjectionPredicate {
184 projection_term: alias.into(),
185 term: b.into(),
186 }]);
187 Ok(b)
188 }
189 (_, ty::ConstKind::Alias(ty::IsRigid::No, alias)) if infcx.next_trait_solver() => {
190 relation.register_predicates([ty::ProjectionPredicate {
191 projection_term: alias.into(),
192 term: a.into(),
193 }]);
194 Ok(b)
195 }
196
197 (ty::ConstKind::Infer(ty::InferConst::Var(vid)), _) => {
198 infcx.instantiate_const_var(relation, true, vid, b)?;
199 Ok(b)
200 }
201
202 (_, ty::ConstKind::Infer(ty::InferConst::Var(vid))) => {
203 infcx.instantiate_const_var(relation, false, vid, a)?;
204 Ok(a)
205 }
206
207 (ty::ConstKind::Alias(ty::IsRigid::No, _), _)
208 | (_, ty::ConstKind::Alias(ty::IsRigid::No, _))
209 if infcx.cx().features().generic_const_exprs() =>
210 {
211 relation.register_predicates([ty::PredicateKind::ConstEquate(a, b)]);
212 Ok(b)
213 }
214
215 _ => structurally_relate_consts(relation, a, b),
216 }
217}
218
219pub fn combine_ty_args<Infcx, I, R>(
220 infcx: &Infcx,
221 relation: &mut R,
222 a_ty: I::Ty,
223 b_ty: I::Ty,
224 variances: I::VariancesOf,
225 a_args: I::GenericArgs,
226 b_args: I::GenericArgs,
227 mk: impl FnOnce(I::GenericArgs) -> I::Ty,
228) -> RelateResult<I, I::Ty>
229where
230 Infcx: InferCtxtLike<Interner = I>,
231 I: Interner,
232 R: PredicateEmittingRelation<Infcx>,
233{
234 let cx = infcx.cx();
235 let mut has_unconstrained_bivariant_arg = false;
236 let args = iter::zip(a_args.iter(), b_args.iter()).enumerate().map(|(i, (a, b))| {
237 let variance = variances.get(i).unwrap();
238 let variance_info = match variance {
239 ty::Invariant => {
240 VarianceDiagInfo::Invariant { ty: a_ty, param_index: i.try_into().unwrap() }
241 }
242 ty::Covariant | ty::Contravariant => VarianceDiagInfo::default(),
243 ty::Bivariant => {
244 let has_non_region_infer = |arg: I::GenericArg| {
245 arg.has_non_region_infer()
246 && infcx.resolve_vars_if_possible(arg).has_non_region_infer()
247 };
248 if has_non_region_infer(a) || has_non_region_infer(b) {
249 has_unconstrained_bivariant_arg = true;
250 }
251 VarianceDiagInfo::default()
252 }
253 };
254 relation.relate_with_variance(variance, variance_info, a, b)
255 });
256 let args = cx.mk_args_from_iter(args)?;
257
258 if has_unconstrained_bivariant_arg {
282 relation.register_predicates([
283 ty::ClauseKind::WellFormed(a_ty.into()),
284 ty::ClauseKind::WellFormed(b_ty.into()),
285 ]);
286 }
287
288 if a_args == args { Ok(a_ty) } else { Ok(mk(args)) }
289}