Auto merge of #54858 - nikomatsakis:universes-refactor-2, r=scalexm

second round of refactorings for universes

A second round of (what I believe to be) "no functional change" refactorings, taken from my universes branch.

r? @scalexm
This commit is contained in:
bors 2018-10-15 16:46:55 +00:00
commit 5a52983d69
30 changed files with 525 additions and 490 deletions

View file

@ -1297,7 +1297,7 @@ impl_stable_hash_for!(enum infer::canonical::CanonicalTyVarKind {
});
impl_stable_hash_for!(
impl<'tcx, R> for struct infer::canonical::QueryResult<'tcx, R> {
impl<'tcx, R> for struct infer::canonical::QueryResponse<'tcx, R> {
var_values, region_constraints, certainty, value
}
);

View file

@ -17,7 +17,7 @@
use infer::canonical::{
Canonical, CanonicalTyVarKind, CanonicalVarInfo, CanonicalVarKind, Canonicalized,
SmallCanonicalVarValues,
OriginalQueryValues,
};
use infer::InferCtxt;
use std::sync::atomic::Ordering;
@ -48,7 +48,7 @@ impl<'cx, 'gcx, 'tcx> InferCtxt<'cx, 'gcx, 'tcx> {
pub fn canonicalize_query<V>(
&self,
value: &V,
var_values: &mut SmallCanonicalVarValues<'tcx>
query_state: &mut OriginalQueryValues<'tcx>,
) -> Canonicalized<'gcx, V>
where
V: TypeFoldable<'tcx> + Lift<'gcx>,
@ -63,11 +63,8 @@ impl<'cx, 'gcx, 'tcx> InferCtxt<'cx, 'gcx, 'tcx> {
value,
Some(self),
self.tcx,
CanonicalizeRegionMode {
static_region: true,
other_free_regions: true,
},
var_values,
&CanonicalizeAllFreeRegions,
query_state,
)
}
@ -96,23 +93,17 @@ impl<'cx, 'gcx, 'tcx> InferCtxt<'cx, 'gcx, 'tcx> {
/// out the [chapter in the rustc guide][c].
///
/// [c]: https://rust-lang-nursery.github.io/rustc-guide/traits/canonicalization.html#canonicalizing-the-query-result
pub fn canonicalize_response<V>(
&self,
value: &V,
) -> Canonicalized<'gcx, V>
pub fn canonicalize_response<V>(&self, value: &V) -> Canonicalized<'gcx, V>
where
V: TypeFoldable<'tcx> + Lift<'gcx>,
{
let mut var_values = SmallVec::new();
let mut query_state = OriginalQueryValues::default();
Canonicalizer::canonicalize(
value,
Some(self),
self.tcx,
CanonicalizeRegionMode {
static_region: false,
other_free_regions: false,
},
&mut var_values
&CanonicalizeQueryResponse,
&mut query_state,
)
}
@ -128,7 +119,7 @@ impl<'cx, 'gcx, 'tcx> InferCtxt<'cx, 'gcx, 'tcx> {
pub fn canonicalize_hr_query_hack<V>(
&self,
value: &V,
var_values: &mut SmallCanonicalVarValues<'tcx>
query_state: &mut OriginalQueryValues<'tcx>,
) -> Canonicalized<'gcx, V>
where
V: TypeFoldable<'tcx> + Lift<'gcx>,
@ -143,27 +134,87 @@ impl<'cx, 'gcx, 'tcx> InferCtxt<'cx, 'gcx, 'tcx> {
value,
Some(self),
self.tcx,
CanonicalizeRegionMode {
static_region: false,
other_free_regions: true,
},
var_values
&CanonicalizeFreeRegionsOtherThanStatic,
query_state,
)
}
}
/// If this flag is true, then all free regions will be replaced with
/// a canonical var. This is used to make queries as generic as
/// possible. For example, the query `F: Foo<'static>` would be
/// canonicalized to `F: Foo<'0>`.
struct CanonicalizeRegionMode {
static_region: bool,
other_free_regions: bool,
/// Controls how we canonicalize "free regions" that are not inference
/// variables. This depends on what we are canonicalizing *for* --
/// e.g., if we are canonicalizing to create a query, we want to
/// replace those with inference variables, since we want to make a
/// maximally general query. But if we are canonicalizing a *query
/// response*, then we don't typically replace free regions, as they
/// must have been introduced from other parts of the system.
trait CanonicalizeRegionMode {
fn canonicalize_free_region(
&self,
canonicalizer: &mut Canonicalizer<'_, '_, 'tcx>,
r: ty::Region<'tcx>,
) -> ty::Region<'tcx>;
fn any(&self) -> bool;
}
impl CanonicalizeRegionMode {
struct CanonicalizeQueryResponse;
impl CanonicalizeRegionMode for CanonicalizeQueryResponse {
fn canonicalize_free_region(
&self,
_canonicalizer: &mut Canonicalizer<'_, '_, 'tcx>,
r: ty::Region<'tcx>,
) -> ty::Region<'tcx> {
match r {
ty::ReFree(_) | ty::ReEmpty | ty::ReErased | ty::ReStatic | ty::ReEarlyBound(..) => r,
_ => {
// Other than `'static` or `'empty`, the query
// response should be executing in a fully
// canonicalized environment, so there shouldn't be
// any other region names it can come up.
bug!("unexpected region in query response: `{:?}`", r)
}
}
}
fn any(&self) -> bool {
self.static_region || self.other_free_regions
false
}
}
struct CanonicalizeAllFreeRegions;
impl CanonicalizeRegionMode for CanonicalizeAllFreeRegions {
fn canonicalize_free_region(
&self,
canonicalizer: &mut Canonicalizer<'_, '_, 'tcx>,
r: ty::Region<'tcx>,
) -> ty::Region<'tcx> {
canonicalizer.canonical_var_for_region(r)
}
fn any(&self) -> bool {
true
}
}
struct CanonicalizeFreeRegionsOtherThanStatic;
impl CanonicalizeRegionMode for CanonicalizeFreeRegionsOtherThanStatic {
fn canonicalize_free_region(
&self,
canonicalizer: &mut Canonicalizer<'_, '_, 'tcx>,
r: ty::Region<'tcx>,
) -> ty::Region<'tcx> {
if let ty::ReStatic = r {
r
} else {
canonicalizer.canonical_var_for_region(r)
}
}
fn any(&self) -> bool {
true
}
}
@ -171,11 +222,11 @@ struct Canonicalizer<'cx, 'gcx: 'tcx, 'tcx: 'cx> {
infcx: Option<&'cx InferCtxt<'cx, 'gcx, 'tcx>>,
tcx: TyCtxt<'cx, 'gcx, 'tcx>,
variables: SmallVec<[CanonicalVarInfo; 8]>,
var_values: &'cx mut SmallCanonicalVarValues<'tcx>,
query_state: &'cx mut OriginalQueryValues<'tcx>,
// Note that indices is only used once `var_values` is big enough to be
// heap-allocated.
indices: FxHashMap<Kind<'tcx>, CanonicalVar>,
canonicalize_region_mode: CanonicalizeRegionMode,
canonicalize_region_mode: &'cx dyn CanonicalizeRegionMode,
needs_canonical_flags: TypeFlags,
}
@ -192,51 +243,25 @@ impl<'cx, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for Canonicalizer<'cx, 'gcx, 'tcx>
}
ty::ReVar(vid) => {
let r = self
.infcx
let r = self.infcx
.unwrap()
.borrow_region_constraints()
.opportunistic_resolve_var(self.tcx, vid);
let info = CanonicalVarInfo {
kind: CanonicalVarKind::Region,
};
debug!(
"canonical: region var found with vid {:?}, \
opportunistically resolved to {:?}",
vid, r
);
let cvar = self.canonical_var(info, r.into());
self.tcx().mk_region(ty::ReCanonical(cvar))
self.canonical_var_for_region(r)
}
ty::ReStatic => {
if self.canonicalize_region_mode.static_region {
let info = CanonicalVarInfo {
kind: CanonicalVarKind::Region,
};
let cvar = self.canonical_var(info, r.into());
self.tcx().mk_region(ty::ReCanonical(cvar))
} else {
r
}
}
ty::ReEarlyBound(..)
ty::ReStatic
| ty::ReEarlyBound(..)
| ty::ReFree(_)
| ty::ReScope(_)
| ty::RePlaceholder(..)
| ty::ReEmpty
| ty::ReErased => {
if self.canonicalize_region_mode.other_free_regions {
let info = CanonicalVarInfo {
kind: CanonicalVarKind::Region,
};
let cvar = self.canonical_var(info, r.into());
self.tcx().mk_region(ty::ReCanonical(cvar))
} else {
r
}
}
| ty::ReErased => self.canonicalize_region_mode.canonicalize_free_region(self, r),
ty::ReClosureBound(..) | ty::ReCanonical(_) => {
bug!("canonical region encountered during canonicalization")
@ -302,10 +327,10 @@ impl<'cx, 'gcx, 'tcx> Canonicalizer<'cx, 'gcx, 'tcx> {
/// `canonicalize_query` and `canonicalize_response`.
fn canonicalize<V>(
value: &V,
infcx: Option<&'cx InferCtxt<'cx, 'gcx, 'tcx>>,
tcx: TyCtxt<'cx, 'gcx, 'tcx>,
canonicalize_region_mode: CanonicalizeRegionMode,
var_values: &'cx mut SmallCanonicalVarValues<'tcx>
infcx: Option<&InferCtxt<'_, 'gcx, 'tcx>>,
tcx: TyCtxt<'_, 'gcx, 'tcx>,
canonicalize_region_mode: &dyn CanonicalizeRegionMode,
query_state: &mut OriginalQueryValues<'tcx>,
) -> Canonicalized<'gcx, V>
where
V: TypeFoldable<'tcx> + Lift<'gcx>,
@ -340,7 +365,7 @@ impl<'cx, 'gcx, 'tcx> Canonicalizer<'cx, 'gcx, 'tcx> {
canonicalize_region_mode,
needs_canonical_flags,
variables: SmallVec::new(),
var_values,
query_state,
indices: FxHashMap::default(),
};
let out_value = value.fold_with(&mut canonicalizer);
@ -371,11 +396,13 @@ impl<'cx, 'gcx, 'tcx> Canonicalizer<'cx, 'gcx, 'tcx> {
fn canonical_var(&mut self, info: CanonicalVarInfo, kind: Kind<'tcx>) -> CanonicalVar {
let Canonicalizer {
variables,
var_values,
query_state,
indices,
..
} = self;
let var_values = &mut query_state.var_values;
// This code is hot. `variables` and `var_values` are usually small
// (fewer than 8 elements ~95% of the time). They are SmallVec's to
// avoid allocations in those cases. We also don't use `indices` to
@ -398,28 +425,34 @@ impl<'cx, 'gcx, 'tcx> Canonicalizer<'cx, 'gcx, 'tcx> {
// fill up `indices` to facilitate subsequent lookups.
if var_values.spilled() {
assert!(indices.is_empty());
*indices =
var_values.iter()
.enumerate()
.map(|(i, &kind)| (kind, CanonicalVar::new(i)))
.collect();
*indices = var_values
.iter()
.enumerate()
.map(|(i, &kind)| (kind, CanonicalVar::new(i)))
.collect();
}
// The cv is the index of the appended element.
CanonicalVar::new(var_values.len() - 1)
}
} else {
// `var_values` is large. Do a hashmap search via `indices`.
*indices
.entry(kind)
.or_insert_with(|| {
variables.push(info);
var_values.push(kind);
assert_eq!(variables.len(), var_values.len());
CanonicalVar::new(variables.len() - 1)
})
*indices.entry(kind).or_insert_with(|| {
variables.push(info);
var_values.push(kind);
assert_eq!(variables.len(), var_values.len());
CanonicalVar::new(variables.len() - 1)
})
}
}
fn canonical_var_for_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
let info = CanonicalVarInfo {
kind: CanonicalVarKind::Region,
};
let cvar = self.canonical_var(info, r.into());
self.tcx().mk_region(ty::ReCanonical(cvar))
}
/// Given a type variable `ty_var` of the given kind, first check
/// if `ty_var` is bound to anything; if so, canonicalize
/// *that*. Otherwise, create a new canonical variable for

View file

@ -44,7 +44,7 @@ use ty::{self, CanonicalVar, Lift, Region, List, TyCtxt};
mod canonicalizer;
pub mod query_result;
pub mod query_response;
mod substitute;
@ -75,9 +75,16 @@ pub struct CanonicalVarValues<'tcx> {
pub var_values: IndexVec<CanonicalVar, Kind<'tcx>>,
}
/// Like CanonicalVarValues, but for use in places where a SmallVec is
/// appropriate.
pub type SmallCanonicalVarValues<'tcx> = SmallVec<[Kind<'tcx>; 8]>;
/// When we canonicalize a value to form a query, we wind up replacing
/// various parts of it with canonical variables. This struct stores
/// those replaced bits to remember for when we process the query
/// result.
#[derive(Clone, Debug, Default, PartialEq, Eq, Hash, RustcDecodable, RustcEncodable)]
pub struct OriginalQueryValues<'tcx> {
/// This is equivalent to `CanonicalVarValues`, but using a
/// `SmallVec` yields a significant performance win.
pub var_values: SmallVec<[Kind<'tcx>; 8]>,
}
/// Information about a canonical variable that is included with the
/// canonical value. This is sufficient information for code to create
@ -118,10 +125,10 @@ pub enum CanonicalTyVarKind {
}
/// After we execute a query with a canonicalized key, we get back a
/// `Canonical<QueryResult<..>>`. You can use
/// `Canonical<QueryResponse<..>>`. You can use
/// `instantiate_query_result` to access the data in this result.
#[derive(Clone, Debug)]
pub struct QueryResult<'tcx, R> {
pub struct QueryResponse<'tcx, R> {
pub var_values: CanonicalVarValues<'tcx>,
pub region_constraints: Vec<QueryRegionConstraint<'tcx>>,
pub certainty: Certainty,
@ -130,8 +137,8 @@ pub struct QueryResult<'tcx, R> {
pub type Canonicalized<'gcx, V> = Canonical<'gcx, <V as Lift<'gcx>>::Lifted>;
pub type CanonicalizedQueryResult<'gcx, T> =
Lrc<Canonical<'gcx, QueryResult<'gcx, <T as Lift<'gcx>>::Lifted>>>;
pub type CanonicalizedQueryResponse<'gcx, T> =
Lrc<Canonical<'gcx, QueryResponse<'gcx, <T as Lift<'gcx>>::Lifted>>>;
/// Indicates whether or not we were able to prove the query to be
/// true.
@ -168,7 +175,7 @@ impl Certainty {
}
}
impl<'tcx, R> QueryResult<'tcx, R> {
impl<'tcx, R> QueryResponse<'tcx, R> {
pub fn is_proven(&self) -> bool {
self.certainty.is_proven()
}
@ -178,7 +185,7 @@ impl<'tcx, R> QueryResult<'tcx, R> {
}
}
impl<'tcx, R> Canonical<'tcx, QueryResult<'tcx, R>> {
impl<'tcx, R> Canonical<'tcx, QueryResponse<'tcx, R>> {
pub fn is_proven(&self) -> bool {
self.value.is_proven()
}
@ -225,12 +232,16 @@ impl<'cx, 'gcx, 'tcx> InferCtxt<'cx, 'gcx, 'tcx> {
/// inference variables and applies it to the canonical value.
/// Returns both the instantiated result *and* the substitution S.
///
/// This is useful at the start of a query: it basically brings
/// the canonical value "into scope" within your new infcx. At the
/// end of processing, the substitution S (once canonicalized)
/// then represents the values that you computed for each of the
/// canonical inputs to your query.
pub fn instantiate_canonical_with_fresh_inference_vars<T>(
/// This is only meant to be invoked as part of constructing an
/// inference context at the start of a query (see
/// `InferCtxtBuilder::enter_with_canonical`). It basically
/// brings the canonical value "into scope" within your new infcx.
///
/// At the end of processing, the substitution S (once
/// canonicalized) then represents the values that you computed
/// for each of the canonical inputs to your query.
pub(in infer) fn instantiate_canonical_with_fresh_inference_vars<T>(
&self,
span: Span,
canonical: &Canonical<'tcx, T>,
@ -238,6 +249,9 @@ impl<'cx, 'gcx, 'tcx> InferCtxt<'cx, 'gcx, 'tcx> {
where
T: TypeFoldable<'tcx>,
{
assert_eq!(self.universe(), ty::UniverseIndex::ROOT, "infcx not newly created");
assert_eq!(self.type_variables.borrow().num_vars(), 0, "infcx not newly created");
let canonical_inference_vars =
self.fresh_inference_vars_for_canonical_vars(span, canonical.variables);
let result = canonical.substitute(self.tcx, &canonical_inference_vars);
@ -344,14 +358,14 @@ BraceStructTypeFoldableImpl! {
}
BraceStructTypeFoldableImpl! {
impl<'tcx, R> TypeFoldable<'tcx> for QueryResult<'tcx, R> {
impl<'tcx, R> TypeFoldable<'tcx> for QueryResponse<'tcx, R> {
var_values, region_constraints, certainty, value
} where R: TypeFoldable<'tcx>,
}
BraceStructLiftImpl! {
impl<'a, 'tcx, R> Lift<'tcx> for QueryResult<'a, R> {
type Lifted = QueryResult<'tcx, R::Lifted>;
impl<'a, 'tcx, R> Lift<'tcx> for QueryResponse<'a, R> {
type Lifted = QueryResponse<'tcx, R::Lifted>;
var_values, region_constraints, certainty, value
} where R: Lift<'tcx>
}

View file

@ -19,8 +19,8 @@
use infer::canonical::substitute::substitute_value;
use infer::canonical::{
Canonical, CanonicalVarKind, CanonicalVarValues, CanonicalizedQueryResult, Certainty,
QueryRegionConstraint, QueryResult, SmallCanonicalVarValues,
Canonical, CanonicalVarKind, CanonicalVarValues, CanonicalizedQueryResponse, Certainty,
OriginalQueryValues, QueryRegionConstraint, QueryResponse,
};
use infer::region_constraints::{Constraint, RegionConstraintData};
use infer::InferCtxtBuilder;
@ -59,18 +59,20 @@ impl<'cx, 'gcx, 'tcx> InferCtxtBuilder<'cx, 'gcx, 'tcx> {
canonical_key: &Canonical<'tcx, K>,
operation: impl FnOnce(&InferCtxt<'_, 'gcx, 'tcx>, &mut FulfillmentContext<'tcx>, K)
-> Fallible<R>,
) -> Fallible<CanonicalizedQueryResult<'gcx, R>>
) -> Fallible<CanonicalizedQueryResponse<'gcx, R>>
where
K: TypeFoldable<'tcx>,
R: Debug + Lift<'gcx> + TypeFoldable<'tcx>,
{
self.enter(|ref infcx| {
let (key, canonical_inference_vars) =
infcx.instantiate_canonical_with_fresh_inference_vars(DUMMY_SP, &canonical_key);
let fulfill_cx = &mut FulfillmentContext::new();
let value = operation(infcx, fulfill_cx, key)?;
infcx.make_canonicalized_query_result(canonical_inference_vars, value, fulfill_cx)
})
self.enter_with_canonical(
DUMMY_SP,
canonical_key,
|ref infcx, key, canonical_inference_vars| {
let fulfill_cx = &mut FulfillmentContext::new();
let value = operation(infcx, fulfill_cx, key)?;
infcx.make_canonicalized_query_response(canonical_inference_vars, value, fulfill_cx)
},
)
}
}
@ -94,41 +96,41 @@ impl<'cx, 'gcx, 'tcx> InferCtxt<'cx, 'gcx, 'tcx> {
/// the same thing happens, but the resulting query is marked as ambiguous.
/// - Finally, if any of the obligations result in a hard error,
/// then `Err(NoSolution)` is returned.
pub fn make_canonicalized_query_result<T>(
pub fn make_canonicalized_query_response<T>(
&self,
inference_vars: CanonicalVarValues<'tcx>,
answer: T,
fulfill_cx: &mut FulfillmentContext<'tcx>,
) -> Fallible<CanonicalizedQueryResult<'gcx, T>>
) -> Fallible<CanonicalizedQueryResponse<'gcx, T>>
where
T: Debug + Lift<'gcx> + TypeFoldable<'tcx>,
{
let query_result = self.make_query_result(inference_vars, answer, fulfill_cx)?;
let canonical_result = self.canonicalize_response(&query_result);
let query_response = self.make_query_response(inference_vars, answer, fulfill_cx)?;
let canonical_result = self.canonicalize_response(&query_response);
debug!(
"make_canonicalized_query_result: canonical_result = {:#?}",
"make_canonicalized_query_response: canonical_result = {:#?}",
canonical_result
);
Ok(Lrc::new(canonical_result))
}
/// Helper for `make_canonicalized_query_result` that does
/// Helper for `make_canonicalized_query_response` that does
/// everything up until the final canonicalization.
fn make_query_result<T>(
fn make_query_response<T>(
&self,
inference_vars: CanonicalVarValues<'tcx>,
answer: T,
fulfill_cx: &mut FulfillmentContext<'tcx>,
) -> Result<QueryResult<'tcx, T>, NoSolution>
) -> Result<QueryResponse<'tcx, T>, NoSolution>
where
T: Debug + TypeFoldable<'tcx> + Lift<'gcx>,
{
let tcx = self.tcx;
debug!(
"make_query_result(\
"make_query_response(\
inference_vars={:?}, \
answer={:?})",
inference_vars, answer,
@ -140,7 +142,7 @@ impl<'cx, 'gcx, 'tcx> InferCtxt<'cx, 'gcx, 'tcx> {
if !true_errors.is_empty() {
// FIXME -- we don't indicate *why* we failed to solve
debug!("make_query_result: true_errors={:#?}", true_errors);
debug!("make_query_response: true_errors={:#?}", true_errors);
return Err(NoSolution);
}
@ -155,7 +157,8 @@ impl<'cx, 'gcx, 'tcx> InferCtxt<'cx, 'gcx, 'tcx> {
region_obligations
.iter()
.map(|(_, r_o)| (r_o.sup_type, r_o.sub_region)),
region_constraints)
region_constraints,
)
});
let certainty = if ambig_errors.is_empty() {
@ -164,7 +167,7 @@ impl<'cx, 'gcx, 'tcx> InferCtxt<'cx, 'gcx, 'tcx> {
Certainty::Ambiguous
};
Ok(QueryResult {
Ok(QueryResponse {
var_values: inference_vars,
region_constraints,
certainty,
@ -182,12 +185,12 @@ impl<'cx, 'gcx, 'tcx> InferCtxt<'cx, 'gcx, 'tcx> {
/// out the [chapter in the rustc guide][c].
///
/// [c]: https://rust-lang-nursery.github.io/rustc-guide/traits/canonicalization.html#processing-the-canonicalized-query-result
pub fn instantiate_query_result_and_region_obligations<R>(
pub fn instantiate_query_response_and_region_obligations<R>(
&self,
cause: &ObligationCause<'tcx>,
param_env: ty::ParamEnv<'tcx>,
original_values: &SmallCanonicalVarValues<'tcx>,
query_result: &Canonical<'tcx, QueryResult<'tcx, R>>,
original_values: &OriginalQueryValues<'tcx>,
query_response: &Canonical<'tcx, QueryResponse<'tcx, R>>,
) -> InferResult<'tcx, R>
where
R: Debug + TypeFoldable<'tcx>,
@ -195,17 +198,17 @@ impl<'cx, 'gcx, 'tcx> InferCtxt<'cx, 'gcx, 'tcx> {
let InferOk {
value: result_subst,
mut obligations,
} = self.query_result_substitution(cause, param_env, original_values, query_result)?;
} = self.query_response_substitution(cause, param_env, original_values, query_response)?;
obligations.extend(self.query_region_constraints_into_obligations(
cause,
param_env,
&query_result.value.region_constraints,
&query_response.value.region_constraints,
&result_subst,
));
let user_result: R =
query_result.substitute_projected(self.tcx, &result_subst, |q_r| &q_r.value);
query_response.substitute_projected(self.tcx, &result_subst, |q_r| &q_r.value);
Ok(InferOk {
value: user_result,
@ -214,7 +217,7 @@ impl<'cx, 'gcx, 'tcx> InferCtxt<'cx, 'gcx, 'tcx> {
}
/// An alternative to
/// `instantiate_query_result_and_region_obligations` that is more
/// `instantiate_query_response_and_region_obligations` that is more
/// efficient for NLL. NLL is a bit more advanced in the
/// "transition to chalk" than the rest of the compiler. During
/// the NLL type check, all of the "processing" of types and
@ -229,8 +232,8 @@ impl<'cx, 'gcx, 'tcx> InferCtxt<'cx, 'gcx, 'tcx> {
/// into the older infcx-style constraints (e.g., calls to
/// `sub_regions` or `register_region_obligation`).
///
/// Therefore, `instantiate_nll_query_result_and_region_obligations` performs the same
/// basic operations as `instantiate_query_result_and_region_obligations` but
/// Therefore, `instantiate_nll_query_response_and_region_obligations` performs the same
/// basic operations as `instantiate_query_response_and_region_obligations` but
/// it returns its result differently:
///
/// - It creates a substitution `S` that maps from the original
@ -248,12 +251,12 @@ impl<'cx, 'gcx, 'tcx> InferCtxt<'cx, 'gcx, 'tcx> {
/// are propagated back in the return value.
/// - Finally, the query result (of type `R`) is propagated back,
/// after applying the substitution `S`.
pub fn instantiate_nll_query_result_and_region_obligations<R>(
pub fn instantiate_nll_query_response_and_region_obligations<R>(
&self,
cause: &ObligationCause<'tcx>,
param_env: ty::ParamEnv<'tcx>,
original_values: &SmallCanonicalVarValues<'tcx>,
query_result: &Canonical<'tcx, QueryResult<'tcx, R>>,
original_values: &OriginalQueryValues<'tcx>,
query_response: &Canonical<'tcx, QueryResponse<'tcx, R>>,
output_query_region_constraints: &mut Vec<QueryRegionConstraint<'tcx>>,
) -> InferResult<'tcx, R>
where
@ -261,22 +264,22 @@ impl<'cx, 'gcx, 'tcx> InferCtxt<'cx, 'gcx, 'tcx> {
{
// In an NLL query, there should be no type variables in the
// query, only region variables.
debug_assert!(query_result.variables.iter().all(|v| match v.kind {
debug_assert!(query_response.variables.iter().all(|v| match v.kind {
CanonicalVarKind::Ty(_) => false,
CanonicalVarKind::Region => true,
}));
let result_subst =
self.query_result_substitution_guess(cause, original_values, query_result);
self.query_response_substitution_guess(cause, original_values, query_response);
// Compute `QueryRegionConstraint` values that unify each of
// the original values `v_o` that was canonicalized into a
// variable...
let mut obligations = vec![];
for (index, original_value) in original_values.iter().enumerate() {
for (index, original_value) in original_values.var_values.iter().enumerate() {
// ...with the value `v_r` of that variable from the query.
let result_value = query_result.substitute_projected(self.tcx, &result_subst, |v| {
let result_value = query_response.substitute_projected(self.tcx, &result_subst, |v| {
&v.var_values[CanonicalVar::new(index)]
});
match (original_value.unpack(), result_value.unpack()) {
@ -311,7 +314,7 @@ impl<'cx, 'gcx, 'tcx> InferCtxt<'cx, 'gcx, 'tcx> {
// ...also include the other query region constraints from the query.
output_query_region_constraints.extend(
query_result.value.region_constraints.iter().filter_map(|r_c| {
query_response.value.region_constraints.iter().filter_map(|r_c| {
let &ty::OutlivesPredicate(k1, r2) = r_c.skip_binder(); // reconstructed below
let k1 = substitute_value(self.tcx, &result_subst, &k1);
let r2 = substitute_value(self.tcx, &result_subst, &r2);
@ -324,7 +327,7 @@ impl<'cx, 'gcx, 'tcx> InferCtxt<'cx, 'gcx, 'tcx> {
);
let user_result: R =
query_result.substitute_projected(self.tcx, &result_subst, |q_r| &q_r.value);
query_response.substitute_projected(self.tcx, &result_subst, |q_r| &q_r.value);
Ok(InferOk {
value: user_result,
@ -342,30 +345,30 @@ impl<'cx, 'gcx, 'tcx> InferCtxt<'cx, 'gcx, 'tcx> {
/// example) we are doing lazy normalization and the value
/// assigned to a type variable is unified with an unnormalized
/// projection.
fn query_result_substitution<R>(
fn query_response_substitution<R>(
&self,
cause: &ObligationCause<'tcx>,
param_env: ty::ParamEnv<'tcx>,
original_values: &SmallCanonicalVarValues<'tcx>,
query_result: &Canonical<'tcx, QueryResult<'tcx, R>>,
original_values: &OriginalQueryValues<'tcx>,
query_response: &Canonical<'tcx, QueryResponse<'tcx, R>>,
) -> InferResult<'tcx, CanonicalVarValues<'tcx>>
where
R: Debug + TypeFoldable<'tcx>,
{
debug!(
"query_result_substitution(original_values={:#?}, query_result={:#?})",
original_values, query_result,
"query_response_substitution(original_values={:#?}, query_response={:#?})",
original_values, query_response,
);
let result_subst =
self.query_result_substitution_guess(cause, original_values, query_result);
self.query_response_substitution_guess(cause, original_values, query_response);
let obligations = self.unify_query_result_substitution_guess(
let obligations = self.unify_query_response_substitution_guess(
cause,
param_env,
original_values,
&result_subst,
query_result,
query_response,
)?
.into_obligations();
@ -384,26 +387,26 @@ impl<'cx, 'gcx, 'tcx> InferCtxt<'cx, 'gcx, 'tcx> {
/// will instantiate fresh inference variables for each canonical
/// variable instead. Therefore, the result of this method must be
/// properly unified
fn query_result_substitution_guess<R>(
fn query_response_substitution_guess<R>(
&self,
cause: &ObligationCause<'tcx>,
original_values: &SmallCanonicalVarValues<'tcx>,
query_result: &Canonical<'tcx, QueryResult<'tcx, R>>,
original_values: &OriginalQueryValues<'tcx>,
query_response: &Canonical<'tcx, QueryResponse<'tcx, R>>,
) -> CanonicalVarValues<'tcx>
where
R: Debug + TypeFoldable<'tcx>,
{
debug!(
"query_result_substitution_guess(original_values={:#?}, query_result={:#?})",
original_values, query_result,
"query_response_substitution_guess(original_values={:#?}, query_response={:#?})",
original_values, query_response,
);
// Every canonical query result includes values for each of
// the inputs to the query. Therefore, we begin by unifying
// these values with the original inputs that were
// canonicalized.
let result_values = &query_result.value.var_values;
assert_eq!(original_values.len(), result_values.len());
let result_values = &query_response.value.var_values;
assert_eq!(original_values.var_values.len(), result_values.len());
// Quickly try to find initial values for the canonical
// variables in the result in terms of the query. We do this
@ -413,11 +416,11 @@ impl<'cx, 'gcx, 'tcx> InferCtxt<'cx, 'gcx, 'tcx> {
// result, then we can type the corresponding value from the
// input. See the example above.
let mut opt_values: IndexVec<CanonicalVar, Option<Kind<'tcx>>> =
IndexVec::from_elem_n(None, query_result.variables.len());
IndexVec::from_elem_n(None, query_response.variables.len());
// In terms of our example above, we are iterating over pairs like:
// [(?A, Vec<?0>), ('static, '?1), (?B, ?0)]
for (original_value, result_value) in original_values.iter().zip(result_values) {
for (original_value, result_value) in original_values.var_values.iter().zip(result_values) {
match result_value.unpack() {
UnpackedKind::Type(result_value) => {
// e.g., here `result_value` might be `?0` in the example above...
@ -440,7 +443,7 @@ impl<'cx, 'gcx, 'tcx> InferCtxt<'cx, 'gcx, 'tcx> {
// given variable in the loop above, use that. Otherwise, use
// a fresh inference variable.
let result_subst = CanonicalVarValues {
var_values: query_result
var_values: query_response
.variables
.iter()
.enumerate()
@ -458,29 +461,34 @@ impl<'cx, 'gcx, 'tcx> InferCtxt<'cx, 'gcx, 'tcx> {
/// query result. Often, but not always, this is a no-op, because
/// we already found the mapping in the "guessing" step.
///
/// See also: `query_result_substitution_guess`
fn unify_query_result_substitution_guess<R>(
/// See also: `query_response_substitution_guess`
fn unify_query_response_substitution_guess<R>(
&self,
cause: &ObligationCause<'tcx>,
param_env: ty::ParamEnv<'tcx>,
original_values: &SmallCanonicalVarValues<'tcx>,
original_values: &OriginalQueryValues<'tcx>,
result_subst: &CanonicalVarValues<'tcx>,
query_result: &Canonical<'tcx, QueryResult<'tcx, R>>,
query_response: &Canonical<'tcx, QueryResponse<'tcx, R>>,
) -> InferResult<'tcx, ()>
where
R: Debug + TypeFoldable<'tcx>,
{
// A closure that yields the result value for the given
// canonical variable; this is taken from
// `query_result.var_values` after applying the substitution
// `query_response.var_values` after applying the substitution
// `result_subst`.
let substituted_query_result = |index: CanonicalVar| -> Kind<'tcx> {
query_result.substitute_projected(self.tcx, &result_subst, |v| &v.var_values[index])
let substituted_query_response = |index: CanonicalVar| -> Kind<'tcx> {
query_response.substitute_projected(self.tcx, &result_subst, |v| &v.var_values[index])
};
// Unify the original value for each variable with the value
// taken from `query_result` (after applying `result_subst`).
Ok(self.unify_canonical_vars(cause, param_env, original_values, substituted_query_result)?)
// taken from `query_response` (after applying `result_subst`).
Ok(self.unify_canonical_vars(
cause,
param_env,
original_values,
substituted_query_response,
)?)
}
/// Converts the region constraints resulting from a query into an
@ -524,12 +532,12 @@ impl<'cx, 'gcx, 'tcx> InferCtxt<'cx, 'gcx, 'tcx> {
&self,
cause: &ObligationCause<'tcx>,
param_env: ty::ParamEnv<'tcx>,
variables1: &SmallCanonicalVarValues<'tcx>,
variables1: &OriginalQueryValues<'tcx>,
variables2: impl Fn(CanonicalVar) -> Kind<'tcx>,
) -> InferResult<'tcx, ()> {
self.commit_if_ok(|_| {
let mut obligations = vec![];
for (index, value1) in variables1.iter().enumerate() {
for (index, value1) in variables1.var_values.iter().enumerate() {
let value2 = variables2(CanonicalVar::new(index));
match (value1.unpack(), value2.unpack()) {

View file

@ -593,11 +593,11 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
where
T : TypeFoldable<'tcx>,
{
let new_universe = self.create_subuniverse();
let next_universe = self.create_next_universe();
let (result, map) = self.tcx.replace_late_bound_regions(binder, |br| {
self.tcx.mk_region(ty::RePlaceholder(ty::Placeholder {
universe: new_universe,
universe: next_universe,
name: br,
}))
});

View file

@ -20,6 +20,7 @@ pub use ty::IntVarValue;
use arena::SyncDroplessArena;
use errors::DiagnosticBuilder;
use hir::def_id::DefId;
use infer::canonical::{Canonical, CanonicalVarValues};
use middle::free_region::RegionRelations;
use middle::lang_items;
use middle::region;
@ -49,7 +50,6 @@ use self::region_constraints::{RegionConstraintCollector, RegionSnapshot};
use self::type_variable::TypeVariableOrigin;
use self::unify_key::ToType;
pub mod opaque_types;
pub mod at;
pub mod canonical;
mod combine;
@ -62,6 +62,7 @@ mod higher_ranked;
pub mod lattice;
mod lexical_region_resolve;
mod lub;
pub mod opaque_types;
pub mod outlives;
pub mod region_constraints;
pub mod resolve;
@ -86,7 +87,7 @@ pub type FixupResult<T> = Result<T, FixupError>; // "fixup result"
/// NLL borrow checker will also do -- it might be set to true.
#[derive(Copy, Clone, Default, Debug)]
pub struct SuppressRegionErrors {
suppressed: bool
suppressed: bool,
}
impl SuppressRegionErrors {
@ -100,15 +101,11 @@ impl SuppressRegionErrors {
pub fn when_nll_is_enabled(tcx: TyCtxt<'_, '_, '_>) -> Self {
match tcx.borrowck_mode() {
// If we're on AST or Migrate mode, report AST region errors
BorrowckMode::Ast | BorrowckMode::Migrate => SuppressRegionErrors {
suppressed: false
},
BorrowckMode::Ast | BorrowckMode::Migrate => SuppressRegionErrors { suppressed: false },
// If we're on MIR or Compare mode, don't report AST region errors as they should
// be reported by NLL
BorrowckMode::Compare | BorrowckMode::Mir => SuppressRegionErrors {
suppressed: true
},
BorrowckMode::Compare | BorrowckMode::Mir => SuppressRegionErrors { suppressed: true },
}
}
}
@ -494,10 +491,30 @@ impl<'a, 'gcx, 'tcx> InferCtxtBuilder<'a, 'gcx, 'tcx> {
self
}
pub fn enter<F, R>(&'tcx mut self, f: F) -> R
/// Given a canonical value `C` as a starting point, create an
/// inference context that contains each of the bound values
/// within instantiated as a fresh variable. The `f` closure is
/// invoked with the new infcx, along with the instantiated value
/// `V` and a substitution `S`. This substitution `S` maps from
/// the bound values in `C` to their instantiated values in `V`
/// (in other words, `S(C) = V`).
pub fn enter_with_canonical<T, R>(
&'tcx mut self,
span: Span,
canonical: &Canonical<'tcx, T>,
f: impl for<'b> FnOnce(InferCtxt<'b, 'gcx, 'tcx>, T, CanonicalVarValues<'tcx>) -> R,
) -> R
where
F: for<'b> FnOnce(InferCtxt<'b, 'gcx, 'tcx>) -> R,
T: TypeFoldable<'tcx>,
{
self.enter(|infcx| {
let (value, subst) =
infcx.instantiate_canonical_with_fresh_inference_vars(span, canonical);
f(infcx, value, subst)
})
}
pub fn enter<R>(&'tcx mut self, f: impl for<'b> FnOnce(InferCtxt<'b, 'gcx, 'tcx>) -> R) -> R {
let InferCtxtBuilder {
global_tcx,
ref arena,
@ -1472,13 +1489,10 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
self.universe.get()
}
/// Create and return a new subunivese of the current universe;
/// update `self.universe` to that new subuniverse. At present,
/// used only in the NLL subtyping code, which uses the new
/// universe-based scheme instead of the more limited leak-check
/// scheme.
pub fn create_subuniverse(&self) -> ty::UniverseIndex {
let u = self.universe.get().subuniverse();
/// Create and return a fresh universe that extends all previous
/// universes. Updates `self.universe` to that new universe.
pub fn create_next_universe(&self) -> ty::UniverseIndex {
let u = self.universe.get().next_universe();
self.universe.set(u);
u
}

View file

@ -10,7 +10,7 @@
use infer::at::At;
use infer::InferOk;
use smallvec::SmallVec;
use infer::canonical::OriginalQueryValues;
use std::iter::FromIterator;
use syntax::source_map::Span;
use ty::subst::Kind;
@ -51,14 +51,14 @@ impl<'cx, 'gcx, 'tcx> At<'cx, 'gcx, 'tcx> {
}
let gcx = tcx.global_tcx();
let mut orig_values = SmallVec::new();
let mut orig_values = OriginalQueryValues::default();
let c_ty = self.infcx.canonicalize_query(&self.param_env.and(ty), &mut orig_values);
let span = self.cause.span;
debug!("c_ty = {:?}", c_ty);
match &gcx.dropck_outlives(c_ty) {
Ok(result) if result.is_proven() => {
if let Ok(InferOk { value, obligations }) =
self.infcx.instantiate_query_result_and_region_obligations(
self.infcx.instantiate_query_response_and_region_obligations(
self.cause,
self.param_env,
&orig_values,

View file

@ -9,7 +9,7 @@
// except according to those terms.
use infer::InferCtxt;
use smallvec::SmallVec;
use infer::canonical::OriginalQueryValues;
use traits::{EvaluationResult, PredicateObligation, SelectionContext,
TraitQueryMode, OverflowError};
@ -38,7 +38,7 @@ impl<'cx, 'gcx, 'tcx> InferCtxt<'cx, 'gcx, 'tcx> {
&self,
obligation: &PredicateObligation<'tcx>,
) -> Result<EvaluationResult, OverflowError> {
let mut _orig_values = SmallVec::new();
let mut _orig_values = OriginalQueryValues::default();
let c_pred = self.canonicalize_query(&obligation.param_env.and(obligation.predicate),
&mut _orig_values);
// Run canonical query. If overflow occurs, rerun from scratch but this time

View file

@ -13,9 +13,9 @@
//! `normalize_projection_ty` query when it encounters projections.
use infer::at::At;
use infer::canonical::OriginalQueryValues;
use infer::{InferCtxt, InferOk};
use mir::interpret::{ConstValue, GlobalId};
use smallvec::SmallVec;
use traits::project::Normalized;
use traits::{Obligation, ObligationCause, PredicateObligation, Reveal};
use ty::fold::{TypeFoldable, TypeFolder};
@ -154,7 +154,7 @@ impl<'cx, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for QueryNormalizer<'cx, 'gcx, 'tcx
let gcx = self.infcx.tcx.global_tcx();
let mut orig_values = SmallVec::new();
let mut orig_values = OriginalQueryValues::default();
let c_data = self.infcx.canonicalize_query(
&self.param_env.and(*data), &mut orig_values);
debug!("QueryNormalizer: c_data = {:#?}", c_data);
@ -167,7 +167,7 @@ impl<'cx, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for QueryNormalizer<'cx, 'gcx, 'tcx
return ty;
}
match self.infcx.instantiate_query_result_and_region_obligations(
match self.infcx.instantiate_query_response_and_region_obligations(
self.cause,
self.param_env,
&orig_values,

View file

@ -9,9 +9,9 @@
// except according to those terms.
use infer::InferCtxt;
use infer::canonical::OriginalQueryValues;
use syntax::ast;
use syntax::source_map::Span;
use smallvec::SmallVec;
use traits::{FulfillmentContext, ObligationCause, TraitEngine, TraitEngineExt};
use traits::query::NoSolution;
use ty::{self, Ty, TyCtxt};
@ -105,7 +105,7 @@ impl<'cx, 'gcx, 'tcx> InferCtxt<'cx, 'gcx, 'tcx> {
) -> Vec<OutlivesBound<'tcx>> {
debug!("implied_outlives_bounds(ty = {:?})", ty);
let mut orig_values = SmallVec::new();
let mut orig_values = OriginalQueryValues::default();
let key = self.canonicalize_query(&param_env.and(ty), &mut orig_values);
let result = match self.tcx.global_tcx().implied_outlives_bounds(key) {
Ok(r) => r,
@ -119,7 +119,7 @@ impl<'cx, 'gcx, 'tcx> InferCtxt<'cx, 'gcx, 'tcx> {
};
assert!(result.value.is_proven());
let result = self.instantiate_query_result_and_region_obligations(
let result = self.instantiate_query_response_and_region_obligations(
&ObligationCause::misc(span, body_id), param_env, &orig_values, &result);
debug!("implied_outlives_bounds for {:?}: {:#?}", ty, result);
let result = match result {

View file

@ -12,7 +12,7 @@ use infer::{InferCtxt, InferOk};
use std::fmt;
use traits::query::Fallible;
use infer::canonical::query_result;
use infer::canonical::query_response;
use infer::canonical::QueryRegionConstraint;
use std::rc::Rc;
use syntax::source_map::DUMMY_SP;
@ -102,7 +102,7 @@ fn scrape_region_constraints<'gcx, 'tcx, R>(
let region_constraint_data = infcx.take_and_reset_region_constraints();
let outlives = query_result::make_query_outlives(
let outlives = query_response::make_query_outlives(
infcx.tcx,
region_obligations
.iter()

View file

@ -8,7 +8,7 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use infer::canonical::{Canonical, Canonicalized, CanonicalizedQueryResult, QueryResult};
use infer::canonical::{Canonical, Canonicalized, CanonicalizedQueryResponse, QueryResponse};
use traits::query::Fallible;
use ty::{ParamEnvAnd, Ty, TyCtxt};
@ -25,12 +25,12 @@ impl<'tcx> Eq<'tcx> {
}
impl<'gcx: 'tcx, 'tcx> super::QueryTypeOp<'gcx, 'tcx> for Eq<'tcx> {
type QueryResult = ();
type QueryResponse = ();
fn try_fast_path(
_tcx: TyCtxt<'_, 'gcx, 'tcx>,
key: &ParamEnvAnd<'tcx, Eq<'tcx>>,
) -> Option<Self::QueryResult> {
) -> Option<Self::QueryResponse> {
if key.value.a == key.value.b {
Some(())
} else {
@ -41,13 +41,13 @@ impl<'gcx: 'tcx, 'tcx> super::QueryTypeOp<'gcx, 'tcx> for Eq<'tcx> {
fn perform_query(
tcx: TyCtxt<'_, 'gcx, 'tcx>,
canonicalized: Canonicalized<'gcx, ParamEnvAnd<'tcx, Self>>,
) -> Fallible<CanonicalizedQueryResult<'gcx, ()>> {
) -> Fallible<CanonicalizedQueryResponse<'gcx, ()>> {
tcx.type_op_eq(canonicalized)
}
fn shrink_to_tcx_lifetime(
v: &'a CanonicalizedQueryResult<'gcx, ()>,
) -> &'a Canonical<'tcx, QueryResult<'tcx, ()>> {
v: &'a CanonicalizedQueryResponse<'gcx, ()>,
) -> &'a Canonical<'tcx, QueryResponse<'tcx, ()>> {
v
}
}

View file

@ -8,7 +8,7 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use infer::canonical::{Canonical, Canonicalized, CanonicalizedQueryResult, QueryResult};
use infer::canonical::{Canonical, Canonicalized, CanonicalizedQueryResponse, QueryResponse};
use traits::query::outlives_bounds::OutlivesBound;
use traits::query::Fallible;
use ty::{ParamEnvAnd, Ty, TyCtxt};
@ -25,19 +25,19 @@ impl<'tcx> ImpliedOutlivesBounds<'tcx> {
}
impl<'gcx: 'tcx, 'tcx> super::QueryTypeOp<'gcx, 'tcx> for ImpliedOutlivesBounds<'tcx> {
type QueryResult = Vec<OutlivesBound<'tcx>>;
type QueryResponse = Vec<OutlivesBound<'tcx>>;
fn try_fast_path(
_tcx: TyCtxt<'_, 'gcx, 'tcx>,
_key: &ParamEnvAnd<'tcx, Self>,
) -> Option<Self::QueryResult> {
) -> Option<Self::QueryResponse> {
None
}
fn perform_query(
tcx: TyCtxt<'_, 'gcx, 'tcx>,
canonicalized: Canonicalized<'gcx, ParamEnvAnd<'tcx, Self>>,
) -> Fallible<CanonicalizedQueryResult<'gcx, Self::QueryResult>> {
) -> Fallible<CanonicalizedQueryResponse<'gcx, Self::QueryResponse>> {
// FIXME the query should take a `ImpliedOutlivesBounds`
let Canonical {
variables,
@ -56,8 +56,8 @@ impl<'gcx: 'tcx, 'tcx> super::QueryTypeOp<'gcx, 'tcx> for ImpliedOutlivesBounds<
}
fn shrink_to_tcx_lifetime(
v: &'a CanonicalizedQueryResult<'gcx, Self::QueryResult>,
) -> &'a Canonical<'tcx, QueryResult<'tcx, Self::QueryResult>> {
v: &'a CanonicalizedQueryResponse<'gcx, Self::QueryResponse>,
) -> &'a Canonical<'tcx, QueryResponse<'tcx, Self::QueryResponse>> {
v
}
}

View file

@ -8,10 +8,11 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use infer::canonical::{Canonical, Canonicalized, CanonicalizedQueryResult, QueryRegionConstraint,
QueryResult};
use infer::canonical::{
Canonical, Canonicalized, CanonicalizedQueryResponse, OriginalQueryValues,
QueryRegionConstraint, QueryResponse,
};
use infer::{InferCtxt, InferOk};
use smallvec::SmallVec;
use std::fmt;
use std::rc::Rc;
use traits::query::Fallible;
@ -55,7 +56,7 @@ pub trait TypeOp<'gcx, 'tcx>: Sized + fmt::Debug {
pub trait QueryTypeOp<'gcx: 'tcx, 'tcx>:
fmt::Debug + Sized + TypeFoldable<'tcx> + Lift<'gcx>
{
type QueryResult: TypeFoldable<'tcx> + Lift<'gcx>;
type QueryResponse: TypeFoldable<'tcx> + Lift<'gcx>;
/// Give query the option for a simple fast path that never
/// actually hits the tcx cache lookup etc. Return `Some(r)` with
@ -63,7 +64,7 @@ pub trait QueryTypeOp<'gcx: 'tcx, 'tcx>:
fn try_fast_path(
tcx: TyCtxt<'_, 'gcx, 'tcx>,
key: &ParamEnvAnd<'tcx, Self>,
) -> Option<Self::QueryResult>;
) -> Option<Self::QueryResponse>;
/// Performs the actual query with the canonicalized key -- the
/// real work happens here. This method is not given an `infcx`
@ -74,29 +75,29 @@ pub trait QueryTypeOp<'gcx: 'tcx, 'tcx>:
fn perform_query(
tcx: TyCtxt<'_, 'gcx, 'tcx>,
canonicalized: Canonicalized<'gcx, ParamEnvAnd<'tcx, Self>>,
) -> Fallible<CanonicalizedQueryResult<'gcx, Self::QueryResult>>;
) -> Fallible<CanonicalizedQueryResponse<'gcx, Self::QueryResponse>>;
/// Casts a lifted query result (which is in the gcx lifetime)
/// into the tcx lifetime. This is always just an identity cast,
/// but the generic code doesn't realize it -- put another way, in
/// the generic code, we have a `Lifted<'gcx, Self::QueryResult>`
/// and we want to convert that to a `Self::QueryResult`. This is
/// the generic code, we have a `Lifted<'gcx, Self::QueryResponse>`
/// and we want to convert that to a `Self::QueryResponse`. This is
/// not a priori valid, so we can't do it -- but in practice, it
/// is always a no-op (e.g., the lifted form of a type,
/// `Ty<'gcx>`, is a subtype of `Ty<'tcx>`). So we have to push
/// the operation into the impls that know more specifically what
/// `QueryResult` is. This operation would (maybe) be nicer with
/// `QueryResponse` is. This operation would (maybe) be nicer with
/// something like HKTs or GATs, since then we could make
/// `QueryResult` parametric and `'gcx` and `'tcx` etc.
/// `QueryResponse` parametric and `'gcx` and `'tcx` etc.
fn shrink_to_tcx_lifetime(
lifted_query_result: &'a CanonicalizedQueryResult<'gcx, Self::QueryResult>,
) -> &'a Canonical<'tcx, QueryResult<'tcx, Self::QueryResult>>;
lifted_query_result: &'a CanonicalizedQueryResponse<'gcx, Self::QueryResponse>,
) -> &'a Canonical<'tcx, QueryResponse<'tcx, Self::QueryResponse>>;
fn fully_perform_into(
query_key: ParamEnvAnd<'tcx, Self>,
infcx: &InferCtxt<'_, 'gcx, 'tcx>,
output_query_region_constraints: &mut Vec<QueryRegionConstraint<'tcx>>,
) -> Fallible<Self::QueryResult> {
) -> Fallible<Self::QueryResponse> {
if let Some(result) = QueryTypeOp::try_fast_path(infcx.tcx, &query_key) {
return Ok(result);
}
@ -105,7 +106,7 @@ pub trait QueryTypeOp<'gcx: 'tcx, 'tcx>:
// `canonicalize_hr_query_hack` here because of things
// like the subtype query, which go awry around
// `'static` otherwise.
let mut canonical_var_values = SmallVec::new();
let mut canonical_var_values = OriginalQueryValues::default();
let canonical_self =
infcx.canonicalize_hr_query_hack(&query_key, &mut canonical_var_values);
let canonical_result = Self::perform_query(infcx.tcx, canonical_self)?;
@ -114,7 +115,7 @@ pub trait QueryTypeOp<'gcx: 'tcx, 'tcx>:
let param_env = query_key.param_env;
let InferOk { value, obligations } = infcx
.instantiate_nll_query_result_and_region_obligations(
.instantiate_nll_query_response_and_region_obligations(
&ObligationCause::dummy(),
param_env,
&canonical_var_values,
@ -145,7 +146,7 @@ impl<'gcx: 'tcx, 'tcx, Q> TypeOp<'gcx, 'tcx> for ParamEnvAnd<'tcx, Q>
where
Q: QueryTypeOp<'gcx, 'tcx>,
{
type Output = Q::QueryResult;
type Output = Q::QueryResponse;
fn fully_perform(
self,

View file

@ -8,7 +8,7 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use infer::canonical::{Canonical, Canonicalized, CanonicalizedQueryResult, QueryResult};
use infer::canonical::{Canonical, Canonicalized, CanonicalizedQueryResponse, QueryResponse};
use std::fmt;
use traits::query::Fallible;
use ty::fold::TypeFoldable;
@ -32,7 +32,7 @@ impl<'gcx: 'tcx, 'tcx, T> super::QueryTypeOp<'gcx, 'tcx> for Normalize<T>
where
T: Normalizable<'gcx, 'tcx>,
{
type QueryResult = T;
type QueryResponse = T;
fn try_fast_path(_tcx: TyCtxt<'_, 'gcx, 'tcx>, key: &ParamEnvAnd<'tcx, Self>) -> Option<T> {
if !key.value.value.has_projections() {
@ -45,13 +45,13 @@ where
fn perform_query(
tcx: TyCtxt<'_, 'gcx, 'tcx>,
canonicalized: Canonicalized<'gcx, ParamEnvAnd<'tcx, Self>>,
) -> Fallible<CanonicalizedQueryResult<'gcx, Self::QueryResult>> {
) -> Fallible<CanonicalizedQueryResponse<'gcx, Self::QueryResponse>> {
T::type_op_method(tcx, canonicalized)
}
fn shrink_to_tcx_lifetime(
v: &'a CanonicalizedQueryResult<'gcx, T>,
) -> &'a Canonical<'tcx, QueryResult<'tcx, T>> {
v: &'a CanonicalizedQueryResponse<'gcx, T>,
) -> &'a Canonical<'tcx, QueryResponse<'tcx, T>> {
T::shrink_to_tcx_lifetime(v)
}
}
@ -60,13 +60,13 @@ pub trait Normalizable<'gcx, 'tcx>: fmt::Debug + TypeFoldable<'tcx> + Lift<'gcx>
fn type_op_method(
tcx: TyCtxt<'_, 'gcx, 'tcx>,
canonicalized: Canonicalized<'gcx, ParamEnvAnd<'tcx, Normalize<Self>>>,
) -> Fallible<CanonicalizedQueryResult<'gcx, Self>>;
) -> Fallible<CanonicalizedQueryResponse<'gcx, Self>>;
/// Convert from the `'gcx` (lifted) form of `Self` into the `tcx`
/// form of `Self`.
fn shrink_to_tcx_lifetime(
v: &'a CanonicalizedQueryResult<'gcx, Self>,
) -> &'a Canonical<'tcx, QueryResult<'tcx, Self>>;
v: &'a CanonicalizedQueryResponse<'gcx, Self>,
) -> &'a Canonical<'tcx, QueryResponse<'tcx, Self>>;
}
impl Normalizable<'gcx, 'tcx> for Ty<'tcx>
@ -76,13 +76,13 @@ where
fn type_op_method(
tcx: TyCtxt<'_, 'gcx, 'tcx>,
canonicalized: Canonicalized<'gcx, ParamEnvAnd<'tcx, Normalize<Self>>>,
) -> Fallible<CanonicalizedQueryResult<'gcx, Self>> {
) -> Fallible<CanonicalizedQueryResponse<'gcx, Self>> {
tcx.type_op_normalize_ty(canonicalized)
}
fn shrink_to_tcx_lifetime(
v: &'a CanonicalizedQueryResult<'gcx, Self>,
) -> &'a Canonical<'tcx, QueryResult<'tcx, Self>> {
v: &'a CanonicalizedQueryResponse<'gcx, Self>,
) -> &'a Canonical<'tcx, QueryResponse<'tcx, Self>> {
v
}
}
@ -94,13 +94,13 @@ where
fn type_op_method(
tcx: TyCtxt<'_, 'gcx, 'tcx>,
canonicalized: Canonicalized<'gcx, ParamEnvAnd<'tcx, Normalize<Self>>>,
) -> Fallible<CanonicalizedQueryResult<'gcx, Self>> {
) -> Fallible<CanonicalizedQueryResponse<'gcx, Self>> {
tcx.type_op_normalize_predicate(canonicalized)
}
fn shrink_to_tcx_lifetime(
v: &'a CanonicalizedQueryResult<'gcx, Self>,
) -> &'a Canonical<'tcx, QueryResult<'tcx, Self>> {
v: &'a CanonicalizedQueryResponse<'gcx, Self>,
) -> &'a Canonical<'tcx, QueryResponse<'tcx, Self>> {
v
}
}
@ -112,13 +112,13 @@ where
fn type_op_method(
tcx: TyCtxt<'_, 'gcx, 'tcx>,
canonicalized: Canonicalized<'gcx, ParamEnvAnd<'tcx, Normalize<Self>>>,
) -> Fallible<CanonicalizedQueryResult<'gcx, Self>> {
) -> Fallible<CanonicalizedQueryResponse<'gcx, Self>> {
tcx.type_op_normalize_poly_fn_sig(canonicalized)
}
fn shrink_to_tcx_lifetime(
v: &'a CanonicalizedQueryResult<'gcx, Self>,
) -> &'a Canonical<'tcx, QueryResult<'tcx, Self>> {
v: &'a CanonicalizedQueryResponse<'gcx, Self>,
) -> &'a Canonical<'tcx, QueryResponse<'tcx, Self>> {
v
}
}
@ -130,13 +130,13 @@ where
fn type_op_method(
tcx: TyCtxt<'_, 'gcx, 'tcx>,
canonicalized: Canonicalized<'gcx, ParamEnvAnd<'tcx, Normalize<Self>>>,
) -> Fallible<CanonicalizedQueryResult<'gcx, Self>> {
) -> Fallible<CanonicalizedQueryResponse<'gcx, Self>> {
tcx.type_op_normalize_fn_sig(canonicalized)
}
fn shrink_to_tcx_lifetime(
v: &'a CanonicalizedQueryResult<'gcx, Self>,
) -> &'a Canonical<'tcx, QueryResult<'tcx, Self>> {
v: &'a CanonicalizedQueryResponse<'gcx, Self>,
) -> &'a Canonical<'tcx, QueryResponse<'tcx, Self>> {
v
}
}

View file

@ -8,7 +8,7 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use infer::canonical::{Canonical, Canonicalized, CanonicalizedQueryResult, QueryResult};
use infer::canonical::{Canonical, Canonicalized, CanonicalizedQueryResponse, QueryResponse};
use traits::query::dropck_outlives::trivial_dropck_outlives;
use traits::query::dropck_outlives::DropckOutlivesResult;
use traits::query::Fallible;
@ -29,12 +29,12 @@ impl super::QueryTypeOp<'gcx, 'tcx> for DropckOutlives<'tcx>
where
'gcx: 'tcx,
{
type QueryResult = DropckOutlivesResult<'tcx>;
type QueryResponse = DropckOutlivesResult<'tcx>;
fn try_fast_path(
tcx: TyCtxt<'_, 'gcx, 'tcx>,
key: &ParamEnvAnd<'tcx, Self>,
) -> Option<Self::QueryResult> {
) -> Option<Self::QueryResponse> {
if trivial_dropck_outlives(tcx, key.value.dropped_ty) {
Some(DropckOutlivesResult::default())
} else {
@ -45,7 +45,7 @@ where
fn perform_query(
tcx: TyCtxt<'_, 'gcx, 'tcx>,
canonicalized: Canonicalized<'gcx, ParamEnvAnd<'tcx, Self>>,
) -> Fallible<CanonicalizedQueryResult<'gcx, Self::QueryResult>> {
) -> Fallible<CanonicalizedQueryResponse<'gcx, Self::QueryResponse>> {
// Subtle: note that we are not invoking
// `infcx.at(...).dropck_outlives(...)` here, but rather the
// underlying `dropck_outlives` query. This same underlying
@ -76,8 +76,8 @@ where
}
fn shrink_to_tcx_lifetime(
lifted_query_result: &'a CanonicalizedQueryResult<'gcx, Self::QueryResult>,
) -> &'a Canonical<'tcx, QueryResult<'tcx, Self::QueryResult>> {
lifted_query_result: &'a CanonicalizedQueryResponse<'gcx, Self::QueryResponse>,
) -> &'a Canonical<'tcx, QueryResponse<'tcx, Self::QueryResponse>> {
lifted_query_result
}
}

View file

@ -8,7 +8,7 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use infer::canonical::{Canonical, Canonicalized, CanonicalizedQueryResult, QueryResult};
use infer::canonical::{Canonical, Canonicalized, CanonicalizedQueryResponse, QueryResponse};
use traits::query::Fallible;
use ty::{ParamEnvAnd, Predicate, TyCtxt};
@ -24,12 +24,12 @@ impl<'tcx> ProvePredicate<'tcx> {
}
impl<'gcx: 'tcx, 'tcx> super::QueryTypeOp<'gcx, 'tcx> for ProvePredicate<'tcx> {
type QueryResult = ();
type QueryResponse = ();
fn try_fast_path(
tcx: TyCtxt<'_, 'gcx, 'tcx>,
key: &ParamEnvAnd<'tcx, Self>,
) -> Option<Self::QueryResult> {
) -> Option<Self::QueryResponse> {
// Proving Sized, very often on "obviously sized" types like
// `&T`, accounts for about 60% percentage of the predicates
// we have to prove. No need to canonicalize and all that for
@ -50,13 +50,13 @@ impl<'gcx: 'tcx, 'tcx> super::QueryTypeOp<'gcx, 'tcx> for ProvePredicate<'tcx> {
fn perform_query(
tcx: TyCtxt<'_, 'gcx, 'tcx>,
canonicalized: Canonicalized<'gcx, ParamEnvAnd<'tcx, Self>>,
) -> Fallible<CanonicalizedQueryResult<'gcx, ()>> {
) -> Fallible<CanonicalizedQueryResponse<'gcx, ()>> {
tcx.type_op_prove_predicate(canonicalized)
}
fn shrink_to_tcx_lifetime(
v: &'a CanonicalizedQueryResult<'gcx, ()>,
) -> &'a Canonical<'tcx, QueryResult<'tcx, ()>> {
v: &'a CanonicalizedQueryResponse<'gcx, ()>,
) -> &'a Canonical<'tcx, QueryResponse<'tcx, ()>> {
v
}
}

View file

@ -8,7 +8,7 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use infer::canonical::{Canonical, Canonicalized, CanonicalizedQueryResult, QueryResult};
use infer::canonical::{Canonical, Canonicalized, CanonicalizedQueryResponse, QueryResponse};
use traits::query::Fallible;
use ty::{ParamEnvAnd, Ty, TyCtxt};
@ -28,7 +28,7 @@ impl<'tcx> Subtype<'tcx> {
}
impl<'gcx: 'tcx, 'tcx> super::QueryTypeOp<'gcx, 'tcx> for Subtype<'tcx> {
type QueryResult = ();
type QueryResponse = ();
fn try_fast_path(_tcx: TyCtxt<'_, 'gcx, 'tcx>, key: &ParamEnvAnd<'tcx, Self>) -> Option<()> {
if key.value.sub == key.value.sup {
@ -41,13 +41,13 @@ impl<'gcx: 'tcx, 'tcx> super::QueryTypeOp<'gcx, 'tcx> for Subtype<'tcx> {
fn perform_query(
tcx: TyCtxt<'_, 'gcx, 'tcx>,
canonicalized: Canonicalized<'gcx, ParamEnvAnd<'tcx, Self>>,
) -> Fallible<CanonicalizedQueryResult<'gcx, ()>> {
) -> Fallible<CanonicalizedQueryResponse<'gcx, ()>> {
tcx.type_op_subtype(canonicalized)
}
fn shrink_to_tcx_lifetime(
v: &'a CanonicalizedQueryResult<'gcx, ()>,
) -> &'a Canonical<'tcx, QueryResult<'tcx, ()>> {
v: &'a CanonicalizedQueryResponse<'gcx, ()>,
) -> &'a Canonical<'tcx, QueryResponse<'tcx, ()>> {
v
}
}

View file

@ -57,6 +57,7 @@ use syntax::symbol::{keywords, Symbol, LocalInternedString, InternedString};
use syntax_pos::{DUMMY_SP, Span};
use smallvec;
use rustc_data_structures::indexed_vec::Idx;
use rustc_data_structures::stable_hasher::{StableHasher, StableHasherResult,
HashStable};
@ -1456,10 +1457,10 @@ impl<'tcx> InstantiatedPredicates<'tcx> {
/// "Universes" are used during type- and trait-checking in the
/// presence of `for<..>` binders to control what sets of names are
/// visible. Universes are arranged into a tree: the root universe
/// contains names that are always visible. But when you enter into
/// some subuniverse, then it may add names that are only visible
/// within that subtree (but it can still name the names of its
/// ancestor universes).
/// contains names that are always visible. Each child then adds a new
/// set of names that are visible, in addition to those of its parent.
/// We say that the child universe "extends" the parent universe with
/// new names.
///
/// To make this more concrete, consider this program:
///
@ -1471,11 +1472,11 @@ impl<'tcx> InstantiatedPredicates<'tcx> {
/// ```
///
/// The struct name `Foo` is in the root universe U0. But the type
/// parameter `T`, introduced on `bar`, is in a subuniverse U1 --
/// i.e., within `bar`, we can name both `T` and `Foo`, but outside of
/// `bar`, we cannot name `T`. Then, within the type of `y`, the
/// region `'a` is in a subuniverse U2 of U1, because we can name it
/// inside the fn type but not outside.
/// parameter `T`, introduced on `bar`, is in an extended universe U1
/// -- i.e., within `bar`, we can name both `T` and `Foo`, but outside
/// of `bar`, we cannot name `T`. Then, within the type of `y`, the
/// region `'a` is in a universe U2 that extends U1, because we can
/// name it inside the fn type but not outside.
///
/// Universes are used to do type- and trait-checking around these
/// "forall" binders (also called **universal quantification**). The
@ -1488,65 +1489,39 @@ impl<'tcx> InstantiatedPredicates<'tcx> {
/// declared, but a type name in a non-zero universe is a placeholder
/// type -- an idealized representative of "types in general" that we
/// use for checking generic functions.
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable)]
pub struct UniverseIndex(u32);
newtype_index! {
pub struct UniverseIndex {
DEBUG_FORMAT = "U{}",
}
}
impl_stable_hash_for!(struct UniverseIndex { private });
impl UniverseIndex {
/// The root universe, where things that the user defined are
/// visible.
pub const ROOT: Self = UniverseIndex(0);
pub const ROOT: UniverseIndex = UniverseIndex::from_u32_const(0);
/// The "max universe" -- this isn't really a valid universe, but
/// it's useful sometimes as a "starting value" when you are
/// taking the minimum of a (non-empty!) set of universes.
pub const MAX: Self = UniverseIndex(::std::u32::MAX);
/// Creates a universe index from the given integer. Not to be
/// used lightly lest you pick a bad value. But sometimes we
/// convert universe indices into integers and back for various
/// reasons.
pub fn from_u32(index: u32) -> Self {
UniverseIndex(index)
}
/// A "subuniverse" corresponds to being inside a `forall` quantifier.
/// So, for example, suppose we have this type in universe `U`:
/// Returns the "next" universe index in order -- this new index
/// is considered to extend all previous universes. This
/// corresponds to entering a `forall` quantifier. So, for
/// example, suppose we have this type in universe `U`:
///
/// ```
/// for<'a> fn(&'a u32)
/// ```
///
/// Once we "enter" into this `for<'a>` quantifier, we are in a
/// subuniverse of `U` -- in this new universe, we can name the
/// region `'a`, but that region was not nameable from `U` because
/// it was not in scope there.
pub fn subuniverse(self) -> UniverseIndex {
UniverseIndex(self.0.checked_add(1).unwrap())
/// new universe that extends `U` -- in this new universe, we can
/// name the region `'a`, but that region was not nameable from
/// `U` because it was not in scope there.
pub fn next_universe(self) -> UniverseIndex {
UniverseIndex::from_u32(self.private.checked_add(1).unwrap())
}
/// True if the names in this universe are a subset of the names in `other`.
pub fn is_subset_of(self, other: UniverseIndex) -> bool {
self.0 <= other.0
}
pub fn as_u32(&self) -> u32 {
self.0
}
pub fn as_usize(&self) -> usize {
self.0 as usize
}
}
impl fmt::Debug for UniverseIndex {
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(fmt, "U{}", self.as_u32())
}
}
impl From<u32> for UniverseIndex {
fn from(index: u32) -> Self {
UniverseIndex(index)
/// True if `self` can name a name from `other` -- in other words,
/// if the set of names in `self` is a superset of those in
/// `other`.
pub fn can_name(self, other: UniverseIndex) -> bool {
self.private >= other.private
}
}

View file

@ -559,7 +559,7 @@ define_queries! { <'tcx>
[] fn normalize_projection_ty: NormalizeProjectionTy(
CanonicalProjectionGoal<'tcx>
) -> Result<
Lrc<Canonical<'tcx, canonical::QueryResult<'tcx, NormalizationResult<'tcx>>>>,
Lrc<Canonical<'tcx, canonical::QueryResponse<'tcx, NormalizationResult<'tcx>>>>,
NoSolution,
>,
@ -571,7 +571,7 @@ define_queries! { <'tcx>
[] fn implied_outlives_bounds: ImpliedOutlivesBounds(
CanonicalTyGoal<'tcx>
) -> Result<
Lrc<Canonical<'tcx, canonical::QueryResult<'tcx, Vec<OutlivesBound<'tcx>>>>>,
Lrc<Canonical<'tcx, canonical::QueryResponse<'tcx, Vec<OutlivesBound<'tcx>>>>>,
NoSolution,
>,
@ -579,7 +579,7 @@ define_queries! { <'tcx>
[] fn dropck_outlives: DropckOutlives(
CanonicalTyGoal<'tcx>
) -> Result<
Lrc<Canonical<'tcx, canonical::QueryResult<'tcx, DropckOutlivesResult<'tcx>>>>,
Lrc<Canonical<'tcx, canonical::QueryResponse<'tcx, DropckOutlivesResult<'tcx>>>>,
NoSolution,
>,
@ -593,7 +593,7 @@ define_queries! { <'tcx>
[] fn type_op_eq: TypeOpEq(
CanonicalTypeOpEqGoal<'tcx>
) -> Result<
Lrc<Canonical<'tcx, canonical::QueryResult<'tcx, ()>>>,
Lrc<Canonical<'tcx, canonical::QueryResponse<'tcx, ()>>>,
NoSolution,
>,
@ -601,7 +601,7 @@ define_queries! { <'tcx>
[] fn type_op_subtype: TypeOpSubtype(
CanonicalTypeOpSubtypeGoal<'tcx>
) -> Result<
Lrc<Canonical<'tcx, canonical::QueryResult<'tcx, ()>>>,
Lrc<Canonical<'tcx, canonical::QueryResponse<'tcx, ()>>>,
NoSolution,
>,
@ -609,7 +609,7 @@ define_queries! { <'tcx>
[] fn type_op_prove_predicate: TypeOpProvePredicate(
CanonicalTypeOpProvePredicateGoal<'tcx>
) -> Result<
Lrc<Canonical<'tcx, canonical::QueryResult<'tcx, ()>>>,
Lrc<Canonical<'tcx, canonical::QueryResponse<'tcx, ()>>>,
NoSolution,
>,
@ -617,7 +617,7 @@ define_queries! { <'tcx>
[] fn type_op_normalize_ty: TypeOpNormalizeTy(
CanonicalTypeOpNormalizeGoal<'tcx, Ty<'tcx>>
) -> Result<
Lrc<Canonical<'tcx, canonical::QueryResult<'tcx, Ty<'tcx>>>>,
Lrc<Canonical<'tcx, canonical::QueryResponse<'tcx, Ty<'tcx>>>>,
NoSolution,
>,
@ -625,7 +625,7 @@ define_queries! { <'tcx>
[] fn type_op_normalize_predicate: TypeOpNormalizePredicate(
CanonicalTypeOpNormalizeGoal<'tcx, ty::Predicate<'tcx>>
) -> Result<
Lrc<Canonical<'tcx, canonical::QueryResult<'tcx, ty::Predicate<'tcx>>>>,
Lrc<Canonical<'tcx, canonical::QueryResponse<'tcx, ty::Predicate<'tcx>>>>,
NoSolution,
>,
@ -633,7 +633,7 @@ define_queries! { <'tcx>
[] fn type_op_normalize_poly_fn_sig: TypeOpNormalizePolyFnSig(
CanonicalTypeOpNormalizeGoal<'tcx, ty::PolyFnSig<'tcx>>
) -> Result<
Lrc<Canonical<'tcx, canonical::QueryResult<'tcx, ty::PolyFnSig<'tcx>>>>,
Lrc<Canonical<'tcx, canonical::QueryResponse<'tcx, ty::PolyFnSig<'tcx>>>>,
NoSolution,
>,
@ -641,7 +641,7 @@ define_queries! { <'tcx>
[] fn type_op_normalize_fn_sig: TypeOpNormalizeFnSig(
CanonicalTypeOpNormalizeGoal<'tcx, ty::FnSig<'tcx>>
) -> Result<
Lrc<Canonical<'tcx, canonical::QueryResult<'tcx, ty::FnSig<'tcx>>>>,
Lrc<Canonical<'tcx, canonical::QueryResponse<'tcx, ty::FnSig<'tcx>>>>,
NoSolution,
>,

View file

@ -57,6 +57,7 @@ CloneTypeFoldableAndLiftImpls! {
::ty::ClosureKind,
::ty::IntVarValue,
::ty::ParamTy,
::ty::UniverseIndex,
::ty::Variance,
::syntax_pos::Span,
}

View file

@ -112,7 +112,7 @@ struct RegionDefinition<'tcx> {
/// Which universe is this region variable defined in? This is
/// most often `ty::UniverseIndex::ROOT`, but when we encounter
/// forall-quantifiers like `for<'a> { 'a = 'b }`, we would create
/// the variable for `'a` in a subuniverse.
/// the variable for `'a` in a fresh universe that extends ROOT.
universe: ty::UniverseIndex,
/// If this is 'static or an early-bound region, then this is
@ -339,11 +339,11 @@ impl<'tcx> RegionInferenceContext<'tcx> {
NLLRegionVariableOrigin::Placeholder(placeholder) => {
// Each placeholder region is only visible from
// its universe `ui` and its superuniverses. So we
// its universe `ui` and its extensions. So we
// can't just add it into `scc` unless the
// universe of the scc can name this region.
let scc_universe = self.scc_universes[scc];
if placeholder.universe.is_subset_of(scc_universe) {
if scc_universe.can_name(placeholder.universe) {
self.scc_values.add_element(scc, placeholder);
} else {
self.add_incompatible_universe(scc);
@ -541,7 +541,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
// Quick check: if scc_b's declared universe is a subset of
// scc_a's declared univese (typically, both are ROOT), then
// it cannot contain any problematic universe elements.
if self.scc_universes[scc_b].is_subset_of(universe_a) {
if universe_a.can_name(self.scc_universes[scc_b]) {
return true;
}
@ -550,7 +550,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
// from universe_a
self.scc_values
.placeholders_contained_in(scc_b)
.all(|p| p.universe.is_subset_of(universe_a))
.all(|p| universe_a.can_name(p.universe))
}
/// Extend `scc` so that it can outlive some placeholder region

View file

@ -148,8 +148,8 @@ crate enum RegionElement {
/// a lifetime parameter).
RootUniversalRegion(RegionVid),
/// A subuniverse from a subuniverse (e.g., instantiated from a
/// `for<'a> fn(&'a u32)` type).
/// A placeholder (e.g., instantiated from a `for<'a> fn(&'a u32)`
/// type).
PlaceholderRegion(ty::Placeholder),
}
@ -252,19 +252,6 @@ impl PlaceholderIndices {
}
}
impl ::std::iter::FromIterator<ty::Placeholder> for PlaceholderIndices {
fn from_iter<I>(iter: I) -> Self
where
I: IntoIterator<Item = ty::Placeholder>,
{
let mut result = Self::default();
iter.into_iter().for_each(|p| {
result.insert(p);
});
result
}
}
/// Stores the full values for a set of regions (in contrast to
/// `LivenessValues`, which only stores those points in the where a
/// region is live). The full value for a region may contain points in

View file

@ -159,7 +159,7 @@ trait TypeRelatingDelegate<'tcx> {
fn push_outlives(&mut self, sup: ty::Region<'tcx>, sub: ty::Region<'tcx>);
/// Creates a new universe index. Used when instantiating placeholders.
fn next_subuniverse(&mut self) -> ty::UniverseIndex;
fn create_next_universe(&mut self) -> ty::UniverseIndex;
/// Creates a new region variable representing a higher-ranked
/// region that is instantiated existentially. This creates an
@ -218,8 +218,8 @@ impl NllTypeRelatingDelegate<'me, 'bccx, 'gcx, 'tcx> {
}
impl TypeRelatingDelegate<'tcx> for NllTypeRelatingDelegate<'_, '_, '_, 'tcx> {
fn next_subuniverse(&mut self) -> ty::UniverseIndex {
self.infcx.create_subuniverse()
fn create_next_universe(&mut self) -> ty::UniverseIndex {
self.infcx.create_next_universe()
}
fn next_existential_region_var(&mut self) -> ty::Region<'tcx> {
@ -324,7 +324,7 @@ where
// new universe for the placeholders we will make
// from here out.
let universe = lazy_universe.unwrap_or_else(|| {
let universe = delegate.next_subuniverse();
let universe = delegate.create_next_universe();
lazy_universe = Some(universe);
universe
});

View file

@ -10,7 +10,9 @@
use chalk_engine::fallible::Fallible as ChalkEngineFallible;
use chalk_engine::{context, hh::HhGoal, DelayedLiteral, ExClause};
use rustc::infer::canonical::{Canonical, CanonicalVarValues, QueryRegionConstraint, QueryResult};
use rustc::infer::canonical::{
Canonical, CanonicalVarValues, OriginalQueryValues, QueryRegionConstraint, QueryResponse,
};
use rustc::infer::{InferCtxt, InferOk, LateBoundRegionConversionTime};
use rustc::traits::{
WellFormed,
@ -26,7 +28,6 @@ use rustc::traits::{
use rustc::ty::fold::{TypeFoldable, TypeFolder, TypeVisitor};
use rustc::ty::subst::Kind;
use rustc::ty::{self, TyCtxt};
use smallvec::SmallVec;
use std::fmt::{self, Debug};
use std::marker::PhantomData;
@ -77,7 +78,7 @@ impl context::Context for ChalkArenas<'tcx> {
// u-canonicalization not yet implemented
type UniverseMap = UniverseMap;
type Solution = Canonical<'tcx, QueryResult<'tcx, ()>>;
type Solution = Canonical<'tcx, QueryResponse<'tcx, ()>>;
type InferenceNormalizedSubst = CanonicalVarValues<'tcx>;
@ -116,7 +117,7 @@ impl context::AggregateOps<ChalkArenas<'gcx>> for ChalkContext<'cx, 'gcx> {
&self,
_root_goal: &Canonical<'gcx, ty::ParamEnvAnd<'gcx, Goal<'gcx>>>,
_simplified_answers: impl context::AnswerStream<ChalkArenas<'gcx>>,
) -> Option<Canonical<'gcx, QueryResult<'gcx, ()>>> {
) -> Option<Canonical<'gcx, QueryResponse<'gcx, ()>>> {
unimplemented!()
}
}
@ -390,7 +391,7 @@ impl context::UnificationOps<ChalkArenas<'gcx>, ChalkArenas<'tcx>>
&mut self,
value: &ty::ParamEnvAnd<'tcx, Goal<'tcx>>,
) -> Canonical<'gcx, ty::ParamEnvAnd<'gcx, Goal<'gcx>>> {
let mut _orig_values = SmallVec::new();
let mut _orig_values = OriginalQueryValues::default();
self.infcx.canonicalize_query(value, &mut _orig_values)
}

View file

@ -9,7 +9,7 @@
// except according to those terms.
use rustc::hir::def_id::DefId;
use rustc::infer::canonical::{Canonical, QueryResult};
use rustc::infer::canonical::{Canonical, QueryResponse};
use rustc::traits::query::dropck_outlives::{DropckOutlivesResult, DtorckConstraint};
use rustc::traits::query::{CanonicalTyGoal, NoSolution};
use rustc::traits::{FulfillmentContext, Normalized, ObligationCause, TraitEngineExt};
@ -30,124 +30,125 @@ crate fn provide(p: &mut Providers) {
fn dropck_outlives<'tcx>(
tcx: TyCtxt<'_, 'tcx, 'tcx>,
goal: CanonicalTyGoal<'tcx>,
) -> Result<Lrc<Canonical<'tcx, QueryResult<'tcx, DropckOutlivesResult<'tcx>>>>, NoSolution> {
debug!("dropck_outlives(goal={:#?})", goal);
canonical_goal: CanonicalTyGoal<'tcx>,
) -> Result<Lrc<Canonical<'tcx, QueryResponse<'tcx, DropckOutlivesResult<'tcx>>>>, NoSolution> {
debug!("dropck_outlives(goal={:#?})", canonical_goal);
tcx.infer_ctxt().enter(|ref infcx| {
let tcx = infcx.tcx;
let (
ParamEnvAnd {
tcx.infer_ctxt().enter_with_canonical(
DUMMY_SP,
&canonical_goal,
|ref infcx, goal, canonical_inference_vars| {
let tcx = infcx.tcx;
let ParamEnvAnd {
param_env,
value: for_ty,
},
canonical_inference_vars,
) = infcx.instantiate_canonical_with_fresh_inference_vars(DUMMY_SP, &goal);
} = goal;
let mut result = DropckOutlivesResult {
kinds: vec![],
overflows: vec![],
};
let mut result = DropckOutlivesResult {
kinds: vec![],
overflows: vec![],
};
// A stack of types left to process. Each round, we pop
// something from the stack and invoke
// `dtorck_constraint_for_ty`. This may produce new types that
// have to be pushed on the stack. This continues until we have explored
// all the reachable types from the type `for_ty`.
//
// Example: Imagine that we have the following code:
//
// ```rust
// struct A {
// value: B,
// children: Vec<A>,
// }
//
// struct B {
// value: u32
// }
//
// fn f() {
// let a: A = ...;
// ..
// } // here, `a` is dropped
// ```
//
// at the point where `a` is dropped, we need to figure out
// which types inside of `a` contain region data that may be
// accessed by any destructors in `a`. We begin by pushing `A`
// onto the stack, as that is the type of `a`. We will then
// invoke `dtorck_constraint_for_ty` which will expand `A`
// into the types of its fields `(B, Vec<A>)`. These will get
// pushed onto the stack. Eventually, expanding `Vec<A>` will
// lead to us trying to push `A` a second time -- to prevent
// infinite recursion, we notice that `A` was already pushed
// once and stop.
let mut ty_stack = vec![(for_ty, 0)];
// A stack of types left to process. Each round, we pop
// something from the stack and invoke
// `dtorck_constraint_for_ty`. This may produce new types that
// have to be pushed on the stack. This continues until we have explored
// all the reachable types from the type `for_ty`.
//
// Example: Imagine that we have the following code:
//
// ```rust
// struct A {
// value: B,
// children: Vec<A>,
// }
//
// struct B {
// value: u32
// }
//
// fn f() {
// let a: A = ...;
// ..
// } // here, `a` is dropped
// ```
//
// at the point where `a` is dropped, we need to figure out
// which types inside of `a` contain region data that may be
// accessed by any destructors in `a`. We begin by pushing `A`
// onto the stack, as that is the type of `a`. We will then
// invoke `dtorck_constraint_for_ty` which will expand `A`
// into the types of its fields `(B, Vec<A>)`. These will get
// pushed onto the stack. Eventually, expanding `Vec<A>` will
// lead to us trying to push `A` a second time -- to prevent
// infinite recursion, we notice that `A` was already pushed
// once and stop.
let mut ty_stack = vec![(for_ty, 0)];
// Set used to detect infinite recursion.
let mut ty_set = FxHashSet();
// Set used to detect infinite recursion.
let mut ty_set = FxHashSet();
let fulfill_cx = &mut FulfillmentContext::new();
let fulfill_cx = &mut FulfillmentContext::new();
let cause = ObligationCause::dummy();
while let Some((ty, depth)) = ty_stack.pop() {
let DtorckConstraint {
dtorck_types,
outlives,
overflows,
} = dtorck_constraint_for_ty(tcx, DUMMY_SP, for_ty, depth, ty)?;
let cause = ObligationCause::dummy();
while let Some((ty, depth)) = ty_stack.pop() {
let DtorckConstraint {
dtorck_types,
outlives,
overflows,
} = dtorck_constraint_for_ty(tcx, DUMMY_SP, for_ty, depth, ty)?;
// "outlives" represent types/regions that may be touched
// by a destructor.
result.kinds.extend(outlives);
result.overflows.extend(overflows);
// "outlives" represent types/regions that may be touched
// by a destructor.
result.kinds.extend(outlives);
result.overflows.extend(overflows);
// dtorck types are "types that will get dropped but which
// do not themselves define a destructor", more or less. We have
// to push them onto the stack to be expanded.
for ty in dtorck_types {
match infcx.at(&cause, param_env).normalize(&ty) {
Ok(Normalized {
value: ty,
obligations,
}) => {
fulfill_cx.register_predicate_obligations(infcx, obligations);
// dtorck types are "types that will get dropped but which
// do not themselves define a destructor", more or less. We have
// to push them onto the stack to be expanded.
for ty in dtorck_types {
match infcx.at(&cause, param_env).normalize(&ty) {
Ok(Normalized {
value: ty,
obligations,
}) => {
fulfill_cx.register_predicate_obligations(infcx, obligations);
debug!("dropck_outlives: ty from dtorck_types = {:?}", ty);
debug!("dropck_outlives: ty from dtorck_types = {:?}", ty);
match ty.sty {
// All parameters live for the duration of the
// function.
ty::Param(..) => {}
match ty.sty {
// All parameters live for the duration of the
// function.
ty::Param(..) => {}
// A projection that we couldn't resolve - it
// might have a destructor.
ty::Projection(..) | ty::Opaque(..) => {
result.kinds.push(ty.into());
}
// A projection that we couldn't resolve - it
// might have a destructor.
ty::Projection(..) | ty::Opaque(..) => {
result.kinds.push(ty.into());
}
_ => {
if ty_set.insert(ty) {
ty_stack.push((ty, depth + 1));
_ => {
if ty_set.insert(ty) {
ty_stack.push((ty, depth + 1));
}
}
}
}
}
// We don't actually expect to fail to normalize.
// That implies a WF error somewhere else.
Err(NoSolution) => {
return Err(NoSolution);
// We don't actually expect to fail to normalize.
// That implies a WF error somewhere else.
Err(NoSolution) => {
return Err(NoSolution);
}
}
}
}
}
debug!("dropck_outlives: result = {:#?}", result);
debug!("dropck_outlives: result = {:#?}", result);
infcx.make_canonicalized_query_result(canonical_inference_vars, result, fulfill_cx)
})
infcx.make_canonicalized_query_response(canonical_inference_vars, result, fulfill_cx)
},
)
}
/// Return a set of constraints that needs to be satisfied in
@ -195,8 +196,7 @@ fn dtorck_constraint_for_ty<'a, 'gcx, 'tcx>(
dtorck_constraint_for_ty(tcx, span, for_ty, depth + 1, ety)
}
ty::Tuple(tys) => tys
.iter()
ty::Tuple(tys) => tys.iter()
.map(|ty| dtorck_constraint_for_ty(tcx, span, for_ty, depth + 1, ty))
.collect(),
@ -308,8 +308,7 @@ crate fn adt_dtorck_constraint<'a, 'tcx>(
return Ok(result);
}
let mut result = def
.all_fields()
let mut result = def.all_fields()
.map(|field| tcx.type_of(field.did))
.map(|fty| dtorck_constraint_for_ty(tcx, span, fty, 0, fty))
.collect::<Result<DtorckConstraint, NoSolution>>()?;

View file

@ -8,9 +8,10 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use rustc::traits::{EvaluationResult, Obligation, ObligationCause,
OverflowError, SelectionContext, TraitQueryMode};
use rustc::traits::query::CanonicalPredicateGoal;
use rustc::traits::{
EvaluationResult, Obligation, ObligationCause, OverflowError, SelectionContext, TraitQueryMode,
};
use rustc::ty::query::Providers;
use rustc::ty::{ParamEnvAnd, TyCtxt};
use syntax::source_map::DUMMY_SP;
@ -24,20 +25,21 @@ crate fn provide(p: &mut Providers) {
fn evaluate_obligation<'tcx>(
tcx: TyCtxt<'_, 'tcx, 'tcx>,
goal: CanonicalPredicateGoal<'tcx>,
canonical_goal: CanonicalPredicateGoal<'tcx>,
) -> Result<EvaluationResult, OverflowError> {
tcx.infer_ctxt().enter(|ref infcx| {
let (
ParamEnvAnd {
tcx.infer_ctxt().enter_with_canonical(
DUMMY_SP,
&canonical_goal,
|ref infcx, goal, _canonical_inference_vars| {
let ParamEnvAnd {
param_env,
value: predicate,
},
_canonical_inference_vars,
) = infcx.instantiate_canonical_with_fresh_inference_vars(DUMMY_SP, &goal);
} = goal;
let mut selcx = SelectionContext::with_query_mode(&infcx, TraitQueryMode::Canonical);
let obligation = Obligation::new(ObligationCause::dummy(), param_env, predicate);
let mut selcx = SelectionContext::with_query_mode(&infcx, TraitQueryMode::Canonical);
let obligation = Obligation::new(ObligationCause::dummy(), param_env, predicate);
selcx.evaluate_obligation_recursively(&obligation)
})
selcx.evaluate_obligation_recursively(&obligation)
},
)
}

View file

@ -37,7 +37,7 @@ fn implied_outlives_bounds<'tcx>(
tcx: TyCtxt<'_, 'tcx, 'tcx>,
goal: CanonicalTyGoal<'tcx>,
) -> Result<
Lrc<Canonical<'tcx, canonical::QueryResult<'tcx, Vec<OutlivesBound<'tcx>>>>>,
Lrc<Canonical<'tcx, canonical::QueryResponse<'tcx, Vec<OutlivesBound<'tcx>>>>>,
NoSolution,
> {
tcx.infer_ctxt()

View file

@ -8,7 +8,7 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use rustc::infer::canonical::{Canonical, QueryResult};
use rustc::infer::canonical::{Canonical, QueryResponse};
use rustc::traits::query::{normalize::NormalizationResult, CanonicalProjectionGoal, NoSolution};
use rustc::traits::{self, ObligationCause, SelectionContext, TraitEngineExt};
use rustc::ty::query::Providers;
@ -28,7 +28,7 @@ crate fn provide(p: &mut Providers) {
fn normalize_projection_ty<'tcx>(
tcx: TyCtxt<'_, 'tcx, 'tcx>,
goal: CanonicalProjectionGoal<'tcx>,
) -> Result<Lrc<Canonical<'tcx, QueryResult<'tcx, NormalizationResult<'tcx>>>>, NoSolution> {
) -> Result<Lrc<Canonical<'tcx, QueryResponse<'tcx, NormalizationResult<'tcx>>>>, NoSolution> {
debug!("normalize_provider(goal={:#?})", goal);
tcx.sess

View file

@ -8,7 +8,7 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use rustc::infer::canonical::{Canonical, QueryResult};
use rustc::infer::canonical::{Canonical, QueryResponse};
use rustc::infer::InferCtxt;
use rustc::traits::query::type_op::eq::Eq;
use rustc::traits::query::type_op::normalize::Normalize;
@ -38,7 +38,7 @@ crate fn provide(p: &mut Providers) {
fn type_op_eq<'tcx>(
tcx: TyCtxt<'_, 'tcx, 'tcx>,
canonicalized: Canonical<'tcx, ParamEnvAnd<'tcx, Eq<'tcx>>>,
) -> Result<Lrc<Canonical<'tcx, QueryResult<'tcx, ()>>>, NoSolution> {
) -> Result<Lrc<Canonical<'tcx, QueryResponse<'tcx, ()>>>, NoSolution> {
tcx.infer_ctxt()
.enter_canonical_trait_query(&canonicalized, |infcx, fulfill_cx, key| {
let (param_env, Eq { a, b }) = key.into_parts();
@ -68,7 +68,7 @@ where
fn type_op_normalize_ty(
tcx: TyCtxt<'_, 'tcx, 'tcx>,
canonicalized: Canonical<'tcx, ParamEnvAnd<'tcx, Normalize<Ty<'tcx>>>>,
) -> Result<Lrc<Canonical<'tcx, QueryResult<'tcx, Ty<'tcx>>>>, NoSolution> {
) -> Result<Lrc<Canonical<'tcx, QueryResponse<'tcx, Ty<'tcx>>>>, NoSolution> {
tcx.infer_ctxt()
.enter_canonical_trait_query(&canonicalized, type_op_normalize)
}
@ -76,7 +76,7 @@ fn type_op_normalize_ty(
fn type_op_normalize_predicate(
tcx: TyCtxt<'_, 'tcx, 'tcx>,
canonicalized: Canonical<'tcx, ParamEnvAnd<'tcx, Normalize<Predicate<'tcx>>>>,
) -> Result<Lrc<Canonical<'tcx, QueryResult<'tcx, Predicate<'tcx>>>>, NoSolution> {
) -> Result<Lrc<Canonical<'tcx, QueryResponse<'tcx, Predicate<'tcx>>>>, NoSolution> {
tcx.infer_ctxt()
.enter_canonical_trait_query(&canonicalized, type_op_normalize)
}
@ -84,7 +84,7 @@ fn type_op_normalize_predicate(
fn type_op_normalize_fn_sig(
tcx: TyCtxt<'_, 'tcx, 'tcx>,
canonicalized: Canonical<'tcx, ParamEnvAnd<'tcx, Normalize<FnSig<'tcx>>>>,
) -> Result<Lrc<Canonical<'tcx, QueryResult<'tcx, FnSig<'tcx>>>>, NoSolution> {
) -> Result<Lrc<Canonical<'tcx, QueryResponse<'tcx, FnSig<'tcx>>>>, NoSolution> {
tcx.infer_ctxt()
.enter_canonical_trait_query(&canonicalized, type_op_normalize)
}
@ -92,7 +92,7 @@ fn type_op_normalize_fn_sig(
fn type_op_normalize_poly_fn_sig(
tcx: TyCtxt<'_, 'tcx, 'tcx>,
canonicalized: Canonical<'tcx, ParamEnvAnd<'tcx, Normalize<PolyFnSig<'tcx>>>>,
) -> Result<Lrc<Canonical<'tcx, QueryResult<'tcx, PolyFnSig<'tcx>>>>, NoSolution> {
) -> Result<Lrc<Canonical<'tcx, QueryResponse<'tcx, PolyFnSig<'tcx>>>>, NoSolution> {
tcx.infer_ctxt()
.enter_canonical_trait_query(&canonicalized, type_op_normalize)
}
@ -100,7 +100,7 @@ fn type_op_normalize_poly_fn_sig(
fn type_op_subtype<'tcx>(
tcx: TyCtxt<'_, 'tcx, 'tcx>,
canonicalized: Canonical<'tcx, ParamEnvAnd<'tcx, Subtype<'tcx>>>,
) -> Result<Lrc<Canonical<'tcx, QueryResult<'tcx, ()>>>, NoSolution> {
) -> Result<Lrc<Canonical<'tcx, QueryResponse<'tcx, ()>>>, NoSolution> {
tcx.infer_ctxt()
.enter_canonical_trait_query(&canonicalized, |infcx, fulfill_cx, key| {
let (param_env, Subtype { sub, sup }) = key.into_parts();
@ -114,7 +114,7 @@ fn type_op_subtype<'tcx>(
fn type_op_prove_predicate<'tcx>(
tcx: TyCtxt<'_, 'tcx, 'tcx>,
canonicalized: Canonical<'tcx, ParamEnvAnd<'tcx, ProvePredicate<'tcx>>>,
) -> Result<Lrc<Canonical<'tcx, QueryResult<'tcx, ()>>>, NoSolution> {
) -> Result<Lrc<Canonical<'tcx, QueryResponse<'tcx, ()>>>, NoSolution> {
tcx.infer_ctxt()
.enter_canonical_trait_query(&canonicalized, |infcx, fulfill_cx, key| {
let (param_env, ProvePredicate { predicate }) = key.into_parts();