Skip to content

Commit 38e0402

Browse files
Pass host param in method_autoderef_steps
1 parent bbdcd06 commit 38e0402

File tree

10 files changed

+75
-56
lines changed

10 files changed

+75
-56
lines changed

compiler/rustc_hir_analysis/src/autoderef.rs

+5-5
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ pub struct Autoderef<'a, 'tcx> {
3030
span: Span,
3131
body_id: LocalDefId,
3232
param_env: ty::ParamEnv<'tcx>,
33+
host_effect_param: ty::Const<'tcx>,
3334

3435
// Current state:
3536
state: AutoderefSnapshot<'tcx>,
@@ -112,6 +113,7 @@ impl<'a, 'tcx> Autoderef<'a, 'tcx> {
112113
body_id: LocalDefId,
113114
span: Span,
114115
base_ty: Ty<'tcx>,
116+
host_effect_param: ty::Const<'tcx>,
115117
) -> Autoderef<'a, 'tcx> {
116118
Autoderef {
117119
infcx,
@@ -127,6 +129,7 @@ impl<'a, 'tcx> Autoderef<'a, 'tcx> {
127129
},
128130
include_raw_pointers: false,
129131
silence_errors: false,
132+
host_effect_param,
130133
}
131134
}
132135

@@ -140,11 +143,8 @@ impl<'a, 'tcx> Autoderef<'a, 'tcx> {
140143
// FIXME(effects): This is still broken, since we don't necessarily have a choice of
141144
// `host = true` or `host = host` in `const` functions. This is also busted in `method_autoderef_steps`.
142145
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-
])
146+
let args = if deref_generics.host_effect_index.is_some() {
147+
self.infcx.tcx.mk_args(&[ty.into(), self.host_effect_param.into()])
148148
} else {
149149
self.infcx.tcx.mk_args(&[ty.into()])
150150
};

compiler/rustc_hir_analysis/src/check/wfcheck.rs

+8-1
Original file line numberDiff line numberDiff line change
@@ -1644,7 +1644,14 @@ fn receiver_is_valid<'tcx>(
16441644
return true;
16451645
}
16461646

1647-
let mut autoderef = Autoderef::new(infcx, wfcx.param_env, wfcx.body_def_id, span, receiver_ty);
1647+
let mut autoderef = Autoderef::new(
1648+
infcx,
1649+
wfcx.param_env,
1650+
wfcx.body_def_id,
1651+
span,
1652+
receiver_ty,
1653+
tcx.expected_host_effect_param_for_body(wfcx.body_def_id),
1654+
);
16481655

