1use std::iter;
2
3use tracing::debug;
4
5use super::{
6 ExpectedFound, RelateResult, StructurallyRelateAliases, TypeRelation,
7 structurally_relate_consts, structurally_relate_tys,
8};
9use crate::error::TypeError;
10use crate::inherent::*;
11use crate::relate::VarianceDiagInfo;
12use crate::solve::Goal;
13use crate::visit::TypeVisitableExt as _;
14use crate::{self as ty, InferCtxtLike, Interner, TypingMode, Upcast};
15
16pub trait PredicateEmittingRelation<Infcx, I = <Infcx as InferCtxtLike>::Interner>:
17 TypeRelation<I>
18where
19 Infcx: InferCtxtLike<Interner = I>,
20 I: Interner,
21{
22 fn span(&self) -> I::Span;
23
24 fn param_env(&self) -> I::ParamEnv;
25
26 fn structurally_relate_aliases(&self) -> StructurallyRelateAliases;
30
31 fn register_goals(&mut self, obligations: impl IntoIterator<Item = Goal<I, I::Predicate>>);
33
34 fn register_predicates(
37 &mut self,
38 obligations: impl IntoIterator<Item: Upcast<I, I::Predicate>>,
39 );
40
41 fn register_alias_relate_predicate(&mut self, a: I::Ty, b: I::Ty);
43}
44
45pub fn super_combine_tys<Infcx, I, R>(
46 infcx: &Infcx,
47 relation: &mut R,
48 a: I::Ty,
49 b: I::Ty,
50) -> RelateResult<I, I::Ty>
51where
52 Infcx: InferCtxtLike<Interner = I>,
53 I: Interner,
54 R: PredicateEmittingRelation<Infcx>,
55{
56 {
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:56",
"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(56u32),
::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};
let mut iter = __CALLSITE.metadata().fields().iter();
__CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&format_args!("super_combine_tys::<{0}>({1:?}, {2:?})",
std::any::type_name::<R>(), a, b) as &dyn Value))])
});
} else { ; }
};debug!("super_combine_tys::<{}>({:?}, {:?})", std::any::type_name::<R>(), a, b);
57 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());
58 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());
59
60 match (a.kind(), b.kind()) {
61 (ty::Error(e), _) | (_, ty::Error(e)) => {
62 infcx.set_tainted_by_errors(e);
63 return Ok(Ty::new_error(infcx.cx(), e));
64 }
65
66 (ty::Infer(ty::IntVar(a_id)), ty::Infer(ty::IntVar(b_id))) => {
68 infcx.equate_int_vids_raw(a_id, b_id);
69 Ok(a)
70 }
71 (ty::Infer(ty::IntVar(v_id)), ty::Int(v)) => {
72 infcx.instantiate_int_var_raw(v_id, ty::IntVarValue::IntType(v));
73 Ok(b)
74 }
75 (ty::Int(v), ty::Infer(ty::IntVar(v_id))) => {
76 infcx.instantiate_int_var_raw(v_id, ty::IntVarValue::IntType(v));
77 Ok(a)
78 }
79 (ty::Infer(ty::IntVar(v_id)), ty::Uint(v)) => {
80 infcx.instantiate_int_var_raw(v_id, ty::IntVarValue::UintType(v));
81 Ok(b)
82 }
83 (ty::Uint(v), ty::Infer(ty::IntVar(v_id))) => {
84 infcx.instantiate_int_var_raw(v_id, ty::IntVarValue::UintType(v));
85 Ok(a)
86 }
87
88 (ty::Infer(ty::FloatVar(a_id)), ty::Infer(ty::FloatVar(b_id))) => {
90 infcx.equate_float_vids_raw(a_id, b_id);
91 Ok(a)
92 }
93 (ty::Infer(ty::FloatVar(v_id)), ty::Float(v)) => {
94 infcx.instantiate_float_var_raw(v_id, ty::FloatVarValue::Known(v));
95 Ok(b)
96 }
97 (ty::Float(v), ty::Infer(ty::FloatVar(v_id))) => {
98 infcx.instantiate_float_var_raw(v_id, ty::FloatVarValue::Known(v));
99 Ok(a)
100 }
101
102 (ty::Alias(..), ty::Infer(ty::TyVar(_))) | (ty::Infer(ty::TyVar(_)), ty::Alias(..))
104 if infcx.next_trait_solver() =>
105 {
106 {
::core::panicking::panic_fmt(format_args!("We do not expect to encounter `TyVar` this late in combine -- they should have been handled earlier"));
}panic!(
107 "We do not expect to encounter `TyVar` this late in combine \
108 -- they should have been handled earlier"
109 )
110 }
111 (_, ty::Infer(ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)))
112 | (ty::Infer(ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)), _)
113 if infcx.next_trait_solver() =>
114 {
115 {
::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")
116 }
117
118 (ty::Alias(is_rigid_a, _), ty::Alias(is_rigid_b, _)) if infcx.next_trait_solver() => {
119 match (is_rigid_a, is_rigid_b) {
120 (ty::IsRigid::Yes, ty::IsRigid::Yes) => structurally_relate_tys(relation, a, b),
121 _ => match relation.structurally_relate_aliases() {
122 StructurallyRelateAliases::Yes => structurally_relate_tys(relation, a, b),
123 StructurallyRelateAliases::No => {
124 relation.register_alias_relate_predicate(a, b);
125 Ok(a)
126 }
127 },
128 }
129 }
130
131 (other, ty::Alias(is_rigid, _)) | (ty::Alias(is_rigid, _), other)
132 if infcx.next_trait_solver() =>
133 {
134 if let StructurallyRelateAliases::No = relation.structurally_relate_aliases()
135 && is_rigid == ty::IsRigid::No
136 {
137 relation.register_alias_relate_predicate(a, b);
138 Ok(a)
139 } else {
140 match other {
141 ty::Infer(infer_ty) => match infer_ty {
142 ty::InferTy::IntVar(_) | ty::InferTy::FloatVar(_) => {
153 Err(TypeError::Sorts(ExpectedFound::new(a, b)))
154 }
155
156 ty::InferTy::TyVar(_)
157 | ty::InferTy::FreshTy(_)
158 | ty::InferTy::FreshIntTy(_)
159 | ty::InferTy::FreshFloatTy(_) => ::core::panicking::panic("internal error: entered unreachable code")unreachable!(),
160 },
161 _ => structurally_relate_tys(relation, a, b),
162 }
163 }
164 }
165
166 (ty::Infer(_), _) | (_, ty::Infer(_)) => Err(TypeError::Sorts(ExpectedFound::new(a, b))),
168
169 (ty::Alias(_, ty::AliasTy { kind: ty::Opaque { .. }, .. }), _)
170 | (_, ty::Alias(_, ty::AliasTy { kind: ty::Opaque { .. }, .. })) => {
171 if !!infcx.next_trait_solver() {
::core::panicking::panic("assertion failed: !infcx.next_trait_solver()")
};assert!(!infcx.next_trait_solver());
172 match infcx.typing_mode_raw().assert_not_erased() {
173 TypingMode::Coherence => {
178 relation.register_predicates([ty::Binder::dummy(ty::PredicateKind::Ambiguous)]);
179 Ok(a)
180 }
181 TypingMode::Typeck { .. }
182 | TypingMode::PostTypeckUntilBorrowck { .. }
183 | TypingMode::PostBorrowck { .. }
184 | TypingMode::PostAnalysis
185 | TypingMode::Codegen => structurally_relate_tys(relation, a, b),
186 }
187 }
188
189 _ => structurally_relate_tys(relation, a, b),
190 }
191}
192
193pub fn super_combine_consts<Infcx, I, R>(
194 infcx: &Infcx,
195 relation: &mut R,
196 a: I::Const,
197 b: I::Const,
198) -> RelateResult<I, I::Const>
199where
200 Infcx: InferCtxtLike<Interner = I>,
201 I: Interner,
202 R: PredicateEmittingRelation<Infcx>,
203{
204 {
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:204",
"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(204u32),
::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};
let mut iter = __CALLSITE.metadata().fields().iter();
__CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&format_args!("super_combine_consts::<{0}>({1:?}, {2:?})",
std::any::type_name::<R>(), a, b) as &dyn Value))])
});
} else { ; }
};debug!("super_combine_consts::<{}>({:?}, {:?})", std::any::type_name::<R>(), a, b);
205 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());
206 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());
207
208 if a == b {
209 return Ok(a);
210 }
211
212 let a = infcx.shallow_resolve_const(a);
213 let b = infcx.shallow_resolve_const(b);
214
215 match (a.kind(), b.kind()) {
216 (
217 ty::ConstKind::Infer(ty::InferConst::Var(a_vid)),
218 ty::ConstKind::Infer(ty::InferConst::Var(b_vid)),
219 ) => {
220 infcx.equate_const_vids_raw(a_vid, b_vid);
221 Ok(a)
222 }
223
224 (ty::ConstKind::Infer(ty::InferConst::Var(_)), ty::ConstKind::Infer(_))
226 | (ty::ConstKind::Infer(_), ty::ConstKind::Infer(ty::InferConst::Var(_))) => {
227 {
::core::panicking::panic_fmt(format_args!("tried to combine ConstKind::Infer/ConstKind::Infer(InferConst::Var): {0:?} and {1:?}",
a, b));
}panic!(
228 "tried to combine ConstKind::Infer/ConstKind::Infer(InferConst::Var): {a:?} and {b:?}"
229 )
230 }
231
232 (ty::ConstKind::Infer(ty::InferConst::Var(vid)), _) => {
233 infcx.instantiate_const_var_raw(relation, true, vid, b)?;
234 Ok(b)
235 }
236
237 (_, ty::ConstKind::Infer(ty::InferConst::Var(vid))) => {
238 infcx.instantiate_const_var_raw(relation, false, vid, a)?;
239 Ok(a)
240 }
241
242 (
243 ty::ConstKind::Unevaluated(ty::IsRigid::Yes, _),
244 ty::ConstKind::Unevaluated(ty::IsRigid::Yes, _),
245 ) if (infcx.cx().features().generic_const_exprs() || infcx.next_trait_solver()) => {
246 structurally_relate_consts(relation, a, b)
247 }
248
249 (ty::ConstKind::Unevaluated(..), _) | (_, ty::ConstKind::Unevaluated(..))
250 if infcx.cx().features().generic_const_exprs() || infcx.next_trait_solver() =>
251 {
252 match relation.structurally_relate_aliases() {
253 StructurallyRelateAliases::No => {
254 relation.register_predicates([if infcx.next_trait_solver() {
255 ty::PredicateKind::AliasRelate(
256 a.into(),
257 b.into(),
258 ty::AliasRelationDirection::Equate,
259 )
260 } else {
261 ty::PredicateKind::ConstEquate(a, b)
262 }]);
263
264 Ok(b)
265 }
266 StructurallyRelateAliases::Yes => structurally_relate_consts(relation, a, b),
267 }
268 }
269 _ => structurally_relate_consts(relation, a, b),
270 }
271}
272
273pub fn combine_ty_args<Infcx, I, R>(
274 infcx: &Infcx,
275 relation: &mut R,
276 a_ty: I::Ty,
277 b_ty: I::Ty,
278 variances: I::VariancesOf,
279 a_args: I::GenericArgs,
280 b_args: I::GenericArgs,
281 mk: impl FnOnce(I::GenericArgs) -> I::Ty,
282) -> RelateResult<I, I::Ty>
283where
284 Infcx: InferCtxtLike<Interner = I>,
285 I: Interner,
286 R: PredicateEmittingRelation<Infcx>,
287{
288 let cx = infcx.cx();
289 let mut has_unconstrained_bivariant_arg = false;
290 let args = iter::zip(a_args.iter(), b_args.iter()).enumerate().map(|(i, (a, b))| {
291 let variance = variances.get(i).unwrap();
292 let variance_info = match variance {
293 ty::Invariant => {
294 VarianceDiagInfo::Invariant { ty: a_ty, param_index: i.try_into().unwrap() }
295 }
296 ty::Covariant | ty::Contravariant => VarianceDiagInfo::default(),
297 ty::Bivariant => {
298 let has_non_region_infer = |arg: I::GenericArg| {
299 arg.has_non_region_infer()
300 && infcx.resolve_vars_if_possible(arg).has_non_region_infer()
301 };
302 if has_non_region_infer(a) || has_non_region_infer(b) {
303 has_unconstrained_bivariant_arg = true;
304 }
305 VarianceDiagInfo::default()
306 }
307 };
308 relation.relate_with_variance(variance, variance_info, a, b)
309 });
310 let args = cx.mk_args_from_iter(args)?;
311
312 if has_unconstrained_bivariant_arg {
336 relation.register_predicates([
337 ty::ClauseKind::WellFormed(a_ty.into()),
338 ty::ClauseKind::WellFormed(b_ty.into()),
339 ]);
340 }
341
342 if a_args == args { Ok(a_ty) } else { Ok(mk(args)) }
343}