parent
777435990e
commit
093926e841
2 changed files with 84 additions and 0 deletions
|
@ -401,6 +401,11 @@ fn project_type<'cx,'tcx>(
|
||||||
&obligation_trait_ref,
|
&obligation_trait_ref,
|
||||||
&mut candidates);
|
&mut candidates);
|
||||||
|
|
||||||
|
assemble_candidates_from_trait_def(selcx,
|
||||||
|
obligation,
|
||||||
|
&obligation_trait_ref,
|
||||||
|
&mut candidates);
|
||||||
|
|
||||||
if let Err(e) = assemble_candidates_from_impls(selcx,
|
if let Err(e) = assemble_candidates_from_impls(selcx,
|
||||||
obligation,
|
obligation,
|
||||||
&obligation_trait_ref,
|
&obligation_trait_ref,
|
||||||
|
@ -446,6 +451,41 @@ fn assemble_candidates_from_param_env<'cx,'tcx>(
|
||||||
candidate_set, env_predicates);
|
candidate_set, env_predicates);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// In the case of a nested projection like <<A as Foo>::FooT as Bar>::BarT, we may find
|
||||||
|
/// that the definition of `Foo` has some clues:
|
||||||
|
///
|
||||||
|
/// ```rust
|
||||||
|
/// trait Foo {
|
||||||
|
/// type FooT : Bar<BarT=i32>
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// Here, for example, we could conclude that the result is `i32`.
|
||||||
|
fn assemble_candidates_from_trait_def<'cx,'tcx>(
|
||||||
|
selcx: &mut SelectionContext<'cx,'tcx>,
|
||||||
|
obligation: &ProjectionTyObligation<'tcx>,
|
||||||
|
obligation_trait_ref: &Rc<ty::TraitRef<'tcx>>,
|
||||||
|
candidate_set: &mut ProjectionTyCandidateSet<'tcx>)
|
||||||
|
{
|
||||||
|
// Check whether the self-type is itself a projection.
|
||||||
|
let trait_ref = match obligation_trait_ref.self_ty().sty {
|
||||||
|
ty::ty_projection(ref data) => data.trait_ref.clone(),
|
||||||
|
ty::ty_infer(ty::TyVar(_)) => {
|
||||||
|
// If the self-type is an inference variable, then it MAY wind up
|
||||||
|
// being a projected type, so induce an ambiguity.
|
||||||
|
candidate_set.ambiguous = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
_ => { return; }
|
||||||
|
};
|
||||||
|
|
||||||
|
// If so, extract what we know from the trait and try to come up with a good answer.
|
||||||
|
let trait_def = ty::lookup_trait_def(selcx.tcx(), trait_ref.def_id);
|
||||||
|
let bounds = trait_def.generics.to_bounds(selcx.tcx(), trait_ref.substs);
|
||||||
|
assemble_candidates_from_predicates(selcx, obligation, obligation_trait_ref,
|
||||||
|
candidate_set, bounds.predicates.into_vec());
|
||||||
|
}
|
||||||
|
|
||||||
fn assemble_candidates_from_predicates<'cx,'tcx>(
|
fn assemble_candidates_from_predicates<'cx,'tcx>(
|
||||||
selcx: &mut SelectionContext<'cx,'tcx>,
|
selcx: &mut SelectionContext<'cx,'tcx>,
|
||||||
obligation: &ProjectionTyObligation<'tcx>,
|
obligation: &ProjectionTyObligation<'tcx>,
|
||||||
|
|
44
src/test/run-pass/associated-types-binding-in-trait.rs
Normal file
44
src/test/run-pass/associated-types-binding-in-trait.rs
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
// 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 <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 a case where the associated type binding (to `bool`, in this
|
||||||
|
// case) is derived from the trait definition. Issue #21636.
|
||||||
|
|
||||||
|
use std::vec;
|
||||||
|
|
||||||
|
pub trait BitIter {
|
||||||
|
type Iter: Iterator<Item=bool>;
|
||||||
|
fn bit_iter(self) -> <Self as BitIter>::Iter;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl BitIter for Vec<bool> {
|
||||||
|
type Iter = vec::IntoIter<bool>;
|
||||||
|
fn bit_iter(self) -> <Self as BitIter>::Iter {
|
||||||
|
self.into_iter()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn count<T>(arg: T) -> usize
|
||||||
|
where T: BitIter
|
||||||
|
{
|
||||||
|
let mut sum = 0;
|
||||||
|
for i in arg.bit_iter() {
|
||||||
|
if i {
|
||||||
|
sum += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sum
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let v = vec![true, false, true];
|
||||||
|
let c = count(v);
|
||||||
|
assert_eq!(c, 2);
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue