1
Fork 0

Check that RPITs are compatible with the opaques inferred during HIR typeck too

This commit is contained in:
Michael Goulet 2023-05-31 17:45:45 +00:00
parent 3d09b990d7
commit df1c1afdaf
7 changed files with 46 additions and 155 deletions

View file

@ -1,3 +1,4 @@
use rustc_errors::StashKey;
use rustc_hir::def_id::LocalDefId;
use rustc_hir::intravisit::{self, Visitor};
use rustc_hir::{self as hir, Expr, ImplItem, Item, Node, TraitItem};
@ -210,12 +211,40 @@ pub(super) fn find_opaque_ty_constraints_for_rpit<'tcx>(
def_id: LocalDefId,
owner_def_id: LocalDefId,
) -> Ty<'_> {
let concrete = tcx.mir_borrowck(owner_def_id).concrete_opaque_types.get(&def_id).copied();
let tables = tcx.typeck(owner_def_id);
if let Some(concrete) = concrete {
// Check that all of the opaques we inferred during HIR are compatible.
// FIXME: We explicitly don't check that the types inferred during HIR
// typeck are compatible with the one that we infer during borrowck,
// because that one actually sometimes has consts evaluated eagerly so
// using strict type equality will fail.
let mut hir_opaque_ty: Option<ty::OpaqueHiddenType<'tcx>> = None;
if tables.tainted_by_errors.is_none() {
for (&opaque_type_key, &hidden_type) in &tables.concrete_opaque_types {
if opaque_type_key.def_id != def_id {
continue;
}
let concrete_type = tcx.erase_regions(
hidden_type.remap_generic_params_to_declaration_params(opaque_type_key, tcx, true),
);
if let Some(prev) = &mut hir_opaque_ty {
if concrete_type.ty != prev.ty && !(concrete_type, prev.ty).references_error() {
prev.report_mismatch(&concrete_type, def_id, tcx).stash(
tcx.def_span(opaque_type_key.def_id),
StashKey::OpaqueHiddenTypeMismatch,
);
}
} else {
hir_opaque_ty = Some(concrete_type);
}
}
}
let mir_opaque_ty = tcx.mir_borrowck(owner_def_id).concrete_opaque_types.get(&def_id).copied();
if let Some(mir_opaque_ty) = mir_opaque_ty {
let scope = tcx.hir().local_def_id_to_hir_id(owner_def_id);
debug!(?scope);
let mut locator = RpitConstraintChecker { def_id, tcx, found: concrete };
let mut locator = RpitConstraintChecker { def_id, tcx, found: mir_opaque_ty };
match tcx.hir().get(scope) {
Node::Item(it) => intravisit::walk_item(&mut locator, it),
@ -224,38 +253,16 @@ pub(super) fn find_opaque_ty_constraints_for_rpit<'tcx>(
other => bug!("{:?} is not a valid scope for an opaque type item", other),
}
concrete.ty
mir_opaque_ty.ty
} else {
let tables = tcx.typeck(owner_def_id);
if let Some(guar) = tables.tainted_by_errors {
// Some error in the
// owner fn prevented us from populating
// Some error in the owner fn prevented us from populating
// the `concrete_opaque_types` table.
tcx.ty_error(guar)
} else {
// Fall back to the RPIT we inferred during HIR typeck
let mut opaque_ty: Option<ty::OpaqueHiddenType<'tcx>> = None;
for (&opaque_type_key, &hidden_type) in &tables.concrete_opaque_types {
if opaque_type_key.def_id != def_id {
continue;
}
let concrete_type =
tcx.erase_regions(hidden_type.remap_generic_params_to_declaration_params(
opaque_type_key,
tcx,
true,
));
if let Some(prev) = &mut opaque_ty {
if concrete_type.ty != prev.ty && !(concrete_type, prev.ty).references_error() {
prev.report_mismatch(&concrete_type, def_id, tcx).emit();
}
} else {
opaque_ty = Some(concrete_type);
}
}
if let Some(opaque_ty) = opaque_ty {
opaque_ty.ty
if let Some(hir_opaque_ty) = hir_opaque_ty {
hir_opaque_ty.ty
} else {
// We failed to resolve the opaque type or it
// resolves to itself. We interpret this as the