1use std::iter;
2use std::rc::Rc;
34use rustc_data_structures::frozen::Frozen;
5use rustc_data_structures::fx::FxIndexMap;
6use rustc_hir::def_id::{DefId, LocalDefId};
7use rustc_infer::infer::outlives::env::RegionBoundPairs;
8use rustc_infer::infer::{InferCtxt, NllRegionVariableOrigin, OpaqueTypeStorageEntries};
9use rustc_infer::traits::ObligationCause;
10use rustc_macros::extension;
11use rustc_middle::mir::{Body, ConstraintCategory};
12use rustc_middle::ty::{
13self, DefiningScopeKind, DefinitionSiteHiddenType, FallibleTypeFolder, GenericArg,
14GenericArgsRef, OpaqueTypeKey, ProvisionalHiddenType, Region, RegionVid, Ty, TyCtxt,
15TypeFoldable, TypeSuperFoldable, TypeVisitableExt, fold_regions,
16};
17use rustc_mir_dataflow::points::DenseLocationMap;
18use rustc_span::Span;
19use rustc_trait_selection::opaque_types::{
20 NonDefiningUseReason, opaque_type_has_defining_use_args,
21};
22use rustc_trait_selection::solve::NoSolution;
23use rustc_trait_selection::traits::query::type_op::custom::CustomTypeOp;
24use tracing::{debug, instrument};
2526use super::reverse_sccs::ReverseSccGraph;
27use crate::consumers::RegionInferenceContext;
28use crate::session_diagnostics::LifetimeMismatchOpaqueParam;
29use crate::type_check::canonical::fully_perform_op_raw;
30use crate::type_check::free_region_relations::UniversalRegionRelations;
31use crate::type_check::{Locations, MirTypeckRegionConstraints};
32use crate::universal_regions::{RegionClassification, UniversalRegions};
33use crate::{BorrowckInferCtxt, CollectRegionConstraintsResult};
3435mod member_constraints;
36mod region_ctxt;
3738use member_constraints::apply_member_constraints;
39use region_ctxt::RegionCtxt;
4041/// We defer errors from [fn handle_opaque_type_uses] and only report them
42/// if there are no `RegionErrors`. If there are region errors, it's likely
43/// that errors here are caused by them and don't need to be handled separately.
44pub(crate) enum DeferredOpaqueTypeError<'tcx> {
45 InvalidOpaqueTypeArgs(NonDefiningUseReason<'tcx>),
46 LifetimeMismatchOpaqueParam(LifetimeMismatchOpaqueParam<'tcx>),
47 UnexpectedHiddenRegion {
48/// The opaque type.
49opaque_type_key: OpaqueTypeKey<'tcx>,
50/// The hidden type containing the member region.
51hidden_type: ProvisionalHiddenType<'tcx>,
52/// The unexpected region.
53member_region: Region<'tcx>,
54 },
55 NonDefiningUseInDefiningScope {
56 span: Span,
57 opaque_type_key: OpaqueTypeKey<'tcx>,
58 },
59}
6061/// We eagerly map all regions to NLL vars here, as we need to make sure we've
62/// introduced nll vars for all used placeholders.
63///
64/// We need to resolve inference vars as even though we're in MIR typeck, we may still
65/// encounter inference variables, e.g. when checking user types.
66pub(crate) fn clone_and_resolve_opaque_types<'tcx>(
67 infcx: &BorrowckInferCtxt<'tcx>,
68 universal_region_relations: &Frozen<UniversalRegionRelations<'tcx>>,
69 constraints: &mut MirTypeckRegionConstraints<'tcx>,
70) -> (OpaqueTypeStorageEntries, Vec<(OpaqueTypeKey<'tcx>, ProvisionalHiddenType<'tcx>)>) {
71let opaque_types = infcx.clone_opaque_types();
72let opaque_types_storage_num_entries = infcx.inner.borrow_mut().opaque_types().num_entries();
73let opaque_types = opaque_types74 .into_iter()
75 .map(|entry| {
76fold_regions(infcx.tcx, infcx.resolve_vars_if_possible(entry), |r, _| {
77let vid = if let ty::RePlaceholder(placeholder) = r.kind() {
78constraints.placeholder_region(infcx, placeholder).as_var()
79 } else {
80universal_region_relations.universal_regions.to_region_vid(r)
81 };
82Region::new_var(infcx.tcx, vid)
83 })
84 })
85 .collect::<Vec<_>>();
86 (opaque_types_storage_num_entries, opaque_types)
87}
8889/// Maps an NLL var to a deterministically chosen equal universal region.
90///
91/// See the corresponding [rustc-dev-guide chapter] for more details. This
92/// ignores changes to the region values due to member constraints. Applying
93/// member constraints does not impact the result of this function.
94///
95/// [rustc-dev-guide chapter]: https://rustc-dev-guide.rust-lang.org/borrow_check/opaque-types-region-inference-restrictions.html
96fn nll_var_to_universal_region<'tcx>(
97 rcx: &RegionCtxt<'_, 'tcx>,
98 r: RegionVid,
99) -> Option<Region<'tcx>> {
100// Use the SCC representative instead of directly using `region`.
101 // See [rustc-dev-guide chapter] § "Strict lifetime equality".
102let vid = rcx.representative(r).rvid();
103match rcx.definitions[vid].origin {
104// Iterate over all universal regions in a consistent order and find the
105 // *first* equal region. This makes sure that equal lifetimes will have
106 // the same name and simplifies subsequent handling.
107 // See [rustc-dev-guide chapter] § "Semantic lifetime equality".
108NllRegionVariableOrigin::FreeRegion => rcx109 .universal_regions()
110 .universal_regions_iter()
111 .filter(|&ur| {
112// See [rustc-dev-guide chapter] § "Closure restrictions".
113 !#[allow(non_exhaustive_omitted_patterns)] match rcx.universal_regions().region_classification(ur)
{
Some(RegionClassification::External) => true,
_ => false,
}matches!(
114 rcx.universal_regions().region_classification(ur),
115Some(RegionClassification::External)
116 )117 })
118 .find(|&ur| rcx.universal_region_relations.equal(vid, ur))
119 .map(|ur| rcx.definitions[ur].external_name.unwrap()),
120 NllRegionVariableOrigin::Placeholder(placeholder) => {
121Some(ty::Region::new_placeholder(rcx.infcx.tcx, placeholder))
122 }
123// If `r` were equal to any universal region, its SCC representative
124 // would have been set to a free region.
125NllRegionVariableOrigin::Existential { .. } => None,
126 }
127}
128129/// Record info needed to report the same name error later.
130#[derive(#[automatically_derived]
impl<'tcx> ::core::marker::Copy for UnexpectedHiddenRegion<'tcx> { }Copy, #[automatically_derived]
impl<'tcx> ::core::clone::Clone for UnexpectedHiddenRegion<'tcx> {
#[inline]
fn clone(&self) -> UnexpectedHiddenRegion<'tcx> {
let _: ::core::clone::AssertParamIsClone<LocalDefId>;
let _: ::core::clone::AssertParamIsClone<OpaqueTypeKey<'tcx>>;
let _: ::core::clone::AssertParamIsClone<ProvisionalHiddenType<'tcx>>;
let _: ::core::clone::AssertParamIsClone<Region<'tcx>>;
*self
}
}Clone, #[automatically_derived]
impl<'tcx> ::core::fmt::Debug for UnexpectedHiddenRegion<'tcx> {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::debug_struct_field4_finish(f,
"UnexpectedHiddenRegion", "def_id", &self.def_id,
"opaque_type_key", &self.opaque_type_key, "hidden_type",
&self.hidden_type, "member_region", &&self.member_region)
}
}Debug)]
131pub(crate) struct UnexpectedHiddenRegion<'tcx> {
132// The def_id of the body where this error occurs.
133 // Needed to handle region vars with their corresponding `infcx`.
134def_id: LocalDefId,
135 opaque_type_key: OpaqueTypeKey<'tcx>,
136 hidden_type: ProvisionalHiddenType<'tcx>,
137 member_region: Region<'tcx>,
138}
139140impl<'tcx> UnexpectedHiddenRegion<'tcx> {
141pub(crate) fn to_error(self) -> (LocalDefId, DeferredOpaqueTypeError<'tcx>) {
142let UnexpectedHiddenRegion { def_id, opaque_type_key, hidden_type, member_region } = self;
143 (
144def_id,
145 DeferredOpaqueTypeError::UnexpectedHiddenRegion {
146opaque_type_key,
147hidden_type,
148member_region,
149 },
150 )
151 }
152}
153154/// Collect all defining uses of opaque types inside of this typeck root. This
155/// expects the hidden type to be mapped to the definition parameters of the opaque
156/// and errors if we end up with distinct hidden types.
157fn add_hidden_type<'tcx>(
158 tcx: TyCtxt<'tcx>,
159 hidden_types: &mut FxIndexMap<LocalDefId, ty::DefinitionSiteHiddenType<'tcx>>,
160 def_id: LocalDefId,
161 hidden_ty: ty::DefinitionSiteHiddenType<'tcx>,
162) {
163// Sometimes two opaque types are the same only after we remap the generic parameters
164 // back to the opaque type definition. E.g. we may have `OpaqueType<X, Y>` mapped to
165 // `(X, Y)` and `OpaqueType<Y, X>` mapped to `(Y, X)`, and those are the same, but we
166 // only know that once we convert the generic parameters to those of the opaque type.
167if let Some(prev) = hidden_types.get_mut(&def_id) {
168if prev.ty == hidden_ty.ty {
169// Pick a better span if there is one.
170 // FIXME(oli-obk): collect multiple spans for better diagnostics down the road.
171prev.span = prev.span.substitute_dummy(hidden_ty.span);
172 } else {
173let (Ok(guar) | Err(guar)) =
174prev.build_mismatch_error(&hidden_ty, tcx).map(|d| d.emit());
175*prev = ty::DefinitionSiteHiddenType::new_error(tcx, guar);
176 }
177 } else {
178hidden_types.insert(def_id, hidden_ty);
179 }
180}
181182#[derive(#[automatically_derived]
impl<'tcx> ::core::fmt::Debug for DefiningUse<'tcx> {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::debug_struct_field3_finish(f, "DefiningUse",
"opaque_type_key", &self.opaque_type_key, "arg_regions",
&self.arg_regions, "hidden_type", &&self.hidden_type)
}
}Debug)]
183struct DefiningUse<'tcx> {
184/// The opaque type using non NLL vars. This uses the actual
185 /// free regions and placeholders. This is necessary
186 /// to interact with code outside of `rustc_borrowck`.
187opaque_type_key: OpaqueTypeKey<'tcx>,
188 arg_regions: Vec<RegionVid>,
189 hidden_type: ProvisionalHiddenType<'tcx>,
190}
191192/// This computes the actual hidden types of the opaque types and maps them to their
193/// definition sites. Outside of registering the computed hidden types this function
194/// does not mutate the current borrowck state.
195///
196/// While it may fail to infer the hidden type and return errors, we always apply
197/// the computed hidden type to all opaque type uses to check whether they
198/// are correct. This is necessary to support non-defining uses of opaques in their
199/// defining scope.
200///
201/// It also means that this whole function is not really soundness critical as we
202/// recheck all uses of the opaques regardless.
203pub(crate) fn compute_definition_site_hidden_types<'tcx>(
204 def_id: LocalDefId,
205 infcx: &BorrowckInferCtxt<'tcx>,
206 universal_region_relations: &Frozen<UniversalRegionRelations<'tcx>>,
207 constraints: &MirTypeckRegionConstraints<'tcx>,
208 location_map: Rc<DenseLocationMap>,
209 hidden_types: &mut FxIndexMap<LocalDefId, ty::DefinitionSiteHiddenType<'tcx>>,
210 unconstrained_hidden_type_errors: &mut Vec<UnexpectedHiddenRegion<'tcx>>,
211 opaque_types: &[(OpaqueTypeKey<'tcx>, ProvisionalHiddenType<'tcx>)],
212) -> Vec<DeferredOpaqueTypeError<'tcx>> {
213let mut errors = Vec::new();
214// When computing the hidden type we need to track member constraints.
215 // We don't mutate the region graph used by `fn compute_regions` but instead
216 // manually track region information via a `RegionCtxt`. We discard this
217 // information at the end of this function.
218let mut rcx = RegionCtxt::new(infcx, universal_region_relations, location_map, constraints);
219220// We start by checking each use of an opaque type during type check and
221 // check whether the generic arguments of the opaque type are fully
222 // universal, if so, it's a defining use.
223let defining_uses = collect_defining_uses(&mut rcx, hidden_types, opaque_types, &mut errors);
224225// We now compute and apply member constraints for all regions in the hidden
226 // types of each defining use. This mutates the region values of the `rcx` which
227 // is used when mapping the defining uses to the definition site.
228apply_member_constraints(&mut rcx, &defining_uses);
229230// After applying member constraints, we now check whether all member regions ended
231 // up equal to one of their choice regions and compute the actual hidden type of
232 // the opaque type definition. This is stored in the `root_cx`.
233compute_definition_site_hidden_types_from_defining_uses(
234def_id,
235&rcx,
236hidden_types,
237unconstrained_hidden_type_errors,
238&defining_uses,
239&mut errors,
240 );
241errors242}
243244x;#[instrument(level = "debug", skip_all, ret)]245fn collect_defining_uses<'tcx>(
246 rcx: &mut RegionCtxt<'_, 'tcx>,
247 hidden_types: &mut FxIndexMap<LocalDefId, ty::DefinitionSiteHiddenType<'tcx>>,
248 opaque_types: &[(OpaqueTypeKey<'tcx>, ProvisionalHiddenType<'tcx>)],
249 errors: &mut Vec<DeferredOpaqueTypeError<'tcx>>,
250) -> Vec<DefiningUse<'tcx>> {
251let infcx = rcx.infcx;
252let mut defining_uses = vec![];
253for &(opaque_type_key, hidden_type) in opaque_types {
254let non_nll_opaque_type_key = opaque_type_key.fold_captured_lifetime_args(infcx.tcx, |r| {
255 nll_var_to_universal_region(&rcx, r.as_var()).unwrap_or(r)
256 });
257if let Err(err) = opaque_type_has_defining_use_args(
258 infcx,
259 non_nll_opaque_type_key,
260 hidden_type.span,
261 DefiningScopeKind::MirBorrowck,
262 ) {
263// A non-defining use. This is a hard error on stable and gets ignored
264 // with `TypingMode::Borrowck`.
265if infcx.tcx.use_typing_mode_borrowck() {
266match err {
267 NonDefiningUseReason::Tainted(guar) => add_hidden_type(
268 infcx.tcx,
269 hidden_types,
270 opaque_type_key.def_id,
271 DefinitionSiteHiddenType::new_error(infcx.tcx, guar),
272 ),
273_ => debug!(?non_nll_opaque_type_key, ?err, "ignoring non-defining use"),
274 }
275 } else {
276 errors.push(DeferredOpaqueTypeError::InvalidOpaqueTypeArgs(err));
277debug!(
278"collect_defining_uses: InvalidOpaqueTypeArgs for {:?} := {:?}",
279 non_nll_opaque_type_key, hidden_type
280 );
281 }
282continue;
283 }
284285// We use the original `opaque_type_key` to compute the `arg_regions`.
286let arg_regions = iter::once(rcx.universal_regions().fr_static)
287 .chain(
288 opaque_type_key
289 .iter_captured_args(infcx.tcx)
290 .filter_map(|(_, arg)| arg.as_region())
291 .map(Region::as_var),
292 )
293 .collect();
294 defining_uses.push(DefiningUse {
295 opaque_type_key: non_nll_opaque_type_key,
296 arg_regions,
297 hidden_type,
298 });
299 }
300301 defining_uses
302}
303304#[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("compute_definition_site_hidden_types_from_defining_uses",
"rustc_borrowck::region_infer::opaque_types",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_borrowck/src/region_infer/opaque_types/mod.rs"),
::tracing_core::__macro_support::Option::Some(304u32),
::tracing_core::__macro_support::Option::Some("rustc_borrowck::region_infer::opaque_types"),
::tracing_core::field::FieldSet::new(&["def_id",
"unconstrained_hidden_type_errors"],
::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};
let mut iter = meta.fields().iter();
meta.fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&::tracing::field::debug(&def_id)
as &dyn Value)),
(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&::tracing::field::debug(&unconstrained_hidden_type_errors)
as &dyn 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: () = loop {};
return __tracing_attr_fake_return;
}
{
let infcx = rcx.infcx;
let tcx = infcx.tcx;
let mut decls_modulo_regions:
FxIndexMap<OpaqueTypeKey<'tcx>,
(OpaqueTypeKey<'tcx>, Span)> = FxIndexMap::default();
for &DefiningUse { opaque_type_key, ref arg_regions, hidden_type }
in defining_uses {
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event compiler/rustc_borrowck/src/region_infer/opaque_types/mod.rs:318",
"rustc_borrowck::region_infer::opaque_types",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_borrowck/src/region_infer/opaque_types/mod.rs"),
::tracing_core::__macro_support::Option::Some(318u32),
::tracing_core::__macro_support::Option::Some("rustc_borrowck::region_infer::opaque_types"),
::tracing_core::field::FieldSet::new(&["opaque_type_key",
"arg_regions", "hidden_type"],
::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(&debug(&opaque_type_key)
as &dyn Value)),
(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&debug(&arg_regions)
as &dyn Value)),
(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&debug(&hidden_type)
as &dyn Value))])
});
} else { ; }
};
let hidden_type =
match hidden_type.try_fold_with(&mut ToArgRegionsFolder::new(rcx,
arg_regions)) {
Ok(hidden_type) => hidden_type,
Err(r) => {
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event compiler/rustc_borrowck/src/region_infer/opaque_types/mod.rs:326",
"rustc_borrowck::region_infer::opaque_types",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_borrowck/src/region_infer/opaque_types/mod.rs"),
::tracing_core::__macro_support::Option::Some(326u32),
::tracing_core::__macro_support::Option::Some("rustc_borrowck::region_infer::opaque_types"),
::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!("UnexpectedHiddenRegion: {0:?}",
r) as &dyn Value))])
});
} else { ; }
};
if rcx.infcx.tcx.use_typing_mode_borrowck() {
unconstrained_hidden_type_errors.push(UnexpectedHiddenRegion {
def_id,
hidden_type,
opaque_type_key,
member_region: ty::Region::new_var(tcx, r),
});
continue;
} else {
errors.push(DeferredOpaqueTypeError::UnexpectedHiddenRegion {
hidden_type,
opaque_type_key,
member_region: ty::Region::new_var(tcx, r),
});
let guar =
tcx.dcx().span_delayed_bug(hidden_type.span,
"opaque type with non-universal region args");
ty::ProvisionalHiddenType::new_error(tcx, guar)
}
}
};
let hidden_type =
infcx.infer_opaque_definition_from_instantiation(opaque_type_key,
hidden_type).unwrap_or_else(|_|
{
let guar =
tcx.dcx().span_delayed_bug(hidden_type.span,
"deferred invalid opaque type args");
DefinitionSiteHiddenType::new_error(tcx, guar)
});
if !rcx.infcx.tcx.use_typing_mode_borrowck() {
if let &ty::Alias(ty::AliasTy {
kind: ty::Opaque { def_id }, args, .. }) =
hidden_type.ty.skip_binder().kind() &&
def_id == opaque_type_key.def_id.to_def_id() &&
args == opaque_type_key.args {
continue;
}
}
if let Some((prev_decl_key, prev_span)) =
decls_modulo_regions.insert(rcx.infcx.tcx.erase_and_anonymize_regions(opaque_type_key),
(opaque_type_key, hidden_type.span)) &&
let Some((arg1, arg2)) =
std::iter::zip(prev_decl_key.iter_captured_args(infcx.tcx).map(|(_,
arg)| arg),
opaque_type_key.iter_captured_args(infcx.tcx).map(|(_, arg)|
arg)).find(|(arg1, arg2)| arg1 != arg2) {
errors.push(DeferredOpaqueTypeError::LifetimeMismatchOpaqueParam(LifetimeMismatchOpaqueParam {
arg: arg1,
prev: arg2,
span: prev_span,
prev_span: hidden_type.span,
}));
}
add_hidden_type(tcx, hidden_types, opaque_type_key.def_id,
hidden_type);
}
}
}
}#[instrument(level = "debug", skip(rcx, hidden_types, defining_uses, errors))]305fn compute_definition_site_hidden_types_from_defining_uses<'tcx>(
306 def_id: LocalDefId,
307 rcx: &RegionCtxt<'_, 'tcx>,
308 hidden_types: &mut FxIndexMap<LocalDefId, ty::DefinitionSiteHiddenType<'tcx>>,
309 unconstrained_hidden_type_errors: &mut Vec<UnexpectedHiddenRegion<'tcx>>,
310 defining_uses: &[DefiningUse<'tcx>],
311 errors: &mut Vec<DeferredOpaqueTypeError<'tcx>>,
312) {
313let infcx = rcx.infcx;
314let tcx = infcx.tcx;
315let mut decls_modulo_regions: FxIndexMap<OpaqueTypeKey<'tcx>, (OpaqueTypeKey<'tcx>, Span)> =
316 FxIndexMap::default();
317for &DefiningUse { opaque_type_key, ref arg_regions, hidden_type } in defining_uses {
318debug!(?opaque_type_key, ?arg_regions, ?hidden_type);
319// After applying member constraints, we now map all regions in the hidden type
320 // to the `arg_regions` of this defining use. In case a region in the hidden type
321 // ended up not being equal to any such region, we error.
322let hidden_type =
323match hidden_type.try_fold_with(&mut ToArgRegionsFolder::new(rcx, arg_regions)) {
324Ok(hidden_type) => hidden_type,
325Err(r) => {
326debug!("UnexpectedHiddenRegion: {:?}", r);
327// If we're using the next solver, the unconstrained region may be resolved by a
328 // fully defining use from another body.
329 // So we don't generate error eagerly here.
330if rcx.infcx.tcx.use_typing_mode_borrowck() {
331 unconstrained_hidden_type_errors.push(UnexpectedHiddenRegion {
332 def_id,
333 hidden_type,
334 opaque_type_key,
335 member_region: ty::Region::new_var(tcx, r),
336 });
337continue;
338 } else {
339 errors.push(DeferredOpaqueTypeError::UnexpectedHiddenRegion {
340 hidden_type,
341 opaque_type_key,
342 member_region: ty::Region::new_var(tcx, r),
343 });
344let guar = tcx.dcx().span_delayed_bug(
345 hidden_type.span,
346"opaque type with non-universal region args",
347 );
348 ty::ProvisionalHiddenType::new_error(tcx, guar)
349 }
350 }
351 };
352353// Now that we mapped the member regions to their final value,
354 // map the arguments of the opaque type key back to the parameters
355 // of the opaque type definition.
356let hidden_type = infcx
357 .infer_opaque_definition_from_instantiation(opaque_type_key, hidden_type)
358 .unwrap_or_else(|_| {
359let guar = tcx
360 .dcx()
361 .span_delayed_bug(hidden_type.span, "deferred invalid opaque type args");
362 DefinitionSiteHiddenType::new_error(tcx, guar)
363 });
364365// Sometimes, when the hidden type is an inference variable, it can happen that
366 // the hidden type becomes the opaque type itself. In this case, this was an opaque
367 // usage of the opaque type and we can ignore it. This check is mirrored in typeck's
368 // writeback.
369if !rcx.infcx.tcx.use_typing_mode_borrowck() {
370if let &ty::Alias(ty::AliasTy { kind: ty::Opaque { def_id }, args, .. }) =
371 hidden_type.ty.skip_binder().kind()
372 && def_id == opaque_type_key.def_id.to_def_id()
373 && args == opaque_type_key.args
374 {
375continue;
376 }
377 }
378379// Check that all opaque types have the same region parameters if they have the same
380 // non-region parameters. This is necessary because within the new solver we perform
381 // various query operations modulo regions, and thus could unsoundly select some impls
382 // that don't hold.
383 //
384 // FIXME(-Znext-solver): This isn't necessary after all. We can remove this check again.
385if let Some((prev_decl_key, prev_span)) = decls_modulo_regions.insert(
386 rcx.infcx.tcx.erase_and_anonymize_regions(opaque_type_key),
387 (opaque_type_key, hidden_type.span),
388 ) && let Some((arg1, arg2)) = std::iter::zip(
389 prev_decl_key.iter_captured_args(infcx.tcx).map(|(_, arg)| arg),
390 opaque_type_key.iter_captured_args(infcx.tcx).map(|(_, arg)| arg),
391 )
392 .find(|(arg1, arg2)| arg1 != arg2)
393 {
394 errors.push(DeferredOpaqueTypeError::LifetimeMismatchOpaqueParam(
395 LifetimeMismatchOpaqueParam {
396 arg: arg1,
397 prev: arg2,
398 span: prev_span,
399 prev_span: hidden_type.span,
400 },
401 ));
402 }
403 add_hidden_type(tcx, hidden_types, opaque_type_key.def_id, hidden_type);
404 }
405}
406407/// A folder to map the regions in the hidden type to their corresponding `arg_regions`.
408///
409/// This folder has to differentiate between member regions and other regions in the hidden
410/// type. Member regions have to be equal to one of the `arg_regions` while other regions simply
411/// get treated as an existential region in the opaque if they are not. Existential
412/// regions are currently represented using `'erased`.
413struct ToArgRegionsFolder<'a, 'tcx> {
414 rcx: &'a RegionCtxt<'a, 'tcx>,
415// When folding closure args or bivariant alias arguments, we simply
416 // ignore non-member regions. However, we still need to map member
417 // regions to their arg region even if its in a closure argument.
418 //
419 // See tests/ui/type-alias-impl-trait/closure_wf_outlives.rs for an example.
420erase_unknown_regions: bool,
421 arg_regions: &'a [RegionVid],
422}
423424impl<'a, 'tcx> ToArgRegionsFolder<'a, 'tcx> {
425fn new(
426 rcx: &'a RegionCtxt<'a, 'tcx>,
427 arg_regions: &'a [RegionVid],
428 ) -> ToArgRegionsFolder<'a, 'tcx> {
429ToArgRegionsFolder { rcx, erase_unknown_regions: false, arg_regions }
430 }
431432fn fold_non_member_arg(&mut self, arg: GenericArg<'tcx>) -> GenericArg<'tcx> {
433let prev = self.erase_unknown_regions;
434self.erase_unknown_regions = true;
435let res = arg.try_fold_with(self).unwrap();
436self.erase_unknown_regions = prev;
437res438 }
439440fn fold_closure_args(
441&mut self,
442 def_id: DefId,
443 args: GenericArgsRef<'tcx>,
444 ) -> Result<GenericArgsRef<'tcx>, RegionVid> {
445let generics = self.cx().generics_of(def_id);
446self.cx().mk_args_from_iter(args.iter().enumerate().map(|(index, arg)| {
447if index < generics.parent_count {
448Ok(self.fold_non_member_arg(arg))
449 } else {
450arg.try_fold_with(self)
451 }
452 }))
453 }
454}
455impl<'tcx> FallibleTypeFolder<TyCtxt<'tcx>> for ToArgRegionsFolder<'_, 'tcx> {
456type Error = RegionVid;
457fn cx(&self) -> TyCtxt<'tcx> {
458self.rcx.infcx.tcx
459 }
460461fn try_fold_region(&mut self, r: Region<'tcx>) -> Result<Region<'tcx>, RegionVid> {
462match r.kind() {
463// ignore bound regions, keep visiting
464ty::ReBound(_, _) => Ok(r),
465_ => {
466let r = r.as_var();
467if let Some(arg_region) = self468 .arg_regions
469 .iter()
470 .copied()
471 .find(|&arg_vid| self.rcx.eval_equal(r, arg_vid))
472 .and_then(|r| nll_var_to_universal_region(self.rcx, r))
473 {
474Ok(arg_region)
475 } else if self.erase_unknown_regions {
476Ok(self.cx().lifetimes.re_erased)
477 } else {
478Err(r)
479 }
480 }
481 }
482 }
483484fn try_fold_ty(&mut self, ty: Ty<'tcx>) -> Result<Ty<'tcx>, RegionVid> {
485if !ty.flags().intersects(ty::TypeFlags::HAS_FREE_REGIONS) {
486return Ok(ty);
487 }
488489let tcx = self.cx();
490Ok(match *ty.kind() {
491 ty::Closure(def_id, args) => {
492Ty::new_closure(tcx, def_id, self.fold_closure_args(def_id, args)?)
493 }
494495 ty::CoroutineClosure(def_id, args) => {
496Ty::new_coroutine_closure(tcx, def_id, self.fold_closure_args(def_id, args)?)
497 }
498499 ty::Coroutine(def_id, args) => {
500Ty::new_coroutine(tcx, def_id, self.fold_closure_args(def_id, args)?)
501 }
502503 ty::Alias(ty::AliasTy { kind, args, .. })
504if let Some(variances) = tcx.opt_alias_variances(kind, kind.def_id()) =>
505 {
506let args = tcx.mk_args_from_iter(std::iter::zip(variances, args.iter()).map(
507 |(&v, s)| {
508if v == ty::Bivariant {
509Ok(self.fold_non_member_arg(s))
510 } else {
511s.try_fold_with(self)
512 }
513 },
514 ))?;
515 ty::AliasTy::new_from_args(tcx, kind, args).to_ty(tcx)
516 }
517518_ => ty.try_super_fold_with(self)?,
519 })
520 }
521}
522523/// This function is what actually applies member constraints to the borrowck
524/// state. It is also responsible to check all uses of the opaques in their
525/// defining scope.
526///
527/// It does this by equating the hidden type of each use with the instantiated final
528/// hidden type of the opaque.
529pub(crate) fn apply_definition_site_hidden_types<'tcx>(
530 infcx: &BorrowckInferCtxt<'tcx>,
531 body: &Body<'tcx>,
532 universal_regions: &UniversalRegions<'tcx>,
533 region_bound_pairs: &RegionBoundPairs<'tcx>,
534 known_type_outlives_obligations: &[ty::PolyTypeOutlivesPredicate<'tcx>],
535 constraints: &mut MirTypeckRegionConstraints<'tcx>,
536 hidden_types: &mut FxIndexMap<LocalDefId, ty::DefinitionSiteHiddenType<'tcx>>,
537 opaque_types: &[(OpaqueTypeKey<'tcx>, ProvisionalHiddenType<'tcx>)],
538) -> Vec<DeferredOpaqueTypeError<'tcx>> {
539let tcx = infcx.tcx;
540let mut errors = Vec::new();
541for &(key, hidden_type) in opaque_types {
542let Some(expected) = hidden_types.get(&key.def_id) else {
543if !tcx.use_typing_mode_borrowck() {
544if let &ty::Alias(ty::AliasTy { kind: ty::Opaque { def_id }, args, .. }) =
545 hidden_type.ty.kind()
546 && def_id == key.def_id.to_def_id()
547 && args == key.args
548 {
549continue;
550 } else {
551{
::core::panicking::panic_fmt(format_args!("internal error: entered unreachable code: {0}",
format_args!("non-defining use in defining scope")));
};unreachable!("non-defining use in defining scope");
552 }
553 }
554 errors.push(DeferredOpaqueTypeError::NonDefiningUseInDefiningScope {
555 span: hidden_type.span,
556 opaque_type_key: key,
557 });
558let guar = tcx.dcx().span_delayed_bug(
559 hidden_type.span,
560"non-defining use in the defining scope with no defining uses",
561 );
562 add_hidden_type(
563 tcx,
564 hidden_types,
565 key.def_id,
566 DefinitionSiteHiddenType::new_error(tcx, guar),
567 );
568continue;
569 };
570571// We erase all non-member region of the opaque and need to treat these as existentials.
572let expected_ty =
573 ty::fold_regions(tcx, expected.ty.instantiate(tcx, key.args), |re, _dbi| {
574match re.kind() {
575 ty::ReErased => infcx.next_nll_region_var(
576 NllRegionVariableOrigin::Existential { name: None },
577 || crate::RegionCtxt::Existential(None),
578 ),
579_ => re,
580 }
581 });
582583// We now simply equate the expected with the actual hidden type.
584let locations = Locations::All(hidden_type.span);
585if let Err(guar) = fully_perform_op_raw(
586 infcx,
587 body,
588 universal_regions,
589 region_bound_pairs,
590 known_type_outlives_obligations,
591 constraints,
592 locations,
593 ConstraintCategory::OpaqueType,
594 CustomTypeOp::new(
595 |ocx| {
596let cause = ObligationCause::misc(
597 hidden_type.span,
598 body.source.def_id().expect_local(),
599 );
600// We need to normalize both types in the old solver before equatingt them.
601let actual_ty = ocx.normalize(&cause, infcx.param_env, hidden_type.ty);
602let expected_ty = ocx.normalize(&cause, infcx.param_env, expected_ty);
603 ocx.eq(&cause, infcx.param_env, actual_ty, expected_ty).map_err(|_| NoSolution)
604 },
605"equating opaque types",
606 ),
607 ) {
608 add_hidden_type(
609 tcx,
610 hidden_types,
611 key.def_id,
612 DefinitionSiteHiddenType::new_error(tcx, guar),
613 );
614 }
615 }
616errors617}
618619/// We handle `UnexpectedHiddenRegion` error lazily in the next solver as
620/// there may be a fully defining use in another body.
621///
622/// In case such a defining use does not exist, we register an error here.
623pub(crate) fn handle_unconstrained_hidden_type_errors<'tcx>(
624 tcx: TyCtxt<'tcx>,
625 hidden_types: &mut FxIndexMap<LocalDefId, ty::DefinitionSiteHiddenType<'tcx>>,
626 unconstrained_hidden_type_errors: &mut Vec<UnexpectedHiddenRegion<'tcx>>,
627 collect_region_constraints_results: &mut FxIndexMap<
628LocalDefId,
629CollectRegionConstraintsResult<'tcx>,
630 >,
631) {
632let mut unconstrained_hidden_type_errors = std::mem::take(unconstrained_hidden_type_errors);
633unconstrained_hidden_type_errors634 .retain(|unconstrained| !hidden_types.contains_key(&unconstrained.opaque_type_key.def_id));
635636unconstrained_hidden_type_errors.iter().for_each(|t| {
637tcx.dcx()
638 .span_delayed_bug(t.hidden_type.span, "opaque type with non-universal region args");
639 });
640641// `UnexpectedHiddenRegion` error contains region var which only makes sense in the
642 // corresponding `infcx`.
643 // So we need to insert the error to the body where it originates from.
644for error in unconstrained_hidden_type_errors {
645let (def_id, error) = error.to_error();
646let Some(result) = collect_region_constraints_results.get_mut(&def_id) else {
647{
::core::panicking::panic_fmt(format_args!("internal error: entered unreachable code: {0}",
format_args!("the body should depend on opaques type if it has opaque use")));
};unreachable!("the body should depend on opaques type if it has opaque use");
648 };
649 result.deferred_opaque_type_errors.push(error);
650 }
651}
652653/// In theory `apply_definition_site_hidden_types` could introduce new uses of opaque types.
654/// We do not check these new uses so this could be unsound.
655///
656/// We detect any new uses and simply delay a bug if they occur. If this results in
657/// an ICE we can properly handle this, but we haven't encountered any such test yet.
658///
659/// See the related comment in `FnCtxt::detect_opaque_types_added_during_writeback`.
660pub(crate) fn detect_opaque_types_added_while_handling_opaque_types<'tcx>(
661 infcx: &InferCtxt<'tcx>,
662 opaque_types_storage_num_entries: OpaqueTypeStorageEntries,
663) {
664for (key, hidden_type) in infcx
665 .inner
666 .borrow_mut()
667 .opaque_types()
668 .opaque_types_added_since(opaque_types_storage_num_entries)
669 {
670let opaque_type_string = infcx.tcx.def_path_str(key.def_id);
671let msg = ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("unexpected cyclic definition of `{0}`",
opaque_type_string))
})format!("unexpected cyclic definition of `{opaque_type_string}`");
672 infcx.dcx().span_delayed_bug(hidden_type.span, msg);
673 }
674675let _ = infcx.take_opaque_types();
676}
677678impl<'tcx> RegionInferenceContext<'tcx> {
679/// Map the regions in the type to named regions. This is similar to what
680 /// `infer_opaque_types` does, but can infer any universal region, not only
681 /// ones from the args for the opaque type. It also doesn't double check
682 /// that the regions produced are in fact equal to the named region they are
683 /// replaced with. This is fine because this function is only to improve the
684 /// region names in error messages.
685 ///
686 /// This differs from `MirBorrowckCtxt::name_regions` since it is particularly
687 /// lax with mapping region vids that are *shorter* than a universal region to
688 /// that universal region. This is useful for member region constraints since
689 /// we want to suggest a universal region name to capture even if it's technically
690 /// not equal to the error region.
691pub(crate) fn name_regions_for_member_constraint<T>(&self, tcx: TyCtxt<'tcx>, ty: T) -> T
692where
693T: TypeFoldable<TyCtxt<'tcx>>,
694 {
695fold_regions(tcx, ty, |region, _| match region.kind() {
696 ty::ReVar(vid) => {
697let scc = self.constraint_sccs.scc(vid);
698699// Special handling of higher-ranked regions.
700if !self.max_nameable_universe(scc).is_root() {
701match self.scc_values.placeholders_contained_in(scc).enumerate().last() {
702// If the region contains a single placeholder then they're equal.
703Some((0, placeholder)) => {
704return ty::Region::new_placeholder(tcx, placeholder);
705 }
706707// Fallback: this will produce a cryptic error message.
708_ => return region,
709 }
710 }
711712// Find something that we can name
713let upper_bound = self.approx_universal_upper_bound(vid);
714if let Some(universal_region) = self.definitions[upper_bound].external_name {
715return universal_region;
716 }
717718// Nothing exact found, so we pick a named upper bound, if there's only one.
719 // If there's >1 universal region, then we probably are dealing w/ an intersection
720 // region which cannot be mapped back to a universal.
721 // FIXME: We could probably compute the LUB if there is one.
722let scc = self.constraint_sccs.scc(vid);
723let rev_scc_graph =
724ReverseSccGraph::compute(&self.constraint_sccs, self.universal_regions());
725let upper_bounds: Vec<_> = rev_scc_graph726 .upper_bounds(scc)
727 .filter_map(|vid| self.definitions[vid].external_name)
728 .filter(|r| !r.is_static())
729 .collect();
730match &upper_bounds[..] {
731 [universal_region] => *universal_region,
732_ => region,
733 }
734 }
735_ => region,
736 })
737 }
738}
739740impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> {
#[doc = " Given the fully resolved, instantiated type for an opaque"]
#[doc = " type, i.e., the value of an inference variable like C1 or C2"]
#[doc = " (*), computes the \"definition type\" for an opaque type"]
#[doc = " definition -- that is, the inferred value of `Foo1<\'x>` or"]
#[doc = " `Foo2<\'x>` that we would conceptually use in its definition:"]
#[doc = " ```ignore (illustrative)"]
#[doc = " type Foo1<\'x> = impl Bar<\'x> = AAA; // <-- this type AAA"]
#[doc = " type Foo2<\'x> = impl Bar<\'x> = BBB; // <-- or this type BBB"]
#[doc = " fn foo<\'a, \'b>(..) -> (Foo1<\'a>, Foo2<\'b>) { .. }"]
#[doc = " ```"]
#[doc =
" Note that these values are defined in terms of a distinct set of"]
#[doc =
" generic parameters (`\'x` instead of `\'a`) from C1 or C2. The main"]
#[doc = " purpose of this function is to do that translation."]
#[doc = ""]
#[doc = " (*) C1 and C2 were introduced in the comments on"]
#[doc =
" `register_member_constraints`. Read that comment for more context."]
fn infer_opaque_definition_from_instantiation(&self,
opaque_type_key: OpaqueTypeKey<'tcx>,
instantiated_ty: ProvisionalHiddenType<'tcx>)
->
Result<ty::DefinitionSiteHiddenType<'tcx>,
NonDefiningUseReason<'tcx>> {
{}
#[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("infer_opaque_definition_from_instantiation",
"rustc_borrowck::region_infer::opaque_types",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_borrowck/src/region_infer/opaque_types/mod.rs"),
::tracing_core::__macro_support::Option::Some(758u32),
::tracing_core::__macro_support::Option::Some("rustc_borrowck::region_infer::opaque_types"),
::tracing_core::field::FieldSet::new(&["opaque_type_key",
"instantiated_ty"],
::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};
let mut iter = meta.fields().iter();
meta.fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&::tracing::field::debug(&opaque_type_key)
as &dyn Value)),
(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&::tracing::field::debug(&instantiated_ty)
as &dyn 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<ty::DefinitionSiteHiddenType<'tcx>,
NonDefiningUseReason<'tcx>> = loop {};
return __tracing_attr_fake_return;
}
{
opaque_type_has_defining_use_args(self, opaque_type_key,
instantiated_ty.span, DefiningScopeKind::MirBorrowck)?;
let definition_ty =
instantiated_ty.remap_generic_params_to_declaration_params(opaque_type_key,
self.tcx, DefiningScopeKind::MirBorrowck);
definition_ty.ty.skip_binder().error_reported()?;
Ok(definition_ty)
}
}
}
}
}#[extension(pub trait InferCtxtExt<'tcx>)]741impl<'tcx> InferCtxt<'tcx> {
742/// Given the fully resolved, instantiated type for an opaque
743 /// type, i.e., the value of an inference variable like C1 or C2
744 /// (*), computes the "definition type" for an opaque type
745 /// definition -- that is, the inferred value of `Foo1<'x>` or
746 /// `Foo2<'x>` that we would conceptually use in its definition:
747 /// ```ignore (illustrative)
748 /// type Foo1<'x> = impl Bar<'x> = AAA; // <-- this type AAA
749 /// type Foo2<'x> = impl Bar<'x> = BBB; // <-- or this type BBB
750 /// fn foo<'a, 'b>(..) -> (Foo1<'a>, Foo2<'b>) { .. }
751 /// ```
752 /// Note that these values are defined in terms of a distinct set of
753 /// generic parameters (`'x` instead of `'a`) from C1 or C2. The main
754 /// purpose of this function is to do that translation.
755 ///
756 /// (*) C1 and C2 were introduced in the comments on
757 /// `register_member_constraints`. Read that comment for more context.
758#[instrument(level = "debug", skip(self))]
759fn infer_opaque_definition_from_instantiation(
760&self,
761 opaque_type_key: OpaqueTypeKey<'tcx>,
762 instantiated_ty: ProvisionalHiddenType<'tcx>,
763 ) -> Result<ty::DefinitionSiteHiddenType<'tcx>, NonDefiningUseReason<'tcx>> {
764 opaque_type_has_defining_use_args(
765self,
766 opaque_type_key,
767 instantiated_ty.span,
768 DefiningScopeKind::MirBorrowck,
769 )?;
770771let definition_ty = instantiated_ty.remap_generic_params_to_declaration_params(
772 opaque_type_key,
773self.tcx,
774 DefiningScopeKind::MirBorrowck,
775 );
776 definition_ty.ty.skip_binder().error_reported()?;
777Ok(definition_ty)
778 }
779}