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.
use hir::def_id::DefId;
use ty::subst::ParamSpace;
use util::nodemap::NodeMap;
use syntax::ast;
use hir;
@ -31,7 +30,7 @@ pub enum Def {
AssociatedTy(DefId /* trait */, DefId),
Trait(DefId),
PrimTy(hir::PrimTy),
TyParam(ParamSpace, u32, DefId, ast::Name),
TyParam(DefId),
Upvar(DefId, // def id of closed over local
ast::NodeId, // node id of closed over local
usize, // index in the freevars list of the closure
@ -122,7 +121,7 @@ impl Def {
match *self {
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::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::Local(id, _) | Def::Upvar(id, _, _, _) => {
id

View File

@ -95,7 +95,7 @@ impl<'a, 'tcx> MarkSymbolVisitor<'a, 'tcx> {
Def::AssociatedTy(..) | Def::Method(_) | Def::AssociatedConst(_)
if self.tcx.trait_of_item(def.def_id()).is_some() => {
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, _) => {
self.check_def_id(tyid.did)
}

View File

@ -14,7 +14,6 @@ use super::{SelectionContext, Obligation, ObligationCause};
use middle::cstore::LOCAL_CRATE;
use hir::def_id::DefId;
use ty::subst::TypeSpace;
use ty::{self, Ty, TyCtxt};
use infer::{InferCtxt, TypeOrigin};
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
// 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
// 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) {
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) {
self_match_impls.push(def_id);
if trait_ref.substs.types.get_slice(TypeSpace).iter()
.zip(impl_trait_ref.substs.types.get_slice(TypeSpace))
if trait_ref.substs.types.get_slice(TypeSpace)[1..].iter()
.zip(&impl_trait_ref.substs.types.get_slice(TypeSpace)[1..])
.all(|(u,v)| self.fuzzy_match_tys(u, v))
{
fuzzy_match_impls.push(def_id);

View File

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

View File

@ -1353,7 +1353,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, '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> {

View File

@ -9,7 +9,6 @@
// except according to those terms.
use hir::def_id::DefId;
use ty::subst;
use infer::type_variable;
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::TyProjection(_) => "associated type".to_string(),
ty::TyParam(ref p) => {
if p.space == subst::SelfSpace {
if p.is_self() {
"Self".to_string()
} else {
"type parameter".to_string()

View File

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

View File

@ -1225,7 +1225,7 @@ impl<'tcx> TraitRef<'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>] {

View File

@ -305,7 +305,7 @@ pub struct TraitObject<'tcx> {
///
/// 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
/// `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
/// that case the `Self` parameter is absent from the substitutions.
@ -512,7 +512,7 @@ impl<'a, 'gcx, 'tcx> 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 {
@ -524,7 +524,13 @@ impl<'a, 'gcx, 'tcx> ParamTy {
}
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 {
match self.sty {
TyParam(ref p) => p.space == subst::SelfSpace,
TyParam(ref p) => p.is_self(),
_ => false
}
}

View File

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

View File

@ -62,35 +62,36 @@ pub enum Ns {
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,
substs: &subst::Substs,
did: DefId,
ns: Ns,
projections: &[ty::ProjectionPredicate])
-> fmt::Result {
let (fn_trait_kind, verbose, item_name, is_in_trait) = ty::tls::with(|tcx| {
let is_in_trait = ns == Ns::Value && tcx.trait_of_item(did).is_some();
if is_in_trait {
write!(f, "<{} as ", substs.types.get(subst::SelfSpace, 0))?;
let mut verbose = false;
let mut num_supplied_defaults = 0;
let mut has_self = false;
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 {
@ -107,15 +108,12 @@ pub fn parameterized(f: &mut fmt::Formatter,
(did, None)
};
write!(f, "{}", tcx.item_path_str(did))?;
Ok((tcx.lang_items.fn_trait_kind(did),
tcx.sess.verbose(),
item_name,
is_in_trait))
Ok((tcx.lang_items.fn_trait_kind(did), item_name))
})?;
if !verbose && fn_trait_kind.is_some() && projections.len() == 1 {
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);
}
}
@ -160,18 +158,9 @@ pub fn parameterized(f: &mut fmt::Formatter,
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);
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, "<", ", ")?;
write!(f, "{}", ty)?;
}
@ -189,7 +178,7 @@ pub fn parameterized(f: &mut fmt::Formatter,
if ns == Ns::Value {
empty.set(true);
if is_in_trait {
if has_self {
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::patch::MirPatch;
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::transform::{Pass, MirPass, MirSource};
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 free_func = tcx.lang_items.require(lang_items::BoxFreeFnLangItem)
.unwrap_or_else(|e| tcx.sess.fatal(&e));
let substs = Substs::new(tcx,
VecPerParamSpace::new(vec![], vec![], vec![ty]),
VecPerParamSpace::new(vec![], vec![], vec![]));
let substs = Substs::new_fn(tcx, vec![ty], vec![]);
let fty = tcx.lookup_item_type(free_func).ty.subst(tcx, substs);
self.patch.new_block(BasicBlockData {

View File

@ -413,7 +413,7 @@ impl tr for Def {
Def::AssociatedTy(trait_did, did) =>
Def::AssociatedTy(trait_did.tr(dcx), did.tr(dcx)),
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) => {
let nid1 = dcx.tr_id(nid1);
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
F: FnMut(&mut TyDecoder<'a, 'tcx>) -> T,
{
let (mut a, mut b, mut c) = (vec![], vec![], vec![]);
for r in &mut [&mut a, &mut b, &mut c] {
let (mut a, mut b) = (vec![], vec![]);
for r in &mut [&mut a, &mut b] {
assert_eq!(self.next(), '[');
while self.peek() != ']' {
r.push(f(self));
}
assert_eq!(self.next(), ']');
}
VecPerParamSpace::new(a, b, c)
VecPerParamSpace::new(a, b)
}
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_id::{CRATE_DEF_INDEX, DefId};
use rustc::ty;
use rustc::ty::subst::{ParamSpace, FnSpace, TypeSpace};
use rustc::hir::{Freevar, FreevarMap, TraitCandidate, TraitMap, GlobMap};
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) {
let type_parameters = match foreign_item.node {
ForeignItemKind::Fn(_, ref generics) => {
HasTypeParameters(generics, FnSpace, ItemRibKind)
HasTypeParameters(generics, ItemRibKind)
}
ForeignItemKind::Static(..) => NoTypeParameters,
};
@ -625,10 +624,6 @@ enum TypeParameters<'a, 'b> {
HasTypeParameters(// Type parameters.
&'b Generics,
// Identifies the things that these parameters
// were declared on (type, fn, etc)
ParamSpace,
// The kind of the rib used for type parameters.
RibKind<'a>),
}
@ -1613,12 +1608,9 @@ impl<'a> Resolver<'a> {
match item.node {
ItemKind::Enum(_, ref generics) |
ItemKind::Ty(_, ref generics) |
ItemKind::Struct(_, ref generics) => {
self.with_type_parameter_rib(HasTypeParameters(generics, TypeSpace, ItemRibKind),
|this| visit::walk_item(this, item));
}
ItemKind::Struct(_, 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));
}
@ -1634,10 +1626,7 @@ impl<'a> Resolver<'a> {
ItemKind::Trait(_, ref generics, ref bounds, ref trait_items) => {
// Create a new rib for the trait-wide type parameters.
self.with_type_parameter_rib(HasTypeParameters(generics,
TypeSpace,
ItemRibKind),
|this| {
self.with_type_parameter_rib(HasTypeParameters(generics, ItemRibKind), |this| {
let local_def_id = this.definitions.local_def_id(item.id);
this.with_self_rib(Def::SelfTy(Some(local_def_id), None), |this| {
this.visit_generics(generics);
@ -1660,7 +1649,6 @@ impl<'a> Resolver<'a> {
TraitItemKind::Method(ref sig, _) => {
let type_parameters =
HasTypeParameters(&sig.generics,
FnSpace,
MethodRibKind(!sig.decl.has_self()));
this.with_type_parameter_rib(type_parameters, |this| {
visit::walk_trait_item(this, trait_item)
@ -1729,10 +1717,10 @@ impl<'a> Resolver<'a> {
where F: FnOnce(&mut Resolver)
{
match type_parameters {
HasTypeParameters(generics, space, rib_kind) => {
HasTypeParameters(generics, rib_kind) => {
let mut function_type_rib = Rib::new(rib_kind);
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;
debug!("with_type_parameter_rib: {}", type_parameter.id);
@ -1745,7 +1733,7 @@ impl<'a> Resolver<'a> {
// plain insert (no renaming)
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);
self.record_def(type_parameter.id, PathResolution::new(def));
}
@ -1917,10 +1905,7 @@ impl<'a> Resolver<'a> {
item_id: NodeId,
impl_items: &[ImplItem]) {
// If applicable, create a rib for the type parameters.
self.with_type_parameter_rib(HasTypeParameters(generics,
TypeSpace,
ItemRibKind),
|this| {
self.with_type_parameter_rib(HasTypeParameters(generics, ItemRibKind), |this| {
// Resolve the type parameters.
this.visit_generics(generics);
@ -1953,7 +1938,6 @@ impl<'a> Resolver<'a> {
// specific type parameters.
let type_parameters =
HasTypeParameters(&sig.generics,
FnSpace,
MethodRibKind(!sig.decl.has_self()));
this.with_type_parameter_rib(type_parameters, |this| {
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::TyAlias(def_id) |
Def::Trait(def_id) |
Def::TyParam(_, _, def_id, _) => {
Def::TyParam(def_id) => {
Some(Data::TypeRefData(TypeRefData {
span: sub_span.unwrap(),
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.
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.
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 middle::resolve_lifetime as rl;
use rustc::lint;
use rustc::ty::subst::{TypeSpace, SelfSpace, Subst, Substs};
use rustc::ty::subst::{TypeSpace, Subst, Substs};
use rustc::traits;
use rustc::ty::{self, Ty, TyCtxt, ToPredicate, TypeFoldable};
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.
if let Some(num_provided) = num_types_provided {
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);
}
@ -476,13 +477,16 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
assert_eq!(def.space, TypeSpace);
regions[def.index as usize]
}, |def, substs| {
assert!(def.space == SelfSpace || def.space == TypeSpace);
assert!(def.space == TypeSpace);
let i = def.index as usize;
if def.space == SelfSpace {
// Self, which must have been provided.
assert_eq!(i, 0);
self_ty.expect("Self type parameter missing")
} else if num_types_provided.map_or(false, |n| i < n) {
// Handle Self first, so we can adjust the index to match the AST.
if let (0, Some(ty)) = (i, self_ty) {
return ty;
}
let i = i - self_ty.is_some() as usize;
if num_types_provided.map_or(false, |n| i < n) {
// A provided type parameter.
match *parameters {
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),
}
}
(&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_name = tcx.type_parameter_def(param_node_id).name;
match self.find_bound_for_assoc_item(param_node_id,
param_name,
assoc_name,
@ -1336,10 +1341,13 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
}
}
_ => {
self.report_ambiguous_associated_type(span,
&ty.to_string(),
"Trait",
&assoc_name.as_str());
// Don't print TyErr to the user.
if !ty.references_error() {
self.report_ambiguous_associated_type(span,
&ty.to_string(),
"Trait",
&assoc_name.as_str());
}
return (tcx.types.err, Def::Err);
}
};
@ -1477,9 +1485,25 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
did,
base_segments.last().unwrap())
}
Def::TyParam(space, index, _, name) => {
Def::TyParam(did) => {
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)) => {
// Self in impl (we know the concrete type).

View File

@ -204,7 +204,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
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);
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);
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!(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, _| {
self.region_var_for_def(span, def)
}, |def, substs| {
if def.space == subst::SelfSpace {
if def.index == 0 {
self_ty
} else if let Some(ref input_types) = opt_input_types {
input_types[def.index as usize]
input_types[def.index as usize - 1]
} else {
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));
assert_eq!(m.generics.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
@ -755,11 +751,9 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
let substs = Substs::for_item(self.tcx, trait_def_id, |def, _| {
self.region_var_for_def(self.span, def)
}, |def, substs| {
if def.space == subst::SelfSpace {
assert_eq!(def.index, 0);
if def.index == 0 {
step.self_ty
} else {
assert_eq!(def.space, subst::TypeSpace);
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 i = def.index as usize;
let segment = match def.space {
subst::SelfSpace => None,
subst::TypeSpace => type_segment,
subst::FnSpace => fn_segment
};
@ -4241,9 +4240,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
self.region_var_for_def(span, def)
}
}, |def, substs| {
let i = def.index as usize;
let mut i = def.index as usize;
let segment = match def.space {
subst::SelfSpace => None,
subst::TypeSpace => type_segment,
subst::FnSpace => fn_segment
};
@ -4252,18 +4250,24 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
Some(&hir::ParenthesizedParameters(_)) => bug!(),
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 default = if can_omit && types.len() == 0 {
def.default
} else {
None
};
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) {
if let Some(ast_ty) = types.get(i) {
// A provided type parameter.
self.to_ty(ast_ty)
} else if let Some(default) = default {
@ -4371,6 +4375,11 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
// Check provided type parameters.
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()
.take_while(|d| d.default.is_none())
.count();

View File

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

View File

@ -386,7 +386,7 @@ impl<'a, 'gcx, 'tcx> CoherenceChecker<'a, 'gcx, 'tcx> {
let source = tcx.lookup_item_type(impl_did).ty;
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)",
source, target);

View File

@ -65,7 +65,7 @@ use middle::lang_items::SizedTraitLangItem;
use middle::const_val::ConstVal;
use rustc_const_eval::EvalHint::UncheckedExprHint;
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::{self, ToPolyTraitRef, Ty, TyCtxt, TypeScheme};
use rustc::ty::{VariantKind};
@ -85,7 +85,6 @@ use std::rc::Rc;
use syntax::{abi, ast, attr};
use syntax::parse::token::keywords;
use syntax::ptr::P;
use syntax_pos::Span;
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);
match path_res.base_def {
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)
}
_ => false
@ -1333,7 +1332,7 @@ fn convert_trait_predicates<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, it: &hir::Item)
// add in the explicit where-clauses
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,
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 def = ty::TypeParameterDef {
space: SelfSpace,
space: TypeSpace,
index: 0,
name: keywords::SelfType.name(),
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();
// Now create the real type parameters.
let types = ast_generics.ty_params.iter().enumerate().map(|(i, _)| {
get_or_create_type_parameter_def(ccx, ast_generics, space, i as u32, allow_defaults)
let types = ast_generics.ty_params.iter().enumerate().map(|(i, p)| {
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();
let has_self = base_generics.has_self || opt_self.is_some();
let (regions, types) = match space {
SelfSpace => bug!(),
TypeSpace => {
assert_eq!(base_generics.regions.as_full_slice().len(), 0);
assert_eq!(base_generics.types.as_full_slice().len(), 0);
(VecPerParamSpace::new(vec![], regions, vec![]),
VecPerParamSpace::new(opt_self.into_iter().collect(), types, vec![]))
(VecPerParamSpace::new(regions, vec![]),
VecPerParamSpace::new(opt_self.into_iter().chain(types).collect(), vec![]))
}
FnSpace => {
assert_eq!(base_generics.regions.len(FnSpace), 0);
assert_eq!(base_generics.types.len(FnSpace), 0);
(VecPerParamSpace::new(base_generics.regions.get_slice(SelfSpace).to_vec(),
base_generics.regions.get_slice(TypeSpace).to_vec(),
(VecPerParamSpace::new(base_generics.regions.get_slice(TypeSpace).to_vec(),
regions),
VecPerParamSpace::new(base_generics.types.get_slice(SelfSpace).to_vec(),
base_generics.types.get_slice(TypeSpace).to_vec(),
VecPerParamSpace::new(base_generics.types.get_slice(TypeSpace).to_vec(),
types))
}
};
@ -1674,7 +1671,7 @@ fn ty_generic_predicates_for_type_or_impl<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
generics: &hir::Generics)
-> 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>,
@ -1682,7 +1679,7 @@ fn ty_generic_predicates_for_fn<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
base_predicates: &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`.
@ -1752,7 +1749,8 @@ fn early_bound_lifetimes_from_generics<'a, 'tcx, 'hir>(
fn ty_generic_predicates<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
space: ParamSpace,
ast_generics: &hir::Generics,
base_predicates: &ty::GenericPredicates<'tcx>)
base_predicates: &ty::GenericPredicates<'tcx>,
has_self: bool)
-> ty::GenericPredicates<'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
// type parameter (e.g., `<T:Foo>`).
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 bounds = compute_bounds(&ccx.icx(&(base_predicates, ast_generics)),
param_ty,
@ -1850,50 +1848,22 @@ fn ty_generic_predicates<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
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>,
ast_generics: &hir::Generics,
space: ParamSpace,
index: u32,
param: &hir::TyParam,
allow_defaults: bool)
-> ty::TypeParameterDef<'tcx>
{
let param = &ast_generics.ty_params[index as usize];
let tcx = ccx.tcx;
match tcx.ty_param_defs.borrow().get(&param.id) {
Some(d) => { return d.clone(); }
None => { }
}
let default = param.default.as_ref().map(
|def| convert_default_type_parameter(ccx, def, space, index)
);
let default =
param.default.as_ref().map(|def| ccx.icx(&()).to_ty(&ExplicitRscope, def));
let object_lifetime_default =
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,
};
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());
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
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_def_id: DefId)
{
@ -2173,12 +2147,11 @@ fn enforce_impl_params_are_constrained<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
impl_trait_ref,
&mut input_parameters);
for (index, ty_param) in ast_generics.ty_params.iter().enumerate() {
let param_ty = ty::ParamTy { space: TypeSpace,
idx: index as u32,
name: ty_param.name };
let ty_generics = generics_of_def_id(ccx, impl_def_id);
for (ty_param, param) in ty_generics.types.as_full_slice().iter().zip(&generics.ty_params) {
let param_ty = ty::ParamTy::for_def(ty_param);
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
// 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.regions.is_empty_in(subst::SelfSpace));
assert!(item_type.generics.regions.is_empty_in(subst::FnSpace));
self.add_constraints_from_substs(
@ -394,14 +392,12 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
}
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`:
let contra = self.contravariant(variance);
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);
for projection in &data.projection_bounds {

View File

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

View File

@ -21,7 +21,7 @@
use arena::TypedArena;
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::maps::ItemVariances;
use std::fmt;
@ -164,16 +164,16 @@ impl<'a, 'tcx> TermsContext<'a, 'tcx> {
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() {
let id = p.lifetime.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() {
let i = has_self as usize + i;
self.add_inferred(item_id, TypeParam, TypeSpace, i, p.id);
}
@ -233,7 +233,7 @@ impl<'a, 'tcx> TermsContext<'a, 'tcx> {
-> ty::Variance
{
match space {
SelfSpace | FnSpace => {
FnSpace => {
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::fold::Folder;
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::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 {
let lifetimes = substs.regions.get_slice(subst::TypeSpace)
.iter()
.filter_map(|v| v.clean(cx))
.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()) {
// 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
// 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 {
Path {
global: false,
segments: vec![PathSegment {
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 {
ty::BoundSend =>
(tcx.lang_items.send_trait().unwrap(),
external_path(cx, "Send", None, vec![], empty)),
external_path(cx, "Send", None, false, vec![], empty)),
ty::BoundSized =>
(tcx.lang_items.sized_trait().unwrap(),
external_path(cx, "Sized", None, vec![], empty)),
external_path(cx, "Sized", None, false, vec![], empty)),
ty::BoundCopy =>
(tcx.lang_items.copy_trait().unwrap(),
external_path(cx, "Copy", None, vec![], empty)),
external_path(cx, "Copy", None, false, vec![], empty)),
ty::BoundSync =>
(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);
TraitBound(PolyTrait {
@ -728,14 +729,14 @@ impl<'tcx> Clean<TyParamBound> for ty::TraitRef<'tcx> {
};
inline::record_extern_fqn(cx, self.def_id, TypeTrait);
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",
self.substs.types.get_slice(ParamSpace::TypeSpace));
&self.input_types()[1..]);
// collect any late bound regions
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 {
for &ty_s in ts {
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
// predicates field (see rustc_typeck::collect::ty_generics), so remove
// them.
let stripped_typarams = gens.types.get_slice(space).iter().map(|tp| {
tp.clean(cx)
let stripped_typarams = gens.types.get_slice(space).iter().filter_map(|tp| {
if tp.name == keywords::SelfType.name() {
assert_eq!(tp.index, 0);
None
} else {
Some(tp.clean(cx))
}
}).collect::<Vec<_>>();
let stripped_lifetimes = gens.regions.get_slice(space).iter().map(|rp| {
let mut srp = rp.clone();
@ -1820,7 +1826,7 @@ impl<'tcx> Clean<Type> for ty::Ty<'tcx> {
};
inline::record_extern_fqn(cx, did, kind);
let path = external_path(cx, &cx.tcx().item_name(did).as_str(),
None, vec![], substs);
None, false, vec![], substs);
ResolvedPath {
path: path,
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(),
Some(did), bindings, obj.principal.0.substs);
Some(did), false, bindings, obj.principal.0.substs);
ResolvedPath {
path: path,
typarams: Some(typarams),

View File

@ -8,15 +8,13 @@
// option. This file may not be copied, modified, or distributed
// 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; }
impl<T: ?Sized> Mirror for T { type It = Self; }
struct S(Option<<S as Mirror>::It>);
#[rustc_no_mir] // FIXME #27840 MIR tries to represent `std::option::Option<S>` first.
fn main() {
let _s = S(None);
}

View File

@ -10,5 +10,7 @@
#![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() {}

View File

@ -20,12 +20,12 @@ trait Trait<'a> {
}
#[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 ())
}
#[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
}

View File

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

View File

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

View File

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

View File

@ -15,7 +15,7 @@
#![feature(rustc_attrs)]
#[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
Test8A(extern "Rust" fn(&'a isize)),
Test8B(&'b [isize]),
@ -23,25 +23,25 @@ enum Base<'a, 'b, 'c:'b, 'd> { //~ ERROR regions=[[];[+, -, o, *];[]]
}
#[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
f: Base<'z, 'y, 'x, 'w>
}
#[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
f: Base<'a, 'a, 'b, 'c>
}
#[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
f: Base<'a, 'b, 'a, 'c>
}
#[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>
}

View File

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

View File

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

View File

@ -14,46 +14,46 @@
#![feature(rustc_attrs)]
#[rustc_variance]
struct TestImm<A, B> { //~ ERROR types=[[];[+, +];[]]
struct TestImm<A, B> { //~ ERROR types=[[+, +];[]]
x: A,
y: B,
}
#[rustc_variance]
struct TestMut<A, B:'static> { //~ ERROR types=[[];[+, o];[]]
struct TestMut<A, B:'static> { //~ ERROR types=[[+, o];[]]
x: A,
y: &'static mut B,
}
#[rustc_variance]
struct TestIndirect<A:'static, B:'static> { //~ ERROR types=[[];[+, o];[]]
struct TestIndirect<A:'static, B:'static> { //~ ERROR types=[[+, o];[]]
m: TestMut<A, B>
}
#[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>,
m: TestMut<B, A>
}
#[rustc_variance]
trait Getter<A> { //~ ERROR types=[[o];[o];[]]
trait Getter<A> { //~ ERROR types=[[o, o];[]]
fn get(&self) -> A;
}
#[rustc_variance]
trait Setter<A> { //~ ERROR types=[[o];[o];[]]
trait Setter<A> { //~ ERROR types=[[o, o];[]]
fn set(&mut self, a: A);
}
#[rustc_variance]
trait GetterSetter<A> { //~ ERROR types=[[o];[o];[]]
trait GetterSetter<A> { //~ ERROR types=[[o, o];[]]
fn get(&self) -> A;
fn set(&mut self, a: A);
}
#[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
// variance. Think of it as if the method requested a dictionary
// 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]
trait SetterInTypeBound<A> { //~ ERROR types=[[o];[o];[]]
trait SetterInTypeBound<A> { //~ ERROR types=[[o, o];[]]
fn do_it<T:Setter<A>>(&self);
}
#[rustc_variance]
struct TestObject<A, R> { //~ ERROR types=[[];[o, o];[]]
struct TestObject<A, R> { //~ ERROR types=[[o, o];[]]
n: Box<Setter<A>+Send>,
m: Box<Getter<R>+Send>,
}

View File

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