Skip to content

Commit af3ca15

Browse files
Fix Deref args when #[const_trait] is enabled
1 parent 4d1bd0d commit af3ca15

File tree

8 files changed

+69
-19
lines changed

8 files changed

+69
-19
lines changed

compiler/rustc_hir_analysis/src/autoderef.rs

+18-4
Original file line numberDiff line numberDiff line change
@@ -109,14 +109,14 @@ impl<'a, 'tcx> Autoderef<'a, 'tcx> {
109109
pub fn new(
110110
infcx: &'a InferCtxt<'tcx>,
111111
param_env: ty::ParamEnv<'tcx>,
112-
body_def_id: LocalDefId,
112+
body_id: LocalDefId,
113113
span: Span,
114114
base_ty: Ty<'tcx>,
115115
) -> Autoderef<'a, 'tcx> {
116116
Autoderef {
117117
infcx,
118118
span,
119-
body_id: body_def_id,
119+
body_id,
120120
param_env,
121121
state: AutoderefSnapshot {
122122
steps: vec![],
@@ -135,7 +135,21 @@ impl<'a, 'tcx> Autoderef<'a, 'tcx> {
135135
let tcx = self.infcx.tcx;
136136

137137
// <ty as Deref>
138-
let trait_ref = ty::TraitRef::new(tcx, tcx.lang_items().deref_trait()?, [ty]);
138+
let deref_trait_def_id = tcx.lang_items().deref_trait()?;
139+
140+
// FIXME(effects): This is still broken, since we don't necessarily have a choice of
141+
// `host = true` or `host = host` in `const` functions. This is also busted in `method_autoderef_steps`.
142+
let deref_generics = self.infcx.tcx.generics_of(deref_trait_def_id);
143+
let args = if let Some(host_param) = deref_generics.host_effect_index {
144+
self.infcx.tcx.mk_args(&[
145+
ty.into(),
146+
self.infcx.var_for_def(self.span, &deref_generics.params[host_param]),
147+
])
148+
} else {
149+
self.infcx.tcx.mk_args(&[ty.into()])
150+
};
151+
152+
let trait_ref = ty::TraitRef::new(tcx, deref_trait_def_id, args);
139153
let cause = traits::ObligationCause::misc(self.span, self.body_id);
140154
let obligation = traits::Obligation::new(
141155
tcx,
@@ -151,7 +165,7 @@ impl<'a, 'tcx> Autoderef<'a, 'tcx> {
151165
let (normalized_ty, obligations) = self.structurally_normalize(Ty::new_projection(
152166
tcx,
153167
tcx.lang_items().deref_target()?,
154-
[ty],
168+
trait_ref.args,
155169
))?;
156170
debug!("overloaded_deref_ty({:?}) = ({:?}, {:?})", ty, normalized_ty, obligations);
157171
self.state.obligations.extend(obligations);

compiler/rustc_hir_typeck/src/autoderef.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
2020
span: Span,
2121
base_ty: Ty<'tcx>,
2222
) -> Option<InferOk<'tcx, MethodCallee<'tcx>>> {
23-
self.try_overloaded_place_op(span, base_ty, &[], PlaceOp::Deref)
23+
let callee = self.try_overloaded_place_op(span, base_ty, &[], PlaceOp::Deref)?;
24+
self.enforce_context_effects(span, callee.value.def_id, callee.value.args);
25+
Some(callee)
2426
}
2527

2628
/// Returns the adjustment steps.

compiler/rustc_middle/src/ty/adjustment.rs

+12-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use crate::ty::{self, Ty, TyCtxt};
22
use rustc_hir as hir;
3+
use rustc_hir::def_id::LocalDefId;
34
use rustc_hir::lang_items::LangItem;
45
use rustc_macros::HashStable;
56
use rustc_span::Span;
@@ -121,7 +122,12 @@ pub struct OverloadedDeref<'tcx> {
121122

122123
impl<'tcx> OverloadedDeref<'tcx> {
123124
/// Get the zst function item type for this method call.
124-
pub fn method_call(&self, tcx: TyCtxt<'tcx>, source: Ty<'tcx>) -> Ty<'tcx> {
125+
pub fn method_call(
126+
&self,
127+
tcx: TyCtxt<'tcx>,
128+
source: Ty<'tcx>,
129+
caller_def_id: LocalDefId,
130+
) -> Ty<'tcx> {
125131
let trait_def_id = match self.mutbl {
126132
hir::Mutability::Not => tcx.require_lang_item(LangItem::Deref, None),
127133
hir::Mutability::Mut => tcx.require_lang_item(LangItem::DerefMut, None),
@@ -132,7 +138,11 @@ impl<'tcx> OverloadedDeref<'tcx> {
132138
.find(|m| m.kind == ty::AssocKind::Fn)
133139
.unwrap()
134140
.def_id;
135-
Ty::new_fn_def(tcx, method_def_id, [source])
141+
Ty::new_fn_def(
142+
tcx,
143+
method_def_id,
144+
tcx.with_opt_host_effect_param(caller_def_id, method_def_id, [source]),
145+
)
136146
}
137147
}
138148

compiler/rustc_mir_build/src/build/matches/test.rs

+6-1
Original file line numberDiff line numberDiff line change
@@ -253,7 +253,12 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
253253
let ref_str_ty = Ty::new_imm_ref(tcx, re_erased, tcx.types.str_);
254254
let ref_str = self.temp(ref_str_ty, test.span);
255255
let deref = tcx.require_lang_item(LangItem::Deref, None);
256-
let method = trait_method(tcx, deref, sym::deref, [ty]);
256+
let method = trait_method(
257+
tcx,
258+
deref,
259+
sym::deref,
260+
tcx.with_opt_host_effect_param(self.def_id, deref, [ty]),
261+
);
257262
let eq_block = self.cfg.start_new_block();
258263
self.cfg.push_assign(
259264
block,

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

+1-1
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@ impl<'tcx> Cx<'tcx> {
118118
Adjust::Deref(Some(deref)) => {
119119
// We don't need to do call adjust_span here since
120120
// deref coercions always start with a built-in deref.
121-
let call = deref.method_call(self.tcx(), expr.ty);
121+
let call = deref.method_call(self.tcx(), expr.ty, self.body_owner.expect_local());
122122

123123
expr = Expr {
124124
temp_lifetime,

compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -3906,7 +3906,8 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
39063906

39073907
// Extract `<U as Deref>::Target` assoc type and check that it is `T`
39083908
&& let Some(deref_target_did) = tcx.lang_items().deref_target()
3909-
&& let projection = Ty::new_projection(tcx,deref_target_did, tcx.mk_args(&[ty::GenericArg::from(found_ty)]))
3909+
&& let args = tcx.with_opt_host_effect_param(tcx.hir().enclosing_body_owner(expr.hir_id), deref_target_did, [found_ty])
3910+
&& let projection = Ty::new_projection(tcx,deref_target_did, args)
39103911
&& let InferOk { value: deref_target, obligations } = infcx.at(&ObligationCause::dummy(), param_env).normalize(projection)
39113912
&& obligations.iter().all(|obligation| infcx.predicate_must_hold_modulo_regions(obligation))
39123913
&& infcx.can_eq(param_env, deref_target, target_ty)

tests/ui/rfcs/rfc-2632-const-trait-impl/effects/minicore.rs

+7-9
Original file line numberDiff line numberDiff line change
@@ -233,7 +233,7 @@ impl<'a, 'b: 'a, T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<&'a U> for &'b
233233

234234

235235
#[lang = "deref"]
236-
// #[const_trait] FIXME
236+
#[const_trait]
237237
trait Deref {
238238
#[lang = "deref_target"]
239239
type Target: ?Sized;
@@ -242,15 +242,15 @@ trait Deref {
242242
}
243243

244244

245-
impl<T: ?Sized> /* const */ Deref for &T {
245+
impl<T: ?Sized> const Deref for &T {
246246
type Target = T;
247247

248248
fn deref(&self) -> &T {
249249
*self
250250
}
251251
}
252252

253-
impl<T: ?Sized> /* const */ Deref for &mut T {
253+
impl<T: ?Sized> const Deref for &mut T {
254254
type Target = T;
255255

256256
fn deref(&self) -> &T {
@@ -283,7 +283,6 @@ impl<T> Option<T> {
283283

284284
use Option::*;
285285

286-
/*
287286
const fn as_deref<T>(opt: &Option<T>) -> Option<&T::Target>
288287
where
289288
T: ~const Deref,
@@ -293,7 +292,6 @@ where
293292
Option::None => Option::None,
294293
}
295294
}
296-
*/
297295

298296
#[const_trait]
299297
trait Into<T>: Sized {
@@ -398,9 +396,9 @@ impl<'a, T: ?Sized> Pin<&'a T> {
398396

399397

400398
impl<P: Deref> Pin<P> {
401-
/* const */ fn as_ref(&self) -> Pin<&P::Target>
399+
const fn as_ref(&self) -> Pin<&P::Target>
402400
where
403-
P: /* ~const */ Deref,
401+
P: ~const Deref,
404402
{
405403
unsafe { Pin::new_unchecked(&*self.pointer) }
406404
}
@@ -432,14 +430,14 @@ impl<T> Option<T> {
432430
}
433431
*/
434432

435-
impl<P: /* ~const */ Deref> /* const */ Deref for Pin<P> {
433+
impl<P: ~const Deref> const Deref for Pin<P> {
436434
type Target = P::Target;
437435
fn deref(&self) -> &P::Target {
438436
Pin::get_ref(Pin::as_ref(self))
439437
}
440438
}
441439

442-
impl<T> /* const */ Deref for Option<T> {
440+
impl<T> const Deref for Option<T> {
443441
type Target = T;
444442
fn deref(&self) -> &T {
445443
loop {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
error[E0493]: destructor of `Self` cannot be evaluated at compile-time
2+
--> $DIR/minicore.rs:501:9
3+
|
4+
LL | *self = source.clone()
5+
| ^^^^^
6+
| |
7+
| the destructor for this type cannot be evaluated in constant functions
8+
| value is dropped here
9+
10+
error[E0493]: destructor of `T` cannot be evaluated at compile-time
11+
--> $DIR/minicore.rs:511:35
12+
|
13+
LL | const fn drop<T: ~const Destruct>(_: T) {}
14+
| ^ - value is dropped here
15+
| |
16+
| the destructor for this type cannot be evaluated in constant functions
17+
18+
error: aborting due to 2 previous errors
19+
20+
For more information about this error, try `rustc --explain E0493`.

0 commit comments

Comments
 (0)