Auto merge of #103683 - fee1-dead-contrib:fix-deferred-cast-checks-constness, r=oli-obk

Retain ParamEnv constness when running deferred cast checks

Fixes #103677.
This commit is contained in:
bors 2022-10-28 19:28:41 +00:00
commit 9565dfeb4e
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) {

View File

@ -0,0 +1,5 @@
// check-pass
const _: fn(&String) = |s| { &*s as &str; };
fn main() {}

View File

@ -3,6 +3,7 @@ use rustc_hir_typeck::{cast, FnCtxt, Inherited};
use rustc_lint::LateContext;
use rustc_middle::ty::{cast::CastKind, Ty};
use rustc_span::DUMMY_SP;
use rustc_hir as hir;
// check if the component types of the transmuted collection and the result have different ABI,
// size or alignment
@ -56,7 +57,7 @@ fn check_cast<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>, from_ty: Ty<'tcx>
if let Ok(check) = cast::CastCheck::new(
&fn_ctxt, e, from_ty, to_ty,
// We won't show any error to the user, so we don't care what the span is here.
DUMMY_SP, DUMMY_SP,
DUMMY_SP, DUMMY_SP, hir::Constness::NotConst,
) {
let res = check.do_check(&fn_ctxt);