Rollup merge of #139902 - lcnr:no-opaque-cast-projection, r=oli-obk

do not emit `OpaqueCast` projections with `-Znext-solver`

We normalize opaque types in their defining scope if the new solver is enabled. This means projections do not contain any 'revealable' opaque types we need to worry about. We either have a type which has been normalized by writeback or we need to normalize it anyways.

r? ```@compiler-errors``` ```@oli-obk```
This commit is contained in:
Matthias Krüger 2025-04-17 17:40:28 +02:00 committed by GitHub
commit 67e2358fbb
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
8 changed files with 52 additions and 35 deletions

View file

@ -1502,17 +1502,22 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
let mut projections = base_place.place.projections;
let node_ty = self.cx.typeck_results().node_type(node);
if !self.cx.tcx().next_trait_solver_globally() {
// Opaque types can't have field projections, but we can instead convert
// the current place in-place (heh) to the hidden type, and then apply all
// follow up projections on that.
if node_ty != place_ty
&& self
.cx
.try_structurally_resolve_type(self.cx.tcx().hir_span(base_place.hir_id), place_ty)
.try_structurally_resolve_type(
self.cx.tcx().hir_span(base_place.hir_id),
place_ty,
)
.is_impl_trait()
{
projections.push(Projection { kind: ProjectionKind::OpaqueCast, ty: node_ty });
}
}
projections.push(Projection { kind, ty });
PlaceWithHirId::new(node, base_place.place.base_ty, base_place.place.base, projections)
}

View file

@ -40,6 +40,8 @@ pub enum ProjectionKind {
/// A conversion from an opaque type to its hidden type so we can
/// do further projections on it.
///
/// This is unused if `-Znext-solver` is enabled.
OpaqueCast,
}

View file

@ -1242,6 +1242,8 @@ pub enum ProjectionElem<V, T> {
/// Like an explicit cast from an opaque type to a concrete type, but without
/// requiring an intermediate variable.
///
/// This is unused with `-Znext-solver`.
OpaqueCast(T),
/// A transmute from an unsafe binder to the type that it wraps. This is a projection

View file

@ -101,12 +101,14 @@ impl<'tcx> MatchPairTree<'tcx> {
place_builder = resolved;
}
if !cx.tcx.next_trait_solver_globally() {
// Only add the OpaqueCast projection if the given place is an opaque type and the
// expected type from the pattern is not.
let may_need_cast = match place_builder.base() {
PlaceBase::Local(local) => {
let ty =
Place::ty_from(local, place_builder.projection(), &cx.local_decls, cx.tcx).ty;
Place::ty_from(local, place_builder.projection(), &cx.local_decls, cx.tcx)
.ty;
ty != pattern.ty && ty.has_opaque_types()
}
_ => true,
@ -114,6 +116,7 @@ impl<'tcx> MatchPairTree<'tcx> {
if may_need_cast {
place_builder = place_builder.project(ProjectionElem::OpaqueCast(pattern.ty));
}
}
let place = place_builder.try_to_place(cx);
let mut subpairs = Vec::new();

View file

@ -39,13 +39,13 @@ impl<'tcx> MutVisitor<'tcx> for PostAnalysisNormalizeVisitor<'tcx> {
_context: PlaceContext,
_location: Location,
) {
// Performance optimization: don't reintern if there is no `OpaqueCast` to remove.
if place.projection.iter().all(|elem| !matches!(elem, ProjectionElem::OpaqueCast(_))) {
return;
}
if !self.tcx.next_trait_solver_globally() {
// `OpaqueCast` projections are only needed if there are opaque types on which projections
// are performed. After the `PostAnalysisNormalize` pass, all opaque types are replaced with their
// hidden types, so we don't need these projections anymore.
//
// Performance optimization: don't reintern if there is no `OpaqueCast` to remove.
if place.projection.iter().any(|elem| matches!(elem, ProjectionElem::OpaqueCast(_))) {
place.projection = self.tcx.mk_place_elems(
&place
.projection
@ -53,6 +53,8 @@ impl<'tcx> MutVisitor<'tcx> for PostAnalysisNormalizeVisitor<'tcx> {
.filter(|elem| !matches!(elem, ProjectionElem::OpaqueCast(_)))
.collect::<Vec<_>>(),
);
};
}
self.super_place(place, _context, _location);
}

View file

@ -1,6 +1,5 @@
//@ compile-flags: --crate-type=lib
//@ edition: 2021
//@ rustc-env:RUST_BACKTRACE=0
//@ check-pass
// tracked in https://github.com/rust-lang/rust/issues/96572

View file

@ -1,3 +1,5 @@
//@ revisions: current next
//@ [next] compile-flags: -Znext-solver
//@ build-pass
//@ edition: 2021

View file

@ -1,3 +1,5 @@
//@ revisions: current next
//@ [next] compile-flags: -Znext-solver
//@ check-pass
#![feature(type_alias_impl_trait)]