Skip to content

Commit 31f5cfd

Browse files
Fix Deref args when #[const_trait] is enabled
1 parent 75c68cf commit 31f5cfd

File tree

9 files changed

+76
-29
lines changed

9 files changed

+76
-29
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_middle/src/ty/util.rs

+8-9
Original file line numberDiff line numberDiff line change
@@ -828,15 +828,14 @@ impl<'tcx> TyCtxt<'tcx> {
828828
callee_def_id: DefId,
829829
args: impl IntoIterator<Item: Into<ty::GenericArg<'tcx>>>,
830830
) -> ty::GenericArgsRef<'tcx> {
831-
let generics = self.generics_of(callee_def_id);
832-
assert_eq!(generics.parent, None);
833-
834-
let opt_const_param = generics
835-
.host_effect_index
836-
.is_some()
837-
.then(|| ty::GenericArg::from(self.expected_host_effect_param_for_body(caller_def_id)));
838-
839-
self.mk_args_from_iter(args.into_iter().map(|arg| arg.into()).chain(opt_const_param))
831+
let mut args = args.into_iter();
832+
ty::GenericArgs::for_item(self, callee_def_id, |param, _| {
833+
if param.is_host_effect() {
834+
self.expected_host_effect_param_for_body(caller_def_id).into()
835+
} else {
836+
args.next().unwrap().into()
837+
}
838+
})
840839
}
841840
}
842841

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

+6-1
Original file line numberDiff line numberDiff line change
@@ -254,7 +254,12 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
254254
let ref_str_ty = Ty::new_imm_ref(tcx, re_erased, tcx.types.str_);
255255
let ref_str = self.temp(ref_str_ty, test.span);
256256
let deref = tcx.require_lang_item(LangItem::Deref, None);
257-
let method = trait_method(tcx, deref, sym::deref, [ty]);
257+
let method = trait_method(
258+
tcx,
259+
deref,
260+
sym::deref,
261+
tcx.with_opt_host_effect_param(self.def_id, deref, [ty]),
262+
);
258263
let eq_block = self.cfg.start_new_block();
259264
self.cfg.push_assign(
260265
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
@@ -4129,7 +4129,8 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
41294129

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

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

+8-10
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// check-pass
1+
// known-bug: unknown
22

33
#![crate_type = "lib"]
44
#![feature(no_core, lang_items, unboxed_closures, auto_traits, intrinsics, rustc_attrs, staged_api)]
@@ -235,7 +235,7 @@ impl<'a, 'b: 'a, T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<&'a U> for &'b
235235

236236

237237
#[lang = "deref"]
238-
// #[const_trait] FIXME
238+
#[const_trait]
239239
trait Deref {
240240
#[lang = "deref_target"]
241241
type Target: ?Sized;
@@ -244,15 +244,15 @@ trait Deref {
244244
}
245245

246246

247-
impl<T: ?Sized> /* const */ Deref for &T {
247+
impl<T: ?Sized> const Deref for &T {
248248
type Target = T;
249249

250250
fn deref(&self) -> &T {
251251
*self
252252
}
253253
}
254254

255-
impl<T: ?Sized> /* const */ Deref for &mut T {
255+
impl<T: ?Sized> const Deref for &mut T {
256256
type Target = T;
257257

258258
fn deref(&self) -> &T {
@@ -285,7 +285,6 @@ impl<T> Option<T> {
285285

286286
use Option::*;
287287

288-
/*
289288
const fn as_deref<T>(opt: &Option<T>) -> Option<&T::Target>
290289
where
291290
T: ~const Deref,
@@ -295,7 +294,6 @@ where
295294
Option::None => Option::None,
296295
}
297296
}
298-
*/
299297

300298
#[const_trait]
301299
trait Into<T>: Sized {
@@ -400,9 +398,9 @@ impl<'a, T: ?Sized> Pin<&'a T> {
400398

401399

402400
impl<P: Deref> Pin<P> {
403-
/* const */ fn as_ref(&self) -> Pin<&P::Target>
401+
const fn as_ref(&self) -> Pin<&P::Target>
404402
where
405-
P: /* ~const */ Deref,
403+
P: ~const Deref,
406404
{
407405
unsafe { Pin::new_unchecked(&*self.pointer) }
408406
}
@@ -434,14 +432,14 @@ impl<T> Option<T> {
434432
}
435433
*/
436434

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

444-
impl<T> /* const */ Deref for Option<T> {
442+
impl<T> const Deref for Option<T> {
445443
type Target = T;
446444
fn deref(&self) -> &T {
447445
loop {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
error[E0282]: type annotations needed
2+
--> $DIR/minicore.rs:291:43
3+
|
4+
LL | Option::Some(t) => Option::Some(t.deref()),
5+
| ^^^^^ cannot infer type
6+
7+
error[E0599]: no method named `deref` found for reference `&T` in the current scope
8+
--> $DIR/minicore.rs:291:43
9+
|
10+
LL | Option::Some(t) => Option::Some(t.deref()),
11+
| ^^^^^ method not found in `&T`
12+
|
13+
= help: items from traits can only be used if the type parameter is bounded by the trait
14+
15+
error: aborting due to 2 previous errors
16+
17+
Some errors have detailed explanations: E0282, E0599.
18+
For more information about an error, try `rustc --explain E0282`.

0 commit comments

Comments
 (0)