Skip to content

Commit c0bd5a5

Browse files
committed
Auto merge of #86901 - sexxi-goose:query_remove, r=nikomatsakis
Make type_implements_trait not a query r? `@nikomatsakis`
2 parents b20e3ff + 1bcbc18 commit c0bd5a5

File tree

11 files changed

+142
-108
lines changed

11 files changed

+142
-108
lines changed

compiler/rustc_middle/src/dep_graph/dep_node.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -285,7 +285,7 @@ pub type DepNode = rustc_query_system::dep_graph::DepNode<DepKind>;
285285
// required that their size stay the same, but we don't want to change
286286
// it inadvertently. This assert just ensures we're aware of any change.
287287
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
288-
static_assert_size!(DepNode, 18);
288+
static_assert_size!(DepNode, 17);
289289

290290
#[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))]
291291
static_assert_size!(DepNode, 24);

compiler/rustc_middle/src/query/mod.rs

-19
Original file line numberDiff line numberDiff line change
@@ -1555,25 +1555,6 @@ rustc_queries! {
15551555
desc { "evaluating trait selection obligation `{}`", goal.value }
15561556
}
15571557

1558-
/// Evaluates whether the given type implements the given trait
1559-
/// in the given environment.
1560-
///
1561-
/// The inputs are:
1562-
///
1563-
/// - the def-id of the trait
1564-
/// - the self type
1565-
/// - the *other* type parameters of the trait, excluding the self-type
1566-
/// - the parameter environment
1567-
///
1568-
/// FIXME. If the type, trait, or environment has inference variables,
1569-
/// this yields `EvaluatedToUnknown`. It should be refactored
1570-
/// to use canonicalization, really.
1571-
query type_implements_trait(
1572-
key: (DefId, Ty<'tcx>, SubstsRef<'tcx>, ty::ParamEnv<'tcx>, )
1573-
) -> traits::EvaluationResult {
1574-
desc { "evaluating `type_implements_trait` `{:?}`", key }
1575-
}
1576-
15771558
/// Do not call this query directly: part of the `Eq` type-op
15781559
query type_op_ascribe_user_type(
15791560
goal: CanonicalTypeOpAscribeUserTypeGoal<'tcx>

compiler/rustc_mir/src/borrow_check/diagnostics/conflict_errors.rs

+4-2
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ use rustc_middle::ty::{self, suggest_constraining_type_param, Ty};
1313
use rustc_span::source_map::DesugaringKind;
1414
use rustc_span::symbol::sym;
1515
use rustc_span::{Span, DUMMY_SP};
16+
use rustc_trait_selection::infer::InferCtxtExt;
1617

1718
use crate::dataflow::drop_flag_effects;
1819
use crate::dataflow::indexes::{MoveOutIndex, MovePathIndex};
@@ -1330,8 +1331,9 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
13301331

13311332
// to avoid panics
13321333
if let Some(iter_trait) = tcx.get_diagnostic_item(sym::Iterator) {
1333-
if tcx
1334-
.type_implements_trait((iter_trait, return_ty, ty_params, self.param_env))
1334+
if self
1335+
.infcx
1336+
.type_implements_trait(iter_trait, return_ty, ty_params, self.param_env)
13351337
.must_apply_modulo_regions()
13361338
{
13371339
if let Ok(snippet) = tcx.sess.source_map().span_to_snippet(return_span) {

compiler/rustc_trait_selection/src/infer.rs

+44-1
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,18 @@
1+
use crate::traits::query::evaluate_obligation::InferCtxtExt as _;
12
use crate::traits::query::outlives_bounds::InferCtxtExt as _;
23
use crate::traits::{self, TraitEngine, TraitEngineExt};
34

45
use rustc_hir as hir;
6+
use rustc_hir::def_id::DefId;
57
use rustc_hir::lang_items::LangItem;
68
use rustc_infer::infer::outlives::env::OutlivesEnvironment;
79
use rustc_infer::traits::ObligationCause;
810
use rustc_middle::arena::ArenaAllocatable;
911
use rustc_middle::infer::canonical::{Canonical, CanonicalizedQueryResponse, QueryResponse};
1012
use rustc_middle::traits::query::Fallible;
13+
use rustc_middle::ty::subst::SubstsRef;
14+
use rustc_middle::ty::ToPredicate;
15+
use rustc_middle::ty::WithConstness;
1116
use rustc_middle::ty::{self, Ty, TypeFoldable};
1217
use rustc_span::{Span, DUMMY_SP};
1318

@@ -32,8 +37,22 @@ pub trait InferCtxtExt<'tcx> {
3237
) -> InferOk<'tcx, T>
3338
where
3439
T: TypeFoldable<'tcx>;
35-
}
3640

41+
/// Check whether a `ty` implements given trait(trait_def_id).
42+
/// The inputs are:
43+
///
44+
/// - the def-id of the trait
45+
/// - the self type
46+
/// - the *other* type parameters of the trait, excluding the self-type
47+
/// - the parameter environment
48+
fn type_implements_trait(
49+
&self,
50+
trait_def_id: DefId,
51+
ty: Ty<'tcx>,
52+
params: SubstsRef<'tcx>,
53+
param_env: ty::ParamEnv<'tcx>,
54+
) -> traits::EvaluationResult;
55+
}
3756
impl<'cx, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'cx, 'tcx> {
3857
fn type_is_copy_modulo_regions(
3958
&self,
@@ -79,6 +98,30 @@ impl<'cx, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'cx, 'tcx> {
7998
);
8099
InferOk { value, obligations }
81100
}
101+
102+
fn type_implements_trait(
103+
&self,
104+
trait_def_id: DefId,
105+
ty: Ty<'tcx>,
106+
params: SubstsRef<'tcx>,
107+
param_env: ty::ParamEnv<'tcx>,
108+
) -> traits::EvaluationResult {
109+
debug!(
110+
"type_implements_trait: trait_def_id={:?}, type={:?}, params={:?}, param_env={:?}",
111+
trait_def_id, ty, params, param_env
112+
);
113+
114+
let trait_ref =
115+
ty::TraitRef { def_id: trait_def_id, substs: self.tcx.mk_substs_trait(ty, params) };
116+
117+
let obligation = traits::Obligation {
118+
cause: traits::ObligationCause::dummy(),
119+
param_env,
120+
recursion_depth: 0,
121+
predicate: trait_ref.without_const().to_predicate(self.tcx),
122+
};
123+
self.evaluate_obligation_no_overflow(&obligation)
124+
}
82125
}
83126

