1use tracing::{debug, instrument};
2
3use self::combine::{PredicateEmittingRelation, super_combine_consts, super_combine_tys};
4use crate::data_structures::DelayedSet;
5use crate::relate::combine::combine_ty_args;
6pub use crate::relate::*;
7use crate::solve::{Goal, VisibleForLeakCheck};
8use crate::{self as ty, InferCtxtLike, Interner, Region};
9
10pub trait RelateExt: InferCtxtLike {
11 fn relate<T: Relate<Self::Interner>>(
12 &self,
13 param_env: <Self::Interner as Interner>::ParamEnv,
14 lhs: T,
15 variance: ty::Variance,
16 rhs: T,
17 span: <Self::Interner as Interner>::Span,
18 ) -> Result<
19 Vec<Goal<Self::Interner, <Self::Interner as Interner>::Predicate>>,
20 TypeError<Self::Interner>,
21 >;
22}
23
24impl<Infcx: InferCtxtLike> RelateExt for Infcx {
25 fn relate<T: Relate<Self::Interner>>(
26 &self,
27 param_env: <Self::Interner as Interner>::ParamEnv,
28 lhs: T,
29 variance: ty::Variance,
30 rhs: T,
31 span: <Self::Interner as Interner>::Span,
32 ) -> Result<
33 Vec<Goal<Self::Interner, <Self::Interner as Interner>::Predicate>>,
34 TypeError<Self::Interner>,
35 > {
36 let mut relate = SolverRelating::new(self, variance, param_env, span);
37 relate.relate(lhs, rhs)?;
38 Ok(relate.goals)
39 }
40}
41
42pub struct SolverRelating<'infcx, Infcx, I: Interner> {
44 infcx: &'infcx Infcx,
45 param_env: I::ParamEnv,
47 span: I::Span,
48 ambient_variance: ty::Variance,
50 goals: Vec<Goal<I, I::Predicate>>,
51 cache: DelayedSet<(ty::Variance, I::Ty, I::Ty)>,
74}
75
76impl<'infcx, Infcx, I> SolverRelating<'infcx, Infcx, I>
77where
78 Infcx: InferCtxtLike<Interner = I>,
79 I: Interner,
80{
81 pub fn new(
82 infcx: &'infcx Infcx,
83 ambient_variance: ty::Variance,
84 param_env: I::ParamEnv,
85 span: I::Span,
86 ) -> Self {
87 SolverRelating {
88 infcx,
89 span,
90 ambient_variance,
91 param_env,
92 goals: ::alloc::vec::Vec::new()vec![],
93 cache: Default::default(),
94 }
95 }
96}
97
98impl<Infcx, I> TypeRelation<I> for SolverRelating<'_, Infcx, I>
99where
100 Infcx: InferCtxtLike<Interner = I>,
101 I: Interner,
102{
103 fn cx(&self) -> I {
104 self.infcx.cx()
105 }
106
107 fn relate_ty_args(
108 &mut self,
109 a_ty: I::Ty,
110 b_ty: I::Ty,
111 def_id: I::DefId,
112 a_args: I::GenericArgs,
113 b_args: I::GenericArgs,
114 _: impl FnOnce(I::GenericArgs) -> I::Ty,
115 ) -> RelateResult<I, I::Ty> {
116 if self.ambient_variance == ty::Invariant {
117 relate_args_invariantly(self, a_args, b_args)?;
121 Ok(a_ty)
122 } else {
123 let variances = self.cx().variances_of(def_id);
124 combine_ty_args(self.infcx, self, a_ty, b_ty, variances, a_args, b_args, |_| a_ty)
125 }
126 }
127 fn relate_with_variance<T: Relate<I>>(
128 &mut self,
129 variance: ty::Variance,
130 _info: VarianceDiagInfo<I>,
131 a: T,
132 b: T,
133 ) -> RelateResult<I, T> {
134 let old_ambient_variance = self.ambient_variance;
135 self.ambient_variance = self.ambient_variance.xform(variance);
136 {
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/solver_relating.rs:136",
"rustc_type_ir::relate::solver_relating",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_type_ir/src/relate/solver_relating.rs"),
::tracing_core::__macro_support::Option::Some(136u32),
::tracing_core::__macro_support::Option::Some("rustc_type_ir::relate::solver_relating"),
::tracing_core::field::FieldSet::new(&["message",
{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("self.ambient_variance")
}> =
::tracing::__macro_support::FieldName::new("self.ambient_variance");
NAME.as_str()
}], ::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!("new ambient variance")
as &dyn ::tracing::field::Value)),
(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&self.ambient_variance)
as &dyn ::tracing::field::Value))])
});
} else { ; }
};debug!(?self.ambient_variance, "new ambient variance");
137
138 let r = if self.ambient_variance == ty::Bivariant { Ok(a) } else { self.relate(a, b) };
139
140 self.ambient_variance = old_ambient_variance;
141 r
142 }
143
144 #[allow(clippy :: suspicious_else_formatting)]
{
let __tracing_attr_span;
let __tracing_attr_guard;
if ::tracing::Level::TRACE <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() ||
{ false } {
__tracing_attr_span =
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("tys",
"rustc_type_ir::relate::solver_relating",
::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("compiler/rustc_type_ir/src/relate/solver_relating.rs"),
::tracing_core::__macro_support::Option::Some(144u32),
::tracing_core::__macro_support::Option::Some("rustc_type_ir::relate::solver_relating"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("a")
}> =
::tracing::__macro_support::FieldName::new("a");
NAME.as_str()
},
{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("b")
}> =
::tracing::__macro_support::FieldName::new("b");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::SPAN)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let mut interest = ::tracing::subscriber::Interest::never();
if ::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() &&
{ interest = __CALLSITE.interest(); !interest.is_never() }
&&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest) {
let meta = __CALLSITE.metadata();
::tracing::Span::new(meta,
&{
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
meta.fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&a)
as &dyn ::tracing::field::Value)),
(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&b)
as &dyn ::tracing::field::Value))])
})
} else {
let span =
::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
{};
span
}
};
__tracing_attr_guard = __tracing_attr_span.enter();
}
#[warn(clippy :: suspicious_else_formatting)]
{
#[allow(unknown_lints, unreachable_code, clippy ::
diverging_sub_expression, clippy :: empty_loop, clippy ::
let_unit_value, clippy :: let_with_type_underscore, clippy ::
needless_return, clippy :: unreachable)]
if false {
let __tracing_attr_fake_return: RelateResult<I, I::Ty> = loop {};
return __tracing_attr_fake_return;
}
{
if a == b { return Ok(a); }
let infcx = self.infcx;
let a = infcx.shallow_resolve(a);
let b = infcx.shallow_resolve(b);
if self.cache.contains(&(self.ambient_variance, a, b)) {
return Ok(a);
}
match (a.kind(), b.kind()) {
(ty::Infer(ty::TyVar(a_id)), ty::Infer(ty::TyVar(b_id))) => {
match self.ambient_variance {
ty::Covariant => {
self.goals.push(Goal::new(self.cx(), self.param_env,
ty::Binder::dummy(ty::PredicateKind::Subtype(ty::SubtypePredicate {
a_is_expected: true,
a,
b,
}))));
}
ty::Contravariant => {
self.goals.push(Goal::new(self.cx(), self.param_env,
ty::Binder::dummy(ty::PredicateKind::Subtype(ty::SubtypePredicate {
a_is_expected: false,
a: b,
b: a,
}))));
}
ty::Invariant => { infcx.equate_ty_vids_raw(a_id, b_id); }
ty::Bivariant => {
{
::core::panicking::panic_fmt(format_args!("internal error: entered unreachable code: {0}",
format_args!("Expected bivariance to be handled in relate_with_variance")));
}
}
}
}
(ty::Infer(ty::TyVar(a_vid)), _) => {
infcx.instantiate_ty_var(self, true, a_vid,
self.ambient_variance, b)?;
}
(_, ty::Infer(ty::TyVar(b_vid))) => {
infcx.instantiate_ty_var(self, false, b_vid,
self.ambient_variance.xform(ty::Contravariant), a)?;
}
_ => { super_combine_tys(self.infcx, self, a, b)?; }
}
if !self.cache.insert((self.ambient_variance, a, b)) {
::core::panicking::panic("assertion failed: self.cache.insert((self.ambient_variance, a, b))")
};
Ok(a)
}
}
}#[instrument(skip(self), level = "trace")]
145 fn tys(&mut self, a: I::Ty, b: I::Ty) -> RelateResult<I, I::Ty> {
146 if a == b {
147 return Ok(a);
148 }
149
150 let infcx = self.infcx;
151 let a = infcx.shallow_resolve(a);
152 let b = infcx.shallow_resolve(b);
153
154 if self.cache.contains(&(self.ambient_variance, a, b)) {
155 return Ok(a);
156 }
157
158 match (a.kind(), b.kind()) {
159 (ty::Infer(ty::TyVar(a_id)), ty::Infer(ty::TyVar(b_id))) => {
160 match self.ambient_variance {
161 ty::Covariant => {
162 self.goals.push(Goal::new(
165 self.cx(),
166 self.param_env,
167 ty::Binder::dummy(ty::PredicateKind::Subtype(ty::SubtypePredicate {
168 a_is_expected: true,
169 a,
170 b,
171 })),
172 ));
173 }
174 ty::Contravariant => {
175 self.goals.push(Goal::new(
178 self.cx(),
179 self.param_env,
180 ty::Binder::dummy(ty::PredicateKind::Subtype(ty::SubtypePredicate {
181 a_is_expected: false,
182 a: b,
183 b: a,
184 })),
185 ));
186 }
187 ty::Invariant => {
188 infcx.equate_ty_vids_raw(a_id, b_id);
189 }
190 ty::Bivariant => {
191 unreachable!("Expected bivariance to be handled in relate_with_variance")
192 }
193 }
194 }
195
196 (ty::Infer(ty::TyVar(a_vid)), _) => {
197 infcx.instantiate_ty_var(self, true, a_vid, self.ambient_variance, b)?;
198 }
199 (_, ty::Infer(ty::TyVar(b_vid))) => {
200 infcx.instantiate_ty_var(
201 self,
202 false,
203 b_vid,
204 self.ambient_variance.xform(ty::Contravariant),
205 a,
206 )?;
207 }
208
209 _ => {
210 super_combine_tys(self.infcx, self, a, b)?;
211 }
212 }
213
214 assert!(self.cache.insert((self.ambient_variance, a, b)));
215
216 Ok(a)
217 }
218
219 #[allow(clippy :: suspicious_else_formatting)]
{
let __tracing_attr_span;
let __tracing_attr_guard;
if ::tracing::Level::TRACE <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() ||
{ false } {
__tracing_attr_span =
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("regions",
"rustc_type_ir::relate::solver_relating",
::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("compiler/rustc_type_ir/src/relate/solver_relating.rs"),
::tracing_core::__macro_support::Option::Some(219u32),
::tracing_core::__macro_support::Option::Some("rustc_type_ir::relate::solver_relating"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("a")
}> =
::tracing::__macro_support::FieldName::new("a");
NAME.as_str()
},
{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("b")
}> =
::tracing::__macro_support::FieldName::new("b");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::SPAN)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let mut interest = ::tracing::subscriber::Interest::never();
if ::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() &&
{ interest = __CALLSITE.interest(); !interest.is_never() }
&&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest) {
let meta = __CALLSITE.metadata();
::tracing::Span::new(meta,
&{
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
meta.fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&a)
as &dyn ::tracing::field::Value)),
(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&b)
as &dyn ::tracing::field::Value))])
})
} else {
let span =
::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
{};
span
}
};
__tracing_attr_guard = __tracing_attr_span.enter();
}
#[warn(clippy :: suspicious_else_formatting)]
{
#[allow(unknown_lints, unreachable_code, clippy ::
diverging_sub_expression, clippy :: empty_loop, clippy ::
let_unit_value, clippy :: let_with_type_underscore, clippy ::
needless_return, clippy :: unreachable)]
if false {
let __tracing_attr_fake_return: RelateResult<I, Region<I>> =
loop {};
return __tracing_attr_fake_return;
}
{
match self.ambient_variance {
ty::Covariant =>
self.infcx.sub_regions(b, a, VisibleForLeakCheck::Yes,
self.span),
ty::Contravariant =>
self.infcx.sub_regions(a, b, VisibleForLeakCheck::Yes,
self.span),
ty::Invariant =>
self.infcx.equate_regions(a, b, VisibleForLeakCheck::Yes,
self.span),
ty::Bivariant => {
{
::core::panicking::panic_fmt(format_args!("internal error: entered unreachable code: {0}",
format_args!("Expected bivariance to be handled in relate_with_variance")));
}
}
}
Ok(a)
}
}
}#[instrument(skip(self), level = "trace")]
220 fn regions(&mut self, a: Region<I>, b: Region<I>) -> RelateResult<I, Region<I>> {
221 match self.ambient_variance {
222 ty::Covariant => self.infcx.sub_regions(b, a, VisibleForLeakCheck::Yes, self.span),
224 ty::Contravariant => self.infcx.sub_regions(a, b, VisibleForLeakCheck::Yes, self.span),
226 ty::Invariant => self.infcx.equate_regions(a, b, VisibleForLeakCheck::Yes, self.span),
227 ty::Bivariant => {
228 unreachable!("Expected bivariance to be handled in relate_with_variance")
229 }
230 }
231
232 Ok(a)
233 }
234
235 #[allow(clippy :: suspicious_else_formatting)]
{
let __tracing_attr_span;
let __tracing_attr_guard;
if ::tracing::Level::TRACE <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() ||
{ false } {
__tracing_attr_span =
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("consts",
"rustc_type_ir::relate::solver_relating",
::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("compiler/rustc_type_ir/src/relate/solver_relating.rs"),
::tracing_core::__macro_support::Option::Some(235u32),
::tracing_core::__macro_support::Option::Some("rustc_type_ir::relate::solver_relating"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("a")
}> =
::tracing::__macro_support::FieldName::new("a");
NAME.as_str()
},
{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("b")
}> =
::tracing::__macro_support::FieldName::new("b");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::SPAN)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let mut interest = ::tracing::subscriber::Interest::never();
if ::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() &&
{ interest = __CALLSITE.interest(); !interest.is_never() }
&&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest) {
let meta = __CALLSITE.metadata();
::tracing::Span::new(meta,
&{
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
meta.fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&a)
as &dyn ::tracing::field::Value)),
(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&b)
as &dyn ::tracing::field::Value))])
})
} else {
let span =
::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
{};
span
}
};
__tracing_attr_guard = __tracing_attr_span.enter();
}
#[warn(clippy :: suspicious_else_formatting)]
{
#[allow(unknown_lints, unreachable_code, clippy ::
diverging_sub_expression, clippy :: empty_loop, clippy ::
let_unit_value, clippy :: let_with_type_underscore, clippy ::
needless_return, clippy :: unreachable)]
if false {
let __tracing_attr_fake_return: RelateResult<I, I::Const> =
loop {};
return __tracing_attr_fake_return;
}
{ super_combine_consts(self.infcx, self, a, b) }
}
}#[instrument(skip(self), level = "trace")]
236 fn consts(&mut self, a: I::Const, b: I::Const) -> RelateResult<I, I::Const> {
237 super_combine_consts(self.infcx, self, a, b)
238 }
239
240 fn binders<T>(
241 &mut self,
242 a: ty::Binder<I, T>,
243 b: ty::Binder<I, T>,
244 ) -> RelateResult<I, ty::Binder<I, T>>
245 where
246 T: Relate<I>,
247 {
248 if a == b {
250 return Ok(a);
251 }
252
253 if let Some(a_inner) = a.no_bound_vars()
255 && let Some(b_inner) = b.no_bound_vars()
256 {
257 self.relate(a_inner, b_inner)?;
258 return Ok(a);
259 }
260
261 match self.ambient_variance {
262 ty::Covariant => {
278 self.infcx.enter_forall_with_empty_assumptions(b, |b| {
279 let a = self.infcx.instantiate_binder_with_infer(a);
280 self.relate(a, b)
281 })?;
282 }
283 ty::Contravariant => {
284 self.infcx.enter_forall_with_empty_assumptions(a, |a| {
285 let b = self.infcx.instantiate_binder_with_infer(b);
286 self.relate(a, b)
287 })?;
288 }
289
290 ty::Invariant => {
301 self.infcx.enter_forall_with_empty_assumptions(b, |b| {
302 let a = self.infcx.instantiate_binder_with_infer(a);
303 self.relate(a, b)
304 })?;
305
306 self.infcx.enter_forall_with_empty_assumptions(a, |a| {
308 let b = self.infcx.instantiate_binder_with_infer(b);
309 self.relate(a, b)
310 })?;
311 }
312 ty::Bivariant => {
313 {
::core::panicking::panic_fmt(format_args!("internal error: entered unreachable code: {0}",
format_args!("Expected bivariance to be handled in relate_with_variance")));
}unreachable!("Expected bivariance to be handled in relate_with_variance")
314 }
315 }
316 Ok(a)
317 }
318}
319
320impl<Infcx, I> PredicateEmittingRelation<Infcx> for SolverRelating<'_, Infcx, I>
321where
322 Infcx: InferCtxtLike<Interner = I>,
323 I: Interner,
324{
325 fn span(&self) -> I::Span {
326 Span::dummy()
327 }
328
329 fn param_env(&self) -> I::ParamEnv {
330 self.param_env
331 }
332
333 fn register_predicates(
334 &mut self,
335 obligations: impl IntoIterator<Item: ty::Upcast<I, I::Predicate>>,
336 ) {
337 self.goals.extend(
338 obligations.into_iter().map(|pred| Goal::new(self.infcx.cx(), self.param_env, pred)),
339 );
340 }
341
342 fn register_goals(&mut self, obligations: impl IntoIterator<Item = Goal<I, I::Predicate>>) {
343 self.goals.extend(obligations);
344 }
345
346 fn ambient_variance(&self) -> ty::Variance {
347 self.ambient_variance
348 }
349}