1
Fork 0

Retain ParamEnv constness when running deferred cast checks

Fixes #103677.
This commit is contained in:
Deadbeef 2022-10-28 11:46:12 +00:00
parent 898f463c93
commit a990b4c1d0
5 changed files with 33 additions and 5 deletions

View file

@ -60,6 +60,8 @@ pub struct CastCheck<'tcx> {
cast_ty: Ty<'tcx>,
cast_span: Span,
span: Span,
/// whether the cast is made in a const context or not.
pub constness: hir::Constness,
}
/// The kind of pointer and associated metadata (thin, length or vtable) - we
@ -210,9 +212,10 @@ impl<'a, 'tcx> CastCheck<'tcx> {
cast_ty: Ty<'tcx>,
cast_span: Span,
span: Span,
constness: hir::Constness,
) -> Result<CastCheck<'tcx>, ErrorGuaranteed> {
let expr_span = expr.span.find_ancestor_inside(span).unwrap_or(expr.span);
let check = CastCheck { expr, expr_ty, expr_span, cast_ty, cast_span, span };
let check = CastCheck { expr, expr_ty, expr_span, cast_ty, cast_span, span, constness };
// For better error messages, check for some obviously unsized
// cases now. We do a more thorough check at the end, once

View file

@ -1272,7 +1272,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
} else {
// Defer other checks until we're done type checking.
let mut deferred_cast_checks = self.deferred_cast_checks.borrow_mut();
match cast::CastCheck::new(self, e, t_expr, t_cast, t.span, expr.span) {
match cast::CastCheck::new(
self,
e,
t_expr,
t_cast,
t.span,
expr.span,
self.param_env.constness(),
) {
Ok(cast_check) => {
debug!(
"check_expr_cast: deferring cast from {:?} to {:?}: {:?}",

View file

@ -33,16 +33,27 @@ use rustc_span::{self, sym, Span};
use rustc_trait_selection::traits::{self, ObligationCauseCode, SelectionContext};
use std::iter;
use std::mem;
use std::ops::ControlFlow;
use std::slice;
impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
pub(in super::super) fn check_casts(&self) {
let mut deferred_cast_checks = self.deferred_cast_checks.borrow_mut();
pub(in super::super) fn check_casts(&mut self) {
// don't hold the borrow to deferred_cast_checks while checking to avoid borrow checker errors
// when writing to `self.param_env`.
let mut deferred_cast_checks = mem::take(&mut *self.deferred_cast_checks.borrow_mut());
debug!("FnCtxt::check_casts: {} deferred checks", deferred_cast_checks.len());
for cast in deferred_cast_checks.drain(..) {
let prev_env = self.param_env;
self.param_env = self.param_env.with_constness(cast.constness);
cast.check(self);
self.param_env = prev_env;
}
*self.deferred_cast_checks.borrow_mut() = deferred_cast_checks;
}
pub(in super::super) fn check_transmutes(&self) {