Skip to content

Commit 669d609

Browse files
committedJun 9, 2023
extract opaque type wf check into separate fn
1 parent 2278365 commit 669d609

File tree

1 file changed

+74
-65
lines changed

1 file changed

+74
-65
lines changed
 

‎compiler/rustc_borrowck/src/region_infer/opaque_types.rs

+74-65
Original file line numberDiff line numberDiff line change
@@ -251,91 +251,100 @@ impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> {
251251
return self.tcx.ty_error(e);
252252
}
253253

254-
let definition_ty = instantiated_ty
255-
.remap_generic_params_to_declaration_params(opaque_type_key, self.tcx, false)
256-
.ty;
257-
258254
if let Err(guar) =
259255
check_opaque_type_parameter_valid(self.tcx, opaque_type_key, instantiated_ty.span)
260256
{
261257
return self.tcx.ty_error(guar);
262258
}
263259

264-
// Only check this for TAIT. RPIT already supports `tests/ui/impl-trait/nested-return-type2.rs`
265-
// on stable and we'd break that.
266-
let opaque_ty_hir = self.tcx.hir().expect_item(opaque_type_key.def_id);
267-
let OpaqueTyOrigin::TyAlias { .. } = opaque_ty_hir.expect_opaque_ty().origin else {
268-
return definition_ty;
269-
};
270-
let def_id = opaque_type_key.def_id;
271-
// This logic duplicates most of `check_opaque_meets_bounds`.
272-
// FIXME(oli-obk): Also do region checks here and then consider removing `check_opaque_meets_bounds` entirely.
273-
let param_env = self.tcx.param_env(def_id);
274-
// HACK This bubble is required for this tests to pass:
275-
// nested-return-type2-tait2.rs
276-
// nested-return-type2-tait3.rs
277-
// FIXME(-Ztrait-solver=next): We probably should use `DefiningAnchor::Error`
278-
// and prepopulate this `InferCtxt` with known opaque values, rather than
279-
// using the `Bind` anchor here. For now it's fine.
280-
let infcx = self
281-
.tcx
282-
.infer_ctxt()
283-
.with_opaque_type_inference(if self.next_trait_solver() {
284-
DefiningAnchor::Bind(def_id)
285-
} else {
286-
DefiningAnchor::Bubble
287-
})
288-
.build();
289-
let ocx = ObligationCtxt::new(&infcx);
290-
// Require the hidden type to be well-formed with only the generics of the opaque type.
291-
// Defining use functions may have more bounds than the opaque type, which is ok, as long as the
292-
// hidden type is well formed even without those bounds.
293-
let predicate = ty::Binder::dummy(ty::PredicateKind::WellFormed(definition_ty.into()));
294-
295-
let id_substs = InternalSubsts::identity_for_item(self.tcx, def_id);
260+
let definition_ty = instantiated_ty
261+
.remap_generic_params_to_declaration_params(opaque_type_key, self.tcx, false)
262+
.ty;
296263

