Skip to content

Commit 432972c

Browse files
committed
Auto merge of rust-lang#132275 - compiler-errors:deref-effects, r=fee1-dead
Register `~const` preds for `Deref` adjustments in HIR typeck This doesn't *do* anything yet, since `Deref` and `DerefMut` aren't constified, and we explicitly don't error on calling non-const trait methods in HIR yet -- presumably that will wait until std is re-constified. But I'm confident this logic is correct, and this (afaict?) is the only major hole left in enforcing `~const` in HIR typeck. r? fee1-dead
2 parents ca87b53 + e3bd6b2 commit 432972c

File tree

9 files changed

+140
-141
lines changed

9 files changed

+140
-141
lines changed

compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs

+26-4
Original file line numberDiff line numberDiff line change
@@ -254,10 +254,32 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
254254
}
255255

256256
for a in &adj {
257-
if let Adjust::NeverToAny = a.kind {
258-
if a.target.is_ty_var() {
259-
self.diverging_type_vars.borrow_mut().insert(a.target);
260-
debug!("apply_adjustments: adding `{:?}` as diverging type var", a.target);
257+
match a.kind {
258+
Adjust::NeverToAny => {
259+
if a.target.is_ty_var() {
260+
self.diverging_type_vars.borrow_mut().insert(a.target);
261+
debug!("apply_adjustments: adding `{:?}` as diverging type var", a.target);
262+
}
263+
}
264+
Adjust::Deref(Some(overloaded_deref)) => {
265+
self.enforce_context_effects(
266+
expr.span,
267+
overloaded_deref.method_call(self.tcx),
268+
self.tcx.mk_args(&[a.target.into()]),
269+
);
270+
}
271+
Adjust::Deref(None) => {
272+
// FIXME(effects): We *could* enforce `&T: ~const Deref` here.
273+
}
274+
Adjust::Pointer(_pointer_coercion) => {
275+
// FIXME(effects): We should probably enforce these.
276+
}
277+
Adjust::ReborrowPin(_mutability) => {
278+
// FIXME(effects): We could enforce these; they correspond to
279+
// `&mut T: DerefMut` tho, so it's kinda moot.
280+
}
281+
Adjust::Borrow(_) => {
282+
// No effects to enforce here.
261283
}
262284
}
263285
}

compiler/rustc_hir_typeck/src/place_op.rs

+1
Original file line numberDiff line numberDiff line change
@@ -296,6 +296,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
296296
);
297297
};
298298
*deref = OverloadedDeref { mutbl, span: deref.span };
299+
self.enforce_context_effects(expr.span, method.def_id, method.args);
299300
// If this is a union field, also throw an error for `DerefMut` of `ManuallyDrop` (see RFC 2514).
300301
// This helps avoid accidental drops.
301302
if inside_union

compiler/rustc_middle/src/ty/adjustment.rs

+6-6
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use rustc_abi::FieldIdx;
22
use rustc_hir as hir;
3+
use rustc_hir::def_id::DefId;
34
use rustc_hir::lang_items::LangItem;
45
use rustc_macros::{HashStable, TyDecodable, TyEncodable, TypeFoldable, TypeVisitable};
56
use rustc_span::Span;
@@ -123,19 +124,18 @@ pub struct OverloadedDeref {
123124
}
124125

125126
impl OverloadedDeref {
126-
/// Get the zst function item type for this method call.
127-
pub fn method_call<'tcx>(&self, tcx: TyCtxt<'tcx>, source: Ty<'tcx>) -> Ty<'tcx> {
127+
/// Get the [`DefId`] of the method call for the given `Deref`/`DerefMut` trait
128+
/// for this overloaded deref's mutability.
129+
pub fn method_call<'tcx>(&self, tcx: TyCtxt<'tcx>) -> DefId {
128130
let trait_def_id = match self.mutbl {
129131
hir::Mutability::Not => tcx.require_lang_item(LangItem::Deref, None),
130132
hir::Mutability::Mut => tcx.require_lang_item(LangItem::DerefMut, None),
131133
};
132-
let method_def_id = tcx
133-
.associated_items(trait_def_id)
134+
tcx.associated_items(trait_def_id)
134135
.in_definition_order()
135136
.find(|m| m.kind == ty::AssocKind::Fn)
136137
.unwrap()
137-
.def_id;
138-
Ty::new_fn_def(tcx, method_def_id, [source])
138+
.def_id
139139
}
140140
}
141141

compiler/rustc_mir_build/src/thir/cx/expr.rs

+10-2
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,9 @@ impl<'tcx> Cx<'tcx> {
136136
Adjust::Deref(Some(deref)) => {
137137
// We don't need to do call adjust_span here since
138138
// deref coercions always start with a built-in deref.
139-
let call = deref.method_call(self.tcx(), expr.ty);
139+
let call_def_id = deref.method_call(self.tcx());
140+
let overloaded_callee =
141+
Ty::new_fn_def(self.tcx(), call_def_id, self.tcx().mk_args(&[expr.ty.into()]));
140142

141143
expr = Expr {
142144
temp_lifetime,
@@ -150,7 +152,13 @@ impl<'tcx> Cx<'tcx> {
150152

151153
let expr = Box::new([self.thir.exprs.push(expr)]);
152154

153-
self.overloaded_place(hir_expr, adjustment.target, Some(call), expr, deref.span)
155+
self.overloaded_place(
156+
hir_expr,
157+
adjustment.target,
158+
Some(overloaded_callee),
159+
expr,
160+
deref.span,
161+
)
154162
}
155163
Adjust::Borrow(AutoBorrow::Ref(m)) => ExprKind::Borrow {
156164
borrow_kind: m.to_borrow_kind(),

0 commit comments

Comments
 (0)