Auto merge of #26147 - arielb1:assoc-trans, r=nikomatsakis
Fixes #25700 r? @nikomatsakis
This commit is contained in:
commit
ff8fee180b
@ -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()
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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)),
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
|
@ -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={})",
|
||||||
|
@ -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))
|
||||||
|
@ -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,
|
||||||
|
24
src/test/compile-fail/issue-25700.rs
Normal file
24
src/test/compile-fail/issue-25700.rs
Normal 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
|
||||||
|
}
|
22
src/test/run-pass/issue-25700-1.rs
Normal file
22
src/test/run-pass/issue-25700-1.rs
Normal 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);
|
||||||
|
}
|
31
src/test/run-pass/issue-25700-2.rs
Normal file
31
src/test/run-pass/issue-25700-2.rs
Normal 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);
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user