Rollup merge of #118882 - compiler-errors:normalized-sig-wf, r=lcnr
Check normalized call signature for WF in mir typeck Unfortunately we don't check that the built-in implementations for `Fn*` traits are actually well-formed in the same way that we do for user-provided impls. Essentially, when checking a call terminator, we end up with a signature that references an unnormalized `<[closure] as FnOnce<...>>::Output` in its output. That output type, due to the built-in impl, doesn't follow the expected rule that `WF(ty)` implies `WF(normalized(ty))`. We fix this by also checking the normalized signature here. **See** boxy's detailed and useful explanation comment which explains this in more detail: https://github.com/rust-lang/rust/issues/114936#issuecomment-1710388741 Fixes #114936 Fixes #118876 r? types cc ``@BoxyUwU`` ``@lcnr``
This commit is contained in:
commit
db9591cfb6
3 changed files with 94 additions and 4 deletions
|
@ -1432,7 +1432,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
|||
return;
|
||||
}
|
||||
};
|
||||
let (sig, map) = tcx.instantiate_bound_regions(sig, |br| {
|
||||
let (unnormalized_sig, map) = tcx.instantiate_bound_regions(sig, |br| {
|
||||
use crate::renumber::RegionCtxt;
|
||||
|
||||
let region_ctxt_fn = || {
|
||||
|
@ -1454,7 +1454,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
|||
region_ctxt_fn,
|
||||
)
|
||||
});
|
||||
debug!(?sig);
|
||||
debug!(?unnormalized_sig);
|
||||
// IMPORTANT: We have to prove well formed for the function signature before
|
||||
// we normalize it, as otherwise types like `<&'a &'b () as Trait>::Assoc`
|
||||
// get normalized away, causing us to ignore the `'b: 'a` bound used by the function.
|
||||
|
@ -1464,7 +1464,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
|||
//
|
||||
// See #91068 for an example.
|
||||
self.prove_predicates(
|
||||
sig.inputs_and_output.iter().map(|ty| {
|
||||
unnormalized_sig.inputs_and_output.iter().map(|ty| {
|
||||
ty::Binder::dummy(ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(
|
||||
ty.into(),
|
||||
)))
|
||||
|
@ -1472,7 +1472,23 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
|||
term_location.to_locations(),
|
||||
ConstraintCategory::Boring,
|
||||
);
|
||||
let sig = self.normalize(sig, term_location);
|
||||
|
||||
let sig = self.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.
|
||||
if sig != unnormalized_sig {
|
||||
self.prove_predicates(
|
||||
sig.inputs_and_output.iter().map(|ty| {
|
||||
ty::Binder::dummy(ty::PredicateKind::Clause(
|
||||
ty::ClauseKind::WellFormed(ty.into()),
|
||||
))
|
||||
}),
|
||||
term_location.to_locations(),
|
||||
ConstraintCategory::Boring,
|
||||
);
|
||||
}
|
||||
|
||||
self.check_call_dest(body, term, &sig, *destination, *target, term_location);
|
||||
|
||||
// The ordinary liveness rules will ensure that all
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue