Skip to content

Commit 34d64ab

Browse files
committed
Auto merge of #112466 - lcnr:opaque-type-cleanup, r=compiler-errors
opaque type cleanup the commits are pretty self-contained. r? `@compiler-errors` cc `@oli-obk`
2 parents 970058e + b62e20d commit 34d64ab

File tree

7 files changed

+204
-175
lines changed

7 files changed

+204
-175
lines changed

compiler/rustc_borrowck/src/region_infer/opaque_types.rs

+77-73
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
6161
pub(crate) fn infer_opaque_types(
6262
&self,
6363
infcx: &InferCtxt<'tcx>,
64-
opaque_ty_decls: FxIndexMap<OpaqueTypeKey<'tcx>, (OpaqueHiddenType<'tcx>, OpaqueTyOrigin)>,
64+
opaque_ty_decls: FxIndexMap<OpaqueTypeKey<'tcx>, OpaqueHiddenType<'tcx>>,
6565
) -> FxIndexMap<LocalDefId, OpaqueHiddenType<'tcx>> {
6666
let mut result: FxIndexMap<LocalDefId, OpaqueHiddenType<'tcx>> = FxIndexMap::default();
6767

@@ -72,7 +72,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
7272
.collect();
7373
debug!(?member_constraints);
7474

75-
for (opaque_type_key, (concrete_type, origin)) in opaque_ty_decls {
75+
for (opaque_type_key, concrete_type) in opaque_ty_decls {
7676
let substs = opaque_type_key.substs;
7777
debug!(?concrete_type, ?substs);
7878

@@ -143,7 +143,6 @@ impl<'tcx> RegionInferenceContext<'tcx> {
143143
let ty = infcx.infer_opaque_definition_from_instantiation(
144144
opaque_type_key,
145145
universal_concrete_type,
146-
origin,
147146
);
148147
// Sometimes two opaque types are the same only after we remap the generic parameters
149148
// back to the opaque type definition. E.g. we may have `OpaqueType<X, Y>` mapped to `(X, Y)`
@@ -215,7 +214,6 @@ pub trait InferCtxtExt<'tcx> {
215214
&self,
216215
opaque_type_key: OpaqueTypeKey<'tcx>,
217216
instantiated_ty: OpaqueHiddenType<'tcx>,
218-
origin: OpaqueTyOrigin,
219217
) -> Ty<'tcx>;
220218
}
221219

@@ -248,109 +246,115 @@ impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> {
248246
&self,
249247
opaque_type_key: OpaqueTypeKey<'tcx>,
250248
instantiated_ty: OpaqueHiddenType<'tcx>,
251-
origin: OpaqueTyOrigin,
252249
) -> Ty<'tcx> {
253250
if let Some(e) = self.tainted_by_errors() {
254251
return self.tcx.ty_error(e);
255252
}
256253

254+
if let Err(guar) =
255+
check_opaque_type_parameter_valid(self.tcx, opaque_type_key, instantiated_ty.span)
256+
{
257+
return self.tcx.ty_error(guar);
258+
}
259+
257260
let definition_ty = instantiated_ty
258261
.remap_generic_params_to_declaration_params(opaque_type_key, self.tcx, false)
259262
.ty;
260263

261-
if let Err(guar) = check_opaque_type_parameter_valid(
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(
262267
self.tcx,
263-
opaque_type_key,
264-
origin,
268+
self.next_trait_solver(),
269+
opaque_type_key.def_id,
265270
instantiated_ty.span,
271+
definition_ty,
266272
) {
267-
return self.tcx.ty_error(guar);
273+
Ok(hidden_ty) => hidden_ty,
274+
Err(guar) => self.tcx.ty_error(guar),
268275
}
276+
}
277+
}
269278

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

302-
// Require that the hidden type actually fulfills all the bounds of the opaque type, even without
303-
// the bounds that the function supplies.
304-
let opaque_ty = self.tcx.mk_opaque(def_id.to_def_id(), id_substs);
305-
if let Err(err) = ocx.eq(
306-
&ObligationCause::misc(instantiated_ty.span, def_id),
307-
param_env,
308-
opaque_ty,
309-
definition_ty,
310-
) {
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| {
311319
infcx
312320
.err_ctxt()
313321
.report_mismatched_types(
314-
&ObligationCause::misc(instantiated_ty.span, def_id),
322+
&ObligationCause::misc(definition_span, def_id),
315323
opaque_ty,
316324
definition_ty,
317325
err,
318326
)
319-
.emit();
320-
}
327+
.emit()
328+
})?;
321329

322-
ocx.register_obligation(Obligation::misc(
323-
infcx.tcx,
324-
instantiated_ty.span,
325-
def_id,
326-
param_env,
327-
predicate,
328-
));
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));
329335

