Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 432972c

Browse files
committedNov 4, 2024
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

Lines changed: 26 additions & 4 deletions
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

Lines changed: 1 addition & 0 deletions
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

Lines changed: 6 additions & 6 deletions
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

Lines changed: 10 additions & 2 deletions
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(),

‎tests/ui/traits/const-traits/effects/minicore.rs renamed to ‎tests/ui/traits/const-traits/effects/auxiliary/minicore.rs

Lines changed: 46 additions & 116 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,7 @@
1-
//@ known-bug: #110395
2-
//@ failure-status: 101
3-
//@ normalize-stderr-test: ".*note: .*\n\n" -> ""
4-
//@ normalize-stderr-test: "thread 'rustc' panicked.*:\n.*\n" -> ""
5-
//@ rustc-env:RUST_BACKTRACE=0
6-
// FIXME(const_trait_impl) check-pass
7-
//@ compile-flags: -Znext-solver
8-
9-
#![crate_type = "lib"]
1+
//@ compile-flags: -Znext-solver -Cpanic=abort
2+
//@ no-prefer-dynamic
3+
4+
#![crate_type = "rlib"]
105
#![feature(
116
no_core,
127
lang_items,
@@ -23,13 +18,17 @@
2318
#![no_core]
2419

2520
#[lang = "sized"]
26-
trait Sized {}
21+
pub trait Sized {}
2722
#[lang = "copy"]
28-
trait Copy {}
23+
pub trait Copy {}
24+
25+
impl Copy for bool {}
26+
impl Copy for u8 {}
27+
impl<T: ?Sized> Copy for &T {}
2928

