Properly analyze captures from unsafe binders
This commit is contained in:
parent
52bf0cf795
commit
04ddafc53c
7 changed files with 51 additions and 5 deletions
|
|
@ -13,6 +13,7 @@ use hir::Expr;
|
|||
use hir::def::DefKind;
|
||||
use hir::pat_util::EnumerateAndAdjustIterator as _;
|
||||
use rustc_abi::{FIRST_VARIANT, FieldIdx, VariantIdx};
|
||||
use rustc_ast::UnsafeBinderCastKind;
|
||||
use rustc_data_structures::fx::FxIndexMap;
|
||||
use rustc_hir::def::{CtorOf, Res};
|
||||
use rustc_hir::def_id::LocalDefId;
|
||||
|
|
@ -1393,10 +1394,18 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
|
|||
self.cat_res(expr.hir_id, expr.span, expr_ty, res)
|
||||
}
|
||||
|
||||
// both type ascription and unsafe binder casts don't affect
|
||||
// the place-ness of the subexpression.
|
||||
// type ascription doesn't affect the place-ness of the subexpression.
|
||||
hir::ExprKind::Type(e, _) => self.cat_expr(e),
|
||||
hir::ExprKind::UnsafeBinderCast(_, e, _) => self.cat_expr(e),
|
||||
|
||||
hir::ExprKind::UnsafeBinderCast(UnsafeBinderCastKind::Unwrap, e, _) => {
|
||||
let base = self.cat_expr(e)?;
|
||||
Ok(self.cat_projection(
|
||||
expr.hir_id,
|
||||
base,
|
||||
expr_ty,
|
||||
ProjectionKind::UnwrapUnsafeBinder,
|
||||
))
|
||||
}
|
||||
|
||||
hir::ExprKind::AddrOf(..)
|
||||
| hir::ExprKind::Call(..)
|
||||
|
|
@ -1427,6 +1436,7 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
|
|||
| hir::ExprKind::Repeat(..)
|
||||
| hir::ExprKind::InlineAsm(..)
|
||||
| hir::ExprKind::OffsetOf(..)
|
||||
| hir::ExprKind::UnsafeBinderCast(UnsafeBinderCastKind::Wrap, ..)
|
||||
| hir::ExprKind::Err(_) => Ok(self.cat_rvalue(expr.hir_id, expr_ty)),
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -902,7 +902,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
fn is_field<'a>(p: &&Projection<'a>) -> bool {
|
||||
match p.kind {
|
||||
ProjectionKind::Field(_, _) => true,
|
||||
ProjectionKind::Deref | ProjectionKind::OpaqueCast => false,
|
||||
ProjectionKind::Deref
|
||||
| ProjectionKind::OpaqueCast
|
||||
| ProjectionKind::UnwrapUnsafeBinder => false,
|
||||
p @ (ProjectionKind::Subslice | ProjectionKind::Index) => {
|
||||
bug!("ProjectionKind {:?} was unexpected", p)
|
||||
}
|
||||
|
|
@ -2197,7 +2199,8 @@ fn restrict_capture_precision(
|
|||
}
|
||||
ProjectionKind::Deref => {}
|
||||
ProjectionKind::OpaqueCast => {}
|
||||
ProjectionKind::Field(..) => {} // ignore
|
||||
ProjectionKind::Field(..) => {}
|
||||
ProjectionKind::UnwrapUnsafeBinder => {}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -2268,6 +2271,7 @@ fn construct_place_string<'tcx>(tcx: TyCtxt<'_>, place: &Place<'tcx>) -> String
|
|||
ProjectionKind::Index => String::from("Index"),
|
||||
ProjectionKind::Subslice => String::from("Subslice"),
|
||||
ProjectionKind::OpaqueCast => String::from("OpaqueCast"),
|
||||
ProjectionKind::UnwrapUnsafeBinder => String::from("UnwrapUnsafeBinder"),
|
||||
};
|
||||
if i != 0 {
|
||||
projections_str.push(',');
|
||||
|
|
|
|||
|
|
@ -43,6 +43,9 @@ pub enum ProjectionKind {
|
|||
///
|
||||
/// This is unused if `-Znext-solver` is enabled.
|
||||
OpaqueCast,
|
||||
|
||||
/// `unwrap_binder!(expr)`
|
||||
UnwrapUnsafeBinder,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, TyEncodable, TyDecodable, HashStable)]
|
||||
|
|
|
|||
|
|
@ -240,6 +240,9 @@ fn strip_prefix<'tcx>(
|
|||
HirProjectionKind::OpaqueCast => {
|
||||
assert_matches!(iter.next(), Some(ProjectionElem::OpaqueCast(..)));
|
||||
}
|
||||
HirProjectionKind::UnwrapUnsafeBinder => {
|
||||
assert_matches!(iter.next(), Some(ProjectionElem::UnwrapUnsafeBinder(..)));
|
||||
}
|
||||
HirProjectionKind::Index | HirProjectionKind::Subslice => {
|
||||
bug!("unexpected projection kind: {:?}", projection);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1220,6 +1220,9 @@ impl<'tcx> ThirBuildCx<'tcx> {
|
|||
HirProjectionKind::OpaqueCast => {
|
||||
ExprKind::Use { source: self.thir.exprs.push(captured_place_expr) }
|
||||
}
|
||||
HirProjectionKind::UnwrapUnsafeBinder => ExprKind::PlaceUnwrapUnsafeBinder {
|
||||
source: self.thir.exprs.push(captured_place_expr),
|
||||
},
|
||||
HirProjectionKind::Index | HirProjectionKind::Subslice => {
|
||||
// We don't capture these projections, so we can ignore them here
|
||||
continue;
|
||||
|
|
|
|||
|
|
@ -941,6 +941,8 @@ impl<'tcx> Delegate<'tcx> for DerefDelegate<'_, 'tcx> {
|
|||
ProjectionKind::Subslice |
|
||||
// Doesn't have surface syntax. Only occurs in patterns.
|
||||
ProjectionKind::OpaqueCast => (),
|
||||
// Only occurs in closure captures.
|
||||
ProjectionKind::UnwrapUnsafeBinder => (),
|
||||
ProjectionKind::Deref => {
|
||||
// Explicit derefs are typically handled later on, but
|
||||
// some items do not need explicit deref, such as array accesses,
|
||||
|
|
|
|||
21
tests/ui/unsafe-binders/cat-projection.rs
Normal file
21
tests/ui/unsafe-binders/cat-projection.rs
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
//@ check-pass
|
||||
|
||||
#![feature(unsafe_binders)]
|
||||
#![allow(incomplete_features)]
|
||||
|
||||
use std::unsafe_binder::unwrap_binder;
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
pub struct S([usize; 8]);
|
||||
|
||||
// Regression test for <https://github.com/rust-lang/rust/issues/141418>.
|
||||
pub fn by_value(x: unsafe<'a> S) -> usize {
|
||||
unsafe { (|| unwrap_binder!(x).0[0])() }
|
||||
}
|
||||
|
||||
// Regression test for <https://github.com/rust-lang/rust/issues/141417>.
|
||||
pub fn by_ref(x: unsafe<'a> &'a S) -> usize {
|
||||
unsafe { (|| unwrap_binder!(x).0[0])() }
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
Loading…
Add table
Add a link
Reference in a new issue