Skip to content

Commit

Permalink
Rollup merge of #133520 - compiler-errors:structurally-resolve-mir-bo…
Browse files Browse the repository at this point in the history
…rrowck, r=lcnr

Structurally resolve before applying projection in borrowck

As far as I can tell, all other `.normalize` calls in borrowck are noops and can remain that way. This is the only one that actually requires structurally resolving the type.

r? lcnr
  • Loading branch information
GuillaumeGomez authored Nov 28, 2024
2 parents 06815d0 + 26c7774 commit b46ed71
Show file tree
Hide file tree
Showing 3 changed files with 72 additions and 2 deletions.
36 changes: 36 additions & 0 deletions compiler/rustc_borrowck/src/type_check/canonical.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ use rustc_middle::mir::ConstraintCategory;
use rustc_middle::ty::{self, Ty, TyCtxt, TypeFoldable, Upcast};
use rustc_span::Span;
use rustc_span::def_id::DefId;
use rustc_trait_selection::solve::NoSolution;
use rustc_trait_selection::traits::ObligationCause;
use rustc_trait_selection::traits::query::type_op::custom::CustomTypeOp;
use rustc_trait_selection::traits::query::type_op::{self, TypeOpOutput};
Expand Down Expand Up @@ -177,6 +178,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
if self.infcx.next_trait_solver() {
let body = self.body;
let param_env = self.infcx.param_env;
// FIXME: Make this into a real type op?
self.fully_perform_op(
location.to_locations(),
ConstraintCategory::Boring,
Expand Down Expand Up @@ -213,6 +215,40 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
}
}

#[instrument(skip(self), level = "debug")]
pub(super) fn structurally_resolve(
&mut self,
ty: Ty<'tcx>,
location: impl NormalizeLocation,
) -> Ty<'tcx> {
if self.infcx.next_trait_solver() {
let body = self.body;
let param_env = self.infcx.param_env;
// FIXME: Make this into a real type op?
self.fully_perform_op(
location.to_locations(),
ConstraintCategory::Boring,
CustomTypeOp::new(
|ocx| {
ocx.structurally_normalize(
&ObligationCause::misc(
location.to_locations().span(body),
body.source.def_id().expect_local(),
),
param_env,
ty,
)
.map_err(|_| NoSolution)
},
"normalizing struct tail",
),
)
.unwrap_or_else(|guar| Ty::new_error(self.tcx(), guar))
} else {
self.normalize(ty, location)
}
}

#[instrument(skip(self), level = "debug")]
pub(super) fn ascribe_user_type(
&mut self,
Expand Down
6 changes: 4 additions & 2 deletions compiler/rustc_borrowck/src/type_check/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1064,7 +1064,9 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
let tcx = self.infcx.tcx;

for proj in &user_ty.projs {
if let ty::Alias(ty::Opaque, ..) = curr_projected_ty.ty.kind() {
if !self.infcx.next_trait_solver()
&& let ty::Alias(ty::Opaque, ..) = curr_projected_ty.ty.kind()
{
// There is nothing that we can compare here if we go through an opaque type.
// We're always in its defining scope as we can otherwise not project through
// it, so we're constraining it anyways.
Expand All @@ -1075,7 +1077,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
proj,
|this, field, ()| {
let ty = this.field_ty(tcx, field);
self.normalize(ty, locations)
self.structurally_resolve(ty, locations)
},
|_, _| unreachable!(),
);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
//@ check-pass
//@ compile-flags: -Znext-solver

trait Interner: Sized {
type Value;
}

enum Kind<I: Interner> {
Value(I::Value),
}

struct Intern;

impl Interner for Intern {
type Value = Wrap<u32>;
}

struct Wrap<T>(T);

type KindAlias = Kind<Intern>;

trait PrettyPrinter: Sized {
fn hello(c: KindAlias) {
match c {
KindAlias::Value(Wrap(v)) => {
println!("{v:?}");
}
}
}
}

fn main() {}

0 comments on commit b46ed71

Please sign in to comment.