diff options
| author | 许杰友 Jieyou Xu (Joe) <39484203+jieyouxu@users.noreply.github.com> | 2025-05-27 01:29:18 +0800 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2025-05-27 01:29:18 +0800 |
| commit | 9f93c48ddcb51416599b8a93116f9771b988d06e (patch) | |
| tree | 75793aa7cc135a4ca14c0a91b93ad80d0a5d47cf | |
| parent | 0e710d0883709d34bfbb76f6813a83fa8fb96c23 (diff) | |
| parent | 04ddafc53ce0e045bae86ad0b20f5be540ca0e84 (diff) | |
| download | rust-9f93c48ddcb51416599b8a93116f9771b988d06e.tar.gz rust-9f93c48ddcb51416599b8a93116f9771b988d06e.zip | |
Rollup merge of #141433 - compiler-errors:unsafe-binder-captures, r=oli-obk
Properly analyze captures from unsafe binders We need to represent the unsafe binder unwrap as an adjustment in HIR. Pretty straightforward b/c we already represent it as a projection elem in MIR. Fixes #141418 Fixes #141417 r? oli-obk
| -rw-r--r-- | compiler/rustc_hir_typeck/src/expr_use_visitor.rs | 16 | ||||
| -rw-r--r-- | compiler/rustc_hir_typeck/src/upvar.rs | 8 | ||||
| -rw-r--r-- | compiler/rustc_middle/src/hir/place.rs | 3 | ||||
| -rw-r--r-- | compiler/rustc_mir_build/src/builder/expr/as_place.rs | 3 | ||||
| -rw-r--r-- | compiler/rustc_mir_build/src/thir/cx/expr.rs | 3 | ||||
| -rw-r--r-- | src/tools/clippy/clippy_utils/src/sugg.rs | 2 | ||||
| -rw-r--r-- | tests/ui/unsafe-binders/cat-projection.rs | 21 |
7 files changed, 51 insertions, 5 deletions
diff --git a/compiler/rustc_hir_typeck/src/expr_use_visitor.rs b/compiler/rustc_hir_typeck/src/expr_use_visitor.rs index 3493d359028..20341318828 100644 --- a/compiler/rustc_hir_typeck/src/expr_use_visitor.rs +++ b/compiler/rustc_hir_typeck/src/expr_use_visitor.rs @@ -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)), } } diff --git a/compiler/rustc_hir_typeck/src/upvar.rs b/compiler/rustc_hir_typeck/src/upvar.rs index 8ab71e5220b..4b2e87f5674 100644 --- a/compiler/rustc_hir_typeck/src/upvar.rs +++ b/compiler/rustc_hir_typeck/src/upvar.rs @@ -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(','); diff --git a/compiler/rustc_middle/src/hir/place.rs b/compiler/rustc_middle/src/hir/place.rs index c3d10615cf1..a34a3419d68 100644 --- a/compiler/rustc_middle/src/hir/place.rs +++ b/compiler/rustc_middle/src/hir/place.rs @@ -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)] diff --git a/compiler/rustc_mir_build/src/builder/expr/as_place.rs b/compiler/rustc_mir_build/src/builder/expr/as_place.rs index fbe53081156..830a129c585 100644 --- a/compiler/rustc_mir_build/src/builder/expr/as_place.rs +++ b/compiler/rustc_mir_build/src/builder/expr/as_place.rs @@ -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); } diff --git a/compiler/rustc_mir_build/src/thir/cx/expr.rs b/compiler/rustc_mir_build/src/thir/cx/expr.rs index fde23413972..226dc920a49 100644 --- a/compiler/rustc_mir_build/src/thir/cx/expr.rs +++ b/compiler/rustc_mir_build/src/thir/cx/expr.rs @@ -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; diff --git a/src/tools/clippy/clippy_utils/src/sugg.rs b/src/tools/clippy/clippy_utils/src/sugg.rs index 93dec113d31..f4dfc8f4b5a 100644 --- a/src/tools/clippy/clippy_utils/src/sugg.rs +++ b/src/tools/clippy/clippy_utils/src/sugg.rs @@ -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, diff --git a/tests/ui/unsafe-binders/cat-projection.rs b/tests/ui/unsafe-binders/cat-projection.rs new file mode 100644 index 00000000000..dd7a78d59b3 --- /dev/null +++ b/tests/ui/unsafe-binders/cat-projection.rs @@ -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() {} |