297-
// Require that the hidden type actually fulfills all the bounds of the opaque type, even without
298-
// the bounds that the function supplies.
299-
let opaque_ty = self.tcx.mk_opaque(def_id.to_def_id(), id_substs);
300-
if let Err(err) = ocx.eq(
301-
&ObligationCause::misc(instantiated_ty.span, def_id),
302-
param_env,
303-
opaque_ty,
264+
// `definition_ty` does not live in of the current inference context,
265+
// so lets make sure that we don't accidentally misuse our current `infcx`.
266+
match check_opaque_type_well_formed(
267+
self.tcx,
268+
self.next_trait_solver(),
269+
opaque_type_key.def_id,
270+
instantiated_ty.span,
304271
definition_ty,
305272
) {
273+
Ok(hidden_ty) => hidden_ty,
274+
Err(guar) => self.tcx.ty_error(guar),
275+
}
276+
}
277+
}
278+
279+
/// This logic duplicates most of `check_opaque_meets_bounds`.
280+
/// FIXME(oli-obk): Also do region checks here and then consider removing
281+
/// `check_opaque_meets_bounds` entirely.
282+
fn check_opaque_type_well_formed<'tcx>(
283+
tcx: TyCtxt<'tcx>,
284+
next_trait_solver: bool,
285+
def_id: LocalDefId,
286+
definition_span: Span,
287+
definition_ty: Ty<'tcx>,
288+
) -> Result<Ty<'tcx>, ErrorGuaranteed> {
289+
// Only check this for TAIT. RPIT already supports `tests/ui/impl-trait/nested-return-type2.rs`
290+
// on stable and we'd break that.
291+
let opaque_ty_hir = tcx.hir().expect_item(def_id);
292+
let OpaqueTyOrigin::TyAlias { .. } = opaque_ty_hir.expect_opaque_ty().origin else {
293+
return Ok(definition_ty);
294+
};
295+
let param_env = tcx.param_env(def_id);
296+
// HACK This bubble is required for this tests to pass:
297+
// nested-return-type2-tait2.rs
298+
// nested-return-type2-tait3.rs
299+
// FIXME(-Ztrait-solver=next): We probably should use `DefiningAnchor::Error`
300+
// and prepopulate this `InferCtxt` with known opaque values, rather than
301+
// using the `Bind` anchor here. For now it's fine.
302+
let infcx = tcx
303+
.infer_ctxt()
304+
.with_next_trait_solver(next_trait_solver)
305+
.with_opaque_type_inference(if next_trait_solver {
306+
DefiningAnchor::Bind(def_id)
307+
} else {
308+
DefiningAnchor::Bubble
309+
})
310+
.build();
311+
let ocx = ObligationCtxt::new(&infcx);
312+
let identity_substs = InternalSubsts::identity_for_item(tcx, def_id);
313+
314+
// Require that the hidden type actually fulfills all the bounds of the opaque type, even without
315+
// the bounds that the function supplies.
316+
let opaque_ty = tcx.mk_opaque(def_id.to_def_id(), identity_substs);
317+
ocx.eq(&ObligationCause::misc(definition_span, def_id), param_env, opaque_ty, definition_ty)
318+
.map_err(|err| {
306319
infcx
307320
.err_ctxt()
308321
.report_mismatched_types(
309-
&ObligationCause::misc(instantiated_ty.span, def_id),
322+
&ObligationCause::misc(definition_span, def_id),
310323
opaque_ty,
311324
definition_ty,
312325
err,
313326
)
314-
.emit();
315-
}
327+
.emit()
328+
})?;
316329

317-
ocx.register_obligation(Obligation::misc(
318-
infcx.tcx,
319-
instantiated_ty.span,
320-
def_id,
321-
param_env,
322-
predicate,
323-
));
330+
// Require the hidden type to be well-formed with only the generics of the opaque type.
331+
// Defining use functions may have more bounds than the opaque type, which is ok, as long as the
332+
// hidden type is well formed even without those bounds.
333+
let predicate = ty::Binder::dummy(ty::PredicateKind::WellFormed(definition_ty.into()));
334+
ocx.register_obligation(Obligation::misc(tcx, definition_span, def_id, param_env, predicate));
324335

325-
// Check that all obligations are satisfied by the implementation's
326-
// version.
327-
let errors = ocx.select_all_or_error();
336+
// Check that all obligations are satisfied by the implementation's
337+
// version.
338+
let errors = ocx.select_all_or_error();
328339

329-
// This is still required for many(half of the tests in ui/type-alias-impl-trait)
330-
// tests to pass
331-
let _ = infcx.take_opaque_types();
340+
// This is still required for many(half of the tests in ui/type-alias-impl-trait)
341+
// tests to pass
342+
let _ = infcx.take_opaque_types();
332343

333-
if errors.is_empty() {
334-
definition_ty
335-
} else {
336-
let reported = infcx.err_ctxt().report_fulfillment_errors(&errors);
337-
self.tcx.ty_error(reported)
338-
}
344+
if errors.is_empty() {
345+
Ok(definition_ty)
346+
} else {
347+
Err(infcx.err_ctxt().report_fulfillment_errors(&errors))
339348
}
340349
}
341350

0 commit comments

Comments
 (0)
Please sign in to comment.