1use hir::def_id::{DefId, LocalDefId};
2use rustc_hir as hir;
3use rustc_middle::traits::ObligationCause;
4use rustc_middle::traits::solve::Goal;
5use rustc_middle::ty::error::{ExpectedFound, TypeError};
6use rustc_middle::ty::{
7 self, BottomUpFolder, OpaqueTypeKey, ProvisionalHiddenType, Ty, TyCtxt, TypeFoldable,
8 TypeVisitableExt, Unnormalized,
9};
10use rustc_span::{Span, bug};
11use tracing::{debug, instrument};
12
13use super::{DefineOpaqueTypes, RegionVariableOrigin};
14use crate::diagnostics::OpaqueHiddenTypeDiag;
15use crate::infer::{InferCtxt, InferOk};
16use crate::traits::{self, Obligation, PredicateObligations};
17
18mod table;
19
20pub use table::{OpaqueTypeStorage, OpaqueTypeStorageEntries, OpaqueTypeTable};
21
22impl<'tcx> InferCtxt<'tcx> {
23 pub fn replace_opaque_types_with_inference_vars<T: TypeFoldable<TyCtxt<'tcx>>>(
26 &self,
27 value: T,
28 body_def_id: LocalDefId,
29 span: Span,
30 param_env: ty::ParamEnv<'tcx>,
31 ) -> InferOk<'tcx, T> {
32 if self.next_trait_solver() {
34 return InferOk { value, obligations: PredicateObligations::new() };
35 }
36
37 if !value.has_opaque_types() {
38 return InferOk { value, obligations: PredicateObligations::new() };
39 }
40
41 let mut obligations = PredicateObligations::new();
42 let value = value.fold_with(&mut BottomUpFolder {
43 tcx: self.tcx,
44 lt_op: |lt| lt,
45 ct_op: |ct| ct,
46 ty_op: |ty| match *ty.kind() {
47 ty::Alias(_, ty::AliasTy { kind: ty::Opaque { def_id }, .. })
48 if self.can_define_opaque_ty(def_id) && !ty.has_escaping_bound_vars() =>
49 {
50 let def_span = self.tcx.def_span(def_id);
51 let span = if span.contains(def_span) { def_span } else { span };
52 let ty_var = self.next_ty_var(span);
53 obligations.extend(
54 self.handle_opaque_type(ty, ty_var, span, param_env)
55 .unwrap()
56 .into_iter()
57 .map(|goal| {
58 Obligation::new(
59 self.tcx,
60 ObligationCause::new(
61 span,
62 body_def_id,
63 traits::ObligationCauseCode::OpaqueReturnType(None),
64 ),
65 goal.param_env,
66 goal.predicate,
67 )
68 }),
69 );
70 ty_var
71 }
72 _ => ty,
73 },
74 });
75 InferOk { value, obligations }
76 }
77
78 pub fn handle_opaque_type(
79 &self,
80 a: Ty<'tcx>,
81 b: Ty<'tcx>,
82 span: Span,
83 param_env: ty::ParamEnv<'tcx>,
84 ) -> Result<Vec<Goal<'tcx, ty::Predicate<'tcx>>>, TypeError<'tcx>> {
85 if true {
if !!self.next_trait_solver() {
::core::panicking::panic("assertion failed: !self.next_trait_solver()")
};
};debug_assert!(!self.next_trait_solver());
86 let process = |a: Ty<'tcx>, b: Ty<'tcx>| match *a.kind() {
87 ty::Alias(_, ty::AliasTy { kind: ty::Opaque { def_id }, args, .. })
88 if def_id.is_local() =>
89 {
90 let def_id = def_id.expect_local();
91 if self.typing_mode_raw().is_coherence() {
92 return Some(self.register_hidden_type(
94 OpaqueTypeKey { def_id, args },
95 span,
96 param_env,
97 b,
98 ));
99 }
100 if !self.can_define_opaque_ty(def_id) {
135 return None;
136 }
137
138 if let ty::Alias(_, ty::AliasTy { kind: ty::Opaque { def_id: b_def_id }, .. }) =
139 *b.kind()
140 {
141 if self.can_define_opaque_ty(b_def_id)
147 && #[allow(non_exhaustive_omitted_patterns)] match self.tcx.opaque_ty_origin(b_def_id)
{
hir::OpaqueTyOrigin::TyAlias { .. } => true,
_ => false,
}matches!(
148 self.tcx.opaque_ty_origin(b_def_id),
149 hir::OpaqueTyOrigin::TyAlias { .. }
150 )
151 {
152 self.dcx().emit_err(OpaqueHiddenTypeDiag {
153 span,
154 hidden_type: self.tcx.def_span(b_def_id),
155 opaque_type: self.tcx.def_span(def_id),
156 });
157 }
158 }
159 Some(self.register_hidden_type(OpaqueTypeKey { def_id, args }, span, param_env, b))
160 }
161 _ => None,
162 };
163 if let Some(res) = process(a, b) {
164 res
165 } else if let Some(res) = process(b, a) {
166 res
167 } else {
168 let (a, b) = self.deeply_resolve_ignoring_regions((a, b));
169 Err(TypeError::Sorts(ExpectedFound::new(a, b)))
170 }
171 }
172}
173
174impl<'tcx> InferCtxt<'tcx> {
175 {}
#[allow(clippy :: suspicious_else_formatting)]
{
let __tracing_attr_span;
let __tracing_attr_guard;
if ::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::DEBUG <=
::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("register_hidden_type",
"rustc_infer::infer::opaque_types", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/080cc27146389dbb5c8772c476b1937be9c6110f/compiler/rustc_infer/src/infer/opaque_types/mod.rs"),
::tracing_core::__macro_support::Option::Some(175u32),
::tracing_core::__macro_support::Option::Some("rustc_infer::infer::opaque_types"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("opaque_type_key")
}> =
::tracing::__macro_support::FieldName::new("opaque_type_key");
NAME.as_str()
},
{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("span")
}> =
::tracing::__macro_support::FieldName::new("span");
NAME.as_str()
},
{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("param_env")
}> =
::tracing::__macro_support::FieldName::new("param_env");
NAME.as_str()
},
{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("hidden_ty")
}> =
::tracing::__macro_support::FieldName::new("hidden_ty");
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::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::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(&opaque_type_key)
as &dyn ::tracing::field::Value)),
(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&span)
as &dyn ::tracing::field::Value)),
(::tracing::__macro_support::Option::Some(&::tracing::field::debug(¶m_env)
as &dyn ::tracing::field::Value)),
(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&hidden_ty)
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:
Result<Vec<Goal<'tcx, ty::Predicate<'tcx>>>,
TypeError<'tcx>> = loop {};
return __tracing_attr_fake_return;
}
{
let mut goals = Vec::new();
self.insert_hidden_type(opaque_type_key, span, param_env,
hidden_ty, &mut goals)?;
self.add_item_bounds_for_hidden_type(opaque_type_key.def_id.to_def_id(),
opaque_type_key.args, param_env, hidden_ty, &mut goals);
Ok(goals)
}
}
}#[instrument(skip(self), level = "debug")]
176 fn register_hidden_type(
177 &self,
178 opaque_type_key: OpaqueTypeKey<'tcx>,
179 span: Span,
180 param_env: ty::ParamEnv<'tcx>,
181 hidden_ty: Ty<'tcx>,
182 ) -> Result<Vec<Goal<'tcx, ty::Predicate<'tcx>>>, TypeError<'tcx>> {
183 let mut goals = Vec::new();
184
185 self.insert_hidden_type(opaque_type_key, span, param_env, hidden_ty, &mut goals)?;
186
187 self.add_item_bounds_for_hidden_type(
188 opaque_type_key.def_id.to_def_id(),
189 opaque_type_key.args,
190 param_env,
191 hidden_ty,
192 &mut goals,
193 );
194
195 Ok(goals)
196 }
197
198 pub fn register_hidden_type_in_storage(
203 &self,
204 opaque_type_key: OpaqueTypeKey<'tcx>,
205 hidden_ty: ProvisionalHiddenType<'tcx>,
206 ) -> Option<Ty<'tcx>> {
207 self.inner.borrow_mut().opaque_types().register(opaque_type_key, hidden_ty)
208 }
209
210 pub fn insert_hidden_type(
218 &self,
219 opaque_type_key: OpaqueTypeKey<'tcx>,
220 span: Span,
221 param_env: ty::ParamEnv<'tcx>,
222 hidden_ty: Ty<'tcx>,
223 goals: &mut Vec<Goal<'tcx, ty::Predicate<'tcx>>>,
224 ) -> Result<(), TypeError<'tcx>> {
225 let tcx = self.tcx;
226 match self.typing_mode_raw().assert_not_erased() {
234 ty::TypingMode::Coherence => {
235 goals.push(Goal::new(tcx, param_env, ty::PredicateKind::Ambiguous));
239 }
240 ty::TypingMode::Typeck { .. } => {
241 let prev = self
242 .inner
243 .borrow_mut()
244 .opaque_types()
245 .register(opaque_type_key, ProvisionalHiddenType { ty: hidden_ty, span });
246 if let Some(prev) = prev {
247 goals.extend(
248 self.at(&ObligationCause::dummy_with_span(span), param_env)
249 .eq(DefineOpaqueTypes::Yes, prev, hidden_ty)?
250 .obligations
251 .into_iter()
252 .map(|obligation| obligation.as_goal()),
253 );
254 }
255 }
256 ty::TypingMode::PostTypeckUntilBorrowck { .. } => {
257 let prev = self
258 .inner
259 .borrow_mut()
260 .opaque_types()
261 .register(opaque_type_key, ProvisionalHiddenType { ty: hidden_ty, span });
262
263 let actual = prev.unwrap_or_else(|| {
266 let actual = tcx
267 .type_of_opaque_hir_typeck(opaque_type_key.def_id)
268 .instantiate(self.tcx, opaque_type_key.args)
269 .skip_norm_wip();
270 let actual = ty::fold_regions(tcx, actual, |re, _dbi| match re.kind() {
271 ty::ReErased => self.next_region_var(RegionVariableOrigin::Misc(span)),
272 _ => re,
273 });
274 actual
275 });
276
277 goals.extend(
278 self.at(&ObligationCause::dummy_with_span(span), param_env)
279 .eq(DefineOpaqueTypes::Yes, hidden_ty, actual)?
280 .obligations
281 .into_iter()
282 .map(|obligation| obligation.as_goal()),
283 );
284 }
285 mode @ (ty::TypingMode::PostBorrowck { .. }
286 | ty::TypingMode::PostAnalysis
287 | ty::TypingMode::Codegen
288 | ty::TypingMode::Reflection) => {
289 ::rustc_span::macros::bug_impl(None,
format_args!("insert hidden type in {0:?}", mode), Location::caller())bug!("insert hidden type in {mode:?}")
290 }
291 }
292
293 Ok(())
294 }
295
296 pub fn add_item_bounds_for_hidden_type(
297 &self,
298 def_id: DefId,
299 args: ty::GenericArgsRef<'tcx>,
300 param_env: ty::ParamEnv<'tcx>,
301 hidden_ty: Ty<'tcx>,
302 goals: &mut Vec<Goal<'tcx, ty::Predicate<'tcx>>>,
303 ) {
304 let tcx = self.tcx;
305 goals.push(Goal::new(tcx, param_env, ty::ClauseKind::WellFormed(hidden_ty.into())));
317
318 let replace_opaques_in = |clause: ty::Clause<'tcx>, goals: &mut Vec<_>| {
319 clause.fold_with(&mut BottomUpFolder {
320 tcx,
321 ty_op: |ty| match *ty.kind() {
322 ty::Alias(
327 _,
328 projection_ty @ ty::AliasTy { kind: ty::Projection { def_id }, .. },
329 ) if !projection_ty.has_escaping_bound_vars()
330 && !tcx.is_impl_trait_in_trait(def_id)
331 && !self.next_trait_solver() =>
332 {
333 let ty_var = self.next_ty_var(self.tcx.def_span(def_id));
334 goals.push(Goal::new(
335 self.tcx,
336 param_env,
337 ty::ProjectionClause {
338 projection_term: projection_ty.into(),
339 term: ty_var.into(),
340 },
341 ));
342 ty_var
343 }
344 ty::Alias(
347 _,
348 ty::AliasTy { kind: ty::Opaque { def_id: def_id2 }, args: args2, .. },
349 ) if def_id == def_id2 && args == args2 => hidden_ty,
350 _ => ty,
351 },
352 lt_op: |lt| lt,
353 ct_op: |ct| ct,
354 })
355 };
356
357 let item_bounds = tcx.explicit_item_bounds(def_id);
358 for (predicate, _) in
359 item_bounds.iter_instantiated_copied(tcx, args).map(Unnormalized::skip_norm_wip)
360 {
361 let predicate = replace_opaques_in(predicate, goals);
362
363 {
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/080cc27146389dbb5c8772c476b1937be9c6110f/compiler/rustc_infer/src/infer/opaque_types/mod.rs:364",
"rustc_infer::infer::opaque_types", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/080cc27146389dbb5c8772c476b1937be9c6110f/compiler/rustc_infer/src/infer/opaque_types/mod.rs"),
::tracing_core::__macro_support::Option::Some(364u32),
::tracing_core::__macro_support::Option::Some("rustc_infer::infer::opaque_types"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("predicate")
}> =
::tracing::__macro_support::FieldName::new("predicate");
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(&::tracing::field::debug(&predicate)
as &dyn ::tracing::field::Value))])
});
} else { ; }
};debug!(?predicate);
365 goals.push(Goal::new(self.tcx, param_env, predicate));
366 }
367
368 if self.tcx.is_conditionally_const(def_id) {
370 let item_bounds = tcx.explicit_implied_const_bounds(def_id);
371 for (predicate, _) in
372 item_bounds.iter_instantiated_copied(tcx, args).map(Unnormalized::skip_norm_wip)
373 {
374 let predicate = replace_opaques_in(
375 predicate.to_host_effect_clause(self.tcx, ty::BoundConstness::Maybe),
376 goals,
377 );
378
379 {
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/080cc27146389dbb5c8772c476b1937be9c6110f/compiler/rustc_infer/src/infer/opaque_types/mod.rs:380",
"rustc_infer::infer::opaque_types", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/080cc27146389dbb5c8772c476b1937be9c6110f/compiler/rustc_infer/src/infer/opaque_types/mod.rs"),
::tracing_core::__macro_support::Option::Some(380u32),
::tracing_core::__macro_support::Option::Some("rustc_infer::infer::opaque_types"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("predicate")
}> =
::tracing::__macro_support::FieldName::new("predicate");
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(&::tracing::field::debug(&predicate)
as &dyn ::tracing::field::Value))])
});
} else { ; }
};debug!(?predicate);
381 goals.push(Goal::new(self.tcx, param_env, predicate));
382 }
383 }
384 }
385}