rustc: remove SelfSpace from ParamSpace.

This commit is contained in:
Eduard Burtescu 2016-08-15 01:07:09 +03:00
parent 4158673ad7
commit c1cfd58cbd
41 changed files with 276 additions and 357 deletions

View File

@ -9,7 +9,6 @@
// except according to those terms. // except according to those terms.
use hir::def_id::DefId; use hir::def_id::DefId;
use ty::subst::ParamSpace;
use util::nodemap::NodeMap; use util::nodemap::NodeMap;
use syntax::ast; use syntax::ast;
use hir; use hir;
@ -31,7 +30,7 @@ pub enum Def {
AssociatedTy(DefId /* trait */, DefId), AssociatedTy(DefId /* trait */, DefId),
Trait(DefId), Trait(DefId),
PrimTy(hir::PrimTy), PrimTy(hir::PrimTy),
TyParam(ParamSpace, u32, DefId, ast::Name), TyParam(DefId),
Upvar(DefId, // def id of closed over local Upvar(DefId, // def id of closed over local
ast::NodeId, // node id of closed over local ast::NodeId, // node id of closed over local
usize, // index in the freevars list of the closure usize, // index in the freevars list of the closure
@ -122,7 +121,7 @@ impl Def {
match *self { match *self {
Def::Fn(id) | Def::Mod(id) | Def::ForeignMod(id) | Def::Static(id, _) | Def::Fn(id) | Def::Mod(id) | Def::ForeignMod(id) | Def::Static(id, _) |
Def::Variant(_, id) | Def::Enum(id) | Def::TyAlias(id) | Def::AssociatedTy(_, id) | Def::Variant(_, id) | Def::Enum(id) | Def::TyAlias(id) | Def::AssociatedTy(_, id) |
Def::TyParam(_, _, id, _) | Def::Struct(id) | Def::Trait(id) | Def::TyParam(id) | Def::Struct(id) | Def::Trait(id) |
Def::Method(id) | Def::Const(id) | Def::AssociatedConst(id) | Def::Method(id) | Def::Const(id) | Def::AssociatedConst(id) |
Def::Local(id, _) | Def::Upvar(id, _, _, _) => { Def::Local(id, _) | Def::Upvar(id, _, _, _) => {
id id

View File

@ -95,7 +95,7 @@ impl<'a, 'tcx> MarkSymbolVisitor<'a, 'tcx> {
Def::AssociatedTy(..) | Def::Method(_) | Def::AssociatedConst(_) Def::AssociatedTy(..) | Def::Method(_) | Def::AssociatedConst(_)
if self.tcx.trait_of_item(def.def_id()).is_some() => { if self.tcx.trait_of_item(def.def_id()).is_some() => {
if let Some(substs) = self.tcx.tables.borrow().item_substs.get(&id) { if let Some(substs) = self.tcx.tables.borrow().item_substs.get(&id) {
match substs.substs.types.get(subst::SelfSpace, 0).sty { match substs.substs.types.get(subst::TypeSpace, 0).sty {
TyEnum(tyid, _) | TyStruct(tyid, _) => { TyEnum(tyid, _) | TyStruct(tyid, _) => {
self.check_def_id(tyid.did) self.check_def_id(tyid.did)
} }

View File

@ -14,7 +14,6 @@ use super::{SelectionContext, Obligation, ObligationCause};
use middle::cstore::LOCAL_CRATE; use middle::cstore::LOCAL_CRATE;
use hir::def_id::DefId; use hir::def_id::DefId;
use ty::subst::TypeSpace;
use ty::{self, Ty, TyCtxt}; use ty::{self, Ty, TyCtxt};
use infer::{InferCtxt, TypeOrigin}; use infer::{InferCtxt, TypeOrigin};
use syntax_pos::DUMMY_SP; use syntax_pos::DUMMY_SP;
@ -160,12 +159,9 @@ fn orphan_check_trait_ref<'tcx>(tcx: TyCtxt,
// First, create an ordered iterator over all the type parameters to the trait, with the self // First, create an ordered iterator over all the type parameters to the trait, with the self
// type appearing first. // type appearing first.
let input_tys = Some(trait_ref.self_ty());
let input_tys = input_tys.iter().chain(trait_ref.substs.types.get_slice(TypeSpace));
// Find the first input type that either references a type parameter OR // Find the first input type that either references a type parameter OR
// some local type. // some local type.
for input_ty in input_tys { for input_ty in trait_ref.input_types() {
if ty_is_local(tcx, input_ty, infer_is_local) { if ty_is_local(tcx, input_ty, infer_is_local) {
debug!("orphan_check_trait_ref: ty_is_local `{:?}`", input_ty); debug!("orphan_check_trait_ref: ty_is_local `{:?}`", input_ty);

View File

@ -232,8 +232,8 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
if let Ok(..) = self.can_equate(&trait_self_ty, &impl_self_ty) { if let Ok(..) = self.can_equate(&trait_self_ty, &impl_self_ty) {
self_match_impls.push(def_id); self_match_impls.push(def_id);
if trait_ref.substs.types.get_slice(TypeSpace).iter() if trait_ref.substs.types.get_slice(TypeSpace)[1..].iter()
.zip(impl_trait_ref.substs.types.get_slice(TypeSpace)) .zip(&impl_trait_ref.substs.types.get_slice(TypeSpace)[1..])
.all(|(u,v)| self.fuzzy_match_tys(u, v)) .all(|(u,v)| self.fuzzy_match_tys(u, v))
{ {
fuzzy_match_impls.push(def_id); fuzzy_match_impls.push(def_id);

View File

@ -20,7 +20,7 @@
use super::elaborate_predicates; use super::elaborate_predicates;
use hir::def_id::DefId; use hir::def_id::DefId;
use ty::subst::{self, SelfSpace, TypeSpace}; use ty::subst;
use traits; use traits;
use ty::{self, ToPolyTraitRef, Ty, TyCtxt, TypeFoldable}; use ty::{self, ToPolyTraitRef, Ty, TyCtxt, TypeFoldable};
use std::rc::Rc; use std::rc::Rc;
@ -146,10 +146,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
match predicate { match predicate {
ty::Predicate::Trait(ref data) => { ty::Predicate::Trait(ref data) => {
// In the case of a trait predicate, we can skip the "self" type. // In the case of a trait predicate, we can skip the "self" type.
data.0.trait_ref.substs.types.get_slice(TypeSpace) data.0.trait_ref.input_types()[1..].iter().any(|t| t.has_self_ty())
.iter()
.cloned()
.any(|t| t.has_self_ty())
} }
ty::Predicate::Projection(..) | ty::Predicate::Projection(..) |
ty::Predicate::WellFormed(..) | ty::Predicate::WellFormed(..) |
@ -325,7 +322,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
ty.maybe_walk(|ty| { ty.maybe_walk(|ty| {
match ty.sty { match ty.sty {
ty::TyParam(ref param_ty) => { ty::TyParam(ref param_ty) => {
if param_ty.space == SelfSpace { if param_ty.is_self() {
error = true; error = true;
} }

View File

@ -1353,7 +1353,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
} }
pub fn mk_self_type(self) -> Ty<'tcx> { pub fn mk_self_type(self) -> Ty<'tcx> {
self.mk_param(subst::SelfSpace, 0, keywords::SelfType.name()) self.mk_param(subst::TypeSpace, 0, keywords::SelfType.name())
} }
pub fn mk_param_from_def(self, def: &ty::TypeParameterDef) -> Ty<'tcx> { pub fn mk_param_from_def(self, def: &ty::TypeParameterDef) -> Ty<'tcx> {

View File

@ -9,7 +9,6 @@
// except according to those terms. // except according to those terms.
use hir::def_id::DefId; use hir::def_id::DefId;
use ty::subst;
use infer::type_variable; use infer::type_variable;
use ty::{self, BoundRegion, Region, Ty, TyCtxt}; use ty::{self, BoundRegion, Region, Ty, TyCtxt};
@ -258,7 +257,7 @@ impl<'a, 'gcx, 'lcx, 'tcx> ty::TyS<'tcx> {
ty::TyInfer(ty::FreshFloatTy(_)) => "skolemized floating-point type".to_string(), ty::TyInfer(ty::FreshFloatTy(_)) => "skolemized floating-point type".to_string(),
ty::TyProjection(_) => "associated type".to_string(), ty::TyProjection(_) => "associated type".to_string(),
ty::TyParam(ref p) => { ty::TyParam(ref p) => {
if p.space == subst::SelfSpace { if p.is_self() {
"Self".to_string() "Self".to_string()
} else { } else {
"type parameter".to_string() "type parameter".to_string()

View File

@ -8,7 +8,7 @@
// option. This file may not be copied, modified, or distributed // option. This file may not be copied, modified, or distributed
// except according to those terms. // except according to those terms.
use ty::subst::{self, Substs}; use ty::subst::Substs;
use ty::{self, Ty, TypeFlags, TypeFoldable}; use ty::{self, Ty, TypeFlags, TypeFoldable};
pub struct FlagComputation { pub struct FlagComputation {
@ -77,7 +77,7 @@ impl FlagComputation {
&ty::TyParam(ref p) => { &ty::TyParam(ref p) => {
self.add_flags(TypeFlags::HAS_LOCAL_NAMES); self.add_flags(TypeFlags::HAS_LOCAL_NAMES);
if p.space == subst::SelfSpace { if p.is_self() {
self.add_flags(TypeFlags::HAS_SELF); self.add_flags(TypeFlags::HAS_SELF);
} else { } else {
self.add_flags(TypeFlags::HAS_PARAMS); self.add_flags(TypeFlags::HAS_PARAMS);

View File

@ -1225,7 +1225,7 @@ impl<'tcx> TraitRef<'tcx> {
} }
pub fn self_ty(&self) -> Ty<'tcx> { pub fn self_ty(&self) -> Ty<'tcx> {
*self.substs.types.get(subst::SelfSpace, 0) *self.substs.types.get(subst::TypeSpace, 0)
} }
pub fn input_types(&self) -> &[Ty<'tcx>] { pub fn input_types(&self) -> &[Ty<'tcx>] {

View File

@ -305,7 +305,7 @@ pub struct TraitObject<'tcx> {
/// ///
/// This would be represented by a trait-reference where the def-id is the /// This would be represented by a trait-reference where the def-id is the
/// def-id for the trait `Foo` and the substs defines `T` as parameter 0 in the /// def-id for the trait `Foo` and the substs defines `T` as parameter 0 in the
/// `SelfSpace` and `U` as parameter 0 in the `TypeSpace`. /// `TypeSpace` and `U` as parameter 1 in the `TypeSpace`.
/// ///
/// Trait references also appear in object types like `Foo<U>`, but in /// Trait references also appear in object types like `Foo<U>`, but in
/// that case the `Self` parameter is absent from the substitutions. /// that case the `Self` parameter is absent from the substitutions.
@ -512,7 +512,7 @@ impl<'a, 'gcx, 'tcx> ParamTy {
} }
pub fn for_self() -> ParamTy { pub fn for_self() -> ParamTy {
ParamTy::new(subst::SelfSpace, 0, keywords::SelfType.name()) ParamTy::new(subst::TypeSpace, 0, keywords::SelfType.name())
} }
pub fn for_def(def: &ty::TypeParameterDef) -> ParamTy { pub fn for_def(def: &ty::TypeParameterDef) -> ParamTy {
@ -524,7 +524,13 @@ impl<'a, 'gcx, 'tcx> ParamTy {
} }
pub fn is_self(&self) -> bool { pub fn is_self(&self) -> bool {
self.space == subst::SelfSpace && self.idx == 0 if self.name == keywords::SelfType.name() {
assert_eq!(self.space, subst::TypeSpace);
assert_eq!(self.idx, 0);
true
} else {
false
}
} }
} }
@ -954,7 +960,7 @@ impl<'a, 'gcx, 'tcx> TyS<'tcx> {
pub fn is_self(&self) -> bool { pub fn is_self(&self) -> bool {
match self.sty { match self.sty {
TyParam(ref p) => p.space == subst::SelfSpace, TyParam(ref p) => p.is_self(),
_ => false _ => false
} }
} }

View File

@ -47,8 +47,8 @@ impl<'a, 'gcx, 'tcx> Substs<'tcx> {
r: Vec<ty::Region>) r: Vec<ty::Region>)
-> &'tcx Substs<'tcx> -> &'tcx Substs<'tcx>
{ {
Substs::new(tcx, VecPerParamSpace::new(vec![], vec![], t), Substs::new(tcx, VecPerParamSpace::new(vec![], t),
VecPerParamSpace::new(vec![], vec![], r)) VecPerParamSpace::new(vec![], r))
} }
pub fn new_type(tcx: TyCtxt<'a, 'gcx, 'tcx>, pub fn new_type(tcx: TyCtxt<'a, 'gcx, 'tcx>,
@ -56,18 +56,19 @@ impl<'a, 'gcx, 'tcx> Substs<'tcx> {
r: Vec<ty::Region>) r: Vec<ty::Region>)
-> &'tcx Substs<'tcx> -> &'tcx Substs<'tcx>
{ {
Substs::new(tcx, VecPerParamSpace::new(vec![], t, vec![]), Substs::new(tcx, VecPerParamSpace::new(t, vec![]),
VecPerParamSpace::new(vec![], r, vec![])) VecPerParamSpace::new(r, vec![]))
} }
pub fn new_trait(tcx: TyCtxt<'a, 'gcx, 'tcx>, pub fn new_trait(tcx: TyCtxt<'a, 'gcx, 'tcx>,
t: Vec<Ty<'tcx>>, mut t: Vec<Ty<'tcx>>,
r: Vec<ty::Region>, r: Vec<ty::Region>,
s: Ty<'tcx>) s: Ty<'tcx>)
-> &'tcx Substs<'tcx> -> &'tcx Substs<'tcx>
{ {
Substs::new(tcx, VecPerParamSpace::new(vec![s], t, vec![]), t.insert(0, s);
VecPerParamSpace::new(vec![], r, vec![])) Substs::new(tcx, VecPerParamSpace::new(t, vec![]),
VecPerParamSpace::new(r, vec![]))
} }
pub fn empty(tcx: TyCtxt<'a, 'gcx, 'tcx>) -> &'tcx Substs<'tcx> { pub fn empty(tcx: TyCtxt<'a, 'gcx, 'tcx>) -> &'tcx Substs<'tcx> {
@ -90,12 +91,10 @@ impl<'a, 'gcx, 'tcx> Substs<'tcx> {
let defs = tcx.lookup_generics(def_id); let defs = tcx.lookup_generics(def_id);
let mut substs = Substs { let mut substs = Substs {
types: VecPerParamSpace { types: VecPerParamSpace {
self_limit: 0,
type_limit: 0, type_limit: 0,
content: Vec::with_capacity(defs.types.content.len()) content: Vec::with_capacity(defs.types.content.len())
}, },
regions: VecPerParamSpace { regions: VecPerParamSpace {
self_limit: 0,
type_limit: 0, type_limit: 0,
content: Vec::with_capacity(defs.regions.content.len()) content: Vec::with_capacity(defs.regions.content.len())
} }
@ -104,7 +103,6 @@ impl<'a, 'gcx, 'tcx> Substs<'tcx> {
for &space in &ParamSpace::all() { for &space in &ParamSpace::all() {
for def in defs.regions.get_slice(space) { for def in defs.regions.get_slice(space) {
assert_eq!(def.space, space); assert_eq!(def.space, space);
assert!(space != SelfSpace);
let region = mk_region(def, &substs); let region = mk_region(def, &substs);
substs.regions.content.push(region); substs.regions.content.push(region);
@ -120,11 +118,7 @@ impl<'a, 'gcx, 'tcx> Substs<'tcx> {
let ty = mk_type(def, &substs); let ty = mk_type(def, &substs);
substs.types.content.push(ty); substs.types.content.push(ty);
if space == SelfSpace { if space == TypeSpace {
substs.types.self_limit += 1;
}
if space <= TypeSpace {
substs.types.type_limit += 1; substs.types.type_limit += 1;
} }
} }
@ -155,7 +149,6 @@ impl<'a, 'gcx, 'tcx> Substs<'tcx> {
target_substs: &Substs<'tcx>) target_substs: &Substs<'tcx>)
-> &'tcx Substs<'tcx> { -> &'tcx Substs<'tcx> {
let defs = tcx.lookup_generics(source_ancestor); let defs = tcx.lookup_generics(source_ancestor);
assert_eq!(self.types.len(SelfSpace), defs.types.len(SelfSpace));
assert_eq!(self.types.len(TypeSpace), defs.types.len(TypeSpace)); assert_eq!(self.types.len(TypeSpace), defs.types.len(TypeSpace));
assert_eq!(target_substs.types.len(FnSpace), 0); assert_eq!(target_substs.types.len(FnSpace), 0);
assert_eq!(defs.types.len(FnSpace), 0); assert_eq!(defs.types.len(FnSpace), 0);
@ -195,29 +188,26 @@ impl<'tcx> Decodable for &'tcx Substs<'tcx> {
#[derive(PartialOrd, Ord, PartialEq, Eq, Copy, #[derive(PartialOrd, Ord, PartialEq, Eq, Copy,
Clone, Hash, RustcEncodable, RustcDecodable, Debug)] Clone, Hash, RustcEncodable, RustcDecodable, Debug)]
pub enum ParamSpace { pub enum ParamSpace {
SelfSpace, // Self parameter on a trait
TypeSpace, // Type parameters attached to a type definition, trait, or impl TypeSpace, // Type parameters attached to a type definition, trait, or impl
FnSpace, // Type parameters attached to a method or fn FnSpace, // Type parameters attached to a method or fn
} }
impl ParamSpace { impl ParamSpace {
pub fn all() -> [ParamSpace; 3] { pub fn all() -> [ParamSpace; 2] {
[SelfSpace, TypeSpace, FnSpace] [TypeSpace, FnSpace]
} }
pub fn to_uint(self) -> usize { pub fn to_uint(self) -> usize {
match self { match self {
SelfSpace => 0, TypeSpace => 0,
TypeSpace => 1, FnSpace => 1,
FnSpace => 2,
} }
} }
pub fn from_uint(u: usize) -> ParamSpace { pub fn from_uint(u: usize) -> ParamSpace {
match u { match u {
0 => SelfSpace, 0 => TypeSpace,
1 => TypeSpace, 1 => FnSpace,
2 => FnSpace,
_ => bug!("Invalid ParamSpace: {}", u) _ => bug!("Invalid ParamSpace: {}", u)
} }
} }
@ -235,18 +225,15 @@ pub struct VecPerParamSpace<T> {
// Here is how the representation corresponds to the abstraction // Here is how the representation corresponds to the abstraction
// i.e. the "abstraction function" AF: // i.e. the "abstraction function" AF:
// //
// AF(self) = (self.content[..self.self_limit], // AF(self) = (self.content[..self.type_limit],
// self.content[self.self_limit..self.type_limit],
// self.content[self.type_limit..]) // self.content[self.type_limit..])
self_limit: usize,
type_limit: usize, type_limit: usize,
content: Vec<T>, content: Vec<T>,
} }
impl<T: fmt::Debug> fmt::Debug for VecPerParamSpace<T> { impl<T: fmt::Debug> fmt::Debug for VecPerParamSpace<T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "[{:?};{:?};{:?}]", write!(f, "[{:?};{:?}]",
self.get_slice(SelfSpace),
self.get_slice(TypeSpace), self.get_slice(TypeSpace),
self.get_slice(FnSpace)) self.get_slice(FnSpace))
} }
@ -255,43 +242,34 @@ impl<T: fmt::Debug> fmt::Debug for VecPerParamSpace<T> {
impl<T> VecPerParamSpace<T> { impl<T> VecPerParamSpace<T> {
fn limits(&self, space: ParamSpace) -> (usize, usize) { fn limits(&self, space: ParamSpace) -> (usize, usize) {
match space { match space {
SelfSpace => (0, self.self_limit), TypeSpace => (0, self.type_limit),
TypeSpace => (self.self_limit, self.type_limit),
FnSpace => (self.type_limit, self.content.len()), FnSpace => (self.type_limit, self.content.len()),
} }
} }
pub fn empty() -> VecPerParamSpace<T> { pub fn empty() -> VecPerParamSpace<T> {
VecPerParamSpace { VecPerParamSpace {
self_limit: 0,
type_limit: 0, type_limit: 0,
content: Vec::new() content: Vec::new()
} }
} }
/// `s` is the self space.
/// `t` is the type space. /// `t` is the type space.
/// `f` is the fn space. /// `f` is the fn space.
pub fn new(s: Vec<T>, t: Vec<T>, f: Vec<T>) -> VecPerParamSpace<T> { pub fn new(t: Vec<T>, f: Vec<T>) -> VecPerParamSpace<T> {
let self_limit = s.len(); let type_limit = t.len();
let type_limit = self_limit + t.len();
let mut content = s; let mut content = t;
content.extend(t);
content.extend(f); content.extend(f);
VecPerParamSpace { VecPerParamSpace {
self_limit: self_limit,
type_limit: type_limit, type_limit: type_limit,
content: content, content: content,
} }
} }
fn new_internal(content: Vec<T>, self_limit: usize, type_limit: usize) fn new_internal(content: Vec<T>, type_limit: usize) -> VecPerParamSpace<T> {
-> VecPerParamSpace<T>
{
VecPerParamSpace { VecPerParamSpace {
self_limit: self_limit,
type_limit: type_limit, type_limit: type_limit,
content: content, content: content,
} }
@ -336,18 +314,14 @@ impl<T> VecPerParamSpace<T> {
pub fn map<U, P>(&self, pred: P) -> VecPerParamSpace<U> where P: FnMut(&T) -> U { pub fn map<U, P>(&self, pred: P) -> VecPerParamSpace<U> where P: FnMut(&T) -> U {
let result = self.as_full_slice().iter().map(pred).collect(); let result = self.as_full_slice().iter().map(pred).collect();
VecPerParamSpace::new_internal(result, VecPerParamSpace::new_internal(result, self.type_limit)
self.self_limit,
self.type_limit)
} }
pub fn map_enumerated<U, P>(&self, pred: P) -> VecPerParamSpace<U> where pub fn map_enumerated<U, P>(&self, pred: P) -> VecPerParamSpace<U> where
P: FnMut((ParamSpace, usize, &T)) -> U, P: FnMut((ParamSpace, usize, &T)) -> U,
{ {
let result = self.iter_enumerated().map(pred).collect(); let result = self.iter_enumerated().map(pred).collect();
VecPerParamSpace::new_internal(result, VecPerParamSpace::new_internal(result, self.type_limit)
self.self_limit,
self.type_limit)
} }
} }
@ -639,8 +613,6 @@ impl<'a, 'gcx, 'tcx> ty::ExistentialTraitRef<'tcx> {
-> ty::ExistentialTraitRef<'tcx> { -> ty::ExistentialTraitRef<'tcx> {
let Substs { mut types, regions } = trait_ref.substs.clone(); let Substs { mut types, regions } = trait_ref.substs.clone();
assert_eq!(types.self_limit, 1);
types.self_limit = 0;
types.type_limit -= 1; types.type_limit -= 1;
types.content.remove(0); types.content.remove(0);
@ -665,8 +637,6 @@ impl<'a, 'gcx, 'tcx> ty::PolyExistentialTraitRef<'tcx> {
self.map_bound(|trait_ref| { self.map_bound(|trait_ref| {
let Substs { mut types, regions } = trait_ref.substs.clone(); let Substs { mut types, regions } = trait_ref.substs.clone();
assert_eq!(types.self_limit, 0);
types.self_limit = 1;
types.type_limit += 1; types.type_limit += 1;
types.content.insert(0, self_ty); types.content.insert(0, self_ty);

View File

@ -62,35 +62,36 @@ pub enum Ns {
Value Value
} }
fn number_of_supplied_defaults<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
substs: &subst::Substs,
space: subst::ParamSpace,
generics: &ty::Generics<'tcx>)
-> usize
{
let ty_params = generics.types.get_slice(space);
let tps = substs.types.get_slice(space);
if ty_params.last().map_or(false, |def| def.default.is_some()) {
let substs = tcx.lift(&substs);
ty_params.iter().zip(tps).rev().take_while(|&(def, &actual)| {
substs.and_then(|substs| def.default.subst(tcx, substs))
== Some(actual)
}).count()
} else {
0
}
}
pub fn parameterized(f: &mut fmt::Formatter, pub fn parameterized(f: &mut fmt::Formatter,
substs: &subst::Substs, substs: &subst::Substs,
did: DefId, did: DefId,
ns: Ns, ns: Ns,
projections: &[ty::ProjectionPredicate]) projections: &[ty::ProjectionPredicate])
-> fmt::Result { -> fmt::Result {
let (fn_trait_kind, verbose, item_name, is_in_trait) = ty::tls::with(|tcx| { let mut verbose = false;
let is_in_trait = ns == Ns::Value && tcx.trait_of_item(did).is_some(); let mut num_supplied_defaults = 0;
if is_in_trait { let mut has_self = false;
write!(f, "<{} as ", substs.types.get(subst::SelfSpace, 0))?; let (fn_trait_kind, item_name) = ty::tls::with(|tcx| {
verbose = tcx.sess.verbose();
let generics = tcx.lookup_generics(did);
if !verbose {
let ty_params = generics.types.get_slice(subst::TypeSpace);
if ty_params.last().map_or(false, |def| def.default.is_some()) {
if let Some(substs) = tcx.lift(&substs) {
let tps = substs.types.get_slice(subst::TypeSpace);
for (def, actual) in ty_params.iter().zip(tps).rev() {
if def.default.subst(tcx, substs) != Some(actual) {
break;
}
num_supplied_defaults += 1;
}
}
}
}
has_self = generics.has_self;
if ns == Ns::Value && has_self {
write!(f, "<{} as ", substs.types.get(subst::TypeSpace, 0))?;
} }
let (did, item_name) = if ns == Ns::Value { let (did, item_name) = if ns == Ns::Value {
@ -107,15 +108,12 @@ pub fn parameterized(f: &mut fmt::Formatter,
(did, None) (did, None)
}; };
write!(f, "{}", tcx.item_path_str(did))?; write!(f, "{}", tcx.item_path_str(did))?;
Ok((tcx.lang_items.fn_trait_kind(did), Ok((tcx.lang_items.fn_trait_kind(did), item_name))
tcx.sess.verbose(),
item_name,
is_in_trait))
})?; })?;
if !verbose && fn_trait_kind.is_some() && projections.len() == 1 { if !verbose && fn_trait_kind.is_some() && projections.len() == 1 {
let projection_ty = projections[0].ty; let projection_ty = projections[0].ty;
if let TyTuple(ref args) = substs.types.get(subst::TypeSpace, 0).sty { if let TyTuple(ref args) = substs.types.get(subst::TypeSpace, 1).sty {
return fn_sig(f, args, false, projection_ty); return fn_sig(f, args, false, projection_ty);
} }
} }
@ -160,18 +158,9 @@ pub fn parameterized(f: &mut fmt::Formatter,
print_regions(f, "<", substs.regions.get_slice(subst::TypeSpace))?; print_regions(f, "<", substs.regions.get_slice(subst::TypeSpace))?;
let num_supplied_defaults = if verbose {
0
} else {
ty::tls::with(|tcx| {
let generics = tcx.lookup_generics(did);
number_of_supplied_defaults(tcx, substs, subst::TypeSpace, generics)
})
};
let tps = substs.types.get_slice(subst::TypeSpace); let tps = substs.types.get_slice(subst::TypeSpace);
for &ty in &tps[..tps.len() - num_supplied_defaults] { for &ty in &tps[has_self as usize..tps.len() - num_supplied_defaults] {
start_or_continue(f, "<", ", ")?; start_or_continue(f, "<", ", ")?;
write!(f, "{}", ty)?; write!(f, "{}", ty)?;
} }
@ -189,7 +178,7 @@ pub fn parameterized(f: &mut fmt::Formatter,
if ns == Ns::Value { if ns == Ns::Value {
empty.set(true); empty.set(true);
if is_in_trait { if has_self {
write!(f, ">")?; write!(f, ">")?;
} }

View File

@ -16,7 +16,7 @@ use super::{drop_flag_effects_for_location, on_all_children_bits};
use super::{DropFlagState, MoveDataParamEnv}; use super::{DropFlagState, MoveDataParamEnv};
use super::patch::MirPatch; use super::patch::MirPatch;
use rustc::ty::{self, Ty, TyCtxt}; use rustc::ty::{self, Ty, TyCtxt};
use rustc::ty::subst::{Subst, Substs, VecPerParamSpace}; use rustc::ty::subst::{Subst, Substs};
use rustc::mir::repr::*; use rustc::mir::repr::*;
use rustc::mir::transform::{Pass, MirPass, MirSource}; use rustc::mir::transform::{Pass, MirPass, MirSource};
use rustc::middle::const_val::ConstVal; use rustc::middle::const_val::ConstVal;
@ -859,9 +859,7 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> {
let unit_temp = Lvalue::Temp(self.patch.new_temp(tcx.mk_nil())); let unit_temp = Lvalue::Temp(self.patch.new_temp(tcx.mk_nil()));
let free_func = tcx.lang_items.require(lang_items::BoxFreeFnLangItem) let free_func = tcx.lang_items.require(lang_items::BoxFreeFnLangItem)
.unwrap_or_else(|e| tcx.sess.fatal(&e)); .unwrap_or_else(|e| tcx.sess.fatal(&e));
let substs = Substs::new(tcx, let substs = Substs::new_fn(tcx, vec![ty], vec![]);
VecPerParamSpace::new(vec![], vec![], vec![ty]),
VecPerParamSpace::new(vec![], vec![], vec![]));
let fty = tcx.lookup_item_type(free_func).ty.subst(tcx, substs); let fty = tcx.lookup_item_type(free_func).ty.subst(tcx, substs);
self.patch.new_block(BasicBlockData { self.patch.new_block(BasicBlockData {

View File

@ -413,7 +413,7 @@ impl tr for Def {
Def::AssociatedTy(trait_did, did) => Def::AssociatedTy(trait_did, did) =>
Def::AssociatedTy(trait_did.tr(dcx), did.tr(dcx)), Def::AssociatedTy(trait_did.tr(dcx), did.tr(dcx)),
Def::PrimTy(p) => Def::PrimTy(p), Def::PrimTy(p) => Def::PrimTy(p),
Def::TyParam(s, index, def_id, n) => Def::TyParam(s, index, def_id.tr(dcx), n), Def::TyParam(did) => Def::TyParam(did.tr(dcx)),
Def::Upvar(_, nid1, index, nid2) => { Def::Upvar(_, nid1, index, nid2) => {
let nid1 = dcx.tr_id(nid1); let nid1 = dcx.tr_id(nid1);
let nid2 = dcx.tr_id(nid2); let nid2 = dcx.tr_id(nid2);

View File

@ -131,15 +131,15 @@ impl<'a,'tcx> TyDecoder<'a,'tcx> {
fn parse_vec_per_param_space<T, F>(&mut self, mut f: F) -> VecPerParamSpace<T> where fn parse_vec_per_param_space<T, F>(&mut self, mut f: F) -> VecPerParamSpace<T> where
F: FnMut(&mut TyDecoder<'a, 'tcx>) -> T, F: FnMut(&mut TyDecoder<'a, 'tcx>) -> T,
{ {
let (mut a, mut b, mut c) = (vec![], vec![], vec![]); let (mut a, mut b) = (vec![], vec![]);
for r in &mut [&mut a, &mut b, &mut c] { for r in &mut [&mut a, &mut b] {
assert_eq!(self.next(), '['); assert_eq!(self.next(), '[');
while self.peek() != ']' { while self.peek() != ']' {
r.push(f(self)); r.push(f(self));
} }
assert_eq!(self.next(), ']'); assert_eq!(self.next(), ']');
} }
VecPerParamSpace::new(a, b, c) VecPerParamSpace::new(a, b)
} }
pub fn parse_substs(&mut self) -> &'tcx Substs<'tcx> { pub fn parse_substs(&mut self) -> &'tcx Substs<'tcx> {

View File

@ -49,7 +49,6 @@ use rustc::lint;
use rustc::hir::def::*; use rustc::hir::def::*;
use rustc::hir::def_id::{CRATE_DEF_INDEX, DefId}; use rustc::hir::def_id::{CRATE_DEF_INDEX, DefId};
use rustc::ty; use rustc::ty;
use rustc::ty::subst::{ParamSpace, FnSpace, TypeSpace};
use rustc::hir::{Freevar, FreevarMap, TraitCandidate, TraitMap, GlobMap}; use rustc::hir::{Freevar, FreevarMap, TraitCandidate, TraitMap, GlobMap};
use rustc::util::nodemap::{NodeMap, NodeSet, FnvHashMap, FnvHashSet}; use rustc::util::nodemap::{NodeMap, NodeSet, FnvHashMap, FnvHashSet};
@ -557,7 +556,7 @@ impl<'a> Visitor for Resolver<'a> {
fn visit_foreign_item(&mut self, foreign_item: &ForeignItem) { fn visit_foreign_item(&mut self, foreign_item: &ForeignItem) {
let type_parameters = match foreign_item.node { let type_parameters = match foreign_item.node {
ForeignItemKind::Fn(_, ref generics) => { ForeignItemKind::Fn(_, ref generics) => {
HasTypeParameters(generics, FnSpace, ItemRibKind) HasTypeParameters(generics, ItemRibKind)
} }
ForeignItemKind::Static(..) => NoTypeParameters, ForeignItemKind::Static(..) => NoTypeParameters,
}; };
@ -625,10 +624,6 @@ enum TypeParameters<'a, 'b> {
HasTypeParameters(// Type parameters. HasTypeParameters(// Type parameters.
&'b Generics, &'b Generics,
// Identifies the things that these parameters
// were declared on (type, fn, etc)
ParamSpace,
// The kind of the rib used for type parameters. // The kind of the rib used for type parameters.
RibKind<'a>), RibKind<'a>),
} }
@ -1613,12 +1608,9 @@ impl<'a> Resolver<'a> {
match item.node { match item.node {
ItemKind::Enum(_, ref generics) | ItemKind::Enum(_, ref generics) |
ItemKind::Ty(_, ref generics) | ItemKind::Ty(_, ref generics) |
ItemKind::Struct(_, ref generics) => { ItemKind::Struct(_, ref generics) |
self.with_type_parameter_rib(HasTypeParameters(generics, TypeSpace, ItemRibKind),
|this| visit::walk_item(this, item));
}
ItemKind::Fn(_, _, _, _, ref generics, _) => { ItemKind::Fn(_, _, _, _, ref generics, _) => {
self.with_type_parameter_rib(HasTypeParameters(generics, FnSpace, ItemRibKind), self.with_type_parameter_rib(HasTypeParameters(generics, ItemRibKind),
|this| visit::walk_item(this, item)); |this| visit::walk_item(this, item));
} }
@ -1634,10 +1626,7 @@ impl<'a> Resolver<'a> {
ItemKind::Trait(_, ref generics, ref bounds, ref trait_items) => { ItemKind::Trait(_, ref generics, ref bounds, ref trait_items) => {
// Create a new rib for the trait-wide type parameters. // Create a new rib for the trait-wide type parameters.
self.with_type_parameter_rib(HasTypeParameters(generics, self.with_type_parameter_rib(HasTypeParameters(generics, ItemRibKind), |this| {
TypeSpace,
ItemRibKind),
|this| {
let local_def_id = this.definitions.local_def_id(item.id); let local_def_id = this.definitions.local_def_id(item.id);
this.with_self_rib(Def::SelfTy(Some(local_def_id), None), |this| { this.with_self_rib(Def::SelfTy(Some(local_def_id), None), |this| {
this.visit_generics(generics); this.visit_generics(generics);
@ -1660,7 +1649,6 @@ impl<'a> Resolver<'a> {
TraitItemKind::Method(ref sig, _) => { TraitItemKind::Method(ref sig, _) => {
let type_parameters = let type_parameters =
HasTypeParameters(&sig.generics, HasTypeParameters(&sig.generics,
FnSpace,
MethodRibKind(!sig.decl.has_self())); MethodRibKind(!sig.decl.has_self()));
this.with_type_parameter_rib(type_parameters, |this| { this.with_type_parameter_rib(type_parameters, |this| {
visit::walk_trait_item(this, trait_item) visit::walk_trait_item(this, trait_item)
@ -1729,10 +1717,10 @@ impl<'a> Resolver<'a> {
where F: FnOnce(&mut Resolver) where F: FnOnce(&mut Resolver)
{ {
match type_parameters { match type_parameters {
HasTypeParameters(generics, space, rib_kind) => { HasTypeParameters(generics, rib_kind) => {
let mut function_type_rib = Rib::new(rib_kind); let mut function_type_rib = Rib::new(rib_kind);
let mut seen_bindings = HashSet::new(); let mut seen_bindings = HashSet::new();
for (index, type_parameter) in generics.ty_params.iter().enumerate() { for type_parameter in &generics.ty_params {
let name = type_parameter.ident.name; let name = type_parameter.ident.name;
debug!("with_type_parameter_rib: {}", type_parameter.id); debug!("with_type_parameter_rib: {}", type_parameter.id);
@ -1745,7 +1733,7 @@ impl<'a> Resolver<'a> {
// plain insert (no renaming) // plain insert (no renaming)
let def_id = self.definitions.local_def_id(type_parameter.id); let def_id = self.definitions.local_def_id(type_parameter.id);
let def = Def::TyParam(space, index as u32, def_id, name); let def = Def::TyParam(def_id);
function_type_rib.bindings.insert(ast::Ident::with_empty_ctxt(name), def); function_type_rib.bindings.insert(ast::Ident::with_empty_ctxt(name), def);
self.record_def(type_parameter.id, PathResolution::new(def)); self.record_def(type_parameter.id, PathResolution::new(def));
} }
@ -1917,10 +1905,7 @@ impl<'a> Resolver<'a> {
item_id: NodeId, item_id: NodeId,
impl_items: &[ImplItem]) { impl_items: &[ImplItem]) {
// If applicable, create a rib for the type parameters. // If applicable, create a rib for the type parameters.
self.with_type_parameter_rib(HasTypeParameters(generics, self.with_type_parameter_rib(HasTypeParameters(generics, ItemRibKind), |this| {
TypeSpace,
ItemRibKind),
|this| {
// Resolve the type parameters. // Resolve the type parameters.
this.visit_generics(generics); this.visit_generics(generics);
@ -1953,7 +1938,6 @@ impl<'a> Resolver<'a> {
// specific type parameters. // specific type parameters.
let type_parameters = let type_parameters =
HasTypeParameters(&sig.generics, HasTypeParameters(&sig.generics,
FnSpace,
MethodRibKind(!sig.decl.has_self())); MethodRibKind(!sig.decl.has_self()));
this.with_type_parameter_rib(type_parameters, |this| { this.with_type_parameter_rib(type_parameters, |this| {
visit::walk_impl_item(this, impl_item); visit::walk_impl_item(this, impl_item);

View File

@ -490,7 +490,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
Def::Enum(def_id) | Def::Enum(def_id) |
Def::TyAlias(def_id) | Def::TyAlias(def_id) |
Def::Trait(def_id) | Def::Trait(def_id) |
Def::TyParam(_, _, def_id, _) => { Def::TyParam(def_id) => {
Some(Data::TypeRefData(TypeRefData { Some(Data::TypeRefData(TypeRefData {
span: sub_span.unwrap(), span: sub_span.unwrap(),
ref_id: Some(def_id), ref_id: Some(def_id),

View File

@ -488,7 +488,7 @@ fn characteristic_def_id_of_trans_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
// DefId, we use the location of the impl after all. // DefId, we use the location of the impl after all.
if tcx.trait_of_item(instance.def).is_some() { if tcx.trait_of_item(instance.def).is_some() {
let self_ty = *instance.substs.types.get(subst::SelfSpace, 0); let self_ty = *instance.substs.types.get(subst::TypeSpace, 0);
// This is an implementation of a trait method. // This is an implementation of a trait method.
return characteristic_def_id_of_type(self_ty).or(Some(instance.def)); return characteristic_def_id_of_type(self_ty).or(Some(instance.def));
} }

View File

@ -55,7 +55,7 @@ use hir::def_id::DefId;
use hir::print as pprust; use hir::print as pprust;
use middle::resolve_lifetime as rl; use middle::resolve_lifetime as rl;
use rustc::lint; use rustc::lint;
use rustc::ty::subst::{TypeSpace, SelfSpace, Subst, Substs}; use rustc::ty::subst::{TypeSpace, Subst, Substs};
use rustc::traits; use rustc::traits;
use rustc::ty::{self, Ty, TyCtxt, ToPredicate, TypeFoldable}; use rustc::ty::{self, Ty, TyCtxt, ToPredicate, TypeFoldable};
use rustc::ty::wf::object_region_bounds; use rustc::ty::wf::object_region_bounds;
@ -455,6 +455,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
// Check the number of type parameters supplied by the user. // Check the number of type parameters supplied by the user.
if let Some(num_provided) = num_types_provided { if let Some(num_provided) = num_types_provided {
let ty_param_defs = decl_generics.types.get_slice(TypeSpace); let ty_param_defs = decl_generics.types.get_slice(TypeSpace);
let ty_param_defs = &ty_param_defs[self_ty.is_some() as usize..];
check_type_argument_count(tcx, span, num_provided, ty_param_defs); check_type_argument_count(tcx, span, num_provided, ty_param_defs);
} }
@ -476,13 +477,16 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
assert_eq!(def.space, TypeSpace); assert_eq!(def.space, TypeSpace);
regions[def.index as usize] regions[def.index as usize]
}, |def, substs| { }, |def, substs| {
assert!(def.space == SelfSpace || def.space == TypeSpace); assert!(def.space == TypeSpace);
let i = def.index as usize; let i = def.index as usize;
if def.space == SelfSpace {
// Self, which must have been provided. // Handle Self first, so we can adjust the index to match the AST.
assert_eq!(i, 0); if let (0, Some(ty)) = (i, self_ty) {
self_ty.expect("Self type parameter missing") return ty;
} else if num_types_provided.map_or(false, |n| i < n) { }
let i = i - self_ty.is_some() as usize;
if num_types_provided.map_or(false, |n| i < n) {
// A provided type parameter. // A provided type parameter.
match *parameters { match *parameters {
hir::AngleBracketedParameters(ref data) => { hir::AngleBracketedParameters(ref data) => {
@ -1325,8 +1329,9 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
Err(ErrorReported) => return (tcx.types.err, Def::Err), Err(ErrorReported) => return (tcx.types.err, Def::Err),
} }
} }
(&ty::TyParam(_), Def::TyParam(_, _, param_did, param_name)) => { (&ty::TyParam(_), Def::TyParam(param_did)) => {
let param_node_id = tcx.map.as_local_node_id(param_did).unwrap(); let param_node_id = tcx.map.as_local_node_id(param_did).unwrap();
let param_name = tcx.type_parameter_def(param_node_id).name;
match self.find_bound_for_assoc_item(param_node_id, match self.find_bound_for_assoc_item(param_node_id,
param_name, param_name,
assoc_name, assoc_name,
@ -1336,10 +1341,13 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
} }
} }
_ => { _ => {
// Don't print TyErr to the user.
if !ty.references_error() {
self.report_ambiguous_associated_type(span, self.report_ambiguous_associated_type(span,
&ty.to_string(), &ty.to_string(),
"Trait", "Trait",
&assoc_name.as_str()); &assoc_name.as_str());
}
return (tcx.types.err, Def::Err); return (tcx.types.err, Def::Err);
} }
}; };
@ -1477,9 +1485,25 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
did, did,
base_segments.last().unwrap()) base_segments.last().unwrap())
} }
Def::TyParam(space, index, _, name) => { Def::TyParam(did) => {
tcx.prohibit_type_params(base_segments); tcx.prohibit_type_params(base_segments);
tcx.mk_param(space, index, name)
let node_id = tcx.map.as_local_node_id(did).unwrap();
let param = tcx.ty_param_defs.borrow().get(&node_id)
.map(ty::ParamTy::for_def);
if let Some(p) = param {
p.to_ty(tcx)
} else {
// Only while computing defaults of earlier type
// parameters can a type parameter be missing its def.
struct_span_err!(tcx.sess, span, E0128,
"type parameters with a default cannot use \
forward declared identifiers")
.span_label(span, &format!("defaulted type parameters \
cannot be forward declared"))
.emit();
tcx.types.err
}
} }
Def::SelfTy(_, Some(impl_id)) => { Def::SelfTy(_, Some(impl_id)) => {
// Self in impl (we know the concrete type). // Self in impl (we know the concrete type).

View File

@ -204,7 +204,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
return None; return None;
} }
let arg_param_ty = *trait_ref.substs().types.get(subst::TypeSpace, 0); let arg_param_ty = *trait_ref.substs().types.get(subst::TypeSpace, 1);
let arg_param_ty = self.resolve_type_vars_if_possible(&arg_param_ty); let arg_param_ty = self.resolve_type_vars_if_possible(&arg_param_ty);
debug!("deduce_sig_from_projection: arg_param_ty {:?}", arg_param_ty); debug!("deduce_sig_from_projection: arg_param_ty {:?}", arg_param_ty);

View File

@ -183,7 +183,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
let trait_def = self.tcx.lookup_trait_def(trait_def_id); let trait_def = self.tcx.lookup_trait_def(trait_def_id);
if let Some(ref input_types) = opt_input_types { if let Some(ref input_types) = opt_input_types {
assert_eq!(trait_def.generics.types.len(subst::TypeSpace), input_types.len()); assert_eq!(trait_def.generics.types.len(subst::TypeSpace) - 1, input_types.len());
} }
assert_eq!(trait_def.generics.types.len(subst::FnSpace), 0); assert_eq!(trait_def.generics.types.len(subst::FnSpace), 0);
assert!(trait_def.generics.regions.is_empty()); assert!(trait_def.generics.regions.is_empty());
@ -192,10 +192,10 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
let substs = Substs::for_item(self.tcx, trait_def_id, |def, _| { let substs = Substs::for_item(self.tcx, trait_def_id, |def, _| {
self.region_var_for_def(span, def) self.region_var_for_def(span, def)
}, |def, substs| { }, |def, substs| {
if def.space == subst::SelfSpace { if def.index == 0 {
self_ty self_ty
} else if let Some(ref input_types) = opt_input_types { } else if let Some(ref input_types) = opt_input_types {
input_types[def.index as usize] input_types[def.index as usize - 1]
} else { } else {
self.type_var_for_def(span, def, substs) self.type_var_for_def(span, def, substs)
} }

View File

@ -522,10 +522,6 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
trait_ref.substs.types.len(subst::TypeSpace)); trait_ref.substs.types.len(subst::TypeSpace));
assert_eq!(m.generics.regions.len(subst::TypeSpace), assert_eq!(m.generics.regions.len(subst::TypeSpace),
trait_ref.substs.regions.len(subst::TypeSpace)); trait_ref.substs.regions.len(subst::TypeSpace));
assert_eq!(m.generics.types.len(subst::SelfSpace),
trait_ref.substs.types.len(subst::SelfSpace));
assert_eq!(m.generics.regions.len(subst::SelfSpace),
trait_ref.substs.regions.len(subst::SelfSpace));
} }
// Because this trait derives from a where-clause, it // Because this trait derives from a where-clause, it
@ -755,11 +751,9 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
let substs = Substs::for_item(self.tcx, trait_def_id, |def, _| { let substs = Substs::for_item(self.tcx, trait_def_id, |def, _| {
self.region_var_for_def(self.span, def) self.region_var_for_def(self.span, def)
}, |def, substs| { }, |def, substs| {
if def.space == subst::SelfSpace { if def.index == 0 {
assert_eq!(def.index, 0);
step.self_ty step.self_ty
} else { } else {
assert_eq!(def.space, subst::TypeSpace);
self.type_var_for_def(self.span, def, substs) self.type_var_for_def(self.span, def, substs)
} }
}); });

View File

@ -4225,7 +4225,6 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
let substs = Substs::for_item(self.tcx, def.def_id(), |def, _| { let substs = Substs::for_item(self.tcx, def.def_id(), |def, _| {
let i = def.index as usize; let i = def.index as usize;
let segment = match def.space { let segment = match def.space {
subst::SelfSpace => None,
subst::TypeSpace => type_segment, subst::TypeSpace => type_segment,
subst::FnSpace => fn_segment subst::FnSpace => fn_segment
}; };
@ -4241,9 +4240,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
self.region_var_for_def(span, def) self.region_var_for_def(span, def)
} }
}, |def, substs| { }, |def, substs| {
let i = def.index as usize; let mut i = def.index as usize;
let segment = match def.space { let segment = match def.space {
subst::SelfSpace => None,
subst::TypeSpace => type_segment, subst::TypeSpace => type_segment,
subst::FnSpace => fn_segment subst::FnSpace => fn_segment
}; };
@ -4252,18 +4250,24 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
Some(&hir::ParenthesizedParameters(_)) => bug!(), Some(&hir::ParenthesizedParameters(_)) => bug!(),
None => &[] None => &[]
}; };
// Handle Self first, so we can adjust the index to match the AST.
if scheme.generics.has_self && def.space == subst::TypeSpace {
if i == 0 {
return opt_self_ty.unwrap_or_else(|| {
self.type_var_for_def(span, def, substs)
});
}
i -= 1;
}
let can_omit = def.space != subst::TypeSpace || !require_type_space; let can_omit = def.space != subst::TypeSpace || !require_type_space;
let default = if can_omit && types.len() == 0 { let default = if can_omit && types.len() == 0 {
def.default def.default
} else { } else {
None None
}; };
if let Some(ast_ty) = types.get(i) {
if def.space == subst::SelfSpace && opt_self_ty.is_some() {
// Self, which has been provided.
assert_eq!(i, 0);
opt_self_ty.unwrap()
} else if let Some(ast_ty) = types.get(i) {
// A provided type parameter. // A provided type parameter.
self.to_ty(ast_ty) self.to_ty(ast_ty)
} else if let Some(default) = default { } else if let Some(default) = default {
@ -4371,6 +4375,11 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
// Check provided type parameters. // Check provided type parameters.
let type_defs = generics.types.get_slice(space); let type_defs = generics.types.get_slice(space);
let type_defs = if space == subst::TypeSpace {
&type_defs[generics.has_self as usize..]
} else {
type_defs
};
let required_len = type_defs.iter() let required_len = type_defs.iter()
.take_while(|d| d.default.is_none()) .take_while(|d| d.default.is_none())
.count(); .count();

View File

@ -14,13 +14,12 @@ use CrateCtxt;
use hir::def_id::DefId; use hir::def_id::DefId;
use middle::region::{CodeExtent}; use middle::region::{CodeExtent};
use rustc::infer::TypeOrigin; use rustc::infer::TypeOrigin;
use rustc::ty::subst::{self, TypeSpace, FnSpace, ParamSpace, SelfSpace}; use rustc::ty::subst;
use rustc::traits; use rustc::traits;
use rustc::ty::{self, Ty, TyCtxt}; use rustc::ty::{self, Ty, TyCtxt};
use std::collections::HashSet; use std::collections::HashSet;
use syntax::ast; use syntax::ast;
use syntax::parse::token::keywords;
use syntax_pos::Span; use syntax_pos::Span;
use errors::DiagnosticBuilder; use errors::DiagnosticBuilder;
@ -461,7 +460,7 @@ impl<'ccx, 'gcx> CheckTypeWellFormedVisitor<'ccx, 'gcx> {
variances.types variances.types
.iter_enumerated() .iter_enumerated()
.filter(|&(_, _, &variance)| variance != ty::Bivariant) .filter(|&(_, _, &variance)| variance != ty::Bivariant)
.map(|(space, index, _)| self.param_ty(ast_generics, space, index)) .map(|(_, index, _)| self.param_ty(ast_generics, index))
.map(|p| Parameter::Type(p)) .map(|p| Parameter::Type(p))
.collect(); .collect();
@ -470,52 +469,34 @@ impl<'ccx, 'gcx> CheckTypeWellFormedVisitor<'ccx, 'gcx> {
&mut constrained_parameters); &mut constrained_parameters);
for (space, index, _) in variances.types.iter_enumerated() { for (space, index, _) in variances.types.iter_enumerated() {
let param_ty = self.param_ty(ast_generics, space, index); assert_eq!(space, subst::TypeSpace);
let param_ty = self.param_ty(ast_generics, index);
if constrained_parameters.contains(&Parameter::Type(param_ty)) { if constrained_parameters.contains(&Parameter::Type(param_ty)) {
continue; continue;
} }
let span = self.ty_param_span(ast_generics, item, space, index); let span = ast_generics.ty_params[index].span;
self.report_bivariance(span, param_ty.name); self.report_bivariance(span, param_ty.name);
} }
for (space, index, &variance) in variances.regions.iter_enumerated() { for (space, index, &variance) in variances.regions.iter_enumerated() {
assert_eq!(space, subst::TypeSpace);
if variance != ty::Bivariant { if variance != ty::Bivariant {
continue; continue;
} }
assert_eq!(space, TypeSpace);
let span = ast_generics.lifetimes[index].lifetime.span; let span = ast_generics.lifetimes[index].lifetime.span;
let name = ast_generics.lifetimes[index].lifetime.name; let name = ast_generics.lifetimes[index].lifetime.name;
self.report_bivariance(span, name); self.report_bivariance(span, name);
} }
} }
fn param_ty(&self, fn param_ty(&self, ast_generics: &hir::Generics, index: usize) -> ty::ParamTy {
ast_generics: &hir::Generics, ty::ParamTy {
space: ParamSpace, space: subst::TypeSpace,
index: usize) idx: index as u32,
-> ty::ParamTy name: ast_generics.ty_params[index].name
{
let name = match space {
TypeSpace => ast_generics.ty_params[index].name,
SelfSpace => keywords::SelfType.name(),
FnSpace => bug!("Fn space occupied?"),
};
ty::ParamTy { space: space, idx: index as u32, name: name }
}
fn ty_param_span(&self,
ast_generics: &hir::Generics,
item: &hir::Item,
space: ParamSpace,
index: usize)
-> Span
{
match space {
TypeSpace => ast_generics.ty_params[index].span,
SelfSpace => item.span,
FnSpace => span_bug!(item.span, "Fn space occupied?"),
} }
} }

View File

@ -386,7 +386,7 @@ impl<'a, 'gcx, 'tcx> CoherenceChecker<'a, 'gcx, 'tcx> {
let source = tcx.lookup_item_type(impl_did).ty; let source = tcx.lookup_item_type(impl_did).ty;
let trait_ref = self.crate_context.tcx.impl_trait_ref(impl_did).unwrap(); let trait_ref = self.crate_context.tcx.impl_trait_ref(impl_did).unwrap();
let target = *trait_ref.substs.types.get(subst::TypeSpace, 0); let target = *trait_ref.substs.types.get(subst::TypeSpace, 1);
debug!("check_implementations_of_coerce_unsized: {:?} -> {:?} (bound)", debug!("check_implementations_of_coerce_unsized: {:?} -> {:?} (bound)",
source, target); source, target);

View File

@ -65,7 +65,7 @@ use middle::lang_items::SizedTraitLangItem;
use middle::const_val::ConstVal; use middle::const_val::ConstVal;
use rustc_const_eval::EvalHint::UncheckedExprHint; use rustc_const_eval::EvalHint::UncheckedExprHint;
use rustc_const_eval::{eval_const_expr_partial, report_const_eval_err}; use rustc_const_eval::{eval_const_expr_partial, report_const_eval_err};
use rustc::ty::subst::{Substs, FnSpace, ParamSpace, SelfSpace, TypeSpace, VecPerParamSpace}; use rustc::ty::subst::{Substs, FnSpace, ParamSpace, TypeSpace, VecPerParamSpace};
use rustc::ty::{ToPredicate, ImplContainer, ImplOrTraitItemContainer, TraitContainer}; use rustc::ty::{ToPredicate, ImplContainer, ImplOrTraitItemContainer, TraitContainer};
use rustc::ty::{self, ToPolyTraitRef, Ty, TyCtxt, TypeScheme}; use rustc::ty::{self, ToPolyTraitRef, Ty, TyCtxt, TypeScheme};
use rustc::ty::{VariantKind}; use rustc::ty::{VariantKind};
@ -85,7 +85,6 @@ use std::rc::Rc;
use syntax::{abi, ast, attr}; use syntax::{abi, ast, attr};
use syntax::parse::token::keywords; use syntax::parse::token::keywords;
use syntax::ptr::P;
use syntax_pos::Span; use syntax_pos::Span;
use rustc::hir::{self, intravisit, map as hir_map, print as pprust}; use rustc::hir::{self, intravisit, map as hir_map, print as pprust};
@ -546,7 +545,7 @@ fn is_param<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
let path_res = tcx.expect_resolution(ast_ty.id); let path_res = tcx.expect_resolution(ast_ty.id);
match path_res.base_def { match path_res.base_def {
Def::SelfTy(Some(def_id), None) | Def::SelfTy(Some(def_id), None) |
Def::TyParam(_, _, def_id, _) if path_res.depth == 0 => { Def::TyParam(def_id) if path_res.depth == 0 => {
def_id == tcx.map.local_def_id(param_id) def_id == tcx.map.local_def_id(param_id)
} }
_ => false _ => false
@ -1333,7 +1332,7 @@ fn convert_trait_predicates<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, it: &hir::Item)
// add in the explicit where-clauses // add in the explicit where-clauses
let mut trait_predicates = let mut trait_predicates =
ty_generic_predicates(ccx, TypeSpace, generics, &base_predicates); ty_generic_predicates(ccx, TypeSpace, generics, &base_predicates, true);
let assoc_predicates = predicates_for_associated_types(ccx, let assoc_predicates = predicates_for_associated_types(ccx,
generics, generics,
@ -1430,7 +1429,7 @@ fn generics_of_def_id<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
let parent = ccx.tcx.map.get_parent(param_id); let parent = ccx.tcx.map.get_parent(param_id);
let def = ty::TypeParameterDef { let def = ty::TypeParameterDef {
space: SelfSpace, space: TypeSpace,
index: 0, index: 0,
name: keywords::SelfType.name(), name: keywords::SelfType.name(),
def_id: tcx.map.local_def_id(param_id), def_id: tcx.map.local_def_id(param_id),
@ -1477,27 +1476,25 @@ fn generics_of_def_id<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
}).collect(); }).collect();
// Now create the real type parameters. // Now create the real type parameters.
let types = ast_generics.ty_params.iter().enumerate().map(|(i, _)| { let types = ast_generics.ty_params.iter().enumerate().map(|(i, p)| {
get_or_create_type_parameter_def(ccx, ast_generics, space, i as u32, allow_defaults) let i = opt_self.is_some() as u32 + i as u32;
get_or_create_type_parameter_def(ccx, ast_generics, space, i, p, allow_defaults)
}).collect(); }).collect();
let has_self = base_generics.has_self || opt_self.is_some(); let has_self = base_generics.has_self || opt_self.is_some();
let (regions, types) = match space { let (regions, types) = match space {
SelfSpace => bug!(),
TypeSpace => { TypeSpace => {
assert_eq!(base_generics.regions.as_full_slice().len(), 0); assert_eq!(base_generics.regions.as_full_slice().len(), 0);
assert_eq!(base_generics.types.as_full_slice().len(), 0); assert_eq!(base_generics.types.as_full_slice().len(), 0);
(VecPerParamSpace::new(vec![], regions, vec![]), (VecPerParamSpace::new(regions, vec![]),
VecPerParamSpace::new(opt_self.into_iter().collect(), types, vec![])) VecPerParamSpace::new(opt_self.into_iter().chain(types).collect(), vec![]))
} }
FnSpace => { FnSpace => {
assert_eq!(base_generics.regions.len(FnSpace), 0); assert_eq!(base_generics.regions.len(FnSpace), 0);
assert_eq!(base_generics.types.len(FnSpace), 0); assert_eq!(base_generics.types.len(FnSpace), 0);
(VecPerParamSpace::new(base_generics.regions.get_slice(SelfSpace).to_vec(), (VecPerParamSpace::new(base_generics.regions.get_slice(TypeSpace).to_vec(),
base_generics.regions.get_slice(TypeSpace).to_vec(),
regions), regions),
VecPerParamSpace::new(base_generics.types.get_slice(SelfSpace).to_vec(), VecPerParamSpace::new(base_generics.types.get_slice(TypeSpace).to_vec(),
base_generics.types.get_slice(TypeSpace).to_vec(),
types)) types))
} }
}; };
@ -1674,7 +1671,7 @@ fn ty_generic_predicates_for_type_or_impl<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
generics: &hir::Generics) generics: &hir::Generics)
-> ty::GenericPredicates<'tcx> -> ty::GenericPredicates<'tcx>
{ {
ty_generic_predicates(ccx, TypeSpace, generics, &ty::GenericPredicates::empty()) ty_generic_predicates(ccx, TypeSpace, generics, &ty::GenericPredicates::empty(), false)
} }
fn ty_generic_predicates_for_fn<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, fn ty_generic_predicates_for_fn<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
@ -1682,7 +1679,7 @@ fn ty_generic_predicates_for_fn<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
base_predicates: &ty::GenericPredicates<'tcx>) base_predicates: &ty::GenericPredicates<'tcx>)
-> ty::GenericPredicates<'tcx> -> ty::GenericPredicates<'tcx>
{ {
ty_generic_predicates(ccx, FnSpace, generics, base_predicates) ty_generic_predicates(ccx, FnSpace, generics, base_predicates, false)
} }
// Add the Sized bound, unless the type parameter is marked as `?Sized`. // Add the Sized bound, unless the type parameter is marked as `?Sized`.
@ -1752,7 +1749,8 @@ fn early_bound_lifetimes_from_generics<'a, 'tcx, 'hir>(
fn ty_generic_predicates<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, fn ty_generic_predicates<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
space: ParamSpace, space: ParamSpace,
ast_generics: &hir::Generics, ast_generics: &hir::Generics,
base_predicates: &ty::GenericPredicates<'tcx>) base_predicates: &ty::GenericPredicates<'tcx>,
has_self: bool)
-> ty::GenericPredicates<'tcx> -> ty::GenericPredicates<'tcx>
{ {
let tcx = ccx.tcx; let tcx = ccx.tcx;
@ -1761,7 +1759,7 @@ fn ty_generic_predicates<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
// Collect the predicates that were written inline by the user on each // Collect the predicates that were written inline by the user on each
// type parameter (e.g., `<T:Foo>`). // type parameter (e.g., `<T:Foo>`).
for (index, param) in ast_generics.ty_params.iter().enumerate() { for (index, param) in ast_generics.ty_params.iter().enumerate() {
let index = index as u32; let index = has_self as u32 + index as u32;
let param_ty = ty::ParamTy::new(space, index, param.name).to_ty(ccx.tcx); let param_ty = ty::ParamTy::new(space, index, param.name).to_ty(ccx.tcx);
let bounds = compute_bounds(&ccx.icx(&(base_predicates, ast_generics)), let bounds = compute_bounds(&ccx.icx(&(base_predicates, ast_generics)),
param_ty, param_ty,
@ -1850,50 +1848,22 @@ fn ty_generic_predicates<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
result result
} }
fn convert_default_type_parameter<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
path: &P<hir::Ty>,
space: ParamSpace,
index: u32)
-> Ty<'tcx>
{
let ty = AstConv::ast_ty_to_ty(&ccx.icx(&()), &ExplicitRscope, &path);
for leaf_ty in ty.walk() {
if let ty::TyParam(p) = leaf_ty.sty {
if p.space == space && p.idx >= index {
struct_span_err!(ccx.tcx.sess, path.span, E0128,
"type parameters with a default cannot use \
forward declared identifiers")
.span_label(path.span, &format!("defaulted type parameters \
cannot be forward declared"))
.emit();
return ccx.tcx.types.err
}
}
}
ty
}
fn get_or_create_type_parameter_def<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, fn get_or_create_type_parameter_def<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
ast_generics: &hir::Generics, ast_generics: &hir::Generics,
space: ParamSpace, space: ParamSpace,
index: u32, index: u32,
param: &hir::TyParam,
allow_defaults: bool) allow_defaults: bool)
-> ty::TypeParameterDef<'tcx> -> ty::TypeParameterDef<'tcx>
{ {
let param = &ast_generics.ty_params[index as usize];
let tcx = ccx.tcx; let tcx = ccx.tcx;
match tcx.ty_param_defs.borrow().get(&param.id) { match tcx.ty_param_defs.borrow().get(&param.id) {
Some(d) => { return d.clone(); } Some(d) => { return d.clone(); }
None => { } None => { }
} }
let default = param.default.as_ref().map( let default =
|def| convert_default_type_parameter(ccx, def, space, index) param.default.as_ref().map(|def| ccx.icx(&()).to_ty(&ExplicitRscope, def));
);
let object_lifetime_default = let object_lifetime_default =
compute_object_lifetime_default(ccx, param.id, compute_object_lifetime_default(ccx, param.id,
@ -1922,6 +1892,10 @@ fn get_or_create_type_parameter_def<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
object_lifetime_default: object_lifetime_default, object_lifetime_default: object_lifetime_default,
}; };
if def.name == keywords::SelfType.name() {
span_bug!(param.span, "`Self` should not be the name of a regular parameter");
}
tcx.ty_param_defs.borrow_mut().insert(param.id, def.clone()); tcx.ty_param_defs.borrow_mut().insert(param.id, def.clone());
debug!("get_or_create_type_parameter_def: def for type param: {:?}, {:?}", debug!("get_or_create_type_parameter_def: def for type param: {:?}, {:?}",
@ -2153,7 +2127,7 @@ pub fn mk_item_substs<'gcx: 'tcx, 'tcx>(astconv: &AstConv<'gcx, 'tcx>,
/// Checks that all the type parameters on an impl /// Checks that all the type parameters on an impl
fn enforce_impl_params_are_constrained<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, fn enforce_impl_params_are_constrained<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
ast_generics: &hir::Generics, generics: &hir::Generics,
impl_predicates: &mut ty::GenericPredicates<'tcx>, impl_predicates: &mut ty::GenericPredicates<'tcx>,
impl_def_id: DefId) impl_def_id: DefId)
{ {
@ -2173,12 +2147,11 @@ fn enforce_impl_params_are_constrained<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
impl_trait_ref, impl_trait_ref,
&mut input_parameters); &mut input_parameters);
for (index, ty_param) in ast_generics.ty_params.iter().enumerate() { let ty_generics = generics_of_def_id(ccx, impl_def_id);
let param_ty = ty::ParamTy { space: TypeSpace, for (ty_param, param) in ty_generics.types.as_full_slice().iter().zip(&generics.ty_params) {
idx: index as u32, let param_ty = ty::ParamTy::for_def(ty_param);
name: ty_param.name };
if !input_parameters.contains(&ctp::Parameter::Type(param_ty)) { if !input_parameters.contains(&ctp::Parameter::Type(param_ty)) {
report_unused_parameter(ccx, ty_param.span, "type", &param_ty.to_string()); report_unused_parameter(ccx, param.span, "type", &param_ty.to_string());
} }
} }
} }

View File

@ -361,9 +361,7 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
// All type parameters on enums and structs should be // All type parameters on enums and structs should be
// in the TypeSpace. // in the TypeSpace.
assert!(item_type.generics.types.is_empty_in(subst::SelfSpace));
assert!(item_type.generics.types.is_empty_in(subst::FnSpace)); assert!(item_type.generics.types.is_empty_in(subst::FnSpace));
assert!(item_type.generics.regions.is_empty_in(subst::SelfSpace));
assert!(item_type.generics.regions.is_empty_in(subst::FnSpace)); assert!(item_type.generics.regions.is_empty_in(subst::FnSpace));
self.add_constraints_from_substs( self.add_constraints_from_substs(
@ -394,14 +392,12 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
} }
ty::TyTrait(ref data) => { ty::TyTrait(ref data) => {
let poly_trait_ref =
data.principal.with_self_ty(self.tcx(), self.tcx().types.err);
// The type `Foo<T+'a>` is contravariant w/r/t `'a`: // The type `Foo<T+'a>` is contravariant w/r/t `'a`:
let contra = self.contravariant(variance); let contra = self.contravariant(variance);
self.add_constraints_from_region(generics, data.region_bound, contra); self.add_constraints_from_region(generics, data.region_bound, contra);
// Ignore the SelfSpace, it is erased. let poly_trait_ref =
data.principal.with_self_ty(self.tcx(), self.tcx().types.err);
self.add_constraints_from_trait_ref(generics, poly_trait_ref.0, variance); self.add_constraints_from_trait_ref(generics, poly_trait_ref.0, variance);
for projection in &data.projection_bounds { for projection in &data.projection_bounds {

View File

@ -110,8 +110,8 @@ impl<'a, 'tcx> SolveContext<'a, 'tcx> {
while index < num_inferred { while index < num_inferred {
let item_id = inferred_infos[index].item_id; let item_id = inferred_infos[index].item_id;
let (mut rs, mut rt, mut rf) = (vec![], vec![], vec![]); let (mut rt, mut rf) = (vec![], vec![]);
let (mut ts, mut tt, mut tf) = (vec![], vec![], vec![]); let (mut tt, mut tf) = (vec![], vec![]);
while index < num_inferred && inferred_infos[index].item_id == item_id { while index < num_inferred && inferred_infos[index].item_id == item_id {
let info = &inferred_infos[index]; let info = &inferred_infos[index];
@ -121,7 +121,6 @@ impl<'a, 'tcx> SolveContext<'a, 'tcx> {
match info.kind { match info.kind {
TypeParam => { TypeParam => {
let types = match info.space { let types = match info.space {
subst::SelfSpace => &mut ts,
subst::TypeSpace => &mut tt, subst::TypeSpace => &mut tt,
subst::FnSpace => &mut tf subst::FnSpace => &mut tf
}; };
@ -130,7 +129,6 @@ impl<'a, 'tcx> SolveContext<'a, 'tcx> {
} }
RegionParam => { RegionParam => {
let regions = match info.space { let regions = match info.space {
subst::SelfSpace => &mut rs,
subst::TypeSpace => &mut rt, subst::TypeSpace => &mut rt,
subst::FnSpace => &mut rf subst::FnSpace => &mut rf
}; };
@ -143,8 +141,8 @@ impl<'a, 'tcx> SolveContext<'a, 'tcx> {
} }
let item_variances = ty::ItemVariances { let item_variances = ty::ItemVariances {
regions: subst::VecPerParamSpace::new(rs, rt, rf), regions: subst::VecPerParamSpace::new(rt, rf),
types: subst::VecPerParamSpace::new(ts, tt, tf) types: subst::VecPerParamSpace::new(tt, tf)
}; };
debug!("item_id={} item_variances={:?}", debug!("item_id={} item_variances={:?}",

View File

@ -21,7 +21,7 @@
use arena::TypedArena; use arena::TypedArena;
use dep_graph::DepTrackingMapConfig; use dep_graph::DepTrackingMapConfig;
use rustc::ty::subst::{ParamSpace, FnSpace, TypeSpace, SelfSpace}; use rustc::ty::subst::{ParamSpace, FnSpace, TypeSpace};
use rustc::ty::{self, TyCtxt}; use rustc::ty::{self, TyCtxt};
use rustc::ty::maps::ItemVariances; use rustc::ty::maps::ItemVariances;
use std::fmt; use std::fmt;
@ -164,16 +164,16 @@ impl<'a, 'tcx> TermsContext<'a, 'tcx> {
let inferreds_on_entry = self.num_inferred(); let inferreds_on_entry = self.num_inferred();
if has_self {
self.add_inferred(item_id, TypeParam, SelfSpace, 0, item_id);
}
for (i, p) in generics.lifetimes.iter().enumerate() { for (i, p) in generics.lifetimes.iter().enumerate() {
let id = p.lifetime.id; let id = p.lifetime.id;
self.add_inferred(item_id, RegionParam, TypeSpace, i, id); self.add_inferred(item_id, RegionParam, TypeSpace, i, id);
} }
if has_self {
self.add_inferred(item_id, TypeParam, TypeSpace, 0, item_id);
}
for (i, p) in generics.ty_params.iter().enumerate() { for (i, p) in generics.ty_params.iter().enumerate() {
let i = has_self as usize + i;
self.add_inferred(item_id, TypeParam, TypeSpace, i, p.id); self.add_inferred(item_id, TypeParam, TypeSpace, i, p.id);
} }
@ -233,7 +233,7 @@ impl<'a, 'tcx> TermsContext<'a, 'tcx> {
-> ty::Variance -> ty::Variance
{ {
match space { match space {
SelfSpace | FnSpace => { FnSpace => {
ty::Bivariant ty::Bivariant
} }

View File

@ -41,7 +41,7 @@ use rustc::hir::def::Def;
use rustc::hir::def_id::{DefId, DefIndex, CRATE_DEF_INDEX}; use rustc::hir::def_id::{DefId, DefIndex, CRATE_DEF_INDEX};
use rustc::hir::fold::Folder; use rustc::hir::fold::Folder;
use rustc::hir::print as pprust; use rustc::hir::print as pprust;
use rustc::ty::subst::{self, ParamSpace, Substs, VecPerParamSpace}; use rustc::ty::subst::{self, Substs, VecPerParamSpace};
use rustc::ty; use rustc::ty;
use rustc::middle::stability; use rustc::middle::stability;
@ -630,13 +630,14 @@ impl Clean<TyParamBound> for hir::TyParamBound {
} }
} }
fn external_path_params(cx: &DocContext, trait_did: Option<DefId>, fn external_path_params(cx: &DocContext, trait_did: Option<DefId>, has_self: bool,
bindings: Vec<TypeBinding>, substs: &Substs) -> PathParameters { bindings: Vec<TypeBinding>, substs: &Substs) -> PathParameters {
let lifetimes = substs.regions.get_slice(subst::TypeSpace) let lifetimes = substs.regions.get_slice(subst::TypeSpace)
.iter() .iter()
.filter_map(|v| v.clean(cx)) .filter_map(|v| v.clean(cx))
.collect(); .collect();
let types = substs.types.get_slice(subst::TypeSpace).to_vec(); let types = substs.types.get_slice(subst::TypeSpace);
let types = types[has_self as usize..].to_vec();
match (trait_did, cx.tcx_opt()) { match (trait_did, cx.tcx_opt()) {
// Attempt to sugar an external path like Fn<(A, B,), C> to Fn(A, B) -> C // Attempt to sugar an external path like Fn<(A, B,), C> to Fn(A, B) -> C
@ -675,13 +676,13 @@ fn external_path_params(cx: &DocContext, trait_did: Option<DefId>,
// trait_did should be set to a trait's DefId if called on a TraitRef, in order to sugar // trait_did should be set to a trait's DefId if called on a TraitRef, in order to sugar
// from Fn<(A, B,), C> to Fn(A, B) -> C // from Fn<(A, B,), C> to Fn(A, B) -> C
fn external_path(cx: &DocContext, name: &str, trait_did: Option<DefId>, fn external_path(cx: &DocContext, name: &str, trait_did: Option<DefId>, has_self: bool,
bindings: Vec<TypeBinding>, substs: &Substs) -> Path { bindings: Vec<TypeBinding>, substs: &Substs) -> Path {
Path { Path {
global: false, global: false,
segments: vec![PathSegment { segments: vec![PathSegment {
name: name.to_string(), name: name.to_string(),
params: external_path_params(cx, trait_did, bindings, substs) params: external_path_params(cx, trait_did, has_self, bindings, substs)
}], }],
} }
} }
@ -696,16 +697,16 @@ impl Clean<TyParamBound> for ty::BuiltinBound {
let (did, path) = match *self { let (did, path) = match *self {
ty::BoundSend => ty::BoundSend =>
(tcx.lang_items.send_trait().unwrap(), (tcx.lang_items.send_trait().unwrap(),
external_path(cx, "Send", None, vec![], empty)), external_path(cx, "Send", None, false, vec![], empty)),
ty::BoundSized => ty::BoundSized =>
(tcx.lang_items.sized_trait().unwrap(), (tcx.lang_items.sized_trait().unwrap(),
external_path(cx, "Sized", None, vec![], empty)), external_path(cx, "Sized", None, false, vec![], empty)),
ty::BoundCopy => ty::BoundCopy =>
(tcx.lang_items.copy_trait().unwrap(), (tcx.lang_items.copy_trait().unwrap(),
external_path(cx, "Copy", None, vec![], empty)), external_path(cx, "Copy", None, false, vec![], empty)),
ty::BoundSync => ty::BoundSync =>
(tcx.lang_items.sync_trait().unwrap(), (tcx.lang_items.sync_trait().unwrap(),
external_path(cx, "Sync", None, vec![], empty)), external_path(cx, "Sync", None, false, vec![], empty)),
}; };
inline::record_extern_fqn(cx, did, TypeTrait); inline::record_extern_fqn(cx, did, TypeTrait);
TraitBound(PolyTrait { TraitBound(PolyTrait {
@ -728,14 +729,14 @@ impl<'tcx> Clean<TyParamBound> for ty::TraitRef<'tcx> {
}; };
inline::record_extern_fqn(cx, self.def_id, TypeTrait); inline::record_extern_fqn(cx, self.def_id, TypeTrait);
let path = external_path(cx, &tcx.item_name(self.def_id).as_str(), let path = external_path(cx, &tcx.item_name(self.def_id).as_str(),
Some(self.def_id), vec![], self.substs); Some(self.def_id), true, vec![], self.substs);
debug!("ty::TraitRef\n substs.types(TypeSpace): {:?}\n", debug!("ty::TraitRef\n substs.types(TypeSpace): {:?}\n",
self.substs.types.get_slice(ParamSpace::TypeSpace)); &self.input_types()[1..]);
// collect any late bound regions // collect any late bound regions
let mut late_bounds = vec![]; let mut late_bounds = vec![];
for &ty_s in self.substs.types.get_slice(ParamSpace::TypeSpace) { for &ty_s in &self.input_types()[1..] {
if let ty::TyTuple(ts) = ty_s.sty { if let ty::TyTuple(ts) = ty_s.sty {
for &ty_s in ts { for &ty_s in ts {
if let ty::TyRef(ref reg, _) = ty_s.sty { if let ty::TyRef(ref reg, _) = ty_s.sty {
@ -982,8 +983,13 @@ impl<'a, 'tcx> Clean<Generics> for (&'a ty::Generics<'tcx>,
// Bounds in the type_params and lifetimes fields are repeated in the // Bounds in the type_params and lifetimes fields are repeated in the
// predicates field (see rustc_typeck::collect::ty_generics), so remove // predicates field (see rustc_typeck::collect::ty_generics), so remove
// them. // them.
let stripped_typarams = gens.types.get_slice(space).iter().map(|tp| { let stripped_typarams = gens.types.get_slice(space).iter().filter_map(|tp| {
tp.clean(cx) if tp.name == keywords::SelfType.name() {
assert_eq!(tp.index, 0);
None
} else {
Some(tp.clean(cx))
}
}).collect::<Vec<_>>(); }).collect::<Vec<_>>();
let stripped_lifetimes = gens.regions.get_slice(space).iter().map(|rp| { let stripped_lifetimes = gens.regions.get_slice(space).iter().map(|rp| {
let mut srp = rp.clone(); let mut srp = rp.clone();
@ -1820,7 +1826,7 @@ impl<'tcx> Clean<Type> for ty::Ty<'tcx> {
}; };
inline::record_extern_fqn(cx, did, kind); inline::record_extern_fqn(cx, did, kind);
let path = external_path(cx, &cx.tcx().item_name(did).as_str(), let path = external_path(cx, &cx.tcx().item_name(did).as_str(),
None, vec![], substs); None, false, vec![], substs);
ResolvedPath { ResolvedPath {
path: path, path: path,
typarams: None, typarams: None,
@ -1847,7 +1853,7 @@ impl<'tcx> Clean<Type> for ty::Ty<'tcx> {
} }
let path = external_path(cx, &cx.tcx().item_name(did).as_str(), let path = external_path(cx, &cx.tcx().item_name(did).as_str(),
Some(did), bindings, obj.principal.0.substs); Some(did), false, bindings, obj.principal.0.substs);
ResolvedPath { ResolvedPath {
path: path, path: path,
typarams: Some(typarams), typarams: Some(typarams),

View File

@ -8,15 +8,13 @@
// option. This file may not be copied, modified, or distributed // option. This file may not be copied, modified, or distributed
// except according to those terms. // except according to those terms.
// error-pattern: overflow representing the type `S` // error-pattern: overflow representing the type
#![feature(rustc_attrs)]
trait Mirror { type It: ?Sized; } trait Mirror { type It: ?Sized; }
impl<T: ?Sized> Mirror for T { type It = Self; } impl<T: ?Sized> Mirror for T { type It = Self; }
struct S(Option<<S as Mirror>::It>); struct S(Option<<S as Mirror>::It>);
#[rustc_no_mir] // FIXME #27840 MIR tries to represent `std::option::Option<S>` first.
fn main() { fn main() {
let _s = S(None); let _s = S(None);
} }

View File

@ -10,5 +10,7 @@
#![feature(default_type_parameter_fallback)] #![feature(default_type_parameter_fallback)]
fn avg<T=T::Item>(_: T) {} //~ ERROR associated type `Item` not found for `T` fn avg<T=T::Item>(_: T) {}
//~^ ERROR type parameters with a default cannot use forward declared identifiers
fn main() {} fn main() {}

View File

@ -20,12 +20,12 @@ trait Trait<'a> {
} }
#[rustc_variance] #[rustc_variance]
struct Foo<'a, T : Trait<'a>> { //~ ERROR ItemVariances(types=[[];[+];[]], regions=[[];[-];[]]) struct Foo<'a, T : Trait<'a>> { //~ ERROR ItemVariances(types=[[+];[]], regions=[[-];[]])
field: (T, &'a ()) field: (T, &'a ())
} }
#[rustc_variance] #[rustc_variance]
struct Bar<'a, T : Trait<'a>> { //~ ERROR ItemVariances(types=[[];[o];[]], regions=[[];[o];[]]) struct Bar<'a, T : Trait<'a>> { //~ ERROR ItemVariances(types=[[o];[]], regions=[[o];[]])
field: <T as Trait<'a>>::Type field: <T as Trait<'a>>::Type
} }

View File

@ -18,7 +18,7 @@ use std::cell::Cell;
// For better or worse, associated types are invariant, and hence we // For better or worse, associated types are invariant, and hence we
// get an invariant result for `'a`. // get an invariant result for `'a`.
#[rustc_variance] #[rustc_variance]
struct Foo<'a> { //~ ERROR regions=[[];[o];[]] struct Foo<'a> { //~ ERROR regions=[[o];[]]
x: Box<Fn(i32) -> &'a i32 + 'static> x: Box<Fn(i32) -> &'a i32 + 'static>
} }

View File

@ -13,11 +13,11 @@
#![feature(rustc_attrs)] #![feature(rustc_attrs)]
#[rustc_variance] #[rustc_variance]
trait Foo: 'static { //~ ERROR types=[[o];[];[]] trait Foo: 'static { //~ ERROR types=[[o];[]]
} }
#[rustc_variance] #[rustc_variance]
trait Bar<T> { //~ ERROR types=[[o];[o];[]] trait Bar<T> { //~ ERROR types=[[o, o];[]]
fn do_it(&self) fn do_it(&self)
where T: 'static; where T: 'static;
} }

View File

@ -16,7 +16,7 @@
// Regions that just appear in normal spots are contravariant: // Regions that just appear in normal spots are contravariant:
#[rustc_variance] #[rustc_variance]
struct Test2<'a, 'b, 'c> { //~ ERROR regions=[[];[-, -, -];[]] struct Test2<'a, 'b, 'c> { //~ ERROR regions=[[-, -, -];[]]
x: &'a isize, x: &'a isize,
y: &'b [isize], y: &'b [isize],
c: &'c str c: &'c str
@ -25,7 +25,7 @@ struct Test2<'a, 'b, 'c> { //~ ERROR regions=[[];[-, -, -];[]]
// Those same annotations in function arguments become covariant: // Those same annotations in function arguments become covariant:
#[rustc_variance] #[rustc_variance]
struct Test3<'a, 'b, 'c> { //~ ERROR regions=[[];[+, +, +];[]] struct Test3<'a, 'b, 'c> { //~ ERROR regions=[[+, +, +];[]]
x: extern "Rust" fn(&'a isize), x: extern "Rust" fn(&'a isize),
y: extern "Rust" fn(&'b [isize]), y: extern "Rust" fn(&'b [isize]),
c: extern "Rust" fn(&'c str), c: extern "Rust" fn(&'c str),
@ -34,7 +34,7 @@ struct Test3<'a, 'b, 'c> { //~ ERROR regions=[[];[+, +, +];[]]
// Mutability induces invariance: // Mutability induces invariance:
#[rustc_variance] #[rustc_variance]
struct Test4<'a, 'b:'a> { //~ ERROR regions=[[];[-, o];[]] struct Test4<'a, 'b:'a> { //~ ERROR regions=[[-, o];[]]
x: &'a mut &'b isize, x: &'a mut &'b isize,
} }
@ -42,7 +42,7 @@ struct Test4<'a, 'b:'a> { //~ ERROR regions=[[];[-, o];[]]
// contravariant context: // contravariant context:
#[rustc_variance] #[rustc_variance]
struct Test5<'a, 'b:'a> { //~ ERROR regions=[[];[+, o];[]] struct Test5<'a, 'b:'a> { //~ ERROR regions=[[+, o];[]]
x: extern "Rust" fn(&'a mut &'b isize), x: extern "Rust" fn(&'a mut &'b isize),
} }
@ -52,14 +52,14 @@ struct Test5<'a, 'b:'a> { //~ ERROR regions=[[];[+, o];[]]
// argument list occurs in an invariant context. // argument list occurs in an invariant context.
#[rustc_variance] #[rustc_variance]
struct Test6<'a, 'b:'a> { //~ ERROR regions=[[];[-, o];[]] struct Test6<'a, 'b:'a> { //~ ERROR regions=[[-, o];[]]
x: &'a mut extern "Rust" fn(&'b isize), x: &'a mut extern "Rust" fn(&'b isize),
} }
// No uses at all is bivariant: // No uses at all is bivariant:
#[rustc_variance] #[rustc_variance]
struct Test7<'a> { //~ ERROR regions=[[];[*];[]] struct Test7<'a> { //~ ERROR regions=[[*];[]]
//~^ ERROR parameter `'a` is never used //~^ ERROR parameter `'a` is never used
x: isize x: isize
} }
@ -67,7 +67,7 @@ struct Test7<'a> { //~ ERROR regions=[[];[*];[]]
// Try enums too. // Try enums too.
#[rustc_variance] #[rustc_variance]
enum Test8<'a, 'b, 'c:'b> { //~ ERROR regions=[[];[+, -, o];[]] enum Test8<'a, 'b, 'c:'b> { //~ ERROR regions=[[+, -, o];[]]
Test8A(extern "Rust" fn(&'a isize)), Test8A(extern "Rust" fn(&'a isize)),
Test8B(&'b [isize]), Test8B(&'b [isize]),
Test8C(&'b mut &'c str), Test8C(&'b mut &'c str),

View File

@ -15,7 +15,7 @@
#![feature(rustc_attrs)] #![feature(rustc_attrs)]
#[rustc_variance] #[rustc_variance]
enum Base<'a, 'b, 'c:'b, 'd> { //~ ERROR regions=[[];[+, -, o, *];[]] enum Base<'a, 'b, 'c:'b, 'd> { //~ ERROR regions=[[+, -, o, *];[]]
//~^ ERROR parameter `'d` is never used //~^ ERROR parameter `'d` is never used
Test8A(extern "Rust" fn(&'a isize)), Test8A(extern "Rust" fn(&'a isize)),
Test8B(&'b [isize]), Test8B(&'b [isize]),
@ -23,25 +23,25 @@ enum Base<'a, 'b, 'c:'b, 'd> { //~ ERROR regions=[[];[+, -, o, *];[]]
} }
#[rustc_variance] #[rustc_variance]
struct Derived1<'w, 'x:'y, 'y, 'z> { //~ ERROR regions=[[];[*, o, -, +];[]] struct Derived1<'w, 'x:'y, 'y, 'z> { //~ ERROR regions=[[*, o, -, +];[]]
//~^ ERROR parameter `'w` is never used //~^ ERROR parameter `'w` is never used
f: Base<'z, 'y, 'x, 'w> f: Base<'z, 'y, 'x, 'w>
} }
#[rustc_variance] // Combine - and + to yield o #[rustc_variance] // Combine - and + to yield o
struct Derived2<'a, 'b:'a, 'c> { //~ ERROR regions=[[];[o, o, *];[]] struct Derived2<'a, 'b:'a, 'c> { //~ ERROR regions=[[o, o, *];[]]
//~^ ERROR parameter `'c` is never used //~^ ERROR parameter `'c` is never used
f: Base<'a, 'a, 'b, 'c> f: Base<'a, 'a, 'b, 'c>
} }
#[rustc_variance] // Combine + and o to yield o (just pay attention to 'a here) #[rustc_variance] // Combine + and o to yield o (just pay attention to 'a here)
struct Derived3<'a:'b, 'b, 'c> { //~ ERROR regions=[[];[o, -, *];[]] struct Derived3<'a:'b, 'b, 'c> { //~ ERROR regions=[[o, -, *];[]]
//~^ ERROR parameter `'c` is never used //~^ ERROR parameter `'c` is never used
f: Base<'a, 'b, 'a, 'c> f: Base<'a, 'b, 'a, 'c>
} }
#[rustc_variance] // Combine + and * to yield + (just pay attention to 'a here) #[rustc_variance] // Combine + and * to yield + (just pay attention to 'a here)
struct Derived4<'a, 'b, 'c:'b> { //~ ERROR regions=[[];[+, -, o];[]] struct Derived4<'a, 'b, 'c:'b> { //~ ERROR regions=[[+, -, o];[]]
f: Base<'a, 'b, 'c, 'a> f: Base<'a, 'b, 'c, 'a>
} }

View File

@ -15,48 +15,48 @@
// influence variance. // influence variance.
#[rustc_variance] #[rustc_variance]
trait Getter<T> { //~ ERROR types=[[o];[o];[]] trait Getter<T> { //~ ERROR types=[[o, o];[]]
fn get(&self) -> T; fn get(&self) -> T;
} }
#[rustc_variance] #[rustc_variance]
trait Setter<T> { //~ ERROR types=[[o];[o];[]] trait Setter<T> { //~ ERROR types=[[o, o];[]]
fn get(&self, T); fn get(&self, T);
} }
#[rustc_variance] #[rustc_variance]
struct TestStruct<U,T:Setter<U>> { //~ ERROR types=[[];[+, +];[]] struct TestStruct<U,T:Setter<U>> { //~ ERROR types=[[+, +];[]]
t: T, u: U t: T, u: U
} }
#[rustc_variance] #[rustc_variance]
enum TestEnum<U,T:Setter<U>> {//~ ERROR types=[[];[*, +];[]] enum TestEnum<U,T:Setter<U>> {//~ ERROR types=[[*, +];[]]
//~^ ERROR parameter `U` is never used //~^ ERROR parameter `U` is never used
Foo(T) Foo(T)
} }
#[rustc_variance] #[rustc_variance]
trait TestTrait<U,T:Setter<U>> { //~ ERROR types=[[o];[o, o];[]] trait TestTrait<U,T:Setter<U>> { //~ ERROR types=[[o, o, o];[]]
fn getter(&self, u: U) -> T; fn getter(&self, u: U) -> T;
} }
#[rustc_variance] #[rustc_variance]
trait TestTrait2<U> : Getter<U> { //~ ERROR types=[[o];[o];[]] trait TestTrait2<U> : Getter<U> { //~ ERROR types=[[o, o];[]]
} }
#[rustc_variance] #[rustc_variance]
trait TestTrait3<U> { //~ ERROR types=[[o];[o];[]] trait TestTrait3<U> { //~ ERROR types=[[o, o];[]]
fn getter<T:Getter<U>>(&self); fn getter<T:Getter<U>>(&self);
} }
#[rustc_variance] #[rustc_variance]
struct TestContraStruct<U,T:Setter<U>> { //~ ERROR types=[[];[*, +];[]] struct TestContraStruct<U,T:Setter<U>> { //~ ERROR types=[[*, +];[]]
//~^ ERROR parameter `U` is never used //~^ ERROR parameter `U` is never used
t: T t: T
} }
#[rustc_variance] #[rustc_variance]
struct TestBox<U,T:Getter<U>+Setter<U>> { //~ ERROR types=[[];[*, +];[]] struct TestBox<U,T:Getter<U>+Setter<U>> { //~ ERROR types=[[*, +];[]]
//~^ ERROR parameter `U` is never used //~^ ERROR parameter `U` is never used
t: T t: T
} }

View File

@ -21,7 +21,7 @@ use std::mem;
trait T { fn foo(&self); } trait T { fn foo(&self); }
#[rustc_variance] #[rustc_variance]
struct TOption<'a> { //~ ERROR regions=[[];[-];[]] struct TOption<'a> { //~ ERROR regions=[[-];[]]
v: Option<Box<T + 'a>>, v: Option<Box<T + 'a>>,
} }

View File

@ -14,46 +14,46 @@
#![feature(rustc_attrs)] #![feature(rustc_attrs)]
#[rustc_variance] #[rustc_variance]
struct TestImm<A, B> { //~ ERROR types=[[];[+, +];[]] struct TestImm<A, B> { //~ ERROR types=[[+, +];[]]
x: A, x: A,
y: B, y: B,
} }
#[rustc_variance] #[rustc_variance]
struct TestMut<A, B:'static> { //~ ERROR types=[[];[+, o];[]] struct TestMut<A, B:'static> { //~ ERROR types=[[+, o];[]]
x: A, x: A,
y: &'static mut B, y: &'static mut B,
} }
#[rustc_variance] #[rustc_variance]
struct TestIndirect<A:'static, B:'static> { //~ ERROR types=[[];[+, o];[]] struct TestIndirect<A:'static, B:'static> { //~ ERROR types=[[+, o];[]]
m: TestMut<A, B> m: TestMut<A, B>
} }
#[rustc_variance] #[rustc_variance]
struct TestIndirect2<A:'static, B:'static> { //~ ERROR types=[[];[o, o];[]] struct TestIndirect2<A:'static, B:'static> { //~ ERROR types=[[o, o];[]]
n: TestMut<A, B>, n: TestMut<A, B>,
m: TestMut<B, A> m: TestMut<B, A>
} }
#[rustc_variance] #[rustc_variance]
trait Getter<A> { //~ ERROR types=[[o];[o];[]] trait Getter<A> { //~ ERROR types=[[o, o];[]]
fn get(&self) -> A; fn get(&self) -> A;
} }
#[rustc_variance] #[rustc_variance]
trait Setter<A> { //~ ERROR types=[[o];[o];[]] trait Setter<A> { //~ ERROR types=[[o, o];[]]
fn set(&mut self, a: A); fn set(&mut self, a: A);
} }
#[rustc_variance] #[rustc_variance]
trait GetterSetter<A> { //~ ERROR types=[[o];[o];[]] trait GetterSetter<A> { //~ ERROR types=[[o, o];[]]
fn get(&self) -> A; fn get(&self) -> A;
fn set(&mut self, a: A); fn set(&mut self, a: A);
} }
#[rustc_variance] #[rustc_variance]
trait GetterInTypeBound<A> { //~ ERROR types=[[o];[o];[]] trait GetterInTypeBound<A> { //~ ERROR types=[[o, o];[]]
// Here, the use of `A` in the method bound *does* affect // Here, the use of `A` in the method bound *does* affect
// variance. Think of it as if the method requested a dictionary // variance. Think of it as if the method requested a dictionary
// for `T:Getter<A>`. Since this dictionary is an input, it is // for `T:Getter<A>`. Since this dictionary is an input, it is
@ -63,12 +63,12 @@ trait GetterInTypeBound<A> { //~ ERROR types=[[o];[o];[]]
} }
#[rustc_variance] #[rustc_variance]
trait SetterInTypeBound<A> { //~ ERROR types=[[o];[o];[]] trait SetterInTypeBound<A> { //~ ERROR types=[[o, o];[]]
fn do_it<T:Setter<A>>(&self); fn do_it<T:Setter<A>>(&self);
} }
#[rustc_variance] #[rustc_variance]
struct TestObject<A, R> { //~ ERROR types=[[];[o, o];[]] struct TestObject<A, R> { //~ ERROR types=[[o, o];[]]
n: Box<Setter<A>+Send>, n: Box<Setter<A>+Send>,
m: Box<Getter<R>+Send>, m: Box<Getter<R>+Send>,
} }

View File

@ -17,32 +17,32 @@ use std::cell::Cell;
// not considered bivariant. // not considered bivariant.
#[rustc_variance] #[rustc_variance]
struct InvariantMut<'a,A:'a,B:'a> { //~ ERROR types=[[];[o, o];[]], regions=[[];[-];[]] struct InvariantMut<'a,A:'a,B:'a> { //~ ERROR types=[[o, o];[]], regions=[[-];[]]
t: &'a mut (A,B) t: &'a mut (A,B)
} }
#[rustc_variance] #[rustc_variance]
struct InvariantCell<A> { //~ ERROR types=[[];[o];[]] struct InvariantCell<A> { //~ ERROR types=[[o];[]]
t: Cell<A> t: Cell<A>
} }
#[rustc_variance] #[rustc_variance]
struct InvariantIndirect<A> { //~ ERROR types=[[];[o];[]] struct InvariantIndirect<A> { //~ ERROR types=[[o];[]]
t: InvariantCell<A> t: InvariantCell<A>
} }
#[rustc_variance] #[rustc_variance]
struct Covariant<A> { //~ ERROR types=[[];[+];[]] struct Covariant<A> { //~ ERROR types=[[+];[]]
t: A, u: fn() -> A t: A, u: fn() -> A
} }
#[rustc_variance] #[rustc_variance]
struct Contravariant<A> { //~ ERROR types=[[];[-];[]] struct Contravariant<A> { //~ ERROR types=[[-];[]]
t: fn(A) t: fn(A)
} }
#[rustc_variance] #[rustc_variance]
enum Enum<A,B,C> { //~ ERROR types=[[];[+, -, o];[]] enum Enum<A,B,C> { //~ ERROR types=[[+, -, o];[]]
Foo(Covariant<A>), Foo(Covariant<A>),
Bar(Contravariant<B>), Bar(Contravariant<B>),
Zed(Covariant<C>,Contravariant<C>) Zed(Covariant<C>,Contravariant<C>)