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 ambient_variance(&self) -> ty::Variance;
42}
43
44pub fn super_combine_tys<Infcx, I, R>(
45 infcx: &Infcx,
46 relation: &mut R,
47 a: I::Ty,
48 b: I::Ty,
49) -> RelateResult<I, I::Ty>
50where
51 Infcx: InferCtxtLike<Interner = I>,
52 I: Interner,
53 R: PredicateEmittingRelation<Infcx>,
54{
55 {
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:55",
"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(55u32),
::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);
56 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());
57 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());
58
59 match (a.kind(), b.kind()) {
60 (ty::Error(e), _) | (_, ty::Error(e)) => {
61 infcx.set_tainted_by_errors(e);
62 return Ok(Ty::new_error(infcx.cx(), e));
63 }
64
65 (ty::Infer(ty::IntVar(a_id)), ty::Infer(ty::IntVar(b_id))) => {
67 infcx.equate_int_vids_raw(a_id, b_id);
68 Ok(a)
69 }
70 (ty::Infer(ty::IntVar(v_id)), ty::Int(v)) => {
71 infcx.instantiate_int_var_raw(v_id, ty::IntVarValue::IntType(v));
72 Ok(b)
73 }
74 (ty::Int(v), ty::Infer(ty::IntVar(v_id))) => {
75 infcx.instantiate_int_var_raw(v_id, ty::IntVarValue::IntType(v));
76 Ok(a)
77 }
78 (ty::Infer(ty::IntVar(v_id)), ty::Uint(v)) => {
79 infcx.instantiate_int_var_raw(v_id, ty::IntVarValue::UintType(v));
80 Ok(b)
81 }
82 (ty::Uint(v), ty::Infer(ty::IntVar(v_id))) => {
83 infcx.instantiate_int_var_raw(v_id, ty::IntVarValue::UintType(v));
84 Ok(a)
85 }
86
87 (ty::Infer(ty::FloatVar(a_id)), ty::Infer(ty::FloatVar(b_id))) => {
89 infcx.equate_float_vids_raw(a_id, b_id);
90 Ok(a)
91 }
92 (ty::Infer(ty::FloatVar(v_id)), ty::Float(v)) => {
93 infcx.instantiate_float_var_raw(v_id, ty::FloatVarValue::Known(v));
94 Ok(b)
95 }
96 (ty::Float(v), ty::Infer(ty::FloatVar(v_id))) => {
97 infcx.instantiate_float_var_raw(v_id, ty::FloatVarValue::Known(v));
98 Ok(a)
99 }
100
101 (ty::Alias(..), ty::Infer(ty::TyVar(_))) | (ty::Infer(ty::TyVar(_)), ty::Alias(..))
103 if infcx.next_trait_solver() =>
104 {
105 {
::core::panicking::panic_fmt(format_args!("We do not expect to encounter `TyVar` this late in combine -- they should have been handled earlier"));
}panic!(
106 "We do not expect to encounter `TyVar` this late in combine \
107 -- they should have been handled earlier"
108 )
109 }
110 (_, ty::Infer(ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)))
111 | (ty::Infer(ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)), _)
112 if infcx.next_trait_solver() =>
113 {
114 {
::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")
115 }
116
117 (ty::Alias(ty::IsRigid::No, alias), _) | (_, ty::Alias(ty::IsRigid::No, alias))
118 if infcx.next_trait_solver()
119 && let StructurallyRelateAliases::No = relation.structurally_relate_aliases() =>
120 {
121 let terms_are_inverted = !#[allow(non_exhaustive_omitted_patterns)] match a.kind() {
ty::Alias(ty::IsRigid::No, _) => true,
_ => false,
}matches!(a.kind(), ty::Alias(ty::IsRigid::No, _));
123 let other = if terms_are_inverted { a } else { b };
124 match (relation.ambient_variance(), terms_are_inverted) {
125 (ty::Invariant, _) => relation.register_predicates([ty::ProjectionPredicate {
126 projection_term: alias.into(),
127 term: other.into(),
128 }]),
129 (ty::Covariant, false) | (ty::Contravariant, true) => {
130 let new_var = infcx.next_ty_infer();
133 relation.register_predicates([
134 ty::PredicateKind::Clause(ty::ClauseKind::Projection(
135 ty::ProjectionPredicate {
136 projection_term: alias.into(),
137 term: new_var.into(),
138 },
139 )),
140 ty::PredicateKind::Subtype(ty::SubtypePredicate {
141 a_is_expected: !terms_are_inverted,
142 a: new_var,
143 b: other,
144 }),
145 ]);
146 }
147 (ty::Contravariant, false) | (ty::Covariant, true) => {
148 let new_var = infcx.next_ty_infer();
150 relation.register_predicates([
151 ty::PredicateKind::Clause(ty::ClauseKind::Projection(
152 ty::ProjectionPredicate {
153 projection_term: alias.into(),
154 term: new_var.into(),
155 },
156 )),
157 ty::PredicateKind::Subtype(ty::SubtypePredicate {
158 a_is_expected: terms_are_inverted,
159 a: other,
160 b: new_var,
161 }),
162 ]);
163 }
164 (ty::Bivariant, _) => {
165 {
::core::panicking::panic_fmt(format_args!("internal error: entered unreachable code: {0}",
format_args!("cannot handle bivariant aliases in register_projection_with_variance")));
}unreachable!(
166 "cannot handle bivariant aliases in register_projection_with_variance"
167 )
168 }
169 }
170 Ok(a)
171 }
172
173 (ty::Infer(_), _) | (_, ty::Infer(_)) => Err(TypeError::Sorts(ExpectedFound::new(a, b))),
175
176 (ty::Alias(_, ty::AliasTy { kind: ty::Opaque { .. }, .. }), _)
177 | (_, ty::Alias(_, ty::AliasTy { kind: ty::Opaque { .. }, .. }))
178 if !infcx.next_trait_solver() =>
179 {
180 match infcx.typing_mode_raw().assert_not_erased() {
181 TypingMode::Coherence => {
186 relation.register_predicates([ty::Binder::dummy(ty::PredicateKind::Ambiguous)]);
187 Ok(a)
188 }
189 TypingMode::Typeck { .. }
190 | TypingMode::PostTypeckUntilBorrowck { .. }
191 | TypingMode::PostBorrowck { .. }
192 | TypingMode::PostAnalysis
193 | TypingMode::Codegen => structurally_relate_tys(relation, a, b),
194 }
195 }
196
197 _ => structurally_relate_tys(relation, a, b),
198 }
199}
200
201pub fn super_combine_consts<Infcx, I, R>(
202 infcx: &Infcx,
203 relation: &mut R,
204 a: I::Const,
205 b: I::Const,
206) -> RelateResult<I, I::Const>
207where
208 Infcx: InferCtxtLike<Interner = I>,
209 I: Interner,
210 R: PredicateEmittingRelation<Infcx>,
211{
212 {
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:212",
"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(212u32),
::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);
213 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());
214 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());
215
216 if a == b {
217 return Ok(a);
218 }
219
220 let a = infcx.shallow_resolve_const(a);
221 let b = infcx.shallow_resolve_const(b);
222
223 match (a.kind(), b.kind()) {
224 (
225 ty::ConstKind::Infer(ty::InferConst::Var(a_vid)),
226 ty::ConstKind::Infer(ty::InferConst::Var(b_vid)),
227 ) => {
228 infcx.equate_const_vids_raw(a_vid, b_vid);
229 Ok(a)
230 }
231
232 (ty::ConstKind::Infer(ty::InferConst::Var(_)), ty::ConstKind::Infer(_))
234 | (ty::ConstKind::Infer(_), ty::ConstKind::Infer(ty::InferConst::Var(_))) => {
235 {
::core::panicking::panic_fmt(format_args!("tried to combine ConstKind::Infer/ConstKind::Infer(InferConst::Var): {0:?} and {1:?}",
a, b));
}panic!(
236 "tried to combine ConstKind::Infer/ConstKind::Infer(InferConst::Var): {a:?} and {b:?}"
237 )
238 }
239
240 (ty::ConstKind::Infer(ty::InferConst::Var(vid)), _) => {
241 infcx.instantiate_const_var_raw(relation, true, vid, b)?;
242 Ok(b)
243 }
244
245 (_, ty::ConstKind::Infer(ty::InferConst::Var(vid))) => {
246 infcx.instantiate_const_var_raw(relation, false, vid, a)?;
247 Ok(a)
248 }
249
250 (ty::ConstKind::Alias(ty::IsRigid::No, alias), _)
251 | (_, ty::ConstKind::Alias(ty::IsRigid::No, alias))
252 if (infcx.cx().features().generic_const_exprs() || infcx.next_trait_solver())
253 && let StructurallyRelateAliases::No = relation.structurally_relate_aliases() =>
254 {
255 if infcx.next_trait_solver() {
256 let other = if #[allow(non_exhaustive_omitted_patterns)] match a.kind() {
ty::ConstKind::Alias(..) => true,
_ => false,
}matches!(a.kind(), ty::ConstKind::Alias(..)) { b } else { a };
257 relation.register_predicates([ty::ProjectionPredicate {
258 projection_term: alias.into(),
259 term: other.into(),
260 }])
261 } else {
262 relation.register_predicates([ty::PredicateKind::ConstEquate(a, b)]);
263 }
264
265 Ok(b)
266 }
267
268 _ => structurally_relate_consts(relation, a, b),
269 }
270}
271
272pub fn combine_ty_args<Infcx, I, R>(
273 infcx: &Infcx,
274 relation: &mut R,
275 a_ty: I::Ty,
276 b_ty: I::Ty,
277 variances: I::VariancesOf,
278 a_args: I::GenericArgs,
279 b_args: I::GenericArgs,
280 mk: impl FnOnce(I::GenericArgs) -> I::Ty,
281) -> RelateResult<I, I::Ty>
282where
283 Infcx: InferCtxtLike<Interner = I>,
284 I: Interner,
285 R: PredicateEmittingRelation<Infcx>,
286{
287 let cx = infcx.cx();
288 let mut has_unconstrained_bivariant_arg = false;
289 let args = iter::zip(a_args.iter(), b_args.iter()).enumerate().map(|(i, (a, b))| {
290 let variance = variances.get(i).unwrap();
291 let variance_info = match variance {
292 ty::Invariant => {
293 VarianceDiagInfo::Invariant { ty: a_ty, param_index: i.try_into().unwrap() }
294 }
295 ty::Covariant | ty::Contravariant => VarianceDiagInfo::default(),
296 ty::Bivariant => {
297 let has_non_region_infer = |arg: I::GenericArg| {
298 arg.has_non_region_infer()
299 && infcx.resolve_vars_if_possible(arg).has_non_region_infer()
300 };
301 if has_non_region_infer(a) || has_non_region_infer(b) {
302 has_unconstrained_bivariant_arg = true;
303 }
304 VarianceDiagInfo::default()
305 }
306 };
307 relation.relate_with_variance(variance, variance_info, a, b)
308 });
309 let args = cx.mk_args_from_iter(args)?;
310
311 if has_unconstrained_bivariant_arg {
335 relation.register_predicates([
336 ty::ClauseKind::WellFormed(a_ty.into()),
337 ty::ClauseKind::WellFormed(b_ty.into()),
338 ]);
339 }
340
341 if a_args == args { Ok(a_ty) } else { Ok(mk(args)) }
342}