84127
pub trait InferCtxtBuilderExt<'tcx> {

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

+3-2
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ use rustc_target::spec::abi;
2828
use std::fmt;
2929

3030
use super::InferCtxtPrivExt;
31+
use crate::infer::InferCtxtExt as _;
3132
use crate::traits::query::evaluate_obligation::InferCtxtExt as _;
3233
use rustc_middle::ty::print::with_no_trimmed_paths;
3334

@@ -2349,12 +2350,12 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
23492350
}
23502351
let self_ty = self.tcx.erase_regions(self_ty);
23512352

2352-
let impls_future = self.tcx.type_implements_trait((
2353+
let impls_future = self.type_implements_trait(
23532354
future_trait,
23542355
self_ty.skip_binder(),
23552356
ty::List::empty(),
23562357
obligation.param_env,
2357-
));
2358+
);
23582359

23592360
let item_def_id = self
23602361
.tcx

compiler/rustc_trait_selection/src/traits/mod.rs

+1-40
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ use rustc_hir::def_id::DefId;
3131
use rustc_middle::ty::fold::TypeFoldable;
3232
use rustc_middle::ty::subst::{InternalSubsts, SubstsRef};
3333
use rustc_middle::ty::{
34-
self, GenericParamDefKind, ParamEnv, ToPredicate, Ty, TyCtxt, VtblEntry, WithConstness,
34+
self, GenericParamDefKind, ToPredicate, Ty, TyCtxt, VtblEntry, WithConstness,
3535
COMMON_VTABLE_ENTRIES,
3636
};
3737
use rustc_span::Span;
@@ -541,44 +541,6 @@ fn vtable_trait_first_method_offset<'tcx>(
541541
vtable_base
542542
}
543543

