Skip to content

Commit

Permalink
Add support for equality constraints on associated types
Browse files Browse the repository at this point in the history
  • Loading branch information
nrc committed Dec 12, 2014
1 parent da83ad8 commit 397dda8
Show file tree
Hide file tree
Showing 29 changed files with 790 additions and 163 deletions.
9 changes: 8 additions & 1 deletion src/librustc/diagnostics.rs
Expand Up @@ -148,5 +148,12 @@ register_diagnostics!(
E0169,
E0170,
E0171,
E0172
E0172,
E0173,
E0174,
E0175,
E0176,
E0177,
E0178,
E0179
)
16 changes: 14 additions & 2 deletions src/librustc/middle/infer/error_reporting.rs
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
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::BoundPredicate(ref bound_pred) => {
for bound in bound_pred.bounds.iter() {
self.check_ty_param_bound(bound_pred.span, bound)
}
}
&ast::EqPredicate(ref eq_pred) => {
self.visit_ty(&*eq_pred.ty);
}
}
}
}
Expand Down
62 changes: 41 additions & 21 deletions src/librustc/middle/resolve.rs
Expand Up @@ -3407,9 +3407,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 @@ -4590,25 +4589,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::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::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 +5285,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
19 changes: 16 additions & 3 deletions src/librustc/middle/resolve_lifetime.rs
Expand Up @@ -210,8 +210,16 @@ 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::BoundPredicate(ast::WhereBoundPredicate{ident, ref bounds, span, ..}) => {
self.visit_ident(span, ident);
visit::walk_ty_param_bounds_helper(self, bounds);
}
&ast::EqPredicate(ast::WhereEqPredicate{id, ref path, ref ty, ..}) => {
self.visit_path(path, id);
self.visit_ty(&**ty);
}
}
}
}

Expand Down Expand Up @@ -486,7 +494,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::BoundPredicate(ast::WhereBoundPredicate{ref bounds, ..}) => {
visit::walk_ty_param_bounds_helper(&mut collector, bounds);
}
_ => {}
}
}
}

Expand Down
7 changes: 7 additions & 0 deletions src/librustc/middle/subst.rs
Expand Up @@ -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 }
Expand Down
15 changes: 13 additions & 2 deletions src/librustc/middle/traits/util.rs
Expand Up @@ -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;
Expand Down Expand Up @@ -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> {
Expand Down

0 comments on commit 397dda8

Please sign in to comment.