16491656
// The `arbitrary_self_types` feature allows raw pointer receivers like `self: *const Self`.
16501657
if arbitrary_self_types_enabled {

compiler/rustc_hir_typeck/src/autoderef.rs

+8-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,14 @@ use std::iter;
1212

1313
impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
1414
pub fn autoderef(&'a self, span: Span, base_ty: Ty<'tcx>) -> Autoderef<'a, 'tcx> {
15-
Autoderef::new(self, self.param_env, self.body_id, span, base_ty)
15+
Autoderef::new(
16+
self,
17+
self.param_env,
18+
self.body_id,
19+
span,
20+
base_ty,
21+
self.tcx.expected_host_effect_param_for_body(self.body_id),
22+
)
1623
}
1724

1825
pub fn try_overloaded_deref(

compiler/rustc_hir_typeck/src/method/probe.rs

+26-21
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ use rustc_infer::infer::DefineOpaqueTypes;
1717
use rustc_infer::infer::{self, InferOk, TyCtxtInferExt};
1818
use rustc_middle::middle::stability;
1919
use rustc_middle::query::Providers;
20+
use rustc_middle::traits::query::type_op::MethodAutoderef;
21+
use rustc_middle::traits::query::CanonicalMethodAutoderefGoal;
2022
use rustc_middle::ty::fast_reject::{simplify_type, TreatParams};
2123
use rustc_middle::ty::AssocItem;
2224
use rustc_middle::ty::GenericParamDefKind;
@@ -36,7 +38,6 @@ use rustc_trait_selection::traits::query::method_autoderef::MethodAutoderefBadTy
3638
use rustc_trait_selection::traits::query::method_autoderef::{
3739
CandidateStep, MethodAutoderefStepsResult,
3840
};
39-
use rustc_trait_selection::traits::query::CanonicalTyGoal;
4041
use rustc_trait_selection::traits::NormalizeExt;
4142
use rustc_trait_selection::traits::{self, ObligationCause};
4243
use std::cell::RefCell;
@@ -371,34 +372,32 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
371372
OP: FnOnce(ProbeContext<'_, 'tcx>) -> Result<R, MethodError<'tcx>>,
372373
{
373374
let mut orig_values = OriginalQueryValues::default();
374-
let param_env_and_self_ty = self.canonicalize_query(
375-
ParamEnvAnd { param_env: self.param_env, value: self_ty },
376-
&mut orig_values,
377-
);
375+
let goal = MethodAutoderef {
376+
self_ty,
377+
host_effect_param: self.tcx.expected_host_effect_param_for_body(self.body_id),
378+
};
379+
let canonical_goal = self.canonicalize_query(self.param_env.and(goal), &mut orig_values);
378380

379381
let steps = match mode {
380-
Mode::MethodCall => self.tcx.method_autoderef_steps(param_env_and_self_ty),
382+
Mode::MethodCall => self.tcx.method_autoderef_steps(canonical_goal),
381383
Mode::Path => self.probe(|_| {
382384
// Mode::Path - the deref steps is "trivial". This turns
383385
// our CanonicalQuery into a "trivial" QueryResponse. This
384386
// is a bit inefficient, but I don't think that writing
385387
// special handling for this "trivial case" is a good idea.
386388

387389
let infcx = &self.infcx;
388-
let (ParamEnvAnd { param_env: _, value: self_ty }, canonical_inference_vars) =
389-
infcx.instantiate_canonical_with_fresh_inference_vars(
390-
span,
391-
&param_env_and_self_ty,
392-
);
390+
let (ParamEnvAnd { param_env: _, value: goal }, canonical_inference_vars) =
391+
infcx.instantiate_canonical_with_fresh_inference_vars(span, &canonical_goal);
393392
debug!(
394-
"probe_op: Mode::Path, param_env_and_self_ty={:?} self_ty={:?}",
395-
param_env_and_self_ty, self_ty
393+
"probe_op: Mode::Path, canonical_goal={:?} self_ty={:?}",
394+
canonical_goal, self_ty
396395
);
397396
MethodAutoderefStepsResult {
398397
steps: infcx.tcx.arena.alloc_from_iter([CandidateStep {
399398
self_ty: self.make_query_response_ignoring_pending_obligations(
400399
canonical_inference_vars,
401-
self_ty,
400+
goal.self_ty,
402401
),
403402
autoderefs: 0,
404403
from_unsafe_deref: false,
@@ -510,17 +509,23 @@ pub fn provide(providers: &mut Providers) {
510509

511510
fn method_autoderef_steps<'tcx>(
512511
tcx: TyCtxt<'tcx>,
513-
goal: CanonicalTyGoal<'tcx>,
512+
goal: CanonicalMethodAutoderefGoal<'tcx>,
514513
) -> MethodAutoderefStepsResult<'tcx> {
515514
debug!("method_autoderef_steps({:?})", goal);
516515

517516
let (ref infcx, goal, inference_vars) = tcx.infer_ctxt().build_with_canonical(DUMMY_SP, &goal);
518-
let ParamEnvAnd { param_env, value: self_ty } = goal;
519-
520-
let mut autoderef =
521-
Autoderef::new(infcx, param_env, hir::def_id::CRATE_DEF_ID, DUMMY_SP, self_ty)
522-
.include_raw_pointers()
523-
.silence_errors();
517+
let ParamEnvAnd { param_env, value: MethodAutoderef { self_ty, host_effect_param } } = goal;
518+
519+
let mut autoderef = Autoderef::new(
520+
infcx,
521+
param_env,
522+
hir::def_id::CRATE_DEF_ID,
523+
DUMMY_SP,
524+
self_ty,
525+
host_effect_param,
526+
)
527+
.include_raw_pointers()
528+
.silence_errors();
524529
let mut reached_raw_pointer = false;
525530
let mut steps: Vec<_> = autoderef
526531
.by_ref()

compiler/rustc_middle/src/query/mod.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ use crate::query::plumbing::{
3030
};
3131
use crate::thir;
3232
use crate::traits::query::{
33-
CanonicalPredicateGoal, CanonicalProjectionGoal, CanonicalTyGoal,
33+
CanonicalMethodAutoderefGoal, CanonicalPredicateGoal, CanonicalProjectionGoal, CanonicalTyGoal,
3434
CanonicalTypeOpAscribeUserTypeGoal, CanonicalTypeOpEqGoal, CanonicalTypeOpNormalizeGoal,
3535
CanonicalTypeOpProvePredicateGoal, CanonicalTypeOpSubtypeGoal, NoSolution,
3636
};
@@ -2077,9 +2077,9 @@ rustc_queries! {
20772077
}
20782078

20792079
query method_autoderef_steps(
2080-
goal: CanonicalTyGoal<'tcx>
2080+
goal: CanonicalMethodAutoderefGoal<'tcx>
20812081
) -> MethodAutoderefStepsResult<'tcx> {
2082-
desc { "computing autoderef types for `{}`", goal.value.value }
2082+
desc { "computing autoderef types for `{}`", goal.value.value.self_ty }
20832083
}
20842084

20852085
query supported_target_features(_: CrateNum) -> &'tcx FxHashMap<String, Option<Symbol>> {

compiler/rustc_middle/src/traits/query.rs

+12-1
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ use rustc_span::Span;
1414

1515
pub mod type_op {
1616
use crate::ty::fold::TypeFoldable;
17-
use crate::ty::{Predicate, Ty, TyCtxt, UserType};
17+
use crate::ty::{Const, Predicate, Ty, TyCtxt, UserType};
1818
use std::fmt;
1919

2020
#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, HashStable, TypeFoldable, TypeVisitable)]
@@ -65,12 +65,23 @@ pub mod type_op {
6565
Self { value }
6666
}
6767
}
68+
69+
#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, HashStable, TypeFoldable, TypeVisitable)]
70+
pub struct MethodAutoderef<'tcx> {
71+
pub self_ty: Ty<'tcx>,
72+
/// Expected host effect value of the caller. For const fns, it's
73+
/// some const param ty, and for normal functions, it's `true`.
74+
pub host_effect_param: Const<'tcx>,
75+
}
6876
}
6977

7078
pub type CanonicalProjectionGoal<'tcx> = Canonical<'tcx, ty::ParamEnvAnd<'tcx, ty::AliasTy<'tcx>>>;
7179

7280
pub type CanonicalTyGoal<'tcx> = Canonical<'tcx, ty::ParamEnvAnd<'tcx, Ty<'tcx>>>;
7381

82+
pub type CanonicalMethodAutoderefGoal<'tcx> =
83+
Canonical<'tcx, ty::ParamEnvAnd<'tcx, type_op::MethodAutoderef<'tcx>>>;
84+
7485
pub type CanonicalPredicateGoal<'tcx> = Canonical<'tcx, ty::ParamEnvAnd<'tcx, ty::Predicate<'tcx>>>;
7586

7687
pub type CanonicalTypeOpAscribeUserTypeGoal<'tcx> =

compiler/rustc_middle/src/ty/util.rs

+6-4
Original file line numberDiff line numberDiff line change
@@ -804,10 +804,12 @@ impl<'tcx> TyCtxt<'tcx> {
804804
self.consts.false_
805805
}
806806
Some(hir::ConstContext::ConstFn) => {
807-
let host_idx = self
808-
.generics_of(def_id)
809-
.host_effect_index
810-
.expect("ConstContext::Maybe must have host effect param");
807+
let host_idx = self.generics_of(def_id).host_effect_index.unwrap_or_else(|| {
808+
span_bug!(
809+
self.def_span(def_id),
810+
"item with `ConstContext::Maybe` must have host effect param"
811+
)
812+
});
811813
ty::GenericArgs::identity_for_item(self, def_id).const_at(host_idx)
812814
}
813815
None => self.consts.true_,

tests/ui/rfcs/rfc-2632-const-trait-impl/effects/const_closure-const_trait_impl-ice-113381.rs

+6-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
1+
// known-bug: unknown
2+
// failure-status: 101
3+
// dont-check-compiler-stderr
4+
5+
// const closures don't have host params...
6+
17
#![feature(const_closures, const_trait_impl, effects)]
28
#![allow(incomplete_features)]
39

@@ -11,5 +17,4 @@ impl Foo for () {
1117

1218
fn main() {
1319
(const || { (()).foo() })();
14-
//~^ ERROR: cannot call non-const fn
1520
}

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

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

33
#![crate_type = "lib"]
44
#![feature(no_core, lang_items, unboxed_closures, auto_traits, intrinsics, rustc_attrs)]

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

-18
This file was deleted.

0 commit comments

Comments
 (0)