Skip to content

Commit

Permalink
Auto merge of rust-lang#86901 - sexxi-goose:query_remove, r=nikomatsakis
Browse files Browse the repository at this point in the history
Make type_implements_trait not a query

r? `@nikomatsakis`
  • Loading branch information
bors committed Jul 7, 2021
2 parents b20e3ff + 1bcbc18 commit c0bd5a5
Show file tree
Hide file tree
Showing 11 changed files with 142 additions and 108 deletions.
2 changes: 1 addition & 1 deletion compiler/rustc_middle/src/dep_graph/dep_node.rs
Original file line number Diff line number Diff line change
Expand Up @@ -285,7 +285,7 @@ pub type DepNode = rustc_query_system::dep_graph::DepNode<DepKind>;
// required that their size stay the same, but we don't want to change
// it inadvertently. This assert just ensures we're aware of any change.
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
static_assert_size!(DepNode, 18);
static_assert_size!(DepNode, 17);

#[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))]
static_assert_size!(DepNode, 24);
Expand Down
19 changes: 0 additions & 19 deletions compiler/rustc_middle/src/query/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1555,25 +1555,6 @@ rustc_queries! {
desc { "evaluating trait selection obligation `{}`", goal.value }
}

/// Evaluates whether the given type implements the given trait
/// in the given environment.
///
/// The inputs are:
///
/// - the def-id of the trait
/// - the self type
/// - the *other* type parameters of the trait, excluding the self-type
/// - the parameter environment
///
/// FIXME. If the type, trait, or environment has inference variables,
/// this yields `EvaluatedToUnknown`. It should be refactored
/// to use canonicalization, really.
query type_implements_trait(
key: (DefId, Ty<'tcx>, SubstsRef<'tcx>, ty::ParamEnv<'tcx>, )
) -> traits::EvaluationResult {
desc { "evaluating `type_implements_trait` `{:?}`", key }
}

/// Do not call this query directly: part of the `Eq` type-op
query type_op_ascribe_user_type(
goal: CanonicalTypeOpAscribeUserTypeGoal<'tcx>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ use rustc_middle::ty::{self, suggest_constraining_type_param, Ty};
use rustc_span::source_map::DesugaringKind;
use rustc_span::symbol::sym;
use rustc_span::{Span, DUMMY_SP};
use rustc_trait_selection::infer::InferCtxtExt;

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

// to avoid panics
if let Some(iter_trait) = tcx.get_diagnostic_item(sym::Iterator) {
if tcx
.type_implements_trait((iter_trait, return_ty, ty_params, self.param_env))
if self
.infcx
.type_implements_trait(iter_trait, return_ty, ty_params, self.param_env)
.must_apply_modulo_regions()
{
if let Ok(snippet) = tcx.sess.source_map().span_to_snippet(return_span) {
Expand Down
45 changes: 44 additions & 1 deletion compiler/rustc_trait_selection/src/infer.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,18 @@
use crate::traits::query::evaluate_obligation::InferCtxtExt as _;
use crate::traits::query::outlives_bounds::InferCtxtExt as _;
use crate::traits::{self, TraitEngine, TraitEngineExt};

use rustc_hir as hir;
use rustc_hir::def_id::DefId;
use rustc_hir::lang_items::LangItem;
use rustc_infer::infer::outlives::env::OutlivesEnvironment;
use rustc_infer::traits::ObligationCause;
use rustc_middle::arena::ArenaAllocatable;
use rustc_middle::infer::canonical::{Canonical, CanonicalizedQueryResponse, QueryResponse};
use rustc_middle::traits::query::Fallible;
use rustc_middle::ty::subst::SubstsRef;
use rustc_middle::ty::ToPredicate;
use rustc_middle::ty::WithConstness;
use rustc_middle::ty::{self, Ty, TypeFoldable};
use rustc_span::{Span, DUMMY_SP};

Expand All @@ -32,8 +37,22 @@ pub trait InferCtxtExt<'tcx> {
) -> InferOk<'tcx, T>
where
T: TypeFoldable<'tcx>;
}

/// Check whether a `ty` implements given trait(trait_def_id).
/// The inputs are:
///
/// - the def-id of the trait
/// - the self type
/// - the *other* type parameters of the trait, excluding the self-type
/// - the parameter environment
fn type_implements_trait(
&self,
trait_def_id: DefId,
ty: Ty<'tcx>,
params: SubstsRef<'tcx>,
param_env: ty::ParamEnv<'tcx>,
) -> traits::EvaluationResult;
}
impl<'cx, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'cx, 'tcx> {
fn type_is_copy_modulo_regions(
&self,
Expand Down Expand Up @@ -79,6 +98,30 @@ impl<'cx, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'cx, 'tcx> {
);
InferOk { value, obligations }
}

fn type_implements_trait(
&self,
trait_def_id: DefId,
ty: Ty<'tcx>,
params: SubstsRef<'tcx>,
param_env: ty::ParamEnv<'tcx>,
) -> traits::EvaluationResult {
debug!(
"type_implements_trait: trait_def_id={:?}, type={:?}, params={:?}, param_env={:?}",
trait_def_id, ty, params, param_env
);

let trait_ref =
ty::TraitRef { def_id: trait_def_id, substs: self.tcx.mk_substs_trait(ty, params) };

let obligation = traits::Obligation {
cause: traits::ObligationCause::dummy(),
param_env,
recursion_depth: 0,
predicate: trait_ref.without_const().to_predicate(self.tcx),
};
self.evaluate_obligation_no_overflow(&obligation)
}
}

