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::query::{
|
||||
CanonicalTypeOpAscribeUserTypeGoal, CanonicalTypeOpNormalizeGoal,
|
||||
CanonicalTypeOpProvePredicateGoal,
|
||||
CanonicalTypeOpAscribeUserTypeGoal, CanonicalTypeOpDeeplyNormalizeGoal,
|
||||
CanonicalTypeOpNormalizeGoal, CanonicalTypeOpProvePredicateGoal,
|
||||
};
|
||||
use rustc_middle::ty::error::TypeError;
|
||||
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> {
|
||||
fn to_universe_info(self, base_universe: ty::UniverseIndex) -> UniverseInfo<'tcx> {
|
||||
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> {
|
||||
canonical_query: CanonicalTypeOpAscribeUserTypeGoal<'tcx>,
|
||||
base_universe: ty::UniverseIndex,
|
||||
|
|
|
@ -149,6 +149,18 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
|||
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")]
|
||||
pub(super) fn normalize_with_category<T>(
|
||||
&mut self,
|
||||
|
|
|
@ -300,9 +300,8 @@ impl<'tcx> UniversalRegionRelationsBuilder<'_, 'tcx> {
|
|||
// Add implied bounds from impl header.
|
||||
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)) {
|
||||
let result: Result<_, ErrorGuaranteed> = param_env
|
||||
.and(DeeplyNormalize { value: ty })
|
||||
.fully_perform(self.infcx, span);
|
||||
let result: Result<_, ErrorGuaranteed> =
|
||||
param_env.and(DeeplyNormalize { value: ty }).fully_perform(self.infcx, span);
|
||||
let Ok(TypeOpOutput { output: norm_ty, constraints: c, .. }) = result else {
|
||||
continue;
|
||||
};
|
||||
|
|
|
@ -1116,7 +1116,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
|||
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))`
|
||||
// with built-in `Fn` implementations, since the impl may not be
|
||||
// well-formed itself.
|
||||
|
|
|
@ -87,6 +87,9 @@ pub type CanonicalTypeOpProvePredicateGoal<'tcx> =
|
|||
pub type CanonicalTypeOpNormalizeGoal<'tcx, 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> =
|
||||
CanonicalQueryInput<'tcx, ty::ParamEnvAnd<'tcx, type_op::ImpliedOutlivesBounds<'tcx>>>;
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
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,
|
||||
| - binding `s` declared here
|
||||
|
@ -14,7 +14,7 @@ LL | }
|
|||
| - `s` dropped here while still borrowed
|
||||
|
||||
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 {
|
||||
| ----- - let's call the lifetime of this reference `'1`
|
||||
|
@ -28,7 +28,7 @@ LL | n(input).0
|
|||
| argument requires that `'1` must outlive `'static`
|
||||
|
||||
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 {
|
||||
| -- ----- `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>
|
||||
fn whoops(
|
||||
s: String,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue