1
Fork 0

Auto merge of #35086 - Manishearth:rollup, r=Manishearth

Rollup of 7 pull requests

- Successful merges: #34951, #34963, #34969, #35013, #35037, #35040, #35058
- Failed merges:
This commit is contained in:
bors 2016-07-28 08:19:33 -07:00 committed by GitHub
commit 748ecb1235
18 changed files with 242 additions and 156 deletions

View file

@ -32,22 +32,27 @@ use ty::{self, Ty, TyCtxt};
use ty::TyVar; use ty::TyVar;
use ty::relate::{Relate, RelateResult, TypeRelation}; use ty::relate::{Relate, RelateResult, TypeRelation};
pub struct Bivariate<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { pub struct Bivariate<'combine, 'infcx: 'combine, 'gcx: 'infcx+'tcx, 'tcx: 'infcx> {
fields: CombineFields<'a, 'gcx, 'tcx> fields: &'combine mut CombineFields<'infcx, 'gcx, 'tcx>,
a_is_expected: bool,
} }
impl<'a, 'gcx, 'tcx> Bivariate<'a, 'gcx, 'tcx> { impl<'combine, 'infcx, 'gcx, 'tcx> Bivariate<'combine, 'infcx, 'gcx, 'tcx> {
pub fn new(fields: CombineFields<'a, 'gcx, 'tcx>) -> Bivariate<'a, 'gcx, 'tcx> { pub fn new(fields: &'combine mut CombineFields<'infcx, 'gcx, 'tcx>, a_is_expected: bool)
Bivariate { fields: fields } -> Bivariate<'combine, 'infcx, 'gcx, 'tcx>
{
Bivariate { fields: fields, a_is_expected: a_is_expected }
} }
} }
impl<'a, 'gcx, 'tcx> TypeRelation<'a, 'gcx, 'tcx> for Bivariate<'a, 'gcx, 'tcx> { impl<'combine, 'infcx, 'gcx, 'tcx> TypeRelation<'infcx, 'gcx, 'tcx>
for Bivariate<'combine, 'infcx, 'gcx, 'tcx>
{
fn tag(&self) -> &'static str { "Bivariate" } fn tag(&self) -> &'static str { "Bivariate" }
fn tcx(&self) -> TyCtxt<'a, 'gcx, 'tcx> { self.fields.tcx() } fn tcx(&self) -> TyCtxt<'infcx, 'gcx, 'tcx> { self.fields.tcx() }
fn a_is_expected(&self) -> bool { self.fields.a_is_expected } fn a_is_expected(&self) -> bool { self.a_is_expected }
fn relate_with_variance<T: Relate<'tcx>>(&mut self, fn relate_with_variance<T: Relate<'tcx>>(&mut self,
variance: ty::Variance, variance: ty::Variance,
@ -86,12 +91,12 @@ impl<'a, 'gcx, 'tcx> TypeRelation<'a, 'gcx, 'tcx> for Bivariate<'a, 'gcx, 'tcx>
} }
(&ty::TyInfer(TyVar(a_id)), _) => { (&ty::TyInfer(TyVar(a_id)), _) => {
self.fields.instantiate(b, BiTo, a_id)?; self.fields.instantiate(b, BiTo, a_id, self.a_is_expected)?;
Ok(a) Ok(a)
} }
(_, &ty::TyInfer(TyVar(b_id))) => { (_, &ty::TyInfer(TyVar(b_id))) => {
self.fields.instantiate(a, BiTo, b_id)?; self.fields.instantiate(a, BiTo, b_id, self.a_is_expected)?;
Ok(a) Ok(a)
} }

View file

@ -52,21 +52,20 @@ use syntax::ast;
use syntax_pos::Span; use syntax_pos::Span;
#[derive(Clone)] #[derive(Clone)]
pub struct CombineFields<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { pub struct CombineFields<'infcx, 'gcx: 'infcx+'tcx, 'tcx: 'infcx> {
pub infcx: &'a InferCtxt<'a, 'gcx, 'tcx>, pub infcx: &'infcx InferCtxt<'infcx, 'gcx, 'tcx>,
pub a_is_expected: bool,
pub trace: TypeTrace<'tcx>, pub trace: TypeTrace<'tcx>,
pub cause: Option<ty::relate::Cause>, pub cause: Option<ty::relate::Cause>,
pub obligations: PredicateObligations<'tcx>, pub obligations: PredicateObligations<'tcx>,
} }
impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { impl<'infcx, 'gcx, 'tcx> InferCtxt<'infcx, 'gcx, 'tcx> {
pub fn super_combine_tys<R>(&self, pub fn super_combine_tys<R>(&self,
relation: &mut R, relation: &mut R,
a: Ty<'tcx>, a: Ty<'tcx>,
b: Ty<'tcx>) b: Ty<'tcx>)
-> RelateResult<'tcx, Ty<'tcx>> -> RelateResult<'tcx, Ty<'tcx>>
where R: TypeRelation<'a, 'gcx, 'tcx> where R: TypeRelation<'infcx, 'gcx, 'tcx>
{ {
let a_is_expected = relation.a_is_expected(); let a_is_expected = relation.a_is_expected();
@ -150,42 +149,36 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
} }
} }
impl<'a, 'gcx, 'tcx> CombineFields<'a, 'gcx, 'tcx> { impl<'infcx, 'gcx, 'tcx> CombineFields<'infcx, 'gcx, 'tcx> {
pub fn tcx(&self) -> TyCtxt<'a, 'gcx, 'tcx> { pub fn tcx(&self) -> TyCtxt<'infcx, 'gcx, 'tcx> {
self.infcx.tcx self.infcx.tcx
} }
pub fn switch_expected(&self) -> CombineFields<'a, 'gcx, 'tcx> { pub fn equate<'a>(&'a mut self, a_is_expected: bool) -> Equate<'a, 'infcx, 'gcx, 'tcx> {
CombineFields { Equate::new(self, a_is_expected)
a_is_expected: !self.a_is_expected,
..(*self).clone()
}
} }
pub fn equate(&self) -> Equate<'a, 'gcx, 'tcx> { pub fn bivariate<'a>(&'a mut self, a_is_expected: bool) -> Bivariate<'a, 'infcx, 'gcx, 'tcx> {
Equate::new(self.clone()) Bivariate::new(self, a_is_expected)
} }
pub fn bivariate(&self) -> Bivariate<'a, 'gcx, 'tcx> { pub fn sub<'a>(&'a mut self, a_is_expected: bool) -> Sub<'a, 'infcx, 'gcx, 'tcx> {
Bivariate::new(self.clone()) Sub::new(self, a_is_expected)
} }
pub fn sub(&self) -> Sub<'a, 'gcx, 'tcx> { pub fn lub<'a>(&'a mut self, a_is_expected: bool) -> Lub<'a, 'infcx, 'gcx, 'tcx> {
Sub::new(self.clone()) Lub::new(self, a_is_expected)
} }
pub fn lub(&self) -> Lub<'a, 'gcx, 'tcx> { pub fn glb<'a>(&'a mut self, a_is_expected: bool) -> Glb<'a, 'infcx, 'gcx, 'tcx> {
Lub::new(self.clone()) Glb::new(self, a_is_expected)
} }
pub fn glb(&self) -> Glb<'a, 'gcx, 'tcx> { pub fn instantiate(&mut self,
Glb::new(self.clone())
}
pub fn instantiate(&self,
a_ty: Ty<'tcx>, a_ty: Ty<'tcx>,
dir: RelationDir, dir: RelationDir,
b_vid: ty::TyVid) b_vid: ty::TyVid,
a_is_expected: bool)
-> RelateResult<'tcx, ()> -> RelateResult<'tcx, ()>
{ {
let mut stack = Vec::new(); let mut stack = Vec::new();
@ -255,10 +248,11 @@ impl<'a, 'gcx, 'tcx> CombineFields<'a, 'gcx, 'tcx> {
// to associate causes/spans with each of the relations in // to associate causes/spans with each of the relations in
// the stack to get this right. // the stack to get this right.
match dir { match dir {
BiTo => self.bivariate().relate(&a_ty, &b_ty), BiTo => self.bivariate(a_is_expected).relate(&a_ty, &b_ty),
EqTo => self.equate().relate(&a_ty, &b_ty), EqTo => self.equate(a_is_expected).relate(&a_ty, &b_ty),
SubtypeOf => self.sub().relate(&a_ty, &b_ty), SubtypeOf => self.sub(a_is_expected).relate(&a_ty, &b_ty),
SupertypeOf => self.sub().relate_with_variance(ty::Contravariant, &a_ty, &b_ty), SupertypeOf => self.sub(a_is_expected).relate_with_variance(
ty::Contravariant, &a_ty, &b_ty),
}?; }?;
} }

View file

@ -15,29 +15,29 @@ use super::type_variable::{EqTo};
use ty::{self, Ty, TyCtxt}; use ty::{self, Ty, TyCtxt};
use ty::TyVar; use ty::TyVar;
use ty::relate::{Relate, RelateResult, TypeRelation}; use ty::relate::{Relate, RelateResult, TypeRelation};
use traits::PredicateObligations;
/// Ensures `a` is made equal to `b`. Returns `a` on success. /// Ensures `a` is made equal to `b`. Returns `a` on success.
pub struct Equate<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { pub struct Equate<'combine, 'infcx: 'combine, 'gcx: 'infcx+'tcx, 'tcx: 'infcx> {
fields: CombineFields<'a, 'gcx, 'tcx> fields: &'combine mut CombineFields<'infcx, 'gcx, 'tcx>,
a_is_expected: bool,
} }
impl<'a, 'gcx, 'tcx> Equate<'a, 'gcx, 'tcx> { impl<'combine, 'infcx, 'gcx, 'tcx> Equate<'combine, 'infcx, 'gcx, 'tcx> {
pub fn new(fields: CombineFields<'a, 'gcx, 'tcx>) -> Equate<'a, 'gcx, 'tcx> { pub fn new(fields: &'combine mut CombineFields<'infcx, 'gcx, 'tcx>, a_is_expected: bool)
Equate { fields: fields } -> Equate<'combine, 'infcx, 'gcx, 'tcx>
} {
Equate { fields: fields, a_is_expected: a_is_expected }
pub fn obligations(self) -> PredicateObligations<'tcx> {
self.fields.obligations
} }
} }
impl<'a, 'gcx, 'tcx> TypeRelation<'a, 'gcx, 'tcx> for Equate<'a, 'gcx, 'tcx> { impl<'combine, 'infcx, 'gcx, 'tcx> TypeRelation<'infcx, 'gcx, 'tcx>
for Equate<'combine, 'infcx, 'gcx, 'tcx>
{
fn tag(&self) -> &'static str { "Equate" } fn tag(&self) -> &'static str { "Equate" }
fn tcx(&self) -> TyCtxt<'a, 'gcx, 'tcx> { self.fields.tcx() } fn tcx(&self) -> TyCtxt<'infcx, 'gcx, 'tcx> { self.fields.tcx() }
fn a_is_expected(&self) -> bool { self.fields.a_is_expected } fn a_is_expected(&self) -> bool { self.a_is_expected }
fn relate_with_variance<T: Relate<'tcx>>(&mut self, fn relate_with_variance<T: Relate<'tcx>>(&mut self,
_: ty::Variance, _: ty::Variance,
@ -63,12 +63,12 @@ impl<'a, 'gcx, 'tcx> TypeRelation<'a, 'gcx, 'tcx> for Equate<'a, 'gcx, 'tcx> {
} }
(&ty::TyInfer(TyVar(a_id)), _) => { (&ty::TyInfer(TyVar(a_id)), _) => {
self.fields.instantiate(b, EqTo, a_id)?; self.fields.instantiate(b, EqTo, a_id, self.a_is_expected)?;
Ok(a) Ok(a)
} }
(_, &ty::TyInfer(TyVar(b_id))) => { (_, &ty::TyInfer(TyVar(b_id))) => {
self.fields.instantiate(a, EqTo, b_id)?; self.fields.instantiate(a, EqTo, b_id, self.a_is_expected)?;
Ok(a) Ok(a)
} }
@ -93,7 +93,7 @@ impl<'a, 'gcx, 'tcx> TypeRelation<'a, 'gcx, 'tcx> for Equate<'a, 'gcx, 'tcx> {
-> RelateResult<'tcx, ty::Binder<T>> -> RelateResult<'tcx, ty::Binder<T>>
where T: Relate<'tcx> where T: Relate<'tcx>
{ {
self.fields.higher_ranked_sub(a, b)?; self.fields.higher_ranked_sub(a, b, self.a_is_expected)?;
self.fields.higher_ranked_sub(b, a) self.fields.higher_ranked_sub(b, a, self.a_is_expected)
} }
} }

View file

@ -15,29 +15,29 @@ use super::Subtype;
use ty::{self, Ty, TyCtxt}; use ty::{self, Ty, TyCtxt};
use ty::relate::{Relate, RelateResult, TypeRelation}; use ty::relate::{Relate, RelateResult, TypeRelation};
use traits::PredicateObligations;
/// "Greatest lower bound" (common subtype) /// "Greatest lower bound" (common subtype)
pub struct Glb<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { pub struct Glb<'combine, 'infcx: 'combine, 'gcx: 'infcx+'tcx, 'tcx: 'infcx> {
fields: CombineFields<'a, 'gcx, 'tcx> fields: &'combine mut CombineFields<'infcx, 'gcx, 'tcx>,
a_is_expected: bool,
} }
impl<'a, 'gcx, 'tcx> Glb<'a, 'gcx, 'tcx> { impl<'combine, 'infcx, 'gcx, 'tcx> Glb<'combine, 'infcx, 'gcx, 'tcx> {
pub fn new(fields: CombineFields<'a, 'gcx, 'tcx>) -> Glb<'a, 'gcx, 'tcx> { pub fn new(fields: &'combine mut CombineFields<'infcx, 'gcx, 'tcx>, a_is_expected: bool)
Glb { fields: fields } -> Glb<'combine, 'infcx, 'gcx, 'tcx>
} {
Glb { fields: fields, a_is_expected: a_is_expected }
pub fn obligations(self) -> PredicateObligations<'tcx> {
self.fields.obligations
} }
} }
impl<'a, 'gcx, 'tcx> TypeRelation<'a, 'gcx, 'tcx> for Glb<'a, 'gcx, 'tcx> { impl<'combine, 'infcx, 'gcx, 'tcx> TypeRelation<'infcx, 'gcx, 'tcx>
for Glb<'combine, 'infcx, 'gcx, 'tcx>
{
fn tag(&self) -> &'static str { "Glb" } fn tag(&self) -> &'static str { "Glb" }
fn tcx(&self) -> TyCtxt<'a, 'gcx, 'tcx> { self.fields.tcx() } fn tcx(&self) -> TyCtxt<'infcx, 'gcx, 'tcx> { self.fields.tcx() }
fn a_is_expected(&self) -> bool { self.fields.a_is_expected } fn a_is_expected(&self) -> bool { self.a_is_expected }
fn relate_with_variance<T: Relate<'tcx>>(&mut self, fn relate_with_variance<T: Relate<'tcx>>(&mut self,
variance: ty::Variance, variance: ty::Variance,
@ -46,10 +46,10 @@ impl<'a, 'gcx, 'tcx> TypeRelation<'a, 'gcx, 'tcx> for Glb<'a, 'gcx, 'tcx> {
-> RelateResult<'tcx, T> -> RelateResult<'tcx, T>
{ {
match variance { match variance {
ty::Invariant => self.fields.equate().relate(a, b), ty::Invariant => self.fields.equate(self.a_is_expected).relate(a, b),
ty::Covariant => self.relate(a, b), ty::Covariant => self.relate(a, b),
ty::Bivariant => self.fields.bivariate().relate(a, b), ty::Bivariant => self.fields.bivariate(self.a_is_expected).relate(a, b),
ty::Contravariant => self.fields.lub().relate(a, b), ty::Contravariant => self.fields.lub(self.a_is_expected).relate(a, b),
} }
} }
@ -71,17 +71,19 @@ impl<'a, 'gcx, 'tcx> TypeRelation<'a, 'gcx, 'tcx> for Glb<'a, 'gcx, 'tcx> {
-> RelateResult<'tcx, ty::Binder<T>> -> RelateResult<'tcx, ty::Binder<T>>
where T: Relate<'tcx> where T: Relate<'tcx>
{ {
self.fields.higher_ranked_glb(a, b) self.fields.higher_ranked_glb(a, b, self.a_is_expected)
} }
} }
impl<'a, 'gcx, 'tcx> LatticeDir<'a, 'gcx, 'tcx> for Glb<'a, 'gcx, 'tcx> { impl<'combine, 'infcx, 'gcx, 'tcx> LatticeDir<'infcx, 'gcx, 'tcx>
fn infcx(&self) -> &'a InferCtxt<'a, 'gcx, 'tcx> { for Glb<'combine, 'infcx, 'gcx, 'tcx>
{
fn infcx(&self) -> &'infcx InferCtxt<'infcx, 'gcx, 'tcx> {
self.fields.infcx self.fields.infcx
} }
fn relate_bound(&self, v: Ty<'tcx>, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, ()> { fn relate_bound(&mut self, v: Ty<'tcx>, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, ()> {
let mut sub = self.fields.sub(); let mut sub = self.fields.sub(self.a_is_expected);
sub.relate(&v, &a)?; sub.relate(&v, &a)?;
sub.relate(&v, &b)?; sub.relate(&v, &b)?;
Ok(()) Ok(())

View file

@ -40,7 +40,7 @@ pub struct HrMatchResult<U> {
} }
impl<'a, 'gcx, 'tcx> CombineFields<'a, 'gcx, 'tcx> { impl<'a, 'gcx, 'tcx> CombineFields<'a, 'gcx, 'tcx> {
pub fn higher_ranked_sub<T>(&self, a: &Binder<T>, b: &Binder<T>) pub fn higher_ranked_sub<T>(&mut self, a: &Binder<T>, b: &Binder<T>, a_is_expected: bool)
-> RelateResult<'tcx, Binder<T>> -> RelateResult<'tcx, Binder<T>>
where T: Relate<'tcx> where T: Relate<'tcx>
{ {
@ -77,11 +77,11 @@ impl<'a, 'gcx, 'tcx> CombineFields<'a, 'gcx, 'tcx> {
debug!("b_prime={:?}", b_prime); debug!("b_prime={:?}", b_prime);
// Compare types now that bound regions have been replaced. // Compare types now that bound regions have been replaced.
let result = self.sub().relate(&a_prime, &b_prime)?; let result = self.sub(a_is_expected).relate(&a_prime, &b_prime)?;
// Presuming type comparison succeeds, we need to check // Presuming type comparison succeeds, we need to check
// that the skolemized regions do not "leak". // that the skolemized regions do not "leak".
self.infcx.leak_check(!self.a_is_expected, span, &skol_map, snapshot)?; self.infcx.leak_check(!a_is_expected, span, &skol_map, snapshot)?;
// We are finished with the skolemized regions now so pop // We are finished with the skolemized regions now so pop
// them off. // them off.
@ -106,10 +106,11 @@ impl<'a, 'gcx, 'tcx> CombineFields<'a, 'gcx, 'tcx> {
/// NB. It should not happen that there are LBR appearing in `U` /// NB. It should not happen that there are LBR appearing in `U`
/// that do not appear in `T`. If that happens, those regions are /// that do not appear in `T`. If that happens, those regions are
/// unconstrained, and this routine replaces them with `'static`. /// unconstrained, and this routine replaces them with `'static`.
pub fn higher_ranked_match<T, U>(&self, pub fn higher_ranked_match<T, U>(&mut self,
span: Span, span: Span,
a_pair: &Binder<(T, U)>, a_pair: &Binder<(T, U)>,
b_match: &T) b_match: &T,
a_is_expected: bool)
-> RelateResult<'tcx, HrMatchResult<U>> -> RelateResult<'tcx, HrMatchResult<U>>
where T: Relate<'tcx>, where T: Relate<'tcx>,
U: TypeFoldable<'tcx> U: TypeFoldable<'tcx>
@ -129,7 +130,7 @@ impl<'a, 'gcx, 'tcx> CombineFields<'a, 'gcx, 'tcx> {
debug!("higher_ranked_match: skol_map={:?}", skol_map); debug!("higher_ranked_match: skol_map={:?}", skol_map);
// Equate types now that bound regions have been replaced. // Equate types now that bound regions have been replaced.
try!(self.equate().relate(&a_match, &b_match)); try!(self.equate(a_is_expected).relate(&a_match, &b_match));
// Map each skolemized region to a vector of other regions that it // Map each skolemized region to a vector of other regions that it
// must be equated with. (Note that this vector may include other // must be equated with. (Note that this vector may include other
@ -221,7 +222,7 @@ impl<'a, 'gcx, 'tcx> CombineFields<'a, 'gcx, 'tcx> {
}); });
} }
pub fn higher_ranked_lub<T>(&self, a: &Binder<T>, b: &Binder<T>) pub fn higher_ranked_lub<T>(&mut self, a: &Binder<T>, b: &Binder<T>, a_is_expected: bool)
-> RelateResult<'tcx, Binder<T>> -> RelateResult<'tcx, Binder<T>>
where T: Relate<'tcx> where T: Relate<'tcx>
{ {
@ -239,7 +240,7 @@ impl<'a, 'gcx, 'tcx> CombineFields<'a, 'gcx, 'tcx> {
// Collect constraints. // Collect constraints.
let result0 = let result0 =
self.lub().relate(&a_with_fresh, &b_with_fresh)?; self.lub(a_is_expected).relate(&a_with_fresh, &b_with_fresh)?;
let result0 = let result0 =
self.infcx.resolve_type_vars_if_possible(&result0); self.infcx.resolve_type_vars_if_possible(&result0);
debug!("lub result0 = {:?}", result0); debug!("lub result0 = {:?}", result0);
@ -311,7 +312,7 @@ impl<'a, 'gcx, 'tcx> CombineFields<'a, 'gcx, 'tcx> {
} }
} }
pub fn higher_ranked_glb<T>(&self, a: &Binder<T>, b: &Binder<T>) pub fn higher_ranked_glb<T>(&mut self, a: &Binder<T>, b: &Binder<T>, a_is_expected: bool)
-> RelateResult<'tcx, Binder<T>> -> RelateResult<'tcx, Binder<T>>
where T: Relate<'tcx> where T: Relate<'tcx>
{ {
@ -333,7 +334,7 @@ impl<'a, 'gcx, 'tcx> CombineFields<'a, 'gcx, 'tcx> {
// Collect constraints. // Collect constraints.
let result0 = let result0 =
self.glb().relate(&a_with_fresh, &b_with_fresh)?; self.glb(a_is_expected).relate(&a_with_fresh, &b_with_fresh)?;
let result0 = let result0 =
self.infcx.resolve_type_vars_if_possible(&result0); self.infcx.resolve_type_vars_if_possible(&result0);
debug!("glb result0 = {:?}", result0); debug!("glb result0 = {:?}", result0);

View file

@ -40,7 +40,7 @@ pub trait LatticeDir<'f, 'gcx: 'f+'tcx, 'tcx: 'f> : TypeRelation<'f, 'gcx, 'tcx>
// Relates the type `v` to `a` and `b` such that `v` represents // Relates the type `v` to `a` and `b` such that `v` represents
// the LUB/GLB of `a` and `b` as appropriate. // the LUB/GLB of `a` and `b` as appropriate.
fn relate_bound(&self, v: Ty<'tcx>, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, ()>; fn relate_bound(&mut self, v: Ty<'tcx>, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, ()>;
} }
pub fn super_lattice_tys<'a, 'gcx, 'tcx, L>(this: &mut L, pub fn super_lattice_tys<'a, 'gcx, 'tcx, L>(this: &mut L,

View file

@ -15,29 +15,29 @@ use super::Subtype;
use ty::{self, Ty, TyCtxt}; use ty::{self, Ty, TyCtxt};
use ty::relate::{Relate, RelateResult, TypeRelation}; use ty::relate::{Relate, RelateResult, TypeRelation};
use traits::PredicateObligations;
/// "Least upper bound" (common supertype) /// "Least upper bound" (common supertype)
pub struct Lub<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { pub struct Lub<'combine, 'infcx: 'combine, 'gcx: 'infcx+'tcx, 'tcx: 'infcx> {
fields: CombineFields<'a, 'gcx, 'tcx> fields: &'combine mut CombineFields<'infcx, 'gcx, 'tcx>,
a_is_expected: bool,
} }
impl<'a, 'gcx, 'tcx> Lub<'a, 'gcx, 'tcx> { impl<'combine, 'infcx, 'gcx, 'tcx> Lub<'combine, 'infcx, 'gcx, 'tcx> {
pub fn new(fields: CombineFields<'a, 'gcx, 'tcx>) -> Lub<'a, 'gcx, 'tcx> { pub fn new(fields: &'combine mut CombineFields<'infcx, 'gcx, 'tcx>, a_is_expected: bool)
Lub { fields: fields } -> Lub<'combine, 'infcx, 'gcx, 'tcx>
} {
Lub { fields: fields, a_is_expected: a_is_expected }
pub fn obligations(self) -> PredicateObligations<'tcx> {
self.fields.obligations
} }
} }
impl<'a, 'gcx, 'tcx> TypeRelation<'a, 'gcx, 'tcx> for Lub<'a, 'gcx, 'tcx> { impl<'combine, 'infcx, 'gcx, 'tcx> TypeRelation<'infcx, 'gcx, 'tcx>
for Lub<'combine, 'infcx, 'gcx, 'tcx>
{
fn tag(&self) -> &'static str { "Lub" } fn tag(&self) -> &'static str { "Lub" }
fn tcx(&self) -> TyCtxt<'a, 'gcx, 'tcx> { self.fields.tcx() } fn tcx(&self) -> TyCtxt<'infcx, 'gcx, 'tcx> { self.fields.tcx() }
fn a_is_expected(&self) -> bool { self.fields.a_is_expected } fn a_is_expected(&self) -> bool { self.a_is_expected }
fn relate_with_variance<T: Relate<'tcx>>(&mut self, fn relate_with_variance<T: Relate<'tcx>>(&mut self,
variance: ty::Variance, variance: ty::Variance,
@ -46,10 +46,10 @@ impl<'a, 'gcx, 'tcx> TypeRelation<'a, 'gcx, 'tcx> for Lub<'a, 'gcx, 'tcx> {
-> RelateResult<'tcx, T> -> RelateResult<'tcx, T>
{ {
match variance { match variance {
ty::Invariant => self.fields.equate().relate(a, b), ty::Invariant => self.fields.equate(self.a_is_expected).relate(a, b),
ty::Covariant => self.relate(a, b), ty::Covariant => self.relate(a, b),
ty::Bivariant => self.fields.bivariate().relate(a, b), ty::Bivariant => self.fields.bivariate(self.a_is_expected).relate(a, b),
ty::Contravariant => self.fields.glb().relate(a, b), ty::Contravariant => self.fields.glb(self.a_is_expected).relate(a, b),
} }
} }
@ -71,17 +71,19 @@ impl<'a, 'gcx, 'tcx> TypeRelation<'a, 'gcx, 'tcx> for Lub<'a, 'gcx, 'tcx> {
-> RelateResult<'tcx, ty::Binder<T>> -> RelateResult<'tcx, ty::Binder<T>>
where T: Relate<'tcx> where T: Relate<'tcx>
{ {
self.fields.higher_ranked_lub(a, b) self.fields.higher_ranked_lub(a, b, self.a_is_expected)
} }
} }
impl<'a, 'gcx, 'tcx> LatticeDir<'a, 'gcx, 'tcx> for Lub<'a, 'gcx, 'tcx> { impl<'combine, 'infcx, 'gcx, 'tcx> LatticeDir<'infcx, 'gcx, 'tcx>
fn infcx(&self) -> &'a InferCtxt<'a, 'gcx, 'tcx> { for Lub<'combine, 'infcx, 'gcx, 'tcx>
{
fn infcx(&self) -> &'infcx InferCtxt<'infcx, 'gcx, 'tcx> {
self.fields.infcx self.fields.infcx
} }
fn relate_bound(&self, v: Ty<'tcx>, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, ()> { fn relate_bound(&mut self, v: Ty<'tcx>, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, ()> {
let mut sub = self.fields.sub(); let mut sub = self.fields.sub(self.a_is_expected);
sub.relate(&a, &v)?; sub.relate(&a, &v)?;
sub.relate(&b, &v)?; sub.relate(&b, &v)?;
Ok(()) Ok(())

View file

@ -48,18 +48,18 @@ use self::higher_ranked::HrMatchResult;
use self::region_inference::{RegionVarBindings, RegionSnapshot}; use self::region_inference::{RegionVarBindings, RegionSnapshot};
use self::unify_key::ToType; use self::unify_key::ToType;
pub mod bivariate; mod bivariate;
pub mod combine; mod combine;
pub mod equate; mod equate;
pub mod error_reporting; pub mod error_reporting;
pub mod glb; mod glb;
mod higher_ranked; mod higher_ranked;
pub mod lattice; pub mod lattice;
pub mod lub; mod lub;
pub mod region_inference; pub mod region_inference;
pub mod resolve; pub mod resolve;
mod freshen; mod freshen;
pub mod sub; mod sub;
pub mod type_variable; pub mod type_variable;
pub mod unify_key; pub mod unify_key;
@ -821,11 +821,10 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
return variables; return variables;
} }
fn combine_fields(&'a self, a_is_expected: bool, trace: TypeTrace<'tcx>) fn combine_fields(&'a self, trace: TypeTrace<'tcx>)
-> CombineFields<'a, 'gcx, 'tcx> { -> CombineFields<'a, 'gcx, 'tcx> {
CombineFields { CombineFields {
infcx: self, infcx: self,
a_is_expected: a_is_expected,
trace: trace, trace: trace,
cause: None, cause: None,
obligations: PredicateObligations::new(), obligations: PredicateObligations::new(),
@ -836,36 +835,36 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
-> InferResult<'tcx, T> -> InferResult<'tcx, T>
where T: Relate<'tcx> where T: Relate<'tcx>
{ {
let mut equate = self.combine_fields(a_is_expected, trace).equate(); let mut fields = self.combine_fields(trace);
let result = equate.relate(a, b); let result = fields.equate(a_is_expected).relate(a, b);
result.map(|t| InferOk { value: t, obligations: equate.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>, a: &T, b: &T)
-> InferResult<'tcx, T> -> InferResult<'tcx, T>
where T: Relate<'tcx> where T: Relate<'tcx>
{ {
let mut sub = self.combine_fields(a_is_expected, trace).sub(); let mut fields = self.combine_fields(trace);
let result = sub.relate(a, b); let result = fields.sub(a_is_expected).relate(a, b);
result.map(|t| InferOk { value: t, obligations: sub.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>, a: &T, b: &T)
-> InferResult<'tcx, T> -> InferResult<'tcx, T>
where T: Relate<'tcx> where T: Relate<'tcx>
{ {
let mut lub = self.combine_fields(a_is_expected, trace).lub(); let mut fields = self.combine_fields(trace);
let result = lub.relate(a, b); let result = fields.lub(a_is_expected).relate(a, b);
result.map(|t| InferOk { value: t, obligations: lub.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>, a: &T, b: &T)
-> InferResult<'tcx, T> -> InferResult<'tcx, T>
where T: Relate<'tcx> where T: Relate<'tcx>
{ {
let mut glb = self.combine_fields(a_is_expected, trace).glb(); let mut fields = self.combine_fields(trace);
let result = glb.relate(a, b); let result = fields.glb(a_is_expected).relate(a, b);
result.map(|t| InferOk { value: t, obligations: glb.obligations() }) result.map(move |t| InferOk { value: t, obligations: fields.obligations })
} }
fn start_snapshot(&self) -> CombinedSnapshot { fn start_snapshot(&self) -> CombinedSnapshot {
@ -1614,8 +1613,8 @@ 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 combine = self.combine_fields(true, trace); let mut combine = self.combine_fields(trace);
let result = combine.higher_ranked_match(span, &match_pair, &match_b)?; 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 })
} }

View file

@ -15,28 +15,35 @@ use super::type_variable::{SubtypeOf, SupertypeOf};
use ty::{self, Ty, TyCtxt}; use ty::{self, Ty, TyCtxt};
use ty::TyVar; use ty::TyVar;
use ty::relate::{Cause, Relate, RelateResult, TypeRelation}; use ty::relate::{Cause, Relate, RelateResult, TypeRelation};
use traits::PredicateObligations;
use std::mem; use std::mem;
/// Ensures `a` is made a subtype of `b`. Returns `a` on success. /// Ensures `a` is made a subtype of `b`. Returns `a` on success.
pub struct Sub<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { pub struct Sub<'combine, 'infcx: 'combine, 'gcx: 'infcx+'tcx, 'tcx: 'infcx> {
fields: CombineFields<'a, 'gcx, 'tcx>, fields: &'combine mut CombineFields<'infcx, 'gcx, 'tcx>,
a_is_expected: bool,
} }
impl<'a, 'gcx, 'tcx> Sub<'a, 'gcx, 'tcx> { impl<'combine, 'infcx, 'gcx, 'tcx> Sub<'combine, 'infcx, 'gcx, 'tcx> {
pub fn new(f: CombineFields<'a, 'gcx, 'tcx>) -> Sub<'a, 'gcx, 'tcx> { pub fn new(f: &'combine mut CombineFields<'infcx, 'gcx, 'tcx>, a_is_expected: bool)
Sub { fields: f } -> Sub<'combine, 'infcx, 'gcx, 'tcx>
{
Sub { fields: f, a_is_expected: a_is_expected }
} }
pub fn obligations(self) -> PredicateObligations<'tcx> { fn with_expected_switched<R, F: FnOnce(&mut Self) -> R>(&mut self, f: F) -> R {
self.fields.obligations self.a_is_expected = !self.a_is_expected;
let result = f(self);
self.a_is_expected = !self.a_is_expected;
result
} }
} }
impl<'a, 'gcx, 'tcx> TypeRelation<'a, 'gcx, 'tcx> for Sub<'a, 'gcx, 'tcx> { impl<'combine, 'infcx, 'gcx, 'tcx> TypeRelation<'infcx, 'gcx, 'tcx>
for Sub<'combine, 'infcx, 'gcx, 'tcx>
{
fn tag(&self) -> &'static str { "Sub" } fn tag(&self) -> &'static str { "Sub" }
fn tcx(&self) -> TyCtxt<'a, 'gcx, 'tcx> { self.fields.infcx.tcx } fn tcx(&self) -> TyCtxt<'infcx, 'gcx, 'tcx> { self.fields.infcx.tcx }
fn a_is_expected(&self) -> bool { self.fields.a_is_expected } fn a_is_expected(&self) -> bool { self.a_is_expected }
fn with_cause<F,R>(&mut self, cause: Cause, f: F) -> R fn with_cause<F,R>(&mut self, cause: Cause, f: F) -> R
where F: FnOnce(&mut Self) -> R where F: FnOnce(&mut Self) -> R
@ -56,10 +63,10 @@ impl<'a, 'gcx, 'tcx> TypeRelation<'a, 'gcx, 'tcx> for Sub<'a, 'gcx, 'tcx> {
-> RelateResult<'tcx, T> -> RelateResult<'tcx, T>
{ {
match variance { match variance {
ty::Invariant => self.fields.equate().relate(a, b), ty::Invariant => self.fields.equate(self.a_is_expected).relate(a, b),
ty::Covariant => self.relate(a, b), ty::Covariant => self.relate(a, b),
ty::Bivariant => self.fields.bivariate().relate(a, b), ty::Bivariant => self.fields.bivariate(self.a_is_expected).relate(a, b),
ty::Contravariant => self.fields.switch_expected().sub().relate(b, a), ty::Contravariant => self.with_expected_switched(|this| { this.relate(b, a) }),
} }
} }
@ -80,12 +87,11 @@ impl<'a, 'gcx, 'tcx> TypeRelation<'a, 'gcx, 'tcx> for Sub<'a, 'gcx, 'tcx> {
} }
(&ty::TyInfer(TyVar(a_id)), _) => { (&ty::TyInfer(TyVar(a_id)), _) => {
self.fields self.fields
.switch_expected() .instantiate(b, SupertypeOf, a_id, !self.a_is_expected)?;
.instantiate(b, SupertypeOf, a_id)?;
Ok(a) Ok(a)
} }
(_, &ty::TyInfer(TyVar(b_id))) => { (_, &ty::TyInfer(TyVar(b_id))) => {
self.fields.instantiate(a, SubtypeOf, b_id)?; self.fields.instantiate(a, SubtypeOf, b_id, self.a_is_expected)?;
Ok(a) Ok(a)
} }
@ -116,6 +122,6 @@ impl<'a, 'gcx, 'tcx> TypeRelation<'a, 'gcx, 'tcx> for Sub<'a, 'gcx, 'tcx> {
-> RelateResult<'tcx, ty::Binder<T>> -> RelateResult<'tcx, ty::Binder<T>>
where T: Relate<'tcx> where T: Relate<'tcx>
{ {
self.fields.higher_ranked_sub(a, b) self.fields.higher_ranked_sub(a, b, self.a_is_expected)
} }
} }

View file

@ -2274,7 +2274,7 @@ impl<'a> Resolver<'a> {
let resolution = if let Some(resolution) = self.resolve_possibly_assoc_item(pat_id, let resolution = if let Some(resolution) = self.resolve_possibly_assoc_item(pat_id,
qself, path, namespace) { qself, path, namespace) {
if resolution.depth == 0 { if resolution.depth == 0 {
if expected_fn(resolution.base_def) { if expected_fn(resolution.base_def) || resolution.base_def == Def::Err {
resolution resolution
} else { } else {
resolve_error( resolve_error(
@ -2345,7 +2345,7 @@ impl<'a> Resolver<'a> {
); );
None None
} }
Def::Local(..) | Def::Upvar(..) | Def::Fn(..) => { Def::Local(..) | Def::Upvar(..) | Def::Fn(..) | Def::Err => {
// These entities are explicitly allowed // These entities are explicitly allowed
// to be shadowed by fresh bindings. // to be shadowed by fresh bindings.
None None

View file

@ -2409,10 +2409,13 @@ fn render_struct(w: &mut fmt::Formatter, it: &clean::Item,
if structhead {"struct "} else {""}, if structhead {"struct "} else {""},
it.name.as_ref().unwrap())?; it.name.as_ref().unwrap())?;
if let Some(g) = g { if let Some(g) = g {
write!(w, "{}{}", *g, WhereClause(g))? write!(w, "{}", g)?
} }
match ty { match ty {
doctree::Plain => { doctree::Plain => {
if let Some(g) = g {
write!(w, "{}", WhereClause(g))?
}
write!(w, " {{\n{}", tab)?; write!(w, " {{\n{}", tab)?;
for field in fields { for field in fields {
if let clean::StructFieldItem(ref ty) = field.inner { if let clean::StructFieldItem(ref ty) = field.inner {
@ -2445,9 +2448,17 @@ fn render_struct(w: &mut fmt::Formatter, it: &clean::Item,
_ => unreachable!() _ => unreachable!()
} }
} }
write!(w, ");")?; write!(w, ")")?;
if let Some(g) = g {
write!(w, "{}", WhereClause(g))?
}
write!(w, ";")?;
} }
doctree::Unit => { doctree::Unit => {
// Needed for PhantomData.
if let Some(g) = g {
write!(w, "{}", WhereClause(g))?
}
write!(w, ";")?; write!(w, ";")?;
} }
} }

View file

@ -124,7 +124,7 @@ pub fn strip_unconfigured_items(mut krate: ast::Crate, sess: &ParseSess, should_
}; };
let err_count = sess.span_diagnostic.err_count(); let err_count = sess.span_diagnostic.err_count();
let krate_attrs = strip_unconfigured.process_cfg_attrs(krate.attrs.clone()); let krate_attrs = strip_unconfigured.configure(krate.attrs.clone()).unwrap_or_default();
features = get_features(&sess.span_diagnostic, &krate_attrs); features = get_features(&sess.span_diagnostic, &krate_attrs);
if err_count < sess.span_diagnostic.err_count() { if err_count < sess.span_diagnostic.err_count() {
krate.attrs = krate_attrs.clone(); // Avoid reconfiguring malformed `cfg_attr`s krate.attrs = krate_attrs.clone(); // Avoid reconfiguring malformed `cfg_attr`s

View file

@ -0,0 +1,27 @@
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// Check that unresolved imports do not create additional errors and ICEs
mod m {
pub use unresolved; //~ ERROR unresolved import `unresolved`
fn f() {
let unresolved = 0; // OK
}
}
fn main() {
match 0u8 {
m::unresolved => {} // OK
m::unresolved(..) => {} // OK
m::unresolved{..} => {} // OK
}
}

View file

@ -0,0 +1,23 @@
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// compile-flags:--test
// rustc-env:RUSTC_BOOTSTRAP_KEY=
// ignore-pretty : (#23623) problems when ending with // comments
#![cfg(any())] // This test should be configured away
#![feature(rustc_attrs)] // Test that this is allowed on stable/beta
#![feature(iter_arith_traits)] // Test that this is not unused
#![deny(unused_features)]
#[test]
fn dummy() {
let () = "this should not reach type-checking";
}

View file

@ -0,0 +1,16 @@
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#![crate_name = "foo"]
pub trait Bar {}
// @has foo/struct.Foo.html '//pre' 'pub struct Foo<T>(pub T) where T: Bar;'
pub struct Foo<T>(pub T) where T: Bar;

View file

@ -12,7 +12,7 @@
pub trait MyTrait { fn dummy(&self) { } } pub trait MyTrait { fn dummy(&self) { } }
// @has foo/struct.Alpha.html '//pre' "pub struct Alpha<A> where A: MyTrait" // @has foo/struct.Alpha.html '//pre' "pub struct Alpha<A>(_) where A: MyTrait"
pub struct Alpha<A>(A) where A: MyTrait; pub struct Alpha<A>(A) where A: MyTrait;
// @has foo/trait.Bravo.html '//pre' "pub trait Bravo<B> where B: MyTrait" // @has foo/trait.Bravo.html '//pre' "pub trait Bravo<B> where B: MyTrait"
pub trait Bravo<B> where B: MyTrait { fn get(&self, B: B); } pub trait Bravo<B> where B: MyTrait { fn get(&self, B: B); }