rollup merge of #21702: nikomatsakis/issue-21636
Check and extract bindings from trait definitions. Fixes #21636. r? @nick29581
This commit is contained in:
commit
103f1459c0
@ -430,6 +430,11 @@ fn project_type<'cx,'tcx>(
|
||||
&obligation_trait_ref,
|
||||
&mut candidates);
|
||||
|
||||
assemble_candidates_from_trait_def(selcx,
|
||||
obligation,
|
||||
&obligation_trait_ref,
|
||||
&mut candidates);
|
||||
|
||||
if let Err(e) = assemble_candidates_from_impls(selcx,
|
||||
obligation,
|
||||
&obligation_trait_ref,
|
||||
@ -474,6 +479,41 @@ fn assemble_candidates_from_param_env<'cx,'tcx>(
|
||||
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>(
|
||||
selcx: &mut SelectionContext<'cx,'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…
x
Reference in New Issue
Block a user