Skip to content

Commit

Permalink
Auto merge of #54252 - arielb1:deref-query, r=nikomatsakis
Browse files Browse the repository at this point in the history
process nested obligations in autoderef

Fixes #53843.

r? @nikomatsakis
  • Loading branch information
bors committed Dec 19, 2018
2 parents 790f4c5 + b4db387 commit daa8792
Show file tree
Hide file tree
Showing 18 changed files with 488 additions and 192 deletions.
1 change: 1 addition & 0 deletions src/librustc/dep_graph/dep_node.rs
Original file line number Diff line number Diff line change
Expand Up @@ -669,6 +669,7 @@ define_dep_nodes!( <'tcx>
[] TypeOpNormalizeFnSig(CanonicalTypeOpNormalizeGoal<'tcx, FnSig<'tcx>>),

[] SubstituteNormalizeAndTestPredicates { key: (DefId, &'tcx Substs<'tcx>) },
[] MethodAutoderefSteps(CanonicalTyGoal<'tcx>),

[input] TargetFeaturesWhitelist,

Expand Down
25 changes: 25 additions & 0 deletions src/librustc/infer/canonical/query_response.rs
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,31 @@ impl<'cx, 'gcx, 'tcx> InferCtxt<'cx, 'gcx, 'tcx> {
Ok(Lrc::new(canonical_result))
}

/// A version of `make_canonicalized_query_response` that does
/// not pack in obligations, for contexts that want to drop
/// pending obligations instead of treating them as an ambiguity (e.g.
/// typeck "probing" contexts).
///
/// If you DO want to keep track of pending obligations (which
/// include all region obligations, so this includes all cases
/// that care about regions) with this function, you have to
/// do it yourself, by e.g. having them be a part of the answer.
pub fn make_query_response_ignoring_pending_obligations<T>(
&self,
inference_vars: CanonicalVarValues<'tcx>,
answer: T
) -> Canonical<'gcx, QueryResponse<'gcx, <T as Lift<'gcx>>::Lifted>>
where
T: Debug + Lift<'gcx> + TypeFoldable<'tcx>,
{
self.canonicalize_response(&QueryResponse {
var_values: inference_vars,
region_constraints: vec![],
certainty: Certainty::Proven, // Ambiguities are OK!
value: answer,
})
}

/// Helper for `make_canonicalized_query_response` that does
/// everything up until the final canonicalization.
fn make_query_response<T>(
Expand Down
26 changes: 23 additions & 3 deletions src/librustc/traits/fulfill.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,16 @@ pub struct FulfillmentContext<'tcx> {
// type-lives-for-region constraints, and because the type
// is well-formed, the constraints should hold.
register_region_obligations: bool,
// Is it OK to register obligations into this infcx inside
// an infcx snapshot?
//
// The "primary fulfillment" in many cases in typeck lives
// outside of any snapshot, so any use of it inside a snapshot
// will lead to trouble and therefore is checked against, but
// other fulfillment contexts sometimes do live inside of
// a snapshot (they don't *straddle* a snapshot, so there
// is no trouble there).
usable_in_snapshot: bool
}

#[derive(Clone, Debug)]
Expand All @@ -74,14 +84,24 @@ impl<'a, 'gcx, 'tcx> FulfillmentContext<'tcx> {
pub fn new() -> FulfillmentContext<'tcx> {
FulfillmentContext {
predicates: ObligationForest::new(),
register_region_obligations: true
register_region_obligations: true,
usable_in_snapshot: false,
}
}

pub fn new_in_snapshot() -> FulfillmentContext<'tcx> {
FulfillmentContext {
predicates: ObligationForest::new(),
register_region_obligations: true,
usable_in_snapshot: true,
}
}

pub fn new_ignoring_regions() -> FulfillmentContext<'tcx> {
FulfillmentContext {
predicates: ObligationForest::new(),
register_region_obligations: false
register_region_obligations: false,
usable_in_snapshot: false
}
}

Expand Down Expand Up @@ -195,7 +215,7 @@ impl<'tcx> TraitEngine<'tcx> for FulfillmentContext<'tcx> {

debug!("register_predicate_obligation(obligation={:?})", obligation);

assert!(!infcx.is_in_snapshot());
assert!(!infcx.is_in_snapshot() || self.usable_in_snapshot);

