Rollup merge of #133520 - compiler-errors:structurally-resolve-mir-borrowck, 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
This commit is contained in:
@@ -7,6 +7,7 @@ use rustc_middle::mir::ConstraintCategory;
|
|||||||
use rustc_middle::ty::{self, Ty, TyCtxt, TypeFoldable, Upcast};
|
use rustc_middle::ty::{self, Ty, TyCtxt, TypeFoldable, Upcast};
|
||||||
use rustc_span::Span;
|
use rustc_span::Span;
|
||||||
use rustc_span::def_id::DefId;
|
use rustc_span::def_id::DefId;
|
||||||
|
use rustc_trait_selection::solve::NoSolution;
|
||||||
use rustc_trait_selection::traits::ObligationCause;
|
use rustc_trait_selection::traits::ObligationCause;
|
||||||
use rustc_trait_selection::traits::query::type_op::custom::CustomTypeOp;
|
use rustc_trait_selection::traits::query::type_op::custom::CustomTypeOp;
|
||||||
use rustc_trait_selection::traits::query::type_op::{self, TypeOpOutput};
|
use rustc_trait_selection::traits::query::type_op::{self, TypeOpOutput};
|
||||||
@@ -177,6 +178,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
|||||||
if self.infcx.next_trait_solver() {
|
if self.infcx.next_trait_solver() {
|
||||||
let body = self.body;
|
let body = self.body;
|
||||||
let param_env = self.infcx.param_env;
|
let param_env = self.infcx.param_env;
|
||||||
|
// FIXME: Make this into a real type op?
|
||||||
self.fully_perform_op(
|
self.fully_perform_op(
|
||||||
location.to_locations(),
|
location.to_locations(),
|
||||||
ConstraintCategory::Boring,
|
ConstraintCategory::Boring,
|
||||||
@@ -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")]
|
#[instrument(skip(self), level = "debug")]
|
||||||
pub(super) fn ascribe_user_type(
|
pub(super) fn ascribe_user_type(
|
||||||
&mut self,
|
&mut self,
|
||||||
|
|||||||
@@ -1064,7 +1064,9 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
|||||||
let tcx = self.infcx.tcx;
|
let tcx = self.infcx.tcx;
|
||||||
|
|
||||||
for proj in &user_ty.projs {
|
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.
|
// 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
|
// We're always in its defining scope as we can otherwise not project through
|
||||||
// it, so we're constraining it anyways.
|
// it, so we're constraining it anyways.
|
||||||
@@ -1075,7 +1077,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
|||||||
proj,
|
proj,
|
||||||
|this, field, ()| {
|
|this, field, ()| {
|
||||||
let ty = this.field_ty(tcx, field);
|
let ty = this.field_ty(tcx, field);
|
||||||
self.normalize(ty, locations)
|
self.structurally_resolve(ty, locations)
|
||||||
},
|
},
|
||||||
|_, _| unreachable!(),
|
|_, _| unreachable!(),
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -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() {}
|
||||||
Reference in New Issue
Block a user