From ea441e16b46ba955e22585f0b7200b551eff4e7c Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Tue, 6 Jan 2015 13:41:14 -0500 Subject: [PATCH] Remember to check the name of the associated type being projected when searching the environment. Fixes #20651. --- src/librustc/middle/traits/project.rs | 10 +++- src/librustc/middle/ty.rs | 4 ++ ...sociated-types-multiple-types-one-trait.rs | 56 +++++++++++++++++++ 3 files changed, 69 insertions(+), 1 deletion(-) create mode 100644 src/test/compile-fail/associated-types-multiple-types-one-trait.rs diff --git a/src/librustc/middle/traits/project.rs b/src/librustc/middle/traits/project.rs index 65f7ad296db..a6be8d16a78 100644 --- a/src/librustc/middle/traits/project.rs +++ b/src/librustc/middle/traits/project.rs @@ -452,7 +452,9 @@ fn assemble_candidates_from_predicates<'cx,'tcx>( for predicate in elaborate_predicates(selcx.tcx(), env_predicates) { match predicate { ty::Predicate::Projection(ref data) => { - let is_match = infcx.probe(|_| { + let same_name = data.item_name() == obligation.predicate.item_name; + + let is_match = same_name && infcx.probe(|_| { let origin = infer::Misc(obligation.cause.span); let obligation_poly_trait_ref = obligation_trait_ref.to_poly_trait_ref(); @@ -465,6 +467,9 @@ fn assemble_candidates_from_predicates<'cx,'tcx>( }); if is_match { + debug!("assemble_candidates_from_predicates: candidate {}", + data.repr(selcx.tcx())); + candidate_set.vec.push( ProjectionTyCandidate::ParamEnv(data.clone())); } @@ -527,6 +532,9 @@ fn assemble_candidates_from_impls<'cx,'tcx>( match vtable { super::VtableImpl(data) => { + debug!("assemble_candidates_from_impls: impl candidate {}", + data.repr(selcx.tcx())); + candidate_set.vec.push( ProjectionTyCandidate::Impl(data)); } diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index c359233eca1..424e64d8e78 100644 --- a/src/librustc/middle/ty.rs +++ b/src/librustc/middle/ty.rs @@ -1866,6 +1866,10 @@ pub struct ProjectionPredicate<'tcx> { pub type PolyProjectionPredicate<'tcx> = Binder>; impl<'tcx> PolyProjectionPredicate<'tcx> { + pub fn item_name(&self) -> ast::Name { + self.0.projection_ty.item_name // safe to skip the binder to access a name + } + pub fn sort_key(&self) -> (ast::DefId, ast::Name) { self.0.projection_ty.sort_key() } diff --git a/src/test/compile-fail/associated-types-multiple-types-one-trait.rs b/src/test/compile-fail/associated-types-multiple-types-one-trait.rs new file mode 100644 index 00000000000..9436f825de8 --- /dev/null +++ b/src/test/compile-fail/associated-types-multiple-types-one-trait.rs @@ -0,0 +1,56 @@ +// Copyright 2015 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +trait Foo { + type X; + type Y; +} + +fn have_x_want_x>(t: &T) +{ + want_x(t); +} + +fn have_x_want_y>(t: &T) +{ + want_y(t); //~ ERROR type mismatch +} + +fn have_y_want_x>(t: &T) +{ + want_x(t); //~ ERROR type mismatch +} + +fn have_y_want_y>(t: &T) +{ + want_y(t); +} + +fn have_xy_want_x>(t: &T) +{ + want_x(t); +} + +fn have_xy_want_y>(t: &T) +{ + want_y(t); +} + +fn have_xy_want_xy>(t: &T) +{ + want_x(t); + want_y(t); +} + +fn want_x>(t: &T) { } + +fn want_y>(t: &T) { } + +fn main() { }