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