summaryrefslogtreecommitdiffstats
path: root/compiler/rustc_hir_analysis/src/collect/type_of
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-30 03:57:31 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-30 03:57:31 +0000
commitdc0db358abe19481e475e10c32149b53370f1a1c (patch)
treeab8ce99c4b255ce46f99ef402c27916055b899ee /compiler/rustc_hir_analysis/src/collect/type_of
parentReleasing progress-linux version 1.71.1+dfsg1-2~progress7.99u1. (diff)
downloadrustc-dc0db358abe19481e475e10c32149b53370f1a1c.tar.xz
rustc-dc0db358abe19481e475e10c32149b53370f1a1c.zip
Merging upstream version 1.72.1+dfsg1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'compiler/rustc_hir_analysis/src/collect/type_of')
-rw-r--r--compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs131
1 files changed, 93 insertions, 38 deletions
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 f7c5b4467..957a6bb34 100644
--- a/compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs
+++ b/compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs
@@ -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};
@@ -5,7 +6,7 @@ use rustc_middle::hir::nested_filter;
use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt};
use rustc_span::DUMMY_SP;
-use crate::errors::UnconstrainedOpaqueType;
+use crate::errors::{TaitForwardCompat, UnconstrainedOpaqueType};
/// Checks "defining uses" of opaque `impl Trait` types to ensure that they meet the restrictions
/// laid for "higher-order pattern unification".
@@ -59,7 +60,20 @@ pub(super) fn find_opaque_ty_constraints_for_tait(tcx: TyCtxt<'_>, def_id: Local
}
}
- let Some(hidden) = locator.found else {
+ if let Some(hidden) = locator.found {
+ // Only check against typeck if we didn't already error
+ if !hidden.ty.references_error() {
+ for concrete_type in locator.typeck_types {
+ if concrete_type.ty != tcx.erase_regions(hidden.ty)
+ && !(concrete_type, hidden).references_error()
+ {
+ hidden.report_mismatch(&concrete_type, def_id, tcx).emit();
+ }
+ }
+ }
+
+ hidden.ty
+ } else {
let reported = tcx.sess.emit_err(UnconstrainedOpaqueType {
span: tcx.def_span(def_id),
name: tcx.item_name(tcx.local_parent(def_id).to_def_id()),
@@ -70,21 +84,8 @@ pub(super) fn find_opaque_ty_constraints_for_tait(tcx: TyCtxt<'_>, def_id: Local
_ => "item",
},
});
- return tcx.ty_error(reported);
- };
-
- // Only check against typeck if we didn't already error
- if !hidden.ty.references_error() {
- for concrete_type in locator.typeck_types {
- if concrete_type.ty != tcx.erase_regions(hidden.ty)
- && !(concrete_type, hidden).references_error()
- {
- hidden.report_mismatch(&concrete_type, def_id, tcx).emit();
- }
- }
+ Ty::new_error(tcx, reported)
}
-
- hidden.ty
}
struct TaitConstraintLocator<'tcx> {
@@ -127,16 +128,41 @@ impl TaitConstraintLocator<'_> {
// ```
let tables = self.tcx.typeck(item_def_id);
if let Some(guar) = tables.tainted_by_errors {
- self.found = Some(ty::OpaqueHiddenType { span: DUMMY_SP, ty: self.tcx.ty_error(guar) });
+ self.found =
+ Some(ty::OpaqueHiddenType { span: DUMMY_SP, ty: Ty::new_error(self.tcx, guar) });
return;
}
- let Some(&typeck_hidden_ty) = tables.concrete_opaque_types.get(&self.def_id) else {
+
+ let mut constrained = false;
+ for (&opaque_type_key, &hidden_type) in &tables.concrete_opaque_types {
+ if opaque_type_key.def_id != self.def_id {
+ continue;
+ }
+ constrained = true;
+ if !self.tcx.opaque_types_defined_by(item_def_id).contains(&self.def_id) {
+ self.tcx.sess.emit_err(TaitForwardCompat {
+ span: hidden_type.span,
+ item_span: self
+ .tcx
+ .def_ident_span(item_def_id)
+ .unwrap_or_else(|| self.tcx.def_span(item_def_id)),
+ });
+ }
+ let concrete_type =
+ self.tcx.erase_regions(hidden_type.remap_generic_params_to_declaration_params(
+ opaque_type_key,
+ self.tcx,
+ true,
+ ));
+ if self.typeck_types.iter().all(|prev| prev.ty != concrete_type.ty) {
+ self.typeck_types.push(concrete_type);
+ }
+ }
+
+ if !constrained {
debug!("no constraints in typeck results");
return;
};
- if self.typeck_types.iter().all(|prev| prev.ty != typeck_hidden_ty.ty) {
- self.typeck_types.push(typeck_hidden_ty);
- }
// Use borrowck to get the type with unerased regions.
let concrete_opaque_types = &self.tcx.mir_borrowck(item_def_id).concrete_opaque_types;
@@ -146,7 +172,7 @@ impl TaitConstraintLocator<'_> {
if let Some(prev) = &mut self.found {
if concrete_type.ty != prev.ty && !(concrete_type, prev.ty).references_error() {
let guar = prev.report_mismatch(&concrete_type, self.def_id, self.tcx).emit();
- prev.ty = self.tcx.ty_error(guar);
+ prev.ty = Ty::new_error(self.tcx, guar);
}
} else {
self.found = Some(concrete_type);
@@ -190,17 +216,45 @@ impl<'tcx> intravisit::Visitor<'tcx> for TaitConstraintLocator<'tcx> {
}
}
-pub(super) fn find_opaque_ty_constraints_for_rpit(
- tcx: TyCtxt<'_>,
+pub(super) fn find_opaque_ty_constraints_for_rpit<'tcx>(
+ tcx: TyCtxt<'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),
@@ -208,27 +262,28 @@ pub(super) fn find_opaque_ty_constraints_for_rpit(
Node::TraitItem(it) => intravisit::walk_trait_item(&mut locator, it),
other => bug!("{:?} is not a valid scope for an opaque type item", other),
}
- }
- concrete.map(|concrete| concrete.ty).unwrap_or_else(|| {
- let table = tcx.typeck(owner_def_id);
- if let Some(guar) = table.tainted_by_errors {
- // Some error in the
- // owner fn prevented us from populating
+ mir_opaque_ty.ty
+ } else {
+ if let Some(guar) = tables.tainted_by_errors {
+ // Some error in the owner fn prevented us from populating
// the `concrete_opaque_types` table.
- tcx.ty_error(guar)
+ Ty::new_error(tcx, guar)
} else {
- table.concrete_opaque_types.get(&def_id).map(|ty| ty.ty).unwrap_or_else(|| {
+ // Fall back to the RPIT we inferred during HIR typeck
+ 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
// no values of the hidden type ever being constructed,
// so we can just make the hidden type be `!`.
// For backwards compatibility reasons, we fall back to
// `()` until we the diverging default is changed.
- tcx.mk_diverging_default()
- })
+ Ty::new_diverging_default(tcx)
+ }
}
- })
+ }
}
struct RpitConstraintChecker<'tcx> {