Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for equality constraints on associated types #19391

Merged
merged 3 commits into from
Dec 12, 2014
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion src/librustc/diagnostics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -148,5 +148,9 @@ register_diagnostics!(
E0169,
E0170,
E0171,
E0172
E0172,
E0173,
E0174,
E0177,
E0178
)
2 changes: 1 addition & 1 deletion src/librustc/metadata/decoder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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),
Expand Down
16 changes: 14 additions & 2 deletions src/librustc/middle/infer/error_reporting.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
11 changes: 9 additions & 2 deletions src/librustc/middle/privacy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
}
}
}
Expand Down
136 changes: 80 additions & 56 deletions src/librustc/middle/resolve.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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,
Expand All @@ -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)
Expand Down Expand Up @@ -414,6 +415,7 @@ enum DuplicateCheckingMode {
impl Copy for DuplicateCheckingMode {}

/// One local scope.
#[deriving(Show)]
struct Rib {
bindings: HashMap<Name, DefLike>,
kind: RibKind,
Expand Down Expand Up @@ -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)),
Expand Down Expand Up @@ -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,
});
}
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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)),
Expand All @@ -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;

Expand Down Expand Up @@ -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);

Expand Down Expand Up @@ -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),
Expand All @@ -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) \
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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 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");
}
}

for bound in predicate.bounds.iter() {
self.resolve_type_parameter_bound(predicate.id, bound,
TraitBoundingTypeParameter);
self.resolve_type(&*eq_pred.ty);
}
}
}
}
Expand Down Expand Up @@ -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()
Expand Down Expand Up @@ -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)));
}
Expand All @@ -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);

Expand Down Expand Up @@ -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<_>>();
Expand All @@ -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)
}
};
Expand Down Expand Up @@ -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 => {
Expand Down
25 changes: 22 additions & 3 deletions src/librustc/middle/resolve_lifetime.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
}
}
}

Expand Down Expand Up @@ -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!()
}
}
}

Expand Down
Loading