pub trait InferCtxtBuilderExt<'tcx> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ use rustc_target::spec::abi;
use std::fmt;

use super::InferCtxtPrivExt;
use crate::infer::InferCtxtExt as _;
use crate::traits::query::evaluate_obligation::InferCtxtExt as _;
use rustc_middle::ty::print::with_no_trimmed_paths;

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

let impls_future = self.tcx.type_implements_trait((
let impls_future = self.type_implements_trait(
future_trait,
self_ty.skip_binder(),
ty::List::empty(),
obligation.param_env,
));
);

let item_def_id = self
.tcx
Expand Down
41 changes: 1 addition & 40 deletions compiler/rustc_trait_selection/src/traits/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ use rustc_hir::def_id::DefId;
use rustc_middle::ty::fold::TypeFoldable;
use rustc_middle::ty::subst::{InternalSubsts, SubstsRef};
use rustc_middle::ty::{
self, GenericParamDefKind, ParamEnv, ToPredicate, Ty, TyCtxt, VtblEntry, WithConstness,
self, GenericParamDefKind, ToPredicate, Ty, TyCtxt, VtblEntry, WithConstness,
COMMON_VTABLE_ENTRIES,
};
use rustc_span::Span;
Expand Down Expand Up @@ -541,44 +541,6 @@ fn vtable_trait_first_method_offset<'tcx>(
vtable_base
}

/// Check whether a `ty` implements given trait(trait_def_id).
/// See query definition for details.
fn type_implements_trait<'tcx>(
tcx: TyCtxt<'tcx>,
key: (
DefId, // trait_def_id,
Ty<'tcx>, // type
SubstsRef<'tcx>,
ParamEnv<'tcx>,
),
) -> EvaluationResult {
let (trait_def_id, ty, params, param_env) = key;

debug!(
"type_implements_trait: trait_def_id={:?}, type={:?}, params={:?}, param_env={:?}",
trait_def_id, ty, params, param_env
);

let trait_ref = ty::TraitRef { def_id: trait_def_id, substs: tcx.mk_substs_trait(ty, params) };

// FIXME(#86868): If there are inference variables anywhere, just give up and assume
// we don't know the answer. This works around the ICEs that would result from
// using those inference variables within the `infer_ctxt` we create below.
// Really we should be using canonicalized variables, or perhaps removing
// this query altogether.
if (trait_ref, param_env).needs_infer() {
return EvaluationResult::EvaluatedToUnknown;
}

let obligation = Obligation {
cause: ObligationCause::dummy(),
param_env,
recursion_depth: 0,
predicate: trait_ref.without_const().to_predicate(tcx),
};
tcx.infer_ctxt().enter(|infcx| infcx.evaluate_obligation_no_overflow(&obligation))
}