3029
#[lang = "add"]
3130
#[const_trait]
32-
trait Add<Rhs = Self> {
31+
pub trait Add<Rhs = Self> {
3332
type Output;
3433

3534
fn add(self, rhs: Rhs) -> Self::Output;
@@ -50,10 +49,9 @@ const fn bar() {
5049
let x = 42_i32 + 43_i32;
5150
}
5251

53-
5452
#[lang = "Try"]
5553
#[const_trait]
56-
trait Try: FromResidual<Self::Residual> {
54+
pub trait Try: FromResidual<Self::Residual> {
5755
type Output;
5856
type Residual;
5957

@@ -64,9 +62,8 @@ trait Try: FromResidual<Self::Residual> {
6462
fn branch(self) -> ControlFlow<Self::Residual, Self::Output>;
6563
}
6664

67-
// FIXME
68-
// #[const_trait]
69-
trait FromResidual<R = <Self as /* FIXME: ~const */ Try>::Residual> {
65+
#[const_trait]
66+
pub trait FromResidual<R = <Self as Try>::Residual> {
7067
#[lang = "from_residual"]
7168
fn from_residual(residual: R) -> Self;
7269
}
@@ -81,102 +78,59 @@ enum ControlFlow<B, C = ()> {
8178
#[const_trait]
8279
#[lang = "fn"]
8380
#[rustc_paren_sugar]
84-
trait Fn<Args: Tuple>: ~const FnMut<Args> {
81+
pub trait Fn<Args: Tuple>: ~const FnMut<Args> {
8582
extern "rust-call" fn call(&self, args: Args) -> Self::Output;
8683
}
8784

8885
#[const_trait]
8986
#[lang = "fn_mut"]
9087
#[rustc_paren_sugar]
91-
trait FnMut<Args: Tuple>: ~const FnOnce<Args> {
88+
pub trait FnMut<Args: Tuple>: ~const FnOnce<Args> {
9289
extern "rust-call" fn call_mut(&mut self, args: Args) -> Self::Output;
9390
}
9491

9592
#[const_trait]
9693
#[lang = "fn_once"]
9794
#[rustc_paren_sugar]
98-
trait FnOnce<Args: Tuple> {
95+
pub trait FnOnce<Args: Tuple> {
9996
#[lang = "fn_once_output"]
10097
type Output;
10198

10299
extern "rust-call" fn call_once(self, args: Args) -> Self::Output;
103100
}
104101

105-
struct ConstFnMutClosure<CapturedData, Function> {
106-
data: CapturedData,
107-
func: Function,
108-
}
109-
110102
#[lang = "tuple_trait"]
111-
trait Tuple {}
112-
113-
macro_rules! impl_fn_mut_tuple {
114-
($($var:ident)*) => {
115-
impl<'a, $($var,)* ClosureArguments: Tuple, Function, ClosureReturnValue> const
116-
FnOnce<ClosureArguments> for ConstFnMutClosure<($(&'a mut $var),*), Function>
117-
where
118-
Function: ~const Fn(($(&mut $var),*), ClosureArguments) -> ClosureReturnValue,
119-
Function: ~const Destruct,
120-
{
121-
type Output = ClosureReturnValue;
122-
123-
extern "rust-call" fn call_once(mut self, args: ClosureArguments) -> Self::Output {
124-
self.call_mut(args)
125-
}
126-
}
127-
impl<'a, $($var,)* ClosureArguments: Tuple, Function, ClosureReturnValue> const
128-
FnMut<ClosureArguments> for ConstFnMutClosure<($(&'a mut $var),*), Function>
129-
where
130-
Function: ~const Fn(($(&mut $var),*), ClosureArguments)-> ClosureReturnValue,
131-
Function: ~const Destruct,
132-
{
133-
extern "rust-call" fn call_mut(&mut self, args: ClosureArguments) -> Self::Output {
134-
#[allow(non_snake_case)]
135-
let ($($var),*) = &mut self.data;
136-
(self.func)(($($var),*), args)
137-
}
138-
}
139-
};
140-
}
141-
//impl_fn_mut_tuple!(A);
142-
//impl_fn_mut_tuple!(A B);
143-
//impl_fn_mut_tuple!(A B C);
144-
//impl_fn_mut_tuple!(A B C D);
145-
//impl_fn_mut_tuple!(A B C D E);
103+
pub trait Tuple {}
146104

147105
#[lang = "legacy_receiver"]
148-
trait LegacyReceiver {}
106+
pub trait LegacyReceiver {}
149107

150108
impl<T: ?Sized> LegacyReceiver for &T {}
151109

152110
impl<T: ?Sized> LegacyReceiver for &mut T {}
153111

154112
#[lang = "destruct"]
155113
#[const_trait]
156-
trait Destruct {}
114+
pub trait Destruct {}
157115

158116
#[lang = "freeze"]
159-
unsafe auto trait Freeze {}
117+
pub unsafe auto trait Freeze {}
160118

161119
#[lang = "drop"]
162120
#[const_trait]
163-
trait Drop {
121+
pub trait Drop {
164122
fn drop(&mut self);
165123
}
166124

167-
/*
168125
#[const_trait]
169-
trait Residual<O> {
126+
pub trait Residual<O> {
170127
type TryType: ~const Try<Output = O, Residual = Self> + Try<Output = O, Residual = Self>;
171128
}
172-
*/
173129

174130
const fn size_of<T>() -> usize {
175131
42
176132
}
177133

178-
impl Copy for u8 {}
179-
180134
impl usize {
181135
#[rustc_allow_incoherent_impl]
182136
const fn repeat_u8(x: u8) -> usize {
@@ -197,15 +151,14 @@ fn panic_fmt() {}
197151

198152
#[lang = "index"]
199153
#[const_trait]
200-
trait Index<Idx: ?Sized> {
154+
pub trait Index<Idx: ?Sized> {
201155
type Output: ?Sized;
202156

203157
fn index(&self, index: Idx) -> &Self::Output;
204158
}
205159

206-
207160
#[const_trait]
208-
unsafe trait SliceIndex<T: ?Sized> {
161+
pub unsafe trait SliceIndex<T: ?Sized> {
209162
type Output: ?Sized;
210163
fn index(self, slice: &T) -> &Self::Output;
211164
}
@@ -221,51 +174,45 @@ where
221174
index.index(self)
222175
}
223176
}
224-
/* FIXME
177+
225178
impl<T, I, const N: usize> const Index<I> for [T; N]
226179
where
227180
[T]: ~const Index<I>,
228181
{
229182
type Output = <[T] as Index<I>>::Output;
230183

231184
#[inline]
232-
// FIXME: make `Self::Output` act like `<Self as ~const Index<I>>::Output`
233185
fn index(&self, index: I) -> &<[T] as Index<I>>::Output {
234186
Index::index(self as &[T], index)
235187
}
236188
}
237-
*/
238189

239190
#[lang = "unsize"]
240-
trait Unsize<T: ?Sized> {
241-
}
191+
pub trait Unsize<T: ?Sized> {}
242192

243193
#[lang = "coerce_unsized"]
244-
trait CoerceUnsized<T: ?Sized> {
245-
}
194+
pub trait CoerceUnsized<T: ?Sized> {}
246195

247196
impl<'a, 'b: 'a, T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<&'a U> for &'b T {}
248197

249-
250198
#[lang = "deref"]
251-
// #[const_trait] FIXME
252-
trait Deref {
199+
#[const_trait]
200+
pub trait Deref {
253201
#[lang = "deref_target"]
254202
type Target: ?Sized;
255203

256204
fn deref(&self) -> &Self::Target;
257205
}
258206

259-
260-
impl<T: ?Sized> /* const */ Deref for &T {
207+
impl<T: ?Sized> const Deref for &T {
261208
type Target = T;
262209

263210
fn deref(&self) -> &T {
264211
*self
265212
}
266213
}
267214

268-
impl<T: ?Sized> /* const */ Deref for &mut T {
215+
impl<T: ?Sized> const Deref for &mut T {
269216
type Target = T;
270217

271218
fn deref(&self) -> &T {
@@ -298,7 +245,6 @@ impl<T> Option<T> {
298245

299246
use Option::*;
300247

301-
/*
302248
const fn as_deref<T>(opt: &Option<T>) -> Option<&T::Target>
303249
where
304250
T: ~const Deref,
@@ -308,15 +254,14 @@ where
308254
Option::None => Option::None,
309255
}
310256
}
311-
*/
312257

313258
#[const_trait]
314-
trait Into<T>: Sized {
259+
pub trait Into<T>: Sized {
315260
fn into(self) -> T;
316261
}
317262

318263
#[const_trait]
319-
trait From<T>: Sized {
264+
pub trait From<T>: Sized {
320265
fn from(value: T) -> Self;
321266
}
322267

@@ -351,7 +296,7 @@ fn from_str(s: &str) -> Result<bool, ()> {
351296

352297
#[lang = "eq"]
353298
#[const_trait]
354-
trait PartialEq<Rhs: ?Sized = Self> {
299+
pub trait PartialEq<Rhs: ?Sized = Self> {
355300
fn eq(&self, other: &Rhs) -> bool;
356301
fn ne(&self, other: &Rhs) -> bool {
357302
!self.eq(other)
@@ -373,10 +318,9 @@ impl PartialEq for str {
373318
}
374319
}
375320

376-
377321
#[lang = "not"]
378322
#[const_trait]
379-
trait Not {
323+
pub trait Not {
380324
type Output;
381325
fn not(self) -> Self::Output;
382326
}
@@ -388,9 +332,6 @@ impl const Not for bool {
388332
}
389333
}
390334

391-
impl Copy for bool {}
392-
impl<'a> Copy for &'a str {}
393-
394335
#[lang = "pin"]
395336
#[fundamental]
396337
#[repr(transparent)]
@@ -411,23 +352,21 @@ impl<'a, T: ?Sized> Pin<&'a T> {
411352
}
412353
}
413354

414-
415355
impl<P: Deref> Pin<P> {
416-
/* const */ fn as_ref(&self) -> Pin<&P::Target>
356+
const fn as_ref(&self) -> Pin<&P::Target>
417357
where
418-
P: /* ~const */ Deref,
358+
P: ~const Deref,
419359
{
420360
unsafe { Pin::new_unchecked(&*self.pointer) }
421361
}
422362
}
423363

424-
425364
impl<'a, T: ?Sized> Pin<&'a mut T> {
426365
const unsafe fn get_unchecked_mut(self) -> &'a mut T {
427366
self.pointer
428367
}
429368
}
430-
/* FIXME lol
369+
431370
impl<T> Option<T> {
432371
const fn as_pin_ref(self: Pin<&Self>) -> Option<Pin<&T>> {
433372
match Pin::get_ref(self).as_ref() {
@@ -445,16 +384,15 @@ impl<T> Option<T> {
445384
}
446385
}
447386
}
448-
*/
449387

450-
impl<P: /* ~const */ Deref> /* const */ Deref for Pin<P> {
388+
impl<P: ~const Deref> const Deref for Pin<P> {
451389
type Target = P::Target;
452390
fn deref(&self) -> &P::Target {
453391
Pin::get_ref(Pin::as_ref(self))
454392
}
455393
}
456394

457-
impl<T> /* const */ Deref for Option<T> {
395+
impl<T> const Deref for Option<T> {
458396
type Target = T;
459397
fn deref(&self) -> &T {
460398
loop {}
@@ -506,23 +444,22 @@ impl<T: ?Sized> Deref for Ref<'_, T> {
506444

507445
#[lang = "clone"]
508446
#[rustc_trivial_field_reads]
509-
#[const_trait]
510-
trait Clone: Sized {
447+
// FIXME: #[const_trait]
448+
pub trait Clone: Sized {
511449
fn clone(&self) -> Self;
512450
fn clone_from(&mut self, source: &Self)
513451
where
514-
Self: ~const Destruct,
452+
// FIXME: Self: ~const Destruct,
515453
{
516454
*self = source.clone()
517455
}
518456
}
519457

520458
#[lang = "structural_peq"]
521-
trait StructuralPartialEq {}
459+
pub trait StructuralPartialEq {}
522460

523-
const fn drop<T: ~const Destruct>(_: T) {}
461+
// FIXME: const fn drop<T: ~const Destruct>(_: T) {}
524462

525-
#[rustc_const_stable_indirect]
526463
#[rustc_intrinsic_must_be_overridden]
527464
#[rustc_intrinsic]
528465
const fn const_eval_select<ARG: Tuple, F, G, RET>(
@@ -536,10 +473,3 @@ where
536473
{
537474
loop {}
538475
}
539-
540-
fn test_const_eval_select() {
541-
const fn const_fn() {}
542-
fn rt_fn() {}
543-
544-
const_eval_select((), const_fn, rt_fn);
545-
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
//@ aux-build:minicore.rs
2+
//@ compile-flags: --crate-type=lib -Znext-solver -Cpanic=abort
3+
4+
#![feature(no_core, const_trait_impl)]
5+
#![no_std]
6+
#![no_core]
7+
8+
extern crate minicore;
9+
use minicore::*;
10+
11+
struct Ty;
12+
impl Deref for Ty {
13+
type Target = ();
14+
fn deref(&self) -> &Self::Target { &() }
15+
}
16+
17+
const fn foo() {
18+
*Ty;
19+
//~^ ERROR the trait bound `Ty: ~const minicore::Deref` is not satisfied
20+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
error[E0277]: the trait bound `Ty: ~const minicore::Deref` is not satisfied
2+
--> $DIR/minicore-deref-fail.rs:18:5
3+
|
4+
LL | *Ty;
5+
| ^^^
6+
7+
error: aborting due to 1 previous error
8+
9+
For more information about this error, try `rustc --explain E0277`.
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
//@ aux-build:minicore.rs
2+
//@ compile-flags: --crate-type=lib -Znext-solver -Cpanic=abort
3+
//@ check-pass
4+
5+
#![feature(no_core)]
6+
#![no_std]
7+
#![no_core]
8+
#![feature(const_trait_impl)]
9+
10+
extern crate minicore;
11+
use minicore::*;
12+
13+
struct Custom;
14+
impl const Add for Custom {
15+
type Output = ();
16+
fn add(self, _other: Self) {}
17+
}
18+
19+
const fn test_op() {
20+
let _x = Add::add(1, 2);
21+
let _y = Custom + Custom;
22+
}

‎tests/ui/traits/const-traits/effects/minicore.stderr

Lines changed: 0 additions & 13 deletions
This file was deleted.

0 commit comments

Comments
 (0)
Please sign in to comment.