Skip to content

Commit 397dda8

Browse files
committed
Add support for equality constraints on associated types
1 parent da83ad8 commit 397dda8

File tree

29 files changed

+790
-163
lines changed

29 files changed

+790
-163
lines changed

src/librustc/diagnostics.rs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -148,5 +148,12 @@ register_diagnostics!(
148148
E0169,
149149
E0170,
150150
E0171,
151-
E0172
151+
E0172,
152+
E0173,
153+
E0174,
154+
E0175,
155+
E0176,
156+
E0177,
157+
E0178,
158+
E0179
152159
)

src/librustc/middle/infer/error_reporting.rs

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1405,10 +1405,22 @@ impl<'a, 'tcx> Rebuilder<'a, 'tcx> {
14051405
let new_types = data.types.map(|t| {
14061406
self.rebuild_arg_ty_or_output(&**t, lifetime, anon_nums, region_names)
14071407
});
1408+
let new_bindings = data.bindings.map(|b| {
1409+
P(ast::TypeBinding {
1410+
id: b.id,
1411+
ident: b.ident,
1412+
ty: self.rebuild_arg_ty_or_output(&*b.ty,
1413+
lifetime,
1414+
anon_nums,
1415+
region_names),
1416+
span: b.span
1417+
})
1418+
});
14081419
ast::AngleBracketedParameters(ast::AngleBracketedParameterData {
14091420
lifetimes: new_lts,
1410-
types: new_types
1411-
})
1421+
types: new_types,
1422+
bindings: new_bindings,
1423+
})
14121424
}
14131425
};
14141426
let new_seg = ast::PathSegment {

src/librustc/middle/privacy.rs

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1453,8 +1453,15 @@ impl<'a, 'tcx, 'v> Visitor<'v> for VisiblePrivateTypesVisitor<'a, 'tcx> {
14531453
}
14541454
}
14551455
for predicate in generics.where_clause.predicates.iter() {
1456-
for bound in predicate.bounds.iter() {
1457-
self.check_ty_param_bound(predicate.span, bound)
1456+
match predicate {
1457+
&ast::BoundPredicate(ref bound_pred) => {
1458+
for bound in bound_pred.bounds.iter() {
1459+
self.check_ty_param_bound(bound_pred.span, bound)
1460+
}
1461+
}
1462+
&ast::EqPredicate(ref eq_pred) => {
1463+
self.visit_ty(&*eq_pred.ty);
1464+
}
14581465
}
14591466
}
14601467
}

src/librustc/middle/resolve.rs

