use middle::resolve_lifetime as rl;
use middle::subst::{FnSpace, TypeSpace, SelfSpace, Subst, Substs};
use middle::subst::{VecPerParamSpace};
-use middle::ty::{self, RegionEscape, Ty};
+use middle::traits;
+use middle::ty::{self, RegionEscape, ToPolyTraitRef, Ty};
use rscope::{self, UnelidableRscope, RegionScope, SpecificRscope,
ShiftedRscope, BindingRscope};
use TypeAndSubsts;
trait_ref
}
-pub fn ast_type_binding_to_projection_predicate<'tcx>(
+fn ast_type_binding_to_projection_predicate<'tcx>(
this: &AstConv<'tcx>,
trait_ref: Rc<ty::TraitRef<'tcx>>,
binding: &ConvertedBinding<'tcx>)
//
// We want to produce `<B as SuperTrait<int>>::T == foo`.
- // FIXME(#19541): supertrait upcasting not actually impl'd :)
+ // Simple case: X is defined in the current trait.
+ if trait_defines_associated_type_named(this, trait_ref.def_id, binding.item_name) {
+ return Ok(ty::ProjectionPredicate {
+ projection_ty: ty::ProjectionTy {
+ trait_ref: trait_ref,
+ item_name: binding.item_name,
+ },
+ ty: binding.ty,
+ });
+ }
+
+ // Otherwise, we have to walk through the supertraits to find those that do.
+ let mut candidates: Vec<_> =
+ traits::supertraits(this.tcx(), trait_ref.to_poly_trait_ref())
+ .filter(|r| trait_defines_associated_type_named(this, r.def_id(), binding.item_name))
+ .collect();
+
+ if candidates.len() > 1 {
+ this.tcx().sess.span_err(
+ binding.span,
+ format!("ambiguous associated type: `{}` defined in multiple supertraits `{}`",
+ token::get_name(binding.item_name),
+ candidates.user_string(this.tcx())).as_slice());
+ return Err(ErrorReported);
+ }
+
+ let candidate = match candidates.pop() {
+ Some(c) => c,
+ None => {
+ this.tcx().sess.span_err(
+ binding.span,
+ format!("no associated type `{}` defined in `{}`",
+ token::get_name(binding.item_name),
+ trait_ref.user_string(this.tcx())).as_slice());
+ return Err(ErrorReported);
+ }
+ };
- if !trait_defines_associated_type_named(this, trait_ref.def_id, binding.item_name) {
+ if ty::binds_late_bound_regions(this.tcx(), &candidate) {
this.tcx().sess.span_err(
binding.span,
- format!("no associated type `{}` defined in `{}`",
+ format!("associated type `{}` defined in higher-ranked supertrait `{}`",
token::get_name(binding.item_name),
- trait_ref.user_string(this.tcx())).as_slice());
+ candidate.user_string(this.tcx())).as_slice());
return Err(ErrorReported);
}
Ok(ty::ProjectionPredicate {
projection_ty: ty::ProjectionTy {
- trait_ref: trait_ref,
+ trait_ref: candidate.0,
item_name: binding.item_name,
},
ty: binding.ty,
{
let tcx = this.tcx();
let ty_param_def_id = provenance.def_id();
+
let mut suitable_bounds: Vec<_>;
let ty_param_name: ast::Name;
{ // contain scope of refcell:
let ty_param_def = &ty_param_defs[ty_param_def_id.node];
ty_param_name = ty_param_def.name;
- // FIXME(#19541): we should consider associated types in
- // super-traits. Probably by elaborating the bounds.
-
+ // FIXME(#20300) -- search where clauses, not bounds
suitable_bounds =
- ty_param_def.bounds.trait_bounds // FIXME(#20300) -- search where clauses, not bounds
- .iter()
- .cloned()
+ traits::transitive_bounds(tcx, ty_param_def.bounds.trait_bounds.as_slice())
.filter(|b| trait_defines_associated_type_named(this, b.def_id(), assoc_name))
.collect();
}
--- /dev/null
+// Copyright 2014 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Test equality constraints in a where clause where the type being
+// equated appears in a supertrait.
+
+#![feature(associated_types)]
+
+pub trait Vehicle {
+ type Color;
+
+ fn go(&self) { }
+}
+
+pub trait Box {
+ type Color;
+
+ fn mail(&self) { }
+}
+
+pub trait BoxCar : Box + Vehicle {
+}
+
+fn dent<C:BoxCar>(c: C, color: C::Color) {
+ //~^ ERROR ambiguous associated type `Color` in bounds of `C`
+ //~| NOTE could derive from `Vehicle`
+ //~| NOTE could derive from `Box`
+}
+
+fn dent_object<COLOR>(c: BoxCar<Color=COLOR>) {
+ //~^ ERROR ambiguous associated type
+}
+
+pub fn main() { }
--- /dev/null
+// Copyright 2014 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Test equality constraints in a where clause where the type being
+// equated appears in a supertrait.
+
+#![feature(associated_types)]
+
+pub trait Vehicle {
+ type Color;
+
+ fn go(&self) { }
+}
+
+pub trait Car : Vehicle {
+ fn honk(&self) { }
+ fn chip_paint(&self, c: Self::Color) { }
+}
+
+///////////////////////////////////////////////////////////////////////////
+
+struct Black;
+struct ModelT;
+impl Vehicle for ModelT { type Color = Black; }
+impl Car for ModelT { }
+
+///////////////////////////////////////////////////////////////////////////
+
+struct Blue;
+struct ModelU;
+impl Vehicle for ModelU { type Color = Blue; }
+impl Car for ModelU { }
+
+///////////////////////////////////////////////////////////////////////////
+
+fn dent<C:Car>(c: C, color: C::Color) { c.chip_paint(color) }
+fn a() { dent(ModelT, Black); }
+fn b() { dent(ModelT, Blue); } //~ ERROR type mismatch
+fn c() { dent(ModelU, Black); } //~ ERROR type mismatch
+fn d() { dent(ModelU, Blue); }
+
+///////////////////////////////////////////////////////////////////////////
+
+fn e() { ModelT.chip_paint(Black); }
+fn f() { ModelT.chip_paint(Blue); } //~ ERROR mismatched types
+fn g() { ModelU.chip_paint(Black); } //~ ERROR mismatched types
+fn h() { ModelU.chip_paint(Blue); }
+
+pub fn main() { }
--- /dev/null
+// Copyright 2014 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Test equality constraints in a where clause where the type being
+// equated appears in a supertrait.
+
+#![feature(associated_types)]
+
+pub trait Vehicle {
+ type Color;
+
+ fn go(&self) { }
+}
+
+pub trait Car : Vehicle {
+ fn honk(&self) { }
+}
+
+///////////////////////////////////////////////////////////////////////////
+
+struct Black;
+struct ModelT;
+impl Vehicle for ModelT { type Color = Black; }
+impl Car for ModelT { }
+
+///////////////////////////////////////////////////////////////////////////
+
+struct Blue;
+struct ModelU;
+impl Vehicle for ModelU { type Color = Blue; }
+impl Car for ModelU { }
+
+///////////////////////////////////////////////////////////////////////////
+
+fn black_car<C:Car<Color=Black>>(c: C) {
+}
+
+fn blue_car<C:Car<Color=Blue>>(c: C) {
+}
+
+fn a() { black_car(ModelT); }
+fn b() { blue_car(ModelT); } //~ ERROR type mismatch
+fn c() { black_car(ModelU); } //~ ERROR type mismatch
+fn d() { blue_car(ModelU); }
+
+pub fn main() { }
--- /dev/null
+// Copyright 2014 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+fn pairwise_sub<T:DoubleEndedIterator<Item=int>>(mut t: T) -> int {
+ let mut result = 0;
+ loop {
+ let front = t.next();
+ let back = t.next_back();
+ match (front, back) {
+ (Some(f), Some(b)) => { result += b - f; }
+ _ => { return result; }
+ }
+ }
+}
+
+fn main() {
+ let v = vec!(1, 2, 3, 4, 5, 6);
+ let r =pairwise_sub(v.into_iter());
+ assert_eq!(r, 9);
+}