Skip to content

Implement pin-project in pattern matching for &pin mut|const T #139751

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -1588,7 +1588,7 @@ fn suggest_ampmut<'tcx>(
} else {
// otherwise, suggest that the user annotates the binding; we provide the
// type of the local.
let ty = decl_ty.builtin_deref(true).unwrap();
let ty = decl_ty.builtin_deref(true, tcx).unwrap();

Some(AmpMutSugg {
has_sugg: false,
Expand Down
5 changes: 4 additions & 1 deletion compiler/rustc_borrowck/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2472,7 +2472,10 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, '_, 'tcx> {

// Check the kind of deref to decide
match base_ty.kind() {
ty::Ref(_, _, mutbl) => {
_ if let Some((_, _, _, mutbl)) =
base_ty.is_ref_or_pin_ref(self.infcx.tcx) =>
{
// FIXME(pin_ergonomics): handle `&pin mut|const T`
match mutbl {
// Shared borrowed data is never mutable
hir::Mutability::Not => Err(place),
Expand Down
7 changes: 5 additions & 2 deletions compiler/rustc_borrowck/src/type_check/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1761,7 +1761,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
} else if let Some(static_def_id) = constant.check_static_ptr(tcx) {
let unnormalized_ty = tcx.type_of(static_def_id).instantiate_identity();
let normalized_ty = self.normalize(unnormalized_ty, locations);
let literal_ty = constant.const_.ty().builtin_deref(true).unwrap();
let literal_ty = constant.const_.ty().builtin_deref(true, tcx).unwrap();

if let Err(terr) =
self.eq_types(literal_ty, normalized_ty, locations, ConstraintCategory::Boring)
Expand Down Expand Up @@ -2360,7 +2360,10 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {

debug!("add_reborrow_constraint - base_ty = {:?}", base_ty);
match base_ty.kind() {
ty::Ref(ref_region, _, mutbl) => {
_ if let Some((ref_region, _, _, mutbl)) =
base_ty.is_ref_or_pin_ref(tcx) =>
{
// FIXME(pin_ergonomics): handle `&pin mut|const T`
constraints.outlives_constraints.push(OutlivesConstraint {
sup: ref_region.as_var(),
sub: borrow_region.as_var(),
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_codegen_cranelift/src/base.rs
Original file line number Diff line number Diff line change
Expand Up @@ -729,7 +729,7 @@ fn codegen_stmt<'tcx>(
let to_ty = fx.monomorphize(to_ty);

fn is_wide_ptr<'tcx>(fx: &FunctionCx<'_, '_, 'tcx>, ty: Ty<'tcx>) -> bool {
ty.builtin_deref(true).is_some_and(|pointee_ty| {
ty.builtin_deref(true, fx.tcx).is_some_and(|pointee_ty| {
fx.tcx
.type_has_metadata(pointee_ty, ty::TypingEnv::fully_monomorphized())
})
Expand Down
6 changes: 3 additions & 3 deletions compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -583,7 +583,7 @@ fn codegen_regular_intrinsic_call<'tcx>(
intrinsic_args!(fx, args => (base, offset); intrinsic);
let offset = offset.load_scalar(fx);

let pointee_ty = base.layout().ty.builtin_deref(true).unwrap();
let pointee_ty = base.layout().ty.builtin_deref(true, fx.tcx).unwrap();
let pointee_size = fx.layout_of(pointee_ty).size.bytes();
let ptr_diff = if pointee_size != 1 {
fx.bcx.ins().imul_imm(offset, pointee_size as i64)
Expand All @@ -609,7 +609,7 @@ fn codegen_regular_intrinsic_call<'tcx>(
let val = val.load_scalar(fx);
let count = count.load_scalar(fx);

let pointee_ty = dst.layout().ty.builtin_deref(true).unwrap();
let pointee_ty = dst.layout().ty.builtin_deref(true, fx.tcx).unwrap();
let pointee_size = fx.layout_of(pointee_ty).size.bytes();
let count = if pointee_size != 1 {
fx.bcx.ins().imul_imm(count, pointee_size as i64)
Expand Down Expand Up @@ -717,7 +717,7 @@ fn codegen_regular_intrinsic_call<'tcx>(

// Cranelift treats loads as volatile by default
// FIXME correctly handle unaligned_volatile_load
let inner_layout = fx.layout_of(ptr.layout().ty.builtin_deref(true).unwrap());
let inner_layout = fx.layout_of(ptr.layout().ty.builtin_deref(true, fx.tcx).unwrap());
let val = CValue::by_ref(Pointer::new(ptr.load_scalar(fx)), inner_layout);
ret.write_cvalue(fx, val);
}
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs
Original file line number Diff line number Diff line change
Expand Up @@ -897,7 +897,7 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>(
intrinsic_args!(fx, args => (ptr, offset); intrinsic);

let (lane_count, ptr_lane_ty) = ptr.layout().ty.simd_size_and_type(fx.tcx);
let pointee_ty = ptr_lane_ty.builtin_deref(true).unwrap();
let pointee_ty = ptr_lane_ty.builtin_deref(true, fx.tcx).unwrap();
let pointee_size = fx.layout_of(pointee_ty).size.bytes();
let (ret_lane_count, ret_lane_ty) = ret.layout().ty.simd_size_and_type(fx.tcx);
let ret_lane_layout = fx.layout_of(ret_lane_ty);
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_codegen_cranelift/src/num.rs
Original file line number Diff line number Diff line change
Expand Up @@ -398,7 +398,7 @@ pub(crate) fn codegen_ptr_binop<'tcx>(
let is_thin_ptr = in_lhs
.layout()
.ty
.builtin_deref(true)
.builtin_deref(true, fx.tcx)
.map(|ty| !fx.tcx.type_has_metadata(ty, ty::TypingEnv::fully_monomorphized()))
.unwrap_or(true);

Expand All @@ -411,7 +411,7 @@ pub(crate) fn codegen_ptr_binop<'tcx>(
codegen_compare_bin_op(fx, bin_op, false, lhs, rhs)
}
BinOp::Offset => {
let pointee_ty = in_lhs.layout().ty.builtin_deref(true).unwrap();
let pointee_ty = in_lhs.layout().ty.builtin_deref(true, fx.tcx).unwrap();
let (base, offset) = (in_lhs, in_rhs.load_scalar(fx));
let pointee_size = fx.layout_of(pointee_ty).size.bytes();
let ptr_diff = fx.bcx.ins().imul_imm(offset, pointee_size as i64);
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_codegen_cranelift/src/unsize.rs
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@ pub(crate) fn coerce_unsized_into<'tcx>(
let dst_ty = dst.layout().ty;
let mut coerce_ptr = || {
let (base, info) =
if fx.layout_of(src.layout().ty.builtin_deref(true).unwrap()).is_unsized() {
if fx.layout_of(src.layout().ty.builtin_deref(true, fx.tcx).unwrap()).is_unsized() {
let (old_base, old_info) = src.load_scalar_pair(fx);
unsize_ptr(fx, old_base, src.layout(), dst.layout(), Some(old_info))
} else {
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_codegen_cranelift/src/value_and_place.rs
Original file line number Diff line number Diff line change
Expand Up @@ -831,7 +831,7 @@ impl<'tcx> CPlace<'tcx> {
}

pub(crate) fn place_deref(self, fx: &mut FunctionCx<'_, '_, 'tcx>) -> CPlace<'tcx> {
let inner_layout = fx.layout_of(self.layout().ty.builtin_deref(true).unwrap());
let inner_layout = fx.layout_of(self.layout().ty.builtin_deref(true, fx.tcx).unwrap());
if fx.tcx.type_has_metadata(inner_layout.ty, ty::TypingEnv::fully_monomorphized()) {
let (addr, extra) = self.to_cvalue(fx).load_scalar_pair(fx);
CPlace::for_ptr_with_extra(Pointer::new(addr), extra, inner_layout)
Expand Down
3 changes: 2 additions & 1 deletion compiler/rustc_codegen_cranelift/src/vtable.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,8 @@ pub(crate) fn get_ptr_and_method_ref<'tcx>(

if let ty::Ref(_, ty, _) = arg.layout().ty.kind() {
if ty.is_dyn_star() {
let inner_layout = fx.layout_of(arg.layout().ty.builtin_deref(true).unwrap());
let inner_layout =
fx.layout_of(arg.layout().ty.builtin_deref(true, fx.tcx).unwrap());
let dyn_star = CPlace::for_ptr(Pointer::new(arg.load_scalar(fx)), inner_layout);
let ptr = dyn_star.place_field(fx, FieldIdx::ZERO).to_ptr();
let vtable =
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_codegen_llvm/src/abi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -626,7 +626,7 @@ impl<'ll, 'tcx> FnAbiLlvmExt<'ll, 'tcx> for FnAbi<'tcx, Ty<'tcx>> {
let element_type_index = unsafe { llvm::LLVMRustGetElementTypeArgIndex(callsite) };
if element_type_index >= 0 {
let arg_ty = self.args[element_type_index as usize].layout.ty;
let pointee_ty = arg_ty.builtin_deref(true).expect("Must be pointer argument");
let pointee_ty = arg_ty.builtin_deref(true, bx.tcx).expect("Must be pointer argument");
let element_type_attr = unsafe {
llvm::LLVMRustCreateElementTypeAttr(bx.llcx, bx.layout_of(pointee_ty).llvm_type(bx))
};
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_codegen_llvm/src/intrinsic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2532,7 +2532,7 @@ fn generic_simd_intrinsic<'ll, 'tcx>(

if name == sym::simd_arith_offset {
// This also checks that the first operand is a ptr type.
let pointee = in_elem.builtin_deref(true).unwrap_or_else(|| {
let pointee = in_elem.builtin_deref(true, bx.tcx).unwrap_or_else(|| {
span_bug!(span, "must be called with a vector of pointer types as first argument")
});
let layout = bx.layout_of(pointee);
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_codegen_ssa/src/mir/block.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1106,7 +1106,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {

// Make sure that we've actually unwrapped the rcvr down
// to a pointer or ref to `dyn* Trait`.
if !op.layout.ty.builtin_deref(true).unwrap().is_dyn_star() {
if !op.layout.ty.builtin_deref(true, bx.tcx()).unwrap().is_dyn_star() {
span_bug!(span, "can't codegen a virtual call on {:#?}", op);
}
let place = op.deref(bx.cx());
Expand Down
4 changes: 3 additions & 1 deletion compiler/rustc_codegen_ssa/src/mir/debuginfo.rs
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,9 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> DebugInfoOffsetLocation<'tcx, Bx>
{
fn deref(&self, bx: &mut Bx) -> Self {
bx.cx().layout_of(
self.ty.builtin_deref(true).unwrap_or_else(|| bug!("cannot deref `{}`", self.ty)),
self.ty
.builtin_deref(true, bx.tcx())
.unwrap_or_else(|| bug!("cannot deref `{}`", self.ty)),
)
}

Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_codegen_ssa/src/mir/operand.rs
Original file line number Diff line number Diff line change
Expand Up @@ -291,7 +291,7 @@ impl<'a, 'tcx, V: CodegenObject> OperandRef<'tcx, V> {
let projected_ty = self
.layout
.ty
.builtin_deref(true)
.builtin_deref(true, cx.tcx())
.unwrap_or_else(|| bug!("deref of non-pointer {:?}", self));

let layout = cx.layout_of(projected_ty);
Expand Down Expand Up @@ -701,7 +701,7 @@ impl<'a, 'tcx, V: CodegenObject> OperandValue<V> {
let unsized_ty = indirect_dest
.layout
.ty
.builtin_deref(true)
.builtin_deref(true, bx.tcx())
.unwrap_or_else(|| bug!("indirect_dest has non-pointer type: {:?}", indirect_dest));

let OperandValue::Ref(PlaceValue { llval: llptr, llextra: Some(llextra), .. }) = self
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_codegen_ssa/src/mir/rvalue.rs
Original file line number Diff line number Diff line change
Expand Up @@ -966,7 +966,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
mir::BinOp::BitXor => bx.xor(lhs, rhs),
mir::BinOp::Offset => {
let pointee_type = lhs_ty
.builtin_deref(true)
.builtin_deref(true, bx.tcx())
.unwrap_or_else(|| bug!("deref of non-pointer {:?}", lhs_ty));
let pointee_layout = bx.cx().layout_of(pointee_type);
if pointee_layout.is_zst() {
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_const_eval/src/const_eval/eval_queries.rs
Original file line number Diff line number Diff line change
Expand Up @@ -216,7 +216,7 @@ pub(super) fn op_to_const<'tcx>(
// This codepath solely exists for `valtree_to_const_value` to not need to generate
// a `ConstValue::Indirect` for wide references, so it is tightly restricted to just
// that case.
let pointee_ty = imm.layout.ty.builtin_deref(false).unwrap(); // `false` = no raw ptrs
let pointee_ty = imm.layout.ty.builtin_deref(false, *ecx.tcx).unwrap(); // `false` = no raw ptrs
debug_assert!(
matches!(
ecx.tcx.struct_tail_for_codegen(pointee_ty, ecx.typing_env()).kind(),
Expand Down
6 changes: 3 additions & 3 deletions compiler/rustc_const_eval/src/interpret/intrinsics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -636,7 +636,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
nonoverlapping: bool,
) -> InterpResult<'tcx> {
let count = self.read_target_usize(count)?;
let layout = self.layout_of(src.layout.ty.builtin_deref(true).unwrap())?;
let layout = self.layout_of(src.layout.ty.builtin_deref(true, *self.tcx).unwrap())?;
let (size, align) = (layout.size, layout.align.abi);

let size = self.compute_size_in_bytes(size, count).ok_or_else(|| {
Expand Down Expand Up @@ -696,7 +696,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
count: &OpTy<'tcx, <M as Machine<'tcx>>::Provenance>,
name: &'static str,
) -> InterpResult<'tcx> {
let layout = self.layout_of(dst.layout.ty.builtin_deref(true).unwrap())?;
let layout = self.layout_of(dst.layout.ty.builtin_deref(true, *self.tcx).unwrap())?;

let dst = self.read_pointer(dst)?;
let byte = self.read_scalar(byte)?.to_u8()?;
Expand Down Expand Up @@ -735,7 +735,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
lhs: &OpTy<'tcx, <M as Machine<'tcx>>::Provenance>,
rhs: &OpTy<'tcx, <M as Machine<'tcx>>::Provenance>,
) -> InterpResult<'tcx, Scalar<M::Provenance>> {
let layout = self.layout_of(lhs.layout.ty.builtin_deref(true).unwrap())?;
let layout = self.layout_of(lhs.layout.ty.builtin_deref(true, *self.tcx).unwrap())?;
assert!(layout.is_sized());

let get_bytes = |this: &InterpCx<'tcx, M>,
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_const_eval/src/interpret/operator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -313,7 +313,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
// Pointer ops that are always supported.
Offset => {
let ptr = left.to_scalar().to_pointer(self)?;
let pointee_ty = left.layout.ty.builtin_deref(true).unwrap();
let pointee_ty = left.layout.ty.builtin_deref(true, *self.tcx).unwrap();
let pointee_layout = self.layout_of(pointee_ty)?;
assert!(pointee_layout.is_sized());

Expand Down
7 changes: 5 additions & 2 deletions compiler/rustc_const_eval/src/interpret/place.rs
Original file line number Diff line number Diff line change
Expand Up @@ -419,8 +419,11 @@ where
&self,
val: &ImmTy<'tcx, M::Provenance>,
) -> InterpResult<'tcx, MPlaceTy<'tcx, M::Provenance>> {
let pointee_type =
val.layout.ty.builtin_deref(true).expect("`ref_to_mplace` called on non-ptr type");
let pointee_type = val
.layout
.ty
.builtin_deref(true, *self.tcx)
.expect("`ref_to_mplace` called on non-ptr type");
let layout = self.layout_of(pointee_type)?;
let (ptr, meta) = val.to_scalar_and_meta();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ fn check_validity_requirement_lax<'tcx>(
}

// Special magic check for references and boxes (i.e., special pointer types).
if let Some(pointee) = this.ty.builtin_deref(false) {
if let Some(pointee) = this.ty.builtin_deref(false, cx.tcx()) {
let pointee = cx.layout_of(pointee)?;
// We need to ensure that the LLVM attributes `aligned` and `dereferenceable(size)` are satisfied.
if pointee.align.abi.bytes() > 1 {
Expand Down
41 changes: 21 additions & 20 deletions compiler/rustc_hir_analysis/src/autoderef.rs
Original file line number Diff line number Diff line change
Expand Up @@ -77,27 +77,28 @@ impl<'a, 'tcx> Iterator for Autoderef<'a, 'tcx> {
// be better to skip this clause and use the Overloaded case only, since &T
// and &mut T implement Receiver. But built-in derefs apply equally to Receiver
// and Deref, and this has benefits for const and the emitted MIR.
let (kind, new_ty) =
if let Some(ty) = self.state.cur_ty.builtin_deref(self.include_raw_pointers) {
debug_assert_eq!(ty, self.infcx.resolve_vars_if_possible(ty));
// NOTE: we may still need to normalize the built-in deref in case
// we have some type like `&<Ty as Trait>::Assoc`, since users of
// autoderef expect this type to have been structurally normalized.
if self.infcx.next_trait_solver()
&& let ty::Alias(..) = ty.kind()
{
let (normalized_ty, obligations) = self.structurally_normalize_ty(ty)?;
self.state.obligations.extend(obligations);
(AutoderefKind::Builtin, normalized_ty)
} else {
(AutoderefKind::Builtin, ty)
}
} else if let Some(ty) = self.overloaded_deref_ty(self.state.cur_ty) {
// The overloaded deref check already normalizes the pointee type.
(AutoderefKind::Overloaded, ty)
let (kind, new_ty) = if let Some(ty) =
self.state.cur_ty.builtin_deref(self.include_raw_pointers, self.infcx.tcx)
{
debug_assert_eq!(ty, self.infcx.resolve_vars_if_possible(ty));
// NOTE: we may still need to normalize the built-in deref in case
// we have some type like `&<Ty as Trait>::Assoc`, since users of
// autoderef expect this type to have been structurally normalized.
if self.infcx.next_trait_solver()
&& let ty::Alias(..) = ty.kind()
{
let (normalized_ty, obligations) = self.structurally_normalize_ty(ty)?;
self.state.obligations.extend(obligations);
(AutoderefKind::Builtin, normalized_ty)
} else {
return None;
};
(AutoderefKind::Builtin, ty)
}
} else if let Some(ty) = self.overloaded_deref_ty(self.state.cur_ty) {
// The overloaded deref check already normalizes the pointee type.
(AutoderefKind::Overloaded, ty)
} else {
return None;
};

self.state.steps.push((self.state.cur_ty, kind));
debug!(
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_hir_analysis/src/check/wfcheck.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1808,7 +1808,7 @@ fn check_method_receiver<'tcx>(
match receiver_validity_err {
ReceiverValidityError::DoesNotDeref if arbitrary_self_types_level.is_some() => {
let hint = match receiver_ty
.builtin_deref(false)
.builtin_deref(false, tcx)
.unwrap_or(receiver_ty)
.ty_adt_def()
.and_then(|adt_def| tcx.get_diagnostic_name(adt_def.did()))
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_hir_typeck/src/expr_use_visitor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1265,7 +1265,7 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
match self
.cx
.try_structurally_resolve_type(pat.span, base_ty)
.builtin_deref(false)
.builtin_deref(false, self.cx.tcx())
{
Some(ty) => Ok(ty),
None => {
Expand Down Expand Up @@ -1555,7 +1555,7 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
let deref_ty = match self
.cx
.try_structurally_resolve_type(self.cx.tcx().hir_span(base_place.hir_id), base_curr_ty)
.builtin_deref(true)
.builtin_deref(true, self.cx.tcx())
{
Some(ty) => ty,
None => {
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -703,7 +703,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let ret_ty = method.sig.output();

// method returns &T, but the type as visible to user is T, so deref
ret_ty.builtin_deref(true).unwrap()
ret_ty.builtin_deref(true, self.tcx).unwrap()
}

pub(crate) fn type_var_is_sized(&self, self_ty: ty::TyVid) -> bool {
Expand Down
Loading
Loading