Lines changed: 41 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -3407,9 +3407,8 @@ impl<'a> Resolver<'a> {
34073407
// This is not a crate-relative path. We resolve the
34083408
// first component of the path in the current lexical
34093409
// scope and then proceed to resolve below that.
3410-
match self.resolve_module_in_lexical_scope(
3411-
module_,
3412-
module_path[0]) {
3410+
match self.resolve_module_in_lexical_scope(module_,
3411+
module_path[0]) {
34133412
Failed(err) => return Failed(err),
34143413
Indeterminate => {
34153414
debug!("(resolving module path for import) \
@@ -4590,25 +4589,42 @@ impl<'a> Resolver<'a> {
45904589

45914590
fn resolve_where_clause(&mut self, where_clause: &ast::WhereClause) {
45924591
for predicate in where_clause.predicates.iter() {
4593-
match self.resolve_identifier(predicate.ident,
4594-
TypeNS,
4595-
true,
4596-
predicate.span) {
4597-
Some((def @ DefTyParam(_, _, _), last_private)) => {
4598-
self.record_def(predicate.id, (def, last_private));
4599-
}
4600-
_ => {
4601-
self.resolve_error(
4602-
predicate.span,
4603-
format!("undeclared type parameter `{}`",
4604-
token::get_ident(
4605-
predicate.ident)).as_slice());
4592+
match predicate {
4593+
&ast::BoundPredicate(ref bound_pred) => {
4594+
match self.resolve_identifier(bound_pred.ident,
4595+
TypeNS,
4596+
true,
4597+
bound_pred.span) {
4598+
Some((def @ DefTyParam(..), last_private)) => {
4599+
self.record_def(bound_pred.id, (def, last_private));
4600+
}
4601+
_ => {
4602+
self.resolve_error(
4603+
bound_pred.span,
4604+
format!("undeclared type parameter `{}`",
4605+
token::get_ident(
4606+
bound_pred.ident)).as_slice());
4607+
}
4608+
}
4609+
4610+
for bound in bound_pred.bounds.iter() {
4611+
self.resolve_type_parameter_bound(bound_pred.id, bound,
4612+
TraitBoundingTypeParameter);
4613+
}
46064614
}
4607-
}
4615+
&ast::EqPredicate(ref eq_pred) => {
4616+
match self.resolve_path(eq_pred.id, &eq_pred.path, TypeNS, true) {
4617+
Some((def @ DefTyParam(..), last_private)) => {
4618+
self.record_def(eq_pred.id, (def, last_private));
4619+
}
4620+
_ => {
4621+
self.resolve_error(eq_pred.path.span,
4622+
"undeclared associated type");
4623+
}
4624+
}
46084625

4609-
for bound in predicate.bounds.iter() {
4610-
self.resolve_type_parameter_bound(predicate.id, bound,
4611-
TraitBoundingTypeParameter);
4626+
self.resolve_type(&*eq_pred.ty);
4627+
}
46124628
}
46134629
}
46144630
}
@@ -5269,15 +5285,19 @@ impl<'a> Resolver<'a> {
52695285
path: &Path,
52705286
namespace: Namespace,
52715287
check_ribs: bool) -> Option<(Def, LastPrivate)> {
5272-
// First, resolve the types.
5288+
// First, resolve the types and associated type bindings.
52735289
for ty in path.segments.iter().flat_map(|s| s.parameters.types().into_iter()) {
52745290
self.resolve_type(&**ty);
52755291
}
5292+
for binding in path.segments.iter().flat_map(|s| s.parameters.bindings().into_iter()) {
5293+
self.resolve_type(&*binding.ty);
5294+
}
52765295

52775296
if path.global {
52785297
return self.resolve_crate_relative_path(path, namespace);
52795298
}
52805299

5300+
// Try to find a path to an item in a module.
52815301
let unqualified_def =
52825302
self.resolve_identifier(path.segments
52835303
.last().unwrap()

src/librustc/middle/resolve_lifetime.rs

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -210,8 +210,16 @@ impl<'a, 'v> Visitor<'v> for LifetimeContext<'a> {
210210
}
211211
}
212212
for predicate in generics.where_clause.predicates.iter() {
213-
self.visit_ident(predicate.span, predicate.ident);
214-
visit::walk_ty_param_bounds_helper(self, &predicate.bounds);
213+
match predicate {
214+
&ast::BoundPredicate(ast::WhereBoundPredicate{ident, ref bounds, span, ..}) => {
215+
self.visit_ident(span, ident);
216+
visit::walk_ty_param_bounds_helper(self, bounds);
217+
}
218+
&ast::EqPredicate(ast::WhereEqPredicate{id, ref path, ref ty, ..}) => {
219+
self.visit_path(path, id);
220+
self.visit_ty(&**ty);
221+
}
222+
}
215223
}
216224
}
217225

@@ -486,7 +494,12 @@ fn early_bound_lifetime_names(generics: &ast::Generics) -> Vec<ast::Name> {
486494
visit::walk_ty_param_bounds_helper(&mut collector, &ty_param.bounds);
487495
}
488496
for predicate in generics.where_clause.predicates.iter() {
489-
visit::walk_ty_param_bounds_helper(&mut collector, &predicate.bounds);
497+
match predicate {
498+
&ast::BoundPredicate(ast::WhereBoundPredicate{ref bounds, ..}) => {
499+
visit::walk_ty_param_bounds_helper(&mut collector, bounds);
500+
}
501+
_ => {}
502+
}
490503
}
491504
}
492505

src/librustc/middle/subst.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,13 @@ pub fn self_ty(&self) -> Option<Ty<'tcx>> {
123123
s
124124
}
125125

126+
pub fn with_assoc_tys(&self, assoc_tys: Vec<Ty<'tcx>>) -> Substs<'tcx> {
127+
assert!(self.types.is_empty_in(AssocSpace));
128+
let mut s = (*self).clone();
129+
s.types.replace(AssocSpace, assoc_tys);
130+
s
131+
}
132+
126133
pub fn erase_regions(self) -> Substs<'tcx> {
127134
let Substs { types, regions: _ } = self;
128135
Substs { types: types, regions: ErasedRegions }

src/librustc/middle/traits/util.rs

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
// except according to those terms.
1111

1212
use middle::subst;
13-
use middle::subst::{ParamSpace, Substs, VecPerParamSpace};
13+
use middle::subst::{ParamSpace, Substs, VecPerParamSpace, Subst};
1414
use middle::infer::InferCtxt;
1515
use middle::ty::{mod, Ty};
1616
use std::collections::HashSet;
@@ -149,7 +149,18 @@ pub fn fresh_substs_for_impl<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
149149
{
150150
let tcx = infcx.tcx;
151151
let impl_generics = ty::lookup_item_type(tcx, impl_def_id).generics;
152-
infcx.fresh_substs_for_generics(span, &impl_generics)
152+
let input_substs = infcx.fresh_substs_for_generics(span, &impl_generics);
153+
154+
// Add substs for the associated types bound in the impl.
155+
let ref items = tcx.impl_items.borrow()[impl_def_id];
156+
let mut assoc_tys = Vec::new();
157+
for item in items.iter() {
158+
if let &ty::ImplOrTraitItemId::TypeTraitItemId(id) = item {
159+
assoc_tys.push(tcx.tcache.borrow()[id].ty.subst(tcx, &input_substs));
160+
}
161+
}
162+
163+
input_substs.with_assoc_tys(assoc_tys)
153164
}
154165

155166
impl<'tcx, N> fmt::Show for VtableImplData<'tcx, N> {

0 commit comments

Comments
 (0)