split definition and use site hidden tys

This commit is contained in:
lcnr 2025-10-27 13:51:55 +01:00
parent 23c7bad921
commit ad20e5c468
14 changed files with 188 additions and 138 deletions

View file

@ -119,7 +119,7 @@ pub fn provide(providers: &mut Providers) {
fn mir_borrowck(
tcx: TyCtxt<'_>,
def: LocalDefId,
) -> Result<&DefinitionSiteHiddenTypes<'_>, ErrorGuaranteed> {
) -> Result<&FxIndexMap<LocalDefId, ty::DefinitionSiteHiddenType<'_>>, ErrorGuaranteed> {
assert!(!tcx.is_typeck_child(def.to_def_id()));
let (input_body, _) = tcx.mir_promoted(def);
debug!("run query mir_borrowck: {}", tcx.def_path_str(def));
@ -130,7 +130,7 @@ fn mir_borrowck(
Err(guar)
} else if input_body.should_skip() {
debug!("Skipping borrowck because of injected body");
let opaque_types = DefinitionSiteHiddenTypes(Default::default());
let opaque_types = Default::default();
Ok(tcx.arena.alloc(opaque_types))
} else {
let mut root_cx = BorrowCheckRootCtxt::new(tcx, def, None);

View file

@ -8,10 +8,10 @@ use rustc_infer::infer::outlives::env::RegionBoundPairs;
use rustc_infer::infer::{InferCtxt, NllRegionVariableOrigin, OpaqueTypeStorageEntries};
use rustc_infer::traits::ObligationCause;
use rustc_macros::extension;
use rustc_middle::mir::{Body, ConstraintCategory, DefinitionSiteHiddenTypes};
use rustc_middle::mir::{Body, ConstraintCategory};
use rustc_middle::ty::{
self, DefiningScopeKind, EarlyBinder, FallibleTypeFolder, GenericArg, GenericArgsRef,
OpaqueHiddenType, OpaqueTypeKey, Region, RegionVid, Ty, TyCtxt, TypeFoldable,
self, DefiningScopeKind, DefinitionSiteHiddenType, FallibleTypeFolder, GenericArg,
GenericArgsRef, OpaqueHiddenType, OpaqueTypeKey, Region, RegionVid, Ty, TyCtxt, TypeFoldable,
TypeSuperFoldable, TypeVisitableExt, fold_regions,
};
use rustc_mir_dataflow::points::DenseLocationMap;
@ -131,27 +131,26 @@ fn nll_var_to_universal_region<'tcx>(
/// and errors if we end up with distinct hidden types.
fn add_hidden_type<'tcx>(
tcx: TyCtxt<'tcx>,
hidden_types: &mut DefinitionSiteHiddenTypes<'tcx>,
hidden_types: &mut FxIndexMap<LocalDefId, ty::DefinitionSiteHiddenType<'tcx>>,
def_id: LocalDefId,
hidden_ty: OpaqueHiddenType<'tcx>,
hidden_ty: ty::DefinitionSiteHiddenType<'tcx>,
) {
// Sometimes two opaque types are the same only after we remap the generic parameters
// back to the opaque type definition. E.g. we may have `OpaqueType<X, Y>` mapped to
// `(X, Y)` and `OpaqueType<Y, X>` mapped to `(Y, X)`, and those are the same, but we
// only know that once we convert the generic parameters to those of the opaque type.
if let Some(prev) = hidden_types.0.get_mut(&def_id) {
if prev.ty != hidden_ty.ty {
let guar = hidden_ty.ty.error_reported().err().unwrap_or_else(|| {
let (Ok(e) | Err(e)) = prev.build_mismatch_error(&hidden_ty, tcx).map(|d| d.emit());
e
});
prev.ty = Ty::new_error(tcx, guar);
if let Some(prev) = hidden_types.get_mut(&def_id) {
if prev.ty == hidden_ty.ty {
// Pick a better span if there is one.
// FIXME(oli-obk): collect multiple spans for better diagnostics down the road.
prev.span = prev.span.substitute_dummy(hidden_ty.span);
} else {
let (Ok(guar) | Err(guar)) =
prev.build_mismatch_error(&hidden_ty, tcx).map(|d| d.emit());
*prev = ty::DefinitionSiteHiddenType::new_error(tcx, guar);
}
// Pick a better span if there is one.
// FIXME(oli-obk): collect multiple spans for better diagnostics down the road.
prev.span = prev.span.substitute_dummy(hidden_ty.span);
} else {
hidden_types.0.insert(def_id, hidden_ty);
hidden_types.insert(def_id, hidden_ty);
}
}
@ -181,7 +180,7 @@ pub(crate) fn compute_definition_site_hidden_types<'tcx>(
universal_region_relations: &Frozen<UniversalRegionRelations<'tcx>>,
constraints: &MirTypeckRegionConstraints<'tcx>,
location_map: Rc<DenseLocationMap>,
hidden_types: &mut DefinitionSiteHiddenTypes<'tcx>,
hidden_types: &mut FxIndexMap<LocalDefId, ty::DefinitionSiteHiddenType<'tcx>>,
opaque_types: &[(OpaqueTypeKey<'tcx>, OpaqueHiddenType<'tcx>)],
) -> Vec<DeferredOpaqueTypeError<'tcx>> {
let mut errors = Vec::new();
@ -216,7 +215,7 @@ pub(crate) fn compute_definition_site_hidden_types<'tcx>(
#[instrument(level = "debug", skip_all, ret)]
fn collect_defining_uses<'tcx>(
rcx: &mut RegionCtxt<'_, 'tcx>,
hidden_types: &mut DefinitionSiteHiddenTypes<'tcx>,
hidden_types: &mut FxIndexMap<LocalDefId, ty::DefinitionSiteHiddenType<'tcx>>,
opaque_types: &[(OpaqueTypeKey<'tcx>, OpaqueHiddenType<'tcx>)],
errors: &mut Vec<DeferredOpaqueTypeError<'tcx>>,
) -> Vec<DefiningUse<'tcx>> {
@ -240,7 +239,7 @@ fn collect_defining_uses<'tcx>(
infcx.tcx,
hidden_types,
opaque_type_key.def_id,
OpaqueHiddenType::new_error(infcx.tcx, guar),
DefinitionSiteHiddenType::new_error(infcx.tcx, guar),
),
_ => debug!(?non_nll_opaque_type_key, ?err, "ignoring non-defining use"),
}
@ -276,7 +275,7 @@ fn collect_defining_uses<'tcx>(
#[instrument(level = "debug", skip(rcx, hidden_types, defining_uses, errors))]
fn compute_definition_site_hidden_types_from_defining_uses<'tcx>(
rcx: &RegionCtxt<'_, 'tcx>,
hidden_types: &mut DefinitionSiteHiddenTypes<'tcx>,
hidden_types: &mut FxIndexMap<LocalDefId, ty::DefinitionSiteHiddenType<'tcx>>,
defining_uses: &[DefiningUse<'tcx>],
errors: &mut Vec<DeferredOpaqueTypeError<'tcx>>,
) {
@ -310,14 +309,13 @@ fn compute_definition_site_hidden_types_from_defining_uses<'tcx>(
// Now that we mapped the member regions to their final value,
// map the arguments of the opaque type key back to the parameters
// of the opaque type definition.
let ty = infcx
let hidden_type = infcx
.infer_opaque_definition_from_instantiation(opaque_type_key, hidden_type)
.unwrap_or_else(|_| {
Ty::new_error_with_message(
rcx.infcx.tcx,
hidden_type.span,
"deferred invalid opaque type args",
)
let guar = tcx
.dcx()
.span_delayed_bug(hidden_type.span, "deferred invalid opaque type args");
DefinitionSiteHiddenType::new_error(tcx, guar)
});
// Sometimes, when the hidden type is an inference variable, it can happen that
@ -325,7 +323,7 @@ fn compute_definition_site_hidden_types_from_defining_uses<'tcx>(
// usage of the opaque type and we can ignore it. This check is mirrored in typeck's
// writeback.
if !rcx.infcx.tcx.use_typing_mode_borrowck() {
if let ty::Alias(ty::Opaque, alias_ty) = ty.kind()
if let ty::Alias(ty::Opaque, alias_ty) = hidden_type.ty.skip_binder().kind()
&& alias_ty.def_id == opaque_type_key.def_id.to_def_id()
&& alias_ty.args == opaque_type_key.args
{
@ -357,12 +355,7 @@ fn compute_definition_site_hidden_types_from_defining_uses<'tcx>(
},
));
}
add_hidden_type(
tcx,
hidden_types,
opaque_type_key.def_id,
OpaqueHiddenType { span: hidden_type.span, ty },
);
add_hidden_type(tcx, hidden_types, opaque_type_key.def_id, hidden_type);
}
}
@ -495,14 +488,13 @@ pub(crate) fn apply_definition_site_hidden_types<'tcx>(
region_bound_pairs: &RegionBoundPairs<'tcx>,
known_type_outlives_obligations: &[ty::PolyTypeOutlivesPredicate<'tcx>],
constraints: &mut MirTypeckRegionConstraints<'tcx>,
hidden_types: &mut DefinitionSiteHiddenTypes<'tcx>,
hidden_types: &mut FxIndexMap<LocalDefId, ty::DefinitionSiteHiddenType<'tcx>>,
opaque_types: &[(OpaqueTypeKey<'tcx>, OpaqueHiddenType<'tcx>)],
) -> Vec<DeferredOpaqueTypeError<'tcx>> {
let tcx = infcx.tcx;
let mut errors = Vec::new();
for &(key, hidden_type) in opaque_types {
let Some(expected) = hidden_types.0.get(&key.def_id).map(|ty| EarlyBinder::bind(*ty))
else {
let Some(expected) = hidden_types.get(&key.def_id) else {
if !tcx.use_typing_mode_borrowck() {
if let ty::Alias(ty::Opaque, alias_ty) = hidden_type.ty.kind()
&& alias_ty.def_id == key.def_id.to_def_id()
@ -521,20 +513,26 @@ pub(crate) fn apply_definition_site_hidden_types<'tcx>(
hidden_type.span,
"non-defining use in the defining scope with no defining uses",
);
add_hidden_type(tcx, hidden_types, key.def_id, OpaqueHiddenType::new_error(tcx, guar));
add_hidden_type(
tcx,
hidden_types,
key.def_id,
DefinitionSiteHiddenType::new_error(tcx, guar),
);
continue;
};
// We erase all non-member region of the opaque and need to treat these as existentials.
let expected = ty::fold_regions(tcx, expected.instantiate(tcx, key.args), |re, _dbi| {
match re.kind() {
ty::ReErased => infcx.next_nll_region_var(
NllRegionVariableOrigin::Existential { name: None },
|| crate::RegionCtxt::Existential(None),
),
_ => re,
}
});
let expected_ty =
ty::fold_regions(tcx, expected.ty.instantiate(tcx, key.args), |re, _dbi| {
match re.kind() {
ty::ReErased => infcx.next_nll_region_var(
NllRegionVariableOrigin::Existential { name: None },
|| crate::RegionCtxt::Existential(None),
),
_ => re,
}
});
// We now simply equate the expected with the actual hidden type.
let locations = Locations::All(hidden_type.span);
@ -555,13 +553,18 @@ pub(crate) fn apply_definition_site_hidden_types<'tcx>(
);
// We need to normalize both types in the old solver before equatingt them.
let actual_ty = ocx.normalize(&cause, infcx.param_env, hidden_type.ty);
let expected_ty = ocx.normalize(&cause, infcx.param_env, expected.ty);
let expected_ty = ocx.normalize(&cause, infcx.param_env, expected_ty);
ocx.eq(&cause, infcx.param_env, actual_ty, expected_ty).map_err(|_| NoSolution)
},
"equating opaque types",
),
) {
add_hidden_type(tcx, hidden_types, key.def_id, OpaqueHiddenType::new_error(tcx, guar));
add_hidden_type(
tcx,
hidden_types,
key.def_id,
DefinitionSiteHiddenType::new_error(tcx, guar),
);
}
}
errors
@ -677,7 +680,7 @@ impl<'tcx> InferCtxt<'tcx> {
&self,
opaque_type_key: OpaqueTypeKey<'tcx>,
instantiated_ty: OpaqueHiddenType<'tcx>,
) -> Result<Ty<'tcx>, NonDefiningUseReason<'tcx>> {
) -> Result<ty::DefinitionSiteHiddenType<'tcx>, NonDefiningUseReason<'tcx>> {
opaque_type_has_defining_use_args(
self,
opaque_type_key,
@ -685,15 +688,12 @@ impl<'tcx> InferCtxt<'tcx> {
DefiningScopeKind::MirBorrowck,
)?;
let definition_ty = instantiated_ty
.remap_generic_params_to_declaration_params(
opaque_type_key,
self.tcx,
DefiningScopeKind::MirBorrowck,
)
.ty;
definition_ty.error_reported()?;
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)
}
}

