auto merge of #19391 : nick29581/rust/assoc-eq, r=nikomatsakis
r? @nikomatsakis cc @aturon (I think you were interested in this for some library stuff) closes #18432
This commit is contained in:
commit
9146a919b6
@ -148,5 +148,9 @@ register_diagnostics!(
|
||||
E0169,
|
||||
E0170,
|
||||
E0171,
|
||||
E0172
|
||||
E0172,
|
||||
E0173,
|
||||
E0174,
|
||||
E0177,
|
||||
E0178
|
||||
)
|
||||
|
@ -435,7 +435,7 @@ pub fn get_symbol(data: &[u8], id: ast::NodeId) -> String {
|
||||
}
|
||||
|
||||
// Something that a name can resolve to.
|
||||
#[deriving(Clone)]
|
||||
#[deriving(Clone,Show)]
|
||||
pub enum DefLike {
|
||||
DlDef(def::Def),
|
||||
DlImpl(ast::DefId),
|
||||
|
@ -1405,10 +1405,22 @@ impl<'a, 'tcx> Rebuilder<'a, 'tcx> {
|
||||
let new_types = data.types.map(|t| {
|
||||
self.rebuild_arg_ty_or_output(&**t, lifetime, anon_nums, region_names)
|
||||
});
|
||||
let new_bindings = data.bindings.map(|b| {
|
||||
P(ast::TypeBinding {
|
||||
id: b.id,
|
||||
ident: b.ident,
|
||||
ty: self.rebuild_arg_ty_or_output(&*b.ty,
|
||||
lifetime,
|
||||
anon_nums,
|
||||
region_names),
|
||||
span: b.span
|
||||
})
|
||||
});
|
||||
ast::AngleBracketedParameters(ast::AngleBracketedParameterData {
|
||||
lifetimes: new_lts,
|
||||
types: new_types
|
||||
})
|
||||
types: new_types,
|
||||
bindings: new_bindings,
|
||||
})
|
||||
}
|
||||
};
|
||||
let new_seg = ast::PathSegment {
|
||||
|
@ -1453,8 +1453,15 @@ impl<'a, 'tcx, 'v> Visitor<'v> for VisiblePrivateTypesVisitor<'a, 'tcx> {
|
||||
}
|
||||
}
|
||||
for predicate in generics.where_clause.predicates.iter() {
|
||||
for bound in predicate.bounds.iter() {
|
||||
self.check_ty_param_bound(predicate.span, bound)
|
||||
match predicate {
|
||||
&ast::WherePredicate::BoundPredicate(ref bound_pred) => {
|
||||
for bound in bound_pred.bounds.iter() {
|
||||
self.check_ty_param_bound(bound_pred.span, bound)
|
||||
}
|
||||
}
|
||||
&ast::WherePredicate::EqPredicate(ref eq_pred) => {
|
||||
self.visit_ty(&*eq_pred.ty);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -108,7 +108,7 @@ pub type ExportMap2 = NodeMap<Vec<Export2>>;
|
||||
|
||||
pub struct Export2 {
|
||||
pub name: String, // The name of the target.
|
||||
pub def_id: DefId, // The definition of the target.
|
||||
pub def_id: DefId, // The definition of the target.
|
||||
}
|
||||
|
||||
// This set contains all exported definitions from external crates. The set does
|
||||
@ -314,7 +314,7 @@ impl<'a> Copy for TypeParameters<'a> {}
|
||||
|
||||
// The rib kind controls the translation of local
|
||||
// definitions (`DefLocal`) to upvars (`DefUpvar`).
|
||||
|
||||
#[deriving(Show)]
|
||||
enum RibKind {
|
||||
// No translation needs to be applied.
|
||||
NormalRibKind,
|
||||
@ -340,6 +340,7 @@ enum RibKind {
|
||||
impl Copy for RibKind {}
|
||||
|
||||
// Methods can be required or provided. RequiredMethod methods only occur in traits.
|
||||
#[deriving(Show)]
|
||||
enum MethodSort {
|
||||
RequiredMethod,
|
||||
ProvidedMethod(NodeId)
|
||||
@ -414,6 +415,7 @@ enum DuplicateCheckingMode {
|
||||
impl Copy for DuplicateCheckingMode {}
|
||||
|
||||
/// One local scope.
|
||||
#[deriving(Show)]
|
||||
struct Rib {
|
||||
bindings: HashMap<Name, DefLike>,
|
||||
kind: RibKind,
|
||||
@ -728,8 +730,11 @@ impl NameBindings {
|
||||
let type_def = self.type_def.borrow().clone();
|
||||
match type_def {
|
||||
None => {
|
||||
let module = Module::new(parent_link, def_id, kind,
|
||||
external, is_public);
|
||||
let module = Module::new(parent_link,
|
||||
def_id,
|
||||
kind,
|
||||
external,
|
||||
is_public);
|
||||
*self.type_def.borrow_mut() = Some(TypeNsDef {
|
||||
modifiers: modifiers,
|
||||
module_def: Some(Rc::new(module)),
|
||||
@ -774,9 +779,9 @@ impl NameBindings {
|
||||
}
|
||||
Some(type_def) => {
|
||||
*self.type_def.borrow_mut() = Some(TypeNsDef {
|
||||
module_def: type_def.module_def,
|
||||
type_def: Some(def),
|
||||
type_span: Some(sp),
|
||||
module_def: type_def.module_def,
|
||||
modifiers: modifiers,
|
||||
});
|
||||
}
|
||||
@ -1286,7 +1291,7 @@ impl<'a> Resolver<'a> {
|
||||
}
|
||||
|
||||
fn get_parent_link(&mut self, parent: ReducedGraphParent, name: Name)
|
||||
-> ParentLink {
|
||||
-> ParentLink {
|
||||
match parent {
|
||||
ModuleReducedGraphParent(module_) => {
|
||||
return ModuleParentLink(module_.downgrade(), name);
|
||||
@ -1578,14 +1583,14 @@ impl<'a> Resolver<'a> {
|
||||
|
||||
ItemImpl(_, Some(_), _, _) => parent,
|
||||
|
||||
ItemTrait(_, _, _, ref methods) => {
|
||||
ItemTrait(_, _, _, ref items) => {
|
||||
let name_bindings =
|
||||
self.add_child(name,
|
||||
parent.clone(),
|
||||
ForbidDuplicateTypesAndModules,
|
||||
sp);
|
||||
|
||||
// Add all the methods within to a new module.
|
||||
// Add all the items within to a new module.
|
||||
let parent_link = self.get_parent_link(parent.clone(), name);
|
||||
name_bindings.define_module(parent_link,
|
||||
Some(local_def(item.id)),
|
||||
@ -1598,13 +1603,12 @@ impl<'a> Resolver<'a> {
|
||||
|
||||
let def_id = local_def(item.id);
|
||||
|
||||
// Add the names of all the methods to the trait info.
|
||||
for method in methods.iter() {
|
||||
let (name, kind) = match *method {
|
||||
// Add the names of all the items to the trait info.
|
||||
for trait_item in items.iter() {
|
||||
let (name, kind) = match *trait_item {
|
||||
ast::RequiredMethod(_) |
|
||||
ast::ProvidedMethod(_) => {
|
||||
let ty_m =
|
||||
ast_util::trait_item_to_ty_method(method);
|
||||
let ty_m = ast_util::trait_item_to_ty_method(trait_item);
|
||||
|
||||
let name = ty_m.ident.name;
|
||||
|
||||
@ -3353,7 +3357,7 @@ impl<'a> Resolver<'a> {
|
||||
use_lexical_scope: UseLexicalScopeFlag,
|
||||
span: Span,
|
||||
name_search_type: NameSearchType)
|
||||
-> ResolveResult<(Rc<Module>, LastPrivate)> {
|
||||
-> ResolveResult<(Rc<Module>, LastPrivate)> {
|
||||
let module_path_len = module_path.len();
|
||||
assert!(module_path_len > 0);
|
||||
|
||||
@ -3382,7 +3386,9 @@ impl<'a> Resolver<'a> {
|
||||
mpath.slice_to(idx - 1));
|
||||
return Failed(Some((span, msg)));
|
||||
},
|
||||
None => return Failed(None),
|
||||
None => {
|
||||
return Failed(None)
|
||||
}
|
||||
}
|
||||
}
|
||||
Failed(err) => return Failed(err),
|
||||
@ -3407,9 +3413,8 @@ impl<'a> Resolver<'a> {
|
||||
// This is not a crate-relative path. We resolve the
|
||||
// first component of the path in the current lexical
|
||||
// scope and then proceed to resolve below that.
|
||||
match self.resolve_module_in_lexical_scope(
|
||||
module_,
|
||||
module_path[0]) {
|
||||
match self.resolve_module_in_lexical_scope(module_,
|
||||
module_path[0]) {
|
||||
Failed(err) => return Failed(err),
|
||||
Indeterminate => {
|
||||
debug!("(resolving module path for import) \
|
||||
@ -3576,8 +3581,7 @@ impl<'a> Resolver<'a> {
|
||||
-> ResolveResult<Rc<Module>> {
|
||||
// If this module is an anonymous module, resolve the item in the
|
||||
// lexical scope. Otherwise, resolve the item from the crate root.
|
||||
let resolve_result = self.resolve_item_in_lexical_scope(
|
||||
module_, name, TypeNS);
|
||||
let resolve_result = self.resolve_item_in_lexical_scope(module_, name, TypeNS);
|
||||
match resolve_result {
|
||||
Success((target, _)) => {
|
||||
let bindings = &*target.bindings;
|
||||
@ -4590,25 +4594,42 @@ impl<'a> Resolver<'a> {
|
||||
|
||||
fn resolve_where_clause(&mut self, where_clause: &ast::WhereClause) {
|
||||
for predicate in where_clause.predicates.iter() {
|
||||
match self.resolve_identifier(predicate.ident,
|
||||
TypeNS,
|
||||
true,
|
||||
predicate.span) {
|
||||
Some((def @ DefTyParam(_, _, _), last_private)) => {
|
||||
self.record_def(predicate.id, (def, last_private));
|
||||
}
|
||||
_ => {
|
||||
self.resolve_error(
|
||||
predicate.span,
|
||||
format!("undeclared type parameter `{}`",
|
||||
token::get_ident(
|
||||
predicate.ident)).as_slice());
|
||||
}
|
||||
}
|
||||
match predicate {
|
||||
&ast::WherePredicate::BoundPredicate(ref bound_pred) => {
|
||||
match self.resolve_identifier(bound_pred.ident,
|
||||
TypeNS,
|
||||
true,
|
||||
bound_pred.span) {
|
||||
Some((def @ DefTyParam(..), last_private)) => {
|
||||
self.record_def(bound_pred.id, (def, last_private));
|
||||
}
|
||||
_ => {
|
||||
self.resolve_error(
|
||||
bound_pred.span,
|
||||
format!("undeclared type parameter `{}`",
|
||||
token::get_ident(
|
||||
bound_pred.ident)).as_slice());
|
||||
}
|
||||
}
|
||||
|
||||
for bound in predicate.bounds.iter() {
|
||||
self.resolve_type_parameter_bound(predicate.id, bound,
|
||||
TraitBoundingTypeParameter);
|
||||
for bound in bound_pred.bounds.iter() {
|
||||
self.resolve_type_parameter_bound(bound_pred.id, bound,
|
||||
TraitBoundingTypeParameter);
|
||||
}
|
||||
}
|
||||
&ast::WherePredicate::EqPredicate(ref eq_pred) => {
|
||||
match self.resolve_path(eq_pred.id, &eq_pred.path, TypeNS, true) {
|
||||
Some((def @ DefTyParam(..), last_private)) => {
|
||||
self.record_def(eq_pred.id, (def, last_private));
|
||||
}
|
||||
_ => {
|
||||
self.resolve_error(eq_pred.path.span,
|
||||
"undeclared associated type");
|
||||
}
|
||||
}
|
||||
|
||||
self.resolve_type(&*eq_pred.ty);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -5269,15 +5290,19 @@ impl<'a> Resolver<'a> {
|
||||
path: &Path,
|
||||
namespace: Namespace,
|
||||
check_ribs: bool) -> Option<(Def, LastPrivate)> {
|
||||
// First, resolve the types.
|
||||
// First, resolve the types and associated type bindings.
|
||||
for ty in path.segments.iter().flat_map(|s| s.parameters.types().into_iter()) {
|
||||
self.resolve_type(&**ty);
|
||||
}
|
||||
for binding in path.segments.iter().flat_map(|s| s.parameters.bindings().into_iter()) {
|
||||
self.resolve_type(&*binding.ty);
|
||||
}
|
||||
|
||||
if path.global {
|
||||
return self.resolve_crate_relative_path(path, namespace);
|
||||
}
|
||||
|
||||
// Try to find a path to an item in a module.
|
||||
let unqualified_def =
|
||||
self.resolve_identifier(path.segments
|
||||
.last().unwrap()
|
||||
@ -5307,15 +5332,15 @@ impl<'a> Resolver<'a> {
|
||||
|
||||
// resolve a single identifier (used as a varref)
|
||||
fn resolve_identifier(&mut self,
|
||||
identifier: Ident,
|
||||
namespace: Namespace,
|
||||
check_ribs: bool,
|
||||
span: Span)
|
||||
-> Option<(Def, LastPrivate)> {
|
||||
identifier: Ident,
|
||||
namespace: Namespace,
|
||||
check_ribs: bool,
|
||||
span: Span)
|
||||
-> Option<(Def, LastPrivate)> {
|
||||
if check_ribs {
|
||||
match self.resolve_identifier_in_local_ribs(identifier,
|
||||
namespace,
|
||||
span) {
|
||||
namespace,
|
||||
span) {
|
||||
Some(def) => {
|
||||
return Some((def, LastMod(AllPublic)));
|
||||
}
|
||||
@ -5333,7 +5358,7 @@ impl<'a> Resolver<'a> {
|
||||
containing_module: Rc<Module>,
|
||||
name: Name,
|
||||
namespace: Namespace)
|
||||
-> NameDefinition {
|
||||
-> NameDefinition {
|
||||
// First, search children.
|
||||
self.populate_module_if_necessary(&containing_module);
|
||||
|
||||
@ -5403,9 +5428,9 @@ impl<'a> Resolver<'a> {
|
||||
|
||||
// resolve a "module-relative" path, e.g. a::b::c
|
||||
fn resolve_module_relative_path(&mut self,
|
||||
path: &Path,
|
||||
namespace: Namespace)
|
||||
-> Option<(Def, LastPrivate)> {
|
||||
path: &Path,
|
||||
namespace: Namespace)
|
||||
-> Option<(Def, LastPrivate)> {
|
||||
let module_path = path.segments.init().iter()
|
||||
.map(|ps| ps.identifier.name)
|
||||
.collect::<Vec<_>>();
|
||||
@ -5422,9 +5447,8 @@ impl<'a> Resolver<'a> {
|
||||
let (span, msg) = match err {
|
||||
Some((span, msg)) => (span, msg),
|
||||
None => {
|
||||
let msg = format!("Use of undeclared module `{}`",
|
||||
self.names_to_string(
|
||||
module_path.as_slice()));
|
||||
let msg = format!("Use of undeclared type or module `{}`",
|
||||
self.names_to_string(module_path.as_slice()));
|
||||
(path.span, msg)
|
||||
}
|
||||
};
|
||||
@ -5518,10 +5542,10 @@ impl<'a> Resolver<'a> {
|
||||
}
|
||||
|
||||
fn resolve_identifier_in_local_ribs(&mut self,
|
||||
ident: Ident,
|
||||
namespace: Namespace,
|
||||
span: Span)
|
||||
-> Option<Def> {
|
||||
ident: Ident,
|
||||
namespace: Namespace,
|
||||
span: Span)
|
||||
-> Option<Def> {
|
||||
// Check the local set of ribs.
|
||||
let search_result = match namespace {
|
||||
ValueNS => {
|
||||
|
@ -210,8 +210,22 @@ impl<'a, 'v> Visitor<'v> for LifetimeContext<'a> {
|
||||
}
|
||||
}
|
||||
for predicate in generics.where_clause.predicates.iter() {
|
||||
self.visit_ident(predicate.span, predicate.ident);
|
||||
visit::walk_ty_param_bounds_helper(self, &predicate.bounds);
|
||||
match predicate {
|
||||
&ast::WherePredicate::BoundPredicate(ast::WhereBoundPredicate{ ident,
|
||||
ref bounds,
|
||||
span,
|
||||
.. }) => {
|
||||
self.visit_ident(span, ident);
|
||||
visit::walk_ty_param_bounds_helper(self, bounds);
|
||||
}
|
||||
&ast::WherePredicate::EqPredicate(ast::WhereEqPredicate{ id,
|
||||
ref path,
|
||||
ref ty,
|
||||
.. }) => {
|
||||
self.visit_path(path, id);
|
||||
self.visit_ty(&**ty);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -486,7 +500,12 @@ fn early_bound_lifetime_names(generics: &ast::Generics) -> Vec<ast::Name> {
|
||||
visit::walk_ty_param_bounds_helper(&mut collector, &ty_param.bounds);
|
||||
}
|
||||
for predicate in generics.where_clause.predicates.iter() {
|
||||
visit::walk_ty_param_bounds_helper(&mut collector, &predicate.bounds);
|
||||
match predicate {
|
||||
&ast::WherePredicate::BoundPredicate(ast::WhereBoundPredicate{ref bounds, ..}) => {
|
||||
visit::walk_ty_param_bounds_helper(&mut collector, bounds);
|
||||
}
|
||||
&ast::WherePredicate::EqPredicate(_) => unimplemented!()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -112,7 +112,7 @@ impl<'tcx> Substs<'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn self_ty(&self) -> Option<Ty<'tcx>> {
|
||||
pub fn self_ty(&self) -> Option<Ty<'tcx>> {
|
||||
self.types.get_self().map(|&t| t)
|
||||
}
|
||||
|
||||
@ -123,6 +123,13 @@ pub fn self_ty(&self) -> Option<Ty<'tcx>> {
|
||||
s
|
||||
}
|
||||
|
||||
pub fn with_assoc_tys(&self, assoc_tys: Vec<Ty<'tcx>>) -> Substs<'tcx> {
|
||||
assert!(self.types.is_empty_in(AssocSpace));
|
||||
let mut s = (*self).clone();
|
||||
s.types.replace(AssocSpace, assoc_tys);
|
||||
s
|
||||
}
|
||||
|
||||
pub fn erase_regions(self) -> Substs<'tcx> {
|
||||
let Substs { types, regions: _ } = self;
|
||||
Substs { types: types, regions: ErasedRegions }
|
||||
|
@ -10,7 +10,7 @@
|
||||
// except according to those terms.
|
||||
|
||||
use middle::subst;
|
||||
use middle::subst::{ParamSpace, Substs, VecPerParamSpace};
|
||||
use middle::subst::{ParamSpace, Substs, VecPerParamSpace, Subst};
|
||||
use middle::infer::InferCtxt;
|
||||
use middle::ty::{mod, Ty};
|
||||
use std::collections::HashSet;
|
||||
@ -139,7 +139,7 @@ impl<'cx, 'tcx> Iterator<Rc<ty::TraitRef<'tcx>>> for Supertraits<'cx, 'tcx> {
|
||||
}
|
||||
|
||||
// determine the `self` type, using fresh variables for all variables
|
||||
// declared on the impl declaration e.g., `impl<A,B> for ~[(A,B)]`
|
||||
// declared on the impl declaration e.g., `impl<A,B> for Box<[(A,B)]>`
|
||||
// would return ($0, $1) where $0 and $1 are freshly instantiated type
|
||||
// variables.
|
||||
pub fn fresh_substs_for_impl<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
|
||||
@ -149,7 +149,18 @@ pub fn fresh_substs_for_impl<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
|
||||
{
|
||||
let tcx = infcx.tcx;
|
||||
let impl_generics = ty::lookup_item_type(tcx, impl_def_id).generics;
|
||||
infcx.fresh_substs_for_generics(span, &impl_generics)
|
||||
let input_substs = infcx.fresh_substs_for_generics(span, &impl_generics);
|
||||
|
||||
// Add substs for the associated types bound in the impl.
|
||||
let ref items = tcx.impl_items.borrow()[impl_def_id];
|
||||
let mut assoc_tys = Vec::new();
|
||||
for item in items.iter() {
|
||||
if let &ty::ImplOrTraitItemId::TypeTraitItemId(id) = item {
|
||||
assoc_tys.push(tcx.tcache.borrow()[id].ty.subst(tcx, &input_substs));
|
||||
}
|
||||
}
|
||||
|
||||
input_substs.with_assoc_tys(assoc_tys)
|
||||
}
|
||||
|
||||
impl<'tcx, N> fmt::Show for VtableImplData<'tcx, N> {
|
||||
|
@ -1613,7 +1613,7 @@ pub struct RegionParameterDef {
|
||||
pub bounds: Vec<ty::Region>,
|
||||
}
|
||||
|
||||
/// Information about the type/lifetime parameters associated with an
|
||||
/// Information about the formal type/lifetime parameters associated with an
|
||||
/// item or method. Analogous to ast::Generics.
|
||||
#[deriving(Clone, Show)]
|
||||
pub struct Generics<'tcx> {
|
||||
|
@ -84,13 +84,18 @@ pub trait AstConv<'tcx> {
|
||||
trait_id: ast::DefId)
|
||||
-> bool;
|
||||
|
||||
/// Returns the binding of the given associated type for some type.
|
||||
/// Returns the concrete type bound to the given associated type (indicated
|
||||
/// by associated_type_id) in the current context. For example,
|
||||
/// in `trait Foo { type A; }` looking up `A` will give a type variable;
|
||||
/// in `impl Foo for ... { type A = int; ... }` looking up `A` will give `int`.
|
||||
fn associated_type_binding(&self,
|
||||
span: Span,
|
||||
ty: Option<Ty<'tcx>>,
|
||||
self_ty: Option<Ty<'tcx>>,
|
||||
// DefId for the declaration of the trait
|
||||
// in which the associated type is declared.
|
||||
trait_id: ast::DefId,
|
||||
associated_type_id: ast::DefId)
|
||||
-> Ty<'tcx>;
|
||||
-> Option<Ty<'tcx>>;
|
||||
}
|
||||
|
||||
pub fn ast_region_to_region(tcx: &ty::ctxt, lifetime: &ast::Lifetime)
|
||||
@ -208,7 +213,6 @@ fn ast_path_substs_for_ty<'tcx,AC,RS>(
|
||||
rscope: &RS,
|
||||
decl_def_id: ast::DefId,
|
||||
decl_generics: &ty::Generics<'tcx>,
|
||||
self_ty: Option<Ty<'tcx>>,
|
||||
path: &ast::Path)
|
||||
-> Substs<'tcx>
|
||||
where AC: AstConv<'tcx>, RS: RegionScope
|
||||
@ -226,19 +230,26 @@ fn ast_path_substs_for_ty<'tcx,AC,RS>(
|
||||
assert!(decl_generics.regions.all(|d| d.space == TypeSpace));
|
||||
assert!(decl_generics.types.all(|d| d.space != FnSpace));
|
||||
|
||||
let (regions, types) = match path.segments.last().unwrap().parameters {
|
||||
let (regions, types, assoc_bindings) = match path.segments.last().unwrap().parameters {
|
||||
ast::AngleBracketedParameters(ref data) => {
|
||||
convert_angle_bracketed_parameters(this, rscope, data)
|
||||
}
|
||||
ast::ParenthesizedParameters(ref data) => {
|
||||
span_err!(tcx.sess, path.span, E0169,
|
||||
"parenthesized parameters may only be used with a trait");
|
||||
(Vec::new(), convert_parenthesized_parameters(this, data))
|
||||
(Vec::new(), convert_parenthesized_parameters(this, data), Vec::new())
|
||||
}
|
||||
};
|
||||
|
||||
create_substs_for_ast_path(this, rscope, path.span, decl_def_id,
|
||||
decl_generics, self_ty, types, regions)
|
||||
create_substs_for_ast_path(this,
|
||||
rscope,
|
||||
path.span,
|
||||
decl_def_id,
|
||||
decl_generics,
|
||||
None,
|
||||
types,
|
||||
regions,
|
||||
assoc_bindings)
|
||||
}
|
||||
|
||||
fn create_substs_for_ast_path<'tcx,AC,RS>(
|
||||
@ -249,7 +260,8 @@ fn create_substs_for_ast_path<'tcx,AC,RS>(
|
||||
decl_generics: &ty::Generics<'tcx>,
|
||||
self_ty: Option<Ty<'tcx>>,
|
||||
types: Vec<Ty<'tcx>>,
|
||||
regions: Vec<ty::Region>)
|
||||
regions: Vec<ty::Region>,
|
||||
assoc_bindings: Vec<(ast::Ident, Ty<'tcx>)>)
|
||||
-> Substs<'tcx>
|
||||
where AC: AstConv<'tcx>, RS: RegionScope
|
||||
{
|
||||
@ -356,13 +368,41 @@ fn create_substs_for_ast_path<'tcx,AC,RS>(
|
||||
}
|
||||
}
|
||||
|
||||
for param in decl_generics.types.get_slice(AssocSpace).iter() {
|
||||
substs.types.push(
|
||||
AssocSpace,
|
||||
this.associated_type_binding(span,
|
||||
self_ty,
|
||||
decl_def_id,
|
||||
param.def_id));
|
||||
for formal_assoc in decl_generics.types.get_slice(AssocSpace).iter() {
|
||||
let mut found = false;
|
||||
for &(ident, ty) in assoc_bindings.iter() {
|
||||
if formal_assoc.name.ident() == ident {
|
||||
substs.types.push(AssocSpace, ty);
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if !found {
|
||||
match this.associated_type_binding(span,
|
||||
self_ty,
|
||||
decl_def_id,
|
||||
formal_assoc.def_id) {
|
||||
Some(ty) => {
|
||||
substs.types.push(AssocSpace, ty);
|
||||
}
|
||||
None => {
|
||||
substs.types.push(AssocSpace, ty::mk_err());
|
||||
span_err!(this.tcx().sess, span, E0171,
|
||||
"missing type for associated type `{}`",
|
||||
token::get_ident(formal_assoc.name.ident()));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for &(ident, _) in assoc_bindings.iter() {
|
||||
let mut formal_idents = decl_generics.types.get_slice(AssocSpace)
|
||||
.iter().map(|t| t.name.ident());
|
||||
if !formal_idents.any(|i| i == ident) {
|
||||
span_err!(this.tcx().sess, span, E0177,
|
||||
"associated type `{}` does not exist",
|
||||
token::get_ident(ident));
|
||||
}
|
||||
}
|
||||
|
||||
return substs;
|
||||
@ -371,7 +411,9 @@ fn create_substs_for_ast_path<'tcx,AC,RS>(
|
||||
fn convert_angle_bracketed_parameters<'tcx, AC, RS>(this: &AC,
|
||||
rscope: &RS,
|
||||
data: &ast::AngleBracketedParameterData)
|
||||
-> (Vec<ty::Region>, Vec<Ty<'tcx>>)
|
||||
-> (Vec<ty::Region>,
|
||||
Vec<Ty<'tcx>>,
|
||||
Vec<(ast::Ident, Ty<'tcx>)>)
|
||||
where AC: AstConv<'tcx>, RS: RegionScope
|
||||
{
|
||||
let regions: Vec<_> =
|
||||
@ -384,7 +426,12 @@ fn convert_angle_bracketed_parameters<'tcx, AC, RS>(this: &AC,
|
||||
.map(|t| ast_ty_to_ty(this, rscope, &**t))
|
||||
.collect();
|
||||
|
||||
(regions, types)
|
||||
let assoc_bindings: Vec<_> =
|
||||
data.bindings.iter()
|
||||
.map(|b| (b.ident, ast_ty_to_ty(this, rscope, &*b.ty)))
|
||||
.collect();
|
||||
|
||||
(regions, types, assoc_bindings)
|
||||
}
|
||||
|
||||
/// Returns the appropriate lifetime to use for any output lifetimes
|
||||
@ -468,16 +515,6 @@ fn convert_parenthesized_parameters<'tcx,AC>(this: &AC,
|
||||
vec![input_ty, output]
|
||||
}
|
||||
|
||||
pub fn instantiate_poly_trait_ref<'tcx,AC,RS>(
|
||||
this: &AC,
|
||||
rscope: &RS,
|
||||
ast_trait_ref: &ast::PolyTraitRef,
|
||||
self_ty: Option<Ty<'tcx>>)
|
||||
-> Rc<ty::TraitRef<'tcx>>
|
||||
where AC: AstConv<'tcx>, RS: RegionScope
|
||||
{
|
||||
instantiate_trait_ref(this, rscope, &ast_trait_ref.trait_ref, self_ty)
|
||||
}
|
||||
|
||||
/// Instantiates the path for the given trait reference, assuming that it's bound to a valid trait
|
||||
/// type. Returns the def_id for the defining trait. Fails if the type is a type other than a trait
|
||||
@ -485,7 +522,8 @@ pub fn instantiate_poly_trait_ref<'tcx,AC,RS>(
|
||||
pub fn instantiate_trait_ref<'tcx,AC,RS>(this: &AC,
|
||||
rscope: &RS,
|
||||
ast_trait_ref: &ast::TraitRef,
|
||||
self_ty: Option<Ty<'tcx>>)
|
||||
self_ty: Option<Ty<'tcx>>,
|
||||
allow_eq: AllowEqConstraints)
|
||||
-> Rc<ty::TraitRef<'tcx>>
|
||||
where AC: AstConv<'tcx>,
|
||||
RS: RegionScope
|
||||
@ -494,8 +532,12 @@ pub fn instantiate_trait_ref<'tcx,AC,RS>(this: &AC,
|
||||
ast_trait_ref.path.span,
|
||||
ast_trait_ref.ref_id) {
|
||||
def::DefTrait(trait_def_id) => {
|
||||
let trait_ref = Rc::new(ast_path_to_trait_ref(this, rscope, trait_def_id,
|
||||
self_ty, &ast_trait_ref.path));
|
||||
let trait_ref = Rc::new(ast_path_to_trait_ref(this,
|
||||
rscope,
|
||||
trait_def_id,
|
||||
self_ty,
|
||||
&ast_trait_ref.path,
|
||||
allow_eq));
|
||||
this.tcx().trait_refs.borrow_mut().insert(ast_trait_ref.ref_id,
|
||||
trait_ref.clone());
|
||||
trait_ref
|
||||
@ -508,15 +550,23 @@ pub fn instantiate_trait_ref<'tcx,AC,RS>(this: &AC,
|
||||
}
|
||||
}
|
||||
|
||||
#[deriving(PartialEq,Show)]
|
||||
pub enum AllowEqConstraints {
|
||||
Allow,
|
||||
DontAllow
|
||||
}
|
||||
|
||||
fn ast_path_to_trait_ref<'tcx,AC,RS>(
|
||||
this: &AC,
|
||||
rscope: &RS,
|
||||
trait_def_id: ast::DefId,
|
||||
self_ty: Option<Ty<'tcx>>,
|
||||
path: &ast::Path)
|
||||
path: &ast::Path,
|
||||
allow_eq: AllowEqConstraints)
|
||||
-> ty::TraitRef<'tcx>
|
||||
where AC: AstConv<'tcx>, RS: RegionScope
|
||||
{
|
||||
debug!("ast_path_to_trait_ref {}", path);
|
||||
let trait_def = this.get_trait_def(trait_def_id);
|
||||
|
||||
// the trait reference introduces a binding level here, so
|
||||
@ -526,15 +576,20 @@ fn ast_path_to_trait_ref<'tcx,AC,RS>(
|
||||
// lifetimes. Oh well, not there yet.
|
||||
let shifted_rscope = ShiftedRscope::new(rscope);
|
||||
|
||||
let (regions, types) = match path.segments.last().unwrap().parameters {
|
||||
let (regions, types, assoc_bindings) = match path.segments.last().unwrap().parameters {
|
||||
ast::AngleBracketedParameters(ref data) => {
|
||||
convert_angle_bracketed_parameters(this, &shifted_rscope, data)
|
||||
}
|
||||
ast::ParenthesizedParameters(ref data) => {
|
||||
(Vec::new(), convert_parenthesized_parameters(this, data))
|
||||
(Vec::new(), convert_parenthesized_parameters(this, data), Vec::new())
|
||||
}
|
||||
};
|
||||
|
||||
if allow_eq == AllowEqConstraints::DontAllow && assoc_bindings.len() > 0 {
|
||||
span_err!(this.tcx().sess, path.span, E0173,
|
||||
"equality constraints are not allowed in this position");
|
||||
}
|
||||
|
||||
let substs = create_substs_for_ast_path(this,
|
||||
&shifted_rscope,
|
||||
path.span,
|
||||
@ -542,7 +597,8 @@ fn ast_path_to_trait_ref<'tcx,AC,RS>(
|
||||
&trait_def.generics,
|
||||
self_ty,
|
||||
types,
|
||||
regions);
|
||||
regions,
|
||||
assoc_bindings);
|
||||
|
||||
ty::TraitRef::new(trait_def_id, substs)
|
||||
}
|
||||
@ -564,7 +620,6 @@ pub fn ast_path_to_ty<'tcx, AC: AstConv<'tcx>, RS: RegionScope>(
|
||||
rscope,
|
||||
did,
|
||||
&generics,
|
||||
None,
|
||||
path);
|
||||
let ty = decl_ty.subst(tcx, &substs);
|
||||
TypeAndSubsts { substs: substs, ty: ty }
|
||||
@ -605,7 +660,7 @@ pub fn ast_path_to_ty_relaxed<'tcx,AC,RS>(
|
||||
Substs::new(VecPerParamSpace::params_from_type(type_params),
|
||||
VecPerParamSpace::params_from_type(region_params))
|
||||
} else {
|
||||
ast_path_substs_for_ty(this, rscope, did, &generics, None, path)
|
||||
ast_path_substs_for_ty(this, rscope, did, &generics, path)
|
||||
};
|
||||
|
||||
let ty = decl_ty.subst(tcx, &substs);
|
||||
@ -694,7 +749,8 @@ fn ast_ty_to_trait_ref<'tcx,AC,RS>(this: &AC,
|
||||
rscope,
|
||||
trait_def_id,
|
||||
None,
|
||||
path));
|
||||
path,
|
||||
AllowEqConstraints::Allow));
|
||||
}
|
||||
_ => {
|
||||
span_err!(this.tcx().sess, ty.span, E0172, "expected a reference to a trait");
|
||||
@ -703,7 +759,7 @@ fn ast_ty_to_trait_ref<'tcx,AC,RS>(this: &AC,
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
span_err!(this.tcx().sess, ty.span, E0171,
|
||||
span_err!(this.tcx().sess, ty.span, E0178,
|
||||
"expected a path on the left-hand side of `+`, not `{}`",
|
||||
pprust::ty_to_string(ty));
|
||||
match ty.node {
|
||||
@ -714,8 +770,7 @@ fn ast_ty_to_trait_ref<'tcx,AC,RS>(this: &AC,
|
||||
pprust::ty_to_string(&*mut_ty.ty),
|
||||
pprust::bounds_to_string(bounds));
|
||||
}
|
||||
|
||||
ast::TyRptr(Some(ref lt), ref mut_ty) => {
|
||||
ast::TyRptr(Some(ref lt), ref mut_ty) => {
|
||||
span_note!(this.tcx().sess, ty.span,
|
||||
"perhaps you meant `&{} {}({} +{})`? (per RFC 248)",
|
||||
pprust::lifetime_to_string(lt),
|
||||
@ -732,7 +787,6 @@ fn ast_ty_to_trait_ref<'tcx,AC,RS>(this: &AC,
|
||||
Err(ErrorReported)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
fn trait_ref_to_object_type<'tcx,AC,RS>(this: &AC,
|
||||
@ -773,7 +827,8 @@ fn qpath_to_ty<'tcx,AC,RS>(this: &AC,
|
||||
let trait_ref = instantiate_trait_ref(this,
|
||||
rscope,
|
||||
&*qpath.trait_ref,
|
||||
Some(self_type));
|
||||
Some(self_type),
|
||||
AllowEqConstraints::DontAllow);
|
||||
|
||||
debug!("qpath_to_ty: trait_ref={}", trait_ref.repr(this.tcx()));
|
||||
|
||||
@ -917,7 +972,8 @@ pub fn ast_ty_to_ty<'tcx, AC: AstConv<'tcx>, RS: RegionScope>(
|
||||
rscope,
|
||||
trait_def_id,
|
||||
None,
|
||||
path);
|
||||
path,
|
||||
AllowEqConstraints::Allow);
|
||||
trait_ref_to_object_type(this, rscope, path.span, result, &[])
|
||||
}
|
||||
def::DefTy(did, _) | def::DefStruct(did) => {
|
||||
@ -1341,7 +1397,11 @@ fn conv_ty_poly_trait_ref<'tcx, AC, RS>(
|
||||
|
||||
let main_trait_bound = match partitioned_bounds.trait_bounds.remove(0) {
|
||||
Some(trait_bound) => {
|
||||
Some(instantiate_poly_trait_ref(this, rscope, trait_bound, None))
|
||||
Some(instantiate_trait_ref(this,
|
||||
rscope,
|
||||
&trait_bound.trait_ref,
|
||||
None,
|
||||
AllowEqConstraints::Allow))
|
||||
}
|
||||
None => {
|
||||
this.tcx().sess.span_err(
|
||||
|
@ -310,7 +310,7 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> {
|
||||
substs: rcvr_substs.clone()
|
||||
});
|
||||
|
||||
self.elaborate_bounds(&[trait_ref.clone()], |this, new_trait_ref, m, method_num| {
|
||||
self.elaborate_bounds(&[trait_ref.clone()], false, |this, new_trait_ref, m, method_num| {
|
||||
let vtable_index =
|
||||
get_method_index(tcx, &*new_trait_ref,
|
||||
trait_ref.clone(), method_num);
|
||||
@ -357,7 +357,7 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> {
|
||||
let bounds =
|
||||
self.fcx.inh.param_env.bounds.get(space, index).trait_bounds
|
||||
.as_slice();
|
||||
self.elaborate_bounds(bounds, |this, trait_ref, m, method_num| {
|
||||
self.elaborate_bounds(bounds, true, |this, trait_ref, m, method_num| {
|
||||
let xform_self_ty =
|
||||
this.xform_self_ty(&m, &trait_ref.substs);
|
||||
|
||||
@ -394,6 +394,7 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> {
|
||||
fn elaborate_bounds(
|
||||
&mut self,
|
||||
bounds: &[Rc<ty::TraitRef<'tcx>>],
|
||||
num_includes_types: bool,
|
||||
mk_cand: for<'a> |this: &mut ProbeContext<'a, 'tcx>,
|
||||
tr: Rc<ty::TraitRef<'tcx>>,
|
||||
m: Rc<ty::Method<'tcx>>,
|
||||
@ -407,7 +408,10 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> {
|
||||
continue;
|
||||
}
|
||||
|
||||
let (pos, method) = match trait_method(tcx, bound_trait_ref.def_id, self.method_name) {
|
||||
let (pos, method) = match trait_method(tcx,
|
||||
bound_trait_ref.def_id,
|
||||
self.method_name,
|
||||
num_includes_types) {
|
||||
Some(v) => v,
|
||||
None => { continue; }
|
||||
};
|
||||
@ -1003,12 +1007,18 @@ fn impl_method<'tcx>(tcx: &ty::ctxt<'tcx>,
|
||||
/// index (or `None`, if no such method).
|
||||
fn trait_method<'tcx>(tcx: &ty::ctxt<'tcx>,
|
||||
trait_def_id: ast::DefId,
|
||||
method_name: ast::Name)
|
||||
method_name: ast::Name,
|
||||
num_includes_types: bool)
|
||||
-> Option<(uint, Rc<ty::Method<'tcx>>)>
|
||||
{
|
||||
let trait_items = ty::trait_items(tcx, trait_def_id);
|
||||
trait_items
|
||||
.iter()
|
||||
.filter(|item|
|
||||
num_includes_types || match *item {
|
||||
&ty::MethodTraitItem(_) => true,
|
||||
&ty::TypeTraitItem(_) => false
|
||||
})
|
||||
.enumerate()
|
||||
.find(|&(_, ref item)| item.name() == method_name)
|
||||
.and_then(|(idx, item)| item.as_opt_method().map(|m| (idx, m)))
|
||||
@ -1025,7 +1035,7 @@ fn get_method_index<'tcx>(tcx: &ty::ctxt<'tcx>,
|
||||
// iterating down the supertraits of the object's trait until
|
||||
// we find the trait the method came from, counting up the
|
||||
// methods from them.
|
||||
let mut method_count = 0;
|
||||
let mut method_count = n_method;
|
||||
ty::each_bound_trait_and_supertraits(tcx, &[subtrait], |bound_ref| {
|
||||
if bound_ref.def_id == trait_ref.def_id {
|
||||
false
|
||||
@ -1040,7 +1050,7 @@ fn get_method_index<'tcx>(tcx: &ty::ctxt<'tcx>,
|
||||
true
|
||||
}
|
||||
});
|
||||
method_count + n_method
|
||||
method_count
|
||||
}
|
||||
|
||||
impl<'tcx> Candidate<'tcx> {
|
||||
|
@ -112,7 +112,7 @@ use std::collections::hash_map::{Occupied, Vacant};
|
||||
use std::mem::replace;
|
||||
use std::rc::Rc;
|
||||
use syntax::{mod, abi, attr};
|
||||
use syntax::ast::{mod, ProvidedMethod, RequiredMethod, TypeTraitItem};
|
||||
use syntax::ast::{mod, ProvidedMethod, RequiredMethod, TypeTraitItem, DefId};
|
||||
use syntax::ast_util::{mod, local_def, PostExpansionMethod};
|
||||
use syntax::codemap::{mod, Span};
|
||||
use syntax::owned_slice::OwnedSlice;
|
||||
@ -1585,9 +1585,9 @@ impl<'a, 'tcx> AstConv<'tcx> for FnCtxt<'a, 'tcx> {
|
||||
_: Option<Ty<'tcx>>,
|
||||
_: ast::DefId,
|
||||
_: ast::DefId)
|
||||
-> Ty<'tcx> {
|
||||
-> Option<Ty<'tcx>> {
|
||||
self.tcx().sess.span_err(span, "unsupported associated type binding");
|
||||
ty::mk_err()
|
||||
Some(ty::mk_err())
|
||||
}
|
||||
}
|
||||
|
||||
@ -5281,10 +5281,18 @@ pub fn instantiate_path<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
|
||||
found {} parameter(s)",
|
||||
type_count, data.types.len());
|
||||
substs.types.truncate(space, 0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if data.bindings.len() > 0 {
|
||||
span_err!(fcx.tcx().sess, data.bindings[0].span, E0182,
|
||||
"unexpected binding of associated item in expression path \
|
||||
(only allowed in type paths)");
|
||||
substs.types.truncate(subst::ParamSpace::AssocSpace, 0);
|
||||
}
|
||||
|
||||
{
|
||||
let region_count = region_defs.len(space);
|
||||
assert_eq!(substs.regions().len(space), 0);
|
||||
@ -5299,6 +5307,7 @@ pub fn instantiate_path<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
|
||||
region_count,
|
||||
data.lifetimes.len());
|
||||
substs.mut_regions().truncate(space, 0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -562,7 +562,7 @@ fn enforce_trait_manually_implementable(tcx: &ty::ctxt, sp: Span, trait_def_id:
|
||||
} else {
|
||||
return // everything OK
|
||||
};
|
||||
span_err!(tcx.sess, sp, E0173, "manual implementations of `{}` are experimental", trait_name);
|
||||
span_err!(tcx.sess, sp, E0183, "manual implementations of `{}` are experimental", trait_name);
|
||||
span_help!(tcx.sess, sp,
|
||||
"add `#![feature(unboxed_closures)]` to the crate attributes to enable");
|
||||
}
|
||||
|
@ -32,7 +32,7 @@ as `ty_param()` instances.
|
||||
use self::ConvertMethodContext::*;
|
||||
use self::CreateTypeParametersForAssociatedTypesFlag::*;
|
||||
|
||||
use astconv::{AstConv, ty_of_arg};
|
||||
use astconv::{AstConv, ty_of_arg, AllowEqConstraints};
|
||||
use astconv::{ast_ty_to_ty, ast_region_to_region};
|
||||
use astconv;
|
||||
use metadata::csearch;
|
||||
@ -197,10 +197,10 @@ impl<'a, 'tcx> AstConv<'tcx> for CrateCtxt<'a, 'tcx> {
|
||||
_: Option<Ty<'tcx>>,
|
||||
_: ast::DefId,
|
||||
_: ast::DefId)
|
||||
-> Ty<'tcx> {
|
||||
-> Option<Ty<'tcx>> {
|
||||
self.tcx().sess.span_err(span, "associated types may not be \
|
||||
referenced here");
|
||||
ty::mk_err()
|
||||
Some(ty::mk_err())
|
||||
}
|
||||
}
|
||||
|
||||
@ -663,48 +663,43 @@ fn is_associated_type_valid_for_param(ty: Ty,
|
||||
|
||||
fn find_associated_type_in_generics<'tcx>(tcx: &ty::ctxt<'tcx>,
|
||||
span: Span,
|
||||
ty: Option<Ty<'tcx>>,
|
||||
self_ty: Option<Ty<'tcx>>,
|
||||
associated_type_id: ast::DefId,
|
||||
generics: &ty::Generics<'tcx>)
|
||||
-> Ty<'tcx>
|
||||
-> Option<Ty<'tcx>>
|
||||
{
|
||||
debug!("find_associated_type_in_generics(ty={}, associated_type_id={}, generics={}",
|
||||
ty.repr(tcx), associated_type_id.repr(tcx), generics.repr(tcx));
|
||||
self_ty.repr(tcx), associated_type_id.repr(tcx), generics.repr(tcx));
|
||||
|
||||
let ty = match ty {
|
||||
let self_ty = match self_ty {
|
||||
None => {
|
||||
tcx.sess.span_bug(span,
|
||||
"find_associated_type_in_generics(): no self \
|
||||
type")
|
||||
return None;
|
||||
}
|
||||
Some(ty) => ty,
|
||||
};
|
||||
|
||||
match ty.sty {
|
||||
match self_ty.sty {
|
||||
ty::ty_param(ref param_ty) => {
|
||||
/*let type_parameter = generics.types.get(param_ty.space,
|
||||
param_ty.idx);
|
||||
let param_id = type_parameter.def_id;*/
|
||||
let param_id = param_ty.def_id;
|
||||
for type_parameter in generics.types.iter() {
|
||||
if type_parameter.def_id == associated_type_id
|
||||
&& type_parameter.associated_with == Some(param_id) {
|
||||
return ty::mk_param_from_def(tcx, type_parameter);
|
||||
return Some(ty::mk_param_from_def(tcx, type_parameter));
|
||||
}
|
||||
}
|
||||
|
||||
tcx.sess.span_err(
|
||||
span,
|
||||
format!("no suitable bound on `{}`",
|
||||
ty.user_string(tcx))[]);
|
||||
ty::mk_err()
|
||||
self_ty.user_string(tcx))[]);
|
||||
Some(ty::mk_err())
|
||||
}
|
||||
_ => {
|
||||
tcx.sess.span_err(
|
||||
span,
|
||||
"it is currently unsupported to access associated types except \
|
||||
through a type parameter; this restriction will be lifted in time");
|
||||
ty::mk_err()
|
||||
Some(ty::mk_err())
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -762,16 +757,16 @@ impl<'a,'tcx> AstConv<'tcx> for ImplCtxt<'a,'tcx> {
|
||||
|
||||
fn associated_type_binding(&self,
|
||||
span: Span,
|
||||
ty: Option<Ty<'tcx>>,
|
||||
self_ty: Option<Ty<'tcx>>,
|
||||
trait_id: ast::DefId,
|
||||
associated_type_id: ast::DefId)
|
||||
-> Ty<'tcx>
|
||||
-> Option<Ty<'tcx>>
|
||||
{
|
||||
let trait_def = ty::lookup_trait_def(self.tcx(), trait_id);
|
||||
match self.opt_trait_ref_id {
|
||||
// It's an associated type on the trait that we're
|
||||
// implementing.
|
||||
Some(trait_ref_id) if trait_ref_id == trait_id => {
|
||||
// It's an associated type on the trait that we're
|
||||
// implementing.
|
||||
let trait_def = ty::lookup_trait_def(self.tcx(), trait_id);
|
||||
assert!(trait_def.generics.types
|
||||
.get_slice(subst::AssocSpace)
|
||||
.iter()
|
||||
@ -782,7 +777,7 @@ impl<'a,'tcx> AstConv<'tcx> for ImplCtxt<'a,'tcx> {
|
||||
ast::MethodImplItem(_) => {}
|
||||
ast::TypeImplItem(ref typedef) => {
|
||||
if associated_type.name() == typedef.ident.name {
|
||||
return self.ccx.to_ty(&ExplicitRscope, &*typedef.typ)
|
||||
return Some(self.ccx.to_ty(&ExplicitRscope, &*typedef.typ))
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -801,7 +796,7 @@ impl<'a,'tcx> AstConv<'tcx> for ImplCtxt<'a,'tcx> {
|
||||
// our bounds.
|
||||
find_associated_type_in_generics(self.ccx.tcx,
|
||||
span,
|
||||
ty,
|
||||
self_ty,
|
||||
associated_type_id,
|
||||
self.impl_generics)
|
||||
}
|
||||
@ -840,17 +835,17 @@ impl<'a,'tcx> AstConv<'tcx> for FnCtxt<'a,'tcx> {
|
||||
|
||||
fn associated_type_binding(&self,
|
||||
span: Span,
|
||||
ty: Option<Ty<'tcx>>,
|
||||
self_ty: Option<Ty<'tcx>>,
|
||||
_: ast::DefId,
|
||||
associated_type_id: ast::DefId)
|
||||
-> Ty<'tcx> {
|
||||
-> Option<Ty<'tcx>> {
|
||||
debug!("collect::FnCtxt::associated_type_binding()");
|
||||
|
||||
// The ID should map to an associated type on one of the traits in
|
||||
// our bounds.
|
||||
find_associated_type_in_generics(self.ccx.tcx,
|
||||
span,
|
||||
ty,
|
||||
self_ty,
|
||||
associated_type_id,
|
||||
self.generics)
|
||||
}
|
||||
@ -887,17 +882,17 @@ impl<'a,'tcx> AstConv<'tcx> for ImplMethodCtxt<'a,'tcx> {
|
||||
|
||||
fn associated_type_binding(&self,
|
||||
span: Span,
|
||||
ty: Option<Ty<'tcx>>,
|
||||
self_ty: Option<Ty<'tcx>>,
|
||||
_: ast::DefId,
|
||||
associated_type_id: ast::DefId)
|
||||
-> Ty<'tcx> {
|
||||
-> Option<Ty<'tcx>> {
|
||||
debug!("collect::ImplMethodCtxt::associated_type_binding()");
|
||||
|
||||
// The ID should map to an associated type on one of the traits in
|
||||
// our bounds.
|
||||
find_associated_type_in_generics(self.ccx.tcx,
|
||||
span,
|
||||
ty,
|
||||
self_ty,
|
||||
associated_type_id,
|
||||
self.method_generics)
|
||||
}
|
||||
@ -943,10 +938,10 @@ impl<'a,'tcx> AstConv<'tcx> for TraitMethodCtxt<'a,'tcx> {
|
||||
|
||||
fn associated_type_binding(&self,
|
||||
span: Span,
|
||||
ty: Option<Ty<'tcx>>,
|
||||
self_ty: Option<Ty<'tcx>>,
|
||||
trait_id: ast::DefId,
|
||||
associated_type_id: ast::DefId)
|
||||
-> Ty<'tcx> {
|
||||
-> Option<Ty<'tcx>> {
|
||||
debug!("collect::TraitMethodCtxt::associated_type_binding()");
|
||||
|
||||
// If this is one of our own associated types, return it.
|
||||
@ -957,10 +952,10 @@ impl<'a,'tcx> AstConv<'tcx> for TraitMethodCtxt<'a,'tcx> {
|
||||
ast::RequiredMethod(_) | ast::ProvidedMethod(_) => {}
|
||||
ast::TypeTraitItem(ref item) => {
|
||||
if local_def(item.ty_param.id) == associated_type_id {
|
||||
return ty::mk_param(self.tcx(),
|
||||
subst::AssocSpace,
|
||||
index,
|
||||
associated_type_id)
|
||||
return Some(ty::mk_param(self.tcx(),
|
||||
subst::AssocSpace,
|
||||
index,
|
||||
associated_type_id))
|
||||
}
|
||||
index += 1;
|
||||
}
|
||||
@ -979,7 +974,7 @@ impl<'a,'tcx> AstConv<'tcx> for TraitMethodCtxt<'a,'tcx> {
|
||||
// our bounds.
|
||||
find_associated_type_in_generics(self.ccx.tcx,
|
||||
span,
|
||||
ty,
|
||||
self_ty,
|
||||
associated_type_id,
|
||||
self.method_generics)
|
||||
}
|
||||
@ -1020,17 +1015,17 @@ impl<'a,'tcx,AC:AstConv<'tcx>> AstConv<'tcx> for GenericsCtxt<'a,'tcx,AC> {
|
||||
|
||||
fn associated_type_binding(&self,
|
||||
span: Span,
|
||||
ty: Option<Ty<'tcx>>,
|
||||
self_ty: Option<Ty<'tcx>>,
|
||||
_: ast::DefId,
|
||||
associated_type_id: ast::DefId)
|
||||
-> Ty<'tcx> {
|
||||
-> Option<Ty<'tcx>> {
|
||||
debug!("collect::GenericsCtxt::associated_type_binding()");
|
||||
|
||||
// The ID should map to an associated type on one of the traits in
|
||||
// our bounds.
|
||||
find_associated_type_in_generics(self.chain.tcx(),
|
||||
span,
|
||||
ty,
|
||||
self_ty,
|
||||
associated_type_id,
|
||||
self.associated_types_generics)
|
||||
}
|
||||
@ -1142,8 +1137,11 @@ pub fn convert(ccx: &CrateCtxt, it: &ast::Item) {
|
||||
parent_visibility);
|
||||
|
||||
for trait_ref in opt_trait_ref.iter() {
|
||||
astconv::instantiate_trait_ref(&icx, &ExplicitRscope, trait_ref,
|
||||
Some(selfty));
|
||||
astconv::instantiate_trait_ref(&icx,
|
||||
&ExplicitRscope,
|
||||
trait_ref,
|
||||
Some(selfty),
|
||||
AllowEqConstraints::DontAllow);
|
||||
}
|
||||
},
|
||||
ast::ItemTrait(_, _, _, ref trait_methods) => {
|
||||
@ -1361,8 +1359,12 @@ pub fn trait_def_of_item<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
|
||||
|
||||
let self_param_ty = ty::ParamTy::for_self(def_id);
|
||||
|
||||
let bounds = compute_bounds(ccx, token::SELF_KEYWORD_NAME, self_param_ty,
|
||||
bounds.as_slice(), unbound, it.span,
|
||||
let bounds = compute_bounds(ccx,
|
||||
token::SELF_KEYWORD_NAME,
|
||||
self_param_ty,
|
||||
bounds.as_slice(),
|
||||
unbound,
|
||||
it.span,
|
||||
&generics.where_clause);
|
||||
|
||||
let substs = mk_item_substs(ccx, &ty_generics);
|
||||
@ -1806,7 +1808,7 @@ fn ty_generics<'tcx,AC>(this: &AC,
|
||||
|
||||
return result;
|
||||
|
||||
fn create_type_parameters_for_associated_types<'tcx,AC>(
|
||||
fn create_type_parameters_for_associated_types<'tcx, AC>(
|
||||
this: &AC,
|
||||
space: subst::ParamSpace,
|
||||
types: &[ast::TyParam],
|
||||
@ -1856,8 +1858,17 @@ fn ty_generics<'tcx,AC>(this: &AC,
|
||||
let trait_def = ty::lookup_trait_def(this.tcx(), trait_def_id);
|
||||
let associated_type_defs = trait_def.generics.types.get_slice(subst::AssocSpace);
|
||||
|
||||
// Find any associated type bindings in the bound.
|
||||
let ref segments = ast_trait_ref.trait_ref.path.segments;
|
||||
let bindings = segments[segments.len() -1].parameters.bindings();
|
||||
|
||||
// Iterate over each associated type `Elem`
|
||||
for associated_type_def in associated_type_defs.iter() {
|
||||
if bindings.iter().any(|b| associated_type_def.name.ident() == b.ident) {
|
||||
// Don't add a variable for a bound associated type.
|
||||
continue;
|
||||
}
|
||||
|
||||
// Create the fresh type parameter `A`
|
||||
let def = ty::TypeParameterDef {
|
||||
name: associated_type_def.name,
|
||||
@ -2016,10 +2027,11 @@ fn conv_param_bounds<'tcx,AC>(this: &AC,
|
||||
let trait_bounds: Vec<Rc<ty::TraitRef>> =
|
||||
trait_bounds.into_iter()
|
||||
.map(|bound| {
|
||||
astconv::instantiate_poly_trait_ref(this,
|
||||
&ExplicitRscope,
|
||||
bound,
|
||||
Some(param_ty.to_ty(this.tcx())))
|
||||
astconv::instantiate_trait_ref(this,
|
||||
&ExplicitRscope,
|
||||
&bound.trait_ref,
|
||||
Some(param_ty.to_ty(this.tcx())),
|
||||
AllowEqConstraints::Allow)
|
||||
})
|
||||
.collect();
|
||||
let region_bounds: Vec<ty::Region> =
|
||||
@ -2047,18 +2059,23 @@ fn merge_param_bounds<'a>(tcx: &ty::ctxt,
|
||||
}
|
||||
|
||||
for predicate in where_clause.predicates.iter() {
|
||||
let predicate_param_id =
|
||||
tcx.def_map
|
||||
.borrow()
|
||||
.get(&predicate.id)
|
||||
.expect("compute_bounds(): resolve didn't resolve the type \
|
||||
parameter identifier in a `where` clause")
|
||||
.def_id();
|
||||
if param_ty.def_id != predicate_param_id {
|
||||
continue
|
||||
}
|
||||
for bound in predicate.bounds.iter() {
|
||||
result.push(bound);
|
||||
match predicate {
|
||||
&ast::WherePredicate::BoundPredicate(ref bound_pred) => {
|
||||
let predicate_param_id =
|
||||
tcx.def_map
|
||||
.borrow()
|
||||
.get(&bound_pred.id)
|
||||
.expect("merge_param_bounds(): resolve didn't resolve the \
|
||||
type parameter identifier in a `where` clause")
|
||||
.def_id();
|
||||
if param_ty.def_id != predicate_param_id {
|
||||
continue
|
||||
}
|
||||
for bound in bound_pred.bounds.iter() {
|
||||
result.push(bound);
|
||||
}
|
||||
}
|
||||
&ast::WherePredicate::EqPredicate(_) => panic!("not implemented")
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -149,5 +149,11 @@ register_diagnostics!(
|
||||
E0171,
|
||||
E0172,
|
||||
E0173, // manual implementations of unboxed closure traits are experimental
|
||||
E0174 // explicit use of unboxed closure methods are experimental
|
||||
E0174, // explicit use of unboxed closure methods are experimental
|
||||
E0177,
|
||||
E0178,
|
||||
E0180,
|
||||
E0181,
|
||||
E0182,
|
||||
E0183
|
||||
)
|
||||
|
@ -693,9 +693,16 @@ pub struct WherePredicate {
|
||||
|
||||
impl Clean<WherePredicate> for ast::WherePredicate {
|
||||
fn clean(&self, cx: &DocContext) -> WherePredicate {
|
||||
WherePredicate {
|
||||
name: self.ident.clean(cx),
|
||||
bounds: self.bounds.clean(cx)
|
||||
match *self {
|
||||
ast::WherePredicate::BoundPredicate(ref wbp) => {
|
||||
WherePredicate {
|
||||
name: wbp.ident.clean(cx),
|
||||
bounds: wbp.bounds.clean(cx)
|
||||
}
|
||||
}
|
||||
ast::WherePredicate::EqPredicate(_) => {
|
||||
unimplemented!();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -255,6 +255,7 @@ impl PathParameters {
|
||||
AngleBracketedParameters(AngleBracketedParameterData {
|
||||
lifetimes: Vec::new(),
|
||||
types: OwnedSlice::empty(),
|
||||
bindings: OwnedSlice::empty(),
|
||||
})
|
||||
}
|
||||
|
||||
@ -307,6 +308,17 @@ impl PathParameters {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn bindings(&self) -> Vec<&P<TypeBinding>> {
|
||||
match *self {
|
||||
AngleBracketedParameters(ref data) => {
|
||||
data.bindings.iter().collect()
|
||||
}
|
||||
ParenthesizedParameters(_) => {
|
||||
Vec::new()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// A path like `Foo<'a, T>`
|
||||
@ -316,11 +328,14 @@ pub struct AngleBracketedParameterData {
|
||||
pub lifetimes: Vec<Lifetime>,
|
||||
/// The type parameters for this path segment, if present.
|
||||
pub types: OwnedSlice<P<Ty>>,
|
||||
/// Bindings (equality constraints) on associated types, if present.
|
||||
/// E.g., `Foo<A=Bar>`.
|
||||
pub bindings: OwnedSlice<P<TypeBinding>>,
|
||||
}
|
||||
|
||||
impl AngleBracketedParameterData {
|
||||
fn is_empty(&self) -> bool {
|
||||
self.lifetimes.is_empty() && self.types.is_empty()
|
||||
self.lifetimes.is_empty() && self.types.is_empty() && self.bindings.is_empty()
|
||||
}
|
||||
}
|
||||
|
||||
@ -406,13 +421,27 @@ pub struct WhereClause {
|
||||
}
|
||||
|
||||
#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)]
|
||||
pub struct WherePredicate {
|
||||
pub enum WherePredicate {
|
||||
BoundPredicate(WhereBoundPredicate),
|
||||
EqPredicate(WhereEqPredicate)
|
||||
}
|
||||
|
||||
#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)]
|
||||
pub struct WhereBoundPredicate {
|
||||
pub id: NodeId,
|
||||
pub span: Span,
|
||||
pub ident: Ident,
|
||||
pub bounds: OwnedSlice<TyParamBound>,
|
||||
}
|
||||
|
||||
#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)]
|
||||
pub struct WhereEqPredicate {
|
||||
pub id: NodeId,
|
||||
pub span: Span,
|
||||
pub path: Path,
|
||||
pub ty: P<Ty>,
|
||||
}
|
||||
|
||||
/// The set of MetaItems that define the compilation environment of the crate,
|
||||
/// used to drive conditional compilation
|
||||
pub type CrateConfig = Vec<P<MetaItem>> ;
|
||||
@ -1118,6 +1147,16 @@ impl FloatTy {
|
||||
}
|
||||
}
|
||||
|
||||
// Bind a type to an associated type: `A=Foo`.
|
||||
#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)]
|
||||
pub struct TypeBinding {
|
||||
pub id: NodeId,
|
||||
pub ident: Ident,
|
||||
pub ty: P<Ty>,
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
|
||||
// NB PartialEq method appears below.
|
||||
#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)]
|
||||
pub struct Ty {
|
||||
|
@ -174,12 +174,28 @@ pub fn ident_to_path(s: Span, identifier: Ident) -> Path {
|
||||
parameters: ast::AngleBracketedParameters(ast::AngleBracketedParameterData {
|
||||
lifetimes: Vec::new(),
|
||||
types: OwnedSlice::empty(),
|
||||
bindings: OwnedSlice::empty(),
|
||||
})
|
||||
}
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
// If path is a single segment ident path, return that ident. Otherwise, return
|
||||
// None.
|
||||
pub fn path_to_ident(path: &Path) -> Option<Ident> {
|
||||
if path.segments.len() != 1 {
|
||||
return None;
|
||||
}
|
||||
|
||||
let segment = &path.segments[0];
|
||||
if !segment.parameters.is_empty() {
|
||||
return None;
|
||||
}
|
||||
|
||||
Some(segment.identifier)
|
||||
}
|
||||
|
||||
pub fn ident_to_pat(id: NodeId, s: Span, i: Ident) -> P<Pat> {
|
||||
P(Pat {
|
||||
id: id,
|
||||
|
@ -37,7 +37,8 @@ pub trait AstBuilder {
|
||||
global: bool,
|
||||
idents: Vec<ast::Ident> ,
|
||||
lifetimes: Vec<ast::Lifetime>,
|
||||
types: Vec<P<ast::Ty>> )
|
||||
types: Vec<P<ast::Ty>>,
|
||||
bindings: Vec<P<ast::TypeBinding>> )
|
||||
-> ast::Path;
|
||||
|
||||
// types
|
||||
@ -293,20 +294,21 @@ pub trait AstBuilder {
|
||||
|
||||
impl<'a> AstBuilder for ExtCtxt<'a> {
|
||||
fn path(&self, span: Span, strs: Vec<ast::Ident> ) -> ast::Path {
|
||||
self.path_all(span, false, strs, Vec::new(), Vec::new())
|
||||
self.path_all(span, false, strs, Vec::new(), Vec::new(), Vec::new())
|
||||
}
|
||||
fn path_ident(&self, span: Span, id: ast::Ident) -> ast::Path {
|
||||
self.path(span, vec!(id))
|
||||
}
|
||||
fn path_global(&self, span: Span, strs: Vec<ast::Ident> ) -> ast::Path {
|
||||
self.path_all(span, true, strs, Vec::new(), Vec::new())
|
||||
self.path_all(span, true, strs, Vec::new(), Vec::new(), Vec::new())
|
||||
}
|
||||
fn path_all(&self,
|
||||
sp: Span,
|
||||
global: bool,
|
||||
mut idents: Vec<ast::Ident> ,
|
||||
lifetimes: Vec<ast::Lifetime>,
|
||||
types: Vec<P<ast::Ty>> )
|
||||
types: Vec<P<ast::Ty>>,
|
||||
bindings: Vec<P<ast::TypeBinding>> )
|
||||
-> ast::Path {
|
||||
let last_identifier = idents.pop().unwrap();
|
||||
let mut segments: Vec<ast::PathSegment> = idents.into_iter()
|
||||
@ -321,6 +323,7 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
|
||||
parameters: ast::AngleBracketedParameters(ast::AngleBracketedParameterData {
|
||||
lifetimes: lifetimes,
|
||||
types: OwnedSlice::from_vec(types),
|
||||
bindings: OwnedSlice::from_vec(bindings),
|
||||
})
|
||||
});
|
||||
ast::Path {
|
||||
@ -391,7 +394,8 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
|
||||
self.ident_of("Option")
|
||||
),
|
||||
Vec::new(),
|
||||
vec!( ty )))
|
||||
vec!( ty ),
|
||||
Vec::new()))
|
||||
}
|
||||
|
||||
fn ty_field_imm(&self, span: Span, name: Ident, ty: P<ast::Ty>) -> ast::TypeField {
|
||||
|
@ -444,7 +444,7 @@ impl<'a> TraitDef<'a> {
|
||||
// Create the type of `self`.
|
||||
let self_type = cx.ty_path(
|
||||
cx.path_all(self.span, false, vec!( type_ident ), self_lifetimes,
|
||||
self_ty_params.into_vec()));
|
||||
self_ty_params.into_vec(), Vec::new()));
|
||||
|
||||
let attr = cx.attribute(
|
||||
self.span,
|
||||
|
@ -80,7 +80,7 @@ impl<'a> Path<'a> {
|
||||
let lt = mk_lifetimes(cx, span, &self.lifetime);
|
||||
let tys = self.params.iter().map(|t| t.to_ty(cx, span, self_ty, self_generics)).collect();
|
||||
|
||||
cx.path_all(span, self.global, idents, lt, tys)
|
||||
cx.path_all(span, self.global, idents, lt, tys, Vec::new())
|
||||
}
|
||||
}
|
||||
|
||||
@ -177,7 +177,7 @@ impl<'a> Ty<'a> {
|
||||
.collect();
|
||||
|
||||
cx.path_all(span, false, vec!(self_ty), lifetimes,
|
||||
self_params.into_vec())
|
||||
self_params.into_vec(), Vec::new())
|
||||
}
|
||||
Literal(ref p) => {
|
||||
p.to_path(cx, span, self_ty, self_generics)
|
||||
|
@ -88,6 +88,7 @@ fn rand_substructure(cx: &mut ExtCtxt, trait_span: Span, substr: &Substructure)
|
||||
true,
|
||||
rand_ident.clone(),
|
||||
Vec::new(),
|
||||
Vec::new(),
|
||||
Vec::new());
|
||||
let rand_name = cx.expr_path(rand_name);
|
||||
|
||||
|
@ -45,7 +45,8 @@ pub fn expand_option_env<'cx>(cx: &'cx mut ExtCtxt, sp: Span, tts: &[ast::TokenT
|
||||
Some(cx.lifetime(sp,
|
||||
cx.ident_of(
|
||||
"'static").name)),
|
||||
ast::MutImmutable))))
|
||||
ast::MutImmutable)),
|
||||
Vec::new()))
|
||||
}
|
||||
Some(s) => {
|
||||
cx.expr_call_global(sp,
|
||||
|
@ -530,6 +530,7 @@ impl<'a, 'b> Context<'a, 'b> {
|
||||
self.fmtsp,
|
||||
true, Context::rtpath(self.ecx, "Argument"),
|
||||
vec![static_lifetime],
|
||||
vec![],
|
||||
vec![]
|
||||
));
|
||||
lets.push(Context::item_static_array(self.ecx,
|
||||
|
@ -146,6 +146,10 @@ pub trait Folder {
|
||||
noop_fold_qpath(t, self)
|
||||
}
|
||||
|
||||
fn fold_ty_binding(&mut self, t: P<TypeBinding>) -> P<TypeBinding> {
|
||||
noop_fold_ty_binding(t, self)
|
||||
}
|
||||
|
||||
fn fold_mod(&mut self, m: Mod) -> Mod {
|
||||
noop_fold_mod(m, self)
|
||||
}
|
||||
@ -391,6 +395,15 @@ pub fn noop_fold_decl<T: Folder>(d: P<Decl>, fld: &mut T) -> SmallVector<P<Decl>
|
||||
})
|
||||
}
|
||||
|
||||
pub fn noop_fold_ty_binding<T: Folder>(b: P<TypeBinding>, fld: &mut T) -> P<TypeBinding> {
|
||||
b.map(|TypeBinding { id, ident, ty, span }| TypeBinding {
|
||||
id: fld.new_id(id),
|
||||
ident: ident,
|
||||
ty: fld.fold_ty(ty),
|
||||
span: fld.new_span(span),
|
||||
})
|
||||
}
|
||||
|
||||
pub fn noop_fold_ty<T: Folder>(t: P<Ty>, fld: &mut T) -> P<Ty> {
|
||||
t.map(|Ty {id, node, span}| Ty {
|
||||
id: fld.new_id(id),
|
||||
@ -533,9 +546,10 @@ pub fn noop_fold_angle_bracketed_parameter_data<T: Folder>(data: AngleBracketedP
|
||||
fld: &mut T)
|
||||
-> AngleBracketedParameterData
|
||||
{
|
||||
let AngleBracketedParameterData { lifetimes, types } = data;
|
||||
let AngleBracketedParameterData { lifetimes, types, bindings } = data;
|
||||
AngleBracketedParameterData { lifetimes: fld.fold_lifetimes(lifetimes),
|
||||
types: types.move_map(|ty| fld.fold_ty(ty)) }
|
||||
types: types.move_map(|ty| fld.fold_ty(ty)),
|
||||
bindings: bindings.move_map(|b| fld.fold_ty_binding(b)) }
|
||||
}
|
||||
|
||||
pub fn noop_fold_parenthesized_parameter_data<T: Folder>(data: ParenthesizedParameterData,
|
||||
@ -807,14 +821,32 @@ pub fn noop_fold_where_clause<T: Folder>(
|
||||
}
|
||||
|
||||
pub fn noop_fold_where_predicate<T: Folder>(
|
||||
WherePredicate {id, ident, bounds, span}: WherePredicate,
|
||||
pred: WherePredicate,
|
||||
fld: &mut T)
|
||||
-> WherePredicate {
|
||||
WherePredicate {
|
||||
id: fld.new_id(id),
|
||||
ident: fld.fold_ident(ident),
|
||||
bounds: bounds.move_map(|x| fld.fold_ty_param_bound(x)),
|
||||
span: fld.new_span(span)
|
||||
match pred {
|
||||
ast::WherePredicate::BoundPredicate(ast::WhereBoundPredicate{id,
|
||||
ident,
|
||||
bounds,
|
||||
span}) => {
|
||||
ast::WherePredicate::BoundPredicate(ast::WhereBoundPredicate {
|
||||
id: fld.new_id(id),
|
||||
ident: fld.fold_ident(ident),
|
||||
bounds: bounds.move_map(|x| fld.fold_ty_param_bound(x)),
|
||||
span: fld.new_span(span)
|
||||
})
|
||||
}
|
||||
ast::WherePredicate::EqPredicate(ast::WhereEqPredicate{id,
|
||||
path,
|
||||
ty,
|
||||
span}) => {
|
||||
ast::WherePredicate::EqPredicate(ast::WhereEqPredicate{
|
||||
id: fld.new_id(id),
|
||||
path: fld.fold_path(path),
|
||||
ty:fld.fold_ty(ty),
|
||||
span: fld.new_span(span)
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -53,7 +53,7 @@ use ast::{StructVariantKind, BiSub, StrStyle};
|
||||
use ast::{SelfExplicit, SelfRegion, SelfStatic, SelfValue};
|
||||
use ast::{Delimited, SequenceRepetition, TokenTree, TraitItem, TraitRef};
|
||||
use ast::{TtDelimited, TtSequence, TtToken};
|
||||
use ast::{TupleVariantKind, Ty, Ty_};
|
||||
use ast::{TupleVariantKind, Ty, Ty_, TypeBinding};
|
||||
use ast::{TypeField, TyFixedLengthVec, TyClosure, TyProc, TyBareFn};
|
||||
use ast::{TyTypeof, TyInfer, TypeMethod};
|
||||
use ast::{TyParam, TyParamBound, TyParen, TyPath, TyPolyTraitRef, TyPtr, TyQPath};
|
||||
@ -62,7 +62,7 @@ use ast::{TypeImplItem, TypeTraitItem, Typedef, UnboxedClosureKind};
|
||||
use ast::{UnnamedField, UnsafeBlock};
|
||||
use ast::{UnsafeFn, ViewItem, ViewItem_, ViewItemExternCrate, ViewItemUse};
|
||||
use ast::{ViewPath, ViewPathGlob, ViewPathList, ViewPathSimple};
|
||||
use ast::{Visibility, WhereClause, WherePredicate};
|
||||
use ast::{Visibility, WhereClause};
|
||||
use ast;
|
||||
use ast_util::{mod, as_prec, ident_to_path, operator_prec};
|
||||
use codemap::{mod, Span, BytePos, Spanned, spanned, mk_sp};
|
||||
@ -769,13 +769,10 @@ impl<'a> Parser<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Parse a sequence bracketed by '<' and '>', stopping
|
||||
/// before the '>'.
|
||||
pub fn parse_seq_to_before_gt<T>(
|
||||
&mut self,
|
||||
sep: Option<token::Token>,
|
||||
f: |&mut Parser| -> T)
|
||||
-> OwnedSlice<T> {
|
||||
pub fn parse_seq_to_before_gt_or_return<T>(&mut self,
|
||||
sep: Option<token::Token>,
|
||||
f: |&mut Parser| -> Option<T>)
|
||||
-> (OwnedSlice<T>, bool) {
|
||||
let mut v = Vec::new();
|
||||
// This loop works by alternating back and forth between parsing types
|
||||
// and commas. For example, given a string `A, B,>`, the parser would
|
||||
@ -792,24 +789,48 @@ impl<'a> Parser<'a> {
|
||||
}
|
||||
|
||||
if i % 2 == 0 {
|
||||
v.push(f(self));
|
||||
match f(self) {
|
||||
Some(result) => v.push(result),
|
||||
None => return (OwnedSlice::from_vec(v), true)
|
||||
}
|
||||
} else {
|
||||
sep.as_ref().map(|t| self.expect(t));
|
||||
}
|
||||
}
|
||||
return OwnedSlice::from_vec(v);
|
||||
return (OwnedSlice::from_vec(v), false);
|
||||
}
|
||||
|
||||
pub fn parse_seq_to_gt<T>(
|
||||
&mut self,
|
||||
sep: Option<token::Token>,
|
||||
f: |&mut Parser| -> T)
|
||||
-> OwnedSlice<T> {
|
||||
/// Parse a sequence bracketed by '<' and '>', stopping
|
||||
/// before the '>'.
|
||||
pub fn parse_seq_to_before_gt<T>(&mut self,
|
||||
sep: Option<token::Token>,
|
||||
f: |&mut Parser| -> T)
|
||||
-> OwnedSlice<T> {
|
||||
let (result, returned) = self.parse_seq_to_before_gt_or_return(sep, |p| Some(f(p)));
|
||||
assert!(!returned);
|
||||
return result;
|
||||
}
|
||||
|
||||
pub fn parse_seq_to_gt<T>(&mut self,
|
||||
sep: Option<token::Token>,
|
||||
f: |&mut Parser| -> T)
|
||||
-> OwnedSlice<T> {
|
||||
let v = self.parse_seq_to_before_gt(sep, f);
|
||||
self.expect_gt();
|
||||
return v;
|
||||
}
|
||||
|
||||
pub fn parse_seq_to_gt_or_return<T>(&mut self,
|
||||
sep: Option<token::Token>,
|
||||
f: |&mut Parser| -> Option<T>)
|
||||
-> (OwnedSlice<T>, bool) {
|
||||
let (v, returned) = self.parse_seq_to_before_gt_or_return(sep, f);
|
||||
if !returned {
|
||||
self.expect_gt();
|
||||
}
|
||||
return (v, returned);
|
||||
}
|
||||
|
||||
/// Parse a sequence, including the closing delimiter. The function
|
||||
/// f must consume tokens until reaching the next separator or
|
||||
/// closing bracket.
|
||||
@ -1842,11 +1863,12 @@ impl<'a> Parser<'a> {
|
||||
|
||||
// Parse types, optionally.
|
||||
let parameters = if self.eat_lt(false) {
|
||||
let (lifetimes, types) = self.parse_generic_values_after_lt();
|
||||
let (lifetimes, types, bindings) = self.parse_generic_values_after_lt();
|
||||
|
||||
ast::AngleBracketedParameters(ast::AngleBracketedParameterData {
|
||||
lifetimes: lifetimes,
|
||||
types: OwnedSlice::from_vec(types),
|
||||
bindings: OwnedSlice::from_vec(bindings),
|
||||
})
|
||||
} else if self.eat(&token::OpenDelim(token::Paren)) {
|
||||
let inputs = self.parse_seq_to_end(
|
||||
@ -1894,6 +1916,7 @@ impl<'a> Parser<'a> {
|
||||
parameters: ast::AngleBracketedParameters(ast::AngleBracketedParameterData {
|
||||
lifetimes: Vec::new(),
|
||||
types: OwnedSlice::empty(),
|
||||
bindings: OwnedSlice::empty(),
|
||||
})
|
||||
});
|
||||
return segments;
|
||||
@ -1902,12 +1925,13 @@ impl<'a> Parser<'a> {
|
||||
// Check for a type segment.
|
||||
if self.eat_lt(false) {
|
||||
// Consumed `a::b::<`, go look for types
|
||||
let (lifetimes, types) = self.parse_generic_values_after_lt();
|
||||
let (lifetimes, types, bindings) = self.parse_generic_values_after_lt();
|
||||
segments.push(ast::PathSegment {
|
||||
identifier: identifier,
|
||||
parameters: ast::AngleBracketedParameters(ast::AngleBracketedParameterData {
|
||||
lifetimes: lifetimes,
|
||||
types: OwnedSlice::from_vec(types),
|
||||
bindings: OwnedSlice::from_vec(bindings),
|
||||
}),
|
||||
});
|
||||
|
||||
@ -2435,13 +2459,18 @@ impl<'a> Parser<'a> {
|
||||
let dot = self.last_span.hi;
|
||||
hi = self.span.hi;
|
||||
self.bump();
|
||||
let (_, tys) = if self.eat(&token::ModSep) {
|
||||
let (_, tys, bindings) = if self.eat(&token::ModSep) {
|
||||
self.expect_lt();
|
||||
self.parse_generic_values_after_lt()
|
||||
} else {
|
||||
(Vec::new(), Vec::new())
|
||||
(Vec::new(), Vec::new(), Vec::new())
|
||||
};
|
||||
|
||||
if bindings.len() > 0 {
|
||||
let last_span = self.last_span;
|
||||
self.span_err(last_span, "type bindings are only permitted on trait paths");
|
||||
}
|
||||
|
||||
// expr.f() method call
|
||||
match self.token {
|
||||
token::OpenDelim(token::Paren) => {
|
||||
@ -4041,16 +4070,51 @@ impl<'a> Parser<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_generic_values_after_lt(&mut self) -> (Vec<ast::Lifetime>, Vec<P<Ty>> ) {
|
||||
fn parse_generic_values_after_lt(&mut self)
|
||||
-> (Vec<ast::Lifetime>, Vec<P<Ty>>, Vec<P<TypeBinding>>) {
|
||||
let lifetimes = self.parse_lifetimes(token::Comma);
|
||||
let result = self.parse_seq_to_gt(
|
||||
|
||||
// First parse types.
|
||||
let (types, returned) = self.parse_seq_to_gt_or_return(
|
||||
Some(token::Comma),
|
||||
|p| {
|
||||
p.forbid_lifetime();
|
||||
p.parse_ty_sum()
|
||||
if p.look_ahead(1, |t| t == &token::Eq) {
|
||||
None
|
||||
} else {
|
||||
Some(p.parse_ty_sum())
|
||||
}
|
||||
}
|
||||
);
|
||||
(lifetimes, result.into_vec())
|
||||
|
||||
// If we found the `>`, don't continue.
|
||||
if !returned {
|
||||
return (lifetimes, types.into_vec(), Vec::new());
|
||||
}
|
||||
|
||||
// Then parse type bindings.
|
||||
let bindings = self.parse_seq_to_gt(
|
||||
Some(token::Comma),
|
||||
|p| {
|
||||
p.forbid_lifetime();
|
||||
let lo = p.span.lo;
|
||||
let ident = p.parse_ident();
|
||||
let found_eq = p.eat(&token::Eq);
|
||||
if !found_eq {
|
||||
let span = p.span;
|
||||
p.span_warn(span, "whoops, no =?");
|
||||
}
|
||||
let ty = p.parse_ty();
|
||||
let hi = p.span.hi;
|
||||
let span = mk_sp(lo, hi);
|
||||
return P(TypeBinding{id: ast::DUMMY_NODE_ID,
|
||||
ident: ident,
|
||||
ty: ty,
|
||||
span: span,
|
||||
});
|
||||
}
|
||||
);
|
||||
(lifetimes, types.into_vec(), bindings.into_vec())
|
||||
}
|
||||
|
||||
fn forbid_lifetime(&mut self) {
|
||||
@ -4070,30 +4134,59 @@ impl<'a> Parser<'a> {
|
||||
let mut parsed_something = false;
|
||||
loop {
|
||||
let lo = self.span.lo;
|
||||
let ident = match self.token {
|
||||
token::Ident(..) => self.parse_ident(),
|
||||
let path = match self.token {
|
||||
token::Ident(..) => self.parse_path(NoTypesAllowed),
|
||||
_ => break,
|
||||
};
|
||||
self.expect(&token::Colon);
|
||||
|
||||
let bounds = self.parse_ty_param_bounds();
|
||||
let hi = self.span.hi;
|
||||
let span = mk_sp(lo, hi);
|
||||
if self.eat(&token::Colon) {
|
||||
let bounds = self.parse_ty_param_bounds();
|
||||
let hi = self.span.hi;
|
||||
let span = mk_sp(lo, hi);
|
||||
|
||||
if bounds.len() == 0 {
|
||||
self.span_err(span,
|
||||
"each predicate in a `where` clause must have \
|
||||
at least one bound in it");
|
||||
if bounds.len() == 0 {
|
||||
self.span_err(span,
|
||||
"each predicate in a `where` clause must have \
|
||||
at least one bound in it");
|
||||
}
|
||||
|
||||
let ident = match ast_util::path_to_ident(&path) {
|
||||
Some(ident) => ident,
|
||||
None => {
|
||||
self.span_err(path.span, "expected a single identifier \
|
||||
in bound where clause");
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
||||
generics.where_clause.predicates.push(
|
||||
ast::WherePredicate::BoundPredicate(ast::WhereBoundPredicate {
|
||||
id: ast::DUMMY_NODE_ID,
|
||||
span: span,
|
||||
ident: ident,
|
||||
bounds: bounds,
|
||||
}));
|
||||
parsed_something = true;
|
||||
} else if self.eat(&token::Eq) {
|
||||
let ty = self.parse_ty();
|
||||
let hi = self.span.hi;
|
||||
let span = mk_sp(lo, hi);
|
||||
generics.where_clause.predicates.push(
|
||||
ast::WherePredicate::EqPredicate(ast::WhereEqPredicate {
|
||||
id: ast::DUMMY_NODE_ID,
|
||||
span: span,
|
||||
path: path,
|
||||
ty: ty,
|
||||
}));
|
||||
parsed_something = true;
|
||||
// FIXME(#18433)
|
||||
self.span_err(span, "equality constraints are not yet supported in where clauses");
|
||||
} else {
|
||||
let last_span = self.last_span;
|
||||
self.span_err(last_span,
|
||||
"unexpected token in `where` clause");
|
||||
}
|
||||
|
||||
generics.where_clause.predicates.push(ast::WherePredicate {
|
||||
id: ast::DUMMY_NODE_ID,
|
||||
span: span,
|
||||
ident: ident,
|
||||
bounds: bounds,
|
||||
});
|
||||
parsed_something = true;
|
||||
|
||||
if !self.eat(&token::Comma) {
|
||||
break
|
||||
}
|
||||
|
@ -1976,6 +1976,18 @@ impl<'a> State<'a> {
|
||||
Inconsistent,
|
||||
data.types.as_slice(),
|
||||
|s, ty| s.print_type(&**ty)));
|
||||
comma = true;
|
||||
}
|
||||
|
||||
for binding in data.bindings.iter() {
|
||||
if comma {
|
||||
try!(self.word_space(","))
|
||||
}
|
||||
try!(self.print_ident(binding.ident));
|
||||
try!(space(&mut self.s));
|
||||
try!(self.word_space("="));
|
||||
try!(self.print_type(&*binding.ty));
|
||||
comma = true;
|
||||
}
|
||||
|
||||
try!(word(&mut self.s, ">"))
|
||||
@ -2437,8 +2449,20 @@ impl<'a> State<'a> {
|
||||
try!(self.word_space(","));
|
||||
}
|
||||
|
||||
try!(self.print_ident(predicate.ident));
|
||||
try!(self.print_bounds(":", predicate.bounds.as_slice()));
|
||||
match predicate {
|
||||
&ast::WherePredicate::BoundPredicate(ast::WhereBoundPredicate{ident,
|
||||
ref bounds,
|
||||
..}) => {
|
||||
try!(self.print_ident(ident));
|
||||
try!(self.print_bounds(":", bounds.as_slice()));
|
||||
}
|
||||
&ast::WherePredicate::EqPredicate(ast::WhereEqPredicate{ref path, ref ty, ..}) => {
|
||||
try!(self.print_path(path, false));
|
||||
try!(space(&mut self.s));
|
||||
try!(self.word_space("="));
|
||||
try!(self.print_type(&**ty));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
|
@ -573,8 +573,22 @@ pub fn walk_generics<'v, V: Visitor<'v>>(visitor: &mut V, generics: &'v Generics
|
||||
}
|
||||
walk_lifetime_decls_helper(visitor, &generics.lifetimes);
|
||||
for predicate in generics.where_clause.predicates.iter() {
|
||||
visitor.visit_ident(predicate.span, predicate.ident);
|
||||
walk_ty_param_bounds_helper(visitor, &predicate.bounds);
|
||||
match predicate {
|
||||
&ast::WherePredicate::BoundPredicate(ast::WhereBoundPredicate{span,
|
||||
ident,
|
||||
ref bounds,
|
||||
..}) => {
|
||||
visitor.visit_ident(span, ident);
|
||||
walk_ty_param_bounds_helper(visitor, bounds);
|
||||
}
|
||||
&ast::WherePredicate::EqPredicate(ast::WhereEqPredicate{id,
|
||||
ref path,
|
||||
ref ty,
|
||||
..}) => {
|
||||
visitor.visit_path(path, id);
|
||||
visitor.visit_ty(&**ty);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -19,6 +19,6 @@ extern crate macro_crate_test;
|
||||
|
||||
fn main() {
|
||||
macro_crate_test::foo();
|
||||
//~^ ERROR failed to resolve. Use of undeclared module `macro_crate_test`
|
||||
//~^ ERROR failed to resolve. Use of undeclared type or module `macro_crate_test`
|
||||
//~^^ ERROR unresolved name `macro_crate_test::foo`
|
||||
}
|
||||
|
27
src/test/compile-fail/assoc-eq-1.rs
Normal file
27
src/test/compile-fail/assoc-eq-1.rs
Normal file
@ -0,0 +1,27 @@
|
||||
// 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.
|
||||
|
||||
// Test equality constraints on associated types. Check that unsupported syntax
|
||||
// does not ICE.
|
||||
|
||||
#![feature(associated_types)]
|
||||
|
||||
pub trait Foo {
|
||||
type A;
|
||||
fn boo(&self) -> <Self as Foo>::A;
|
||||
}
|
||||
|
||||
fn foo2<I: Foo>(x: I) {
|
||||
let _: A = x.boo(); //~ERROR use of undeclared
|
||||
let _: I::A = x.boo(); //~ERROR failed to resolve
|
||||
//~^ERROR use of undeclared type name `I::A`
|
||||
}
|
||||
|
||||
pub fn main() {}
|
30
src/test/compile-fail/assoc-eq-2.rs
Normal file
30
src/test/compile-fail/assoc-eq-2.rs
Normal file
@ -0,0 +1,30 @@
|
||||
// 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.
|
||||
|
||||
// Test equality constraints on associated types. Check we get an error when an
|
||||
// equality constraint is used in a qualified path.
|
||||
|
||||
#![feature(associated_types)]
|
||||
|
||||
pub trait Foo {
|
||||
type A;
|
||||
fn boo(&self) -> <Self as Foo>::A;
|
||||
}
|
||||
|
||||
struct Bar;
|
||||
|
||||
impl Foo for int {
|
||||
type A = uint;
|
||||
fn boo(&self) -> uint { 42 }
|
||||
}
|
||||
|
||||
fn baz<I: Foo>(x: &<I as Foo<A=Bar>>::A) {} //~ERROR equality constraints are not allowed in this
|
||||
|
||||
pub fn main() {}
|
48
src/test/compile-fail/assoc-eq-3.rs
Normal file
48
src/test/compile-fail/assoc-eq-3.rs
Normal file
@ -0,0 +1,48 @@
|
||||
// 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.
|
||||
|
||||
// Test equality constraints on associated types. Check we get type errors
|
||||
// where we should.
|
||||
|
||||
#![feature(associated_types)]
|
||||
|
||||
pub trait Foo {
|
||||
type A;
|
||||
fn boo(&self) -> <Self as Foo>::A;
|
||||
}
|
||||
|
||||
struct Bar;
|
||||
|
||||
impl Foo for int {
|
||||
type A = uint;
|
||||
fn boo(&self) -> uint {
|
||||
42
|
||||
}
|
||||
}
|
||||
|
||||
fn foo1<I: Foo<A=Bar>>(x: I) {
|
||||
let _: Bar = x.boo();
|
||||
}
|
||||
|
||||
fn foo2<I: Foo>(x: I) {
|
||||
let _: Bar = x.boo(); //~ERROR mismatched types
|
||||
}
|
||||
|
||||
|
||||
pub fn baz(x: &Foo<A=Bar>) {
|
||||
let _: Bar = x.boo();
|
||||
}
|
||||
|
||||
|
||||
pub fn main() {
|
||||
let a = 42i;
|
||||
foo1(a); //~ERROR the trait `Foo` is not implemented for the type `int`
|
||||
baz(&a); //~ERROR the trait `Foo` is not implemented for the type `int`
|
||||
}
|
28
src/test/compile-fail/assoc-eq-expr-path.rs
Normal file
28
src/test/compile-fail/assoc-eq-expr-path.rs
Normal file
@ -0,0 +1,28 @@
|
||||
// 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.
|
||||
|
||||
// Check that an associated type cannot be bound in an expression path.
|
||||
|
||||
#![feature(associated_types)]
|
||||
|
||||
trait Foo {
|
||||
type A;
|
||||
fn bar() -> int;
|
||||
}
|
||||
|
||||
impl Foo for int {
|
||||
type A = uint;
|
||||
fn bar() -> int { 42 }
|
||||
}
|
||||
|
||||
pub fn main() {
|
||||
let x: int = Foo::<A=uint>::bar();
|
||||
//~^ERROR unexpected binding of associated item in expression path
|
||||
}
|
@ -18,17 +18,17 @@ trait Bar {
|
||||
|
||||
struct Foo<'a> {
|
||||
a: &'a Bar+'a,
|
||||
//~^ ERROR E0171
|
||||
//~^ ERROR E0178
|
||||
//~^^ NOTE perhaps you meant `&'a (Bar + 'a)`?
|
||||
|
||||
b: &'a mut Bar+'a,
|
||||
//~^ ERROR E0171
|
||||
//~^ ERROR E0178
|
||||
//~^^ NOTE perhaps you meant `&'a mut (Bar + 'a)`?
|
||||
|
||||
c: Box<Bar+'a>, // OK, no paren needed in this context
|
||||
|
||||
d: fn() -> Bar+'a,
|
||||
//~^ ERROR E0171
|
||||
//~^ ERROR E0178
|
||||
//~^^ NOTE perhaps you forgot parentheses
|
||||
//~^^^ WARN deprecated syntax
|
||||
}
|
||||
|
@ -31,6 +31,6 @@ impl ToString_ for Point {
|
||||
fn main() {
|
||||
let p = Point::new(0.0, 0.0);
|
||||
//~^ ERROR unresolved name `Point::new`
|
||||
//~^^ ERROR failed to resolve. Use of undeclared module `Point`
|
||||
//~^^ ERROR failed to resolve. Use of undeclared type or module `Point`
|
||||
println!("{}", p.to_string());
|
||||
}
|
||||
|
@ -25,7 +25,7 @@ test!(b,
|
||||
#[qux]
|
||||
fn main() {
|
||||
a::bar();
|
||||
//~^ ERROR failed to resolve. Use of undeclared module `a`
|
||||
//~^ ERROR failed to resolve. Use of undeclared type or module `a`
|
||||
//~^^ ERROR unresolved name `a::bar`
|
||||
b::bar();
|
||||
}
|
||||
|
55
src/test/run-pass/assoc-eq.rs
Normal file
55
src/test/run-pass/assoc-eq.rs
Normal file
@ -0,0 +1,55 @@
|
||||
// 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.
|
||||
|
||||
// Test equality constraints on associated types.
|
||||
|
||||
#![feature(associated_types)]
|
||||
|
||||
pub trait Foo {
|
||||
type A;
|
||||
fn boo(&self) -> <Self as Foo>::A;
|
||||
}
|
||||
|
||||
struct Bar;
|
||||
|
||||
impl Foo for int {
|
||||
type A = uint;
|
||||
fn boo(&self) -> uint { 42 }
|
||||
}
|
||||
impl Foo for Bar {
|
||||
type A = int;
|
||||
fn boo(&self) -> int { 43 }
|
||||
}
|
||||
impl Foo for char {
|
||||
type A = Bar;
|
||||
fn boo(&self) -> Bar { Bar }
|
||||
}
|
||||
|
||||
fn foo1<I: Foo<A=Bar>>(x: I) -> Bar {
|
||||
x.boo()
|
||||
}
|
||||
fn foo2<I: Foo>(x: I) -> <I as Foo>::A {
|
||||
x.boo()
|
||||
}
|
||||
fn baz(x: &Foo<A=Bar>) -> Bar {
|
||||
x.boo()
|
||||
}
|
||||
|
||||
pub fn main() {
|
||||
let a = 42i;
|
||||
assert!(foo2(a) == 42u);
|
||||
|
||||
let a = Bar;
|
||||
assert!(foo2(a) == 43i);
|
||||
|
||||
let a = 'a';
|
||||
foo1(a);
|
||||
baz(&a);
|
||||
}
|
Loading…
Reference in New Issue
Block a user