544-
/// Check whether a `ty` implements given trait(trait_def_id).
545-
/// See query definition for details.
546-
fn type_implements_trait<'tcx>(
547-
tcx: TyCtxt<'tcx>,
548-
key: (
549-
DefId, // trait_def_id,
550-
Ty<'tcx>, // type
551-
SubstsRef<'tcx>,
552-
ParamEnv<'tcx>,
553-
),
554-
) -> EvaluationResult {
555-
let (trait_def_id, ty, params, param_env) = key;
556-
557-
debug!(
558-
"type_implements_trait: trait_def_id={:?}, type={:?}, params={:?}, param_env={:?}",
559-
trait_def_id, ty, params, param_env
560-
);
561-
562-
let trait_ref = ty::TraitRef { def_id: trait_def_id, substs: tcx.mk_substs_trait(ty, params) };
563-
564-
// FIXME(#86868): If there are inference variables anywhere, just give up and assume
565-
// we don't know the answer. This works around the ICEs that would result from
566-
// using those inference variables within the `infer_ctxt` we create below.
567-
// Really we should be using canonicalized variables, or perhaps removing
568-
// this query altogether.
569-
if (trait_ref, param_env).needs_infer() {
570-
return EvaluationResult::EvaluatedToUnknown;
571-
}
572-
573-
let obligation = Obligation {
574-
cause: ObligationCause::dummy(),
575-
param_env,
576-
recursion_depth: 0,
577-
predicate: trait_ref.without_const().to_predicate(tcx),
578-
};
579-
tcx.infer_ctxt().enter(|infcx| infcx.evaluate_obligation_no_overflow(&obligation))
580-
}
581-
582544
pub fn provide(providers: &mut ty::query::Providers) {
583545
object_safety::provide(providers);
584546
structural_match::provide(providers);
@@ -587,7 +549,6 @@ pub fn provide(providers: &mut ty::query::Providers) {
587549
specializes: specialize::specializes,
588550
codegen_fulfill_obligation: codegen::codegen_fulfill_obligation,
589551
vtable_entries,
590-
type_implements_trait,
591552
subst_and_check_impossible_predicates,
592553
mir_abstract_const: |tcx, def_id| {
593554
let def_id = def_id.expect_local();

compiler/rustc_typeck/src/check/cast.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ use rustc_session::lint;
4545
use rustc_session::Session;
4646
use rustc_span::symbol::sym;
4747
use rustc_span::Span;
48+
use rustc_trait_selection::infer::InferCtxtExt;
4849
use rustc_trait_selection::traits;
4950
use rustc_trait_selection::traits::error_reporting::report_object_safety_error;
5051

@@ -441,8 +442,8 @@ impl<'a, 'tcx> CastCheck<'tcx> {
441442
let expr_ty = fcx.tcx.erase_regions(expr_ty);
442443
let ty_params = fcx.tcx.mk_substs_trait(expr_ty, &[]);
443444
if fcx
444-
.tcx
445-
.type_implements_trait((from_trait, ty, ty_params, fcx.param_env))
445+
.infcx
446+
.type_implements_trait(from_trait, ty, ty_params, fcx.param_env)
446447
.must_apply_modulo_regions()
447448
{
448449
label = false;

compiler/rustc_typeck/src/check/upvar.rs

+25-34
Original file line numberDiff line numberDiff line change
@@ -42,13 +42,11 @@ use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor};
4242
use rustc_infer::infer::UpvarRegion;
4343
use rustc_middle::hir::place::{Place, PlaceBase, PlaceWithHirId, Projection, ProjectionKind};
4444
use rustc_middle::mir::FakeReadCause;
45-
use rustc_middle::ty::{
46-
self, ClosureSizeProfileData, TraitRef, Ty, TyCtxt, TypeckResults, UpvarSubsts,
47-
};
45+
use rustc_middle::ty::{self, ClosureSizeProfileData, Ty, TyCtxt, TypeckResults, UpvarSubsts};
4846
use rustc_session::lint;
4947
use rustc_span::sym;
5048
use rustc_span::{MultiSpan, Span, Symbol};
51-
use rustc_trait_selection::traits::{Obligation, ObligationCause};
49+
use rustc_trait_selection::infer::InferCtxtExt;
5250

5351
use rustc_data_structures::stable_set::FxHashSet;
5452
use rustc_index::vec::Idx;
@@ -578,29 +576,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
578576
reasons
579577
}
580578

581-
/// Returns true if `ty` may implement `trait_def_id`
582-
fn ty_impls_trait(
583-
&self,
584-
ty: Ty<'tcx>,
585-
cause: &ObligationCause<'tcx>,
586-
trait_def_id: DefId,
587-
) -> bool {
588-
use crate::rustc_middle::ty::ToPredicate;
589-
use crate::rustc_middle::ty::WithConstness;
590-
use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt;
591-
let tcx = self.infcx.tcx;
592-
593-
let trait_ref = TraitRef { def_id: trait_def_id, substs: tcx.mk_substs_trait(ty, &[]) };
594-
595-
let obligation = Obligation::new(
596-
cause.clone(),
597-
self.param_env,
598-
trait_ref.without_const().to_predicate(tcx),
599-
);
600-
601-
self.infcx.predicate_may_hold(&obligation)
602-
}
603-
604579
/// Returns true if migration is needed for trait for the provided var_hir_id
605580
fn need_2229_migrations_for_trait(
606581
&self,
@@ -618,10 +593,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
618593

619594
let ty = self.infcx.resolve_vars_if_possible(self.node_ty(var_hir_id));
620595

621-
let cause = ObligationCause::misc(self.tcx.hir().span(var_hir_id), self.body_id);
622-
623596
let obligation_should_hold = check_trait
624-
.map(|check_trait| self.ty_impls_trait(ty, &cause, check_trait))
597+
.map(|check_trait| {
598+
self.infcx
599+
.type_implements_trait(
600+
check_trait,
601+
ty,
602+
self.tcx.mk_substs_trait(ty, &[]),
603+
self.param_env,
604+
)
605+
.must_apply_modulo_regions()
606+
})
625607
.unwrap_or(false);
626608

627609
// Check whether catpured fields also implement the trait
@@ -630,7 +612,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
630612
let ty = capture.place.ty();
631613

632614
let obligation_holds_for_capture = check_trait
633-
.map(|check_trait| self.ty_impls_trait(ty, &cause, check_trait))
615+
.map(|check_trait| {
616+
self.infcx
617+
.type_implements_trait(
618+
check_trait,
619+
ty,
620+
self.tcx.mk_substs_trait(ty, &[]),
621+
self.param_env,
622+
)
623+
.must_apply_modulo_regions()
624+
})
634625
.unwrap_or(false);
635626

636627
if !obligation_holds_for_capture && obligation_should_hold {
@@ -961,13 +952,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
961952
let is_drop_defined_for_ty = |ty: Ty<'tcx>| {
962953
let drop_trait = self.tcx.require_lang_item(hir::LangItem::Drop, Some(closure_span));
963954
let ty_params = self.tcx.mk_substs_trait(base_path_ty, &[]);
964-
self.tcx
965-
.type_implements_trait((
955+
self.infcx
956+
.type_implements_trait(
966957
drop_trait,
967958
ty,
968959
ty_params,
969960
self.tcx.param_env(closure_def_id.expect_local()),
970-
))
961+
)
971962
.must_apply_modulo_regions()
972963
};
973964

src/test/incremental/issue-86753.rs

+50
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
// edition:2018
2+
// revisions: rpass1
3+
4+
5+
// Regression test for #86753. The `type_implements_trait` query (since moved to a method)
6+
// was encountering an ICE during incremental testing when hashing its arguments.
7+
#![warn(rust_2021_compatibility)]
8+
9+
use std::future::Future;
10+
use std::pin::Pin;
11+
use std::task::{Poll, Context};
12+
13+
struct LocalSet {}
14+
struct RunUntil<'a, F> {
15+
_local_set: &'a LocalSet,
16+
_future: F,
17+
}
18+
impl<'a, F> RunUntil<'a, F> {
19+
fn project<'pin>(self: Pin<&'pin mut Self>) -> Projection<'pin, 'a, F> {
20+
unimplemented!()
21+
}
22+
}
23+
24+
struct Projection<'pin, 'a, F>
25+
where
26+
RunUntil<'a, F>: 'pin,
27+
{
28+
pub local_set: &'pin mut &'a LocalSet,
29+
pub future: Pin<&'pin mut F>,
30+
}
31+
32+
impl LocalSet {
33+
fn with<T>(&self, _f: impl FnOnce() -> T) -> T {
34+
unimplemented!()
35+
}
36+
}
37+
impl<T: Future> Future for RunUntil<'_, T> {
38+
type Output = T::Output;
39+
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
40+
let me = self.project();
41+
me.local_set.with(|| {
42+
let _ = cx.waker();
43+
let f = me.future;
44+
let _ = f.poll(cx);
45+
Poll::Pending
46+
})
47+
}
48+
}
49+
50+
fn main() {}

src/test/ui/issues/issue-73886.stderr

+3-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,9 @@ error[E0605]: non-primitive cast: `u32` as `Option<_>`
88
--> $DIR/issue-73886.rs:4:13
99
|
1010
LL | let _ = 7u32 as Option<_>;
11-
| ^^^^^^^^^^^^^^^^^ an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object
11+
| ^^^^^^^^^^^^^^^^^ help: consider using the `From` trait instead: `Option<_>::from(7u32)`
12+
|
13+
= note: an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object
1214

1315
error: aborting due to 2 previous errors
1416

0 commit comments

Comments
 (0)