Deeply normalize signature in new solver
This commit is contained in:
parent
ef9d992a0d
commit
d5be3bae51
8 changed files with 129 additions and 9 deletions
|
@ -9,8 +9,8 @@ use rustc_infer::infer::{
|
||||||
};
|
};
|
||||||
use rustc_infer::traits::ObligationCause;
|
use rustc_infer::traits::ObligationCause;
|
||||||
use rustc_infer::traits::query::{
|
use rustc_infer::traits::query::{
|
||||||
CanonicalTypeOpAscribeUserTypeGoal, CanonicalTypeOpNormalizeGoal,
|
CanonicalTypeOpAscribeUserTypeGoal, CanonicalTypeOpDeeplyNormalizeGoal,
|
||||||
CanonicalTypeOpProvePredicateGoal,
|
CanonicalTypeOpNormalizeGoal, CanonicalTypeOpProvePredicateGoal,
|
||||||
};
|
};
|
||||||
use rustc_middle::ty::error::TypeError;
|
use rustc_middle::ty::error::TypeError;
|
||||||
use rustc_middle::ty::{
|
use rustc_middle::ty::{
|
||||||
|
@ -109,6 +109,14 @@ impl<'tcx, T: Copy + fmt::Display + TypeFoldable<TyCtxt<'tcx>> + 'tcx> ToUnivers
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'tcx, T: Copy + fmt::Display + TypeFoldable<TyCtxt<'tcx>> + 'tcx> ToUniverseInfo<'tcx>
|
||||||
|
for CanonicalTypeOpDeeplyNormalizeGoal<'tcx, T>
|
||||||
|
{
|
||||||
|
fn to_universe_info(self, base_universe: ty::UniverseIndex) -> UniverseInfo<'tcx> {
|
||||||
|
UniverseInfo::TypeOp(Rc::new(DeeplyNormalizeQuery { canonical_query: self, base_universe }))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<'tcx> ToUniverseInfo<'tcx> for CanonicalTypeOpAscribeUserTypeGoal<'tcx> {
|
impl<'tcx> ToUniverseInfo<'tcx> for CanonicalTypeOpAscribeUserTypeGoal<'tcx> {
|
||||||
fn to_universe_info(self, base_universe: ty::UniverseIndex) -> UniverseInfo<'tcx> {
|
fn to_universe_info(self, base_universe: ty::UniverseIndex) -> UniverseInfo<'tcx> {
|
||||||
UniverseInfo::TypeOp(Rc::new(AscribeUserTypeQuery { canonical_query: self, base_universe }))
|
UniverseInfo::TypeOp(Rc::new(AscribeUserTypeQuery { canonical_query: self, base_universe }))
|
||||||
|
@ -285,6 +293,53 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct DeeplyNormalizeQuery<'tcx, T> {
|
||||||
|
canonical_query: CanonicalTypeOpDeeplyNormalizeGoal<'tcx, T>,
|
||||||
|
base_universe: ty::UniverseIndex,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'tcx, T> TypeOpInfo<'tcx> for DeeplyNormalizeQuery<'tcx, T>
|
||||||
|
where
|
||||||
|
T: Copy + fmt::Display + TypeFoldable<TyCtxt<'tcx>> + 'tcx,
|
||||||
|
{
|
||||||
|
fn fallback_error(&self, tcx: TyCtxt<'tcx>, span: Span) -> Diag<'tcx> {
|
||||||
|
tcx.dcx().create_err(HigherRankedLifetimeError {
|
||||||
|
cause: Some(HigherRankedErrorCause::CouldNotNormalize {
|
||||||
|
value: self.canonical_query.canonical.value.value.value.to_string(),
|
||||||
|
}),
|
||||||
|
span,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fn base_universe(&self) -> ty::UniverseIndex {
|
||||||
|
self.base_universe
|
||||||
|
}
|
||||||
|
|
||||||
|
fn nice_error<'infcx>(
|
||||||
|
&self,
|
||||||
|
mbcx: &mut MirBorrowckCtxt<'_, 'infcx, 'tcx>,
|
||||||
|
cause: ObligationCause<'tcx>,
|
||||||
|
placeholder_region: ty::Region<'tcx>,
|
||||||
|
error_region: Option<ty::Region<'tcx>>,
|
||||||
|
) -> Option<Diag<'infcx>> {
|
||||||
|
let (infcx, key, _) =
|
||||||
|
mbcx.infcx.tcx.infer_ctxt().build_with_canonical(cause.span, &self.canonical_query);
|
||||||
|
let ocx = ObligationCtxt::new(&infcx);
|
||||||
|
|
||||||
|
let (param_env, value) = key.into_parts();
|
||||||
|
let _ = ocx.deeply_normalize(&cause, param_env, value.value);
|
||||||
|
|
||||||
|
let diag = try_extract_error_from_fulfill_cx(
|
||||||
|
&ocx,
|
||||||
|
mbcx.mir_def_id(),
|
||||||
|
placeholder_region,
|
||||||
|
error_region,
|
||||||
|
)?
|
||||||
|
.with_dcx(mbcx.dcx());
|
||||||
|
Some(diag)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
struct AscribeUserTypeQuery<'tcx> {
|
struct AscribeUserTypeQuery<'tcx> {
|
||||||
canonical_query: CanonicalTypeOpAscribeUserTypeGoal<'tcx>,
|
canonical_query: CanonicalTypeOpAscribeUserTypeGoal<'tcx>,
|
||||||
base_universe: ty::UniverseIndex,
|
base_universe: ty::UniverseIndex,
|
||||||
|
|
|
@ -149,6 +149,18 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
||||||
self.normalize_with_category(value, location, ConstraintCategory::Boring)
|
self.normalize_with_category(value, location, ConstraintCategory::Boring)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(super) fn deeply_normalize<T>(&mut self, value: T, location: impl NormalizeLocation) -> T
|
||||||
|
where
|
||||||
|
T: type_op::normalize::Normalizable<'tcx> + fmt::Display + Copy + 'tcx,
|
||||||
|
{
|
||||||
|
let result: Result<_, ErrorGuaranteed> = self.fully_perform_op(
|
||||||
|
location.to_locations(),
|
||||||
|
ConstraintCategory::Boring,
|
||||||
|
self.infcx.param_env.and(type_op::normalize::DeeplyNormalize { value }),
|
||||||
|
);
|
||||||
|
result.unwrap_or(value)
|
||||||
|
}
|
||||||
|
|
||||||
#[instrument(skip(self), level = "debug")]
|
#[instrument(skip(self), level = "debug")]
|
||||||
pub(super) fn normalize_with_category<T>(
|
pub(super) fn normalize_with_category<T>(
|
||||||
&mut self,
|
&mut self,
|
||||||
|
|
|
@ -300,9 +300,8 @@ impl<'tcx> UniversalRegionRelationsBuilder<'_, 'tcx> {
|
||||||
// Add implied bounds from impl header.
|
// Add implied bounds from impl header.
|
||||||
if matches!(tcx.def_kind(defining_ty_def_id), DefKind::AssocFn | DefKind::AssocConst) {
|
if matches!(tcx.def_kind(defining_ty_def_id), DefKind::AssocFn | DefKind::AssocConst) {
|
||||||
for &(ty, _) in tcx.assumed_wf_types(tcx.local_parent(defining_ty_def_id)) {
|
for &(ty, _) in tcx.assumed_wf_types(tcx.local_parent(defining_ty_def_id)) {
|
||||||
let result: Result<_, ErrorGuaranteed> = param_env
|
let result: Result<_, ErrorGuaranteed> =
|
||||||
.and(DeeplyNormalize { value: ty })
|
param_env.and(DeeplyNormalize { value: ty }).fully_perform(self.infcx, span);
|
||||||
.fully_perform(self.infcx, span);
|
|
||||||
let Ok(TypeOpOutput { output: norm_ty, constraints: c, .. }) = result else {
|
let Ok(TypeOpOutput { output: norm_ty, constraints: c, .. }) = result else {
|
||||||
continue;
|
continue;
|
||||||
};
|
};
|
||||||
|
|
|
@ -1116,7 +1116,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
||||||
ConstraintCategory::Boring,
|
ConstraintCategory::Boring,
|
||||||
);
|
);
|
||||||
|
|
||||||
let sig = self.normalize(unnormalized_sig, term_location);
|
let sig = self.deeply_normalize(unnormalized_sig, term_location);
|
||||||
// HACK(#114936): `WF(sig)` does not imply `WF(normalized(sig))`
|
// HACK(#114936): `WF(sig)` does not imply `WF(normalized(sig))`
|
||||||
// with built-in `Fn` implementations, since the impl may not be
|
// with built-in `Fn` implementations, since the impl may not be
|
||||||
// well-formed itself.
|
// well-formed itself.
|
||||||
|
|
|
@ -87,6 +87,9 @@ pub type CanonicalTypeOpProvePredicateGoal<'tcx> =
|
||||||
pub type CanonicalTypeOpNormalizeGoal<'tcx, T> =
|
pub type CanonicalTypeOpNormalizeGoal<'tcx, T> =
|
||||||
CanonicalQueryInput<'tcx, ty::ParamEnvAnd<'tcx, type_op::Normalize<T>>>;
|
CanonicalQueryInput<'tcx, ty::ParamEnvAnd<'tcx, type_op::Normalize<T>>>;
|
||||||
|
|
||||||
|
pub type CanonicalTypeOpDeeplyNormalizeGoal<'tcx, T> =
|
||||||
|
CanonicalQueryInput<'tcx, ty::ParamEnvAnd<'tcx, type_op::DeeplyNormalize<T>>>;
|
||||||
|
|
||||||
pub type CanonicalImpliedOutlivesBoundsGoal<'tcx> =
|
pub type CanonicalImpliedOutlivesBoundsGoal<'tcx> =
|
||||||
CanonicalQueryInput<'tcx, ty::ParamEnvAnd<'tcx, type_op::ImpliedOutlivesBounds<'tcx>>>;
|
CanonicalQueryInput<'tcx, ty::ParamEnvAnd<'tcx, type_op::ImpliedOutlivesBounds<'tcx>>>;
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
error[E0597]: `s` does not live long enough
|
error[E0597]: `s` does not live long enough
|
||||||
--> $DIR/check-normalized-sig-for-wf.rs:7:7
|
--> $DIR/check-normalized-sig-for-wf.rs:11:7
|
||||||
|
|
|
|
||||||
LL | s: String,
|
LL | s: String,
|
||||||
| - binding `s` declared here
|
| - binding `s` declared here
|
||||||
|
@ -14,7 +14,7 @@ LL | }
|
||||||
| - `s` dropped here while still borrowed
|
| - `s` dropped here while still borrowed
|
||||||
|
|
||||||
error[E0521]: borrowed data escapes outside of function
|
error[E0521]: borrowed data escapes outside of function
|
||||||
--> $DIR/check-normalized-sig-for-wf.rs:15:5
|
--> $DIR/check-normalized-sig-for-wf.rs:19:5
|
||||||
|
|
|
|
||||||
LL | fn extend<T>(input: &T) -> &'static T {
|
LL | fn extend<T>(input: &T) -> &'static T {
|
||||||
| ----- - let's call the lifetime of this reference `'1`
|
| ----- - let's call the lifetime of this reference `'1`
|
||||||
|
@ -28,7 +28,7 @@ LL | n(input).0
|
||||||
| argument requires that `'1` must outlive `'static`
|
| argument requires that `'1` must outlive `'static`
|
||||||
|
|
||||||
error[E0521]: borrowed data escapes outside of function
|
error[E0521]: borrowed data escapes outside of function
|
||||||
--> $DIR/check-normalized-sig-for-wf.rs:23:5
|
--> $DIR/check-normalized-sig-for-wf.rs:27:5
|
||||||
|
|
|
|
||||||
LL | fn extend_mut<'a, T>(input: &'a mut T) -> &'static mut T {
|
LL | fn extend_mut<'a, T>(input: &'a mut T) -> &'static mut T {
|
||||||
| -- ----- `input` is a reference that is only valid in the function body
|
| -- ----- `input` is a reference that is only valid in the function body
|
47
tests/ui/nll/check-normalized-sig-for-wf.next.stderr
Normal file
47
tests/ui/nll/check-normalized-sig-for-wf.next.stderr
Normal file
|
@ -0,0 +1,47 @@
|
||||||
|
error[E0597]: `s` does not live long enough
|
||||||
|
--> $DIR/check-normalized-sig-for-wf.rs:11:7
|
||||||
|
|
|
||||||
|
LL | s: String,
|
||||||
|
| - binding `s` declared here
|
||||||
|
...
|
||||||
|
LL | f(&s).0
|
||||||
|
| --^^-
|
||||||
|
| | |
|
||||||
|
| | borrowed value does not live long enough
|
||||||
|
| argument requires that `s` is borrowed for `'static`
|
||||||
|
LL |
|
||||||
|
LL | }
|
||||||
|
| - `s` dropped here while still borrowed
|
||||||
|
|
||||||
|
error[E0521]: borrowed data escapes outside of function
|
||||||
|
--> $DIR/check-normalized-sig-for-wf.rs:19:5
|
||||||
|
|
|
||||||
|
LL | fn extend<T>(input: &T) -> &'static T {
|
||||||
|
| ----- - let's call the lifetime of this reference `'1`
|
||||||
|
| |
|
||||||
|
| `input` is a reference that is only valid in the function body
|
||||||
|
...
|
||||||
|
LL | n(input).0
|
||||||
|
| ^^^^^^^^
|
||||||
|
| |
|
||||||
|
| `input` escapes the function body here
|
||||||
|
| argument requires that `'1` must outlive `'static`
|
||||||
|
|
||||||
|
error[E0521]: borrowed data escapes outside of function
|
||||||
|
--> $DIR/check-normalized-sig-for-wf.rs:27:5
|
||||||
|
|
|
||||||
|
LL | fn extend_mut<'a, T>(input: &'a mut T) -> &'static mut T {
|
||||||
|
| -- ----- `input` is a reference that is only valid in the function body
|
||||||
|
| |
|
||||||
|
| lifetime `'a` defined here
|
||||||
|
...
|
||||||
|
LL | n(input).0
|
||||||
|
| ^^^^^^^^
|
||||||
|
| |
|
||||||
|
| `input` escapes the function body here
|
||||||
|
| argument requires that `'a` must outlive `'static`
|
||||||
|
|
||||||
|
error: aborting due to 3 previous errors
|
||||||
|
|
||||||
|
Some errors have detailed explanations: E0521, E0597.
|
||||||
|
For more information about an error, try `rustc --explain E0521`.
|
|
@ -1,3 +1,7 @@
|
||||||
|
//@ revisions: current next
|
||||||
|
//@ ignore-compare-mode-next-solver (explicit revisions)
|
||||||
|
//@[next] compile-flags: -Znext-solver
|
||||||
|
|
||||||
// <https://github.com/rust-lang/rust/issues/114936>
|
// <https://github.com/rust-lang/rust/issues/114936>
|
||||||
fn whoops(
|
fn whoops(
|
||||||
s: String,
|
s: String,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue