Change:
The following doesn't compile, but I believe it should: Error: Even though , and . In fact, this compiles:
should be , because the old definition that didn't use assoc types was . Probably the code that detects builtin bounds wasn't updated to handle associated types. cc
This breaks us in hyper. For now, I'll have to manually , knowing that it's safe.,,

Discussion:
} } <ins> fn collect_predicates_for_types(&mut self, obligation: &TraitObligation<'tcx>, trait_def_id: ast::DefId, types: Vec<Ty<'tcx>>) -> Vec<PredicateObligation<'tcx>> { let derived_cause = match self.tcx().lang_items.to_builtin_kind(trait_def_id) { Some(_) => { self.derived_cause(obligation, BuiltinDerivedObligation) }, None => { self.derived_cause(obligation, ImplDerivedObligation) } }; let normalized = project::normalize_with_depth(self, obligation.cause.clone(), obligation.recursion_depth + 1, &types); let obligations = normalized.value.iter().map(|&nested_ty| { // the obligation might be higher-ranked, e.g. for<'a> &'a // int : Copy. In that case, we will wind up with // late-bound regions in the `nested` vector. So for each // one we instantiate to a skolemized region, do our work // to produce something like `&'0 int : Copy`, and then // re-bind it. This is a bit of busy-work but preserves // the invariant that we only manipulate free regions, not // bound ones. self.infcx.try(|snapshot| { let (skol_ty, skol_map) = self.infcx().skolemize_late_bound_regions(&ty::Binder(nested_ty), snapshot); let skol_predicate = util::predicate_for_trait_def( self.tcx(), derived_cause.clone(), trait_def_id, obligation.recursion_depth + 1, skol_ty); match skol_predicate { Ok(skol_predicate) => Ok(self.infcx().plug_leaks(skol_map, snapshot, &skol_predicate)), Err(ErrorReported) => Err(ErrorReported) } }) }).collect::<Result<Vec<PredicateObligation<'tcx>>, _>>(); match obligations { Ok(mut obls) => { obls.push_all(normalized.obligations.as_slice()); obls }, Err(ErrorReported) => Vec::new() } } </ins> /////////////////////////////////////////////////////////////////////////// // CONFIRMATION //

nested: Vec<Ty<'tcx>>) -> VtableBuiltinData<PredicateObligation<'tcx>> { <del> let derived_cause = self.derived_cause(obligation, BuiltinDerivedObligation); let obligations = nested.iter().map(|&bound_ty| { // the obligation might be higher-ranked, e.g. for<'a> &'a // int : Copy. In that case, we will wind up with // late-bound regions in the `nested` vector. So for each // one we instantiate to a skolemized region, do our work // to produce something like `&'0 int : Copy`, and then // re-bind it. This is a bit of busy-work but preserves // the invariant that we only manipulate free regions, not // bound ones. self.infcx.try(|snapshot| { let (skol_ty, skol_map) = self.infcx().skolemize_late_bound_regions(&ty::Binder(bound_ty), snapshot); let skol_predicate = util::predicate_for_builtin_bound( self.tcx(), derived_cause.clone(), bound, obligation.recursion_depth + 1, skol_ty); match skol_predicate { Ok(skol_predicate) => Ok(self.infcx().plug_leaks(skol_map, snapshot, &skol_predicate)), Err(ErrorReported) => Err(ErrorReported) } }) }).collect::<Result<_, _>>(); let obligations = match obligations { Ok(o) => o, Err(ErrorReported) => Vec::new(), </del> <ins> let trait_def = match self.tcx().lang_items.from_builtin_kind(bound) { Ok(def_id) => def_id, Err(_) => { self.tcx().sess.bug("builtin trait definition not found"); } </ins> }; <ins> let obligations = self.collect_predicates_for_types(obligation, trait_def, nested); </ins> let obligations = VecPerParamSpace::new(obligations, Vec::new(), Vec::new()); debug!("vtable_builtin_data: obligations={}",

nested: Vec<Ty<'tcx>>) -> VtableDefaultImplData<PredicateObligation<'tcx>> { <del> let derived_cause = self.derived_cause(obligation, ImplDerivedObligation); let obligations = nested.iter().map(|&nested_ty| { // the obligation might be higher-ranked, e.g. for<'a> &'a // int : Copy. In that case, we will wind up with // late-bound regions in the `nested` vector. So for each // one we instantiate to a skolemized region, do our work // to produce something like `&'0 int : Copy`, and then // re-bind it. This is a bit of busy-work but preserves // the invariant that we only manipulate free regions, not // bound ones. self.infcx.try(|snapshot| { let (skol_ty, skol_map) = self.infcx().skolemize_late_bound_regions(&ty::Binder(nested_ty), snapshot); let skol_predicate = util::predicate_for_default_trait_impl( self.tcx(), derived_cause.clone(), trait_def_id, obligation.recursion_depth + 1, skol_ty); match skol_predicate { Ok(skol_predicate) => Ok(self.infcx().plug_leaks(skol_map, snapshot, &skol_predicate)), Err(ErrorReported) => Err(ErrorReported) } }) }).collect::<Result<_, _>>(); let mut obligations = match obligations { Ok(o) => o, Err(ErrorReported) => Vec::new() }; </del> <ins> let mut obligations = self.collect_predicates_for_types(obligation, trait_def_id, nested); </ins> let _: Result<(),()> = self.infcx.try(|snapshot| { let (_, skol_map) =

}) } <del> pub fn predicate_for_default_trait_impl<'tcx>( </del> <ins> pub fn predicate_for_trait_def<'tcx>( </ins> tcx: &ty::ctxt<'tcx>, cause: ObligationCause<'tcx>, trait_def_id: ast::DefId,

<ins> // 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 transitive analysis for associated types. Collected types // should be normalized and new obligations generated. use std::borrow::{ToOwned, Cow}; fn assert_send<T: Send>(_: T) {} fn main() { assert_send(Cow::Borrowed("foo")); } </ins>

<ins> // 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 transitive analysis for associated types. Collected types // should be normalized and new obligations generated. trait Foo { type A; fn foo(&self) {} } impl Foo for usize { type A = usize; } struct Bar<T: Foo> { inner: T::A } fn is_send<T: Send>() {} fn main() { is_send::<Bar<usize>>(); } </ins>