Auto merge of #26147 - arielb1:assoc-trans, r=nikomatsakis

Fixes #25700

r? @nikomatsakis
This commit is contained in:
bors 2015-06-18 21:34:04 +00:00
commit ff8fee180b
9 changed files with 231 additions and 107 deletions

View File

@ -245,7 +245,7 @@ pub enum Vtable<'tcx, N> {
/// Vtable automatically generated for a closure. The def ID is the ID /// Vtable automatically generated for a closure. The def ID is the ID
/// of the closure expression. This is a `VtableImpl` in spirit, but the /// of the closure expression. This is a `VtableImpl` in spirit, but the
/// impl is generated by the compiler and does not appear in the source. /// impl is generated by the compiler and does not appear in the source.
VtableClosure(ast::DefId, subst::Substs<'tcx>), VtableClosure(VtableClosureData<'tcx, N>),
/// Same as above, but for a fn pointer type with the given signature. /// Same as above, but for a fn pointer type with the given signature.
VtableFnPointer(ty::Ty<'tcx>), VtableFnPointer(ty::Ty<'tcx>),
@ -268,6 +268,15 @@ pub struct VtableImplData<'tcx, N> {
pub nested: Vec<N> pub nested: Vec<N>
} }
#[derive(Clone, PartialEq, Eq)]
pub struct VtableClosureData<'tcx, N> {
pub closure_def_id: ast::DefId,
pub substs: subst::Substs<'tcx>,
/// Nested obligations. This can be non-empty if the closure
/// signature contains associated types.
pub nested: Vec<N>
}
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct VtableDefaultImplData<N> { pub struct VtableDefaultImplData<N> {
pub trait_def_id: ast::DefId, pub trait_def_id: ast::DefId,
@ -304,12 +313,12 @@ pub fn predicates_for_generics<'tcx>(tcx: &ty::ctxt<'tcx>,
/// `bound` or is not known to meet bound (note that this is /// `bound` or is not known to meet bound (note that this is
/// conservative towards *no impl*, which is the opposite of the /// conservative towards *no impl*, which is the opposite of the
/// `evaluate` methods). /// `evaluate` methods).
pub fn evaluate_builtin_bound<'a,'tcx>(infcx: &InferCtxt<'a,'tcx>, pub fn type_known_to_meet_builtin_bound<'a,'tcx>(infcx: &InferCtxt<'a,'tcx>,
typer: &ty::ClosureTyper<'tcx>, typer: &ty::ClosureTyper<'tcx>,
ty: Ty<'tcx>, ty: Ty<'tcx>,
bound: ty::BuiltinBound, bound: ty::BuiltinBound,
span: Span) span: Span)
-> SelectionResult<'tcx, ()> -> bool
{ {
debug!("type_known_to_meet_builtin_bound(ty={}, bound={:?})", debug!("type_known_to_meet_builtin_bound(ty={}, bound={:?})",
ty.repr(infcx.tcx), ty.repr(infcx.tcx),
@ -327,61 +336,18 @@ pub fn evaluate_builtin_bound<'a,'tcx>(infcx: &InferCtxt<'a,'tcx>,
// Note: we only assume something is `Copy` if we can // Note: we only assume something is `Copy` if we can
// *definitively* show that it implements `Copy`. Otherwise, // *definitively* show that it implements `Copy`. Otherwise,
// assume it is move; linear is always ok. // assume it is move; linear is always ok.
let result = match fulfill_cx.select_all_or_error(infcx, typer) { match fulfill_cx.select_all_or_error(infcx, typer) {
Ok(()) => Ok(Some(())), // Success, we know it implements Copy. Ok(()) => {
Err(errors) => { debug!("type_known_to_meet_builtin_bound: ty={} bound={:?} success",
// If there were any hard errors, propagate an arbitrary
// one of those. If no hard errors at all, report
// ambiguity.
let sel_error =
errors.iter()
.filter_map(|err| {
match err.code {
CodeAmbiguity => None,
CodeSelectionError(ref e) => Some(e.clone()),
CodeProjectionError(_) => {
infcx.tcx.sess.span_bug(
span,
"projection error while selecting?")
}
}
})
.next();
match sel_error {
None => { Ok(None) }
Some(e) => { Err(e) }
}
}
};
debug!("type_known_to_meet_builtin_bound: ty={} bound={:?} result={:?}",
ty.repr(infcx.tcx), ty.repr(infcx.tcx),
bound, bound);
result);
result
}
pub fn type_known_to_meet_builtin_bound<'a,'tcx>(infcx: &InferCtxt<'a,'tcx>,
typer: &ty::ClosureTyper<'tcx>,
ty: Ty<'tcx>,
bound: ty::BuiltinBound,
span: Span)
-> bool
{
match evaluate_builtin_bound(infcx, typer, ty, bound, span) {
Ok(Some(())) => {
// definitely impl'd
true true
} }
Ok(None) => { Err(e) => {
// ambiguous: if coherence check was successful, shouldn't debug!("type_known_to_meet_builtin_bound: ty={} bound={:?} errors={}",
// happen, but we might have reported an error and been ty.repr(infcx.tcx),
// soldering on, so just treat this like not implemented bound,
false e.repr(infcx.tcx));
}
Err(_) => {
// errors: not implemented.
false false
} }
} }
@ -545,8 +511,8 @@ impl<'tcx, N> Vtable<'tcx, N> {
VtableParam(n) => n, VtableParam(n) => n,
VtableBuiltin(i) => i.nested, VtableBuiltin(i) => i.nested,
VtableDefaultImpl(d) => d.nested, VtableDefaultImpl(d) => d.nested,
VtableObject(_) | VtableFnPointer(..) | VtableClosure(c) => c.nested,
VtableClosure(..) => vec![] VtableObject(_) | VtableFnPointer(..) => vec![]
} }
} }
@ -567,7 +533,11 @@ impl<'tcx, N> Vtable<'tcx, N> {
nested: d.nested.into_iter().map(f).collect() nested: d.nested.into_iter().map(f).collect()
}), }),
VtableFnPointer(f) => VtableFnPointer(f), VtableFnPointer(f) => VtableFnPointer(f),
VtableClosure(d, s) => VtableClosure(d, s), VtableClosure(c) => VtableClosure(VtableClosureData {
closure_def_id: c.closure_def_id,
substs: c.substs,
nested: c.nested.into_iter().map(f).collect()
})
} }
} }
} }

View File

@ -17,15 +17,15 @@ use super::ObligationCause;
use super::PredicateObligation; use super::PredicateObligation;
use super::SelectionContext; use super::SelectionContext;
use super::SelectionError; use super::SelectionError;
use super::VtableClosureData;
use super::VtableImplData; use super::VtableImplData;
use super::util; use super::util;
use middle::infer; use middle::infer;
use middle::subst::{Subst, Substs}; use middle::subst::Subst;
use middle::ty::{self, AsPredicate, ReferencesError, RegionEscape, use middle::ty::{self, AsPredicate, ReferencesError, RegionEscape,
HasProjectionTypes, ToPolyTraitRef, Ty}; HasProjectionTypes, ToPolyTraitRef, Ty};
use middle::ty_fold::{self, TypeFoldable, TypeFolder}; use middle::ty_fold::{self, TypeFoldable, TypeFolder};
use syntax::ast;
use syntax::parse::token; use syntax::parse::token;
use util::common::FN_OUTPUT_NAME; use util::common::FN_OUTPUT_NAME;
use util::ppaux::Repr; use util::ppaux::Repr;
@ -57,7 +57,7 @@ pub struct MismatchedProjectionTypes<'tcx> {
enum ProjectionTyCandidate<'tcx> { enum ProjectionTyCandidate<'tcx> {
ParamEnv(ty::PolyProjectionPredicate<'tcx>), ParamEnv(ty::PolyProjectionPredicate<'tcx>),
Impl(VtableImplData<'tcx, PredicateObligation<'tcx>>), Impl(VtableImplData<'tcx, PredicateObligation<'tcx>>),
Closure(ast::DefId, Substs<'tcx>), Closure(VtableClosureData<'tcx, PredicateObligation<'tcx>>),
FnPointer(Ty<'tcx>), FnPointer(Ty<'tcx>),
} }
@ -162,11 +162,16 @@ fn consider_unification_despite_ambiguity<'cx,'tcx>(selcx: &mut SelectionContext
self_ty, self_ty,
&closure_type.sig, &closure_type.sig,
util::TupleArgumentsFlag::No); util::TupleArgumentsFlag::No);
// We don't have to normalize the return type here - this is only
// reached for TyClosure: Fn inputs where the closure kind is
// still unknown, which should only occur in typeck where the
// closure type is already normalized.
let (ret_type, _) = let (ret_type, _) =
infcx.replace_late_bound_regions_with_fresh_var( infcx.replace_late_bound_regions_with_fresh_var(
obligation.cause.span, obligation.cause.span,
infer::AssocTypeProjection(obligation.predicate.projection_ty.item_name), infer::AssocTypeProjection(obligation.predicate.projection_ty.item_name),
&ty::Binder(ret_type)); &ty::Binder(ret_type));
debug!("consider_unification_despite_ambiguity: ret_type={:?}", debug!("consider_unification_despite_ambiguity: ret_type={:?}",
ret_type.repr(selcx.tcx())); ret_type.repr(selcx.tcx()));
let origin = infer::RelateOutputImplTypes(obligation.cause.span); let origin = infer::RelateOutputImplTypes(obligation.cause.span);
@ -686,9 +691,9 @@ fn assemble_candidates_from_impls<'cx,'tcx>(
selcx, obligation, obligation_trait_ref, candidate_set, selcx, obligation, obligation_trait_ref, candidate_set,
data.object_ty); data.object_ty);
} }
super::VtableClosure(closure_def_id, substs) => { super::VtableClosure(data) => {
candidate_set.vec.push( candidate_set.vec.push(
ProjectionTyCandidate::Closure(closure_def_id, substs)); ProjectionTyCandidate::Closure(data));
} }
super::VtableFnPointer(fn_type) => { super::VtableFnPointer(fn_type) => {
candidate_set.vec.push( candidate_set.vec.push(
@ -755,8 +760,8 @@ fn confirm_candidate<'cx,'tcx>(
confirm_impl_candidate(selcx, obligation, impl_vtable) confirm_impl_candidate(selcx, obligation, impl_vtable)
} }
ProjectionTyCandidate::Closure(def_id, substs) => { ProjectionTyCandidate::Closure(closure_vtable) => {
confirm_closure_candidate(selcx, obligation, def_id, &substs) confirm_closure_candidate(selcx, obligation, closure_vtable)
} }
ProjectionTyCandidate::FnPointer(fn_type) => { ProjectionTyCandidate::FnPointer(fn_type) => {
@ -779,13 +784,24 @@ fn confirm_fn_pointer_candidate<'cx,'tcx>(
fn confirm_closure_candidate<'cx,'tcx>( fn confirm_closure_candidate<'cx,'tcx>(
selcx: &mut SelectionContext<'cx,'tcx>, selcx: &mut SelectionContext<'cx,'tcx>,
obligation: &ProjectionTyObligation<'tcx>, obligation: &ProjectionTyObligation<'tcx>,
closure_def_id: ast::DefId, vtable: VtableClosureData<'tcx, PredicateObligation<'tcx>>)
substs: &Substs<'tcx>)
-> (Ty<'tcx>, Vec<PredicateObligation<'tcx>>) -> (Ty<'tcx>, Vec<PredicateObligation<'tcx>>)
{ {
let closure_typer = selcx.closure_typer(); let closure_typer = selcx.closure_typer();
let closure_type = closure_typer.closure_type(closure_def_id, substs); let closure_type = closure_typer.closure_type(vtable.closure_def_id, &vtable.substs);
confirm_callable_candidate(selcx, obligation, &closure_type.sig, util::TupleArgumentsFlag::No) let Normalized {
value: closure_type,
mut obligations
} = normalize_with_depth(selcx,
obligation.cause.clone(),
obligation.recursion_depth+1,
&closure_type);
let (ty, mut cc_obligations) = confirm_callable_candidate(selcx,
obligation,
&closure_type.sig,
util::TupleArgumentsFlag::No);
obligations.append(&mut cc_obligations);
(ty, obligations)
} }
fn confirm_callable_candidate<'cx,'tcx>( fn confirm_callable_candidate<'cx,'tcx>(
@ -797,7 +813,7 @@ fn confirm_callable_candidate<'cx,'tcx>(
{ {
let tcx = selcx.tcx(); let tcx = selcx.tcx();
debug!("confirm_closure_candidate({},{})", debug!("confirm_callable_candidate({},{})",
obligation.repr(tcx), obligation.repr(tcx),
fn_sig.repr(tcx)); fn_sig.repr(tcx));
@ -921,8 +937,8 @@ impl<'tcx> Repr<'tcx> for ProjectionTyCandidate<'tcx> {
format!("ParamEnv({})", data.repr(tcx)), format!("ParamEnv({})", data.repr(tcx)),
ProjectionTyCandidate::Impl(ref data) => ProjectionTyCandidate::Impl(ref data) =>
format!("Impl({})", data.repr(tcx)), format!("Impl({})", data.repr(tcx)),
ProjectionTyCandidate::Closure(ref a, ref b) => ProjectionTyCandidate::Closure(ref data) =>
format!("Closure(({},{}))", a.repr(tcx), b.repr(tcx)), format!("Closure({})", data.repr(tcx)),
ProjectionTyCandidate::FnPointer(a) => ProjectionTyCandidate::FnPointer(a) =>
format!("FnPointer(({}))", a.repr(tcx)), format!("FnPointer(({}))", a.repr(tcx)),
} }

View File

@ -31,7 +31,8 @@ use super::Selection;
use super::SelectionResult; use super::SelectionResult;
use super::{VtableBuiltin, VtableImpl, VtableParam, VtableClosure, use super::{VtableBuiltin, VtableImpl, VtableParam, VtableClosure,
VtableFnPointer, VtableObject, VtableDefaultImpl}; VtableFnPointer, VtableObject, VtableDefaultImpl};
use super::{VtableImplData, VtableObjectData, VtableBuiltinData, VtableDefaultImplData}; use super::{VtableImplData, VtableObjectData, VtableBuiltinData,
VtableClosureData, VtableDefaultImplData};
use super::object_safety; use super::object_safety;
use super::util; use super::util;
@ -355,7 +356,14 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
}; };
assert!(!substs.has_escaping_regions()); assert!(!substs.has_escaping_regions());
let closure_trait_ref = self.closure_trait_ref(obligation, closure_def_id, substs); // It is OK to call the unnormalized variant here - this is only
// reached for TyClosure: Fn inputs where the closure kind is
// still unknown, which should only occur in typeck where the
// closure type is already normalized.
let closure_trait_ref = self.closure_trait_ref_unnormalized(obligation,
closure_def_id,
substs);
match self.confirm_poly_trait_refs(obligation.cause.clone(), match self.confirm_poly_trait_refs(obligation.cause.clone(),
obligation.predicate.to_poly_trait_ref(), obligation.predicate.to_poly_trait_ref(),
closure_trait_ref) { closure_trait_ref) {
@ -2001,8 +2009,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
} }
ClosureCandidate(closure_def_id, substs) => { ClosureCandidate(closure_def_id, substs) => {
let vtable_closure =
try!(self.confirm_closure_candidate(obligation, closure_def_id, &substs)); try!(self.confirm_closure_candidate(obligation, closure_def_id, &substs));
Ok(VtableClosure(closure_def_id, substs)) Ok(VtableClosure(vtable_closure))
} }
BuiltinObjectCandidate => { BuiltinObjectCandidate => {
@ -2343,24 +2352,33 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
obligation: &TraitObligation<'tcx>, obligation: &TraitObligation<'tcx>,
closure_def_id: ast::DefId, closure_def_id: ast::DefId,
substs: &Substs<'tcx>) substs: &Substs<'tcx>)
-> Result<(),SelectionError<'tcx>> -> Result<VtableClosureData<'tcx, PredicateObligation<'tcx>>,
SelectionError<'tcx>>
{ {
debug!("confirm_closure_candidate({},{},{})", debug!("confirm_closure_candidate({},{},{})",
obligation.repr(self.tcx()), obligation.repr(self.tcx()),
closure_def_id.repr(self.tcx()), closure_def_id.repr(self.tcx()),
substs.repr(self.tcx())); substs.repr(self.tcx()));
let trait_ref = self.closure_trait_ref(obligation, let Normalized {
closure_def_id, value: trait_ref,
substs); obligations
} = self.closure_trait_ref(obligation, closure_def_id, substs);
debug!("confirm_closure_candidate(closure_def_id={}, trait_ref={})", debug!("confirm_closure_candidate(closure_def_id={}, trait_ref={}, obligations={})",
closure_def_id.repr(self.tcx()), closure_def_id.repr(self.tcx()),
trait_ref.repr(self.tcx())); trait_ref.repr(self.tcx()),
obligations.repr(self.tcx()));
self.confirm_poly_trait_refs(obligation.cause.clone(), try!(self.confirm_poly_trait_refs(obligation.cause.clone(),
obligation.predicate.to_poly_trait_ref(), obligation.predicate.to_poly_trait_ref(),
trait_ref) trait_ref));
Ok(VtableClosureData {
closure_def_id: closure_def_id,
substs: substs.clone(),
nested: obligations
})
} }
/// In the case of closure types and fn pointers, /// In the case of closure types and fn pointers,
@ -2819,7 +2837,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
} }
} }
fn closure_trait_ref(&self, fn closure_trait_ref_unnormalized(&mut self,
obligation: &TraitObligation<'tcx>, obligation: &TraitObligation<'tcx>,
closure_def_id: ast::DefId, closure_def_id: ast::DefId,
substs: &Substs<'tcx>) substs: &Substs<'tcx>)
@ -2832,7 +2850,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
obligation.predicate.0.self_ty(), // (1) obligation.predicate.0.self_ty(), // (1)
&closure_type.sig, &closure_type.sig,
util::TupleArgumentsFlag::No); util::TupleArgumentsFlag::No);
// (1) Feels icky to skip the binder here, but OTOH we know // (1) Feels icky to skip the binder here, but OTOH we know
// that the self-type is an unboxed closure type and hence is // that the self-type is an unboxed closure type and hence is
// in fact unparameterized (or at least does not reference any // in fact unparameterized (or at least does not reference any
@ -2842,6 +2859,23 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
ty::Binder(trait_ref) ty::Binder(trait_ref)
} }
fn closure_trait_ref(&mut self,
obligation: &TraitObligation<'tcx>,
closure_def_id: ast::DefId,
substs: &Substs<'tcx>)
-> Normalized<'tcx, ty::PolyTraitRef<'tcx>>
{
let trait_ref = self.closure_trait_ref_unnormalized(
obligation, closure_def_id, substs);
// A closure signature can contain associated types which
// must be normalized.
normalize_with_depth(self,
obligation.cause.clone(),
obligation.recursion_depth+1,
&trait_ref)
}
/// Returns the obligations that are implied by instantiating an /// Returns the obligations that are implied by instantiating an
/// impl or trait. The obligations are substituted and fully /// impl or trait. The obligations are substituted and fully
/// normalized. This is used when confirming an impl or default /// normalized. This is used when confirming an impl or default

View File

@ -308,6 +308,12 @@ impl<'tcx, N> fmt::Debug for VtableImplData<'tcx, N> {
} }
} }
impl<'tcx, N> fmt::Debug for super::VtableClosureData<'tcx, N> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "VtableClosure({:?})", self.closure_def_id)
}
}
impl<'tcx> fmt::Debug for super::VtableObjectData<'tcx> { impl<'tcx> fmt::Debug for super::VtableObjectData<'tcx> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "VtableObject(...)") write!(f, "VtableObject(...)")
@ -497,10 +503,8 @@ impl<'tcx, N:Repr<'tcx>> Repr<'tcx> for super::Vtable<'tcx, N> {
super::VtableDefaultImpl(ref t) => super::VtableDefaultImpl(ref t) =>
t.repr(tcx), t.repr(tcx),
super::VtableClosure(ref d, ref s) => super::VtableClosure(ref d) =>
format!("VtableClosure({},{})",
d.repr(tcx), d.repr(tcx),
s.repr(tcx)),
super::VtableFnPointer(ref d) => super::VtableFnPointer(ref d) =>
format!("VtableFnPointer({})", format!("VtableFnPointer({})",
@ -529,6 +533,15 @@ impl<'tcx, N:Repr<'tcx>> Repr<'tcx> for super::VtableImplData<'tcx, N> {
} }
} }
impl<'tcx, N:Repr<'tcx>> Repr<'tcx> for super::VtableClosureData<'tcx, N> {
fn repr(&self, tcx: &ty::ctxt<'tcx>) -> String {
format!("VtableClosure(closure_def_id={}, substs={}, nested={})",
self.closure_def_id.repr(tcx),
self.substs.repr(tcx),
self.nested.repr(tcx))
}
}
impl<'tcx, N:Repr<'tcx>> Repr<'tcx> for super::VtableBuiltinData<N> { impl<'tcx, N:Repr<'tcx>> Repr<'tcx> for super::VtableBuiltinData<N> {
fn repr(&self, tcx: &ty::ctxt<'tcx>) -> String { fn repr(&self, tcx: &ty::ctxt<'tcx>) -> String {
format!("VtableBuiltin(nested={})", format!("VtableBuiltin(nested={})",

View File

@ -479,6 +479,16 @@ impl<'tcx, N: TypeFoldable<'tcx>> TypeFoldable<'tcx> for traits::VtableImplData<
} }
} }
impl<'tcx, N: TypeFoldable<'tcx>> TypeFoldable<'tcx> for traits::VtableClosureData<'tcx, N> {
fn fold_with<F:TypeFolder<'tcx>>(&self, folder: &mut F) -> traits::VtableClosureData<'tcx, N> {
traits::VtableClosureData {
closure_def_id: self.closure_def_id,
substs: self.substs.fold_with(folder),
nested: self.nested.fold_with(folder),
}
}
}
impl<'tcx, N: TypeFoldable<'tcx>> TypeFoldable<'tcx> for traits::VtableDefaultImplData<N> { impl<'tcx, N: TypeFoldable<'tcx>> TypeFoldable<'tcx> for traits::VtableDefaultImplData<N> {
fn fold_with<F:TypeFolder<'tcx>>(&self, folder: &mut F) -> traits::VtableDefaultImplData<N> { fn fold_with<F:TypeFolder<'tcx>>(&self, folder: &mut F) -> traits::VtableDefaultImplData<N> {
traits::VtableDefaultImplData { traits::VtableDefaultImplData {
@ -501,8 +511,8 @@ impl<'tcx, N: TypeFoldable<'tcx>> TypeFoldable<'tcx> for traits::Vtable<'tcx, N>
match *self { match *self {
traits::VtableImpl(ref v) => traits::VtableImpl(v.fold_with(folder)), traits::VtableImpl(ref v) => traits::VtableImpl(v.fold_with(folder)),
traits::VtableDefaultImpl(ref t) => traits::VtableDefaultImpl(t.fold_with(folder)), traits::VtableDefaultImpl(ref t) => traits::VtableDefaultImpl(t.fold_with(folder)),
traits::VtableClosure(d, ref s) => { traits::VtableClosure(ref d) => {
traits::VtableClosure(d, s.fold_with(folder)) traits::VtableClosure(d.fold_with(folder))
} }
traits::VtableFnPointer(ref d) => { traits::VtableFnPointer(ref d) => {
traits::VtableFnPointer(d.fold_with(folder)) traits::VtableFnPointer(d.fold_with(folder))

View File

@ -359,13 +359,13 @@ fn trans_monomorphized_callee<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
Callee { bcx: bcx, data: Fn(llfn) } Callee { bcx: bcx, data: Fn(llfn) }
} }
traits::VtableClosure(closure_def_id, substs) => { traits::VtableClosure(vtable_closure) => {
// The substitutions should have no type parameters remaining // The substitutions should have no type parameters remaining
// after passing through fulfill_obligation // after passing through fulfill_obligation
let trait_closure_kind = bcx.tcx().lang_items.fn_trait_kind(trait_id).unwrap(); let trait_closure_kind = bcx.tcx().lang_items.fn_trait_kind(trait_id).unwrap();
let llfn = closure::trans_closure_method(bcx.ccx(), let llfn = closure::trans_closure_method(bcx.ccx(),
closure_def_id, vtable_closure.closure_def_id,
substs, vtable_closure.substs,
MethodCallKey(method_call), MethodCallKey(method_call),
bcx.fcx.param_substs, bcx.fcx.param_substs,
trait_closure_kind); trait_closure_kind);
@ -716,7 +716,11 @@ pub fn get_vtable<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
nested: _ }) => { nested: _ }) => {
emit_vtable_methods(ccx, id, substs, param_substs).into_iter() emit_vtable_methods(ccx, id, substs, param_substs).into_iter()
} }
traits::VtableClosure(closure_def_id, substs) => { traits::VtableClosure(
traits::VtableClosureData {
closure_def_id,
substs,
nested: _ }) => {
let trait_closure_kind = tcx.lang_items.fn_trait_kind(trait_ref.def_id()).unwrap(); let trait_closure_kind = tcx.lang_items.fn_trait_kind(trait_ref.def_id()).unwrap();
let llfn = closure::trans_closure_method(ccx, let llfn = closure::trans_closure_method(ccx,
closure_def_id, closure_def_id,

View File

@ -0,0 +1,24 @@
// 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.
struct S<T: 'static>(Option<&'static T>);
trait Tr { type Out; }
impl<T> Tr for T { type Out = T; }
impl<T: 'static> Copy for S<T> where S<T>: Tr<Out=T> {}
impl<T: 'static> Clone for S<T> where S<T>: Tr<Out=T> {
fn clone(&self) -> Self { *self }
}
fn main() {
let t = S::<()>(None);
drop(t);
drop(t); //~ ERROR use of moved value
}

View File

@ -0,0 +1,22 @@
// 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.
struct S<T: 'static>(Option<&'static T>);
trait Tr { type Out; }
impl<T> Tr for T { type Out = T; }
impl<T: 'static> Copy for S<T> where S<T>: Tr<Out=T> {}
impl<T: 'static> Clone for S<T> where S<T>: Tr<Out=T> {
fn clone(&self) -> Self { *self }
}
fn main() {
S::<()>(None);
}

View File

@ -0,0 +1,31 @@
// 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.
pub trait Parser {
type Input;
}
pub struct Iter<P: Parser>(P, P::Input);
pub struct Map<P, F>(P, F);
impl<P, F> Parser for Map<P, F> where F: FnMut(P) {
type Input = u8;
}
trait AstId { type Untyped; }
impl AstId for u32 { type Untyped = u32; }
fn record_type<Id: AstId>(i: Id::Untyped) -> u8 {
Iter(Map(i, |_: Id::Untyped| {}), 42).1
}
pub fn main() {
assert_eq!(record_type::<u32>(3), 42);
}