Skip to content

do not emit OpaqueCast projections with -Znext-solver #139902

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Apr 17, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 15 additions & 10 deletions compiler/rustc_hir_typeck/src/expr_use_visitor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1502,16 +1502,21 @@ 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);
// 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)
.is_impl_trait()
{
projections.push(Projection { kind: ProjectionKind::OpaqueCast, ty: node_ty });
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,
)
.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)
Expand Down
2 changes: 2 additions & 0 deletions compiler/rustc_middle/src/hir/place.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
}

Expand Down
2 changes: 2 additions & 0 deletions compiler/rustc_middle/src/mir/syntax.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
25 changes: 14 additions & 11 deletions compiler/rustc_mir_build/src/builder/matches/match_pair.rs
Original file line number Diff line number Diff line change
Expand Up @@ -101,18 +101,21 @@ impl<'tcx> MatchPairTree<'tcx> {
place_builder = resolved;
}

// 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;
ty != pattern.ty && ty.has_opaque_types()
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;
ty != pattern.ty && ty.has_opaque_types()
}
_ => true,
};
if may_need_cast {
place_builder = place_builder.project(ProjectionElem::OpaqueCast(pattern.ty));
}
_ => true,
};
if may_need_cast {
place_builder = place_builder.project(ProjectionElem::OpaqueCast(pattern.ty));
}

let place = place_builder.try_to_place(cx);
Expand Down
28 changes: 15 additions & 13 deletions compiler/rustc_mir_transform/src/post_analysis_normalize.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,20 +39,22 @@ 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(_))) {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this also affects the old solver as we now continue to super_visit even if there are no opaque casts involved.

I think this is more correct as we want to normalize types and consts regardless of whether a projection contained an opaque.

place.projection = self.tcx.mk_place_elems(
&place
.projection
.into_iter()
.filter(|elem| !matches!(elem, ProjectionElem::OpaqueCast(_)))
.collect::<Vec<_>>(),
);
};
}
// `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.
place.projection = self.tcx.mk_place_elems(
&place
.projection
.into_iter()
.filter(|elem| !matches!(elem, ProjectionElem::OpaqueCast(_)))
.collect::<Vec<_>>(),
);
self.super_place(place, _context, _location);
}

Expand Down
Original file line number Diff line number Diff line change
@@ -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
Expand Down
2 changes: 2 additions & 0 deletions tests/ui/type-alias-impl-trait/destructure_tait-ice-113594.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
//@ revisions: current next
//@ [next] compile-flags: -Znext-solver
//@ build-pass
//@ edition: 2021

Expand Down
2 changes: 2 additions & 0 deletions tests/ui/type-alias-impl-trait/tait-normalize.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
//@ revisions: current next
//@ [next] compile-flags: -Znext-solver
//@ check-pass

#![feature(type_alias_impl_trait)]
Expand Down
Loading