strip param-env from infcx
This commit is contained in:
parent
541523d10d
commit
5fb0f0dc2e
52 changed files with 694 additions and 383 deletions
|
@ -55,6 +55,7 @@ pub struct CombineFields<'infcx, 'gcx: 'infcx+'tcx, 'tcx: 'infcx> {
|
||||||
pub infcx: &'infcx InferCtxt<'infcx, 'gcx, 'tcx>,
|
pub infcx: &'infcx InferCtxt<'infcx, 'gcx, 'tcx>,
|
||||||
pub trace: TypeTrace<'tcx>,
|
pub trace: TypeTrace<'tcx>,
|
||||||
pub cause: Option<ty::relate::Cause>,
|
pub cause: Option<ty::relate::Cause>,
|
||||||
|
pub param_env: ty::ParamEnv<'tcx>,
|
||||||
pub obligations: PredicateObligations<'tcx>,
|
pub obligations: PredicateObligations<'tcx>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -215,6 +216,7 @@ impl<'infcx, 'gcx, 'tcx> CombineFields<'infcx, 'gcx, 'tcx> {
|
||||||
|
|
||||||
if needs_wf {
|
if needs_wf {
|
||||||
self.obligations.push(Obligation::new(self.trace.cause.clone(),
|
self.obligations.push(Obligation::new(self.trace.cause.clone(),
|
||||||
|
self.param_env,
|
||||||
ty::Predicate::WellFormed(b_ty)));
|
ty::Predicate::WellFormed(b_ty)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -161,8 +161,6 @@ pub struct InferCtxt<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
|
||||||
// For region variables.
|
// For region variables.
|
||||||
region_vars: RegionVarBindings<'a, 'gcx, 'tcx>,
|
region_vars: RegionVarBindings<'a, 'gcx, 'tcx>,
|
||||||
|
|
||||||
pub param_env: ty::ParamEnv<'gcx>,
|
|
||||||
|
|
||||||
/// Caches the results of trait selection. This cache is used
|
/// Caches the results of trait selection. This cache is used
|
||||||
/// for things that have to do with the parameters in scope.
|
/// for things that have to do with the parameters in scope.
|
||||||
pub selection_cache: traits::SelectionCache<'tcx>,
|
pub selection_cache: traits::SelectionCache<'tcx>,
|
||||||
|
@ -400,55 +398,39 @@ impl fmt::Display for FixupError {
|
||||||
pub trait InferEnv<'a, 'tcx> {
|
pub trait InferEnv<'a, 'tcx> {
|
||||||
fn to_parts(self, tcx: TyCtxt<'a, 'tcx, 'tcx>)
|
fn to_parts(self, tcx: TyCtxt<'a, 'tcx, 'tcx>)
|
||||||
-> (Option<&'a ty::TypeckTables<'tcx>>,
|
-> (Option<&'a ty::TypeckTables<'tcx>>,
|
||||||
Option<ty::TypeckTables<'tcx>>,
|
Option<ty::TypeckTables<'tcx>>);
|
||||||
ty::ParamEnv<'tcx>);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'tcx> InferEnv<'a, 'tcx> for Reveal {
|
impl<'a, 'tcx> InferEnv<'a, 'tcx> for () {
|
||||||
fn to_parts(self, _: TyCtxt<'a, 'tcx, 'tcx>)
|
fn to_parts(self, _: TyCtxt<'a, 'tcx, 'tcx>)
|
||||||
-> (Option<&'a ty::TypeckTables<'tcx>>,
|
-> (Option<&'a ty::TypeckTables<'tcx>>,
|
||||||
Option<ty::TypeckTables<'tcx>>,
|
Option<ty::TypeckTables<'tcx>>) {
|
||||||
ty::ParamEnv<'tcx>) {
|
(None, None)
|
||||||
(None, None, ty::ParamEnv::empty(self))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'tcx> InferEnv<'a, 'tcx> for ty::ParamEnv<'tcx> {
|
impl<'a, 'tcx> InferEnv<'a, 'tcx> for &'a ty::TypeckTables<'tcx> {
|
||||||
fn to_parts(self, _: TyCtxt<'a, 'tcx, 'tcx>)
|
fn to_parts(self, _: TyCtxt<'a, 'tcx, 'tcx>)
|
||||||
-> (Option<&'a ty::TypeckTables<'tcx>>,
|
-> (Option<&'a ty::TypeckTables<'tcx>>,
|
||||||
Option<ty::TypeckTables<'tcx>>,
|
Option<ty::TypeckTables<'tcx>>) {
|
||||||
ty::ParamEnv<'tcx>) {
|
(Some(self), None)
|
||||||
(None, None, self)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'tcx> InferEnv<'a, 'tcx> for (&'a ty::TypeckTables<'tcx>, ty::ParamEnv<'tcx>) {
|
impl<'a, 'tcx> InferEnv<'a, 'tcx> for ty::TypeckTables<'tcx> {
|
||||||
fn to_parts(self, _: TyCtxt<'a, 'tcx, 'tcx>)
|
fn to_parts(self, _: TyCtxt<'a, 'tcx, 'tcx>)
|
||||||
-> (Option<&'a ty::TypeckTables<'tcx>>,
|
-> (Option<&'a ty::TypeckTables<'tcx>>,
|
||||||
Option<ty::TypeckTables<'tcx>>,
|
Option<ty::TypeckTables<'tcx>>) {
|
||||||
ty::ParamEnv<'tcx>) {
|
(None, Some(self))
|
||||||
(Some(self.0), None, self.1)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a, 'tcx> InferEnv<'a, 'tcx> for (ty::TypeckTables<'tcx>, ty::ParamEnv<'tcx>) {
|
|
||||||
fn to_parts(self, _: TyCtxt<'a, 'tcx, 'tcx>)
|
|
||||||
-> (Option<&'a ty::TypeckTables<'tcx>>,
|
|
||||||
Option<ty::TypeckTables<'tcx>>,
|
|
||||||
ty::ParamEnv<'tcx>) {
|
|
||||||
(None, Some(self.0), self.1)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'tcx> InferEnv<'a, 'tcx> for hir::BodyId {
|
impl<'a, 'tcx> InferEnv<'a, 'tcx> for hir::BodyId {
|
||||||
fn to_parts(self, tcx: TyCtxt<'a, 'tcx, 'tcx>)
|
fn to_parts(self, tcx: TyCtxt<'a, 'tcx, 'tcx>)
|
||||||
-> (Option<&'a ty::TypeckTables<'tcx>>,
|
-> (Option<&'a ty::TypeckTables<'tcx>>,
|
||||||
Option<ty::TypeckTables<'tcx>>,
|
Option<ty::TypeckTables<'tcx>>) {
|
||||||
ty::ParamEnv<'tcx>) {
|
|
||||||
let def_id = tcx.hir.body_owner_def_id(self);
|
let def_id = tcx.hir.body_owner_def_id(self);
|
||||||
(Some(tcx.typeck_tables_of(def_id)),
|
(Some(tcx.typeck_tables_of(def_id)), None)
|
||||||
None,
|
|
||||||
tcx.param_env(def_id))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -460,18 +442,16 @@ pub struct InferCtxtBuilder<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
|
||||||
arena: DroplessArena,
|
arena: DroplessArena,
|
||||||
fresh_tables: Option<RefCell<ty::TypeckTables<'tcx>>>,
|
fresh_tables: Option<RefCell<ty::TypeckTables<'tcx>>>,
|
||||||
tables: Option<&'a ty::TypeckTables<'gcx>>,
|
tables: Option<&'a ty::TypeckTables<'gcx>>,
|
||||||
param_env: ty::ParamEnv<'gcx>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'gcx> {
|
impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'gcx> {
|
||||||
pub fn infer_ctxt<E: InferEnv<'a, 'gcx>>(self, env: E) -> InferCtxtBuilder<'a, 'gcx, 'tcx> {
|
pub fn infer_ctxt<E: InferEnv<'a, 'gcx>>(self, env: E) -> InferCtxtBuilder<'a, 'gcx, 'tcx> {
|
||||||
let (tables, fresh_tables, param_env) = env.to_parts(self);
|
let (tables, fresh_tables) = env.to_parts(self);
|
||||||
InferCtxtBuilder {
|
InferCtxtBuilder {
|
||||||
global_tcx: self,
|
global_tcx: self,
|
||||||
arena: DroplessArena::new(),
|
arena: DroplessArena::new(),
|
||||||
fresh_tables: fresh_tables.map(RefCell::new),
|
fresh_tables: fresh_tables.map(RefCell::new),
|
||||||
tables: tables,
|
tables: tables,
|
||||||
param_env: param_env,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -480,7 +460,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'gcx> {
|
||||||
/// If any inference functionality is used, ICEs will occur.
|
/// If any inference functionality is used, ICEs will occur.
|
||||||
pub fn borrowck_fake_infer_ctxt(self, body: hir::BodyId)
|
pub fn borrowck_fake_infer_ctxt(self, body: hir::BodyId)
|
||||||
-> InferCtxt<'a, 'gcx, 'gcx> {
|
-> InferCtxt<'a, 'gcx, 'gcx> {
|
||||||
let (tables, _, param_env) = body.to_parts(self);
|
let (tables, _) = body.to_parts(self);
|
||||||
InferCtxt {
|
InferCtxt {
|
||||||
tcx: self,
|
tcx: self,
|
||||||
tables: InferTables::Interned(tables.unwrap()),
|
tables: InferTables::Interned(tables.unwrap()),
|
||||||
|
@ -488,7 +468,6 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'gcx> {
|
||||||
int_unification_table: RefCell::new(UnificationTable::new()),
|
int_unification_table: RefCell::new(UnificationTable::new()),
|
||||||
float_unification_table: RefCell::new(UnificationTable::new()),
|
float_unification_table: RefCell::new(UnificationTable::new()),
|
||||||
region_vars: RegionVarBindings::new(self),
|
region_vars: RegionVarBindings::new(self),
|
||||||
param_env: param_env,
|
|
||||||
selection_cache: traits::SelectionCache::new(),
|
selection_cache: traits::SelectionCache::new(),
|
||||||
evaluation_cache: traits::EvaluationCache::new(),
|
evaluation_cache: traits::EvaluationCache::new(),
|
||||||
projection_cache: RefCell::new(traits::ProjectionCache::new()),
|
projection_cache: RefCell::new(traits::ProjectionCache::new()),
|
||||||
|
@ -509,7 +488,6 @@ impl<'a, 'gcx, 'tcx> InferCtxtBuilder<'a, 'gcx, 'tcx> {
|
||||||
ref arena,
|
ref arena,
|
||||||
ref fresh_tables,
|
ref fresh_tables,
|
||||||
tables,
|
tables,
|
||||||
param_env,
|
|
||||||
} = *self;
|
} = *self;
|
||||||
let tables = tables.map(InferTables::Interned).unwrap_or_else(|| {
|
let tables = tables.map(InferTables::Interned).unwrap_or_else(|| {
|
||||||
fresh_tables.as_ref().map_or(InferTables::Missing, InferTables::InProgress)
|
fresh_tables.as_ref().map_or(InferTables::Missing, InferTables::InProgress)
|
||||||
|
@ -522,7 +500,6 @@ impl<'a, 'gcx, 'tcx> InferCtxtBuilder<'a, 'gcx, 'tcx> {
|
||||||
int_unification_table: RefCell::new(UnificationTable::new()),
|
int_unification_table: RefCell::new(UnificationTable::new()),
|
||||||
float_unification_table: RefCell::new(UnificationTable::new()),
|
float_unification_table: RefCell::new(UnificationTable::new()),
|
||||||
region_vars: RegionVarBindings::new(tcx),
|
region_vars: RegionVarBindings::new(tcx),
|
||||||
param_env: param_env,
|
|
||||||
selection_cache: traits::SelectionCache::new(),
|
selection_cache: traits::SelectionCache::new(),
|
||||||
evaluation_cache: traits::EvaluationCache::new(),
|
evaluation_cache: traits::EvaluationCache::new(),
|
||||||
reported_trait_errors: RefCell::new(FxHashSet()),
|
reported_trait_errors: RefCell::new(FxHashSet()),
|
||||||
|
@ -563,7 +540,10 @@ pub struct CombinedSnapshot<'a, 'tcx:'a> {
|
||||||
/// Helper trait for shortening the lifetimes inside a
|
/// Helper trait for shortening the lifetimes inside a
|
||||||
/// value for post-type-checking normalization.
|
/// value for post-type-checking normalization.
|
||||||
pub trait TransNormalize<'gcx>: TypeFoldable<'gcx> {
|
pub trait TransNormalize<'gcx>: TypeFoldable<'gcx> {
|
||||||
fn trans_normalize<'a, 'tcx>(&self, infcx: &InferCtxt<'a, 'gcx, 'tcx>) -> Self;
|
fn trans_normalize<'a, 'tcx>(&self,
|
||||||
|
infcx: &InferCtxt<'a, 'gcx, 'tcx>,
|
||||||
|
param_env: ty::ParamEnv<'tcx>)
|
||||||
|
-> Self;
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! items { ($($item:item)+) => ($($item)+) }
|
macro_rules! items { ($($item:item)+) => ($($item)+) }
|
||||||
|
@ -571,9 +551,10 @@ macro_rules! impl_trans_normalize {
|
||||||
($lt_gcx:tt, $($ty:ty),+) => {
|
($lt_gcx:tt, $($ty:ty),+) => {
|
||||||
items!($(impl<$lt_gcx> TransNormalize<$lt_gcx> for $ty {
|
items!($(impl<$lt_gcx> TransNormalize<$lt_gcx> for $ty {
|
||||||
fn trans_normalize<'a, 'tcx>(&self,
|
fn trans_normalize<'a, 'tcx>(&self,
|
||||||
infcx: &InferCtxt<'a, $lt_gcx, 'tcx>)
|
infcx: &InferCtxt<'a, $lt_gcx, 'tcx>,
|
||||||
|
param_env: ty::ParamEnv<'tcx>)
|
||||||
-> Self {
|
-> Self {
|
||||||
infcx.normalize_projections_in(self)
|
infcx.normalize_projections_in(param_env, self)
|
||||||
}
|
}
|
||||||
})+);
|
})+);
|
||||||
}
|
}
|
||||||
|
@ -590,13 +571,16 @@ impl_trans_normalize!('gcx,
|
||||||
);
|
);
|
||||||
|
|
||||||
impl<'gcx> TransNormalize<'gcx> for LvalueTy<'gcx> {
|
impl<'gcx> TransNormalize<'gcx> for LvalueTy<'gcx> {
|
||||||
fn trans_normalize<'a, 'tcx>(&self, infcx: &InferCtxt<'a, 'gcx, 'tcx>) -> Self {
|
fn trans_normalize<'a, 'tcx>(&self,
|
||||||
|
infcx: &InferCtxt<'a, 'gcx, 'tcx>,
|
||||||
|
param_env: ty::ParamEnv<'tcx>)
|
||||||
|
-> Self {
|
||||||
match *self {
|
match *self {
|
||||||
LvalueTy::Ty { ty } => LvalueTy::Ty { ty: ty.trans_normalize(infcx) },
|
LvalueTy::Ty { ty } => LvalueTy::Ty { ty: ty.trans_normalize(infcx, param_env) },
|
||||||
LvalueTy::Downcast { adt_def, substs, variant_index } => {
|
LvalueTy::Downcast { adt_def, substs, variant_index } => {
|
||||||
LvalueTy::Downcast {
|
LvalueTy::Downcast {
|
||||||
adt_def: adt_def,
|
adt_def: adt_def,
|
||||||
substs: substs.trans_normalize(infcx),
|
substs: substs.trans_normalize(infcx, param_env),
|
||||||
variant_index: variant_index
|
variant_index: variant_index
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -618,19 +602,23 @@ impl<'a, 'tcx> TyCtxt<'a, 'tcx, 'tcx> {
|
||||||
self.normalize_associated_type(&value)
|
self.normalize_associated_type(&value)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Fully normalizes any associated types in `value`, using an
|
||||||
|
/// empty environment and `Reveal::All` mode (therefore, suitable
|
||||||
|
/// only for monomorphized code during trans, basically).
|
||||||
pub fn normalize_associated_type<T>(self, value: &T) -> T
|
pub fn normalize_associated_type<T>(self, value: &T) -> T
|
||||||
where T: TransNormalize<'tcx>
|
where T: TransNormalize<'tcx>
|
||||||
{
|
{
|
||||||
debug!("normalize_associated_type(t={:?})", value);
|
debug!("normalize_associated_type(t={:?})", value);
|
||||||
|
|
||||||
|
let param_env = ty::ParamEnv::empty(Reveal::All);
|
||||||
let value = self.erase_regions(value);
|
let value = self.erase_regions(value);
|
||||||
|
|
||||||
if !value.has_projection_types() {
|
if !value.has_projection_types() {
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
self.infer_ctxt(Reveal::All).enter(|infcx| {
|
self.infer_ctxt(()).enter(|infcx| {
|
||||||
value.trans_normalize(&infcx)
|
value.trans_normalize(&infcx, param_env)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -651,20 +639,20 @@ impl<'a, 'tcx> TyCtxt<'a, 'tcx, 'tcx> {
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
self.infer_ctxt(env.reveal_all()).enter(|infcx| {
|
self.infer_ctxt(()).enter(|infcx| {
|
||||||
value.trans_normalize(&infcx)
|
value.trans_normalize(&infcx, env.reveal_all())
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
|
impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
|
||||||
fn normalize_projections_in<T>(&self, value: &T) -> T::Lifted
|
fn normalize_projections_in<T>(&self, param_env: ty::ParamEnv<'tcx>, value: &T) -> T::Lifted
|
||||||
where T: TypeFoldable<'tcx> + ty::Lift<'gcx>
|
where T: TypeFoldable<'tcx> + ty::Lift<'gcx>
|
||||||
{
|
{
|
||||||
let mut selcx = traits::SelectionContext::new(self);
|
let mut selcx = traits::SelectionContext::new(self);
|
||||||
let cause = traits::ObligationCause::dummy();
|
let cause = traits::ObligationCause::dummy();
|
||||||
let traits::Normalized { value: result, obligations } =
|
let traits::Normalized { value: result, obligations } =
|
||||||
traits::normalize(&mut selcx, cause, value);
|
traits::normalize(&mut selcx, param_env, cause, value);
|
||||||
|
|
||||||
debug!("normalize_projections_in: result={:?} obligations={:?}",
|
debug!("normalize_projections_in: result={:?} obligations={:?}",
|
||||||
result, obligations);
|
result, obligations);
|
||||||
|
@ -803,48 +791,69 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
|
||||||
return variables;
|
return variables;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn combine_fields(&'a self, trace: TypeTrace<'tcx>)
|
fn combine_fields(&'a self, trace: TypeTrace<'tcx>, param_env: ty::ParamEnv<'tcx>)
|
||||||
-> CombineFields<'a, 'gcx, 'tcx> {
|
-> CombineFields<'a, 'gcx, 'tcx> {
|
||||||
CombineFields {
|
CombineFields {
|
||||||
infcx: self,
|
infcx: self,
|
||||||
trace: trace,
|
trace: trace,
|
||||||
cause: None,
|
cause: None,
|
||||||
|
param_env,
|
||||||
obligations: PredicateObligations::new(),
|
obligations: PredicateObligations::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn equate<T>(&'a self, a_is_expected: bool, trace: TypeTrace<'tcx>, a: &T, b: &T)
|
pub fn equate<T>(&'a self,
|
||||||
|
a_is_expected: bool,
|
||||||
|
trace: TypeTrace<'tcx>,
|
||||||
|
param_env: ty::ParamEnv<'tcx>,
|
||||||
|
a: &T,
|
||||||
|
b: &T)
|
||||||
-> InferResult<'tcx, T>
|
-> InferResult<'tcx, T>
|
||||||
where T: Relate<'tcx>
|
where T: Relate<'tcx>
|
||||||
{
|
{
|
||||||
let mut fields = self.combine_fields(trace);
|
let mut fields = self.combine_fields(trace, param_env);
|
||||||
let result = fields.equate(a_is_expected).relate(a, b);
|
let result = fields.equate(a_is_expected).relate(a, b);
|
||||||
result.map(move |t| InferOk { value: t, obligations: fields.obligations })
|
result.map(move |t| InferOk { value: t, obligations: fields.obligations })
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn sub<T>(&'a self, a_is_expected: bool, trace: TypeTrace<'tcx>, a: &T, b: &T)
|
pub fn sub<T>(&'a self,
|
||||||
|
a_is_expected: bool,
|
||||||
|
trace: TypeTrace<'tcx>,
|
||||||
|
param_env: ty::ParamEnv<'tcx>,
|
||||||
|
a: &T,
|
||||||
|
b: &T)
|
||||||
-> InferResult<'tcx, T>
|
-> InferResult<'tcx, T>
|
||||||
where T: Relate<'tcx>
|
where T: Relate<'tcx>
|
||||||
{
|
{
|
||||||
let mut fields = self.combine_fields(trace);
|
let mut fields = self.combine_fields(trace, param_env);
|
||||||
let result = fields.sub(a_is_expected).relate(a, b);
|
let result = fields.sub(a_is_expected).relate(a, b);
|
||||||
result.map(move |t| InferOk { value: t, obligations: fields.obligations })
|
result.map(move |t| InferOk { value: t, obligations: fields.obligations })
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn lub<T>(&'a self, a_is_expected: bool, trace: TypeTrace<'tcx>, a: &T, b: &T)
|
pub fn lub<T>(&'a self,
|
||||||
|
a_is_expected: bool,
|
||||||
|
trace: TypeTrace<'tcx>,
|
||||||
|
param_env: ty::ParamEnv<'tcx>,
|
||||||
|
a: &T,
|
||||||
|
b: &T)
|
||||||
-> InferResult<'tcx, T>
|
-> InferResult<'tcx, T>
|
||||||
where T: Relate<'tcx>
|
where T: Relate<'tcx>
|
||||||
{
|
{
|
||||||
let mut fields = self.combine_fields(trace);
|
let mut fields = self.combine_fields(trace, param_env);
|
||||||
let result = fields.lub(a_is_expected).relate(a, b);
|
let result = fields.lub(a_is_expected).relate(a, b);
|
||||||
result.map(move |t| InferOk { value: t, obligations: fields.obligations })
|
result.map(move |t| InferOk { value: t, obligations: fields.obligations })
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn glb<T>(&'a self, a_is_expected: bool, trace: TypeTrace<'tcx>, a: &T, b: &T)
|
pub fn glb<T>(&'a self,
|
||||||
|
a_is_expected: bool,
|
||||||
|
trace: TypeTrace<'tcx>,
|
||||||
|
param_env: ty::ParamEnv<'tcx>,
|
||||||
|
a: &T,
|
||||||
|
b: &T)
|
||||||
-> InferResult<'tcx, T>
|
-> InferResult<'tcx, T>
|
||||||
where T: Relate<'tcx>
|
where T: Relate<'tcx>
|
||||||
{
|
{
|
||||||
let mut fields = self.combine_fields(trace);
|
let mut fields = self.combine_fields(trace, param_env);
|
||||||
let result = fields.glb(a_is_expected).relate(a, b);
|
let result = fields.glb(a_is_expected).relate(a, b);
|
||||||
result.map(move |t| InferOk { value: t, obligations: fields.obligations })
|
result.map(move |t| InferOk { value: t, obligations: fields.obligations })
|
||||||
}
|
}
|
||||||
|
@ -1011,18 +1020,20 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
|
||||||
pub fn sub_types(&self,
|
pub fn sub_types(&self,
|
||||||
a_is_expected: bool,
|
a_is_expected: bool,
|
||||||
cause: &ObligationCause<'tcx>,
|
cause: &ObligationCause<'tcx>,
|
||||||
|
param_env: ty::ParamEnv<'tcx>,
|
||||||
a: Ty<'tcx>,
|
a: Ty<'tcx>,
|
||||||
b: Ty<'tcx>)
|
b: Ty<'tcx>)
|
||||||
-> InferResult<'tcx, ()>
|
-> InferResult<'tcx, ()>
|
||||||
{
|
{
|
||||||
debug!("sub_types({:?} <: {:?})", a, b);
|
debug!("sub_types({:?} <: {:?})", a, b);
|
||||||
self.commit_if_ok(|_| {
|
self.commit_if_ok(|_| {
|
||||||
let trace = TypeTrace::types(cause, a_is_expected, a, b);
|
let trace = TypeTrace::types(cause, a_is_expected, a, b);
|
||||||
self.sub(a_is_expected, trace, &a, &b).map(|ok| ok.unit())
|
self.sub(a_is_expected, trace, param_env, &a, &b).map(|ok| ok.unit())
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn can_sub_types(&self,
|
pub fn can_sub_types(&self,
|
||||||
|
param_env: ty::ParamEnv<'tcx>,
|
||||||
a: Ty<'tcx>,
|
a: Ty<'tcx>,
|
||||||
b: Ty<'tcx>)
|
b: Ty<'tcx>)
|
||||||
-> UnitResult<'tcx>
|
-> UnitResult<'tcx>
|
||||||
|
@ -1030,7 +1041,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
|
||||||
self.probe(|_| {
|
self.probe(|_| {
|
||||||
let origin = &ObligationCause::dummy();
|
let origin = &ObligationCause::dummy();
|
||||||
let trace = TypeTrace::types(origin, true, a, b);
|
let trace = TypeTrace::types(origin, true, a, b);
|
||||||
self.sub(true, trace, &a, &b).map(|InferOk { obligations: _, .. }| {
|
self.sub(true, trace, param_env, &a, &b).map(|InferOk { obligations: _, .. }| {
|
||||||
// Ignore obligations, since we are unrolling
|
// Ignore obligations, since we are unrolling
|
||||||
// everything anyway.
|
// everything anyway.
|
||||||
})
|
})
|
||||||
|
@ -1040,21 +1051,23 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
|
||||||
pub fn eq_types(&self,
|
pub fn eq_types(&self,
|
||||||
a_is_expected: bool,
|
a_is_expected: bool,
|
||||||
cause: &ObligationCause<'tcx>,
|
cause: &ObligationCause<'tcx>,
|
||||||
|
param_env: ty::ParamEnv<'tcx>,
|
||||||
a: Ty<'tcx>,
|
a: Ty<'tcx>,
|
||||||
b: Ty<'tcx>)
|
b: Ty<'tcx>)
|
||||||
-> InferResult<'tcx, ()>
|
-> InferResult<'tcx, ()>
|
||||||
{
|
{
|
||||||
self.commit_if_ok(|_| {
|
self.commit_if_ok(|_| {
|
||||||
let trace = TypeTrace::types(cause, a_is_expected, a, b);
|
let trace = TypeTrace::types(cause, a_is_expected, a, b);
|
||||||
self.equate(a_is_expected, trace, &a, &b).map(|ok| ok.unit())
|
self.equate(a_is_expected, trace, param_env, &a, &b).map(|ok| ok.unit())
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn eq_trait_refs(&self,
|
pub fn eq_trait_refs(&self,
|
||||||
a_is_expected: bool,
|
a_is_expected: bool,
|
||||||
cause: &ObligationCause<'tcx>,
|
cause: &ObligationCause<'tcx>,
|
||||||
a: ty::TraitRef<'tcx>,
|
param_env: ty::ParamEnv<'tcx>,
|
||||||
b: ty::TraitRef<'tcx>)
|
a: ty::TraitRef<'tcx>,
|
||||||
|
b: ty::TraitRef<'tcx>)
|
||||||
-> InferResult<'tcx, ()>
|
-> InferResult<'tcx, ()>
|
||||||
{
|
{
|
||||||
debug!("eq_trait_refs({:?} = {:?})", a, b);
|
debug!("eq_trait_refs({:?} = {:?})", a, b);
|
||||||
|
@ -1063,21 +1076,24 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
|
||||||
cause: cause.clone(),
|
cause: cause.clone(),
|
||||||
values: TraitRefs(ExpectedFound::new(a_is_expected, a, b))
|
values: TraitRefs(ExpectedFound::new(a_is_expected, a, b))
|
||||||
};
|
};
|
||||||
self.equate(a_is_expected, trace, &a, &b).map(|ok| ok.unit())
|
self.equate(a_is_expected, trace, param_env, &a, &b).map(|ok| ok.unit())
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn eq_impl_headers(&self,
|
pub fn eq_impl_headers(&self,
|
||||||
a_is_expected: bool,
|
a_is_expected: bool,
|
||||||
cause: &ObligationCause<'tcx>,
|
cause: &ObligationCause<'tcx>,
|
||||||
|
param_env: ty::ParamEnv<'tcx>,
|
||||||
a: &ty::ImplHeader<'tcx>,
|
a: &ty::ImplHeader<'tcx>,
|
||||||
b: &ty::ImplHeader<'tcx>)
|
b: &ty::ImplHeader<'tcx>)
|
||||||
-> InferResult<'tcx, ()>
|
-> InferResult<'tcx, ()>
|
||||||
{
|
{
|
||||||
debug!("eq_impl_header({:?} = {:?})", a, b);
|
debug!("eq_impl_header({:?} = {:?})", a, b);
|
||||||
match (a.trait_ref, b.trait_ref) {
|
match (a.trait_ref, b.trait_ref) {
|
||||||
(Some(a_ref), Some(b_ref)) => self.eq_trait_refs(a_is_expected, cause, a_ref, b_ref),
|
(Some(a_ref), Some(b_ref)) =>
|
||||||
(None, None) => self.eq_types(a_is_expected, cause, a.self_ty, b.self_ty),
|
self.eq_trait_refs(a_is_expected, cause, param_env, a_ref, b_ref),
|
||||||
|
(None, None) =>
|
||||||
|
self.eq_types(a_is_expected, cause, param_env, a.self_ty, b.self_ty),
|
||||||
_ => bug!("mk_eq_impl_headers given mismatched impl kinds"),
|
_ => bug!("mk_eq_impl_headers given mismatched impl kinds"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1085,6 +1101,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
|
||||||
pub fn sub_poly_trait_refs(&self,
|
pub fn sub_poly_trait_refs(&self,
|
||||||
a_is_expected: bool,
|
a_is_expected: bool,
|
||||||
cause: ObligationCause<'tcx>,
|
cause: ObligationCause<'tcx>,
|
||||||
|
param_env: ty::ParamEnv<'tcx>,
|
||||||
a: ty::PolyTraitRef<'tcx>,
|
a: ty::PolyTraitRef<'tcx>,
|
||||||
b: ty::PolyTraitRef<'tcx>)
|
b: ty::PolyTraitRef<'tcx>)
|
||||||
-> InferResult<'tcx, ()>
|
-> InferResult<'tcx, ()>
|
||||||
|
@ -1095,7 +1112,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
|
||||||
cause: cause,
|
cause: cause,
|
||||||
values: PolyTraitRefs(ExpectedFound::new(a_is_expected, a, b))
|
values: PolyTraitRefs(ExpectedFound::new(a_is_expected, a, b))
|
||||||
};
|
};
|
||||||
self.sub(a_is_expected, trace, &a, &b).map(|ok| ok.unit())
|
self.sub(a_is_expected, trace, param_env, &a, &b).map(|ok| ok.unit())
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1109,6 +1126,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
|
||||||
|
|
||||||
pub fn equality_predicate(&self,
|
pub fn equality_predicate(&self,
|
||||||
cause: &ObligationCause<'tcx>,
|
cause: &ObligationCause<'tcx>,
|
||||||
|
param_env: ty::ParamEnv<'tcx>,
|
||||||
predicate: &ty::PolyEquatePredicate<'tcx>)
|
predicate: &ty::PolyEquatePredicate<'tcx>)
|
||||||
-> InferResult<'tcx, ()>
|
-> InferResult<'tcx, ()>
|
||||||
{
|
{
|
||||||
|
@ -1116,7 +1134,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
|
||||||
let (ty::EquatePredicate(a, b), skol_map) =
|
let (ty::EquatePredicate(a, b), skol_map) =
|
||||||
self.skolemize_late_bound_regions(predicate, snapshot);
|
self.skolemize_late_bound_regions(predicate, snapshot);
|
||||||
let cause_span = cause.span;
|
let cause_span = cause.span;
|
||||||
let eqty_ok = self.eq_types(false, cause, a, b)?;
|
let eqty_ok = self.eq_types(false, cause, param_env, a, b)?;
|
||||||
self.leak_check(false, cause_span, &skol_map, snapshot)?;
|
self.leak_check(false, cause_span, &skol_map, snapshot)?;
|
||||||
self.pop_skolemized(skol_map, snapshot);
|
self.pop_skolemized(skol_map, snapshot);
|
||||||
Ok(eqty_ok.unit())
|
Ok(eqty_ok.unit())
|
||||||
|
@ -1125,6 +1143,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
|
||||||
|
|
||||||
pub fn subtype_predicate(&self,
|
pub fn subtype_predicate(&self,
|
||||||
cause: &ObligationCause<'tcx>,
|
cause: &ObligationCause<'tcx>,
|
||||||
|
param_env: ty::ParamEnv<'tcx>,
|
||||||
predicate: &ty::PolySubtypePredicate<'tcx>)
|
predicate: &ty::PolySubtypePredicate<'tcx>)
|
||||||
-> Option<InferResult<'tcx, ()>>
|
-> Option<InferResult<'tcx, ()>>
|
||||||
{
|
{
|
||||||
|
@ -1153,7 +1172,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
|
||||||
self.skolemize_late_bound_regions(predicate, snapshot);
|
self.skolemize_late_bound_regions(predicate, snapshot);
|
||||||
|
|
||||||
let cause_span = cause.span;
|
let cause_span = cause.span;
|
||||||
let ok = self.sub_types(a_is_expected, cause, a, b)?;
|
let ok = self.sub_types(a_is_expected, cause, param_env, a, b)?;
|
||||||
self.leak_check(false, cause_span, &skol_map, snapshot)?;
|
self.leak_check(false, cause_span, &skol_map, snapshot)?;
|
||||||
self.pop_skolemized(skol_map, snapshot);
|
self.pop_skolemized(skol_map, snapshot);
|
||||||
Ok(ok.unit())
|
Ok(ok.unit())
|
||||||
|
@ -1555,6 +1574,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
|
||||||
/// details.
|
/// details.
|
||||||
pub fn match_poly_projection_predicate(&self,
|
pub fn match_poly_projection_predicate(&self,
|
||||||
cause: ObligationCause<'tcx>,
|
cause: ObligationCause<'tcx>,
|
||||||
|
param_env: ty::ParamEnv<'tcx>,
|
||||||
match_a: ty::PolyProjectionPredicate<'tcx>,
|
match_a: ty::PolyProjectionPredicate<'tcx>,
|
||||||
match_b: ty::TraitRef<'tcx>)
|
match_b: ty::TraitRef<'tcx>)
|
||||||
-> InferResult<'tcx, HrMatchResult<Ty<'tcx>>>
|
-> InferResult<'tcx, HrMatchResult<Ty<'tcx>>>
|
||||||
|
@ -1567,7 +1587,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
|
||||||
};
|
};
|
||||||
|
|
||||||
let match_pair = match_a.map_bound(|p| (p.projection_ty.trait_ref, p.ty));
|
let match_pair = match_a.map_bound(|p| (p.projection_ty.trait_ref, p.ty));
|
||||||
let mut combine = self.combine_fields(trace);
|
let mut combine = self.combine_fields(trace, param_env);
|
||||||
let result = combine.higher_ranked_match(span, &match_pair, &match_b, true)?;
|
let result = combine.higher_ranked_match(span, &match_pair, &match_b, true)?;
|
||||||
Ok(InferOk { value: result, obligations: combine.obligations })
|
Ok(InferOk { value: result, obligations: combine.obligations })
|
||||||
}
|
}
|
||||||
|
@ -1586,7 +1606,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
|
||||||
self.region_vars.verify_generic_bound(origin, kind, a, bound);
|
self.region_vars.verify_generic_bound(origin, kind, a, bound);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn can_equate<T>(&self, a: &T, b: &T) -> UnitResult<'tcx>
|
pub fn can_equate<T>(&self, param_env: ty::ParamEnv<'tcx>, a: &T, b: &T) -> UnitResult<'tcx>
|
||||||
where T: Relate<'tcx> + fmt::Debug
|
where T: Relate<'tcx> + fmt::Debug
|
||||||
{
|
{
|
||||||
debug!("can_equate({:?}, {:?})", a, b);
|
debug!("can_equate({:?}, {:?})", a, b);
|
||||||
|
@ -1596,7 +1616,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
|
||||||
// generic so we don't have to do anything quite this
|
// generic so we don't have to do anything quite this
|
||||||
// terrible.
|
// terrible.
|
||||||
let trace = TypeTrace::dummy(self.tcx);
|
let trace = TypeTrace::dummy(self.tcx);
|
||||||
self.equate(true, trace, a, b).map(|InferOk { obligations: _, .. }| {
|
self.equate(true, trace, param_env, a, b).map(|InferOk { obligations: _, .. }| {
|
||||||
// We can intentionally ignore obligations here, since
|
// We can intentionally ignore obligations here, since
|
||||||
// this is part of a simple test for general
|
// this is part of a simple test for general
|
||||||
// "equatability". However, it's not entirely clear
|
// "equatability". However, it's not entirely clear
|
||||||
|
@ -1617,9 +1637,13 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
|
||||||
self.resolve_type_vars_or_error(&ty)
|
self.resolve_type_vars_or_error(&ty)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn type_moves_by_default(&self, ty: Ty<'tcx>, span: Span) -> bool {
|
pub fn type_moves_by_default(&self,
|
||||||
|
param_env: ty::ParamEnv<'tcx>,
|
||||||
|
ty: Ty<'tcx>,
|
||||||
|
span: Span)
|
||||||
|
-> bool {
|
||||||
let ty = self.resolve_type_vars_if_possible(&ty);
|
let ty = self.resolve_type_vars_if_possible(&ty);
|
||||||
if let Some(ty) = self.tcx.lift_to_global(&ty) {
|
if let Some((param_env, ty)) = self.tcx.lift_to_global(&(param_env, ty)) {
|
||||||
// Even if the type may have no inference variables, during
|
// Even if the type may have no inference variables, during
|
||||||
// type-checking closure types are in local tables only.
|
// type-checking closure types are in local tables only.
|
||||||
let local_closures = match self.tables {
|
let local_closures = match self.tables {
|
||||||
|
@ -1627,7 +1651,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
|
||||||
_ => false
|
_ => false
|
||||||
};
|
};
|
||||||
if !local_closures {
|
if !local_closures {
|
||||||
return ty.moves_by_default(self.tcx.global_tcx(), self.param_env(), span);
|
return ty.moves_by_default(self.tcx.global_tcx(), param_env, span);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1637,17 +1661,13 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
|
||||||
// rightly refuses to work with inference variables, but
|
// rightly refuses to work with inference variables, but
|
||||||
// moves_by_default has a cache, which we want to use in other
|
// moves_by_default has a cache, which we want to use in other
|
||||||
// cases.
|
// cases.
|
||||||
!traits::type_known_to_meet_bound(self, ty, copy_def_id, span)
|
!traits::type_known_to_meet_bound(self, param_env, ty, copy_def_id, span)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn upvar_capture(&self, upvar_id: ty::UpvarId) -> Option<ty::UpvarCapture<'tcx>> {
|
pub fn upvar_capture(&self, upvar_id: ty::UpvarId) -> Option<ty::UpvarCapture<'tcx>> {
|
||||||
self.tables.borrow().upvar_capture_map.get(&upvar_id).cloned()
|
self.tables.borrow().upvar_capture_map.get(&upvar_id).cloned()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn param_env(&self) -> ty::ParamEnv<'gcx> {
|
|
||||||
self.param_env
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn closure_kind(&self,
|
pub fn closure_kind(&self,
|
||||||
def_id: DefId)
|
def_id: DefId)
|
||||||
-> Option<ty::ClosureKind>
|
-> Option<ty::ClosureKind>
|
||||||
|
|
|
@ -96,6 +96,7 @@ impl<'combine, 'infcx, 'gcx, 'tcx> TypeRelation<'infcx, 'gcx, 'tcx>
|
||||||
self.fields.obligations.push(
|
self.fields.obligations.push(
|
||||||
Obligation::new(
|
Obligation::new(
|
||||||
self.fields.trace.cause.clone(),
|
self.fields.trace.cause.clone(),
|
||||||
|
self.fields.param_env,
|
||||||
ty::Predicate::Subtype(
|
ty::Predicate::Subtype(
|
||||||
ty::Binder(ty::SubtypePredicate {
|
ty::Binder(ty::SubtypePredicate {
|
||||||
a_is_expected: self.a_is_expected,
|
a_is_expected: self.a_is_expected,
|
||||||
|
|
|
@ -47,7 +47,7 @@
|
||||||
#![cfg_attr(stage0, feature(staged_api))]
|
#![cfg_attr(stage0, feature(staged_api))]
|
||||||
#![cfg_attr(stage0, feature(loop_break_value))]
|
#![cfg_attr(stage0, feature(loop_break_value))]
|
||||||
|
|
||||||
#![recursion_limit="192"]
|
#![recursion_limit="256"]
|
||||||
|
|
||||||
extern crate arena;
|
extern crate arena;
|
||||||
extern crate core;
|
extern crate core;
|
||||||
|
|
|
@ -242,6 +242,7 @@ impl OverloadedCallType {
|
||||||
pub struct ExprUseVisitor<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
|
pub struct ExprUseVisitor<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
|
||||||
mc: mc::MemCategorizationContext<'a, 'gcx, 'tcx>,
|
mc: mc::MemCategorizationContext<'a, 'gcx, 'tcx>,
|
||||||
delegate: &'a mut Delegate<'tcx>,
|
delegate: &'a mut Delegate<'tcx>,
|
||||||
|
param_env: ty::ParamEnv<'tcx>,
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the TYPER results in an error, it's because the type check
|
// If the TYPER results in an error, it's because the type check
|
||||||
|
@ -266,24 +267,28 @@ macro_rules! return_if_err {
|
||||||
impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> {
|
impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> {
|
||||||
pub fn new(delegate: &'a mut (Delegate<'tcx>+'a),
|
pub fn new(delegate: &'a mut (Delegate<'tcx>+'a),
|
||||||
region_maps: &'a RegionMaps,
|
region_maps: &'a RegionMaps,
|
||||||
infcx: &'a InferCtxt<'a, 'gcx, 'tcx>)
|
infcx: &'a InferCtxt<'a, 'gcx, 'tcx>,
|
||||||
|
param_env: ty::ParamEnv<'tcx>)
|
||||||
-> Self
|
-> Self
|
||||||
{
|
{
|
||||||
ExprUseVisitor::with_options(delegate,
|
ExprUseVisitor::with_options(delegate,
|
||||||
infcx,
|
infcx,
|
||||||
|
param_env,
|
||||||
region_maps,
|
region_maps,
|
||||||
mc::MemCategorizationOptions::default())
|
mc::MemCategorizationOptions::default())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn with_options(delegate: &'a mut (Delegate<'tcx>+'a),
|
pub fn with_options(delegate: &'a mut (Delegate<'tcx>+'a),
|
||||||
infcx: &'a InferCtxt<'a, 'gcx, 'tcx>,
|
infcx: &'a InferCtxt<'a, 'gcx, 'tcx>,
|
||||||
|
param_env: ty::ParamEnv<'tcx>,
|
||||||
region_maps: &'a RegionMaps,
|
region_maps: &'a RegionMaps,
|
||||||
options: mc::MemCategorizationOptions)
|
options: mc::MemCategorizationOptions)
|
||||||
-> Self
|
-> Self
|
||||||
{
|
{
|
||||||
ExprUseVisitor {
|
ExprUseVisitor {
|
||||||
mc: mc::MemCategorizationContext::with_options(infcx, region_maps, options),
|
mc: mc::MemCategorizationContext::with_options(infcx, region_maps, options),
|
||||||
delegate: delegate
|
delegate,
|
||||||
|
param_env,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -318,7 +323,7 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> {
|
||||||
debug!("delegate_consume(consume_id={}, cmt={:?})",
|
debug!("delegate_consume(consume_id={}, cmt={:?})",
|
||||||
consume_id, cmt);
|
consume_id, cmt);
|
||||||
|
|
||||||
let mode = copy_or_move(self.mc.infcx, &cmt, DirectRefMove);
|
let mode = copy_or_move(self.mc.infcx, self.param_env, &cmt, DirectRefMove);
|
||||||
self.delegate.consume(consume_id, consume_span, cmt, mode);
|
self.delegate.consume(consume_id, consume_span, cmt, mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -797,7 +802,7 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> {
|
||||||
PatKind::Binding(hir::BindByRef(..), ..) =>
|
PatKind::Binding(hir::BindByRef(..), ..) =>
|
||||||
mode.lub(BorrowingMatch),
|
mode.lub(BorrowingMatch),
|
||||||
PatKind::Binding(hir::BindByValue(..), ..) => {
|
PatKind::Binding(hir::BindByValue(..), ..) => {
|
||||||
match copy_or_move(self.mc.infcx, &cmt_pat, PatBindingMove) {
|
match copy_or_move(self.mc.infcx, self.param_env, &cmt_pat, PatBindingMove) {
|
||||||
Copy => mode.lub(CopyingMatch),
|
Copy => mode.lub(CopyingMatch),
|
||||||
Move(..) => mode.lub(MovingMatch),
|
Move(..) => mode.lub(MovingMatch),
|
||||||
}
|
}
|
||||||
|
@ -813,10 +818,9 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> {
|
||||||
fn walk_pat(&mut self, cmt_discr: mc::cmt<'tcx>, pat: &hir::Pat, match_mode: MatchMode) {
|
fn walk_pat(&mut self, cmt_discr: mc::cmt<'tcx>, pat: &hir::Pat, match_mode: MatchMode) {
|
||||||
debug!("walk_pat cmt_discr={:?} pat={:?}", cmt_discr, pat);
|
debug!("walk_pat cmt_discr={:?} pat={:?}", cmt_discr, pat);
|
||||||
|
|
||||||
let tcx = &self.tcx();
|
let tcx = self.tcx();
|
||||||
let mc = &self.mc;
|
|
||||||
let infcx = self.mc.infcx;
|
let infcx = self.mc.infcx;
|
||||||
let delegate = &mut self.delegate;
|
let ExprUseVisitor { ref mc, ref mut delegate, param_env } = *self;
|
||||||
return_if_err!(mc.cat_pattern(cmt_discr.clone(), pat, |mc, cmt_pat, pat| {
|
return_if_err!(mc.cat_pattern(cmt_discr.clone(), pat, |mc, cmt_pat, pat| {
|
||||||
if let PatKind::Binding(bmode, def_id, ..) = pat.node {
|
if let PatKind::Binding(bmode, def_id, ..) = pat.node {
|
||||||
debug!("binding cmt_pat={:?} pat={:?} match_mode={:?}", cmt_pat, pat, match_mode);
|
debug!("binding cmt_pat={:?} pat={:?} match_mode={:?}", cmt_pat, pat, match_mode);
|
||||||
|
@ -840,7 +844,7 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
hir::BindByValue(..) => {
|
hir::BindByValue(..) => {
|
||||||
let mode = copy_or_move(infcx, &cmt_pat, PatBindingMove);
|
let mode = copy_or_move(infcx, param_env, &cmt_pat, PatBindingMove);
|
||||||
debug!("walk_pat binding consuming pat");
|
debug!("walk_pat binding consuming pat");
|
||||||
delegate.consume_pat(pat, cmt_pat, mode);
|
delegate.consume_pat(pat, cmt_pat, mode);
|
||||||
}
|
}
|
||||||
|
@ -899,7 +903,10 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> {
|
||||||
freevar.def));
|
freevar.def));
|
||||||
match upvar_capture {
|
match upvar_capture {
|
||||||
ty::UpvarCapture::ByValue => {
|
ty::UpvarCapture::ByValue => {
|
||||||
let mode = copy_or_move(self.mc.infcx, &cmt_var, CaptureMove);
|
let mode = copy_or_move(self.mc.infcx,
|
||||||
|
self.param_env,
|
||||||
|
&cmt_var,
|
||||||
|
CaptureMove);
|
||||||
self.delegate.consume(closure_expr.id, freevar.span, cmt_var, mode);
|
self.delegate.consume(closure_expr.id, freevar.span, cmt_var, mode);
|
||||||
}
|
}
|
||||||
ty::UpvarCapture::ByRef(upvar_borrow) => {
|
ty::UpvarCapture::ByRef(upvar_borrow) => {
|
||||||
|
@ -929,11 +936,12 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn copy_or_move<'a, 'gcx, 'tcx>(infcx: &InferCtxt<'a, 'gcx, 'tcx>,
|
fn copy_or_move<'a, 'gcx, 'tcx>(infcx: &InferCtxt<'a, 'gcx, 'tcx>,
|
||||||
|
param_env: ty::ParamEnv<'tcx>,
|
||||||
cmt: &mc::cmt<'tcx>,
|
cmt: &mc::cmt<'tcx>,
|
||||||
move_reason: MoveReason)
|
move_reason: MoveReason)
|
||||||
-> ConsumeMode
|
-> ConsumeMode
|
||||||
{
|
{
|
||||||
if infcx.type_moves_by_default(cmt.ty, cmt.span) {
|
if infcx.type_moves_by_default(param_env, cmt.ty, cmt.span) {
|
||||||
Move(move_reason)
|
Move(move_reason)
|
||||||
} else {
|
} else {
|
||||||
Copy
|
Copy
|
||||||
|
|
|
@ -10,10 +10,11 @@
|
||||||
|
|
||||||
//! See `README.md` for high-level documentation
|
//! See `README.md` for high-level documentation
|
||||||
|
|
||||||
use super::{SelectionContext, Obligation, ObligationCause};
|
|
||||||
|
|
||||||
use hir::def_id::{DefId, LOCAL_CRATE};
|
use hir::def_id::{DefId, LOCAL_CRATE};
|
||||||
|
use syntax_pos::DUMMY_SP;
|
||||||
|
use traits::{self, Normalized, SelectionContext, Obligation, ObligationCause, Reveal};
|
||||||
use ty::{self, Ty, TyCtxt};
|
use ty::{self, Ty, TyCtxt};
|
||||||
|
use ty::subst::Subst;
|
||||||
|
|
||||||
use infer::{InferCtxt, InferOk};
|
use infer::{InferCtxt, InferOk};
|
||||||
|
|
||||||
|
@ -37,6 +38,28 @@ pub fn overlapping_impls<'cx, 'gcx, 'tcx>(infcx: &InferCtxt<'cx, 'gcx, 'tcx>,
|
||||||
overlap(selcx, impl1_def_id, impl2_def_id)
|
overlap(selcx, impl1_def_id, impl2_def_id)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn with_fresh_ty_vars<'cx, 'gcx, 'tcx>(selcx: &mut SelectionContext<'cx, 'gcx, 'tcx>,
|
||||||
|
param_env: ty::ParamEnv<'tcx>,
|
||||||
|
impl_def_id: DefId)
|
||||||
|
-> ty::ImplHeader<'tcx>
|
||||||
|
{
|
||||||
|
let tcx = selcx.tcx();
|
||||||
|
let impl_substs = selcx.infcx().fresh_substs_for_item(DUMMY_SP, impl_def_id);
|
||||||
|
|
||||||
|
let header = ty::ImplHeader {
|
||||||
|
impl_def_id: impl_def_id,
|
||||||
|
self_ty: tcx.type_of(impl_def_id),
|
||||||
|
trait_ref: tcx.impl_trait_ref(impl_def_id),
|
||||||
|
predicates: tcx.predicates_of(impl_def_id).predicates
|
||||||
|
}.subst(tcx, impl_substs);
|
||||||
|
|
||||||
|
let Normalized { value: mut header, obligations } =
|
||||||
|
traits::normalize(selcx, param_env, ObligationCause::dummy(), &header);
|
||||||
|
|
||||||
|
header.predicates.extend(obligations.into_iter().map(|o| o.predicate));
|
||||||
|
header
|
||||||
|
}
|
||||||
|
|
||||||
/// Can both impl `a` and impl `b` be satisfied by a common type (including
|
/// Can both impl `a` and impl `b` be satisfied by a common type (including
|
||||||
/// `where` clauses)? If so, returns an `ImplHeader` that unifies the two impls.
|
/// `where` clauses)? If so, returns an `ImplHeader` that unifies the two impls.
|
||||||
fn overlap<'cx, 'gcx, 'tcx>(selcx: &mut SelectionContext<'cx, 'gcx, 'tcx>,
|
fn overlap<'cx, 'gcx, 'tcx>(selcx: &mut SelectionContext<'cx, 'gcx, 'tcx>,
|
||||||
|
@ -48,17 +71,24 @@ fn overlap<'cx, 'gcx, 'tcx>(selcx: &mut SelectionContext<'cx, 'gcx, 'tcx>,
|
||||||
a_def_id,
|
a_def_id,
|
||||||
b_def_id);
|
b_def_id);
|
||||||
|
|
||||||
let a_impl_header = ty::ImplHeader::with_fresh_ty_vars(selcx, a_def_id);
|
// For the purposes of this check, we don't bring any skolemized
|
||||||
let b_impl_header = ty::ImplHeader::with_fresh_ty_vars(selcx, b_def_id);
|
// types into scope; instead, we replace the generic types with
|
||||||
|
// fresh type variables, and hence we do our evaluations in an
|
||||||
|
// empty environment.
|
||||||
|
let param_env = ty::ParamEnv::empty(Reveal::UserFacing);
|
||||||
|
|
||||||
|
let a_impl_header = with_fresh_ty_vars(selcx, param_env, a_def_id);
|
||||||
|
let b_impl_header = with_fresh_ty_vars(selcx, param_env, b_def_id);
|
||||||
|
|
||||||
debug!("overlap: a_impl_header={:?}", a_impl_header);
|
debug!("overlap: a_impl_header={:?}", a_impl_header);
|
||||||
debug!("overlap: b_impl_header={:?}", b_impl_header);
|
debug!("overlap: b_impl_header={:?}", b_impl_header);
|
||||||
|
|
||||||
// Do `a` and `b` unify? If not, no overlap.
|
// Do `a` and `b` unify? If not, no overlap.
|
||||||
let obligations = match selcx.infcx().eq_impl_headers(true,
|
let obligations = match selcx.infcx().eq_impl_headers(true,
|
||||||
&ObligationCause::dummy(),
|
&ObligationCause::dummy(),
|
||||||
&a_impl_header,
|
param_env,
|
||||||
&b_impl_header) {
|
&a_impl_header,
|
||||||
|
&b_impl_header) {
|
||||||
Ok(InferOk { obligations, .. }) => {
|
Ok(InferOk { obligations, .. }) => {
|
||||||
obligations
|
obligations
|
||||||
}
|
}
|
||||||
|
@ -75,6 +105,7 @@ fn overlap<'cx, 'gcx, 'tcx>(selcx: &mut SelectionContext<'cx, 'gcx, 'tcx>,
|
||||||
.chain(&b_impl_header.predicates)
|
.chain(&b_impl_header.predicates)
|
||||||
.map(|p| infcx.resolve_type_vars_if_possible(p))
|
.map(|p| infcx.resolve_type_vars_if_possible(p))
|
||||||
.map(|p| Obligation { cause: ObligationCause::dummy(),
|
.map(|p| Obligation { cause: ObligationCause::dummy(),
|
||||||
|
param_env: param_env,
|
||||||
recursion_depth: 0,
|
recursion_depth: 0,
|
||||||
predicate: p })
|
predicate: p })
|
||||||
.chain(obligations)
|
.chain(obligations)
|
||||||
|
|
|
@ -179,12 +179,13 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
|
||||||
data);
|
data);
|
||||||
let normalized = super::normalize_projection_type(
|
let normalized = super::normalize_projection_type(
|
||||||
&mut selcx,
|
&mut selcx,
|
||||||
|
obligation.param_env,
|
||||||
data.projection_ty,
|
data.projection_ty,
|
||||||
obligation.cause.clone(),
|
obligation.cause.clone(),
|
||||||
0
|
0
|
||||||
);
|
);
|
||||||
if let Err(error) = self.eq_types(
|
if let Err(error) = self.eq_types(
|
||||||
false, &obligation.cause,
|
false, &obligation.cause, obligation.param_env,
|
||||||
data.ty, normalized.value
|
data.ty, normalized.value
|
||||||
) {
|
) {
|
||||||
values = Some(infer::ValuePairs::Types(ExpectedFound {
|
values = Some(infer::ValuePairs::Types(ExpectedFound {
|
||||||
|
@ -251,7 +252,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
|
||||||
-> Option<DefId>
|
-> Option<DefId>
|
||||||
{
|
{
|
||||||
let tcx = self.tcx;
|
let tcx = self.tcx;
|
||||||
|
let param_env = obligation.param_env;
|
||||||
let trait_ref = tcx.erase_late_bound_regions(&trait_ref);
|
let trait_ref = tcx.erase_late_bound_regions(&trait_ref);
|
||||||
let trait_self_ty = trait_ref.self_ty();
|
let trait_self_ty = trait_ref.self_ty();
|
||||||
|
|
||||||
|
@ -268,7 +269,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
|
||||||
|
|
||||||
let impl_self_ty = impl_trait_ref.self_ty();
|
let impl_self_ty = impl_trait_ref.self_ty();
|
||||||
|
|
||||||
if let Ok(..) = self.can_equate(&trait_self_ty, &impl_self_ty) {
|
if let Ok(..) = self.can_equate(param_env, &trait_self_ty, &impl_self_ty) {
|
||||||
self_match_impls.push(def_id);
|
self_match_impls.push(def_id);
|
||||||
|
|
||||||
if trait_ref.substs.types().skip(1)
|
if trait_ref.substs.types().skip(1)
|
||||||
|
@ -578,7 +579,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
|
||||||
|
|
||||||
// Try to report a help message
|
// Try to report a help message
|
||||||
if !trait_ref.has_infer_types() &&
|
if !trait_ref.has_infer_types() &&
|
||||||
self.predicate_can_apply(trait_ref) {
|
self.predicate_can_apply(obligation.param_env, trait_ref) {
|
||||||
// If a where-clause may be useful, remind the
|
// If a where-clause may be useful, remind the
|
||||||
// user that they can add it.
|
// user that they can add it.
|
||||||
//
|
//
|
||||||
|
@ -607,7 +608,8 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
|
||||||
ty::Predicate::Equate(ref predicate) => {
|
ty::Predicate::Equate(ref predicate) => {
|
||||||
let predicate = self.resolve_type_vars_if_possible(predicate);
|
let predicate = self.resolve_type_vars_if_possible(predicate);
|
||||||
let err = self.equality_predicate(&obligation.cause,
|
let err = self.equality_predicate(&obligation.cause,
|
||||||
&predicate).err().unwrap();
|
obligation.param_env,
|
||||||
|
&predicate).err().unwrap();
|
||||||
struct_span_err!(self.tcx.sess, span, E0278,
|
struct_span_err!(self.tcx.sess, span, E0278,
|
||||||
"the requirement `{}` is not satisfied (`{}`)",
|
"the requirement `{}` is not satisfied (`{}`)",
|
||||||
predicate, err)
|
predicate, err)
|
||||||
|
@ -936,7 +938,10 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
|
||||||
|
|
||||||
/// Returns whether the trait predicate may apply for *some* assignment
|
/// Returns whether the trait predicate may apply for *some* assignment
|
||||||
/// to the type parameters.
|
/// to the type parameters.
|
||||||
fn predicate_can_apply(&self, pred: ty::PolyTraitRef<'tcx>) -> bool {
|
fn predicate_can_apply(&self,
|
||||||
|
param_env: ty::ParamEnv<'tcx>,
|
||||||
|
pred: ty::PolyTraitRef<'tcx>)
|
||||||
|
-> bool {
|
||||||
struct ParamToVarFolder<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
|
struct ParamToVarFolder<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
|
||||||
infcx: &'a InferCtxt<'a, 'gcx, 'tcx>,
|
infcx: &'a InferCtxt<'a, 'gcx, 'tcx>,
|
||||||
var_map: FxHashMap<Ty<'tcx>, Ty<'tcx>>
|
var_map: FxHashMap<Ty<'tcx>, Ty<'tcx>>
|
||||||
|
@ -967,12 +972,14 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
|
||||||
|
|
||||||
let cleaned_pred = super::project::normalize(
|
let cleaned_pred = super::project::normalize(
|
||||||
&mut selcx,
|
&mut selcx,
|
||||||
|
param_env,
|
||||||
ObligationCause::dummy(),
|
ObligationCause::dummy(),
|
||||||
&cleaned_pred
|
&cleaned_pred
|
||||||
).value;
|
).value;
|
||||||
|
|
||||||
let obligation = Obligation::new(
|
let obligation = Obligation::new(
|
||||||
ObligationCause::dummy(),
|
ObligationCause::dummy(),
|
||||||
|
param_env,
|
||||||
cleaned_pred.to_predicate()
|
cleaned_pred.to_predicate()
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
@ -113,6 +113,7 @@ impl<'a, 'gcx, 'tcx> FulfillmentContext<'tcx> {
|
||||||
/// `projection_ty` again.
|
/// `projection_ty` again.
|
||||||
pub fn normalize_projection_type(&mut self,
|
pub fn normalize_projection_type(&mut self,
|
||||||
infcx: &InferCtxt<'a, 'gcx, 'tcx>,
|
infcx: &InferCtxt<'a, 'gcx, 'tcx>,
|
||||||
|
param_env: ty::ParamEnv<'tcx>,
|
||||||
projection_ty: ty::ProjectionTy<'tcx>,
|
projection_ty: ty::ProjectionTy<'tcx>,
|
||||||
cause: ObligationCause<'tcx>)
|
cause: ObligationCause<'tcx>)
|
||||||
-> Ty<'tcx>
|
-> Ty<'tcx>
|
||||||
|
@ -125,7 +126,11 @@ impl<'a, 'gcx, 'tcx> FulfillmentContext<'tcx> {
|
||||||
// FIXME(#20304) -- cache
|
// FIXME(#20304) -- cache
|
||||||
|
|
||||||
let mut selcx = SelectionContext::new(infcx);
|
let mut selcx = SelectionContext::new(infcx);
|
||||||
let normalized = project::normalize_projection_type(&mut selcx, projection_ty, cause, 0);
|
let normalized = project::normalize_projection_type(&mut selcx,
|
||||||
|
param_env,
|
||||||
|
projection_ty,
|
||||||
|
cause,
|
||||||
|
0);
|
||||||
|
|
||||||
for obligation in normalized.obligations {
|
for obligation in normalized.obligations {
|
||||||
self.register_predicate_obligation(infcx, obligation);
|
self.register_predicate_obligation(infcx, obligation);
|
||||||
|
@ -136,8 +141,12 @@ impl<'a, 'gcx, 'tcx> FulfillmentContext<'tcx> {
|
||||||
normalized.value
|
normalized.value
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Requires that `ty` must implement the trait with `def_id` in
|
||||||
|
/// the given environment. This trait must not have any type
|
||||||
|
/// parameters (except for `Self`).
|
||||||
pub fn register_bound(&mut self,
|
pub fn register_bound(&mut self,
|
||||||
infcx: &InferCtxt<'a, 'gcx, 'tcx>,
|
infcx: &InferCtxt<'a, 'gcx, 'tcx>,
|
||||||
|
param_env: ty::ParamEnv<'tcx>,
|
||||||
ty: Ty<'tcx>,
|
ty: Ty<'tcx>,
|
||||||
def_id: DefId,
|
def_id: DefId,
|
||||||
cause: ObligationCause<'tcx>)
|
cause: ObligationCause<'tcx>)
|
||||||
|
@ -149,6 +158,7 @@ impl<'a, 'gcx, 'tcx> FulfillmentContext<'tcx> {
|
||||||
self.register_predicate_obligation(infcx, Obligation {
|
self.register_predicate_obligation(infcx, Obligation {
|
||||||
cause: cause,
|
cause: cause,
|
||||||
recursion_depth: 0,
|
recursion_depth: 0,
|
||||||
|
param_env,
|
||||||
predicate: trait_ref.to_predicate()
|
predicate: trait_ref.to_predicate()
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -410,7 +420,7 @@ fn process_predicate<'a, 'gcx, 'tcx>(
|
||||||
}
|
}
|
||||||
|
|
||||||
ty::Predicate::Equate(ref binder) => {
|
ty::Predicate::Equate(ref binder) => {
|
||||||
match selcx.infcx().equality_predicate(&obligation.cause, binder) {
|
match selcx.infcx().equality_predicate(&obligation.cause, obligation.param_env, binder) {
|
||||||
Ok(InferOk { obligations, value: () }) => {
|
Ok(InferOk { obligations, value: () }) => {
|
||||||
Ok(Some(obligations))
|
Ok(Some(obligations))
|
||||||
},
|
},
|
||||||
|
@ -498,7 +508,7 @@ fn process_predicate<'a, 'gcx, 'tcx>(
|
||||||
}
|
}
|
||||||
|
|
||||||
ty::Predicate::WellFormed(ty) => {
|
ty::Predicate::WellFormed(ty) => {
|
||||||
match ty::wf::obligations(selcx.infcx(), obligation.cause.body_id,
|
match ty::wf::obligations(selcx.infcx(), obligation.param_env, obligation.cause.body_id,
|
||||||
ty, obligation.cause.span) {
|
ty, obligation.cause.span) {
|
||||||
None => {
|
None => {
|
||||||
pending_obligation.stalled_on = vec![ty];
|
pending_obligation.stalled_on = vec![ty];
|
||||||
|
@ -509,7 +519,7 @@ fn process_predicate<'a, 'gcx, 'tcx>(
|
||||||
}
|
}
|
||||||
|
|
||||||
ty::Predicate::Subtype(ref subtype) => {
|
ty::Predicate::Subtype(ref subtype) => {
|
||||||
match selcx.infcx().subtype_predicate(&obligation.cause, subtype) {
|
match selcx.infcx().subtype_predicate(&obligation.cause, obligation.param_env, subtype) {
|
||||||
None => {
|
None => {
|
||||||
// none means that both are unresolved
|
// none means that both are unresolved
|
||||||
pending_obligation.stalled_on = vec![subtype.skip_binder().a,
|
pending_obligation.stalled_on = vec![subtype.skip_binder().a,
|
||||||
|
|
|
@ -68,6 +68,7 @@ mod util;
|
||||||
#[derive(Clone, PartialEq, Eq)]
|
#[derive(Clone, PartialEq, Eq)]
|
||||||
pub struct Obligation<'tcx, T> {
|
pub struct Obligation<'tcx, T> {
|
||||||
pub cause: ObligationCause<'tcx>,
|
pub cause: ObligationCause<'tcx>,
|
||||||
|
pub param_env: ty::ParamEnv<'tcx>,
|
||||||
pub recursion_depth: usize,
|
pub recursion_depth: usize,
|
||||||
pub predicate: T,
|
pub predicate: T,
|
||||||
}
|
}
|
||||||
|
@ -359,10 +360,11 @@ pub struct VtableFnPointerData<'tcx, N> {
|
||||||
|
|
||||||
/// Creates predicate obligations from the generic bounds.
|
/// Creates predicate obligations from the generic bounds.
|
||||||
pub fn predicates_for_generics<'tcx>(cause: ObligationCause<'tcx>,
|
pub fn predicates_for_generics<'tcx>(cause: ObligationCause<'tcx>,
|
||||||
|
param_env: ty::ParamEnv<'tcx>,
|
||||||
generic_bounds: &ty::InstantiatedPredicates<'tcx>)
|
generic_bounds: &ty::InstantiatedPredicates<'tcx>)
|
||||||
-> PredicateObligations<'tcx>
|
-> PredicateObligations<'tcx>
|
||||||
{
|
{
|
||||||
util::predicates_for_generics(cause, 0, generic_bounds)
|
util::predicates_for_generics(cause, 0, param_env, generic_bounds)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Determines whether the type `ty` is known to meet `bound` and
|
/// Determines whether the type `ty` is known to meet `bound` and
|
||||||
|
@ -371,6 +373,7 @@ pub fn predicates_for_generics<'tcx>(cause: ObligationCause<'tcx>,
|
||||||
/// conservative towards *no impl*, which is the opposite of the
|
/// conservative towards *no impl*, which is the opposite of the
|
||||||
/// `evaluate` methods).
|
/// `evaluate` methods).
|
||||||
pub fn type_known_to_meet_bound<'a, 'gcx, 'tcx>(infcx: &InferCtxt<'a, 'gcx, 'tcx>,
|
pub fn type_known_to_meet_bound<'a, 'gcx, 'tcx>(infcx: &InferCtxt<'a, 'gcx, 'tcx>,
|
||||||
|
param_env: ty::ParamEnv<'tcx>,
|
||||||
ty: Ty<'tcx>,
|
ty: Ty<'tcx>,
|
||||||
def_id: DefId,
|
def_id: DefId,
|
||||||
span: Span)
|
span: Span)
|
||||||
|
@ -385,6 +388,7 @@ pub fn type_known_to_meet_bound<'a, 'gcx, 'tcx>(infcx: &InferCtxt<'a, 'gcx, 'tcx
|
||||||
substs: infcx.tcx.mk_substs_trait(ty, &[]),
|
substs: infcx.tcx.mk_substs_trait(ty, &[]),
|
||||||
};
|
};
|
||||||
let obligation = Obligation {
|
let obligation = Obligation {
|
||||||
|
param_env,
|
||||||
cause: ObligationCause::misc(span, ast::DUMMY_NODE_ID),
|
cause: ObligationCause::misc(span, ast::DUMMY_NODE_ID),
|
||||||
recursion_depth: 0,
|
recursion_depth: 0,
|
||||||
predicate: trait_ref.to_predicate(),
|
predicate: trait_ref.to_predicate(),
|
||||||
|
@ -408,7 +412,7 @@ pub fn type_known_to_meet_bound<'a, 'gcx, 'tcx>(infcx: &InferCtxt<'a, 'gcx, 'tcx
|
||||||
// anyhow).
|
// anyhow).
|
||||||
let cause = ObligationCause::misc(span, ast::DUMMY_NODE_ID);
|
let cause = ObligationCause::misc(span, ast::DUMMY_NODE_ID);
|
||||||
|
|
||||||
fulfill_cx.register_bound(infcx, ty, def_id, cause);
|
fulfill_cx.register_bound(infcx, param_env, ty, def_id, cause);
|
||||||
|
|
||||||
// Note: we only assume something is `Copy` if we can
|
// Note: we only assume something is `Copy` if we can
|
||||||
// *definitively* show that it implements `Copy`. Otherwise,
|
// *definitively* show that it implements `Copy`. Otherwise,
|
||||||
|
@ -480,22 +484,24 @@ pub fn normalize_param_env_or_error<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||||
let elaborated_env = ty::ParamEnv::new(tcx.intern_predicates(&predicates),
|
let elaborated_env = ty::ParamEnv::new(tcx.intern_predicates(&predicates),
|
||||||
unnormalized_env.reveal);
|
unnormalized_env.reveal);
|
||||||
|
|
||||||
tcx.infer_ctxt(elaborated_env).enter(|infcx| {
|
tcx.infer_ctxt(()).enter(|infcx| {
|
||||||
let predicates = match fully_normalize(
|
let predicates = match fully_normalize(
|
||||||
&infcx, cause,
|
&infcx,
|
||||||
// You would really want to pass infcx.param_env.caller_bounds here,
|
cause,
|
||||||
// but that is an interned slice, and fully_normalize takes &T and returns T, so
|
elaborated_env,
|
||||||
// without further refactoring, a slice can't be used. Luckily, we still have the
|
// You would really want to pass infcx.param_env.caller_bounds here,
|
||||||
// predicate vector from which we created the ParamEnv in infcx, so we
|
// but that is an interned slice, and fully_normalize takes &T and returns T, so
|
||||||
// can pass that instead. It's roundabout and a bit brittle, but this code path
|
// without further refactoring, a slice can't be used. Luckily, we still have the
|
||||||
// ought to be refactored anyway, and until then it saves us from having to copy.
|
// predicate vector from which we created the ParamEnv in infcx, so we
|
||||||
&predicates,
|
// can pass that instead. It's roundabout and a bit brittle, but this code path
|
||||||
|
// ought to be refactored anyway, and until then it saves us from having to copy.
|
||||||
|
&predicates,
|
||||||
) {
|
) {
|
||||||
Ok(predicates) => predicates,
|
Ok(predicates) => predicates,
|
||||||
Err(errors) => {
|
Err(errors) => {
|
||||||
infcx.report_fulfillment_errors(&errors);
|
infcx.report_fulfillment_errors(&errors);
|
||||||
// An unnormalized env is better than nothing.
|
// An unnormalized env is better than nothing.
|
||||||
return infcx.param_env;
|
return elaborated_env;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -517,17 +523,17 @@ pub fn normalize_param_env_or_error<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||||
// all things considered.
|
// all things considered.
|
||||||
tcx.sess.span_err(span, &fixup_err.to_string());
|
tcx.sess.span_err(span, &fixup_err.to_string());
|
||||||
// An unnormalized env is better than nothing.
|
// An unnormalized env is better than nothing.
|
||||||
return infcx.param_env;
|
return elaborated_env;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let predicates = match tcx.lift_to_global(&predicates) {
|
let predicates = match tcx.lift_to_global(&predicates) {
|
||||||
Some(predicates) => predicates,
|
Some(predicates) => predicates,
|
||||||
None => return infcx.param_env
|
None => return elaborated_env,
|
||||||
};
|
};
|
||||||
|
|
||||||
debug!("normalize_param_env_or_error: resolved predicates={:?}",
|
debug!("normalize_param_env_or_error: resolved predicates={:?}",
|
||||||
predicates);
|
predicates);
|
||||||
|
|
||||||
ty::ParamEnv::new(tcx.intern_predicates(&predicates), unnormalized_env.reveal)
|
ty::ParamEnv::new(tcx.intern_predicates(&predicates), unnormalized_env.reveal)
|
||||||
})
|
})
|
||||||
|
@ -535,6 +541,7 @@ pub fn normalize_param_env_or_error<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||||
|
|
||||||
pub fn fully_normalize<'a, 'gcx, 'tcx, T>(infcx: &InferCtxt<'a, 'gcx, 'tcx>,
|
pub fn fully_normalize<'a, 'gcx, 'tcx, T>(infcx: &InferCtxt<'a, 'gcx, 'tcx>,
|
||||||
cause: ObligationCause<'tcx>,
|
cause: ObligationCause<'tcx>,
|
||||||
|
param_env: ty::ParamEnv<'tcx>,
|
||||||
value: &T)
|
value: &T)
|
||||||
-> Result<T, Vec<FulfillmentError<'tcx>>>
|
-> Result<T, Vec<FulfillmentError<'tcx>>>
|
||||||
where T : TypeFoldable<'tcx>
|
where T : TypeFoldable<'tcx>
|
||||||
|
@ -558,7 +565,7 @@ pub fn fully_normalize<'a, 'gcx, 'tcx, T>(infcx: &InferCtxt<'a, 'gcx, 'tcx>,
|
||||||
let mut fulfill_cx = FulfillmentContext::new();
|
let mut fulfill_cx = FulfillmentContext::new();
|
||||||
|
|
||||||
let Normalized { value: normalized_value, obligations } =
|
let Normalized { value: normalized_value, obligations } =
|
||||||
project::normalize(selcx, cause, value);
|
project::normalize(selcx, param_env, cause, value);
|
||||||
debug!("fully_normalize: normalized_value={:?} obligations={:?}",
|
debug!("fully_normalize: normalized_value={:?} obligations={:?}",
|
||||||
normalized_value,
|
normalized_value,
|
||||||
obligations);
|
obligations);
|
||||||
|
@ -580,10 +587,10 @@ pub fn fully_normalize<'a, 'gcx, 'tcx, T>(infcx: &InferCtxt<'a, 'gcx, 'tcx>,
|
||||||
Ok(resolved_value)
|
Ok(resolved_value)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Normalizes the predicates and checks whether they hold. If this
|
/// Normalizes the predicates and checks whether they hold in an empty
|
||||||
/// returns false, then either normalize encountered an error or one
|
/// environment. If this returns false, then either normalize
|
||||||
/// of the predicates did not hold. Used when creating vtables to
|
/// encountered an error or one of the predicates did not hold. Used
|
||||||
/// check for unsatisfiable methods.
|
/// when creating vtables to check for unsatisfiable methods.
|
||||||
pub fn normalize_and_test_predicates<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
pub fn normalize_and_test_predicates<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||||
predicates: Vec<ty::Predicate<'tcx>>)
|
predicates: Vec<ty::Predicate<'tcx>>)
|
||||||
-> bool
|
-> bool
|
||||||
|
@ -591,17 +598,18 @@ pub fn normalize_and_test_predicates<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||||
debug!("normalize_and_test_predicates(predicates={:?})",
|
debug!("normalize_and_test_predicates(predicates={:?})",
|
||||||
predicates);
|
predicates);
|
||||||
|
|
||||||
tcx.infer_ctxt(Reveal::All).enter(|infcx| {
|
tcx.infer_ctxt(()).enter(|infcx| {
|
||||||
|
let param_env = ty::ParamEnv::empty(Reveal::All);
|
||||||
let mut selcx = SelectionContext::new(&infcx);
|
let mut selcx = SelectionContext::new(&infcx);
|
||||||
let mut fulfill_cx = FulfillmentContext::new();
|
let mut fulfill_cx = FulfillmentContext::new();
|
||||||
let cause = ObligationCause::dummy();
|
let cause = ObligationCause::dummy();
|
||||||
let Normalized { value: predicates, obligations } =
|
let Normalized { value: predicates, obligations } =
|
||||||
normalize(&mut selcx, cause.clone(), &predicates);
|
normalize(&mut selcx, param_env, cause.clone(), &predicates);
|
||||||
for obligation in obligations {
|
for obligation in obligations {
|
||||||
fulfill_cx.register_predicate_obligation(&infcx, obligation);
|
fulfill_cx.register_predicate_obligation(&infcx, obligation);
|
||||||
}
|
}
|
||||||
for predicate in predicates {
|
for predicate in predicates {
|
||||||
let obligation = Obligation::new(cause.clone(), predicate);
|
let obligation = Obligation::new(cause.clone(), param_env, predicate);
|
||||||
fulfill_cx.register_predicate_obligation(&infcx, obligation);
|
fulfill_cx.register_predicate_obligation(&infcx, obligation);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -663,30 +671,33 @@ pub fn get_vtable_methods<'a, 'tcx>(
|
||||||
|
|
||||||
impl<'tcx,O> Obligation<'tcx,O> {
|
impl<'tcx,O> Obligation<'tcx,O> {
|
||||||
pub fn new(cause: ObligationCause<'tcx>,
|
pub fn new(cause: ObligationCause<'tcx>,
|
||||||
trait_ref: O)
|
param_env: ty::ParamEnv<'tcx>,
|
||||||
|
predicate: O)
|
||||||
-> Obligation<'tcx, O>
|
-> Obligation<'tcx, O>
|
||||||
{
|
{
|
||||||
Obligation { cause: cause,
|
Obligation { cause, param_env, recursion_depth: 0, predicate }
|
||||||
recursion_depth: 0,
|
|
||||||
predicate: trait_ref }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn with_depth(cause: ObligationCause<'tcx>,
|
fn with_depth(cause: ObligationCause<'tcx>,
|
||||||
recursion_depth: usize,
|
recursion_depth: usize,
|
||||||
trait_ref: O)
|
param_env: ty::ParamEnv<'tcx>,
|
||||||
|
predicate: O)
|
||||||
-> Obligation<'tcx, O>
|
-> Obligation<'tcx, O>
|
||||||
{
|
{
|
||||||
Obligation { cause: cause,
|
Obligation { cause, param_env, recursion_depth, predicate }
|
||||||
recursion_depth: recursion_depth,
|
|
||||||
predicate: trait_ref }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn misc(span: Span, body_id: ast::NodeId, trait_ref: O) -> Obligation<'tcx, O> {
|
pub fn misc(span: Span,
|
||||||
Obligation::new(ObligationCause::misc(span, body_id), trait_ref)
|
body_id: ast::NodeId,
|
||||||
|
param_env: ty::ParamEnv<'tcx>,
|
||||||
|
trait_ref: O)
|
||||||
|
-> Obligation<'tcx, O> {
|
||||||
|
Obligation::new(ObligationCause::misc(span, body_id), param_env, trait_ref)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn with<P>(&self, value: P) -> Obligation<'tcx,P> {
|
pub fn with<P>(&self, value: P) -> Obligation<'tcx,P> {
|
||||||
Obligation { cause: self.cause.clone(),
|
Obligation { cause: self.cause.clone(),
|
||||||
|
param_env: self.param_env,
|
||||||
recursion_depth: self.recursion_depth,
|
recursion_depth: self.recursion_depth,
|
||||||
predicate: value }
|
predicate: value }
|
||||||
}
|
}
|
||||||
|
|
|
@ -168,7 +168,8 @@ fn project_and_unify_type<'cx, 'gcx, 'tcx>(
|
||||||
|
|
||||||
let Normalized { value: normalized_ty, mut obligations } =
|
let Normalized { value: normalized_ty, mut obligations } =
|
||||||
match opt_normalize_projection_type(selcx,
|
match opt_normalize_projection_type(selcx,
|
||||||
obligation.predicate.projection_ty.clone(),
|
obligation.param_env,
|
||||||
|
obligation.predicate.projection_ty,
|
||||||
obligation.cause.clone(),
|
obligation.cause.clone(),
|
||||||
obligation.recursion_depth) {
|
obligation.recursion_depth) {
|
||||||
Some(n) => n,
|
Some(n) => n,
|
||||||
|
@ -180,7 +181,11 @@ fn project_and_unify_type<'cx, 'gcx, 'tcx>(
|
||||||
obligations);
|
obligations);
|
||||||
|
|
||||||
let infcx = selcx.infcx();
|
let infcx = selcx.infcx();
|
||||||
match infcx.eq_types(true, &obligation.cause, normalized_ty, obligation.predicate.ty) {
|
match infcx.eq_types(true,
|
||||||
|
&obligation.cause,
|
||||||
|
obligation.param_env,
|
||||||
|
normalized_ty,
|
||||||
|
obligation.predicate.ty) {
|
||||||
Ok(InferOk { obligations: inferred_obligations, value: () }) => {
|
Ok(InferOk { obligations: inferred_obligations, value: () }) => {
|
||||||
obligations.extend(inferred_obligations);
|
obligations.extend(inferred_obligations);
|
||||||
Ok(Some(obligations))
|
Ok(Some(obligations))
|
||||||
|
@ -194,17 +199,19 @@ fn project_and_unify_type<'cx, 'gcx, 'tcx>(
|
||||||
/// combines the normalized result and any additional obligations that
|
/// combines the normalized result and any additional obligations that
|
||||||
/// were incurred as result.
|
/// were incurred as result.
|
||||||
pub fn normalize<'a, 'b, 'gcx, 'tcx, T>(selcx: &'a mut SelectionContext<'b, 'gcx, 'tcx>,
|
pub fn normalize<'a, 'b, 'gcx, 'tcx, T>(selcx: &'a mut SelectionContext<'b, 'gcx, 'tcx>,
|
||||||
|
param_env: ty::ParamEnv<'tcx>,
|
||||||
cause: ObligationCause<'tcx>,
|
cause: ObligationCause<'tcx>,
|
||||||
value: &T)
|
value: &T)
|
||||||
-> Normalized<'tcx, T>
|
-> Normalized<'tcx, T>
|
||||||
where T : TypeFoldable<'tcx>
|
where T : TypeFoldable<'tcx>
|
||||||
{
|
{
|
||||||
normalize_with_depth(selcx, cause, 0, value)
|
normalize_with_depth(selcx, param_env, cause, 0, value)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// As `normalize`, but with a custom depth.
|
/// As `normalize`, but with a custom depth.
|
||||||
pub fn normalize_with_depth<'a, 'b, 'gcx, 'tcx, T>(
|
pub fn normalize_with_depth<'a, 'b, 'gcx, 'tcx, T>(
|
||||||
selcx: &'a mut SelectionContext<'b, 'gcx, 'tcx>,
|
selcx: &'a mut SelectionContext<'b, 'gcx, 'tcx>,
|
||||||
|
param_env: ty::ParamEnv<'tcx>,
|
||||||
cause: ObligationCause<'tcx>,
|
cause: ObligationCause<'tcx>,
|
||||||
depth: usize,
|
depth: usize,
|
||||||
value: &T)
|
value: &T)
|
||||||
|
@ -213,7 +220,7 @@ pub fn normalize_with_depth<'a, 'b, 'gcx, 'tcx, T>(
|
||||||
where T : TypeFoldable<'tcx>
|
where T : TypeFoldable<'tcx>
|
||||||
{
|
{
|
||||||
debug!("normalize_with_depth(depth={}, value={:?})", depth, value);
|
debug!("normalize_with_depth(depth={}, value={:?})", depth, value);
|
||||||
let mut normalizer = AssociatedTypeNormalizer::new(selcx, cause, depth);
|
let mut normalizer = AssociatedTypeNormalizer::new(selcx, param_env, cause, depth);
|
||||||
let result = normalizer.fold(value);
|
let result = normalizer.fold(value);
|
||||||
debug!("normalize_with_depth: depth={} result={:?} with {} obligations",
|
debug!("normalize_with_depth: depth={} result={:?} with {} obligations",
|
||||||
depth, result, normalizer.obligations.len());
|
depth, result, normalizer.obligations.len());
|
||||||
|
@ -227,6 +234,7 @@ pub fn normalize_with_depth<'a, 'b, 'gcx, 'tcx, T>(
|
||||||
|
|
||||||
struct AssociatedTypeNormalizer<'a, 'b: 'a, 'gcx: 'b+'tcx, 'tcx: 'b> {
|
struct AssociatedTypeNormalizer<'a, 'b: 'a, 'gcx: 'b+'tcx, 'tcx: 'b> {
|
||||||
selcx: &'a mut SelectionContext<'b, 'gcx, 'tcx>,
|
selcx: &'a mut SelectionContext<'b, 'gcx, 'tcx>,
|
||||||
|
param_env: ty::ParamEnv<'tcx>,
|
||||||
cause: ObligationCause<'tcx>,
|
cause: ObligationCause<'tcx>,
|
||||||
obligations: Vec<PredicateObligation<'tcx>>,
|
obligations: Vec<PredicateObligation<'tcx>>,
|
||||||
depth: usize,
|
depth: usize,
|
||||||
|
@ -234,12 +242,14 @@ struct AssociatedTypeNormalizer<'a, 'b: 'a, 'gcx: 'b+'tcx, 'tcx: 'b> {
|
||||||
|
|
||||||
impl<'a, 'b, 'gcx, 'tcx> AssociatedTypeNormalizer<'a, 'b, 'gcx, 'tcx> {
|
impl<'a, 'b, 'gcx, 'tcx> AssociatedTypeNormalizer<'a, 'b, 'gcx, 'tcx> {
|
||||||
fn new(selcx: &'a mut SelectionContext<'b, 'gcx, 'tcx>,
|
fn new(selcx: &'a mut SelectionContext<'b, 'gcx, 'tcx>,
|
||||||
|
param_env: ty::ParamEnv<'tcx>,
|
||||||
cause: ObligationCause<'tcx>,
|
cause: ObligationCause<'tcx>,
|
||||||
depth: usize)
|
depth: usize)
|
||||||
-> AssociatedTypeNormalizer<'a, 'b, 'gcx, 'tcx>
|
-> AssociatedTypeNormalizer<'a, 'b, 'gcx, 'tcx>
|
||||||
{
|
{
|
||||||
AssociatedTypeNormalizer {
|
AssociatedTypeNormalizer {
|
||||||
selcx: selcx,
|
selcx: selcx,
|
||||||
|
param_env: param_env,
|
||||||
cause: cause,
|
cause: cause,
|
||||||
obligations: vec![],
|
obligations: vec![],
|
||||||
depth: depth,
|
depth: depth,
|
||||||
|
@ -305,6 +315,7 @@ impl<'a, 'b, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for AssociatedTypeNormalizer<'a,
|
||||||
|
|
||||||
let Normalized { value: normalized_ty, obligations } =
|
let Normalized { value: normalized_ty, obligations } =
|
||||||
normalize_projection_type(self.selcx,
|
normalize_projection_type(self.selcx,
|
||||||
|
self.param_env,
|
||||||
data.clone(),
|
data.clone(),
|
||||||
self.cause.clone(),
|
self.cause.clone(),
|
||||||
self.depth);
|
self.depth);
|
||||||
|
@ -344,12 +355,13 @@ impl<'tcx,T> Normalized<'tcx,T> {
|
||||||
/// obligation `<T as Trait>::Item == $X` for later.
|
/// obligation `<T as Trait>::Item == $X` for later.
|
||||||
pub fn normalize_projection_type<'a, 'b, 'gcx, 'tcx>(
|
pub fn normalize_projection_type<'a, 'b, 'gcx, 'tcx>(
|
||||||
selcx: &'a mut SelectionContext<'b, 'gcx, 'tcx>,
|
selcx: &'a mut SelectionContext<'b, 'gcx, 'tcx>,
|
||||||
|
param_env: ty::ParamEnv<'tcx>,
|
||||||
projection_ty: ty::ProjectionTy<'tcx>,
|
projection_ty: ty::ProjectionTy<'tcx>,
|
||||||
cause: ObligationCause<'tcx>,
|
cause: ObligationCause<'tcx>,
|
||||||
depth: usize)
|
depth: usize)
|
||||||
-> NormalizedTy<'tcx>
|
-> NormalizedTy<'tcx>
|
||||||
{
|
{
|
||||||
opt_normalize_projection_type(selcx, projection_ty.clone(), cause.clone(), depth)
|
opt_normalize_projection_type(selcx, param_env, projection_ty.clone(), cause.clone(), depth)
|
||||||
.unwrap_or_else(move || {
|
.unwrap_or_else(move || {
|
||||||
// if we bottom out in ambiguity, create a type variable
|
// if we bottom out in ambiguity, create a type variable
|
||||||
// and a deferred predicate to resolve this when more type
|
// and a deferred predicate to resolve this when more type
|
||||||
|
@ -366,7 +378,7 @@ pub fn normalize_projection_type<'a, 'b, 'gcx, 'tcx>(
|
||||||
ty: ty_var
|
ty: ty_var
|
||||||
});
|
});
|
||||||
let obligation = Obligation::with_depth(
|
let obligation = Obligation::with_depth(
|
||||||
cause, depth + 1, projection.to_predicate());
|
cause, depth + 1, param_env, projection.to_predicate());
|
||||||
Normalized {
|
Normalized {
|
||||||
value: ty_var,
|
value: ty_var,
|
||||||
obligations: vec![obligation]
|
obligations: vec![obligation]
|
||||||
|
@ -380,6 +392,7 @@ pub fn normalize_projection_type<'a, 'b, 'gcx, 'tcx>(
|
||||||
/// which indicates that there are unbound type variables.
|
/// which indicates that there are unbound type variables.
|
||||||
fn opt_normalize_projection_type<'a, 'b, 'gcx, 'tcx>(
|
fn opt_normalize_projection_type<'a, 'b, 'gcx, 'tcx>(
|
||||||
selcx: &'a mut SelectionContext<'b, 'gcx, 'tcx>,
|
selcx: &'a mut SelectionContext<'b, 'gcx, 'tcx>,
|
||||||
|
param_env: ty::ParamEnv<'tcx>,
|
||||||
projection_ty: ty::ProjectionTy<'tcx>,
|
projection_ty: ty::ProjectionTy<'tcx>,
|
||||||
cause: ObligationCause<'tcx>,
|
cause: ObligationCause<'tcx>,
|
||||||
depth: usize)
|
depth: usize)
|
||||||
|
@ -449,6 +462,7 @@ fn opt_normalize_projection_type<'a, 'b, 'gcx, 'tcx>(
|
||||||
let recursion_limit = selcx.tcx().sess.recursion_limit.get();
|
let recursion_limit = selcx.tcx().sess.recursion_limit.get();
|
||||||
let obligation = Obligation::with_depth(cause.clone(),
|
let obligation = Obligation::with_depth(cause.clone(),
|
||||||
recursion_limit,
|
recursion_limit,
|
||||||
|
param_env,
|
||||||
projection_ty);
|
projection_ty);
|
||||||
selcx.infcx().report_overflow_error(&obligation, false);
|
selcx.infcx().report_overflow_error(&obligation, false);
|
||||||
}
|
}
|
||||||
|
@ -464,11 +478,11 @@ fn opt_normalize_projection_type<'a, 'b, 'gcx, 'tcx>(
|
||||||
Err(ProjectionCacheEntry::Error) => {
|
Err(ProjectionCacheEntry::Error) => {
|
||||||
debug!("opt_normalize_projection_type: \
|
debug!("opt_normalize_projection_type: \
|
||||||
found error");
|
found error");
|
||||||
return Some(normalize_to_error(selcx, projection_ty, cause, depth));
|
return Some(normalize_to_error(selcx, param_env, projection_ty, cause, depth));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let obligation = Obligation::with_depth(cause.clone(), depth, projection_ty.clone());
|
let obligation = Obligation::with_depth(cause.clone(), depth, param_env, projection_ty);
|
||||||
match project_type(selcx, &obligation) {
|
match project_type(selcx, &obligation) {
|
||||||
Ok(ProjectedTy::Progress(Progress { ty: projected_ty,
|
Ok(ProjectedTy::Progress(Progress { ty: projected_ty,
|
||||||
mut obligations,
|
mut obligations,
|
||||||
|
@ -489,7 +503,7 @@ fn opt_normalize_projection_type<'a, 'b, 'gcx, 'tcx>(
|
||||||
cacheable);
|
cacheable);
|
||||||
|
|
||||||
let result = if projected_ty.has_projection_types() {
|
let result = if projected_ty.has_projection_types() {
|
||||||
let mut normalizer = AssociatedTypeNormalizer::new(selcx, cause, depth+1);
|
let mut normalizer = AssociatedTypeNormalizer::new(selcx, param_env, cause, depth+1);
|
||||||
let normalized_ty = normalizer.fold(&projected_ty);
|
let normalized_ty = normalizer.fold(&projected_ty);
|
||||||
|
|
||||||
debug!("opt_normalize_projection_type: \
|
debug!("opt_normalize_projection_type: \
|
||||||
|
@ -540,7 +554,7 @@ fn opt_normalize_projection_type<'a, 'b, 'gcx, 'tcx>(
|
||||||
|
|
||||||
infcx.projection_cache.borrow_mut()
|
infcx.projection_cache.borrow_mut()
|
||||||
.error(projection_ty);
|
.error(projection_ty);
|
||||||
Some(normalize_to_error(selcx, projection_ty, cause, depth))
|
Some(normalize_to_error(selcx, param_env, projection_ty, cause, depth))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -565,6 +579,7 @@ fn opt_normalize_projection_type<'a, 'b, 'gcx, 'tcx>(
|
||||||
/// because it contains `[type error]`. Yuck! (See issue #29857 for
|
/// because it contains `[type error]`. Yuck! (See issue #29857 for
|
||||||
/// one case where this arose.)
|
/// one case where this arose.)
|
||||||
fn normalize_to_error<'a, 'gcx, 'tcx>(selcx: &mut SelectionContext<'a, 'gcx, 'tcx>,
|
fn normalize_to_error<'a, 'gcx, 'tcx>(selcx: &mut SelectionContext<'a, 'gcx, 'tcx>,
|
||||||
|
param_env: ty::ParamEnv<'tcx>,
|
||||||
projection_ty: ty::ProjectionTy<'tcx>,
|
projection_ty: ty::ProjectionTy<'tcx>,
|
||||||
cause: ObligationCause<'tcx>,
|
cause: ObligationCause<'tcx>,
|
||||||
depth: usize)
|
depth: usize)
|
||||||
|
@ -573,6 +588,7 @@ fn normalize_to_error<'a, 'gcx, 'tcx>(selcx: &mut SelectionContext<'a, 'gcx, 'tc
|
||||||
let trait_ref = projection_ty.trait_ref.to_poly_trait_ref();
|
let trait_ref = projection_ty.trait_ref.to_poly_trait_ref();
|
||||||
let trait_obligation = Obligation { cause: cause,
|
let trait_obligation = Obligation { cause: cause,
|
||||||
recursion_depth: depth,
|
recursion_depth: depth,
|
||||||
|
param_env,
|
||||||
predicate: trait_ref.to_predicate() };
|
predicate: trait_ref.to_predicate() };
|
||||||
let tcx = selcx.infcx().tcx;
|
let tcx = selcx.infcx().tcx;
|
||||||
let def_id = tcx.associated_items(projection_ty.trait_ref.def_id).find(|i|
|
let def_id = tcx.associated_items(projection_ty.trait_ref.def_id).find(|i|
|
||||||
|
@ -746,13 +762,12 @@ fn assemble_candidates_from_param_env<'cx, 'gcx, 'tcx>(
|
||||||
candidate_set: &mut ProjectionTyCandidateSet<'tcx>)
|
candidate_set: &mut ProjectionTyCandidateSet<'tcx>)
|
||||||
{
|
{
|
||||||
debug!("assemble_candidates_from_param_env(..)");
|
debug!("assemble_candidates_from_param_env(..)");
|
||||||
let env_predicates = selcx.param_env().caller_bounds.iter().cloned();
|
|
||||||
assemble_candidates_from_predicates(selcx,
|
assemble_candidates_from_predicates(selcx,
|
||||||
obligation,
|
obligation,
|
||||||
obligation_trait_ref,
|
obligation_trait_ref,
|
||||||
candidate_set,
|
candidate_set,
|
||||||
ProjectionTyCandidate::ParamEnv,
|
ProjectionTyCandidate::ParamEnv,
|
||||||
env_predicates);
|
obligation.param_env.caller_bounds.iter().cloned());
|
||||||
}
|
}
|
||||||
|
|
||||||
/// In the case of a nested projection like <<A as Foo>::FooT as Bar>::BarT, we may find
|
/// In the case of a nested projection like <<A as Foo>::FooT as Bar>::BarT, we may find
|
||||||
|
@ -807,7 +822,7 @@ fn assemble_candidates_from_predicates<'cx, 'gcx, 'tcx, I>(
|
||||||
candidate_set: &mut ProjectionTyCandidateSet<'tcx>,
|
candidate_set: &mut ProjectionTyCandidateSet<'tcx>,
|
||||||
ctor: fn(ty::PolyProjectionPredicate<'tcx>) -> ProjectionTyCandidate<'tcx>,
|
ctor: fn(ty::PolyProjectionPredicate<'tcx>) -> ProjectionTyCandidate<'tcx>,
|
||||||
env_predicates: I)
|
env_predicates: I)
|
||||||
where I: Iterator<Item=ty::Predicate<'tcx>>
|
where I: IntoIterator<Item=ty::Predicate<'tcx>>
|
||||||
{
|
{
|
||||||
debug!("assemble_candidates_from_predicates(obligation={:?})",
|
debug!("assemble_candidates_from_predicates(obligation={:?})",
|
||||||
obligation);
|
obligation);
|
||||||
|
@ -827,6 +842,7 @@ fn assemble_candidates_from_predicates<'cx, 'gcx, 'tcx, I>(
|
||||||
obligation_trait_ref.to_poly_trait_ref();
|
obligation_trait_ref.to_poly_trait_ref();
|
||||||
infcx.sub_poly_trait_refs(false,
|
infcx.sub_poly_trait_refs(false,
|
||||||
obligation.cause.clone(),
|
obligation.cause.clone(),
|
||||||
|
obligation.param_env,
|
||||||
data_poly_trait_ref,
|
data_poly_trait_ref,
|
||||||
obligation_poly_trait_ref)
|
obligation_poly_trait_ref)
|
||||||
.map(|InferOk { obligations: _, value: () }| {
|
.map(|InferOk { obligations: _, value: () }| {
|
||||||
|
@ -936,7 +952,7 @@ fn assemble_candidates_from_impls<'cx, 'gcx, 'tcx>(
|
||||||
// get a result which isn't correct for all monomorphizations.
|
// get a result which isn't correct for all monomorphizations.
|
||||||
let new_candidate = if !is_default {
|
let new_candidate = if !is_default {
|
||||||
Some(ProjectionTyCandidate::Select)
|
Some(ProjectionTyCandidate::Select)
|
||||||
} else if selcx.projection_mode() == Reveal::All {
|
} else if obligation.param_env.reveal == Reveal::All {
|
||||||
assert!(!poly_trait_ref.needs_infer());
|
assert!(!poly_trait_ref.needs_infer());
|
||||||
if !poly_trait_ref.needs_subst() {
|
if !poly_trait_ref.needs_subst() {
|
||||||
Some(ProjectionTyCandidate::Select)
|
Some(ProjectionTyCandidate::Select)
|
||||||
|
@ -1096,6 +1112,7 @@ fn confirm_object_candidate<'cx, 'gcx, 'tcx>(
|
||||||
selcx.infcx().probe(|_| {
|
selcx.infcx().probe(|_| {
|
||||||
selcx.infcx().sub_poly_trait_refs(false,
|
selcx.infcx().sub_poly_trait_refs(false,
|
||||||
obligation.cause.clone(),
|
obligation.cause.clone(),
|
||||||
|
obligation.param_env,
|
||||||
data_poly_trait_ref,
|
data_poly_trait_ref,
|
||||||
obligation_poly_trait_ref).is_ok()
|
obligation_poly_trait_ref).is_ok()
|
||||||
})
|
})
|
||||||
|
@ -1143,6 +1160,7 @@ fn confirm_closure_candidate<'cx, 'gcx, 'tcx>(
|
||||||
value: closure_type,
|
value: closure_type,
|
||||||
obligations
|
obligations
|
||||||
} = normalize_with_depth(selcx,
|
} = normalize_with_depth(selcx,
|
||||||
|
obligation.param_env,
|
||||||
obligation.cause.clone(),
|
obligation.cause.clone(),
|
||||||
obligation.recursion_depth+1,
|
obligation.recursion_depth+1,
|
||||||
&closure_type);
|
&closure_type);
|
||||||
|
@ -1203,8 +1221,9 @@ fn confirm_param_env_candidate<'cx, 'gcx, 'tcx>(
|
||||||
{
|
{
|
||||||
let infcx = selcx.infcx();
|
let infcx = selcx.infcx();
|
||||||
let cause = obligation.cause.clone();
|
let cause = obligation.cause.clone();
|
||||||
|
let param_env = obligation.param_env;
|
||||||
let trait_ref = obligation.predicate.trait_ref;
|
let trait_ref = obligation.predicate.trait_ref;
|
||||||
match infcx.match_poly_projection_predicate(cause, poly_projection, trait_ref) {
|
match infcx.match_poly_projection_predicate(cause, param_env, poly_projection, trait_ref) {
|
||||||
Ok(InferOk { value: ty_match, obligations }) => {
|
Ok(InferOk { value: ty_match, obligations }) => {
|
||||||
Progress {
|
Progress {
|
||||||
ty: ty_match.value,
|
ty: ty_match.value,
|
||||||
|
@ -1233,6 +1252,7 @@ fn confirm_impl_candidate<'cx, 'gcx, 'tcx>(
|
||||||
let VtableImplData { substs, nested, impl_def_id } = impl_vtable;
|
let VtableImplData { substs, nested, impl_def_id } = impl_vtable;
|
||||||
|
|
||||||
let tcx = selcx.tcx();
|
let tcx = selcx.tcx();
|
||||||
|
let param_env = obligation.param_env;
|
||||||
let assoc_ty = assoc_ty_def(selcx, impl_def_id, obligation.predicate.item_name(tcx));
|
let assoc_ty = assoc_ty_def(selcx, impl_def_id, obligation.predicate.item_name(tcx));
|
||||||
|
|
||||||
let ty = if !assoc_ty.item.defaultness.has_value() {
|
let ty = if !assoc_ty.item.defaultness.has_value() {
|
||||||
|
@ -1247,7 +1267,7 @@ fn confirm_impl_candidate<'cx, 'gcx, 'tcx>(
|
||||||
} else {
|
} else {
|
||||||
tcx.type_of(assoc_ty.item.def_id)
|
tcx.type_of(assoc_ty.item.def_id)
|
||||||
};
|
};
|
||||||
let substs = translate_substs(selcx.infcx(), impl_def_id, substs, assoc_ty.node);
|
let substs = translate_substs(selcx.infcx(), param_env, impl_def_id, substs, assoc_ty.node);
|
||||||
Progress {
|
Progress {
|
||||||
ty: ty.subst(tcx, substs),
|
ty: ty.subst(tcx, substs),
|
||||||
obligations: nested,
|
obligations: nested,
|
||||||
|
|
|
@ -21,7 +21,6 @@ use super::{PredicateObligation, TraitObligation, ObligationCause};
|
||||||
use super::{ObligationCauseCode, BuiltinDerivedObligation, ImplDerivedObligation};
|
use super::{ObligationCauseCode, BuiltinDerivedObligation, ImplDerivedObligation};
|
||||||
use super::{SelectionError, Unimplemented, OutputTypeParameterMismatch};
|
use super::{SelectionError, Unimplemented, OutputTypeParameterMismatch};
|
||||||
use super::{ObjectCastObligation, Obligation};
|
use super::{ObjectCastObligation, Obligation};
|
||||||
use super::Reveal;
|
|
||||||
use super::TraitNotObjectSafe;
|
use super::TraitNotObjectSafe;
|
||||||
use super::Selection;
|
use super::Selection;
|
||||||
use super::SelectionResult;
|
use super::SelectionResult;
|
||||||
|
@ -315,18 +314,10 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
|
||||||
self.infcx.tcx
|
self.infcx.tcx
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn param_env(&self) -> ty::ParamEnv<'gcx> {
|
|
||||||
self.infcx.param_env()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn closure_typer(&self) -> &'cx InferCtxt<'cx, 'gcx, 'tcx> {
|
pub fn closure_typer(&self) -> &'cx InferCtxt<'cx, 'gcx, 'tcx> {
|
||||||
self.infcx
|
self.infcx
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn projection_mode(&self) -> Reveal {
|
|
||||||
self.param_env().reveal
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Wraps the inference context's in_snapshot s.t. snapshot handling is only from the selection
|
/// Wraps the inference context's in_snapshot s.t. snapshot handling is only from the selection
|
||||||
/// context's self.
|
/// context's self.
|
||||||
fn in_snapshot<R, F>(&mut self, f: F) -> R
|
fn in_snapshot<R, F>(&mut self, f: F) -> R
|
||||||
|
@ -540,7 +531,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
|
||||||
|
|
||||||
ty::Predicate::Equate(ref p) => {
|
ty::Predicate::Equate(ref p) => {
|
||||||
// does this code ever run?
|
// does this code ever run?
|
||||||
match self.infcx.equality_predicate(&obligation.cause, p) {
|
match self.infcx.equality_predicate(&obligation.cause, obligation.param_env, p) {
|
||||||
Ok(InferOk { obligations, .. }) => {
|
Ok(InferOk { obligations, .. }) => {
|
||||||
self.inferred_obligations.extend(obligations);
|
self.inferred_obligations.extend(obligations);
|
||||||
EvaluatedToOk
|
EvaluatedToOk
|
||||||
|
@ -551,7 +542,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
|
||||||
|
|
||||||
ty::Predicate::Subtype(ref p) => {
|
ty::Predicate::Subtype(ref p) => {
|
||||||
// does this code ever run?
|
// does this code ever run?
|
||||||
match self.infcx.subtype_predicate(&obligation.cause, p) {
|
match self.infcx.subtype_predicate(&obligation.cause, obligation.param_env, p) {
|
||||||
Some(Ok(InferOk { obligations, .. })) => {
|
Some(Ok(InferOk { obligations, .. })) => {
|
||||||
self.inferred_obligations.extend(obligations);
|
self.inferred_obligations.extend(obligations);
|
||||||
EvaluatedToOk
|
EvaluatedToOk
|
||||||
|
@ -562,7 +553,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
ty::Predicate::WellFormed(ty) => {
|
ty::Predicate::WellFormed(ty) => {
|
||||||
match ty::wf::obligations(self.infcx, obligation.cause.body_id,
|
match ty::wf::obligations(self.infcx, obligation.param_env, obligation.cause.body_id,
|
||||||
ty, obligation.cause.span) {
|
ty, obligation.cause.span) {
|
||||||
Some(obligations) =>
|
Some(obligations) =>
|
||||||
self.evaluate_predicates_recursively(previous_stack, obligations.iter()),
|
self.evaluate_predicates_recursively(previous_stack, obligations.iter()),
|
||||||
|
@ -628,7 +619,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
|
||||||
|
|
||||||
let stack = self.push_stack(previous_stack, obligation);
|
let stack = self.push_stack(previous_stack, obligation);
|
||||||
let fresh_trait_ref = stack.fresh_trait_ref;
|
let fresh_trait_ref = stack.fresh_trait_ref;
|
||||||
if let Some(result) = self.check_evaluation_cache(fresh_trait_ref) {
|
if let Some(result) = self.check_evaluation_cache(obligation.param_env, fresh_trait_ref) {
|
||||||
debug!("CACHE HIT: EVAL({:?})={:?}",
|
debug!("CACHE HIT: EVAL({:?})={:?}",
|
||||||
fresh_trait_ref,
|
fresh_trait_ref,
|
||||||
result);
|
result);
|
||||||
|
@ -640,7 +631,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
|
||||||
debug!("CACHE MISS: EVAL({:?})={:?}",
|
debug!("CACHE MISS: EVAL({:?})={:?}",
|
||||||
fresh_trait_ref,
|
fresh_trait_ref,
|
||||||
result);
|
result);
|
||||||
self.insert_evaluation_cache(fresh_trait_ref, result);
|
self.insert_evaluation_cache(obligation.param_env, fresh_trait_ref, result);
|
||||||
|
|
||||||
result
|
result
|
||||||
}
|
}
|
||||||
|
@ -751,10 +742,12 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
|
||||||
result
|
result
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_evaluation_cache(&self, trait_ref: ty::PolyTraitRef<'tcx>)
|
fn check_evaluation_cache(&self,
|
||||||
|
param_env: ty::ParamEnv<'tcx>,
|
||||||
|
trait_ref: ty::PolyTraitRef<'tcx>)
|
||||||
-> Option<EvaluationResult>
|
-> Option<EvaluationResult>
|
||||||
{
|
{
|
||||||
if self.can_use_global_caches() {
|
if self.can_use_global_caches(param_env) {
|
||||||
let cache = self.tcx().evaluation_cache.hashmap.borrow();
|
let cache = self.tcx().evaluation_cache.hashmap.borrow();
|
||||||
if let Some(cached) = cache.get(&trait_ref) {
|
if let Some(cached) = cache.get(&trait_ref) {
|
||||||
return Some(cached.clone());
|
return Some(cached.clone());
|
||||||
|
@ -764,6 +757,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn insert_evaluation_cache(&mut self,
|
fn insert_evaluation_cache(&mut self,
|
||||||
|
param_env: ty::ParamEnv<'tcx>,
|
||||||
trait_ref: ty::PolyTraitRef<'tcx>,
|
trait_ref: ty::PolyTraitRef<'tcx>,
|
||||||
result: EvaluationResult)
|
result: EvaluationResult)
|
||||||
{
|
{
|
||||||
|
@ -778,7 +772,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if self.can_use_global_caches() {
|
if self.can_use_global_caches(param_env) {
|
||||||
let mut cache = self.tcx().evaluation_cache.hashmap.borrow_mut();
|
let mut cache = self.tcx().evaluation_cache.hashmap.borrow_mut();
|
||||||
if let Some(trait_ref) = self.tcx().lift_to_global(&trait_ref) {
|
if let Some(trait_ref) = self.tcx().lift_to_global(&trait_ref) {
|
||||||
cache.insert(trait_ref, result);
|
cache.insert(trait_ref, result);
|
||||||
|
@ -819,7 +813,8 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
|
||||||
stack);
|
stack);
|
||||||
assert!(!stack.obligation.predicate.has_escaping_regions());
|
assert!(!stack.obligation.predicate.has_escaping_regions());
|
||||||
|
|
||||||
if let Some(c) = self.check_candidate_cache(&cache_fresh_trait_pred) {
|
if let Some(c) = self.check_candidate_cache(stack.obligation.param_env,
|
||||||
|
&cache_fresh_trait_pred) {
|
||||||
debug!("CACHE HIT: SELECT({:?})={:?}",
|
debug!("CACHE HIT: SELECT({:?})={:?}",
|
||||||
cache_fresh_trait_pred,
|
cache_fresh_trait_pred,
|
||||||
c);
|
c);
|
||||||
|
@ -832,7 +827,9 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
|
||||||
if self.should_update_candidate_cache(&cache_fresh_trait_pred, &candidate) {
|
if self.should_update_candidate_cache(&cache_fresh_trait_pred, &candidate) {
|
||||||
debug!("CACHE MISS: SELECT({:?})={:?}",
|
debug!("CACHE MISS: SELECT({:?})={:?}",
|
||||||
cache_fresh_trait_pred, candidate);
|
cache_fresh_trait_pred, candidate);
|
||||||
self.insert_candidate_cache(cache_fresh_trait_pred, candidate.clone());
|
self.insert_candidate_cache(stack.obligation.param_env,
|
||||||
|
cache_fresh_trait_pred,
|
||||||
|
candidate.clone());
|
||||||
}
|
}
|
||||||
|
|
||||||
candidate
|
candidate
|
||||||
|
@ -995,7 +992,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
|
||||||
/// Returns true if the global caches can be used.
|
/// Returns true if the global caches can be used.
|
||||||
/// Do note that if the type itself is not in the
|
/// Do note that if the type itself is not in the
|
||||||
/// global tcx, the local caches will be used.
|
/// global tcx, the local caches will be used.
|
||||||
fn can_use_global_caches(&self) -> bool {
|
fn can_use_global_caches(&self, param_env: ty::ParamEnv<'tcx>) -> bool {
|
||||||
// If there are any where-clauses in scope, then we always use
|
// If there are any where-clauses in scope, then we always use
|
||||||
// a cache local to this particular scope. Otherwise, we
|
// a cache local to this particular scope. Otherwise, we
|
||||||
// switch to a global cache. We used to try and draw
|
// switch to a global cache. We used to try and draw
|
||||||
|
@ -1003,7 +1000,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
|
||||||
// annoying and weird bugs like #22019 and #18290. This simple
|
// annoying and weird bugs like #22019 and #18290. This simple
|
||||||
// rule seems to be pretty clearly safe and also still retains
|
// rule seems to be pretty clearly safe and also still retains
|
||||||
// a very high hit rate (~95% when compiling rustc).
|
// a very high hit rate (~95% when compiling rustc).
|
||||||
if !self.param_env().caller_bounds.is_empty() {
|
if !param_env.caller_bounds.is_empty() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1023,11 +1020,12 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_candidate_cache(&mut self,
|
fn check_candidate_cache(&mut self,
|
||||||
|
param_env: ty::ParamEnv<'tcx>,
|
||||||
cache_fresh_trait_pred: &ty::PolyTraitPredicate<'tcx>)
|
cache_fresh_trait_pred: &ty::PolyTraitPredicate<'tcx>)
|
||||||
-> Option<SelectionResult<'tcx, SelectionCandidate<'tcx>>>
|
-> Option<SelectionResult<'tcx, SelectionCandidate<'tcx>>>
|
||||||
{
|
{
|
||||||
let trait_ref = &cache_fresh_trait_pred.0.trait_ref;
|
let trait_ref = &cache_fresh_trait_pred.0.trait_ref;
|
||||||
if self.can_use_global_caches() {
|
if self.can_use_global_caches(param_env) {
|
||||||
let cache = self.tcx().selection_cache.hashmap.borrow();
|
let cache = self.tcx().selection_cache.hashmap.borrow();
|
||||||
if let Some(cached) = cache.get(&trait_ref) {
|
if let Some(cached) = cache.get(&trait_ref) {
|
||||||
return Some(cached.clone());
|
return Some(cached.clone());
|
||||||
|
@ -1037,11 +1035,12 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn insert_candidate_cache(&mut self,
|
fn insert_candidate_cache(&mut self,
|
||||||
|
param_env: ty::ParamEnv<'tcx>,
|
||||||
cache_fresh_trait_pred: ty::PolyTraitPredicate<'tcx>,
|
cache_fresh_trait_pred: ty::PolyTraitPredicate<'tcx>,
|
||||||
candidate: SelectionResult<'tcx, SelectionCandidate<'tcx>>)
|
candidate: SelectionResult<'tcx, SelectionCandidate<'tcx>>)
|
||||||
{
|
{
|
||||||
let trait_ref = cache_fresh_trait_pred.0.trait_ref;
|
let trait_ref = cache_fresh_trait_pred.0.trait_ref;
|
||||||
if self.can_use_global_caches() {
|
if self.can_use_global_caches(param_env) {
|
||||||
let mut cache = self.tcx().selection_cache.hashmap.borrow_mut();
|
let mut cache = self.tcx().selection_cache.hashmap.borrow_mut();
|
||||||
if let Some(trait_ref) = self.tcx().lift_to_global(&trait_ref) {
|
if let Some(trait_ref) = self.tcx().lift_to_global(&trait_ref) {
|
||||||
if let Some(candidate) = self.tcx().lift_to_global(&candidate) {
|
if let Some(candidate) = self.tcx().lift_to_global(&candidate) {
|
||||||
|
@ -1099,6 +1098,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
|
||||||
{
|
{
|
||||||
let TraitObligationStack { obligation, .. } = *stack;
|
let TraitObligationStack { obligation, .. } = *stack;
|
||||||
let ref obligation = Obligation {
|
let ref obligation = Obligation {
|
||||||
|
param_env: obligation.param_env,
|
||||||
cause: obligation.cause.clone(),
|
cause: obligation.cause.clone(),
|
||||||
recursion_depth: obligation.recursion_depth,
|
recursion_depth: obligation.recursion_depth,
|
||||||
predicate: self.infcx().resolve_type_vars_if_possible(&obligation.predicate)
|
predicate: self.infcx().resolve_type_vars_if_possible(&obligation.predicate)
|
||||||
|
@ -1272,6 +1272,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
|
||||||
let cause = obligation.cause.clone();
|
let cause = obligation.cause.clone();
|
||||||
match self.infcx.sub_poly_trait_refs(false,
|
match self.infcx.sub_poly_trait_refs(false,
|
||||||
cause,
|
cause,
|
||||||
|
obligation.param_env,
|
||||||
trait_bound.clone(),
|
trait_bound.clone(),
|
||||||
ty::Binder(skol_trait_ref.clone())) {
|
ty::Binder(skol_trait_ref.clone())) {
|
||||||
Ok(InferOk { obligations, .. }) => {
|
Ok(InferOk { obligations, .. }) => {
|
||||||
|
@ -1296,9 +1297,9 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
|
||||||
stack.obligation);
|
stack.obligation);
|
||||||
|
|
||||||
let all_bounds =
|
let all_bounds =
|
||||||
self.param_env().caller_bounds
|
stack.obligation.param_env.caller_bounds
|
||||||
.iter()
|
.iter()
|
||||||
.filter_map(|o| o.to_opt_poly_trait_ref());
|
.filter_map(|o| o.to_opt_poly_trait_ref());
|
||||||
|
|
||||||
// micro-optimization: filter out predicates relating to different
|
// micro-optimization: filter out predicates relating to different
|
||||||
// traits.
|
// traits.
|
||||||
|
@ -1953,6 +1954,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn collect_predicates_for_types(&mut self,
|
fn collect_predicates_for_types(&mut self,
|
||||||
|
param_env: ty::ParamEnv<'tcx>,
|
||||||
cause: ObligationCause<'tcx>,
|
cause: ObligationCause<'tcx>,
|
||||||
recursion_depth: usize,
|
recursion_depth: usize,
|
||||||
trait_def_id: DefId,
|
trait_def_id: DefId,
|
||||||
|
@ -1981,16 +1983,17 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
|
||||||
this.infcx().skolemize_late_bound_regions(&ty, snapshot);
|
this.infcx().skolemize_late_bound_regions(&ty, snapshot);
|
||||||
let Normalized { value: normalized_ty, mut obligations } =
|
let Normalized { value: normalized_ty, mut obligations } =
|
||||||
project::normalize_with_depth(this,
|
project::normalize_with_depth(this,
|
||||||
|
param_env,
|
||||||
cause.clone(),
|
cause.clone(),
|
||||||
recursion_depth,
|
recursion_depth,
|
||||||
&skol_ty);
|
&skol_ty);
|
||||||
let skol_obligation =
|
let skol_obligation =
|
||||||
this.tcx().predicate_for_trait_def(
|
this.tcx().predicate_for_trait_def(param_env,
|
||||||
cause.clone(),
|
cause.clone(),
|
||||||
trait_def_id,
|
trait_def_id,
|
||||||
recursion_depth,
|
recursion_depth,
|
||||||
normalized_ty,
|
normalized_ty,
|
||||||
&[]);
|
&[]);
|
||||||
obligations.push(skol_obligation);
|
obligations.push(skol_obligation);
|
||||||
this.infcx().plug_leaks(skol_map, snapshot, obligations)
|
this.infcx().plug_leaks(skol_map, snapshot, obligations)
|
||||||
})
|
})
|
||||||
|
@ -2131,7 +2134,8 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
|
||||||
};
|
};
|
||||||
|
|
||||||
let cause = obligation.derived_cause(BuiltinDerivedObligation);
|
let cause = obligation.derived_cause(BuiltinDerivedObligation);
|
||||||
self.collect_predicates_for_types(cause,
|
self.collect_predicates_for_types(obligation.param_env,
|
||||||
|
cause,
|
||||||
obligation.recursion_depth+1,
|
obligation.recursion_depth+1,
|
||||||
trait_def,
|
trait_def,
|
||||||
nested)
|
nested)
|
||||||
|
@ -2175,6 +2179,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
|
||||||
|
|
||||||
let cause = obligation.derived_cause(BuiltinDerivedObligation);
|
let cause = obligation.derived_cause(BuiltinDerivedObligation);
|
||||||
let mut obligations = self.collect_predicates_for_types(
|
let mut obligations = self.collect_predicates_for_types(
|
||||||
|
obligation.param_env,
|
||||||
cause,
|
cause,
|
||||||
obligation.recursion_depth+1,
|
obligation.recursion_depth+1,
|
||||||
trait_def_id,
|
trait_def_id,
|
||||||
|
@ -2187,6 +2192,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
|
||||||
let cause = obligation.derived_cause(ImplDerivedObligation);
|
let cause = obligation.derived_cause(ImplDerivedObligation);
|
||||||
this.impl_or_trait_obligations(cause,
|
this.impl_or_trait_obligations(cause,
|
||||||
obligation.recursion_depth + 1,
|
obligation.recursion_depth + 1,
|
||||||
|
obligation.param_env,
|
||||||
trait_def_id,
|
trait_def_id,
|
||||||
&trait_ref.substs,
|
&trait_ref.substs,
|
||||||
skol_map,
|
skol_map,
|
||||||
|
@ -2220,9 +2226,13 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
|
||||||
snapshot);
|
snapshot);
|
||||||
debug!("confirm_impl_candidate substs={:?}", substs);
|
debug!("confirm_impl_candidate substs={:?}", substs);
|
||||||
let cause = obligation.derived_cause(ImplDerivedObligation);
|
let cause = obligation.derived_cause(ImplDerivedObligation);
|
||||||
this.vtable_impl(impl_def_id, substs, cause,
|
this.vtable_impl(impl_def_id,
|
||||||
|
substs,
|
||||||
|
cause,
|
||||||
obligation.recursion_depth + 1,
|
obligation.recursion_depth + 1,
|
||||||
skol_map, snapshot)
|
obligation.param_env,
|
||||||
|
skol_map,
|
||||||
|
snapshot)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2231,6 +2241,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
|
||||||
mut substs: Normalized<'tcx, &'tcx Substs<'tcx>>,
|
mut substs: Normalized<'tcx, &'tcx Substs<'tcx>>,
|
||||||
cause: ObligationCause<'tcx>,
|
cause: ObligationCause<'tcx>,
|
||||||
recursion_depth: usize,
|
recursion_depth: usize,
|
||||||
|
param_env: ty::ParamEnv<'tcx>,
|
||||||
skol_map: infer::SkolemizationMap<'tcx>,
|
skol_map: infer::SkolemizationMap<'tcx>,
|
||||||
snapshot: &infer::CombinedSnapshot)
|
snapshot: &infer::CombinedSnapshot)
|
||||||
-> VtableImplData<'tcx, PredicateObligation<'tcx>>
|
-> VtableImplData<'tcx, PredicateObligation<'tcx>>
|
||||||
|
@ -2244,6 +2255,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
|
||||||
let mut impl_obligations =
|
let mut impl_obligations =
|
||||||
self.impl_or_trait_obligations(cause,
|
self.impl_or_trait_obligations(cause,
|
||||||
recursion_depth,
|
recursion_depth,
|
||||||
|
param_env,
|
||||||
impl_def_id,
|
impl_def_id,
|
||||||
&substs.value,
|
&substs.value,
|
||||||
skol_map,
|
skol_map,
|
||||||
|
@ -2345,6 +2357,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
|
||||||
.map_bound(|(trait_ref, _)| trait_ref);
|
.map_bound(|(trait_ref, _)| trait_ref);
|
||||||
|
|
||||||
self.confirm_poly_trait_refs(obligation.cause.clone(),
|
self.confirm_poly_trait_refs(obligation.cause.clone(),
|
||||||
|
obligation.param_env,
|
||||||
obligation.predicate.to_poly_trait_ref(),
|
obligation.predicate.to_poly_trait_ref(),
|
||||||
trait_ref)?;
|
trait_ref)?;
|
||||||
Ok(VtableFnPointerData { fn_ty: self_ty, nested: vec![] })
|
Ok(VtableFnPointerData { fn_ty: self_ty, nested: vec![] })
|
||||||
|
@ -2374,12 +2387,14 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
|
||||||
obligations);
|
obligations);
|
||||||
|
|
||||||
self.confirm_poly_trait_refs(obligation.cause.clone(),
|
self.confirm_poly_trait_refs(obligation.cause.clone(),
|
||||||
|
obligation.param_env,
|
||||||
obligation.predicate.to_poly_trait_ref(),
|
obligation.predicate.to_poly_trait_ref(),
|
||||||
trait_ref)?;
|
trait_ref)?;
|
||||||
|
|
||||||
obligations.push(Obligation::new(
|
obligations.push(Obligation::new(
|
||||||
obligation.cause.clone(),
|
obligation.cause.clone(),
|
||||||
ty::Predicate::ClosureKind(closure_def_id, kind)));
|
obligation.param_env,
|
||||||
|
ty::Predicate::ClosureKind(closure_def_id, kind)));
|
||||||
|
|
||||||
Ok(VtableClosureData {
|
Ok(VtableClosureData {
|
||||||
closure_def_id: closure_def_id,
|
closure_def_id: closure_def_id,
|
||||||
|
@ -2415,6 +2430,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
|
||||||
/// report an error to the user.
|
/// report an error to the user.
|
||||||
fn confirm_poly_trait_refs(&mut self,
|
fn confirm_poly_trait_refs(&mut self,
|
||||||
obligation_cause: ObligationCause<'tcx>,
|
obligation_cause: ObligationCause<'tcx>,
|
||||||
|
obligation_param_env: ty::ParamEnv<'tcx>,
|
||||||
obligation_trait_ref: ty::PolyTraitRef<'tcx>,
|
obligation_trait_ref: ty::PolyTraitRef<'tcx>,
|
||||||
expected_trait_ref: ty::PolyTraitRef<'tcx>)
|
expected_trait_ref: ty::PolyTraitRef<'tcx>)
|
||||||
-> Result<(), SelectionError<'tcx>>
|
-> Result<(), SelectionError<'tcx>>
|
||||||
|
@ -2422,6 +2438,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
|
||||||
let obligation_trait_ref = obligation_trait_ref.clone();
|
let obligation_trait_ref = obligation_trait_ref.clone();
|
||||||
self.infcx.sub_poly_trait_refs(false,
|
self.infcx.sub_poly_trait_refs(false,
|
||||||
obligation_cause.clone(),
|
obligation_cause.clone(),
|
||||||
|
obligation_param_env,
|
||||||
expected_trait_ref.clone(),
|
expected_trait_ref.clone(),
|
||||||
obligation_trait_ref.clone())
|
obligation_trait_ref.clone())
|
||||||
.map(|InferOk { obligations, .. }| self.inferred_obligations.extend(obligations))
|
.map(|InferOk { obligations, .. }| self.inferred_obligations.extend(obligations))
|
||||||
|
@ -2458,7 +2475,11 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
|
||||||
let new_trait = tcx.mk_dynamic(
|
let new_trait = tcx.mk_dynamic(
|
||||||
ty::Binder(tcx.mk_existential_predicates(iter)), r_b);
|
ty::Binder(tcx.mk_existential_predicates(iter)), r_b);
|
||||||
let InferOk { obligations, .. } =
|
let InferOk { obligations, .. } =
|
||||||
self.infcx.eq_types(false, &obligation.cause, new_trait, target)
|
self.infcx.eq_types(false,
|
||||||
|
&obligation.cause,
|
||||||
|
obligation.param_env,
|
||||||
|
new_trait,
|
||||||
|
target)
|
||||||
.map_err(|_| Unimplemented)?;
|
.map_err(|_| Unimplemented)?;
|
||||||
self.inferred_obligations.extend(obligations);
|
self.inferred_obligations.extend(obligations);
|
||||||
|
|
||||||
|
@ -2469,6 +2490,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
|
||||||
let outlives = ty::OutlivesPredicate(r_a, r_b);
|
let outlives = ty::OutlivesPredicate(r_a, r_b);
|
||||||
nested.push(Obligation::with_depth(cause,
|
nested.push(Obligation::with_depth(cause,
|
||||||
obligation.recursion_depth + 1,
|
obligation.recursion_depth + 1,
|
||||||
|
obligation.param_env,
|
||||||
ty::Binder(outlives).to_predicate()));
|
ty::Binder(outlives).to_predicate()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2488,6 +2510,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
|
||||||
let mut push = |predicate| {
|
let mut push = |predicate| {
|
||||||
nested.push(Obligation::with_depth(cause.clone(),
|
nested.push(Obligation::with_depth(cause.clone(),
|
||||||
obligation.recursion_depth + 1,
|
obligation.recursion_depth + 1,
|
||||||
|
obligation.param_env,
|
||||||
predicate));
|
predicate));
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -2517,7 +2540,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
|
||||||
// [T; n] -> [T].
|
// [T; n] -> [T].
|
||||||
(&ty::TyArray(a, _), &ty::TySlice(b)) => {
|
(&ty::TyArray(a, _), &ty::TySlice(b)) => {
|
||||||
let InferOk { obligations, .. } =
|
let InferOk { obligations, .. } =
|
||||||
self.infcx.eq_types(false, &obligation.cause, a, b)
|
self.infcx.eq_types(false, &obligation.cause, obligation.param_env, a, b)
|
||||||
.map_err(|_| Unimplemented)?;
|
.map_err(|_| Unimplemented)?;
|
||||||
self.inferred_obligations.extend(obligations);
|
self.inferred_obligations.extend(obligations);
|
||||||
}
|
}
|
||||||
|
@ -2580,12 +2603,17 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
|
||||||
});
|
});
|
||||||
let new_struct = tcx.mk_adt(def, tcx.mk_substs(params));
|
let new_struct = tcx.mk_adt(def, tcx.mk_substs(params));
|
||||||
let InferOk { obligations, .. } =
|
let InferOk { obligations, .. } =
|
||||||
self.infcx.eq_types(false, &obligation.cause, new_struct, target)
|
self.infcx.eq_types(false,
|
||||||
|
&obligation.cause,
|
||||||
|
obligation.param_env,
|
||||||
|
new_struct,
|
||||||
|
target)
|
||||||
.map_err(|_| Unimplemented)?;
|
.map_err(|_| Unimplemented)?;
|
||||||
self.inferred_obligations.extend(obligations);
|
self.inferred_obligations.extend(obligations);
|
||||||
|
|
||||||
// Construct the nested Field<T>: Unsize<Field<U>> predicate.
|
// Construct the nested Field<T>: Unsize<Field<U>> predicate.
|
||||||
nested.push(tcx.predicate_for_trait_def(
|
nested.push(tcx.predicate_for_trait_def(
|
||||||
|
obligation.param_env,
|
||||||
obligation.cause.clone(),
|
obligation.cause.clone(),
|
||||||
obligation.predicate.def_id(),
|
obligation.predicate.def_id(),
|
||||||
obligation.recursion_depth + 1,
|
obligation.recursion_depth + 1,
|
||||||
|
@ -2655,6 +2683,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
|
||||||
|
|
||||||
let impl_trait_ref =
|
let impl_trait_ref =
|
||||||
project::normalize_with_depth(self,
|
project::normalize_with_depth(self,
|
||||||
|
obligation.param_env,
|
||||||
obligation.cause.clone(),
|
obligation.cause.clone(),
|
||||||
obligation.recursion_depth + 1,
|
obligation.recursion_depth + 1,
|
||||||
&impl_trait_ref);
|
&impl_trait_ref);
|
||||||
|
@ -2669,6 +2698,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
|
||||||
let InferOk { obligations, .. } =
|
let InferOk { obligations, .. } =
|
||||||
self.infcx.eq_trait_refs(false,
|
self.infcx.eq_trait_refs(false,
|
||||||
&obligation.cause,
|
&obligation.cause,
|
||||||
|
obligation.param_env,
|
||||||
impl_trait_ref.value.clone(),
|
impl_trait_ref.value.clone(),
|
||||||
skol_obligation_trait_ref)
|
skol_obligation_trait_ref)
|
||||||
.map_err(|e| {
|
.map_err(|e| {
|
||||||
|
@ -2742,6 +2772,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
|
||||||
|
|
||||||
self.infcx.sub_poly_trait_refs(false,
|
self.infcx.sub_poly_trait_refs(false,
|
||||||
obligation.cause.clone(),
|
obligation.cause.clone(),
|
||||||
|
obligation.param_env,
|
||||||
poly_trait_ref,
|
poly_trait_ref,
|
||||||
obligation.predicate.to_poly_trait_ref())
|
obligation.predicate.to_poly_trait_ref())
|
||||||
.map(|InferOk { obligations, .. }| self.inferred_obligations.extend(obligations))
|
.map(|InferOk { obligations, .. }| self.inferred_obligations.extend(obligations))
|
||||||
|
@ -2809,6 +2840,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
|
||||||
// A closure signature can contain associated types which
|
// A closure signature can contain associated types which
|
||||||
// must be normalized.
|
// must be normalized.
|
||||||
normalize_with_depth(self,
|
normalize_with_depth(self,
|
||||||
|
obligation.param_env,
|
||||||
obligation.cause.clone(),
|
obligation.cause.clone(),
|
||||||
obligation.recursion_depth+1,
|
obligation.recursion_depth+1,
|
||||||
&trait_ref)
|
&trait_ref)
|
||||||
|
@ -2821,6 +2853,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
|
||||||
fn impl_or_trait_obligations(&mut self,
|
fn impl_or_trait_obligations(&mut self,
|
||||||
cause: ObligationCause<'tcx>,
|
cause: ObligationCause<'tcx>,
|
||||||
recursion_depth: usize,
|
recursion_depth: usize,
|
||||||
|
param_env: ty::ParamEnv<'tcx>,
|
||||||
def_id: DefId, // of impl or trait
|
def_id: DefId, // of impl or trait
|
||||||
substs: &Substs<'tcx>, // for impl or trait
|
substs: &Substs<'tcx>, // for impl or trait
|
||||||
skol_map: infer::SkolemizationMap<'tcx>,
|
skol_map: infer::SkolemizationMap<'tcx>,
|
||||||
|
@ -2847,12 +2880,13 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
|
||||||
let predicates = tcx.predicates_of(def_id);
|
let predicates = tcx.predicates_of(def_id);
|
||||||
assert_eq!(predicates.parent, None);
|
assert_eq!(predicates.parent, None);
|
||||||
let predicates = predicates.predicates.iter().flat_map(|predicate| {
|
let predicates = predicates.predicates.iter().flat_map(|predicate| {
|
||||||
let predicate = normalize_with_depth(self, cause.clone(), recursion_depth,
|
let predicate = normalize_with_depth(self, param_env, cause.clone(), recursion_depth,
|
||||||
&predicate.subst(tcx, substs));
|
&predicate.subst(tcx, substs));
|
||||||
predicate.obligations.into_iter().chain(
|
predicate.obligations.into_iter().chain(
|
||||||
Some(Obligation {
|
Some(Obligation {
|
||||||
cause: cause.clone(),
|
cause: cause.clone(),
|
||||||
recursion_depth: recursion_depth,
|
recursion_depth: recursion_depth,
|
||||||
|
param_env,
|
||||||
predicate: predicate.value
|
predicate: predicate.value
|
||||||
}))
|
}))
|
||||||
}).collect();
|
}).collect();
|
||||||
|
|
|
@ -41,6 +41,7 @@ pub struct OverlapError {
|
||||||
/// Given a subst for the requested impl, translate it to a subst
|
/// Given a subst for the requested impl, translate it to a subst
|
||||||
/// appropriate for the actual item definition (whether it be in that impl,
|
/// appropriate for the actual item definition (whether it be in that impl,
|
||||||
/// a parent impl, or the trait).
|
/// a parent impl, or the trait).
|
||||||
|
///
|
||||||
/// When we have selected one impl, but are actually using item definitions from
|
/// When we have selected one impl, but are actually using item definitions from
|
||||||
/// a parent impl providing a default, we need a way to translate between the
|
/// a parent impl providing a default, we need a way to translate between the
|
||||||
/// type parameters of the two impls. Here the `source_impl` is the one we've
|
/// type parameters of the two impls. Here the `source_impl` is the one we've
|
||||||
|
@ -73,6 +74,7 @@ pub struct OverlapError {
|
||||||
/// *fulfillment* to relate the two impls, requiring that all projections are
|
/// *fulfillment* to relate the two impls, requiring that all projections are
|
||||||
/// resolved.
|
/// resolved.
|
||||||
pub fn translate_substs<'a, 'gcx, 'tcx>(infcx: &InferCtxt<'a, 'gcx, 'tcx>,
|
pub fn translate_substs<'a, 'gcx, 'tcx>(infcx: &InferCtxt<'a, 'gcx, 'tcx>,
|
||||||
|
param_env: ty::ParamEnv<'tcx>,
|
||||||
source_impl: DefId,
|
source_impl: DefId,
|
||||||
source_substs: &'tcx Substs<'tcx>,
|
source_substs: &'tcx Substs<'tcx>,
|
||||||
target_node: specialization_graph::Node)
|
target_node: specialization_graph::Node)
|
||||||
|
@ -91,10 +93,11 @@ pub fn translate_substs<'a, 'gcx, 'tcx>(infcx: &InferCtxt<'a, 'gcx, 'tcx>,
|
||||||
return source_substs;
|
return source_substs;
|
||||||
}
|
}
|
||||||
|
|
||||||
fulfill_implication(infcx, source_trait_ref, target_impl).unwrap_or_else(|_| {
|
fulfill_implication(infcx, param_env, source_trait_ref, target_impl)
|
||||||
bug!("When translating substitutions for specialization, the expected \
|
.unwrap_or_else(|_| {
|
||||||
specializaiton failed to hold")
|
bug!("When translating substitutions for specialization, the expected \
|
||||||
})
|
specializaiton failed to hold")
|
||||||
|
})
|
||||||
}
|
}
|
||||||
specialization_graph::Node::Trait(..) => source_trait_ref.substs,
|
specialization_graph::Node::Trait(..) => source_trait_ref.substs,
|
||||||
};
|
};
|
||||||
|
@ -122,9 +125,10 @@ pub fn find_associated_item<'a, 'tcx>(
|
||||||
let ancestors = trait_def.ancestors(tcx, impl_data.impl_def_id);
|
let ancestors = trait_def.ancestors(tcx, impl_data.impl_def_id);
|
||||||
match ancestors.defs(tcx, item.name, item.kind).next() {
|
match ancestors.defs(tcx, item.name, item.kind).next() {
|
||||||
Some(node_item) => {
|
Some(node_item) => {
|
||||||
let substs = tcx.infer_ctxt(Reveal::All).enter(|infcx| {
|
let substs = tcx.infer_ctxt(()).enter(|infcx| {
|
||||||
|
let param_env = ty::ParamEnv::empty(Reveal::All);
|
||||||
let substs = substs.rebase_onto(tcx, trait_def_id, impl_data.substs);
|
let substs = substs.rebase_onto(tcx, trait_def_id, impl_data.substs);
|
||||||
let substs = translate_substs(&infcx, impl_data.impl_def_id,
|
let substs = translate_substs(&infcx, param_env, impl_data.impl_def_id,
|
||||||
substs, node_item.node);
|
substs, node_item.node);
|
||||||
let substs = infcx.tcx.erase_regions(&substs);
|
let substs = infcx.tcx.erase_regions(&substs);
|
||||||
tcx.lift(&substs).unwrap_or_else(|| {
|
tcx.lift(&substs).unwrap_or_else(|| {
|
||||||
|
@ -184,11 +188,14 @@ pub fn specializes<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||||
let impl1_trait_ref = tcx.impl_trait_ref(impl1_def_id).unwrap();
|
let impl1_trait_ref = tcx.impl_trait_ref(impl1_def_id).unwrap();
|
||||||
|
|
||||||
// Create a infcx, taking the predicates of impl1 as assumptions:
|
// Create a infcx, taking the predicates of impl1 as assumptions:
|
||||||
let result = tcx.infer_ctxt(penv).enter(|infcx| {
|
let result = tcx.infer_ctxt(()).enter(|infcx| {
|
||||||
// Normalize the trait reference. The WF rules ought to ensure
|
// Normalize the trait reference. The WF rules ought to ensure
|
||||||
// that this always succeeds.
|
// that this always succeeds.
|
||||||
let impl1_trait_ref =
|
let impl1_trait_ref =
|
||||||
match traits::fully_normalize(&infcx, ObligationCause::dummy(), &impl1_trait_ref) {
|
match traits::fully_normalize(&infcx,
|
||||||
|
ObligationCause::dummy(),
|
||||||
|
penv,
|
||||||
|
&impl1_trait_ref) {
|
||||||
Ok(impl1_trait_ref) => impl1_trait_ref,
|
Ok(impl1_trait_ref) => impl1_trait_ref,
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
bug!("failed to fully normalize {:?}: {:?}", impl1_trait_ref, err);
|
bug!("failed to fully normalize {:?}: {:?}", impl1_trait_ref, err);
|
||||||
|
@ -196,7 +203,7 @@ pub fn specializes<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||||
};
|
};
|
||||||
|
|
||||||
// Attempt to prove that impl2 applies, given all of the above.
|
// Attempt to prove that impl2 applies, given all of the above.
|
||||||
fulfill_implication(&infcx, impl1_trait_ref, impl2_def_id).is_ok()
|
fulfill_implication(&infcx, penv, impl1_trait_ref, impl2_def_id).is_ok()
|
||||||
});
|
});
|
||||||
|
|
||||||
tcx.specializes_cache.borrow_mut().insert(impl1_def_id, impl2_def_id, result);
|
tcx.specializes_cache.borrow_mut().insert(impl1_def_id, impl2_def_id, result);
|
||||||
|
@ -209,18 +216,21 @@ pub fn specializes<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||||
/// `source_trait_ref` and those whose identity is determined via a where
|
/// `source_trait_ref` and those whose identity is determined via a where
|
||||||
/// clause in the impl.
|
/// clause in the impl.
|
||||||
fn fulfill_implication<'a, 'gcx, 'tcx>(infcx: &InferCtxt<'a, 'gcx, 'tcx>,
|
fn fulfill_implication<'a, 'gcx, 'tcx>(infcx: &InferCtxt<'a, 'gcx, 'tcx>,
|
||||||
|
param_env: ty::ParamEnv<'tcx>,
|
||||||
source_trait_ref: ty::TraitRef<'tcx>,
|
source_trait_ref: ty::TraitRef<'tcx>,
|
||||||
target_impl: DefId)
|
target_impl: DefId)
|
||||||
-> Result<&'tcx Substs<'tcx>, ()> {
|
-> Result<&'tcx Substs<'tcx>, ()> {
|
||||||
let selcx = &mut SelectionContext::new(&infcx);
|
let selcx = &mut SelectionContext::new(&infcx);
|
||||||
let target_substs = infcx.fresh_substs_for_item(DUMMY_SP, target_impl);
|
let target_substs = infcx.fresh_substs_for_item(DUMMY_SP, target_impl);
|
||||||
let (target_trait_ref, mut obligations) = impl_trait_ref_and_oblig(selcx,
|
let (target_trait_ref, mut obligations) = impl_trait_ref_and_oblig(selcx,
|
||||||
target_impl,
|
param_env,
|
||||||
target_substs);
|
target_impl,
|
||||||
|
target_substs);
|
||||||
|
|
||||||
// do the impls unify? If not, no specialization.
|
// do the impls unify? If not, no specialization.
|
||||||
match infcx.eq_trait_refs(true,
|
match infcx.eq_trait_refs(true,
|
||||||
&ObligationCause::dummy(),
|
&ObligationCause::dummy(),
|
||||||
|
param_env,
|
||||||
source_trait_ref,
|
source_trait_ref,
|
||||||
target_trait_ref) {
|
target_trait_ref) {
|
||||||
Ok(InferOk { obligations: o, .. }) => {
|
Ok(InferOk { obligations: o, .. }) => {
|
||||||
|
@ -250,7 +260,7 @@ fn fulfill_implication<'a, 'gcx, 'tcx>(infcx: &InferCtxt<'a, 'gcx, 'tcx>,
|
||||||
source_trait_ref,
|
source_trait_ref,
|
||||||
target_trait_ref,
|
target_trait_ref,
|
||||||
errors,
|
errors,
|
||||||
infcx.param_env.caller_bounds);
|
param_env.caller_bounds);
|
||||||
Err(())
|
Err(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
use super::{OverlapError, specializes};
|
use super::{OverlapError, specializes};
|
||||||
|
|
||||||
use hir::def_id::DefId;
|
use hir::def_id::DefId;
|
||||||
use traits::{self, Reveal};
|
use traits;
|
||||||
use ty::{self, TyCtxt, TypeFoldable};
|
use ty::{self, TyCtxt, TypeFoldable};
|
||||||
use ty::fast_reject::{self, SimplifiedType};
|
use ty::fast_reject::{self, SimplifiedType};
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
@ -109,7 +109,7 @@ impl<'a, 'gcx, 'tcx> Children {
|
||||||
let possible_sibling = *slot;
|
let possible_sibling = *slot;
|
||||||
|
|
||||||
let tcx = tcx.global_tcx();
|
let tcx = tcx.global_tcx();
|
||||||
let (le, ge) = tcx.infer_ctxt(Reveal::UserFacing).enter(|infcx| {
|
let (le, ge) = tcx.infer_ctxt(()).enter(|infcx| {
|
||||||
let overlap = traits::overlapping_impls(&infcx,
|
let overlap = traits::overlapping_impls(&infcx,
|
||||||
possible_sibling,
|
possible_sibling,
|
||||||
impl_def_id);
|
impl_def_id);
|
||||||
|
|
|
@ -341,6 +341,7 @@ impl<'tcx, O: TypeFoldable<'tcx>> TypeFoldable<'tcx> for traits::Obligation<'tcx
|
||||||
cause: self.cause.clone(),
|
cause: self.cause.clone(),
|
||||||
recursion_depth: self.recursion_depth,
|
recursion_depth: self.recursion_depth,
|
||||||
predicate: self.predicate.fold_with(folder),
|
predicate: self.predicate.fold_with(folder),
|
||||||
|
param_env: self.param_env.fold_with(folder),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -46,12 +46,14 @@ impl<'a, 'tcx> TyCtxt<'a, 'tcx, 'tcx> {
|
||||||
|
|
||||||
// Do the initial selection for the obligation. This yields the
|
// Do the initial selection for the obligation. This yields the
|
||||||
// shallow result we are looking for -- that is, what specific impl.
|
// shallow result we are looking for -- that is, what specific impl.
|
||||||
self.infer_ctxt(Reveal::All).enter(|infcx| {
|
self.infer_ctxt(()).enter(|infcx| {
|
||||||
let mut selcx = SelectionContext::new(&infcx);
|
let mut selcx = SelectionContext::new(&infcx);
|
||||||
|
|
||||||
|
let param_env = ty::ParamEnv::empty(Reveal::All);
|
||||||
let obligation_cause = ObligationCause::misc(span,
|
let obligation_cause = ObligationCause::misc(span,
|
||||||
ast::DUMMY_NODE_ID);
|
ast::DUMMY_NODE_ID);
|
||||||
let obligation = Obligation::new(obligation_cause,
|
let obligation = Obligation::new(obligation_cause,
|
||||||
|
param_env,
|
||||||
trait_ref.to_poly_trait_predicate());
|
trait_ref.to_poly_trait_predicate());
|
||||||
|
|
||||||
let selection = match selcx.select(&obligation) {
|
let selection = match selcx.select(&obligation) {
|
||||||
|
|
|
@ -358,6 +358,7 @@ impl<'tcx,I:Iterator<Item=ty::Predicate<'tcx>>> Iterator for FilterToTraits<I> {
|
||||||
/// returning the resulting trait ref and all obligations that arise.
|
/// returning the resulting trait ref and all obligations that arise.
|
||||||
/// The obligations are closed under normalization.
|
/// The obligations are closed under normalization.
|
||||||
pub fn impl_trait_ref_and_oblig<'a, 'gcx, 'tcx>(selcx: &mut SelectionContext<'a, 'gcx, 'tcx>,
|
pub fn impl_trait_ref_and_oblig<'a, 'gcx, 'tcx>(selcx: &mut SelectionContext<'a, 'gcx, 'tcx>,
|
||||||
|
param_env: ty::ParamEnv<'tcx>,
|
||||||
impl_def_id: DefId,
|
impl_def_id: DefId,
|
||||||
impl_substs: &Substs<'tcx>)
|
impl_substs: &Substs<'tcx>)
|
||||||
-> (ty::TraitRef<'tcx>,
|
-> (ty::TraitRef<'tcx>,
|
||||||
|
@ -368,14 +369,14 @@ pub fn impl_trait_ref_and_oblig<'a, 'gcx, 'tcx>(selcx: &mut SelectionContext<'a,
|
||||||
let impl_trait_ref =
|
let impl_trait_ref =
|
||||||
impl_trait_ref.subst(selcx.tcx(), impl_substs);
|
impl_trait_ref.subst(selcx.tcx(), impl_substs);
|
||||||
let Normalized { value: impl_trait_ref, obligations: normalization_obligations1 } =
|
let Normalized { value: impl_trait_ref, obligations: normalization_obligations1 } =
|
||||||
super::normalize(selcx, ObligationCause::dummy(), &impl_trait_ref);
|
super::normalize(selcx, param_env, ObligationCause::dummy(), &impl_trait_ref);
|
||||||
|
|
||||||
let predicates = selcx.tcx().predicates_of(impl_def_id);
|
let predicates = selcx.tcx().predicates_of(impl_def_id);
|
||||||
let predicates = predicates.instantiate(selcx.tcx(), impl_substs);
|
let predicates = predicates.instantiate(selcx.tcx(), impl_substs);
|
||||||
let Normalized { value: predicates, obligations: normalization_obligations2 } =
|
let Normalized { value: predicates, obligations: normalization_obligations2 } =
|
||||||
super::normalize(selcx, ObligationCause::dummy(), &predicates);
|
super::normalize(selcx, param_env, ObligationCause::dummy(), &predicates);
|
||||||
let impl_obligations =
|
let impl_obligations =
|
||||||
predicates_for_generics(ObligationCause::dummy(), 0, &predicates);
|
predicates_for_generics(ObligationCause::dummy(), 0, param_env, &predicates);
|
||||||
|
|
||||||
let impl_obligations: Vec<_> =
|
let impl_obligations: Vec<_> =
|
||||||
impl_obligations.into_iter()
|
impl_obligations.into_iter()
|
||||||
|
@ -389,6 +390,7 @@ pub fn impl_trait_ref_and_oblig<'a, 'gcx, 'tcx>(selcx: &mut SelectionContext<'a,
|
||||||
/// See `super::obligations_for_generics`
|
/// See `super::obligations_for_generics`
|
||||||
pub fn predicates_for_generics<'tcx>(cause: ObligationCause<'tcx>,
|
pub fn predicates_for_generics<'tcx>(cause: ObligationCause<'tcx>,
|
||||||
recursion_depth: usize,
|
recursion_depth: usize,
|
||||||
|
param_env: ty::ParamEnv<'tcx>,
|
||||||
generic_bounds: &ty::InstantiatedPredicates<'tcx>)
|
generic_bounds: &ty::InstantiatedPredicates<'tcx>)
|
||||||
-> Vec<PredicateObligation<'tcx>>
|
-> Vec<PredicateObligation<'tcx>>
|
||||||
{
|
{
|
||||||
|
@ -398,18 +400,21 @@ pub fn predicates_for_generics<'tcx>(cause: ObligationCause<'tcx>,
|
||||||
generic_bounds.predicates.iter().map(|predicate| {
|
generic_bounds.predicates.iter().map(|predicate| {
|
||||||
Obligation { cause: cause.clone(),
|
Obligation { cause: cause.clone(),
|
||||||
recursion_depth: recursion_depth,
|
recursion_depth: recursion_depth,
|
||||||
|
param_env: param_env,
|
||||||
predicate: predicate.clone() }
|
predicate: predicate.clone() }
|
||||||
}).collect()
|
}).collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn predicate_for_trait_ref<'tcx>(
|
pub fn predicate_for_trait_ref<'tcx>(
|
||||||
cause: ObligationCause<'tcx>,
|
cause: ObligationCause<'tcx>,
|
||||||
|
param_env: ty::ParamEnv<'tcx>,
|
||||||
trait_ref: ty::TraitRef<'tcx>,
|
trait_ref: ty::TraitRef<'tcx>,
|
||||||
recursion_depth: usize)
|
recursion_depth: usize)
|
||||||
-> PredicateObligation<'tcx>
|
-> PredicateObligation<'tcx>
|
||||||
{
|
{
|
||||||
Obligation {
|
Obligation {
|
||||||
cause: cause,
|
cause: cause,
|
||||||
|
param_env: param_env,
|
||||||
recursion_depth: recursion_depth,
|
recursion_depth: recursion_depth,
|
||||||
predicate: trait_ref.to_predicate(),
|
predicate: trait_ref.to_predicate(),
|
||||||
}
|
}
|
||||||
|
@ -417,18 +422,19 @@ pub fn predicate_for_trait_ref<'tcx>(
|
||||||
|
|
||||||
impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
|
impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
|
||||||
pub fn predicate_for_trait_def(self,
|
pub fn predicate_for_trait_def(self,
|
||||||
cause: ObligationCause<'tcx>,
|
param_env: ty::ParamEnv<'tcx>,
|
||||||
trait_def_id: DefId,
|
cause: ObligationCause<'tcx>,
|
||||||
recursion_depth: usize,
|
trait_def_id: DefId,
|
||||||
param_ty: Ty<'tcx>,
|
recursion_depth: usize,
|
||||||
ty_params: &[Ty<'tcx>])
|
param_ty: Ty<'tcx>,
|
||||||
|
ty_params: &[Ty<'tcx>])
|
||||||
-> PredicateObligation<'tcx>
|
-> PredicateObligation<'tcx>
|
||||||
{
|
{
|
||||||
let trait_ref = ty::TraitRef {
|
let trait_ref = ty::TraitRef {
|
||||||
def_id: trait_def_id,
|
def_id: trait_def_id,
|
||||||
substs: self.mk_substs_trait(param_ty, ty_params)
|
substs: self.mk_substs_trait(param_ty, ty_params)
|
||||||
};
|
};
|
||||||
predicate_for_trait_ref(cause, trait_ref, recursion_depth)
|
predicate_for_trait_ref(cause, param_env, trait_ref, recursion_depth)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Cast a trait reference into a reference to one of its super
|
/// Cast a trait reference into a reference to one of its super
|
||||||
|
|
|
@ -765,6 +765,18 @@ pub trait Lift<'tcx> {
|
||||||
fn lift_to_tcx<'a, 'gcx>(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> Option<Self::Lifted>;
|
fn lift_to_tcx<'a, 'gcx>(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> Option<Self::Lifted>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'a, 'tcx> Lift<'tcx> for ty::ParamEnv<'a> {
|
||||||
|
type Lifted = ty::ParamEnv<'tcx>;
|
||||||
|
fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option<ty::ParamEnv<'tcx>> {
|
||||||
|
self.caller_bounds.lift_to_tcx(tcx).and_then(|caller_bounds| {
|
||||||
|
Some(ty::ParamEnv {
|
||||||
|
reveal: self.reveal,
|
||||||
|
caller_bounds,
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<'a, 'tcx> Lift<'tcx> for Ty<'a> {
|
impl<'a, 'tcx> Lift<'tcx> for Ty<'a> {
|
||||||
type Lifted = Ty<'tcx>;
|
type Lifted = Ty<'tcx>;
|
||||||
fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option<Ty<'tcx>> {
|
fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option<Ty<'tcx>> {
|
||||||
|
@ -851,6 +863,25 @@ impl<'a, 'tcx> Lift<'tcx> for &'a Slice<ExistentialPredicate<'a>> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'a, 'tcx> Lift<'tcx> for &'a Slice<Predicate<'a>> {
|
||||||
|
type Lifted = &'tcx Slice<Predicate<'tcx>>;
|
||||||
|
fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>)
|
||||||
|
-> Option<&'tcx Slice<Predicate<'tcx>>> {
|
||||||
|
if self.is_empty() {
|
||||||
|
return Some(Slice::empty());
|
||||||
|
}
|
||||||
|
if tcx.interners.arena.in_arena(*self as *const _) {
|
||||||
|
return Some(unsafe { mem::transmute(*self) });
|
||||||
|
}
|
||||||
|
// Also try in the global tcx if we're not that.
|
||||||
|
if !tcx.is_global() {
|
||||||
|
self.lift_to_tcx(tcx.global_tcx())
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub mod tls {
|
pub mod tls {
|
||||||
use super::{CtxtInterners, GlobalCtxt, TyCtxt};
|
use super::{CtxtInterners, GlobalCtxt, TyCtxt};
|
||||||
|
|
||||||
|
|
|
@ -158,29 +158,6 @@ pub struct ImplHeader<'tcx> {
|
||||||
pub predicates: Vec<Predicate<'tcx>>,
|
pub predicates: Vec<Predicate<'tcx>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'gcx, 'tcx> ImplHeader<'tcx> {
|
|
||||||
pub fn with_fresh_ty_vars(selcx: &mut traits::SelectionContext<'a, 'gcx, 'tcx>,
|
|
||||||
impl_def_id: DefId)
|
|
||||||
-> ImplHeader<'tcx>
|
|
||||||
{
|
|
||||||
let tcx = selcx.tcx();
|
|
||||||
let impl_substs = selcx.infcx().fresh_substs_for_item(DUMMY_SP, impl_def_id);
|
|
||||||
|
|
||||||
let header = ImplHeader {
|
|
||||||
impl_def_id: impl_def_id,
|
|
||||||
self_ty: tcx.type_of(impl_def_id),
|
|
||||||
trait_ref: tcx.impl_trait_ref(impl_def_id),
|
|
||||||
predicates: tcx.predicates_of(impl_def_id).predicates
|
|
||||||
}.subst(tcx, impl_substs);
|
|
||||||
|
|
||||||
let traits::Normalized { value: mut header, obligations } =
|
|
||||||
traits::normalize(selcx, traits::ObligationCause::dummy(), &header);
|
|
||||||
|
|
||||||
header.predicates.extend(obligations.into_iter().map(|o| o.predicate));
|
|
||||||
header
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug)]
|
#[derive(Copy, Clone, Debug)]
|
||||||
pub struct AssociatedItem {
|
pub struct AssociatedItem {
|
||||||
pub def_id: DefId,
|
pub def_id: DefId,
|
||||||
|
|
|
@ -466,6 +466,20 @@ impl<'tcx, T:TypeFoldable<'tcx>> TypeFoldable<'tcx> for ty::Binder<T> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'tcx> TypeFoldable<'tcx> for ty::ParamEnv<'tcx> {
|
||||||
|
fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self {
|
||||||
|
ty::ParamEnv {
|
||||||
|
reveal: self.reveal,
|
||||||
|
caller_bounds: self.caller_bounds.fold_with(folder),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
|
||||||
|
let &ty::ParamEnv { reveal: _, ref caller_bounds } = self;
|
||||||
|
caller_bounds.super_visit_with(visitor)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::Slice<ty::ExistentialPredicate<'tcx>> {
|
impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::Slice<ty::ExistentialPredicate<'tcx>> {
|
||||||
fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self {
|
fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self {
|
||||||
let v = self.iter().map(|p| p.fold_with(folder)).collect::<AccumulateVec<[_; 8]>>();
|
let v = self.iter().map(|p| p.fold_with(folder)).collect::<AccumulateVec<[_; 8]>>();
|
||||||
|
@ -771,6 +785,17 @@ impl<'tcx> TypeFoldable<'tcx> for ty::GenericPredicates<'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::Slice<ty::Predicate<'tcx>> {
|
||||||
|
fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self {
|
||||||
|
let v = self.iter().map(|p| p.fold_with(folder)).collect::<AccumulateVec<[_; 8]>>();
|
||||||
|
folder.tcx().intern_predicates(&v)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
|
||||||
|
self.iter().any(|p| p.visit_with(visitor))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<'tcx> TypeFoldable<'tcx> for ty::Predicate<'tcx> {
|
impl<'tcx> TypeFoldable<'tcx> for ty::Predicate<'tcx> {
|
||||||
fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self {
|
fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self {
|
||||||
match *self {
|
match *self {
|
||||||
|
|
|
@ -170,11 +170,12 @@ impl<'tcx> ty::ParamEnv<'tcx> {
|
||||||
ty::ParamEnv { reveal: Reveal::All, ..self }
|
ty::ParamEnv { reveal: Reveal::All, ..self }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn can_type_implement_copy<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
pub fn can_type_implement_copy<'a>(self,
|
||||||
|
tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||||
self_type: Ty<'tcx>, span: Span)
|
self_type: Ty<'tcx>, span: Span)
|
||||||
-> Result<(), CopyImplementationError> {
|
-> Result<(), CopyImplementationError<'tcx>> {
|
||||||
// FIXME: (@jroesch) float this code up
|
// FIXME: (@jroesch) float this code up
|
||||||
tcx.infer_ctxt(self.clone()).enter(|infcx| {
|
tcx.infer_ctxt(()).enter(|infcx| {
|
||||||
let (adt, substs) = match self_type.sty {
|
let (adt, substs) = match self_type.sty {
|
||||||
ty::TyAdt(adt, substs) => (adt, substs),
|
ty::TyAdt(adt, substs) => (adt, substs),
|
||||||
_ => return Err(CopyImplementationError::NotAnAdt),
|
_ => return Err(CopyImplementationError::NotAnAdt),
|
||||||
|
@ -182,8 +183,8 @@ impl<'tcx> ty::ParamEnv<'tcx> {
|
||||||
|
|
||||||
let field_implements_copy = |field: &ty::FieldDef| {
|
let field_implements_copy = |field: &ty::FieldDef| {
|
||||||
let cause = traits::ObligationCause::dummy();
|
let cause = traits::ObligationCause::dummy();
|
||||||
match traits::fully_normalize(&infcx, cause, &field.ty(tcx, substs)) {
|
match traits::fully_normalize(&infcx, cause, self, &field.ty(tcx, substs)) {
|
||||||
Ok(ty) => !infcx.type_moves_by_default(ty, span),
|
Ok(ty) => !infcx.type_moves_by_default(self, ty, span),
|
||||||
Err(..) => false,
|
Err(..) => false,
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -963,8 +964,12 @@ fn is_copy_raw<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||||
{
|
{
|
||||||
let (param_env, ty) = query.into_parts();
|
let (param_env, ty) = query.into_parts();
|
||||||
let trait_def_id = tcx.require_lang_item(lang_items::CopyTraitLangItem);
|
let trait_def_id = tcx.require_lang_item(lang_items::CopyTraitLangItem);
|
||||||
tcx.infer_ctxt(param_env)
|
tcx.infer_ctxt(())
|
||||||
.enter(|infcx| traits::type_known_to_meet_bound(&infcx, ty, trait_def_id, DUMMY_SP))
|
.enter(|infcx| traits::type_known_to_meet_bound(&infcx,
|
||||||
|
param_env,
|
||||||
|
ty,
|
||||||
|
trait_def_id,
|
||||||
|
DUMMY_SP))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_sized_raw<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
fn is_sized_raw<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||||
|
@ -973,8 +978,12 @@ fn is_sized_raw<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||||
{
|
{
|
||||||
let (param_env, ty) = query.into_parts();
|
let (param_env, ty) = query.into_parts();
|
||||||
let trait_def_id = tcx.require_lang_item(lang_items::SizedTraitLangItem);
|
let trait_def_id = tcx.require_lang_item(lang_items::SizedTraitLangItem);
|
||||||
tcx.infer_ctxt(param_env)
|
tcx.infer_ctxt(())
|
||||||
.enter(|infcx| traits::type_known_to_meet_bound(&infcx, ty, trait_def_id, DUMMY_SP))
|
.enter(|infcx| traits::type_known_to_meet_bound(&infcx,
|
||||||
|
param_env,
|
||||||
|
ty,
|
||||||
|
trait_def_id,
|
||||||
|
DUMMY_SP))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_freeze_raw<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
fn is_freeze_raw<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||||
|
@ -983,8 +992,12 @@ fn is_freeze_raw<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||||
{
|
{
|
||||||
let (param_env, ty) = query.into_parts();
|
let (param_env, ty) = query.into_parts();
|
||||||
let trait_def_id = tcx.require_lang_item(lang_items::FreezeTraitLangItem);
|
let trait_def_id = tcx.require_lang_item(lang_items::FreezeTraitLangItem);
|
||||||
tcx.infer_ctxt(param_env)
|
tcx.infer_ctxt(())
|
||||||
.enter(|infcx| traits::type_known_to_meet_bound(&infcx, ty, trait_def_id, DUMMY_SP))
|
.enter(|infcx| traits::type_known_to_meet_bound(&infcx,
|
||||||
|
param_env,
|
||||||
|
ty,
|
||||||
|
trait_def_id,
|
||||||
|
DUMMY_SP))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn needs_drop_raw<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
fn needs_drop_raw<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||||
|
|
|
@ -26,12 +26,14 @@ use middle::lang_items;
|
||||||
/// make any progress at all. This is to prevent "livelock" where we
|
/// make any progress at all. This is to prevent "livelock" where we
|
||||||
/// say "$0 is WF if $0 is WF".
|
/// say "$0 is WF if $0 is WF".
|
||||||
pub fn obligations<'a, 'gcx, 'tcx>(infcx: &InferCtxt<'a, 'gcx, 'tcx>,
|
pub fn obligations<'a, 'gcx, 'tcx>(infcx: &InferCtxt<'a, 'gcx, 'tcx>,
|
||||||
|
param_env: ty::ParamEnv<'tcx>,
|
||||||
body_id: ast::NodeId,
|
body_id: ast::NodeId,
|
||||||
ty: Ty<'tcx>,
|
ty: Ty<'tcx>,
|
||||||
span: Span)
|
span: Span)
|
||||||
-> Option<Vec<traits::PredicateObligation<'tcx>>>
|
-> Option<Vec<traits::PredicateObligation<'tcx>>>
|
||||||
{
|
{
|
||||||
let mut wf = WfPredicates { infcx: infcx,
|
let mut wf = WfPredicates { infcx: infcx,
|
||||||
|
param_env: param_env,
|
||||||
body_id: body_id,
|
body_id: body_id,
|
||||||
span: span,
|
span: span,
|
||||||
out: vec![] };
|
out: vec![] };
|
||||||
|
@ -50,23 +52,25 @@ pub fn obligations<'a, 'gcx, 'tcx>(infcx: &InferCtxt<'a, 'gcx, 'tcx>,
|
||||||
/// `trait Set<K:Eq>`, then the trait reference `Foo: Set<Bar>` is WF
|
/// `trait Set<K:Eq>`, then the trait reference `Foo: Set<Bar>` is WF
|
||||||
/// if `Bar: Eq`.
|
/// if `Bar: Eq`.
|
||||||
pub fn trait_obligations<'a, 'gcx, 'tcx>(infcx: &InferCtxt<'a, 'gcx, 'tcx>,
|
pub fn trait_obligations<'a, 'gcx, 'tcx>(infcx: &InferCtxt<'a, 'gcx, 'tcx>,
|
||||||
|
param_env: ty::ParamEnv<'tcx>,
|
||||||
body_id: ast::NodeId,
|
body_id: ast::NodeId,
|
||||||
trait_ref: &ty::TraitRef<'tcx>,
|
trait_ref: &ty::TraitRef<'tcx>,
|
||||||
span: Span)
|
span: Span)
|
||||||
-> Vec<traits::PredicateObligation<'tcx>>
|
-> Vec<traits::PredicateObligation<'tcx>>
|
||||||
{
|
{
|
||||||
let mut wf = WfPredicates { infcx: infcx, body_id: body_id, span: span, out: vec![] };
|
let mut wf = WfPredicates { infcx, param_env, body_id, span, out: vec![] };
|
||||||
wf.compute_trait_ref(trait_ref);
|
wf.compute_trait_ref(trait_ref);
|
||||||
wf.normalize()
|
wf.normalize()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn predicate_obligations<'a, 'gcx, 'tcx>(infcx: &InferCtxt<'a, 'gcx, 'tcx>,
|
pub fn predicate_obligations<'a, 'gcx, 'tcx>(infcx: &InferCtxt<'a, 'gcx, 'tcx>,
|
||||||
|
param_env: ty::ParamEnv<'tcx>,
|
||||||
body_id: ast::NodeId,
|
body_id: ast::NodeId,
|
||||||
predicate: &ty::Predicate<'tcx>,
|
predicate: &ty::Predicate<'tcx>,
|
||||||
span: Span)
|
span: Span)
|
||||||
-> Vec<traits::PredicateObligation<'tcx>>
|
-> Vec<traits::PredicateObligation<'tcx>>
|
||||||
{
|
{
|
||||||
let mut wf = WfPredicates { infcx: infcx, body_id: body_id, span: span, out: vec![] };
|
let mut wf = WfPredicates { infcx, param_env, body_id, span, out: vec![] };
|
||||||
|
|
||||||
// (*) ok to skip binders, because wf code is prepared for it
|
// (*) ok to skip binders, because wf code is prepared for it
|
||||||
match *predicate {
|
match *predicate {
|
||||||
|
@ -126,6 +130,7 @@ pub enum ImpliedBound<'tcx> {
|
||||||
/// the `ImpliedBound` type for more details.
|
/// the `ImpliedBound` type for more details.
|
||||||
pub fn implied_bounds<'a, 'gcx, 'tcx>(
|
pub fn implied_bounds<'a, 'gcx, 'tcx>(
|
||||||
infcx: &'a InferCtxt<'a, 'gcx, 'tcx>,
|
infcx: &'a InferCtxt<'a, 'gcx, 'tcx>,
|
||||||
|
param_env: ty::ParamEnv<'tcx>,
|
||||||
body_id: ast::NodeId,
|
body_id: ast::NodeId,
|
||||||
ty: Ty<'tcx>,
|
ty: Ty<'tcx>,
|
||||||
span: Span)
|
span: Span)
|
||||||
|
@ -148,7 +153,7 @@ pub fn implied_bounds<'a, 'gcx, 'tcx>(
|
||||||
// than the ultimate set. (Note: normally there won't be
|
// than the ultimate set. (Note: normally there won't be
|
||||||
// unresolved inference variables here anyway, but there might be
|
// unresolved inference variables here anyway, but there might be
|
||||||
// during typeck under some circumstances.)
|
// during typeck under some circumstances.)
|
||||||
let obligations = obligations(infcx, body_id, ty, span).unwrap_or(vec![]);
|
let obligations = obligations(infcx, param_env, body_id, ty, span).unwrap_or(vec![]);
|
||||||
|
|
||||||
// From the full set of obligations, just filter down to the
|
// From the full set of obligations, just filter down to the
|
||||||
// region relationships.
|
// region relationships.
|
||||||
|
@ -231,6 +236,7 @@ fn implied_bounds_from_components<'tcx>(sub_region: ty::Region<'tcx>,
|
||||||
|
|
||||||
struct WfPredicates<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
|
struct WfPredicates<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
|
||||||
infcx: &'a InferCtxt<'a, 'gcx, 'tcx>,
|
infcx: &'a InferCtxt<'a, 'gcx, 'tcx>,
|
||||||
|
param_env: ty::ParamEnv<'tcx>,
|
||||||
body_id: ast::NodeId,
|
body_id: ast::NodeId,
|
||||||
span: Span,
|
span: Span,
|
||||||
out: Vec<traits::PredicateObligation<'tcx>>,
|
out: Vec<traits::PredicateObligation<'tcx>>,
|
||||||
|
@ -244,11 +250,12 @@ impl<'a, 'gcx, 'tcx> WfPredicates<'a, 'gcx, 'tcx> {
|
||||||
fn normalize(&mut self) -> Vec<traits::PredicateObligation<'tcx>> {
|
fn normalize(&mut self) -> Vec<traits::PredicateObligation<'tcx>> {
|
||||||
let cause = self.cause(traits::MiscObligation);
|
let cause = self.cause(traits::MiscObligation);
|
||||||
let infcx = &mut self.infcx;
|
let infcx = &mut self.infcx;
|
||||||
|
let param_env = self.param_env;
|
||||||
self.out.iter()
|
self.out.iter()
|
||||||
.inspect(|pred| assert!(!pred.has_escaping_regions()))
|
.inspect(|pred| assert!(!pred.has_escaping_regions()))
|
||||||
.flat_map(|pred| {
|
.flat_map(|pred| {
|
||||||
let mut selcx = traits::SelectionContext::new(infcx);
|
let mut selcx = traits::SelectionContext::new(infcx);
|
||||||
let pred = traits::normalize(&mut selcx, cause.clone(), pred);
|
let pred = traits::normalize(&mut selcx, param_env, cause.clone(), pred);
|
||||||
once(pred.value).chain(pred.obligations)
|
once(pred.value).chain(pred.obligations)
|
||||||
})
|
})
|
||||||
.collect()
|
.collect()
|
||||||
|
@ -261,10 +268,12 @@ impl<'a, 'gcx, 'tcx> WfPredicates<'a, 'gcx, 'tcx> {
|
||||||
self.out.extend(obligations);
|
self.out.extend(obligations);
|
||||||
|
|
||||||
let cause = self.cause(traits::MiscObligation);
|
let cause = self.cause(traits::MiscObligation);
|
||||||
|
let param_env = self.param_env;
|
||||||
self.out.extend(
|
self.out.extend(
|
||||||
trait_ref.substs.types()
|
trait_ref.substs.types()
|
||||||
.filter(|ty| !ty.has_escaping_regions())
|
.filter(|ty| !ty.has_escaping_regions())
|
||||||
.map(|ty| traits::Obligation::new(cause.clone(),
|
.map(|ty| traits::Obligation::new(cause.clone(),
|
||||||
|
param_env,
|
||||||
ty::Predicate::WellFormed(ty))));
|
ty::Predicate::WellFormed(ty))));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -280,7 +289,7 @@ impl<'a, 'gcx, 'tcx> WfPredicates<'a, 'gcx, 'tcx> {
|
||||||
if !data.has_escaping_regions() {
|
if !data.has_escaping_regions() {
|
||||||
let predicate = data.trait_ref.to_predicate();
|
let predicate = data.trait_ref.to_predicate();
|
||||||
let cause = self.cause(traits::ProjectionWf(data));
|
let cause = self.cause(traits::ProjectionWf(data));
|
||||||
self.out.push(traits::Obligation::new(cause, predicate));
|
self.out.push(traits::Obligation::new(cause, self.param_env, predicate));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -291,7 +300,7 @@ impl<'a, 'gcx, 'tcx> WfPredicates<'a, 'gcx, 'tcx> {
|
||||||
def_id: self.infcx.tcx.require_lang_item(lang_items::SizedTraitLangItem),
|
def_id: self.infcx.tcx.require_lang_item(lang_items::SizedTraitLangItem),
|
||||||
substs: self.infcx.tcx.mk_substs_trait(subty, &[]),
|
substs: self.infcx.tcx.mk_substs_trait(subty, &[]),
|
||||||
};
|
};
|
||||||
self.out.push(traits::Obligation::new(cause, trait_ref.to_predicate()));
|
self.out.push(traits::Obligation::new(cause, self.param_env, trait_ref.to_predicate()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -301,6 +310,7 @@ impl<'a, 'gcx, 'tcx> WfPredicates<'a, 'gcx, 'tcx> {
|
||||||
/// in which case we are not able to simplify at all.
|
/// in which case we are not able to simplify at all.
|
||||||
fn compute(&mut self, ty0: Ty<'tcx>) -> bool {
|
fn compute(&mut self, ty0: Ty<'tcx>) -> bool {
|
||||||
let mut subtys = ty0.walk();
|
let mut subtys = ty0.walk();
|
||||||
|
let param_env = self.param_env;
|
||||||
while let Some(ty) = subtys.next() {
|
while let Some(ty) = subtys.next() {
|
||||||
match ty.sty {
|
match ty.sty {
|
||||||
ty::TyBool |
|
ty::TyBool |
|
||||||
|
@ -350,6 +360,7 @@ impl<'a, 'gcx, 'tcx> WfPredicates<'a, 'gcx, 'tcx> {
|
||||||
self.out.push(
|
self.out.push(
|
||||||
traits::Obligation::new(
|
traits::Obligation::new(
|
||||||
cause,
|
cause,
|
||||||
|
param_env,
|
||||||
ty::Predicate::TypeOutlives(
|
ty::Predicate::TypeOutlives(
|
||||||
ty::Binder(
|
ty::Binder(
|
||||||
ty::OutlivesPredicate(mt.ty, r)))));
|
ty::OutlivesPredicate(mt.ty, r)))));
|
||||||
|
@ -389,12 +400,12 @@ impl<'a, 'gcx, 'tcx> WfPredicates<'a, 'gcx, 'tcx> {
|
||||||
// checking those
|
// checking those
|
||||||
|
|
||||||
let cause = self.cause(traits::MiscObligation);
|
let cause = self.cause(traits::MiscObligation);
|
||||||
|
|
||||||
let component_traits =
|
let component_traits =
|
||||||
data.auto_traits().chain(data.principal().map(|p| p.def_id()));
|
data.auto_traits().chain(data.principal().map(|p| p.def_id()));
|
||||||
self.out.extend(
|
self.out.extend(
|
||||||
component_traits.map(|did| traits::Obligation::new(
|
component_traits.map(|did| traits::Obligation::new(
|
||||||
cause.clone(),
|
cause.clone(),
|
||||||
|
param_env,
|
||||||
ty::Predicate::ObjectSafe(did)
|
ty::Predicate::ObjectSafe(did)
|
||||||
))
|
))
|
||||||
);
|
);
|
||||||
|
@ -422,7 +433,9 @@ impl<'a, 'gcx, 'tcx> WfPredicates<'a, 'gcx, 'tcx> {
|
||||||
|
|
||||||
let cause = self.cause(traits::MiscObligation);
|
let cause = self.cause(traits::MiscObligation);
|
||||||
self.out.push( // ...not the type we started from, so we made progress.
|
self.out.push( // ...not the type we started from, so we made progress.
|
||||||
traits::Obligation::new(cause, ty::Predicate::WellFormed(ty)));
|
traits::Obligation::new(cause,
|
||||||
|
self.param_env,
|
||||||
|
ty::Predicate::WellFormed(ty)));
|
||||||
} else {
|
} else {
|
||||||
// Yes, resolved, proceed with the
|
// Yes, resolved, proceed with the
|
||||||
// result. Should never return false because
|
// result. Should never return false because
|
||||||
|
@ -448,7 +461,9 @@ impl<'a, 'gcx, 'tcx> WfPredicates<'a, 'gcx, 'tcx> {
|
||||||
let cause = self.cause(traits::ItemObligation(def_id));
|
let cause = self.cause(traits::ItemObligation(def_id));
|
||||||
predicates.predicates
|
predicates.predicates
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|pred| traits::Obligation::new(cause.clone(), pred))
|
.map(|pred| traits::Obligation::new(cause.clone(),
|
||||||
|
self.param_env,
|
||||||
|
pred))
|
||||||
.filter(|pred| !pred.has_escaping_regions())
|
.filter(|pred| !pred.has_escaping_regions())
|
||||||
.collect()
|
.collect()
|
||||||
}
|
}
|
||||||
|
@ -497,7 +512,9 @@ impl<'a, 'gcx, 'tcx> WfPredicates<'a, 'gcx, 'tcx> {
|
||||||
for implicit_bound in implicit_bounds {
|
for implicit_bound in implicit_bounds {
|
||||||
let cause = self.cause(traits::ObjectTypeBound(ty, explicit_bound));
|
let cause = self.cause(traits::ObjectTypeBound(ty, explicit_bound));
|
||||||
let outlives = ty::Binder(ty::OutlivesPredicate(explicit_bound, implicit_bound));
|
let outlives = ty::Binder(ty::OutlivesPredicate(explicit_bound, implicit_bound));
|
||||||
self.out.push(traits::Obligation::new(cause, outlives.to_predicate()));
|
self.out.push(traits::Obligation::new(cause,
|
||||||
|
self.param_env,
|
||||||
|
outlives.to_predicate()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -90,7 +90,7 @@ struct CheckLoanCtxt<'a, 'tcx: 'a> {
|
||||||
dfcx_loans: &'a LoanDataFlow<'a, 'tcx>,
|
dfcx_loans: &'a LoanDataFlow<'a, 'tcx>,
|
||||||
move_data: &'a move_data::FlowedMoveData<'a, 'tcx>,
|
move_data: &'a move_data::FlowedMoveData<'a, 'tcx>,
|
||||||
all_loans: &'a [Loan<'tcx>],
|
all_loans: &'a [Loan<'tcx>],
|
||||||
param_env: &'a ty::ParamEnv<'tcx>,
|
param_env: ty::ParamEnv<'tcx>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'tcx> euv::Delegate<'tcx> for CheckLoanCtxt<'a, 'tcx> {
|
impl<'a, 'tcx> euv::Delegate<'tcx> for CheckLoanCtxt<'a, 'tcx> {
|
||||||
|
@ -191,15 +191,17 @@ pub fn check_loans<'a, 'b, 'c, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>,
|
||||||
body: &hir::Body) {
|
body: &hir::Body) {
|
||||||
debug!("check_loans(body id={})", body.value.id);
|
debug!("check_loans(body id={})", body.value.id);
|
||||||
|
|
||||||
|
let def_id = bccx.tcx.hir.body_owner_def_id(body.id());
|
||||||
let infcx = bccx.tcx.borrowck_fake_infer_ctxt(body.id());
|
let infcx = bccx.tcx.borrowck_fake_infer_ctxt(body.id());
|
||||||
|
let param_env = bccx.tcx.param_env(def_id);
|
||||||
let mut clcx = CheckLoanCtxt {
|
let mut clcx = CheckLoanCtxt {
|
||||||
bccx: bccx,
|
bccx: bccx,
|
||||||
dfcx_loans: dfcx_loans,
|
dfcx_loans: dfcx_loans,
|
||||||
move_data: move_data,
|
move_data: move_data,
|
||||||
all_loans: all_loans,
|
all_loans: all_loans,
|
||||||
param_env: &infcx.param_env
|
param_env,
|
||||||
};
|
};
|
||||||
euv::ExprUseVisitor::new(&mut clcx, &bccx.region_maps, &infcx).consume_body(body);
|
euv::ExprUseVisitor::new(&mut clcx, &bccx.region_maps, &infcx, param_env).consume_body(body);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(PartialEq)]
|
#[derive(PartialEq)]
|
||||||
|
|
|
@ -38,9 +38,10 @@ mod move_error;
|
||||||
|
|
||||||
pub fn gather_loans_in_fn<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>,
|
pub fn gather_loans_in_fn<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>,
|
||||||
body: hir::BodyId)
|
body: hir::BodyId)
|
||||||
-> (Vec<Loan<'tcx>>,
|
-> (Vec<Loan<'tcx>>, move_data::MoveData<'tcx>) {
|
||||||
move_data::MoveData<'tcx>) {
|
let def_id = bccx.tcx.hir.body_owner_def_id(body);
|
||||||
let infcx = bccx.tcx.borrowck_fake_infer_ctxt(body);
|
let infcx = bccx.tcx.borrowck_fake_infer_ctxt(body);
|
||||||
|
let param_env = bccx.tcx.param_env(def_id);
|
||||||
let mut glcx = GatherLoanCtxt {
|
let mut glcx = GatherLoanCtxt {
|
||||||
bccx: bccx,
|
bccx: bccx,
|
||||||
infcx: &infcx,
|
infcx: &infcx,
|
||||||
|
@ -51,7 +52,7 @@ pub fn gather_loans_in_fn<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>,
|
||||||
};
|
};
|
||||||
|
|
||||||
let body = glcx.bccx.tcx.hir.body(body);
|
let body = glcx.bccx.tcx.hir.body(body);
|
||||||
euv::ExprUseVisitor::new(&mut glcx, &bccx.region_maps, &infcx).consume_body(body);
|
euv::ExprUseVisitor::new(&mut glcx, &bccx.region_maps, &infcx, param_env).consume_body(body);
|
||||||
|
|
||||||
glcx.report_potential_errors();
|
glcx.report_potential_errors();
|
||||||
let GatherLoanCtxt { all_loans, move_data, .. } = glcx;
|
let GatherLoanCtxt { all_loans, move_data, .. } = glcx;
|
||||||
|
|
|
@ -526,7 +526,7 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> {
|
||||||
lp: &LoanPath<'tcx>,
|
lp: &LoanPath<'tcx>,
|
||||||
the_move: &move_data::Move,
|
the_move: &move_data::Move,
|
||||||
moved_lp: &LoanPath<'tcx>,
|
moved_lp: &LoanPath<'tcx>,
|
||||||
_param_env: &ty::ParamEnv<'tcx>) {
|
_param_env: ty::ParamEnv<'tcx>) {
|
||||||
let (verb, verb_participle) = match use_kind {
|
let (verb, verb_participle) = match use_kind {
|
||||||
MovedInUse => ("use", "used"),
|
MovedInUse => ("use", "used"),
|
||||||
MovedInCapture => ("capture", "captured"),
|
MovedInCapture => ("capture", "captured"),
|
||||||
|
|
|
@ -517,11 +517,11 @@ fn check_legality_of_move_bindings(cx: &MatchVisitor,
|
||||||
///
|
///
|
||||||
/// FIXME: this should be done by borrowck.
|
/// FIXME: this should be done by borrowck.
|
||||||
fn check_for_mutation_in_guard(cx: &MatchVisitor, guard: &hir::Expr) {
|
fn check_for_mutation_in_guard(cx: &MatchVisitor, guard: &hir::Expr) {
|
||||||
cx.tcx.infer_ctxt((cx.tables, cx.param_env)).enter(|infcx| {
|
cx.tcx.infer_ctxt(cx.tables).enter(|infcx| {
|
||||||
let mut checker = MutationChecker {
|
let mut checker = MutationChecker {
|
||||||
cx: cx,
|
cx: cx,
|
||||||
};
|
};
|
||||||
ExprUseVisitor::new(&mut checker, cx.region_maps, &infcx).walk_expr(guard);
|
ExprUseVisitor::new(&mut checker, cx.region_maps, &infcx, cx.param_env).walk_expr(guard);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -483,9 +483,11 @@ fn resolve_trait_associated_const<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||||
debug!("resolve_trait_associated_const: trait_ref={:?}",
|
debug!("resolve_trait_associated_const: trait_ref={:?}",
|
||||||
trait_ref);
|
trait_ref);
|
||||||
|
|
||||||
tcx.infer_ctxt(Reveal::UserFacing).enter(|infcx| {
|
tcx.infer_ctxt(()).enter(|infcx| {
|
||||||
|
let param_env = ty::ParamEnv::empty(Reveal::UserFacing);
|
||||||
let mut selcx = traits::SelectionContext::new(&infcx);
|
let mut selcx = traits::SelectionContext::new(&infcx);
|
||||||
let obligation = traits::Obligation::new(traits::ObligationCause::dummy(),
|
let obligation = traits::Obligation::new(traits::ObligationCause::dummy(),
|
||||||
|
param_env,
|
||||||
trait_ref.to_poly_trait_predicate());
|
trait_ref.to_poly_trait_predicate());
|
||||||
let selection = match selcx.select(&obligation) {
|
let selection = match selcx.select(&obligation) {
|
||||||
Ok(Some(vtable)) => vtable,
|
Ok(Some(vtable)) => vtable,
|
||||||
|
|
|
@ -951,12 +951,13 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnconditionalRecursion {
|
||||||
let trait_ref = ty::TraitRef::from_method(tcx, trait_def_id, callee_substs);
|
let trait_ref = ty::TraitRef::from_method(tcx, trait_def_id, callee_substs);
|
||||||
let trait_ref = ty::Binder(trait_ref);
|
let trait_ref = ty::Binder(trait_ref);
|
||||||
let span = tcx.hir.span(expr_id);
|
let span = tcx.hir.span(expr_id);
|
||||||
|
let param_env = tcx.param_env(method.def_id);
|
||||||
let obligation =
|
let obligation =
|
||||||
traits::Obligation::new(traits::ObligationCause::misc(span, expr_id),
|
traits::Obligation::new(traits::ObligationCause::misc(span, expr_id),
|
||||||
|
param_env,
|
||||||
trait_ref.to_poly_trait_predicate());
|
trait_ref.to_poly_trait_predicate());
|
||||||
|
|
||||||
let param_env = tcx.param_env(method.def_id);
|
tcx.infer_ctxt(()).enter(|infcx| {
|
||||||
tcx.infer_ctxt(param_env).enter(|infcx| {
|
|
||||||
let mut selcx = traits::SelectionContext::new(&infcx);
|
let mut selcx = traits::SelectionContext::new(&infcx);
|
||||||
match selcx.select(&obligation) {
|
match selcx.select(&obligation) {
|
||||||
// The method comes from a `T: Trait` bound.
|
// The method comes from a `T: Trait` bound.
|
||||||
|
|
|
@ -171,8 +171,7 @@ fn create_constructor_shim<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||||
{
|
{
|
||||||
let span = tcx.hir.span(ctor_id);
|
let span = tcx.hir.span(ctor_id);
|
||||||
if let hir::VariantData::Tuple(ref fields, ctor_id) = *v {
|
if let hir::VariantData::Tuple(ref fields, ctor_id) = *v {
|
||||||
let pe = tcx.param_env(tcx.hir.local_def_id(ctor_id));
|
tcx.infer_ctxt(()).enter(|infcx| {
|
||||||
tcx.infer_ctxt(pe).enter(|infcx| {
|
|
||||||
let (mut mir, src) =
|
let (mut mir, src) =
|
||||||
shim::build_adt_ctor(&infcx, ctor_id, fields, span);
|
shim::build_adt_ctor(&infcx, ctor_id, fields, span);
|
||||||
|
|
||||||
|
|
|
@ -35,6 +35,7 @@ use std::rc::Rc;
|
||||||
pub struct Cx<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> {
|
pub struct Cx<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> {
|
||||||
tcx: TyCtxt<'a, 'gcx, 'tcx>,
|
tcx: TyCtxt<'a, 'gcx, 'tcx>,
|
||||||
infcx: &'a InferCtxt<'a, 'gcx, 'tcx>,
|
infcx: &'a InferCtxt<'a, 'gcx, 'tcx>,
|
||||||
|
pub param_env: ty::ParamEnv<'tcx>,
|
||||||
pub region_maps: Rc<RegionMaps>,
|
pub region_maps: Rc<RegionMaps>,
|
||||||
|
|
||||||
/// This is `Constness::Const` if we are compiling a `static`,
|
/// This is `Constness::Const` if we are compiling a `static`,
|
||||||
|
@ -64,6 +65,7 @@ impl<'a, 'gcx, 'tcx> Cx<'a, 'gcx, 'tcx> {
|
||||||
let src_id = src.item_id();
|
let src_id = src.item_id();
|
||||||
let src_def_id = tcx.hir.local_def_id(src_id);
|
let src_def_id = tcx.hir.local_def_id(src_id);
|
||||||
|
|
||||||
|
let param_env = tcx.param_env(src_def_id);
|
||||||
let region_maps = tcx.region_maps(src_def_id);
|
let region_maps = tcx.region_maps(src_def_id);
|
||||||
|
|
||||||
let attrs = tcx.hir.attrs(src_id);
|
let attrs = tcx.hir.attrs(src_id);
|
||||||
|
@ -80,7 +82,7 @@ impl<'a, 'gcx, 'tcx> Cx<'a, 'gcx, 'tcx> {
|
||||||
// Constants and const fn's always need overflow checks.
|
// Constants and const fn's always need overflow checks.
|
||||||
check_overflow |= constness == hir::Constness::Const;
|
check_overflow |= constness == hir::Constness::Const;
|
||||||
|
|
||||||
Cx { tcx, infcx, region_maps, constness, src, check_overflow }
|
Cx { tcx, infcx, param_env, region_maps, constness, src, check_overflow }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -169,12 +171,12 @@ impl<'a, 'gcx, 'tcx> Cx<'a, 'gcx, 'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn needs_drop(&mut self, ty: Ty<'tcx>) -> bool {
|
pub fn needs_drop(&mut self, ty: Ty<'tcx>) -> bool {
|
||||||
let ty = self.tcx.lift_to_global(&ty).unwrap_or_else(|| {
|
let (ty, param_env) = self.tcx.lift_to_global(&(ty, self.param_env)).unwrap_or_else(|| {
|
||||||
bug!("MIR: Cx::needs_drop({}) got \
|
bug!("MIR: Cx::needs_drop({:?}, {:?}) got \
|
||||||
type with inference types/regions",
|
type with inference types/regions",
|
||||||
ty);
|
ty, self.param_env);
|
||||||
});
|
});
|
||||||
ty.needs_drop(self.tcx.global_tcx(), self.infcx.param_env)
|
ty.needs_drop(self.tcx.global_tcx(), param_env)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn tcx(&self) -> TyCtxt<'a, 'gcx, 'tcx> {
|
pub fn tcx(&self) -> TyCtxt<'a, 'gcx, 'tcx> {
|
||||||
|
|
|
@ -998,10 +998,13 @@ impl MirPass for QualifyAndPromoteConstants {
|
||||||
// Statics must be Sync.
|
// Statics must be Sync.
|
||||||
if mode == Mode::Static {
|
if mode == Mode::Static {
|
||||||
let ty = mir.return_ty;
|
let ty = mir.return_ty;
|
||||||
tcx.infer_ctxt(Reveal::UserFacing).enter(|infcx| {
|
tcx.infer_ctxt(()).enter(|infcx| {
|
||||||
|
let param_env = ty::ParamEnv::empty(Reveal::UserFacing);
|
||||||
let cause = traits::ObligationCause::new(mir.span, id, traits::SharedStatic);
|
let cause = traits::ObligationCause::new(mir.span, id, traits::SharedStatic);
|
||||||
let mut fulfillment_cx = traits::FulfillmentContext::new();
|
let mut fulfillment_cx = traits::FulfillmentContext::new();
|
||||||
fulfillment_cx.register_bound(&infcx, ty,
|
fulfillment_cx.register_bound(&infcx,
|
||||||
|
param_env,
|
||||||
|
ty,
|
||||||
tcx.require_lang_item(lang_items::SyncTraitLangItem),
|
tcx.require_lang_item(lang_items::SyncTraitLangItem),
|
||||||
cause);
|
cause);
|
||||||
if let Err(err) = fulfillment_cx.select_all_or_error(&infcx) {
|
if let Err(err) = fulfillment_cx.select_all_or_error(&infcx) {
|
||||||
|
|
|
@ -320,6 +320,7 @@ impl<'a, 'b, 'gcx, 'tcx> TypeVerifier<'a, 'b, 'gcx, 'tcx> {
|
||||||
|
|
||||||
pub struct TypeChecker<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
|
pub struct TypeChecker<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
|
||||||
infcx: &'a InferCtxt<'a, 'gcx, 'tcx>,
|
infcx: &'a InferCtxt<'a, 'gcx, 'tcx>,
|
||||||
|
param_env: ty::ParamEnv<'gcx>,
|
||||||
fulfillment_cx: traits::FulfillmentContext<'tcx>,
|
fulfillment_cx: traits::FulfillmentContext<'tcx>,
|
||||||
last_span: Span,
|
last_span: Span,
|
||||||
body_id: ast::NodeId,
|
body_id: ast::NodeId,
|
||||||
|
@ -327,12 +328,16 @@ pub struct TypeChecker<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
|
impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
|
||||||
fn new(infcx: &'a InferCtxt<'a, 'gcx, 'tcx>, body_id: ast::NodeId) -> Self {
|
fn new(infcx: &'a InferCtxt<'a, 'gcx, 'tcx>,
|
||||||
|
body_id: ast::NodeId,
|
||||||
|
param_env: ty::ParamEnv<'gcx>)
|
||||||
|
-> Self {
|
||||||
TypeChecker {
|
TypeChecker {
|
||||||
infcx: infcx,
|
infcx: infcx,
|
||||||
fulfillment_cx: traits::FulfillmentContext::new(),
|
fulfillment_cx: traits::FulfillmentContext::new(),
|
||||||
last_span: DUMMY_SP,
|
last_span: DUMMY_SP,
|
||||||
body_id: body_id,
|
body_id,
|
||||||
|
param_env,
|
||||||
reported_errors: FxHashSet(),
|
reported_errors: FxHashSet(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -351,14 +356,14 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
|
||||||
fn sub_types(&mut self, sup: Ty<'tcx>, sub: Ty<'tcx>)
|
fn sub_types(&mut self, sup: Ty<'tcx>, sub: Ty<'tcx>)
|
||||||
-> infer::UnitResult<'tcx>
|
-> infer::UnitResult<'tcx>
|
||||||
{
|
{
|
||||||
self.infcx.sub_types(false, &self.misc(self.last_span), sup, sub)
|
self.infcx.sub_types(false, &self.misc(self.last_span), self.param_env, sup, sub)
|
||||||
.map(|ok| self.register_infer_ok_obligations(ok))
|
.map(|ok| self.register_infer_ok_obligations(ok))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn eq_types(&mut self, span: Span, a: Ty<'tcx>, b: Ty<'tcx>)
|
fn eq_types(&mut self, span: Span, a: Ty<'tcx>, b: Ty<'tcx>)
|
||||||
-> infer::UnitResult<'tcx>
|
-> infer::UnitResult<'tcx>
|
||||||
{
|
{
|
||||||
self.infcx.eq_types(false, &self.misc(span), a, b)
|
self.infcx.eq_types(false, &self.misc(span), self.param_env, a, b)
|
||||||
.map(|ok| self.register_infer_ok_obligations(ok))
|
.map(|ok| self.register_infer_ok_obligations(ok))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -665,7 +670,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
|
||||||
|
|
||||||
let span = local_decl.source_info.span;
|
let span = local_decl.source_info.span;
|
||||||
let ty = local_decl.ty;
|
let ty = local_decl.ty;
|
||||||
if !ty.is_sized(self.tcx().global_tcx(), self.infcx.param_env(), span) {
|
if !ty.is_sized(self.tcx().global_tcx(), self.param_env, span) {
|
||||||
// in current MIR construction, all non-control-flow rvalue
|
// in current MIR construction, all non-control-flow rvalue
|
||||||
// expressions evaluate through `as_temp` or `into` a return
|
// expressions evaluate through `as_temp` or `into` a return
|
||||||
// slot or local, so to find all unsized rvalues it is enough
|
// slot or local, so to find all unsized rvalues it is enough
|
||||||
|
@ -706,7 +711,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
|
||||||
let mut selcx = traits::SelectionContext::new(self.infcx);
|
let mut selcx = traits::SelectionContext::new(self.infcx);
|
||||||
let cause = traits::ObligationCause::misc(self.last_span, ast::CRATE_NODE_ID);
|
let cause = traits::ObligationCause::misc(self.last_span, ast::CRATE_NODE_ID);
|
||||||
let traits::Normalized { value, obligations } =
|
let traits::Normalized { value, obligations } =
|
||||||
traits::normalize(&mut selcx, cause, value);
|
traits::normalize(&mut selcx, self.param_env, cause, value);
|
||||||
|
|
||||||
debug!("normalize: value={:?} obligations={:?}",
|
debug!("normalize: value={:?} obligations={:?}",
|
||||||
value,
|
value,
|
||||||
|
@ -752,8 +757,8 @@ impl MirPass for TypeckMir {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let param_env = tcx.param_env(def_id);
|
let param_env = tcx.param_env(def_id);
|
||||||
tcx.infer_ctxt(param_env).enter(|infcx| {
|
tcx.infer_ctxt(()).enter(|infcx| {
|
||||||
let mut checker = TypeChecker::new(&infcx, item_id);
|
let mut checker = TypeChecker::new(&infcx, item_id, param_env);
|
||||||
{
|
{
|
||||||
let mut verifier = TypeVerifier::new(&mut checker, mir);
|
let mut verifier = TypeVerifier::new(&mut checker, mir);
|
||||||
verifier.visit_mir(mir);
|
verifier.visit_mir(mir);
|
||||||
|
|
|
@ -139,10 +139,10 @@ impl<'a, 'tcx> Visitor<'tcx> for CheckCrateVisitor<'a, 'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
let outer_penv = self.tcx.infer_ctxt(body_id).enter(|infcx| {
|
let outer_penv = self.tcx.infer_ctxt(body_id).enter(|infcx| {
|
||||||
let param_env = infcx.param_env.clone();
|
let param_env = self.tcx.param_env(item_def_id);
|
||||||
let outer_penv = mem::replace(&mut self.param_env, param_env);
|
let outer_penv = mem::replace(&mut self.param_env, param_env);
|
||||||
let region_maps = &self.tcx.region_maps(item_def_id);
|
let region_maps = &self.tcx.region_maps(item_def_id);
|
||||||
euv::ExprUseVisitor::new(self, region_maps, &infcx).consume_body(body);
|
euv::ExprUseVisitor::new(self, region_maps, &infcx, param_env).consume_body(body);
|
||||||
outer_penv
|
outer_penv
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -23,12 +23,12 @@ use monomorphize::Instance;
|
||||||
use partitioning::CodegenUnit;
|
use partitioning::CodegenUnit;
|
||||||
use type_::Type;
|
use type_::Type;
|
||||||
use rustc_data_structures::base_n;
|
use rustc_data_structures::base_n;
|
||||||
|
use rustc::session::config::{self, NoDebugInfo};
|
||||||
|
use rustc::session::Session;
|
||||||
use rustc::ty::subst::Substs;
|
use rustc::ty::subst::Substs;
|
||||||
use rustc::ty::{self, Ty, TyCtxt};
|
use rustc::ty::{self, Ty, TyCtxt};
|
||||||
use rustc::ty::layout::{LayoutCx, LayoutError, LayoutTyper, TyLayout};
|
use rustc::ty::layout::{LayoutCx, LayoutError, LayoutTyper, TyLayout};
|
||||||
use session::config::{self, NoDebugInfo};
|
use rustc::util::nodemap::{NodeSet, DefIdMap, FxHashMap};
|
||||||
use session::Session;
|
|
||||||
use util::nodemap::{NodeSet, DefIdMap, FxHashMap};
|
|
||||||
|
|
||||||
use std::ffi::{CStr, CString};
|
use std::ffi::{CStr, CString};
|
||||||
use std::cell::{Cell, RefCell};
|
use std::cell::{Cell, RefCell};
|
||||||
|
|
|
@ -118,13 +118,16 @@ impl<'a, 'gcx, 'tcx> Autoderef<'a, 'gcx, 'tcx> {
|
||||||
let cause = traits::ObligationCause::misc(self.span, self.fcx.body_id);
|
let cause = traits::ObligationCause::misc(self.span, self.fcx.body_id);
|
||||||
|
|
||||||
let mut selcx = traits::SelectionContext::new(self.fcx);
|
let mut selcx = traits::SelectionContext::new(self.fcx);
|
||||||
let obligation = traits::Obligation::new(cause.clone(), trait_ref.to_predicate());
|
let obligation = traits::Obligation::new(cause.clone(),
|
||||||
|
self.fcx.param_env,
|
||||||
|
trait_ref.to_predicate());
|
||||||
if !selcx.evaluate_obligation(&obligation) {
|
if !selcx.evaluate_obligation(&obligation) {
|
||||||
debug!("overloaded_deref_ty: cannot match obligation");
|
debug!("overloaded_deref_ty: cannot match obligation");
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
let normalized = traits::normalize_projection_type(&mut selcx,
|
let normalized = traits::normalize_projection_type(&mut selcx,
|
||||||
|
self.fcx.param_env,
|
||||||
ty::ProjectionTy::from_ref_and_name(
|
ty::ProjectionTy::from_ref_and_name(
|
||||||
tcx,
|
tcx,
|
||||||
trait_ref,
|
trait_ref,
|
||||||
|
|
|
@ -555,6 +555,6 @@ impl<'a, 'gcx, 'tcx> CastCheck<'tcx> {
|
||||||
impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||||
fn type_is_known_to_be_sized(&self, ty: Ty<'tcx>, span: Span) -> bool {
|
fn type_is_known_to_be_sized(&self, ty: Ty<'tcx>, span: Span) -> bool {
|
||||||
let lang_item = self.tcx.require_lang_item(lang_items::SizedTraitLangItem);
|
let lang_item = self.tcx.require_lang_item(lang_items::SizedTraitLangItem);
|
||||||
traits::type_known_to_meet_bound(self, ty, lang_item, span)
|
traits::type_known_to_meet_bound(self, self.param_env, ty, lang_item, span)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -81,9 +81,11 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||||
|
|
||||||
let fn_sig = self.liberate_late_bound_regions(expr_def_id, &sig);
|
let fn_sig = self.liberate_late_bound_regions(expr_def_id, &sig);
|
||||||
let fn_sig = self.inh.normalize_associated_types_in(body.value.span,
|
let fn_sig = self.inh.normalize_associated_types_in(body.value.span,
|
||||||
body.value.id, &fn_sig);
|
body.value.id,
|
||||||
|
self.param_env,
|
||||||
|
&fn_sig);
|
||||||
|
|
||||||
check_fn(self, fn_sig, decl, expr.id, body);
|
check_fn(self, self.param_env, fn_sig, decl, expr.id, body);
|
||||||
|
|
||||||
// Tuple up the arguments and insert the resulting function type into
|
// Tuple up the arguments and insert the resulting function type into
|
||||||
// the `closures` table.
|
// the `closures` table.
|
||||||
|
|
|
@ -137,9 +137,9 @@ impl<'f, 'gcx, 'tcx> Coerce<'f, 'gcx, 'tcx> {
|
||||||
self.commit_if_ok(|_| {
|
self.commit_if_ok(|_| {
|
||||||
let trace = TypeTrace::types(&self.cause, false, a, b);
|
let trace = TypeTrace::types(&self.cause, false, a, b);
|
||||||
if self.use_lub {
|
if self.use_lub {
|
||||||
self.lub(false, trace, &a, &b)
|
self.lub(false, trace, self.fcx.param_env, &a, &b)
|
||||||
} else {
|
} else {
|
||||||
self.sub(false, trace, &a, &b)
|
self.sub(false, trace, self.fcx.param_env, &a, &b)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -511,9 +511,12 @@ impl<'f, 'gcx, 'tcx> Coerce<'f, 'gcx, 'tcx> {
|
||||||
|
|
||||||
// Create an obligation for `Source: CoerceUnsized<Target>`.
|
// Create an obligation for `Source: CoerceUnsized<Target>`.
|
||||||
let cause = ObligationCause::misc(self.cause.span, self.body_id);
|
let cause = ObligationCause::misc(self.cause.span, self.body_id);
|
||||||
queue.push_back(self.tcx
|
queue.push_back(self.tcx.predicate_for_trait_def(self.fcx.param_env,
|
||||||
.predicate_for_trait_def(cause, coerce_unsized_did, 0,
|
cause,
|
||||||
coerce_source, &[coerce_target]));
|
coerce_unsized_did,
|
||||||
|
0,
|
||||||
|
coerce_source,
|
||||||
|
&[coerce_target]));
|
||||||
|
|
||||||
// Keep resolving `CoerceUnsized` and `Unsize` predicates to avoid
|
// Keep resolving `CoerceUnsized` and `Unsize` predicates to avoid
|
||||||
// emitting a coercion in cases like `Foo<$1>` -> `Foo<$2>`, where
|
// emitting a coercion in cases like `Foo<$1>` -> `Foo<$2>`, where
|
||||||
|
@ -775,13 +778,13 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||||
match (&prev_ty.sty, &new_ty.sty) {
|
match (&prev_ty.sty, &new_ty.sty) {
|
||||||
(&ty::TyFnDef(a_def_id, a_substs, a_fty), &ty::TyFnDef(b_def_id, b_substs, b_fty)) => {
|
(&ty::TyFnDef(a_def_id, a_substs, a_fty), &ty::TyFnDef(b_def_id, b_substs, b_fty)) => {
|
||||||
// The signature must always match.
|
// The signature must always match.
|
||||||
let fty = self.lub(true, trace.clone(), &a_fty, &b_fty)
|
let fty = self.lub(true, trace.clone(), self.param_env, &a_fty, &b_fty)
|
||||||
.map(|ok| self.register_infer_ok_obligations(ok))?;
|
.map(|ok| self.register_infer_ok_obligations(ok))?;
|
||||||
|
|
||||||
if a_def_id == b_def_id {
|
if a_def_id == b_def_id {
|
||||||
// Same function, maybe the parameters match.
|
// Same function, maybe the parameters match.
|
||||||
let substs = self.commit_if_ok(|_| {
|
let substs = self.commit_if_ok(|_| {
|
||||||
self.lub(true, trace.clone(), &a_substs, &b_substs)
|
self.lub(true, trace.clone(), self.param_env, &a_substs, &b_substs)
|
||||||
.map(|ok| self.register_infer_ok_obligations(ok))
|
.map(|ok| self.register_infer_ok_obligations(ok))
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -850,7 +853,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||||
|
|
||||||
if !noop {
|
if !noop {
|
||||||
return self.commit_if_ok(|_| {
|
return self.commit_if_ok(|_| {
|
||||||
self.lub(true, trace.clone(), &prev_ty, &new_ty)
|
self.lub(true, trace.clone(), self.param_env, &prev_ty, &new_ty)
|
||||||
.map(|ok| self.register_infer_ok_obligations(ok))
|
.map(|ok| self.register_infer_ok_obligations(ok))
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -863,7 +866,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||||
Err(e)
|
Err(e)
|
||||||
} else {
|
} else {
|
||||||
self.commit_if_ok(|_| {
|
self.commit_if_ok(|_| {
|
||||||
self.lub(true, trace, &prev_ty, &new_ty)
|
self.lub(true, trace, self.param_env, &prev_ty, &new_ty)
|
||||||
.map(|ok| self.register_infer_ok_obligations(ok))
|
.map(|ok| self.register_infer_ok_obligations(ok))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -1106,7 +1109,7 @@ impl<'gcx, 'tcx, 'exprs, E> CoerceMany<'gcx, 'tcx, 'exprs, E>
|
||||||
// Another example is `break` with no argument expression.
|
// Another example is `break` with no argument expression.
|
||||||
assert!(expression_ty.is_nil());
|
assert!(expression_ty.is_nil());
|
||||||
assert!(expression_ty.is_nil(), "if let hack without unit type");
|
assert!(expression_ty.is_nil(), "if let hack without unit type");
|
||||||
fcx.eq_types(label_expression_as_expected, cause, expression_ty, self.merged_ty())
|
fcx.eq_types(label_expression_as_expected, cause, fcx.param_env, expression_ty, self.merged_ty())
|
||||||
.map(|infer_ok| {
|
.map(|infer_ok| {
|
||||||
fcx.register_infer_ok_obligations(infer_ok);
|
fcx.register_infer_ok_obligations(infer_ok);
|
||||||
expression_ty
|
expression_ty
|
||||||
|
|
|
@ -219,12 +219,12 @@ fn compare_predicate_entailment<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||||
param_env,
|
param_env,
|
||||||
normalize_cause.clone());
|
normalize_cause.clone());
|
||||||
|
|
||||||
tcx.infer_ctxt(param_env).enter(|infcx| {
|
tcx.infer_ctxt(()).enter(|infcx| {
|
||||||
let inh = Inherited::new(infcx, impl_m.def_id);
|
let inh = Inherited::new(infcx, impl_m.def_id);
|
||||||
let infcx = &inh.infcx;
|
let infcx = &inh.infcx;
|
||||||
|
|
||||||
debug!("compare_impl_method: caller_bounds={:?}",
|
debug!("compare_impl_method: caller_bounds={:?}",
|
||||||
infcx.param_env.caller_bounds);
|
param_env.caller_bounds);
|
||||||
|
|
||||||
let mut selcx = traits::SelectionContext::new(&infcx);
|
let mut selcx = traits::SelectionContext::new(&infcx);
|
||||||
|
|
||||||
|
@ -234,10 +234,10 @@ fn compare_predicate_entailment<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||||
&ty::Binder(impl_m_own_bounds.predicates));
|
&ty::Binder(impl_m_own_bounds.predicates));
|
||||||
for predicate in impl_m_own_bounds {
|
for predicate in impl_m_own_bounds {
|
||||||
let traits::Normalized { value: predicate, obligations } =
|
let traits::Normalized { value: predicate, obligations } =
|
||||||
traits::normalize(&mut selcx, normalize_cause.clone(), &predicate);
|
traits::normalize(&mut selcx, param_env, normalize_cause.clone(), &predicate);
|
||||||
|
|
||||||
inh.register_predicates(obligations);
|
inh.register_predicates(obligations);
|
||||||
inh.register_predicate(traits::Obligation::new(cause.clone(), predicate));
|
inh.register_predicate(traits::Obligation::new(cause.clone(), param_env, predicate));
|
||||||
}
|
}
|
||||||
|
|
||||||
// We now need to check that the signature of the impl method is
|
// We now need to check that the signature of the impl method is
|
||||||
|
@ -270,6 +270,7 @@ fn compare_predicate_entailment<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||||
let impl_sig =
|
let impl_sig =
|
||||||
inh.normalize_associated_types_in(impl_m_span,
|
inh.normalize_associated_types_in(impl_m_span,
|
||||||
impl_m_node_id,
|
impl_m_node_id,
|
||||||
|
param_env,
|
||||||
&impl_sig);
|
&impl_sig);
|
||||||
let impl_fty = tcx.mk_fn_ptr(ty::Binder(impl_sig));
|
let impl_fty = tcx.mk_fn_ptr(ty::Binder(impl_sig));
|
||||||
debug!("compare_impl_method: impl_fty={:?}", impl_fty);
|
debug!("compare_impl_method: impl_fty={:?}", impl_fty);
|
||||||
|
@ -282,12 +283,13 @@ fn compare_predicate_entailment<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||||
let trait_sig =
|
let trait_sig =
|
||||||
inh.normalize_associated_types_in(impl_m_span,
|
inh.normalize_associated_types_in(impl_m_span,
|
||||||
impl_m_node_id,
|
impl_m_node_id,
|
||||||
|
param_env,
|
||||||
&trait_sig);
|
&trait_sig);
|
||||||
let trait_fty = tcx.mk_fn_ptr(ty::Binder(trait_sig));
|
let trait_fty = tcx.mk_fn_ptr(ty::Binder(trait_sig));
|
||||||
|
|
||||||
debug!("compare_impl_method: trait_fty={:?}", trait_fty);
|
debug!("compare_impl_method: trait_fty={:?}", trait_fty);
|
||||||
|
|
||||||
let sub_result = infcx.sub_types(false, &cause, impl_fty, trait_fty)
|
let sub_result = infcx.sub_types(false, &cause, param_env, impl_fty, trait_fty)
|
||||||
.map(|InferOk { obligations, .. }| {
|
.map(|InferOk { obligations, .. }| {
|
||||||
inh.register_predicates(obligations);
|
inh.register_predicates(obligations);
|
||||||
});
|
});
|
||||||
|
@ -298,6 +300,7 @@ fn compare_predicate_entailment<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||||
trait_fty);
|
trait_fty);
|
||||||
|
|
||||||
let (impl_err_span, trait_err_span) = extract_spans_for_error_reporting(&infcx,
|
let (impl_err_span, trait_err_span) = extract_spans_for_error_reporting(&infcx,
|
||||||
|
param_env,
|
||||||
&terr,
|
&terr,
|
||||||
&cause,
|
&cause,
|
||||||
impl_m,
|
impl_m,
|
||||||
|
@ -345,11 +348,10 @@ fn compare_predicate_entailment<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||||
// pass around temporarily.
|
// pass around temporarily.
|
||||||
let region_maps = RegionMaps::new();
|
let region_maps = RegionMaps::new();
|
||||||
let mut free_regions = FreeRegionMap::new();
|
let mut free_regions = FreeRegionMap::new();
|
||||||
free_regions.relate_free_regions_from_predicates(
|
free_regions.relate_free_regions_from_predicates(¶m_env.caller_bounds);
|
||||||
&infcx.param_env.caller_bounds);
|
|
||||||
infcx.resolve_regions_and_report_errors(impl_m.def_id, ®ion_maps, &free_regions);
|
infcx.resolve_regions_and_report_errors(impl_m.def_id, ®ion_maps, &free_regions);
|
||||||
} else {
|
} else {
|
||||||
let fcx = FnCtxt::new(&inh, impl_m_node_id);
|
let fcx = FnCtxt::new(&inh, param_env, impl_m_node_id);
|
||||||
fcx.regionck_item(impl_m_node_id, impl_m_span, &[]);
|
fcx.regionck_item(impl_m_node_id, impl_m_span, &[]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -400,6 +402,7 @@ fn check_region_bounds_on_impl_method<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn extract_spans_for_error_reporting<'a, 'gcx, 'tcx>(infcx: &infer::InferCtxt<'a, 'gcx, 'tcx>,
|
fn extract_spans_for_error_reporting<'a, 'gcx, 'tcx>(infcx: &infer::InferCtxt<'a, 'gcx, 'tcx>,
|
||||||
|
param_env: ty::ParamEnv<'tcx>,
|
||||||
terr: &TypeError,
|
terr: &TypeError,
|
||||||
cause: &ObligationCause<'tcx>,
|
cause: &ObligationCause<'tcx>,
|
||||||
impl_m: &ty::AssociatedItem,
|
impl_m: &ty::AssociatedItem,
|
||||||
|
@ -458,14 +461,21 @@ fn extract_spans_for_error_reporting<'a, 'gcx, 'tcx>(infcx: &infer::InferCtxt<'a
|
||||||
.zip(impl_m_iter)
|
.zip(impl_m_iter)
|
||||||
.zip(trait_m_iter)
|
.zip(trait_m_iter)
|
||||||
.filter_map(|(((impl_arg_ty, trait_arg_ty), impl_arg), trait_arg)| {
|
.filter_map(|(((impl_arg_ty, trait_arg_ty), impl_arg), trait_arg)| {
|
||||||
match infcx.sub_types(true, &cause, trait_arg_ty, impl_arg_ty) {
|
match infcx.sub_types(true,
|
||||||
|
&cause,
|
||||||
|
param_env,
|
||||||
|
trait_arg_ty,
|
||||||
|
impl_arg_ty) {
|
||||||
Ok(_) => None,
|
Ok(_) => None,
|
||||||
Err(_) => Some((impl_arg.span, Some(trait_arg.span))),
|
Err(_) => Some((impl_arg.span, Some(trait_arg.span))),
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.next()
|
.next()
|
||||||
.unwrap_or_else(|| {
|
.unwrap_or_else(|| {
|
||||||
if infcx.sub_types(false, &cause, impl_sig.output(),
|
if infcx.sub_types(false,
|
||||||
|
&cause,
|
||||||
|
param_env,
|
||||||
|
impl_sig.output(),
|
||||||
trait_sig.output())
|
trait_sig.output())
|
||||||
.is_err() {
|
.is_err() {
|
||||||
(impl_m_output.span(), Some(trait_m_output.span()))
|
(impl_m_output.span(), Some(trait_m_output.span()))
|
||||||
|
@ -714,7 +724,8 @@ pub fn compare_const_impl<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||||
impl_trait_ref: ty::TraitRef<'tcx>) {
|
impl_trait_ref: ty::TraitRef<'tcx>) {
|
||||||
debug!("compare_const_impl(impl_trait_ref={:?})", impl_trait_ref);
|
debug!("compare_const_impl(impl_trait_ref={:?})", impl_trait_ref);
|
||||||
|
|
||||||
tcx.infer_ctxt(Reveal::UserFacing).enter(|infcx| {
|
tcx.infer_ctxt(()).enter(|infcx| {
|
||||||
|
let param_env = ty::ParamEnv::empty(Reveal::UserFacing);
|
||||||
let inh = Inherited::new(infcx, impl_c.def_id);
|
let inh = Inherited::new(infcx, impl_c.def_id);
|
||||||
let infcx = &inh.infcx;
|
let infcx = &inh.infcx;
|
||||||
|
|
||||||
|
@ -737,17 +748,19 @@ pub fn compare_const_impl<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||||
// There is no "body" here, so just pass dummy id.
|
// There is no "body" here, so just pass dummy id.
|
||||||
let impl_ty = inh.normalize_associated_types_in(impl_c_span,
|
let impl_ty = inh.normalize_associated_types_in(impl_c_span,
|
||||||
impl_c_node_id,
|
impl_c_node_id,
|
||||||
|
param_env,
|
||||||
&impl_ty);
|
&impl_ty);
|
||||||
|
|
||||||
debug!("compare_const_impl: impl_ty={:?}", impl_ty);
|
debug!("compare_const_impl: impl_ty={:?}", impl_ty);
|
||||||
|
|
||||||
let trait_ty = inh.normalize_associated_types_in(impl_c_span,
|
let trait_ty = inh.normalize_associated_types_in(impl_c_span,
|
||||||
impl_c_node_id,
|
impl_c_node_id,
|
||||||
|
param_env,
|
||||||
&trait_ty);
|
&trait_ty);
|
||||||
|
|
||||||
debug!("compare_const_impl: trait_ty={:?}", trait_ty);
|
debug!("compare_const_impl: trait_ty={:?}", trait_ty);
|
||||||
|
|
||||||
let err = infcx.sub_types(false, &cause, impl_ty, trait_ty)
|
let err = infcx.sub_types(false, &cause, param_env, impl_ty, trait_ty)
|
||||||
.map(|ok| inh.register_infer_ok_obligations(ok));
|
.map(|ok| inh.register_infer_ok_obligations(ok));
|
||||||
|
|
||||||
if let Err(terr) = err {
|
if let Err(terr) = err {
|
||||||
|
@ -795,7 +808,7 @@ pub fn compare_const_impl<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let fcx = FnCtxt::new(&inh, impl_c_node_id);
|
let fcx = FnCtxt::new(&inh, param_env, impl_c_node_id);
|
||||||
fcx.regionck_item(impl_c_node_id, impl_c_span, &[]);
|
fcx.regionck_item(impl_c_node_id, impl_c_span, &[]);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,7 +27,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||||
// they don't.
|
// they don't.
|
||||||
pub fn demand_suptype(&self, sp: Span, expected: Ty<'tcx>, actual: Ty<'tcx>) {
|
pub fn demand_suptype(&self, sp: Span, expected: Ty<'tcx>, actual: Ty<'tcx>) {
|
||||||
let cause = self.misc(sp);
|
let cause = self.misc(sp);
|
||||||
match self.sub_types(false, &cause, actual, expected) {
|
match self.sub_types(false, &cause, self.param_env, actual, expected) {
|
||||||
Ok(InferOk { obligations, value: () }) => {
|
Ok(InferOk { obligations, value: () }) => {
|
||||||
self.register_predicates(obligations);
|
self.register_predicates(obligations);
|
||||||
},
|
},
|
||||||
|
@ -54,7 +54,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||||
cause: &ObligationCause<'tcx>,
|
cause: &ObligationCause<'tcx>,
|
||||||
expected: Ty<'tcx>,
|
expected: Ty<'tcx>,
|
||||||
actual: Ty<'tcx>) -> Option<DiagnosticBuilder<'tcx>> {
|
actual: Ty<'tcx>) -> Option<DiagnosticBuilder<'tcx>> {
|
||||||
match self.eq_types(false, cause, actual, expected) {
|
match self.eq_types(false, cause, self.param_env, actual, expected) {
|
||||||
Ok(InferOk { obligations, value: () }) => {
|
Ok(InferOk { obligations, value: () }) => {
|
||||||
self.register_predicates(obligations);
|
self.register_predicates(obligations);
|
||||||
None
|
None
|
||||||
|
|
|
@ -79,8 +79,8 @@ fn ensure_drop_params_and_item_params_correspond<'a, 'tcx>(
|
||||||
|
|
||||||
// check that the impl type can be made to match the trait type.
|
// check that the impl type can be made to match the trait type.
|
||||||
|
|
||||||
let impl_param_env = tcx.param_env(self_type_did);
|
tcx.infer_ctxt(()).enter(|ref infcx| {
|
||||||
tcx.infer_ctxt(impl_param_env).enter(|ref infcx| {
|
let impl_param_env = tcx.param_env(self_type_did);
|
||||||
let tcx = infcx.tcx;
|
let tcx = infcx.tcx;
|
||||||
let mut fulfillment_cx = traits::FulfillmentContext::new();
|
let mut fulfillment_cx = traits::FulfillmentContext::new();
|
||||||
|
|
||||||
|
@ -92,7 +92,7 @@ fn ensure_drop_params_and_item_params_correspond<'a, 'tcx>(
|
||||||
let fresh_impl_self_ty = drop_impl_ty.subst(tcx, fresh_impl_substs);
|
let fresh_impl_self_ty = drop_impl_ty.subst(tcx, fresh_impl_substs);
|
||||||
|
|
||||||
let cause = &ObligationCause::misc(drop_impl_span, drop_impl_node_id);
|
let cause = &ObligationCause::misc(drop_impl_span, drop_impl_node_id);
|
||||||
match infcx.eq_types(true, cause, named_type, fresh_impl_self_ty) {
|
match infcx.eq_types(true, cause, impl_param_env, named_type, fresh_impl_self_ty) {
|
||||||
Ok(InferOk { obligations, .. }) => {
|
Ok(InferOk { obligations, .. }) => {
|
||||||
fulfillment_cx.register_predicate_obligations(infcx, obligations);
|
fulfillment_cx.register_predicate_obligations(infcx, obligations);
|
||||||
}
|
}
|
||||||
|
|
|
@ -340,7 +340,7 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn unify_receivers(&mut self, self_ty: Ty<'tcx>, method_self_ty: Ty<'tcx>) {
|
fn unify_receivers(&mut self, self_ty: Ty<'tcx>, method_self_ty: Ty<'tcx>) {
|
||||||
match self.sub_types(false, &self.misc(self.span), self_ty, method_self_ty) {
|
match self.sub_types(false, &self.misc(self.span), self.param_env, self_ty, method_self_ty) {
|
||||||
Ok(InferOk { obligations, value: () }) => {
|
Ok(InferOk { obligations, value: () }) => {
|
||||||
self.register_predicates(obligations);
|
self.register_predicates(obligations);
|
||||||
}
|
}
|
||||||
|
|
|
@ -205,7 +205,10 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||||
// Construct an obligation
|
// Construct an obligation
|
||||||
let poly_trait_ref = trait_ref.to_poly_trait_ref();
|
let poly_trait_ref = trait_ref.to_poly_trait_ref();
|
||||||
let obligation =
|
let obligation =
|
||||||
traits::Obligation::misc(span, self.body_id, poly_trait_ref.to_predicate());
|
traits::Obligation::misc(span,
|
||||||
|
self.body_id,
|
||||||
|
self.param_env,
|
||||||
|
poly_trait_ref.to_predicate());
|
||||||
|
|
||||||
// Now we want to know if this can be matched
|
// Now we want to know if this can be matched
|
||||||
let mut selcx = traits::SelectionContext::new(self);
|
let mut selcx = traits::SelectionContext::new(self);
|
||||||
|
@ -262,14 +265,18 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||||
assert!(!bounds.has_escaping_regions());
|
assert!(!bounds.has_escaping_regions());
|
||||||
|
|
||||||
let cause = traits::ObligationCause::misc(span, self.body_id);
|
let cause = traits::ObligationCause::misc(span, self.body_id);
|
||||||
obligations.extend(traits::predicates_for_generics(cause.clone(), &bounds));
|
obligations.extend(traits::predicates_for_generics(cause.clone(),
|
||||||
|
self.param_env,
|
||||||
|
&bounds));
|
||||||
|
|
||||||
// Also add an obligation for the method type being well-formed.
|
// Also add an obligation for the method type being well-formed.
|
||||||
let method_ty = tcx.mk_fn_ptr(ty::Binder(fn_sig));
|
let method_ty = tcx.mk_fn_ptr(ty::Binder(fn_sig));
|
||||||
debug!("lookup_in_trait_adjusted: matched method method_ty={:?} obligation={:?}",
|
debug!("lookup_in_trait_adjusted: matched method method_ty={:?} obligation={:?}",
|
||||||
method_ty,
|
method_ty,
|
||||||
obligation);
|
obligation);
|
||||||
obligations.push(traits::Obligation::new(cause, ty::Predicate::WellFormed(method_ty)));
|
obligations.push(traits::Obligation::new(cause,
|
||||||
|
self.param_env,
|
||||||
|
ty::Predicate::WellFormed(method_ty)));
|
||||||
|
|
||||||
let callee = MethodCallee {
|
let callee = MethodCallee {
|
||||||
def_id: def_id,
|
def_id: def_id,
|
||||||
|
|
|
@ -540,7 +540,7 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
|
||||||
let cause = traits::ObligationCause::misc(self.span, self.body_id);
|
let cause = traits::ObligationCause::misc(self.span, self.body_id);
|
||||||
let mut selcx = &mut traits::SelectionContext::new(self.fcx);
|
let mut selcx = &mut traits::SelectionContext::new(self.fcx);
|
||||||
let traits::Normalized { value: xform_self_ty, obligations } =
|
let traits::Normalized { value: xform_self_ty, obligations } =
|
||||||
traits::normalize(selcx, cause, &xform_self_ty);
|
traits::normalize(selcx, self.param_env, cause, &xform_self_ty);
|
||||||
debug!("assemble_inherent_impl_probe: xform_self_ty = {:?}",
|
debug!("assemble_inherent_impl_probe: xform_self_ty = {:?}",
|
||||||
xform_self_ty);
|
xform_self_ty);
|
||||||
|
|
||||||
|
@ -679,7 +679,7 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
|
||||||
let output = fty.output().subst(self.tcx, substs);
|
let output = fty.output().subst(self.tcx, substs);
|
||||||
let (output, _) = self.replace_late_bound_regions_with_fresh_var(
|
let (output, _) = self.replace_late_bound_regions_with_fresh_var(
|
||||||
self.span, infer::FnCall, &output);
|
self.span, infer::FnCall, &output);
|
||||||
self.can_sub_types(output, expected).is_ok()
|
self.can_sub_types(self.param_env, output, expected).is_ok()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
_ => false,
|
_ => false,
|
||||||
|
@ -751,7 +751,7 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
|
||||||
let cause = traits::ObligationCause::misc(self.span, self.body_id);
|
let cause = traits::ObligationCause::misc(self.span, self.body_id);
|
||||||
let mut selcx = &mut traits::SelectionContext::new(self.fcx);
|
let mut selcx = &mut traits::SelectionContext::new(self.fcx);
|
||||||
let traits::Normalized { value: xform_self_ty, obligations } =
|
let traits::Normalized { value: xform_self_ty, obligations } =
|
||||||
traits::normalize(selcx, cause, &xform_self_ty);
|
traits::normalize(selcx, self.param_env, cause, &xform_self_ty);
|
||||||
|
|
||||||
debug!("xform_self_ty={:?}", xform_self_ty);
|
debug!("xform_self_ty={:?}", xform_self_ty);
|
||||||
|
|
||||||
|
@ -885,7 +885,7 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
|
||||||
substs,
|
substs,
|
||||||
bound);
|
bound);
|
||||||
|
|
||||||
if self.can_equate(&step.self_ty, &bound.self_ty()).is_ok() {
|
if self.can_equate(self.param_env, &step.self_ty, &bound.self_ty()).is_ok() {
|
||||||
let xform_self_ty = self.xform_self_ty(&item, bound.self_ty(), bound.substs);
|
let xform_self_ty = self.xform_self_ty(&item, bound.self_ty(), bound.substs);
|
||||||
|
|
||||||
debug!("assemble_projection_candidates: bound={:?} xform_self_ty={:?}",
|
debug!("assemble_projection_candidates: bound={:?} xform_self_ty={:?}",
|
||||||
|
@ -1145,6 +1145,7 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
|
||||||
// First check that the self type can be related.
|
// First check that the self type can be related.
|
||||||
let sub_obligations = match self.sub_types(false,
|
let sub_obligations = match self.sub_types(false,
|
||||||
&ObligationCause::dummy(),
|
&ObligationCause::dummy(),
|
||||||
|
self.param_env,
|
||||||
self_ty,
|
self_ty,
|
||||||
probe.xform_self_ty) {
|
probe.xform_self_ty) {
|
||||||
Ok(InferOk { obligations, value: () }) => obligations,
|
Ok(InferOk { obligations, value: () }) => obligations,
|
||||||
|
@ -1182,10 +1183,10 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
|
||||||
let impl_bounds = self.tcx.predicates_of(impl_def_id);
|
let impl_bounds = self.tcx.predicates_of(impl_def_id);
|
||||||
let impl_bounds = impl_bounds.instantiate(self.tcx, substs);
|
let impl_bounds = impl_bounds.instantiate(self.tcx, substs);
|
||||||
let traits::Normalized { value: impl_bounds, obligations: norm_obligations } =
|
let traits::Normalized { value: impl_bounds, obligations: norm_obligations } =
|
||||||
traits::normalize(selcx, cause.clone(), &impl_bounds);
|
traits::normalize(selcx, self.param_env, cause.clone(), &impl_bounds);
|
||||||
|
|
||||||
// Convert the bounds into obligations.
|
// Convert the bounds into obligations.
|
||||||
let obligations = traits::predicates_for_generics(cause.clone(), &impl_bounds);
|
let obligations = traits::predicates_for_generics(cause.clone(), self.param_env, &impl_bounds);
|
||||||
debug!("impl_obligations={:?}", obligations);
|
debug!("impl_obligations={:?}", obligations);
|
||||||
|
|
||||||
// Evaluate those obligations to see if they might possibly hold.
|
// Evaluate those obligations to see if they might possibly hold.
|
||||||
|
|
|
@ -57,7 +57,10 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||||
let trait_ref = ty::TraitRef::new(fn_once, fn_once_substs);
|
let trait_ref = ty::TraitRef::new(fn_once, fn_once_substs);
|
||||||
let poly_trait_ref = trait_ref.to_poly_trait_ref();
|
let poly_trait_ref = trait_ref.to_poly_trait_ref();
|
||||||
let obligation =
|
let obligation =
|
||||||
Obligation::misc(span, self.body_id, poly_trait_ref.to_predicate());
|
Obligation::misc(span,
|
||||||
|
self.body_id,
|
||||||
|
self.param_env,
|
||||||
|
poly_trait_ref.to_predicate());
|
||||||
SelectionContext::new(self).evaluate_obligation(&obligation)
|
SelectionContext::new(self).evaluate_obligation(&obligation)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
|
@ -450,6 +450,14 @@ impl<'gcx, 'tcx> EnclosingBreakables<'gcx, 'tcx> {
|
||||||
pub struct FnCtxt<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
|
pub struct FnCtxt<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
|
||||||
body_id: ast::NodeId,
|
body_id: ast::NodeId,
|
||||||
|
|
||||||
|
/// The parameter environment used for proving trait obligations
|
||||||
|
/// in this function. This can change when we descend into
|
||||||
|
/// closures (as they bring new things into scope), hence it is
|
||||||
|
/// not part of `Inherited` (as of the time of this writing,
|
||||||
|
/// closures do not yet change the environment, but they will
|
||||||
|
/// eventually).
|
||||||
|
param_env: ty::ParamEnv<'tcx>,
|
||||||
|
|
||||||
// Number of errors that had been reported when we started
|
// Number of errors that had been reported when we started
|
||||||
// checking this function. On exit, if we find that *more* errors
|
// checking this function. On exit, if we find that *more* errors
|
||||||
// have been reported, we will skip regionck and other work that
|
// have been reported, we will skip regionck and other work that
|
||||||
|
@ -528,9 +536,8 @@ impl<'a, 'gcx, 'tcx> Inherited<'a, 'gcx, 'tcx> {
|
||||||
pub fn build(tcx: TyCtxt<'a, 'gcx, 'gcx>, def_id: DefId)
|
pub fn build(tcx: TyCtxt<'a, 'gcx, 'gcx>, def_id: DefId)
|
||||||
-> InheritedBuilder<'a, 'gcx, 'tcx> {
|
-> InheritedBuilder<'a, 'gcx, 'tcx> {
|
||||||
let tables = ty::TypeckTables::empty();
|
let tables = ty::TypeckTables::empty();
|
||||||
let param_env = tcx.param_env(def_id);
|
|
||||||
InheritedBuilder {
|
InheritedBuilder {
|
||||||
infcx: tcx.infer_ctxt((tables, param_env)),
|
infcx: tcx.infer_ctxt(tables),
|
||||||
def_id,
|
def_id,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -590,16 +597,18 @@ impl<'a, 'gcx, 'tcx> Inherited<'a, 'gcx, 'tcx> {
|
||||||
fn normalize_associated_types_in<T>(&self,
|
fn normalize_associated_types_in<T>(&self,
|
||||||
span: Span,
|
span: Span,
|
||||||
body_id: ast::NodeId,
|
body_id: ast::NodeId,
|
||||||
|
param_env: ty::ParamEnv<'tcx>,
|
||||||
value: &T) -> T
|
value: &T) -> T
|
||||||
where T : TypeFoldable<'tcx>
|
where T : TypeFoldable<'tcx>
|
||||||
{
|
{
|
||||||
let ok = self.normalize_associated_types_in_as_infer_ok(span, body_id, value);
|
let ok = self.normalize_associated_types_in_as_infer_ok(span, body_id, param_env, value);
|
||||||
self.register_infer_ok_obligations(ok)
|
self.register_infer_ok_obligations(ok)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn normalize_associated_types_in_as_infer_ok<T>(&self,
|
fn normalize_associated_types_in_as_infer_ok<T>(&self,
|
||||||
span: Span,
|
span: Span,
|
||||||
body_id: ast::NodeId,
|
body_id: ast::NodeId,
|
||||||
|
param_env: ty::ParamEnv<'tcx>,
|
||||||
value: &T)
|
value: &T)
|
||||||
-> InferOk<'tcx, T>
|
-> InferOk<'tcx, T>
|
||||||
where T : TypeFoldable<'tcx>
|
where T : TypeFoldable<'tcx>
|
||||||
|
@ -608,7 +617,7 @@ impl<'a, 'gcx, 'tcx> Inherited<'a, 'gcx, 'tcx> {
|
||||||
let mut selcx = traits::SelectionContext::new(self);
|
let mut selcx = traits::SelectionContext::new(self);
|
||||||
let cause = ObligationCause::misc(span, body_id);
|
let cause = ObligationCause::misc(span, body_id);
|
||||||
let traits::Normalized { value, obligations } =
|
let traits::Normalized { value, obligations } =
|
||||||
traits::normalize(&mut selcx, cause, value);
|
traits::normalize(&mut selcx, param_env, cause, value);
|
||||||
debug!("normalize_associated_types_in: result={:?} predicates={:?}",
|
debug!("normalize_associated_types_in: result={:?} predicates={:?}",
|
||||||
value,
|
value,
|
||||||
obligations);
|
obligations);
|
||||||
|
@ -797,6 +806,7 @@ fn typeck_tables_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||||
let body = tcx.hir.body(body_id);
|
let body = tcx.hir.body(body_id);
|
||||||
|
|
||||||
Inherited::build(tcx, def_id).enter(|inh| {
|
Inherited::build(tcx, def_id).enter(|inh| {
|
||||||
|
let param_env = tcx.param_env(def_id);
|
||||||
let fcx = if let Some(decl) = fn_decl {
|
let fcx = if let Some(decl) = fn_decl {
|
||||||
let fn_sig = tcx.type_of(def_id).fn_sig();
|
let fn_sig = tcx.type_of(def_id).fn_sig();
|
||||||
|
|
||||||
|
@ -806,11 +816,14 @@ fn typeck_tables_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||||
let fn_sig =
|
let fn_sig =
|
||||||
inh.liberate_late_bound_regions(def_id, &fn_sig);
|
inh.liberate_late_bound_regions(def_id, &fn_sig);
|
||||||
let fn_sig =
|
let fn_sig =
|
||||||
inh.normalize_associated_types_in(body.value.span, body_id.node_id, &fn_sig);
|
inh.normalize_associated_types_in(body.value.span,
|
||||||
|
body_id.node_id,
|
||||||
|
param_env,
|
||||||
|
&fn_sig);
|
||||||
|
|
||||||
check_fn(&inh, fn_sig, decl, id, body)
|
check_fn(&inh, param_env, fn_sig, decl, id, body)
|
||||||
} else {
|
} else {
|
||||||
let fcx = FnCtxt::new(&inh, body.value.id);
|
let fcx = FnCtxt::new(&inh, param_env, body.value.id);
|
||||||
let expected_type = tcx.type_of(def_id);
|
let expected_type = tcx.type_of(def_id);
|
||||||
let expected_type = fcx.normalize_associated_types_in(body.value.span, &expected_type);
|
let expected_type = fcx.normalize_associated_types_in(body.value.span, &expected_type);
|
||||||
fcx.require_type_is_sized(expected_type, body.value.span, traits::ConstSized);
|
fcx.require_type_is_sized(expected_type, body.value.span, traits::ConstSized);
|
||||||
|
@ -919,6 +932,7 @@ impl<'a, 'gcx, 'tcx> Visitor<'gcx> for GatherLocalsVisitor<'a, 'gcx, 'tcx> {
|
||||||
/// * ...
|
/// * ...
|
||||||
/// * inherited: other fields inherited from the enclosing fn (if any)
|
/// * inherited: other fields inherited from the enclosing fn (if any)
|
||||||
fn check_fn<'a, 'gcx, 'tcx>(inherited: &'a Inherited<'a, 'gcx, 'tcx>,
|
fn check_fn<'a, 'gcx, 'tcx>(inherited: &'a Inherited<'a, 'gcx, 'tcx>,
|
||||||
|
param_env: ty::ParamEnv<'tcx>,
|
||||||
fn_sig: ty::FnSig<'tcx>,
|
fn_sig: ty::FnSig<'tcx>,
|
||||||
decl: &'gcx hir::FnDecl,
|
decl: &'gcx hir::FnDecl,
|
||||||
fn_id: ast::NodeId,
|
fn_id: ast::NodeId,
|
||||||
|
@ -927,11 +941,11 @@ fn check_fn<'a, 'gcx, 'tcx>(inherited: &'a Inherited<'a, 'gcx, 'tcx>,
|
||||||
{
|
{
|
||||||
let mut fn_sig = fn_sig.clone();
|
let mut fn_sig = fn_sig.clone();
|
||||||
|
|
||||||
debug!("check_fn(sig={:?}, fn_id={})", fn_sig, fn_id);
|
debug!("check_fn(sig={:?}, fn_id={}, param_env={:?})", fn_sig, fn_id, param_env);
|
||||||
|
|
||||||
// Create the function context. This is either derived from scratch or,
|
// Create the function context. This is either derived from scratch or,
|
||||||
// in the case of function expressions, based on the outer context.
|
// in the case of function expressions, based on the outer context.
|
||||||
let mut fcx = FnCtxt::new(inherited, body.value.id);
|
let mut fcx = FnCtxt::new(inherited, param_env, body.value.id);
|
||||||
*fcx.ps.borrow_mut() = UnsafetyState::function(fn_sig.unsafety, fn_id);
|
*fcx.ps.borrow_mut() = UnsafetyState::function(fn_sig.unsafety, fn_id);
|
||||||
|
|
||||||
let ret_ty = fn_sig.output();
|
let ret_ty = fn_sig.output();
|
||||||
|
@ -1633,10 +1647,12 @@ enum TupleArgumentsFlag {
|
||||||
|
|
||||||
impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||||
pub fn new(inh: &'a Inherited<'a, 'gcx, 'tcx>,
|
pub fn new(inh: &'a Inherited<'a, 'gcx, 'tcx>,
|
||||||
|
param_env: ty::ParamEnv<'tcx>,
|
||||||
body_id: ast::NodeId)
|
body_id: ast::NodeId)
|
||||||
-> FnCtxt<'a, 'gcx, 'tcx> {
|
-> FnCtxt<'a, 'gcx, 'tcx> {
|
||||||
FnCtxt {
|
FnCtxt {
|
||||||
body_id: body_id,
|
body_id: body_id,
|
||||||
|
param_env,
|
||||||
err_count_on_creation: inh.tcx.sess.err_count(),
|
err_count_on_creation: inh.tcx.sess.err_count(),
|
||||||
ret_coercion: None,
|
ret_coercion: None,
|
||||||
ps: RefCell::new(UnsafetyState::function(hir::Unsafety::Normal,
|
ps: RefCell::new(UnsafetyState::function(hir::Unsafety::Normal,
|
||||||
|
@ -1870,7 +1886,9 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||||
// Require that the predicate holds for the concrete type.
|
// Require that the predicate holds for the concrete type.
|
||||||
let cause = traits::ObligationCause::new(span, self.body_id,
|
let cause = traits::ObligationCause::new(span, self.body_id,
|
||||||
traits::ReturnType);
|
traits::ReturnType);
|
||||||
self.register_predicate(traits::Obligation::new(cause, predicate));
|
self.register_predicate(traits::Obligation::new(cause,
|
||||||
|
self.param_env,
|
||||||
|
predicate));
|
||||||
}
|
}
|
||||||
|
|
||||||
ty_var
|
ty_var
|
||||||
|
@ -1883,15 +1901,14 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||||
fn normalize_associated_types_in<T>(&self, span: Span, value: &T) -> T
|
fn normalize_associated_types_in<T>(&self, span: Span, value: &T) -> T
|
||||||
where T : TypeFoldable<'tcx>
|
where T : TypeFoldable<'tcx>
|
||||||
{
|
{
|
||||||
let ok = self.normalize_associated_types_in_as_infer_ok(span, value);
|
self.inh.normalize_associated_types_in(span, self.body_id, self.param_env, value)
|
||||||
self.register_infer_ok_obligations(ok)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn normalize_associated_types_in_as_infer_ok<T>(&self, span: Span, value: &T)
|
fn normalize_associated_types_in_as_infer_ok<T>(&self, span: Span, value: &T)
|
||||||
-> InferOk<'tcx, T>
|
-> InferOk<'tcx, T>
|
||||||
where T : TypeFoldable<'tcx>
|
where T : TypeFoldable<'tcx>
|
||||||
{
|
{
|
||||||
self.inh.normalize_associated_types_in_as_infer_ok(span, self.body_id, value)
|
self.inh.normalize_associated_types_in_as_infer_ok(span, self.body_id, self.param_env, value)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn write_nil(&self, node_id: ast::NodeId) {
|
pub fn write_nil(&self, node_id: ast::NodeId) {
|
||||||
|
@ -1929,7 +1946,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||||
cause: traits::ObligationCause<'tcx>)
|
cause: traits::ObligationCause<'tcx>)
|
||||||
{
|
{
|
||||||
self.fulfillment_cx.borrow_mut()
|
self.fulfillment_cx.borrow_mut()
|
||||||
.register_bound(self, ty, def_id, cause);
|
.register_bound(self, self.param_env, ty, def_id, cause);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn to_ty(&self, ast_t: &hir::Ty) -> Ty<'tcx> {
|
pub fn to_ty(&self, ast_t: &hir::Ty) -> Ty<'tcx> {
|
||||||
|
@ -1970,7 +1987,9 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||||
{
|
{
|
||||||
// WF obligations never themselves fail, so no real need to give a detailed cause:
|
// WF obligations never themselves fail, so no real need to give a detailed cause:
|
||||||
let cause = traits::ObligationCause::new(span, self.body_id, code);
|
let cause = traits::ObligationCause::new(span, self.body_id, code);
|
||||||
self.register_predicate(traits::Obligation::new(cause, ty::Predicate::WellFormed(ty)));
|
self.register_predicate(traits::Obligation::new(cause,
|
||||||
|
self.param_env,
|
||||||
|
ty::Predicate::WellFormed(ty)));
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn register_old_wf_obligation(&self,
|
pub fn register_old_wf_obligation(&self,
|
||||||
|
@ -2023,7 +2042,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||||
debug!("add_obligations_for_parameters(predicates={:?})",
|
debug!("add_obligations_for_parameters(predicates={:?})",
|
||||||
predicates);
|
predicates);
|
||||||
|
|
||||||
for obligation in traits::predicates_for_generics(cause, predicates) {
|
for obligation in traits::predicates_for_generics(cause, self.param_env, predicates) {
|
||||||
self.register_predicate(obligation);
|
self.register_predicate(obligation);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2704,7 +2723,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||||
// is polymorphic) and the expected return type.
|
// is polymorphic) and the expected return type.
|
||||||
// No argument expectations are produced if unification fails.
|
// No argument expectations are produced if unification fails.
|
||||||
let origin = self.misc(call_span);
|
let origin = self.misc(call_span);
|
||||||
let ures = self.sub_types(false, &origin, formal_ret, ret_ty);
|
let ures = self.sub_types(false, &origin, self.param_env, formal_ret, ret_ty);
|
||||||
|
|
||||||
// FIXME(#15760) can't use try! here, FromError doesn't default
|
// FIXME(#15760) can't use try! here, FromError doesn't default
|
||||||
// to identity so the resulting type is not constrained.
|
// to identity so the resulting type is not constrained.
|
||||||
|
@ -4199,7 +4218,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||||
_ => return,
|
_ => return,
|
||||||
};
|
};
|
||||||
let last_expr_ty = self.expr_ty(last_expr);
|
let last_expr_ty = self.expr_ty(last_expr);
|
||||||
if self.can_sub_types(last_expr_ty, expected_ty).is_err() {
|
if self.can_sub_types(self.param_env, last_expr_ty, expected_ty).is_err() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let original_span = original_sp(last_stmt.span, blk.span);
|
let original_span = original_sp(last_stmt.span, blk.span);
|
||||||
|
@ -4459,7 +4478,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||||
let ty = self.tcx.type_of(impl_def_id);
|
let ty = self.tcx.type_of(impl_def_id);
|
||||||
|
|
||||||
let impl_ty = self.instantiate_type_scheme(span, &substs, &ty);
|
let impl_ty = self.instantiate_type_scheme(span, &substs, &ty);
|
||||||
match self.sub_types(false, &self.misc(span), self_ty, impl_ty) {
|
match self.sub_types(false, &self.misc(span), self.param_env, self_ty, impl_ty) {
|
||||||
Ok(ok) => self.register_infer_ok_obligations(ok),
|
Ok(ok) => self.register_infer_ok_obligations(ok),
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
span_bug!(span,
|
span_bug!(span,
|
||||||
|
|
|
@ -238,9 +238,15 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||||
lhs_ty);
|
lhs_ty);
|
||||||
|
|
||||||
if let TypeVariants::TyRef(_, ref ty_mut) = lhs_ty.sty {
|
if let TypeVariants::TyRef(_, ref ty_mut) = lhs_ty.sty {
|
||||||
if !self.infcx.type_moves_by_default(ty_mut.ty, lhs_expr.span) &&
|
if {
|
||||||
self.lookup_op_method(ty_mut.ty, &[rhs_ty],
|
!self.infcx.type_moves_by_default(self.param_env,
|
||||||
Op::Binary(op, is_assign)).is_ok() {
|
ty_mut.ty,
|
||||||
|
lhs_expr.span) &&
|
||||||
|
self.lookup_op_method(ty_mut.ty,
|
||||||
|
&[rhs_ty],
|
||||||
|
Op::Binary(op, is_assign))
|
||||||
|
.is_ok()
|
||||||
|
} {
|
||||||
err.note(
|
err.note(
|
||||||
&format!(
|
&format!(
|
||||||
"this is a reference to a type that `{}` can be applied \
|
"this is a reference to a type that `{}` can be applied \
|
||||||
|
|
|
@ -386,7 +386,7 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> {
|
||||||
for &ty in fn_sig_tys {
|
for &ty in fn_sig_tys {
|
||||||
let ty = self.resolve_type(ty);
|
let ty = self.resolve_type(ty);
|
||||||
debug!("relate_free_regions(t={:?})", ty);
|
debug!("relate_free_regions(t={:?})", ty);
|
||||||
let implied_bounds = ty::wf::implied_bounds(self, body_id, ty, span);
|
let implied_bounds = ty::wf::implied_bounds(self, self.fcx.param_env, body_id, ty, span);
|
||||||
|
|
||||||
// Record any relations between free regions that we observe into the free-region-map.
|
// Record any relations between free regions that we observe into the free-region-map.
|
||||||
self.free_region_map.relate_free_regions_from_implied_bounds(&implied_bounds);
|
self.free_region_map.relate_free_regions_from_implied_bounds(&implied_bounds);
|
||||||
|
@ -1660,7 +1660,7 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> {
|
||||||
|
|
||||||
// check whether this predicate applies to our current projection
|
// check whether this predicate applies to our current projection
|
||||||
let cause = self.fcx.misc(span);
|
let cause = self.fcx.misc(span);
|
||||||
match self.eq_types(false, &cause, ty, outlives.0) {
|
match self.eq_types(false, &cause, self.fcx.param_env, ty, outlives.0) {
|
||||||
Ok(ok) => {
|
Ok(ok) => {
|
||||||
self.register_infer_ok_obligations(ok);
|
self.register_infer_ok_obligations(ok);
|
||||||
Ok(outlives.1)
|
Ok(outlives.1)
|
||||||
|
|
|
@ -166,9 +166,11 @@ impl<'a, 'gcx, 'tcx> AdjustBorrowKind<'a, 'gcx, 'tcx> {
|
||||||
{
|
{
|
||||||
let body_owner_def_id = self.fcx.tcx.hir.body_owner_def_id(body.id());
|
let body_owner_def_id = self.fcx.tcx.hir.body_owner_def_id(body.id());
|
||||||
let region_maps = &self.fcx.tcx.region_maps(body_owner_def_id);
|
let region_maps = &self.fcx.tcx.region_maps(body_owner_def_id);
|
||||||
|
let param_env = self.fcx.param_env;
|
||||||
let mut euv =
|
let mut euv =
|
||||||
euv::ExprUseVisitor::with_options(self,
|
euv::ExprUseVisitor::with_options(self,
|
||||||
self.fcx,
|
self.fcx,
|
||||||
|
param_env,
|
||||||
region_maps,
|
region_maps,
|
||||||
mc::MemCategorizationOptions {
|
mc::MemCategorizationOptions {
|
||||||
during_closure_kind_inference: true
|
during_closure_kind_inference: true
|
||||||
|
|
|
@ -37,7 +37,8 @@ struct CheckWfFcxBuilder<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
|
||||||
inherited: super::InheritedBuilder<'a, 'gcx, 'tcx>,
|
inherited: super::InheritedBuilder<'a, 'gcx, 'tcx>,
|
||||||
code: ObligationCauseCode<'gcx>,
|
code: ObligationCauseCode<'gcx>,
|
||||||
id: ast::NodeId,
|
id: ast::NodeId,
|
||||||
span: Span
|
span: Span,
|
||||||
|
param_env: ty::ParamEnv<'tcx>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'gcx, 'tcx> CheckWfFcxBuilder<'a, 'gcx, 'tcx> {
|
impl<'a, 'gcx, 'tcx> CheckWfFcxBuilder<'a, 'gcx, 'tcx> {
|
||||||
|
@ -48,8 +49,9 @@ impl<'a, 'gcx, 'tcx> CheckWfFcxBuilder<'a, 'gcx, 'tcx> {
|
||||||
let code = self.code.clone();
|
let code = self.code.clone();
|
||||||
let id = self.id;
|
let id = self.id;
|
||||||
let span = self.span;
|
let span = self.span;
|
||||||
|
let param_env = self.param_env;
|
||||||
self.inherited.enter(|inh| {
|
self.inherited.enter(|inh| {
|
||||||
let fcx = FnCtxt::new(&inh, id);
|
let fcx = FnCtxt::new(&inh, param_env, id);
|
||||||
let wf_tys = f(&fcx, &mut CheckTypeWellFormedVisitor {
|
let wf_tys = f(&fcx, &mut CheckTypeWellFormedVisitor {
|
||||||
tcx: fcx.tcx.global_tcx(),
|
tcx: fcx.tcx.global_tcx(),
|
||||||
code: code
|
code: code
|
||||||
|
@ -206,11 +208,13 @@ impl<'a, 'gcx> CheckTypeWellFormedVisitor<'a, 'gcx> {
|
||||||
|
|
||||||
fn for_id<'tcx>(&self, id: ast::NodeId, span: Span)
|
fn for_id<'tcx>(&self, id: ast::NodeId, span: Span)
|
||||||
-> CheckWfFcxBuilder<'a, 'gcx, 'tcx> {
|
-> CheckWfFcxBuilder<'a, 'gcx, 'tcx> {
|
||||||
|
let def_id = self.tcx.hir.local_def_id(id);
|
||||||
CheckWfFcxBuilder {
|
CheckWfFcxBuilder {
|
||||||
inherited: Inherited::build(self.tcx, self.tcx.hir.local_def_id(id)),
|
inherited: Inherited::build(self.tcx, def_id),
|
||||||
code: self.code.clone(),
|
code: self.code.clone(),
|
||||||
id: id,
|
id: id,
|
||||||
span: span
|
span: span,
|
||||||
|
param_env: self.tcx.param_env(def_id),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -374,6 +378,7 @@ impl<'a, 'gcx> CheckTypeWellFormedVisitor<'a, 'gcx> {
|
||||||
ast_trait_ref.path.span, &trait_ref);
|
ast_trait_ref.path.span, &trait_ref);
|
||||||
let obligations =
|
let obligations =
|
||||||
ty::wf::trait_obligations(fcx,
|
ty::wf::trait_obligations(fcx,
|
||||||
|
fcx.param_env,
|
||||||
fcx.body_id,
|
fcx.body_id,
|
||||||
&trait_ref,
|
&trait_ref,
|
||||||
ast_trait_ref.path.span);
|
ast_trait_ref.path.span);
|
||||||
|
@ -405,6 +410,7 @@ impl<'a, 'gcx> CheckTypeWellFormedVisitor<'a, 'gcx> {
|
||||||
predicates.predicates
|
predicates.predicates
|
||||||
.iter()
|
.iter()
|
||||||
.flat_map(|p| ty::wf::predicate_obligations(fcx,
|
.flat_map(|p| ty::wf::predicate_obligations(fcx,
|
||||||
|
fcx.param_env,
|
||||||
fcx.body_id,
|
fcx.body_id,
|
||||||
p,
|
p,
|
||||||
span));
|
span));
|
||||||
|
|
|
@ -208,7 +208,7 @@ pub fn coerce_unsized_info<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||||
source,
|
source,
|
||||||
target);
|
target);
|
||||||
|
|
||||||
tcx.infer_ctxt(param_env).enter(|infcx| {
|
tcx.infer_ctxt(()).enter(|infcx| {
|
||||||
let cause = ObligationCause::misc(span, impl_node_id);
|
let cause = ObligationCause::misc(span, impl_node_id);
|
||||||
let check_mutbl = |mt_a: ty::TypeAndMut<'tcx>,
|
let check_mutbl = |mt_a: ty::TypeAndMut<'tcx>,
|
||||||
mt_b: ty::TypeAndMut<'tcx>,
|
mt_b: ty::TypeAndMut<'tcx>,
|
||||||
|
@ -308,7 +308,7 @@ pub fn coerce_unsized_info<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||||
// we may have to evaluate constraint
|
// we may have to evaluate constraint
|
||||||
// expressions in the course of execution.)
|
// expressions in the course of execution.)
|
||||||
// See e.g. #41936.
|
// See e.g. #41936.
|
||||||
if let Ok(ok) = infcx.eq_types(false, &cause, b, a) {
|
if let Ok(ok) = infcx.eq_types(false, &cause, param_env, b, a) {
|
||||||
if ok.obligations.is_empty() {
|
if ok.obligations.is_empty() {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
@ -376,7 +376,12 @@ pub fn coerce_unsized_info<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||||
|
|
||||||
// Register an obligation for `A: Trait<B>`.
|
// Register an obligation for `A: Trait<B>`.
|
||||||
let cause = traits::ObligationCause::misc(span, impl_node_id);
|
let cause = traits::ObligationCause::misc(span, impl_node_id);
|
||||||
let predicate = tcx.predicate_for_trait_def(cause, trait_def_id, 0, source, &[target]);
|
let predicate = tcx.predicate_for_trait_def(param_env,
|
||||||
|
cause,
|
||||||
|
trait_def_id,
|
||||||
|
0,
|
||||||
|
source,
|
||||||
|
&[target]);
|
||||||
fulfill_cx.register_predicate_obligation(&infcx, predicate);
|
fulfill_cx.register_predicate_obligation(&infcx, predicate);
|
||||||
|
|
||||||
// Check that all transitive obligations are satisfied.
|
// Check that all transitive obligations are satisfied.
|
||||||
|
@ -387,8 +392,7 @@ pub fn coerce_unsized_info<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||||
// Finally, resolve all regions.
|
// Finally, resolve all regions.
|
||||||
let region_maps = RegionMaps::new();
|
let region_maps = RegionMaps::new();
|
||||||
let mut free_regions = FreeRegionMap::new();
|
let mut free_regions = FreeRegionMap::new();
|
||||||
free_regions.relate_free_regions_from_predicates(&infcx.param_env
|
free_regions.relate_free_regions_from_predicates(¶m_env.caller_bounds);
|
||||||
.caller_bounds);
|
|
||||||
infcx.resolve_regions_and_report_errors(impl_did, ®ion_maps, &free_regions);
|
infcx.resolve_regions_and_report_errors(impl_did, ®ion_maps, &free_regions);
|
||||||
|
|
||||||
CoerceUnsizedInfo {
|
CoerceUnsizedInfo {
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
use rustc::hir::def_id::{CrateNum, DefId, LOCAL_CRATE};
|
use rustc::hir::def_id::{CrateNum, DefId, LOCAL_CRATE};
|
||||||
use rustc::hir;
|
use rustc::hir;
|
||||||
use rustc::hir::itemlikevisit::ItemLikeVisitor;
|
use rustc::hir::itemlikevisit::ItemLikeVisitor;
|
||||||
use rustc::traits::{self, Reveal};
|
use rustc::traits;
|
||||||
use rustc::ty::{self, TyCtxt};
|
use rustc::ty::{self, TyCtxt};
|
||||||
|
|
||||||
pub fn crate_inherent_impls_overlap_check<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
pub fn crate_inherent_impls_overlap_check<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||||
|
@ -70,7 +70,7 @@ impl<'a, 'tcx> InherentOverlapChecker<'a, 'tcx> {
|
||||||
|
|
||||||
for (i, &impl1_def_id) in impls.iter().enumerate() {
|
for (i, &impl1_def_id) in impls.iter().enumerate() {
|
||||||
for &impl2_def_id in &impls[(i + 1)..] {
|
for &impl2_def_id in &impls[(i + 1)..] {
|
||||||
self.tcx.infer_ctxt(Reveal::UserFacing).enter(|infcx| {
|
self.tcx.infer_ctxt(()).enter(|infcx| {
|
||||||
if traits::overlapping_impls(&infcx, impl1_def_id, impl2_def_id).is_some() {
|
if traits::overlapping_impls(&infcx, impl1_def_id, impl2_def_id).is_some() {
|
||||||
self.check_for_common_items_in_impls(impl1_def_id, impl2_def_id)
|
self.check_for_common_items_in_impls(impl1_def_id, impl2_def_id)
|
||||||
}
|
}
|
||||||
|
|
|
@ -155,9 +155,10 @@ fn require_same_types<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||||
expected: Ty<'tcx>,
|
expected: Ty<'tcx>,
|
||||||
actual: Ty<'tcx>)
|
actual: Ty<'tcx>)
|
||||||
-> bool {
|
-> bool {
|
||||||
tcx.infer_ctxt(Reveal::UserFacing).enter(|ref infcx| {
|
tcx.infer_ctxt(()).enter(|ref infcx| {
|
||||||
|
let param_env = ty::ParamEnv::empty(Reveal::UserFacing);
|
||||||
let mut fulfill_cx = FulfillmentContext::new();
|
let mut fulfill_cx = FulfillmentContext::new();
|
||||||
match infcx.eq_types(false, &cause, expected, actual) {
|
match infcx.eq_types(false, &cause, param_env, expected, actual) {
|
||||||
Ok(InferOk { obligations, .. }) => {
|
Ok(InferOk { obligations, .. }) => {
|
||||||
fulfill_cx.register_predicate_obligations(infcx, obligations);
|
fulfill_cx.register_predicate_obligations(infcx, obligations);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue