Skip to content

Commit 534e6f4

Browse files
committed
Add support for equality constraints on associated types
1 parent 738d980 commit 534e6f4

30 files changed

+792
-165
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/lint/context.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -567,13 +567,13 @@ impl<'a, 'tcx> AstConv<'tcx> for Context<'a, 'tcx>{
567567
_: Option<Ty<'tcx>>,
568568
trait_id: ast::DefId,
569569
associated_type_id: ast::DefId)
570-
-> Ty<'tcx> {
570+
-> Option<Ty<'tcx>> {
571571
// FIXME(pcwalton): This is wrong.
572572
let trait_def = self.get_trait_def(trait_id);
573573
let index = ty::associated_type_parameter_index(self.tcx,
574574
&*trait_def,
575575
associated_type_id);
576-
ty::mk_param(self.tcx, subst::TypeSpace, index, associated_type_id)
576+
Some(ty::mk_param(self.tcx, subst::TypeSpace, index, associated_type_id))
577577
}
578578
}
579579

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
@@ -3342,9 +3342,8 @@ impl<'a> Resolver<'a> {
33423342
// This is not a crate-relative path. We resolve the
33433343
// first component of the path in the current lexical
33443344
// scope and then proceed to resolve below that.
3345-
match self.resolve_module_in_lexical_scope(
3346-
module_,
3347-
module_path[0]) {
3345+
match self.resolve_module_in_lexical_scope(module_,
3346+
module_path[0]) {
33483347
Failed(err) => return Failed(err),
33493348
Indeterminate => {
33503349
debug!("(resolving module path for import) \
@@ -4525,25 +4524,42 @@ impl<'a> Resolver<'a> {
45254524

45264525
fn resolve_where_clause(&mut self, where_clause: &ast::WhereClause) {
45274526
for predicate in where_clause.predicates.iter() {
4528-
match self.resolve_identifier(predicate.ident,
4529-
TypeNS,
4530-
true,
4531-
predicate.span) {
4532-
Some((def @ DefTyParam(_, _, _), last_private)) => {
4533-
self.record_def(predicate.id, (def, last_private));
4534-
}
4535-
_ => {
4536-
self.resolve_error(
4537-
predicate.span,
4538-
format!("undeclared type parameter `{}`",
4539-
token::get_ident(
4540-
predicate.ident)).as_slice());
4527+
match predicate {
4528+
&ast::BoundPredicate(ref bound_pred) => {
4529+
match self.resolve_identifier(bound_pred.ident,
4530+
TypeNS,
4531+
true,
4532+
bound_pred.span) {
4533+
Some((def @ DefTyParam(..), last_private)) => {
4534+
self.record_def(bound_pred.id, (def, last_private));
4535+
}
4536+
_ => {
4537+
self.resolve_error(
4538+
bound_pred.span,
4539+
format!("undeclared type parameter `{}`",
4540+
token::get_ident(
4541+
bound_pred.ident)).as_slice());
4542+
}
4543+
}
4544+
4545+
for bound in bound_pred.bounds.iter() {
4546+
self.resolve_type_parameter_bound(bound_pred.id, bound,
4547+
TraitBoundingTypeParameter);
4548+
}
45414549
}
4542-
}
4550+
&ast::EqPredicate(ref eq_pred) => {
4551+
match self.resolve_path(eq_pred.id, &eq_pred.path, TypeNS, true) {
4552+
Some((def @ DefTyParam(..), last_private)) => {
4553+
self.record_def(eq_pred.id, (def, last_private));
4554+
}
4555+
_ => {
4556+
self.resolve_error(eq_pred.path.span,
4557+
"undeclared associated type");
4558+
}
4559+
}
45434560

4544-
for bound in predicate.bounds.iter() {
4545-
self.resolve_type_parameter_bound(predicate.id, bound,
4546-
TraitBoundingTypeParameter);
4561+
self.resolve_type(&*eq_pred.ty);
4562+
}
45474563
}
45484564
}
45494565
}
@@ -5204,15 +5220,19 @@ impl<'a> Resolver<'a> {
52045220
path: &Path,
52055221
namespace: Namespace,
52065222
check_ribs: bool) -> Option<(Def, LastPrivate)> {
5207-
// First, resolve the types.
5223+
// First, resolve the types and associated type bindings.
52085224
for ty in path.segments.iter().flat_map(|s| s.parameters.types().into_iter()) {
52095225
self.resolve_type(&**ty);
52105226
}
5227+
for binding in path.segments.iter().flat_map(|s| s.parameters.bindings().into_iter()) {
5228+
self.resolve_type(&*binding.ty);
5229+
}
52115230

52125231
if path.global {
52135232
return self.resolve_crate_relative_path(path, namespace);
52145233
}
52155234

5235+
// Try to find a path to an item in a module.
52165236
let unqualified_def =
52175237
self.resolve_identifier(path.segments
52185238
.last().unwrap()

src/librustc/middle/resolve_lifetime.rs

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

@@ -484,7 +492,12 @@ fn early_bound_lifetime_names(generics: &ast::Generics) -> Vec<ast::Name> {
484492
visit::walk_ty_param_bounds_helper(&mut collector, &ty_param.bounds);
485493
}
486494
for predicate in generics.where_clause.predicates.iter() {
487-
visit::walk_ty_param_bounds_helper(&mut collector, &predicate.bounds);
495+
match predicate {
496+
&ast::BoundPredicate(ast::WhereBoundPredicate{ref bounds, ..}) => {
497+
visit::walk_ty_param_bounds_helper(&mut collector, bounds);
498+
}
499+
_ => {}
500+
}
488501
}
489502
}
490503

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::typeck::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)