pub fn provide(providers: &mut ty::query::Providers) {
object_safety::provide(providers);
structural_match::provide(providers);
Expand All @@ -587,7 +549,6 @@ pub fn provide(providers: &mut ty::query::Providers) {
specializes: specialize::specializes,
codegen_fulfill_obligation: codegen::codegen_fulfill_obligation,
vtable_entries,
type_implements_trait,
subst_and_check_impossible_predicates,
mir_abstract_const: |tcx, def_id| {
let def_id = def_id.expect_local();
Expand Down
5 changes: 3 additions & 2 deletions compiler/rustc_typeck/src/check/cast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ use rustc_session::lint;
use rustc_session::Session;
use rustc_span::symbol::sym;
use rustc_span::Span;
use rustc_trait_selection::infer::InferCtxtExt;
use rustc_trait_selection::traits;
use rustc_trait_selection::traits::error_reporting::report_object_safety_error;

Expand Down Expand Up @@ -441,8 +442,8 @@ impl<'a, 'tcx> CastCheck<'tcx> {
let expr_ty = fcx.tcx.erase_regions(expr_ty);
let ty_params = fcx.tcx.mk_substs_trait(expr_ty, &[]);
if fcx
.tcx
.type_implements_trait((from_trait, ty, ty_params, fcx.param_env))
.infcx
.type_implements_trait(from_trait, ty, ty_params, fcx.param_env)
.must_apply_modulo_regions()
{
label = false;
Expand Down
59 changes: 25 additions & 34 deletions compiler/rustc_typeck/src/check/upvar.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,13 +42,11 @@ use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor};
use rustc_infer::infer::UpvarRegion;
use rustc_middle::hir::place::{Place, PlaceBase, PlaceWithHirId, Projection, ProjectionKind};
use rustc_middle::mir::FakeReadCause;
use rustc_middle::ty::{
self, ClosureSizeProfileData, TraitRef, Ty, TyCtxt, TypeckResults, UpvarSubsts,
};
use rustc_middle::ty::{self, ClosureSizeProfileData, Ty, TyCtxt, TypeckResults, UpvarSubsts};
use rustc_session::lint;
use rustc_span::sym;
use rustc_span::{MultiSpan, Span, Symbol};
use rustc_trait_selection::traits::{Obligation, ObligationCause};
use rustc_trait_selection::infer::InferCtxtExt;

use rustc_data_structures::stable_set::FxHashSet;
use rustc_index::vec::Idx;
Expand Down Expand Up @@ -578,29 +576,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
reasons
}

/// Returns true if `ty` may implement `trait_def_id`
fn ty_impls_trait(
&self,
ty: Ty<'tcx>,
cause: &ObligationCause<'tcx>,
trait_def_id: DefId,
) -> bool {
use crate::rustc_middle::ty::ToPredicate;
use crate::rustc_middle::ty::WithConstness;
use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt;
let tcx = self.infcx.tcx;

let trait_ref = TraitRef { def_id: trait_def_id, substs: tcx.mk_substs_trait(ty, &[]) };

let obligation = Obligation::new(
cause.clone(),
self.param_env,
trait_ref.without_const().to_predicate(tcx),
);

self.infcx.predicate_may_hold(&obligation)
}

/// Returns true if migration is needed for trait for the provided var_hir_id
fn need_2229_migrations_for_trait(
&self,
Expand All @@ -618,10 +593,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {

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

let cause = ObligationCause::misc(self.tcx.hir().span(var_hir_id), self.body_id);

let obligation_should_hold = check_trait
.map(|check_trait| self.ty_impls_trait(ty, &cause, check_trait))
.map(|check_trait| {
self.infcx
.type_implements_trait(
check_trait,
ty,
self.tcx.mk_substs_trait(ty, &[]),
self.param_env,
)
.must_apply_modulo_regions()
})
.unwrap_or(false);

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

let obligation_holds_for_capture = check_trait
.map(|check_trait| self.ty_impls_trait(ty, &cause, check_trait))
.map(|check_trait| {
self.infcx
.type_implements_trait(
check_trait,
ty,
self.tcx.mk_substs_trait(ty, &[]),
self.param_env,
)
.must_apply_modulo_regions()
})
.unwrap_or(false);

if !obligation_holds_for_capture && obligation_should_hold {
Expand Down Expand Up @@ -961,13 +952,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let is_drop_defined_for_ty = |ty: Ty<'tcx>| {
let drop_trait = self.tcx.require_lang_item(hir::LangItem::Drop, Some(closure_span));
let ty_params = self.tcx.mk_substs_trait(base_path_ty, &[]);
self.tcx
.type_implements_trait((
self.infcx
.type_implements_trait(
drop_trait,
ty,
ty_params,
self.tcx.param_env(closure_def_id.expect_local()),
))
)
.must_apply_modulo_regions()
};

Expand Down
50 changes: 50 additions & 0 deletions src/test/incremental/issue-86753.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
// edition:2018
// revisions: rpass1


// Regression test for #86753. The `type_implements_trait` query (since moved to a method)
// was encountering an ICE during incremental testing when hashing its arguments.
#![warn(rust_2021_compatibility)]

use std::future::Future;
use std::pin::Pin;
use std::task::{Poll, Context};

struct LocalSet {}
struct RunUntil<'a, F> {
_local_set: &'a LocalSet,
_future: F,
}
impl<'a, F> RunUntil<'a, F> {
fn project<'pin>(self: Pin<&'pin mut Self>) -> Projection<'pin, 'a, F> {
unimplemented!()
}
}

struct Projection<'pin, 'a, F>
where
RunUntil<'a, F>: 'pin,
{
pub local_set: &'pin mut &'a LocalSet,
pub future: Pin<&'pin mut F>,
}

impl LocalSet {
fn with<T>(&self, _f: impl FnOnce() -> T) -> T {
unimplemented!()
}
}
impl<T: Future> Future for RunUntil<'_, T> {
type Output = T::Output;
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
let me = self.project();
me.local_set.with(|| {
let _ = cx.waker();
let f = me.future;
let _ = f.poll(cx);
Poll::Pending
})
}
}

fn main() {}
4 changes: 3 additions & 1 deletion src/test/ui/issues/issue-73886.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@ error[E0605]: non-primitive cast: `u32` as `Option<_>`
--> $DIR/issue-73886.rs:4:13
|
LL | let _ = 7u32 as Option<_>;
| ^^^^^^^^^^^^^^^^^ an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object
| ^^^^^^^^^^^^^^^^^ help: consider using the `From` trait instead: `Option<_>::from(7u32)`
|
= note: an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object

error: aborting due to 2 previous errors

Expand Down
Loading

0 comments on commit c0bd5a5

Please sign in to comment.