From cd5dc484f5e8901e4b520c2df71dac6833b434da Mon Sep 17 00:00:00 2001 From: lcnr Date: Mon, 27 Oct 2025 13:51:55 +0100 Subject: [PATCH] split definition and use site hidden tys --- compiler/rustc_borrowck/src/lib.rs | 4 +- .../src/region_infer/opaque_types/mod.rs | 116 +++++++++--------- compiler/rustc_borrowck/src/root_cx.rs | 12 +- .../rustc_hir_analysis/src/check/check.rs | 2 +- .../rustc_hir_analysis/src/collect/type_of.rs | 8 +- .../src/collect/type_of/opaque.rs | 50 ++++---- compiler/rustc_hir_typeck/src/opaque_types.rs | 14 ++- compiler/rustc_hir_typeck/src/writeback.rs | 28 ++--- compiler/rustc_middle/src/arena.rs | 5 +- compiler/rustc_middle/src/mir/query.rs | 9 +- compiler/rustc_middle/src/query/mod.rs | 5 +- compiler/rustc_middle/src/ty/mod.rs | 67 ++++++++-- .../rustc_middle/src/ty/typeck_results.rs | 2 +- compiler/rustc_pattern_analysis/src/rustc.rs | 2 +- 14 files changed, 187 insertions(+), 137 deletions(-) diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs index a57689a45b67b..054af132a52b7 100644 --- a/compiler/rustc_borrowck/src/lib.rs +++ b/compiler/rustc_borrowck/src/lib.rs @@ -119,7 +119,7 @@ pub fn provide(providers: &mut Providers) { fn mir_borrowck( tcx: TyCtxt<'_>, def: LocalDefId, -) -> Result<&DefinitionSiteHiddenTypes<'_>, ErrorGuaranteed> { +) -> Result<&FxIndexMap>, 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); diff --git a/compiler/rustc_borrowck/src/region_infer/opaque_types/mod.rs b/compiler/rustc_borrowck/src/region_infer/opaque_types/mod.rs index 67d1d44b1e1f8..2294c6381625a 100644 --- a/compiler/rustc_borrowck/src/region_infer/opaque_types/mod.rs +++ b/compiler/rustc_borrowck/src/region_infer/opaque_types/mod.rs @@ -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>, 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` mapped to // `(X, Y)` and `OpaqueType` 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>, constraints: &MirTypeckRegionConstraints<'tcx>, location_map: Rc, - hidden_types: &mut DefinitionSiteHiddenTypes<'tcx>, + hidden_types: &mut FxIndexMap>, opaque_types: &[(OpaqueTypeKey<'tcx>, OpaqueHiddenType<'tcx>)], ) -> Vec> { 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>, opaque_types: &[(OpaqueTypeKey<'tcx>, OpaqueHiddenType<'tcx>)], errors: &mut Vec>, ) -> Vec> { @@ -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>, defining_uses: &[DefiningUse<'tcx>], errors: &mut Vec>, ) { @@ -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>, opaque_types: &[(OpaqueTypeKey<'tcx>, OpaqueHiddenType<'tcx>)], ) -> Vec> { 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, NonDefiningUseReason<'tcx>> { + ) -> Result, 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) } } diff --git a/compiler/rustc_borrowck/src/root_cx.rs b/compiler/rustc_borrowck/src/root_cx.rs index 21c11e1287353..c3ff8cba94722 100644 --- a/compiler/rustc_borrowck/src/root_cx.rs +++ b/compiler/rustc_borrowck/src/root_cx.rs @@ -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>, /// 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>, ErrorGuaranteed> + { if let Some(guar) = self.tainted_by_errors { Err(guar) } else { diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs index 95b47c8aba671..1e10818bb38d3 100644 --- a/compiler/rustc_hir_analysis/src/check/check.rs +++ b/compiler/rustc_hir_analysis/src/check/check.rs @@ -432,7 +432,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 { diff --git a/compiler/rustc_hir_analysis/src/collect/type_of.rs b/compiler/rustc_hir_analysis/src/collect/type_of.rs index 8cbf17162e321..e93725e136137 100644 --- a/compiler/rustc_hir_analysis/src/collect/type_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/type_of.rs @@ -345,7 +345,7 @@ pub(super) fn type_of_opaque( def_id: DefId, ) -> Result>, 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>( diff --git a/compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs b/compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs index a02990fe4abaf..298ab3004e501 100644 --- a/compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs +++ b/compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs @@ -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;` (#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>, + found: Option>, 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,12 +239,12 @@ 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>> { 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 { @@ -257,24 +255,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)), }, } } diff --git a/compiler/rustc_hir_typeck/src/opaque_types.rs b/compiler/rustc_hir_typeck/src/opaque_types.rs index 05b5b1a8af803..b779f8b8317f9 100644 --- a/compiler/rustc_hir_typeck/src/opaque_types.rs +++ b/compiler/rustc_hir_typeck/src/opaque_types.rs @@ -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), }; diff --git a/compiler/rustc_hir_typeck/src/writeback.rs b/compiler/rustc_hir_typeck/src/writeback.rs index 697029e55f7cb..08ed44bce9714 100644 --- a/compiler/rustc_hir_typeck/src/writeback.rs +++ b/compiler/rustc_hir_typeck/src/writeback.rs @@ -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> for EagerlyNormalizeConsts<'tcx> { struct HasRecursiveOpaque<'a, 'tcx> { def_id: LocalDefId, seen: FxHashSet, - opaques: &'a FxIndexMap>, + opaques: &'a FxIndexMap>, tcx: TyCtxt<'tcx>, } @@ -1063,9 +1061,7 @@ impl<'tcx> TypeVisitor> 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)?; } } diff --git a/compiler/rustc_middle/src/arena.rs b/compiler/rustc_middle/src/arena.rs index feaad5bb96eb9..66ee88f0e5220 100644 --- a/compiler/rustc_middle/src/arena.rs +++ b/compiler/rustc_middle/src/arena.rs @@ -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, diff --git a/compiler/rustc_middle/src/mir/query.rs b/compiler/rustc_middle/src/mir/query.rs index 2e6c9f207e26b..7629ae9817fea 100644 --- a/compiler/rustc_middle/src/mir/query.rs +++ b/compiler/rustc_middle/src/mir/query.rs @@ -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>); - /// The result of the `mir_const_qualif` query. /// /// Each field (except `tainted_by_errors`) corresponds to an implementer of the `Qualif` trait in diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index 588ff68ba572d..6fe65f193b435 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -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>, + ErrorGuaranteed + > { desc { |tcx| "borrow-checking `{}`", tcx.def_path_str(key) } } diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 93d0c77c1daee..a4828895a04ff 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -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)); + } + 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)), } - result + } + + pub fn build_mismatch_error( + &self, + other: &Self, + tcx: TyCtxt<'tcx>, + ) -> Result, 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, + })) } } diff --git a/compiler/rustc_middle/src/ty/typeck_results.rs b/compiler/rustc_middle/src/ty/typeck_results.rs index d1fb700913d91..56340c8597579 100644 --- a/compiler/rustc_middle/src/ty/typeck_results.rs +++ b/compiler/rustc_middle/src/ty/typeck_results.rs @@ -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>, + pub hidden_types: FxIndexMap>, /// Tracks the minimum captures required for a closure; /// see `MinCaptureInformationMap` for more details. diff --git a/compiler/rustc_pattern_analysis/src/rustc.rs b/compiler/rustc_pattern_analysis/src/rustc.rs index 0652461e97501..8df34ee941b21 100644 --- a/compiler/rustc_pattern_analysis/src/rustc.rs +++ b/compiler/rustc_pattern_analysis/src/rustc.rs @@ -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 {