self.predicates.register_obligation(PendingPredicateObligation {
obligation,
Expand Down
55 changes: 55 additions & 0 deletions src/librustc/traits/query/method_autoderef.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use rustc_data_structures::sync::Lrc;
use infer::canonical::{Canonical, QueryResponse};
use ty::Ty;

#[derive(Debug)]
pub struct CandidateStep<'tcx> {
pub self_ty: Canonical<'tcx, QueryResponse<'tcx, Ty<'tcx>>>,
pub autoderefs: usize,
// true if the type results from a dereference of a raw pointer.
// when assembling candidates, we include these steps, but not when
// picking methods. This so that if we have `foo: *const Foo` and `Foo` has methods
// `fn by_raw_ptr(self: *const Self)` and `fn by_ref(&self)`, then
// `foo.by_raw_ptr()` will work and `foo.by_ref()` won't.
pub from_unsafe_deref: bool,
pub unsize: bool,
}

#[derive(Clone, Debug)]
pub struct MethodAutoderefStepsResult<'tcx> {
/// The valid autoderef steps that could be find.
pub steps: Lrc<Vec<CandidateStep<'tcx>>>,
/// If Some(T), a type autoderef reported an error on.
pub opt_bad_ty: Option<Lrc<MethodAutoderefBadTy<'tcx>>>,
/// If `true`, `steps` has been truncated due to reaching the
/// recursion limit.
pub reached_recursion_limit: bool,
}

#[derive(Debug)]
pub struct MethodAutoderefBadTy<'tcx> {
pub reached_raw_pointer: bool,
pub ty: Canonical<'tcx, QueryResponse<'tcx, Ty<'tcx>>>,
}

impl_stable_hash_for!(struct MethodAutoderefBadTy<'tcx> {
reached_raw_pointer, ty
});

impl_stable_hash_for!(struct MethodAutoderefStepsResult<'tcx> {
reached_recursion_limit, steps, opt_bad_ty
});

impl_stable_hash_for!(struct CandidateStep<'tcx> {
self_ty, autoderefs, from_unsafe_deref, unsize
});
1 change: 1 addition & 0 deletions src/librustc/traits/query/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ use ty::{self, Ty};

pub mod dropck_outlives;
pub mod evaluate_obligation;
pub mod method_autoderef;
pub mod normalize;
pub mod normalize_erasing_regions;
pub mod outlives_bounds;
Expand Down
6 changes: 6 additions & 0 deletions src/librustc/ty/query/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -827,6 +827,12 @@ impl<'tcx> QueryDescription<'tcx> for queries::substitute_normalize_and_test_pre
}
}

impl<'tcx> QueryDescription<'tcx> for queries::method_autoderef_steps<'tcx> {
fn describe(_tcx: TyCtxt<'_, '_, '_>, goal: CanonicalTyGoal<'tcx>) -> Cow<'static, str> {
format!("computing autoderef types for `{:?}`", goal).into()
}
}

impl<'tcx> QueryDescription<'tcx> for queries::target_features_whitelist<'tcx> {
fn describe(_tcx: TyCtxt<'_, '_, '_>, _: CrateNum) -> Cow<'static, str> {
"looking up the whitelist of target features".into()
Expand Down
5 changes: 5 additions & 0 deletions src/librustc/ty/query/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ use traits::query::{
CanonicalTypeOpSubtypeGoal, CanonicalTypeOpProvePredicateGoal,
CanonicalTypeOpNormalizeGoal, NoSolution,
};
use traits::query::method_autoderef::MethodAutoderefStepsResult;
use traits::query::dropck_outlives::{DtorckConstraint, DropckOutlivesResult};
use traits::query::normalize::NormalizationResult;
use traits::query::outlives_bounds::OutlivesBound;
Expand Down Expand Up @@ -668,6 +669,10 @@ define_queries! { <'tcx>

[] fn substitute_normalize_and_test_predicates:
substitute_normalize_and_test_predicates_node((DefId, &'tcx Substs<'tcx>)) -> bool,

[] fn method_autoderef_steps: MethodAutoderefSteps(
CanonicalTyGoal<'tcx>
) -> MethodAutoderefStepsResult<'tcx>,
},

Other {
Expand Down
1 change: 1 addition & 0 deletions src/librustc/ty/query/plumbing.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1116,6 +1116,7 @@ pub fn force_from_dep_node<'a, 'gcx, 'lcx>(tcx: TyCtxt<'a, 'gcx, 'lcx>,
DepKind::TypeOpNormalizePolyFnSig |
DepKind::TypeOpNormalizeFnSig |
DepKind::SubstituteNormalizeAndTestPredicates |
DepKind::MethodAutoderefSteps |
DepKind::InstanceDefSizeEstimate |
DepKind::ProgramClausesForEnv |

Expand Down
Loading

0 comments on commit daa8792

Please sign in to comment.