Move associated types into the Assoc space and add in the builtin bounds
from the definition (including Sized).
This commit is contained in:
parent
d2f8074eac
commit
fb9d0ccc2f
@ -118,10 +118,11 @@ impl Substs {
|
||||
|
||||
pub fn new_trait(t: Vec<ty::t>,
|
||||
r: Vec<ty::Region>,
|
||||
a: Vec<ty::t>,
|
||||
s: ty::t)
|
||||
-> Substs
|
||||
{
|
||||
Substs::new(VecPerParamSpace::new(t, vec!(s), Vec::new(), Vec::new()),
|
||||
Substs::new(VecPerParamSpace::new(t, vec!(s), a, Vec::new()),
|
||||
VecPerParamSpace::new(r, Vec::new(), Vec::new(), Vec::new()))
|
||||
}
|
||||
|
||||
|
@ -1683,6 +1683,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||
vec![arguments_tuple.subst(self.tcx(), substs),
|
||||
new_signature.output.unwrap().subst(self.tcx(), substs)],
|
||||
vec![],
|
||||
vec![],
|
||||
obligation.self_ty())
|
||||
});
|
||||
|
||||
|
@ -573,10 +573,6 @@ pub struct ctxt<'tcx> {
|
||||
/// Maps def IDs to true if and only if they're associated types.
|
||||
pub associated_types: RefCell<DefIdMap<bool>>,
|
||||
|
||||
/// Maps def IDs of traits to information about their associated types.
|
||||
pub trait_associated_types:
|
||||
RefCell<DefIdMap<Rc<Vec<AssociatedTypeInfo>>>>,
|
||||
|
||||
/// Caches the results of trait selection. This cache is used
|
||||
/// for things that do not have to do with the parameters in scope.
|
||||
pub selection_cache: traits::SelectionCache,
|
||||
@ -1564,7 +1560,6 @@ pub fn mk_ctxt<'tcx>(s: Session,
|
||||
stability: RefCell::new(stability),
|
||||
capture_modes: capture_modes,
|
||||
associated_types: RefCell::new(DefIdMap::new()),
|
||||
trait_associated_types: RefCell::new(DefIdMap::new()),
|
||||
selection_cache: traits::SelectionCache::new(),
|
||||
repr_hint_cache: RefCell::new(DefIdMap::new()),
|
||||
}
|
||||
@ -1994,6 +1989,16 @@ impl ItemSubsts {
|
||||
}
|
||||
}
|
||||
|
||||
impl ParamBounds {
|
||||
pub fn empty() -> ParamBounds {
|
||||
ParamBounds {
|
||||
builtin_bounds: empty_builtin_bounds(),
|
||||
trait_bounds: Vec::new(),
|
||||
region_bounds: Vec::new(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Type utilities
|
||||
|
||||
pub fn type_is_nil(ty: t) -> bool {
|
||||
@ -4155,18 +4160,6 @@ impl Ord for AssociatedTypeInfo {
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the associated types belonging to the given trait, in parameter
|
||||
/// order.
|
||||
pub fn associated_types_for_trait(cx: &ctxt, trait_id: ast::DefId)
|
||||
-> Rc<Vec<AssociatedTypeInfo>> {
|
||||
cx.trait_associated_types
|
||||
.borrow()
|
||||
.find(&trait_id)
|
||||
.expect("associated_types_for_trait(): trait not found, try calling \
|
||||
ensure_associated_types()")
|
||||
.clone()
|
||||
}
|
||||
|
||||
pub fn trait_item_def_ids(cx: &ctxt, id: ast::DefId)
|
||||
-> Rc<Vec<ImplOrTraitItemId>> {
|
||||
lookup_locally_or_in_crate_store("trait_item_def_ids",
|
||||
|
@ -54,7 +54,7 @@ use middle::def;
|
||||
use middle::lang_items::{FnTraitLangItem, FnMutTraitLangItem};
|
||||
use middle::lang_items::{FnOnceTraitLangItem};
|
||||
use middle::resolve_lifetime as rl;
|
||||
use middle::subst::{FnSpace, TypeSpace, SelfSpace, Subst, Substs};
|
||||
use middle::subst::{FnSpace, TypeSpace, AssocSpace, SelfSpace, Subst, Substs};
|
||||
use middle::subst::{VecPerParamSpace};
|
||||
use middle::ty;
|
||||
use middle::typeck::lookup_def_tcx;
|
||||
@ -215,7 +215,8 @@ fn ast_path_substs<'tcx,AC,RS>(
|
||||
associated_ty: Option<ty::t>,
|
||||
path: &ast::Path)
|
||||
-> Substs
|
||||
where AC: AstConv<'tcx>, RS: RegionScope {
|
||||
where AC: AstConv<'tcx>, RS: RegionScope
|
||||
{
|
||||
/*!
|
||||
* Given a path `path` that refers to an item `I` with the
|
||||
* declared generics `decl_generics`, returns an appropriate
|
||||
@ -338,17 +339,21 @@ fn ast_path_substs<'tcx,AC,RS>(
|
||||
substs.types.push(TypeSpace, default);
|
||||
}
|
||||
None => {
|
||||
// This is an associated type.
|
||||
substs.types.push(
|
||||
TypeSpace,
|
||||
this.associated_type_binding(path.span,
|
||||
associated_ty,
|
||||
decl_def_id,
|
||||
param.def_id))
|
||||
tcx.sess.span_bug(path.span,
|
||||
"extra parameter without default");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for param in decl_generics.types.get_slice(AssocSpace).iter() {
|
||||
substs.types.push(
|
||||
AssocSpace,
|
||||
this.associated_type_binding(path.span,
|
||||
associated_ty,
|
||||
decl_def_id,
|
||||
param.def_id))
|
||||
}
|
||||
|
||||
substs
|
||||
}
|
||||
|
||||
@ -628,9 +633,13 @@ fn mk_pointer<'tcx, AC: AstConv<'tcx>, RS: RegionScope>(
|
||||
a_seq_ty: &ast::Ty,
|
||||
ptr_ty: PointerTy,
|
||||
constr: |ty::t| -> ty::t)
|
||||
-> ty::t {
|
||||
-> ty::t
|
||||
{
|
||||
let tcx = this.tcx();
|
||||
debug!("mk_pointer(ptr_ty={})", ptr_ty);
|
||||
|
||||
debug!("mk_pointer(ptr_ty={}, a_seq_ty={})",
|
||||
ptr_ty,
|
||||
a_seq_ty.repr(tcx));
|
||||
|
||||
match a_seq_ty.node {
|
||||
ast::TyVec(ref ty) => {
|
||||
@ -730,7 +739,13 @@ fn associated_ty_to_ty<'tcx,AC,RS>(this: &AC,
|
||||
trait_type_id: ast::DefId,
|
||||
span: Span)
|
||||
-> ty::t
|
||||
where AC: AstConv<'tcx>, RS: RegionScope {
|
||||
where AC: AstConv<'tcx>, RS: RegionScope
|
||||
{
|
||||
debug!("associated_ty_to_ty(trait_path={}, for_ast_type={}, trait_type_id={})",
|
||||
trait_path.repr(this.tcx()),
|
||||
for_ast_type.repr(this.tcx()),
|
||||
trait_type_id.repr(this.tcx()));
|
||||
|
||||
// Find the trait that this associated type belongs to.
|
||||
let trait_did = match ty::impl_or_trait_item(this.tcx(),
|
||||
trait_type_id).container() {
|
||||
@ -757,9 +772,16 @@ fn associated_ty_to_ty<'tcx,AC,RS>(this: &AC,
|
||||
None,
|
||||
Some(for_type),
|
||||
trait_path);
|
||||
|
||||
debug!("associated_ty_to_ty(trait_ref={})",
|
||||
trait_ref.repr(this.tcx()));
|
||||
|
||||
let trait_def = this.get_trait_def(trait_did);
|
||||
for type_parameter in trait_def.generics.types.iter() {
|
||||
if type_parameter.def_id == trait_type_id {
|
||||
debug!("associated_ty_to_ty(type_parameter={} substs={})",
|
||||
type_parameter.repr(this.tcx()),
|
||||
trait_ref.substs.repr(this.tcx()));
|
||||
return *trait_ref.substs.types.get(type_parameter.space,
|
||||
type_parameter.index)
|
||||
}
|
||||
@ -772,7 +794,10 @@ fn associated_ty_to_ty<'tcx,AC,RS>(this: &AC,
|
||||
// Parses the programmer's textual representation of a type into our
|
||||
// internal notion of a type.
|
||||
pub fn ast_ty_to_ty<'tcx, AC: AstConv<'tcx>, RS: RegionScope>(
|
||||
this: &AC, rscope: &RS, ast_ty: &ast::Ty) -> ty::t {
|
||||
this: &AC, rscope: &RS, ast_ty: &ast::Ty) -> ty::t
|
||||
{
|
||||
debug!("ast_ty_to_ty(ast_ty={})",
|
||||
ast_ty.repr(this.tcx()));
|
||||
|
||||
let tcx = this.tcx();
|
||||
|
||||
|
@ -305,6 +305,12 @@ fn collect_trait_methods(ccx: &CrateCtxt,
|
||||
}
|
||||
});
|
||||
|
||||
debug!("ty_method_of_trait_method yielded {} \
|
||||
for method {} of trait {}",
|
||||
ty_method.repr(ccx.tcx),
|
||||
trait_item.repr(ccx.tcx),
|
||||
local_def(trait_id).repr(ccx.tcx));
|
||||
|
||||
make_method_ty(ccx, &*ty_method);
|
||||
|
||||
tcx.impl_or_trait_items
|
||||
@ -460,7 +466,7 @@ fn convert_associated_type(ccx: &CrateCtxt,
|
||||
// associated type.
|
||||
let type_parameter_def = trait_def.generics
|
||||
.types
|
||||
.get_slice(subst::TypeSpace)
|
||||
.get_slice(subst::AssocSpace)
|
||||
.iter()
|
||||
.find(|def| {
|
||||
def.def_id == local_def(associated_type.ty_param.id)
|
||||
@ -475,7 +481,7 @@ fn convert_associated_type(ccx: &CrateCtxt,
|
||||
}
|
||||
};
|
||||
let param_type = ty::mk_param(ccx.tcx,
|
||||
subst::TypeSpace,
|
||||
type_parameter_def.space,
|
||||
type_parameter_def.index,
|
||||
local_def(associated_type.ty_param.id));
|
||||
ccx.tcx.tcache.borrow_mut().insert(local_def(associated_type.ty_param.id),
|
||||
@ -780,25 +786,18 @@ impl<'a,'tcx> AstConv<'tcx> for ImplCtxt<'a,'tcx> {
|
||||
ty: Option<ty::t>,
|
||||
trait_id: ast::DefId,
|
||||
associated_type_id: ast::DefId)
|
||||
-> ty::t {
|
||||
ensure_associated_types(self, trait_id);
|
||||
let associated_type_ids = ty::associated_types_for_trait(self.ccx.tcx,
|
||||
trait_id);
|
||||
-> ty::t
|
||||
{
|
||||
let trait_def = ty::lookup_trait_def(self.tcx(), trait_id);
|
||||
match self.opt_trait_ref_id {
|
||||
Some(trait_ref_id) if trait_ref_id == trait_id => {
|
||||
// It's an associated type on the trait that we're
|
||||
// implementing.
|
||||
let associated_type_id =
|
||||
associated_type_ids.iter()
|
||||
.find(|id| {
|
||||
id.def_id == associated_type_id
|
||||
})
|
||||
.expect("associated_type_binding(): \
|
||||
expected associated type ID \
|
||||
in trait");
|
||||
let associated_type =
|
||||
ty::impl_or_trait_item(self.ccx.tcx,
|
||||
associated_type_id.def_id);
|
||||
assert!(trait_def.generics.types
|
||||
.get_slice(subst::AssocSpace)
|
||||
.iter()
|
||||
.any(|type_param_def| type_param_def.def_id == associated_type_id));
|
||||
let associated_type = ty::impl_or_trait_item(self.ccx.tcx, associated_type_id);
|
||||
for impl_item in self.impl_items.iter() {
|
||||
match *impl_item {
|
||||
ast::MethodImplItem(_) => {}
|
||||
@ -980,7 +979,7 @@ impl<'a,'tcx> AstConv<'tcx> for TraitMethodCtxt<'a,'tcx> {
|
||||
ast::TypeTraitItem(ref item) => {
|
||||
if local_def(item.ty_param.id) == associated_type_id {
|
||||
return ty::mk_param(self.tcx(),
|
||||
subst::TypeSpace,
|
||||
subst::AssocSpace,
|
||||
index,
|
||||
associated_type_id)
|
||||
}
|
||||
@ -1451,7 +1450,8 @@ pub fn trait_def_of_item(ccx: &CrateCtxt, it: &ast::Item) -> Rc<ty::TraitDef> {
|
||||
trait_id: ast::NodeId,
|
||||
generics: &ast::Generics,
|
||||
items: &[ast::TraitItem])
|
||||
-> subst::Substs {
|
||||
-> subst::Substs
|
||||
{
|
||||
// Creates a no-op substitution for the trait's type parameters.
|
||||
let regions =
|
||||
generics.lifetimes
|
||||
@ -1464,7 +1464,7 @@ pub fn trait_def_of_item(ccx: &CrateCtxt, it: &ast::Item) -> Rc<ty::TraitDef> {
|
||||
.collect();
|
||||
|
||||
// Start with the generics in the type parameters...
|
||||
let mut types: Vec<_> =
|
||||
let types: Vec<_> =
|
||||
generics.ty_params
|
||||
.iter()
|
||||
.enumerate()
|
||||
@ -1472,24 +1472,27 @@ pub fn trait_def_of_item(ccx: &CrateCtxt, it: &ast::Item) -> Rc<ty::TraitDef> {
|
||||
i, local_def(def.id)))
|
||||
.collect();
|
||||
|
||||
// ...and add generics synthesized from the associated types.
|
||||
for item in items.iter() {
|
||||
match *item {
|
||||
// ...and also create generics synthesized from the associated types.
|
||||
let assoc_types: Vec<_> =
|
||||
items.iter()
|
||||
.flat_map(|item| match *item {
|
||||
ast::TypeTraitItem(ref trait_item) => {
|
||||
let index = types.len();
|
||||
types.push(ty::mk_param(ccx.tcx,
|
||||
subst::TypeSpace,
|
||||
index,
|
||||
local_def(trait_item.ty_param.id)))
|
||||
Some(ty::mk_param(ccx.tcx,
|
||||
subst::AssocSpace,
|
||||
index,
|
||||
local_def(trait_item.ty_param.id))).into_iter()
|
||||
}
|
||||
ast::RequiredMethod(_) | ast::ProvidedMethod(_) => {}
|
||||
}
|
||||
}
|
||||
ast::RequiredMethod(_) | ast::ProvidedMethod(_) => {
|
||||
None.into_iter()
|
||||
}
|
||||
})
|
||||
.collect();
|
||||
|
||||
let self_ty =
|
||||
ty::mk_param(ccx.tcx, subst::SelfSpace, 0, local_def(trait_id));
|
||||
|
||||
subst::Substs::new_trait(types, regions, self_ty)
|
||||
subst::Substs::new_trait(types, regions, assoc_types, self_ty)
|
||||
}
|
||||
}
|
||||
|
||||
@ -1680,14 +1683,14 @@ fn ty_generics_for_trait(ccx: &CrateCtxt,
|
||||
let def =
|
||||
get_or_create_type_parameter_def(
|
||||
ccx,
|
||||
subst::TypeSpace,
|
||||
subst::AssocSpace,
|
||||
&associated_type.ty_param,
|
||||
generics.types.len(subst::TypeSpace),
|
||||
&ast_generics.where_clause,
|
||||
Some(local_def(trait_id)));
|
||||
ccx.tcx.ty_param_defs.borrow_mut().insert(associated_type.ty_param.id,
|
||||
def.clone());
|
||||
generics.types.push(subst::TypeSpace, def);
|
||||
generics.types.push(subst::AssocSpace, def);
|
||||
}
|
||||
ast::ProvidedMethod(_) | ast::RequiredMethod(_) => {}
|
||||
}
|
||||
@ -1786,86 +1789,17 @@ enum CreateTypeParametersForAssociatedTypesFlag {
|
||||
CreateTypeParametersForAssociatedTypes,
|
||||
}
|
||||
|
||||
fn ensure_associated_types<'tcx,AC>(this: &AC, trait_id: ast::DefId)
|
||||
where AC: AstConv<'tcx> {
|
||||
if this.tcx().trait_associated_types.borrow().contains_key(&trait_id) {
|
||||
return
|
||||
}
|
||||
|
||||
if trait_id.krate == ast::LOCAL_CRATE {
|
||||
match this.tcx().map.find(trait_id.node) {
|
||||
Some(ast_map::NodeItem(item)) => {
|
||||
match item.node {
|
||||
ast::ItemTrait(_, _, _, ref trait_items) => {
|
||||
let mut result = Vec::new();
|
||||
let mut index = 0;
|
||||
for trait_item in trait_items.iter() {
|
||||
match *trait_item {
|
||||
ast::RequiredMethod(_) |
|
||||
ast::ProvidedMethod(_) => {}
|
||||
ast::TypeTraitItem(ref associated_type) => {
|
||||
let info = ty::AssociatedTypeInfo {
|
||||
def_id: local_def(associated_type.ty_param.id),
|
||||
index: index,
|
||||
name: associated_type.ty_param.ident.name,
|
||||
};
|
||||
result.push(info);
|
||||
index += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
this.tcx()
|
||||
.trait_associated_types
|
||||
.borrow_mut()
|
||||
.insert(trait_id, Rc::new(result));
|
||||
return
|
||||
}
|
||||
_ => {
|
||||
this.tcx().sess.bug("ensure_associated_types() \
|
||||
called on non-trait")
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
this.tcx().sess.bug("ensure_associated_types() called on \
|
||||
non-trait")
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Cross-crate case.
|
||||
let mut result = Vec::new();
|
||||
let mut index = 0;
|
||||
let trait_items = ty::trait_items(this.tcx(), trait_id);
|
||||
for trait_item in trait_items.iter() {
|
||||
match *trait_item {
|
||||
ty::MethodTraitItem(_) => {}
|
||||
ty::TypeTraitItem(ref associated_type) => {
|
||||
let info = ty::AssociatedTypeInfo {
|
||||
def_id: associated_type.def_id,
|
||||
index: index,
|
||||
name: associated_type.name
|
||||
};
|
||||
result.push(info);
|
||||
index += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
this.tcx().trait_associated_types.borrow_mut().insert(trait_id,
|
||||
Rc::new(result));
|
||||
}
|
||||
|
||||
fn ty_generics<'tcx,AC>(this: &AC,
|
||||
space: subst::ParamSpace,
|
||||
lifetime_defs: &[ast::LifetimeDef],
|
||||
types: &[ast::TyParam],
|
||||
base_generics: ty::Generics,
|
||||
where_clause: &ast::WhereClause,
|
||||
create_type_parameters_for_associated_types:
|
||||
create_type_parameters_for_associated_types_flag:
|
||||
CreateTypeParametersForAssociatedTypesFlag)
|
||||
-> ty::Generics
|
||||
where AC: AstConv<'tcx> {
|
||||
where AC: AstConv<'tcx>
|
||||
{
|
||||
let mut result = base_generics;
|
||||
|
||||
for (i, l) in lifetime_defs.iter().enumerate() {
|
||||
@ -1886,62 +1820,11 @@ fn ty_generics<'tcx,AC>(this: &AC,
|
||||
// First, create the virtual type parameters for associated types if
|
||||
// necessary.
|
||||
let mut associated_types_generics = ty::Generics::empty();
|
||||
match create_type_parameters_for_associated_types {
|
||||
match create_type_parameters_for_associated_types_flag {
|
||||
DontCreateTypeParametersForAssociatedTypes => {}
|
||||
CreateTypeParametersForAssociatedTypes => {
|
||||
let mut index = 0;
|
||||
for param in types.iter() {
|
||||
for bound in param.bounds.iter() {
|
||||
match *bound {
|
||||
ast::TraitTyParamBound(ref trait_bound) => {
|
||||
match lookup_def_tcx(this.tcx(),
|
||||
trait_bound.path.span,
|
||||
trait_bound.ref_id) {
|
||||
def::DefTrait(trait_did) => {
|
||||
ensure_associated_types(this, trait_did);
|
||||
let associated_types =
|
||||
ty::associated_types_for_trait(
|
||||
this.tcx(),
|
||||
trait_did);
|
||||
for associated_type_info in
|
||||
associated_types.iter() {
|
||||
let associated_type_trait_item =
|
||||
ty::impl_or_trait_item(
|
||||
this.tcx(),
|
||||
associated_type_info.def_id);
|
||||
let def = ty::TypeParameterDef {
|
||||
name: associated_type_trait_item.name(),
|
||||
def_id: associated_type_info.def_id,
|
||||
space: space,
|
||||
index: types.len() + index,
|
||||
bounds: ty::ParamBounds {
|
||||
builtin_bounds:
|
||||
ty::empty_builtin_bounds(),
|
||||
trait_bounds: Vec::new(),
|
||||
region_bounds: Vec::new(),
|
||||
},
|
||||
associated_with: {
|
||||
Some(local_def(param.id))
|
||||
},
|
||||
default: None,
|
||||
};
|
||||
associated_types_generics.types
|
||||
.push(space,
|
||||
def);
|
||||
index += 1;
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
this.tcx().sess.span_bug(trait_bound.path
|
||||
.span,
|
||||
"not a trait?!")
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
create_type_parameters_for_associated_types(this, space, types,
|
||||
&mut associated_types_generics);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1976,6 +1859,83 @@ fn ty_generics<'tcx,AC>(this: &AC,
|
||||
}
|
||||
|
||||
return result;
|
||||
|
||||
fn create_type_parameters_for_associated_types<'tcx,AC>(
|
||||
this: &AC,
|
||||
space: subst::ParamSpace,
|
||||
types: &[ast::TyParam],
|
||||
associated_types_generics: &mut ty::Generics)
|
||||
where AC: AstConv<'tcx>
|
||||
{
|
||||
// The idea here is roughly as follows. We start with
|
||||
// an item that is paramerized by various type parameters
|
||||
// with bounds:
|
||||
//
|
||||
// fn foo<T:Iterator>(t: T) { ... }
|
||||
//
|
||||
// The traits in those bounds declare associated types:
|
||||
//
|
||||
// trait Iterator { type Elem; ... }
|
||||
//
|
||||
// And we rewrite the original function so that every associated
|
||||
// type is bound to some fresh type parameter:
|
||||
//
|
||||
// fn foo<A,T:Iterator<Elem=A>>(t: T) { ... }
|
||||
|
||||
// Number of synthetic type parameters created thus far
|
||||
let mut index = 0;
|
||||
|
||||
// Iterate over the each type parameter `T` (from the example)
|
||||
for param in types.iter() {
|
||||
// Iterate over the bound `Iterator`
|
||||
for bound in param.bounds.iter() {
|
||||
// In the above example, `ast_trait_ref` is `Iterator`.
|
||||
let ast_trait_ref = match *bound {
|
||||
ast::TraitTyParamBound(ref r) => r,
|
||||
ast::UnboxedFnTyParamBound(..) => { continue; }
|
||||
ast::RegionTyParamBound(..) => { continue; }
|
||||
};
|
||||
|
||||
let trait_def_id =
|
||||
match lookup_def_tcx(this.tcx(),
|
||||
ast_trait_ref.path.span,
|
||||
ast_trait_ref.ref_id) {
|
||||
def::DefTrait(trait_def_id) => trait_def_id,
|
||||
_ => {
|
||||
this.tcx().sess.span_bug(ast_trait_ref.path.span,
|
||||
"not a trait?!")
|
||||
}
|
||||
};
|
||||
|
||||
// trait_def_id is def-id of `Iterator`
|
||||
let trait_def = ty::lookup_trait_def(this.tcx(), trait_def_id);
|
||||
let associated_type_defs = trait_def.generics.types.get_slice(subst::AssocSpace);
|
||||
|
||||
// Iterate over each associated type `Elem`
|
||||
for associated_type_def in associated_type_defs.iter() {
|
||||
// Create the fresh type parameter `A`
|
||||
let def = ty::TypeParameterDef {
|
||||
name: associated_type_def.name,
|
||||
def_id: associated_type_def.def_id,
|
||||
space: space,
|
||||
index: types.len() + index,
|
||||
bounds: ty::ParamBounds {
|
||||
builtin_bounds: associated_type_def.bounds.builtin_bounds,
|
||||
|
||||
// FIXME(#18178) -- we should add the other bounds, but
|
||||
// that requires subst and more logic
|
||||
trait_bounds: Vec::new(),
|
||||
region_bounds: Vec::new(),
|
||||
},
|
||||
associated_with: Some(local_def(param.id)),
|
||||
default: None,
|
||||
};
|
||||
associated_types_generics.types.push(space, def);
|
||||
index += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn get_or_create_type_parameter_def<'tcx,AC>(this: &AC,
|
||||
|
@ -774,10 +774,15 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
||||
assert!(generics.regions.len(subst::FnSpace) == 0);
|
||||
|
||||
let type_parameter_count = generics.types.len(subst::TypeSpace);
|
||||
let type_parameters = self.next_ty_vars(type_parameter_count);
|
||||
|
||||
let region_param_defs = generics.regions.get_slice(subst::TypeSpace);
|
||||
let regions = self.region_vars_for_defs(span, region_param_defs);
|
||||
let type_parameters = self.next_ty_vars(type_parameter_count);
|
||||
subst::Substs::new_trait(type_parameters, regions, self_ty)
|
||||
|
||||
let assoc_type_parameter_count = generics.types.len(subst::AssocSpace);
|
||||
let assoc_type_parameters = self.next_ty_vars(assoc_type_parameter_count);
|
||||
|
||||
subst::Substs::new_trait(type_parameters, regions, assoc_type_parameters, self_ty)
|
||||
}
|
||||
|
||||
pub fn fresh_bound_region(&self, binder_id: ast::NodeId) -> ty::Region {
|
||||
@ -791,7 +796,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
||||
|
||||
pub fn ty_to_string(&self, t: ty::t) -> String {
|
||||
ty_to_string(self.tcx,
|
||||
self.resolve_type_vars_if_possible(t))
|
||||
self.resolve_type_vars_if_possible(t))
|
||||
}
|
||||
|
||||
pub fn tys_to_string(&self, ts: &[ty::t]) -> String {
|
||||
|
@ -423,7 +423,13 @@ pub fn ty_to_string(cx: &ctxt, typ: t) -> String {
|
||||
}
|
||||
ty_infer(infer_ty) => infer_ty_to_string(cx, infer_ty),
|
||||
ty_err => "[type error]".to_string(),
|
||||
ty_param(ref param_ty) => param_ty.repr(cx),
|
||||
ty_param(ref param_ty) => {
|
||||
if cx.sess.verbose() {
|
||||
param_ty.repr(cx)
|
||||
} else {
|
||||
param_ty.user_string(cx)
|
||||
}
|
||||
}
|
||||
ty_enum(did, ref substs) | ty_struct(did, ref substs) => {
|
||||
let base = ty::item_path_str(cx, did);
|
||||
let generics = ty::lookup_item_type(cx, did).generics;
|
||||
@ -479,6 +485,17 @@ pub fn parameterized(cx: &ctxt,
|
||||
generics: &ty::Generics)
|
||||
-> String
|
||||
{
|
||||
if cx.sess.verbose() {
|
||||
if substs.is_noop() {
|
||||
return format!("{}", base);
|
||||
} else {
|
||||
return format!("{}<{},{}>",
|
||||
base,
|
||||
substs.regions.repr(cx),
|
||||
substs.types.repr(cx));
|
||||
}
|
||||
}
|
||||
|
||||
let mut strs = Vec::new();
|
||||
|
||||
match substs.regions {
|
||||
@ -503,7 +520,7 @@ pub fn parameterized(cx: &ctxt,
|
||||
let tps = substs.types.get_slice(subst::TypeSpace);
|
||||
let ty_params = generics.types.get_slice(subst::TypeSpace);
|
||||
let has_defaults = ty_params.last().map_or(false, |def| def.default.is_some());
|
||||
let num_defaults = if has_defaults && !cx.sess.verbose() {
|
||||
let num_defaults = if has_defaults {
|
||||
ty_params.iter().zip(tps.iter()).rev().take_while(|&(def, &actual)| {
|
||||
match def.default {
|
||||
Some(default) => default.subst(cx, substs) == actual,
|
||||
@ -518,18 +535,6 @@ pub fn parameterized(cx: &ctxt,
|
||||
strs.push(ty_to_string(cx, *t))
|
||||
}
|
||||
|
||||
if cx.sess.verbose() {
|
||||
for t in substs.types.get_slice(subst::SelfSpace).iter() {
|
||||
strs.push(format!("self {}", t.repr(cx)));
|
||||
}
|
||||
|
||||
// generally there shouldn't be any substs in the fn param
|
||||
// space, but in verbose mode, print them out.
|
||||
for t in substs.types.get_slice(subst::FnSpace).iter() {
|
||||
strs.push(format!("fn {}", t.repr(cx)));
|
||||
}
|
||||
}
|
||||
|
||||
if strs.len() > 0u {
|
||||
format!("{}<{}>", base, strs.connect(", "))
|
||||
} else {
|
||||
@ -725,7 +730,7 @@ impl Repr for ty::TraitRef {
|
||||
fn repr(&self, tcx: &ctxt) -> String {
|
||||
let base = ty::item_path_str(tcx, self.def_id);
|
||||
let trait_def = ty::lookup_trait_def(tcx, self.def_id);
|
||||
format!("<{} as {}>",
|
||||
format!("<{} : {}>",
|
||||
self.substs.self_ty().repr(tcx),
|
||||
parameterized(tcx, base.as_slice(), &self.substs, &trait_def.generics))
|
||||
}
|
||||
@ -740,6 +745,19 @@ impl Repr for ty::TraitDef {
|
||||
}
|
||||
}
|
||||
|
||||
impl Repr for ast::TraitItem {
|
||||
fn repr(&self, _tcx: &ctxt) -> String {
|
||||
match *self {
|
||||
ast::RequiredMethod(ref data) => format!("RequiredMethod({}, id={})",
|
||||
data.ident, data.id),
|
||||
ast::ProvidedMethod(ref data) => format!("ProvidedMethod(id={})",
|
||||
data.id),
|
||||
ast::TypeTraitItem(ref data) => format!("TypeTraitItem({}, id={})",
|
||||
data.ty_param.ident, data.ty_param.id),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Repr for ast::Expr {
|
||||
fn repr(&self, _tcx: &ctxt) -> String {
|
||||
format!("expr({}: {})", self.id, pprust::expr_to_string(self))
|
||||
@ -758,6 +776,12 @@ impl UserString for ast::Path {
|
||||
}
|
||||
}
|
||||
|
||||
impl Repr for ast::Ty {
|
||||
fn repr(&self, _tcx: &ctxt) -> String {
|
||||
format!("type({})", pprust::ty_to_string(self))
|
||||
}
|
||||
}
|
||||
|
||||
impl Repr for ast::Item {
|
||||
fn repr(&self, tcx: &ctxt) -> String {
|
||||
format!("item({})", tcx.map.node_to_string(self.id))
|
||||
@ -1261,7 +1285,8 @@ impl UserString for ParamTy {
|
||||
|
||||
impl Repr for ParamTy {
|
||||
fn repr(&self, tcx: &ctxt) -> String {
|
||||
self.user_string(tcx)
|
||||
let ident = self.user_string(tcx);
|
||||
format!("{}/{}.{}", ident, self.space, self.idx)
|
||||
}
|
||||
}
|
||||
|
||||
|
24
src/test/compile-fail/associated-types-unsized.rs
Normal file
24
src/test/compile-fail/associated-types-unsized.rs
Normal file
@ -0,0 +1,24 @@
|
||||
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
#![feature(associated_types)]
|
||||
|
||||
trait Get {
|
||||
type Sized? Value;
|
||||
fn get(&self) -> <Self as Get>::Value;
|
||||
}
|
||||
|
||||
fn foo<T:Get>(t: T) {
|
||||
let x = t.get(); //~ ERROR the trait `core::kinds::Sized` is not implemented
|
||||
}
|
||||
|
||||
fn main() {
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user