View file

@ -17,9 +17,8 @@ use crate::region_infer::opaque_types::{
};
use crate::type_check::{Locations, constraint_conversion};
use crate::{
ClosureRegionRequirements, CollectRegionConstraintsResult, DefinitionSiteHiddenTypes,
PropagatedBorrowCheckResults, borrowck_check_region_constraints,
borrowck_collect_region_constraints,
ClosureRegionRequirements, CollectRegionConstraintsResult, PropagatedBorrowCheckResults,
borrowck_check_region_constraints, borrowck_collect_region_constraints,
};
/// The shared context used by both the root as well as all its nested
@ -27,7 +26,7 @@ use crate::{
pub(super) struct BorrowCheckRootCtxt<'tcx> {
pub tcx: TyCtxt<'tcx>,
root_def_id: LocalDefId,
hidden_types: DefinitionSiteHiddenTypes<'tcx>,
hidden_types: FxIndexMap<LocalDefId, ty::DefinitionSiteHiddenType<'tcx>>,
/// The region constraints computed by [borrowck_collect_region_constraints]. This uses
/// an [FxIndexMap] to guarantee that iterating over it visits nested bodies before
/// their parents.
@ -72,7 +71,10 @@ impl<'tcx> BorrowCheckRootCtxt<'tcx> {
&self.propagated_borrowck_results[&nested_body_def_id].used_mut_upvars
}
pub(super) fn finalize(self) -> Result<&'tcx DefinitionSiteHiddenTypes<'tcx>, ErrorGuaranteed> {
pub(super) fn finalize(
self,
) -> Result<&'tcx FxIndexMap<LocalDefId, ty::DefinitionSiteHiddenType<'tcx>>, ErrorGuaranteed>
{
if let Some(guar) = self.tainted_by_errors {
Err(guar)
} else {

View file

@ -430,7 +430,7 @@ fn best_definition_site_of_opaque<'tcx>(
.tcx
.mir_borrowck(item_def_id)
.ok()
.and_then(|opaque_types| opaque_types.0.get(&self.opaque_def_id))
.and_then(|opaque_types| opaque_types.get(&self.opaque_def_id))
{
ControlFlow::Break((hidden_ty.span, item_def_id))
} else {

View file

@ -345,7 +345,7 @@ pub(super) fn type_of_opaque(
def_id: DefId,
) -> Result<ty::EarlyBinder<'_, Ty<'_>>, CyclePlaceholder> {
if let Some(def_id) = def_id.as_local() {
Ok(ty::EarlyBinder::bind(match tcx.hir_node_by_def_id(def_id).expect_opaque_ty().origin {
Ok(match tcx.hir_node_by_def_id(def_id).expect_opaque_ty().origin {
hir::OpaqueTyOrigin::TyAlias { in_assoc_ty: false, .. } => {
opaque::find_opaque_ty_constraints_for_tait(
tcx,
@ -378,7 +378,7 @@ pub(super) fn type_of_opaque(
DefiningScopeKind::MirBorrowck,
)
}
}))
})
} else {
// Foreign opaque type will go through the foreign provider
// and load the type from metadata.
@ -390,7 +390,7 @@ pub(super) fn type_of_opaque_hir_typeck(
tcx: TyCtxt<'_>,
def_id: LocalDefId,
) -> ty::EarlyBinder<'_, Ty<'_>> {
ty::EarlyBinder::bind(match tcx.hir_node_by_def_id(def_id).expect_opaque_ty().origin {
match tcx.hir_node_by_def_id(def_id).expect_opaque_ty().origin {
hir::OpaqueTyOrigin::TyAlias { in_assoc_ty: false, .. } => {
opaque::find_opaque_ty_constraints_for_tait(tcx, def_id, DefiningScopeKind::HirTypeck)
}
@ -419,7 +419,7 @@ pub(super) fn type_of_opaque_hir_typeck(
DefiningScopeKind::HirTypeck,
)
}
})
}
}
fn infer_placeholder_type<'tcx>(

View file

@ -3,7 +3,7 @@ use rustc_hir::def_id::LocalDefId;
use rustc_hir::{self as hir, Expr, ImplItem, Item, Node, TraitItem, def, intravisit};
use rustc_middle::bug;
use rustc_middle::hir::nested_filter;
use rustc_middle::ty::{self, DefiningScopeKind, Ty, TyCtxt, TypeVisitableExt};
use rustc_middle::ty::{self, DefiningScopeKind, EarlyBinder, Ty, TyCtxt, TypeVisitableExt};
use rustc_trait_selection::opaque_types::report_item_does_not_constrain_error;
use tracing::{debug, instrument, trace};
@ -16,7 +16,7 @@ pub(super) fn find_opaque_ty_constraints_for_impl_trait_in_assoc_type(
tcx: TyCtxt<'_>,
def_id: LocalDefId,
opaque_types_from: DefiningScopeKind,
) -> Ty<'_> {
) -> EarlyBinder<'_, Ty<'_>> {
let mut parent_def_id = def_id;
while tcx.def_kind(parent_def_id) == def::DefKind::OpaqueTy {
// Account for `type Alias = impl Trait<Foo = impl Trait>;` (#116031)
@ -49,7 +49,7 @@ pub(super) fn find_opaque_ty_constraints_for_impl_trait_in_assoc_type(
name: tcx.item_ident(parent_def_id.to_def_id()),
what: "impl",
});
Ty::new_error(tcx, guar)
EarlyBinder::bind(Ty::new_error(tcx, guar))
}
}
@ -76,7 +76,7 @@ pub(super) fn find_opaque_ty_constraints_for_tait(
tcx: TyCtxt<'_>,
def_id: LocalDefId,
opaque_types_from: DefiningScopeKind,
) -> Ty<'_> {
) -> EarlyBinder<'_, Ty<'_>> {
let mut locator = TaitConstraintLocator { def_id, tcx, found: None, opaque_types_from };
tcx.hir_walk_toplevel_module(&mut locator);
@ -94,7 +94,7 @@ pub(super) fn find_opaque_ty_constraints_for_tait(
name: tcx.item_ident(parent_def_id.to_def_id()),
what: "crate",
});
Ty::new_error(tcx, guar)
EarlyBinder::bind(Ty::new_error(tcx, guar))
}
}
@ -109,18 +109,18 @@ struct TaitConstraintLocator<'tcx> {
/// with the first type that we find, and then later types are
/// checked against it (we also carry the span of that first
/// type).
found: Option<ty::OpaqueHiddenType<'tcx>>,
found: Option<ty::DefinitionSiteHiddenType<'tcx>>,
opaque_types_from: DefiningScopeKind,
}
impl<'tcx> TaitConstraintLocator<'tcx> {
fn insert_found(&mut self, hidden_ty: ty::OpaqueHiddenType<'tcx>) {
fn insert_found(&mut self, hidden_ty: ty::DefinitionSiteHiddenType<'tcx>) {
if let Some(prev) = &mut self.found {
if hidden_ty.ty != prev.ty {
let (Ok(guar) | Err(guar)) =
prev.build_mismatch_error(&hidden_ty, self.tcx).map(|d| d.emit());
prev.ty = Ty::new_error(self.tcx, guar);
*prev = ty::DefinitionSiteHiddenType::new_error(self.tcx, guar);
}
} else {
self.found = Some(hidden_ty);
@ -133,7 +133,7 @@ impl<'tcx> TaitConstraintLocator<'tcx> {
// with the new solver.
assert!(!self.tcx.next_trait_solver_globally());
let guar = report_item_does_not_constrain_error(self.tcx, item_def_id, self.def_id, None);
self.insert_found(ty::OpaqueHiddenType::new_error(self.tcx, guar));
self.insert_found(ty::DefinitionSiteHiddenType::new_error(self.tcx, guar));
}
#[instrument(skip(self), level = "debug")]
@ -168,7 +168,7 @@ impl<'tcx> TaitConstraintLocator<'tcx> {
hir_sig.decl.output.span(),
"inferring return types and opaque types do not mix well",
);
self.found = Some(ty::OpaqueHiddenType::new_error(tcx, guar));
self.found = Some(ty::DefinitionSiteHiddenType::new_error(tcx, guar));
return;
}
@ -176,7 +176,7 @@ impl<'tcx> TaitConstraintLocator<'tcx> {
DefiningScopeKind::HirTypeck => {
let tables = tcx.typeck(item_def_id);
if let Some(guar) = tables.tainted_by_errors {
self.insert_found(ty::OpaqueHiddenType::new_error(tcx, guar));
self.insert_found(ty::DefinitionSiteHiddenType::new_error(tcx, guar));
} else if let Some(&hidden_type) = tables.hidden_types.get(&self.def_id) {
self.insert_found(hidden_type);
} else {
@ -184,17 +184,15 @@ impl<'tcx> TaitConstraintLocator<'tcx> {
}
}
DefiningScopeKind::MirBorrowck => match tcx.mir_borrowck(item_def_id) {
Err(guar) => self.insert_found(ty::OpaqueHiddenType::new_error(tcx, guar)),
Err(guar) => self.insert_found(ty::DefinitionSiteHiddenType::new_error(tcx, guar)),
Ok(hidden_types) => {
if let Some(&hidden_type) = hidden_types.0.get(&self.def_id) {
if let Some(&hidden_type) = hidden_types.get(&self.def_id) {
debug!(?hidden_type, "found constraint");
self.insert_found(hidden_type);
} else if let Err(guar) = tcx
.type_of_opaque_hir_typeck(self.def_id)
.instantiate_identity()
.error_reported()
} else if let Err(guar) =
tcx.type_of_opaque_hir_typeck(self.def_id).skip_binder().error_reported()
{
self.insert_found(ty::OpaqueHiddenType::new_error(tcx, guar));
self.insert_found(ty::DefinitionSiteHiddenType::new_error(tcx, guar));
} else {
self.non_defining_use_in_defining_scope(item_def_id);
}
@ -241,7 +239,7 @@ pub(super) fn find_opaque_ty_constraints_for_rpit<'tcx>(
def_id: LocalDefId,
owner_def_id: LocalDefId,
opaque_types_from: DefiningScopeKind,
) -> Ty<'tcx> {
) -> EarlyBinder<'tcx, Ty<'tcx>> {
// When an opaque type is stranded, its hidden type cannot be inferred
// so we should not continue.
if !tcx.opaque_types_defined_by(owner_def_id).contains(&def_id) {
@ -249,14 +247,14 @@ pub(super) fn find_opaque_ty_constraints_for_rpit<'tcx>(
let guar = tcx
.dcx()
.span_delayed_bug(opaque_type_span, "cannot infer type for stranded opaque type");
return Ty::new_error(tcx, guar);
return EarlyBinder::bind(Ty::new_error(tcx, guar));
}
match opaque_types_from {
DefiningScopeKind::HirTypeck => {
let tables = tcx.typeck(owner_def_id);
if let Some(guar) = tables.tainted_by_errors {
Ty::new_error(tcx, guar)
EarlyBinder::bind(Ty::new_error(tcx, guar))
} else if let Some(hidden_ty) = tables.hidden_types.get(&def_id) {
hidden_ty.ty
} else {
@ -267,24 +265,24 @@ pub(super) fn find_opaque_ty_constraints_for_rpit<'tcx>(
// so we can just make the hidden type be `!`.
// For backwards compatibility reasons, we fall back to
// `()` until we the diverging default is changed.
Ty::new_diverging_default(tcx)
EarlyBinder::bind(Ty::new_diverging_default(tcx))
}
}
DefiningScopeKind::MirBorrowck => match tcx.mir_borrowck(owner_def_id) {
Ok(hidden_types) => {
if let Some(hidden_ty) = hidden_types.0.get(&def_id) {
if let Some(hidden_ty) = hidden_types.get(&def_id) {
hidden_ty.ty
} else {
let hir_ty = tcx.type_of_opaque_hir_typeck(def_id).instantiate_identity();
if let Err(guar) = hir_ty.error_reported() {
Ty::new_error(tcx, guar)
let hir_ty = tcx.type_of_opaque_hir_typeck(def_id);
if let Err(guar) = hir_ty.skip_binder().error_reported() {
EarlyBinder::bind(Ty::new_error(tcx, guar))
} else {
assert!(!tcx.next_trait_solver_globally());
hir_ty
}
}
}
Err(guar) => Ty::new_error(tcx, guar),
Err(guar) => EarlyBinder::bind(Ty::new_error(tcx, guar)),
},
}
}

View file

@ -1,8 +1,8 @@
use rustc_hir::def::DefKind;
use rustc_infer::traits::ObligationCause;
use rustc_middle::ty::{
self, DefiningScopeKind, EarlyBinder, OpaqueHiddenType, OpaqueTypeKey, TypeVisitableExt,
TypingMode,
self, DefiningScopeKind, DefinitionSiteHiddenType, OpaqueHiddenType, OpaqueTypeKey,
TypeVisitableExt, TypingMode,
};
use rustc_trait_selection::error_reporting::infer::need_type_info::TypeAnnotationNeeded;
use rustc_trait_selection::opaque_types::{
@ -59,7 +59,7 @@ enum UsageKind<'tcx> {
None,
NonDefiningUse(OpaqueTypeKey<'tcx>, OpaqueHiddenType<'tcx>),
UnconstrainedHiddenType(OpaqueHiddenType<'tcx>),
HasDefiningUse(OpaqueHiddenType<'tcx>),
HasDefiningUse(DefinitionSiteHiddenType<'tcx>),
}
impl<'tcx> UsageKind<'tcx> {
@ -131,7 +131,7 @@ impl<'tcx> FnCtxt<'_, 'tcx> {
continue;
}
let expected = EarlyBinder::bind(ty.ty).instantiate(tcx, opaque_type_key.args);
let expected = ty.ty.instantiate(tcx, opaque_type_key.args);
self.demand_eqtype(hidden_type.span, expected, hidden_type.ty);
}
@ -191,7 +191,7 @@ impl<'tcx> FnCtxt<'_, 'tcx> {
self.typeck_results
.borrow_mut()
.hidden_types
.insert(def_id, OpaqueHiddenType::new_error(tcx, guar));
.insert(def_id, DefinitionSiteHiddenType::new_error(tcx, guar));
self.set_tainted_by_errors(guar);
}
}
@ -210,7 +210,9 @@ impl<'tcx> FnCtxt<'_, 'tcx> {
) {
match err {
NonDefiningUseReason::Tainted(guar) => {
return UsageKind::HasDefiningUse(OpaqueHiddenType::new_error(self.tcx, guar));
return UsageKind::HasDefiningUse(DefinitionSiteHiddenType::new_error(
self.tcx, guar,
));
}
_ => return UsageKind::NonDefiningUse(opaque_type_key, hidden_type),
};

View file

@ -21,7 +21,7 @@ use rustc_infer::traits::solve::Goal;
use rustc_middle::traits::ObligationCause;
use rustc_middle::ty::adjustment::{Adjust, Adjustment, PointerCoercion};
use rustc_middle::ty::{
self, DefiningScopeKind, OpaqueHiddenType, Ty, TyCtxt, TypeFoldable, TypeFolder,
self, DefiningScopeKind, DefinitionSiteHiddenType, Ty, TyCtxt, TypeFoldable, TypeFolder,
TypeSuperFoldable, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor,
fold_regions,
};
@ -550,10 +550,6 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
fn visit_opaque_types_next(&mut self) {
let mut fcx_typeck_results = self.fcx.typeck_results.borrow_mut();
assert_eq!(fcx_typeck_results.hir_owner, self.typeck_results.hir_owner);
for hidden_ty in fcx_typeck_results.hidden_types.values() {
assert!(!hidden_ty.has_infer());
}
assert_eq!(self.typeck_results.hidden_types.len(), 0);
self.typeck_results.hidden_types = mem::take(&mut fcx_typeck_results.hidden_types);
}
@ -589,7 +585,7 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
) {
self.typeck_results.hidden_types.insert(
opaque_type_key.def_id,
ty::OpaqueHiddenType::new_error(tcx, err.report(self.fcx)),
ty::DefinitionSiteHiddenType::new_error(tcx, err.report(self.fcx)),
);
}
@ -603,15 +599,16 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
self.typeck_results.hidden_types.insert(opaque_type_key.def_id, hidden_type)
{
let entry =
&mut self.typeck_results.hidden_types.get_mut(&opaque_type_key.def_id).unwrap();
self.typeck_results.hidden_types.get_mut(&opaque_type_key.def_id).unwrap();
if prev.ty != hidden_type.ty {
if let Some(guar) = self.typeck_results.tainted_by_errors {
entry.ty = Ty::new_error(tcx, guar);
let guar = if let Some(guar) = self.typeck_results.tainted_by_errors {
guar
} else {
let (Ok(guar) | Err(guar)) =
prev.build_mismatch_error(&hidden_type, tcx).map(|d| d.emit());
entry.ty = Ty::new_error(tcx, guar);
}
guar
};
*entry = DefinitionSiteHiddenType::new_error(tcx, guar);
}
// Pick a better span if there is one.
@ -627,6 +624,7 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
.filter(|&(&def_id, hidden_ty)| {
hidden_ty
.ty
.instantiate_identity()
.visit_with(&mut HasRecursiveOpaque {
def_id,
seen: Default::default(),
@ -646,7 +644,7 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
.emit();
self.typeck_results
.hidden_types
.insert(def_id, OpaqueHiddenType { span, ty: Ty::new_error(tcx, guar) });
.insert(def_id, DefinitionSiteHiddenType::new_error(tcx, guar));
}
}
@ -1045,7 +1043,7 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for EagerlyNormalizeConsts<'tcx> {
struct HasRecursiveOpaque<'a, 'tcx> {
def_id: LocalDefId,
seen: FxHashSet<LocalDefId>,
opaques: &'a FxIndexMap<LocalDefId, ty::OpaqueHiddenType<'tcx>>,
opaques: &'a FxIndexMap<LocalDefId, ty::DefinitionSiteHiddenType<'tcx>>,
tcx: TyCtxt<'tcx>,
}
@ -1063,9 +1061,7 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for HasRecursiveOpaque<'_, 'tcx> {
if self.seen.insert(def_id)
&& let Some(hidden_ty) = self.opaques.get(&def_id)
{
ty::EarlyBinder::bind(hidden_ty.ty)
.instantiate(self.tcx, alias_ty.args)
.visit_with(self)?;
hidden_ty.ty.instantiate(self.tcx, alias_ty.args).visit_with(self)?;
}
}

View file

@ -27,7 +27,10 @@ macro_rules! arena_types {
rustc_middle::mir::Body<'tcx>
>,
[decode] typeck_results: rustc_middle::ty::TypeckResults<'tcx>,
[decode] borrowck_result: rustc_middle::mir::DefinitionSiteHiddenTypes<'tcx>,
[decode] borrowck_result: rustc_data_structures::fx::FxIndexMap<
rustc_hir::def_id::LocalDefId,
rustc_middle::ty::DefinitionSiteHiddenType<'tcx>,
>,
[] resolver: rustc_data_structures::steal::Steal<(
rustc_middle::ty::ResolverAstLowering,
std::sync::Arc<rustc_ast::Crate>,

View file

@ -3,16 +3,14 @@
use std::fmt::{self, Debug};
use rustc_abi::{FieldIdx, VariantIdx};
use rustc_data_structures::fx::FxIndexMap;
use rustc_errors::ErrorGuaranteed;
use rustc_hir::def_id::LocalDefId;
use rustc_index::IndexVec;
use rustc_index::bit_set::BitMatrix;
use rustc_macros::{HashStable, TyDecodable, TyEncodable, TypeFoldable, TypeVisitable};
use rustc_span::{Span, Symbol};
use super::{ConstValue, SourceInfo};
use crate::ty::{self, CoroutineArgsExt, OpaqueHiddenType, Ty};
use crate::ty::{self, CoroutineArgsExt, Ty};
rustc_index::newtype_index! {
#[derive(HashStable)]
@ -84,11 +82,6 @@ impl Debug for CoroutineLayout<'_> {
}
}
/// All the opaque types that have had their hidden type fully computed.
/// Unlike the value in `TypeckResults`, this has unerased regions.
#[derive(Default, Debug, TyEncodable, TyDecodable, HashStable)]
pub struct DefinitionSiteHiddenTypes<'tcx>(pub FxIndexMap<LocalDefId, OpaqueHiddenType<'tcx>>);
/// The result of the `mir_const_qualif` query.
///
/// Each field (except `tainted_by_errors`) corresponds to an implementer of the `Qualif` trait in

View file

@ -1244,7 +1244,10 @@ rustc_queries! {
/// Borrow-checks the given typeck root, e.g. functions, const/static items,
/// and its children, e.g. closures, inline consts.
query mir_borrowck(key: LocalDefId) -> Result<&'tcx mir::DefinitionSiteHiddenTypes<'tcx>, ErrorGuaranteed> {
query mir_borrowck(key: LocalDefId) -> Result<
&'tcx FxIndexMap<LocalDefId, ty::DefinitionSiteHiddenType<'tcx>>,
ErrorGuaranteed
> {
desc { |tcx| "borrow-checking `{}`", tcx.def_path_str(key) }
}

View file

@ -798,7 +798,7 @@ impl<'tcx> OpaqueHiddenType<'tcx> {
opaque_type_key: OpaqueTypeKey<'tcx>,
tcx: TyCtxt<'tcx>,
defining_scope_kind: DefiningScopeKind,
) -> Self {
) -> DefinitionSiteHiddenType<'tcx> {
let OpaqueTypeKey { def_id, args } = opaque_type_key;
// Use args to build up a reverse map from regions to their
@ -821,15 +821,68 @@ impl<'tcx> OpaqueHiddenType<'tcx> {
//
// We erase regions when doing this during HIR typeck. We manually use `fold_regions`
// here as we do not want to anonymize bound variables.
let this = match defining_scope_kind {
DefiningScopeKind::HirTypeck => fold_regions(tcx, self, |_, _| tcx.lifetimes.re_erased),
DefiningScopeKind::MirBorrowck => self,
let ty = match defining_scope_kind {
DefiningScopeKind::HirTypeck => {
fold_regions(tcx, self.ty, |_, _| tcx.lifetimes.re_erased)
}
DefiningScopeKind::MirBorrowck => self.ty,
};
let result = this.fold_with(&mut opaque_types::ReverseMapper::new(tcx, map, self.span));
let result_ty = ty.fold_with(&mut opaque_types::ReverseMapper::new(tcx, map, self.span));
if cfg!(debug_assertions) && matches!(defining_scope_kind, DefiningScopeKind::HirTypeck) {
assert_eq!(result.ty, fold_regions(tcx, result.ty, |_, _| tcx.lifetimes.re_erased));
assert_eq!(result_ty, fold_regions(tcx, result_ty, |_, _| tcx.lifetimes.re_erased));
}
result
DefinitionSiteHiddenType { span: self.span, ty: ty::EarlyBinder::bind(result_ty) }
}
}
#[derive(Copy, Clone, Debug, HashStable, TyEncodable, TyDecodable)]
pub struct DefinitionSiteHiddenType<'tcx> {
/// The span of the definition of the opaque type. So for example:
///
/// ```ignore (incomplete snippet)
/// type Foo = impl Baz;
/// fn bar() -> Foo {
/// // ^^^ This is the span we are looking for!
/// }
/// ```
///
/// In cases where the fn returns `(impl Trait, impl Trait)` or
/// other such combinations, the result is currently
/// over-approximated, but better than nothing.
pub span: Span,
/// The final type of the opaque.
pub ty: ty::EarlyBinder<'tcx, Ty<'tcx>>,
}
impl<'tcx> DefinitionSiteHiddenType<'tcx> {
pub fn new_error(tcx: TyCtxt<'tcx>, guar: ErrorGuaranteed) -> DefinitionSiteHiddenType<'tcx> {
DefinitionSiteHiddenType {
span: DUMMY_SP,
ty: ty::EarlyBinder::bind(Ty::new_error(tcx, guar)),
}
}
pub fn build_mismatch_error(
&self,
other: &Self,
tcx: TyCtxt<'tcx>,
) -> Result<Diag<'tcx>, ErrorGuaranteed> {
let self_ty = self.ty.instantiate_identity();
let other_ty = other.ty.instantiate_identity();
(self_ty, other_ty).error_reported()?;
// Found different concrete types for the opaque type.
let sub_diag = if self.span == other.span {
TypeMismatchReason::ConflictType { span: self.span }
} else {
TypeMismatchReason::PreviousUse { span: self.span }
};
Ok(tcx.dcx().create_err(OpaqueHiddenTypeMismatch {
self_ty,
other_ty,
other_span: other.span,
sub: sub_diag,
}))
}
}

View file

@ -167,7 +167,7 @@ pub struct TypeckResults<'tcx> {
/// We also store the type here, so that the compiler can use it as a hint
/// for figuring out hidden types, even if they are only set in dead code
/// (which doesn't show up in MIR).
pub hidden_types: FxIndexMap<LocalDefId, ty::OpaqueHiddenType<'tcx>>,
pub hidden_types: FxIndexMap<LocalDefId, ty::DefinitionSiteHiddenType<'tcx>>,
/// Tracks the minimum captures required for a closure;
/// see `MinCaptureInformationMap` for more details.

View file

@ -148,7 +148,7 @@ impl<'p, 'tcx: 'p> RustcPatCtxt<'p, 'tcx> {
self.typeck_results
.hidden_types
.get(&key.def_id)
.map(|x| ty::EarlyBinder::bind(x.ty).instantiate(self.tcx, key.args))
.map(|x| x.ty.instantiate(self.tcx, key.args))
}
// This can take a non-revealed `Ty` because it reveals opaques itself.
pub fn is_uninhabited(&self, ty: Ty<'tcx>) -> bool {