330-
// Check that all obligations are satisfied by the implementation's
331-
// version.
332-
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();
333339

334-
// This is still required for many(half of the tests in ui/type-alias-impl-trait)
335-
// tests to pass
336-
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();
337343

338-
if errors.is_empty() {
339-
definition_ty
340-
} else {
341-
let reported = infcx.err_ctxt().report_fulfillment_errors(&errors);
342-
self.tcx.ty_error(reported)
343-
}
344+
if errors.is_empty() {
345+
Ok(definition_ty)
346+
} else {
347+
Err(infcx.err_ctxt().report_fulfillment_errors(&errors))
344348
}
345349
}
346350

347351
fn check_opaque_type_parameter_valid(
348352
tcx: TyCtxt<'_>,
349353
opaque_type_key: OpaqueTypeKey<'_>,
350-
origin: OpaqueTyOrigin,
351354
span: Span,
352355
) -> Result<(), ErrorGuaranteed> {
353-
match origin {
356+
let opaque_ty_hir = tcx.hir().expect_item(opaque_type_key.def_id);
357+
match opaque_ty_hir.expect_opaque_ty().origin {
354358
// No need to check return position impl trait (RPIT)
355359
// because for type and const parameters they are correct
356360
// by construction: we convert

compiler/rustc_borrowck/src/type_check/mod.rs

+23-11
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ use std::{fmt, iter, mem};
77

88
use either::Either;
99

10-
use hir::OpaqueTyOrigin;
1110
use rustc_data_structures::frozen::Frozen;
1211
use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};
1312
use rustc_errors::ErrorGuaranteed;
@@ -28,6 +27,7 @@ use rustc_middle::mir::visit::{NonMutatingUseContext, PlaceContext, Visitor};
2827
use rustc_middle::mir::AssertKind;
2928
use rustc_middle::mir::*;
3029
use rustc_middle::traits::query::NoSolution;
30+
use rustc_middle::traits::ObligationCause;
3131
use rustc_middle::ty::adjustment::PointerCast;
3232
use rustc_middle::ty::cast::CastTy;
3333
use rustc_middle::ty::subst::{SubstsRef, UserSubsts};
@@ -241,7 +241,7 @@ pub(crate) fn type_check<'mir, 'tcx>(
241241
hidden_type.ty = infcx.tcx.ty_error(reported);
242242
}
243243

244-
(opaque_type_key, (hidden_type, decl.origin))
244+
(opaque_type_key, hidden_type)
245245
})
246246
.collect();
247247

@@ -878,8 +878,7 @@ struct BorrowCheckContext<'a, 'tcx> {
878878
pub(crate) struct MirTypeckResults<'tcx> {
879879
pub(crate) constraints: MirTypeckRegionConstraints<'tcx>,
880880
pub(crate) universal_region_relations: Frozen<UniversalRegionRelations<'tcx>>,
881-
pub(crate) opaque_type_values:
882-
FxIndexMap<OpaqueTypeKey<'tcx>, (OpaqueHiddenType<'tcx>, OpaqueTyOrigin)>,
881+
pub(crate) opaque_type_values: FxIndexMap<OpaqueTypeKey<'tcx>, OpaqueHiddenType<'tcx>>,
883882
}
884883

885884
/// A collection of region constraints that must be satisfied for the
@@ -1053,15 +1052,28 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
10531052
ConstraintCategory::OpaqueType,
10541053
CustomTypeOp::new(
10551054
|ocx| {
1056-
for (key, hidden_ty) in renumbered_opaques {
1057-
ocx.register_infer_ok_obligations(
1058-
ocx.infcx.register_hidden_type_in_new_solver(
1059-
key,
1060-
param_env,
1061-
hidden_ty.ty,
1062-
)?,
1055+
let mut obligations = Vec::new();
1056+
for (opaque_type_key, hidden_ty) in renumbered_opaques {
1057+
let cause = ObligationCause::dummy();
1058+
ocx.infcx.insert_hidden_type(
1059+
opaque_type_key,
1060+
&cause,
1061+
param_env,
1062+
hidden_ty.ty,
1063+
true,
1064+
&mut obligations,
1065+
)?;
1066+
1067+
ocx.infcx.add_item_bounds_for_hidden_type(
1068+
opaque_type_key,
1069+
cause,
1070+
param_env,
1071+
hidden_ty.ty,
1072+
&mut obligations,
10631073
);
10641074
}
1075+
1076+
ocx.register_obligations(obligations);
10651077
Ok(())
10661078
},
10671079
"register pre-defined opaques",

0 commit comments

Comments
 (0)