mirror of
https://github.com/rust-lang/rust.git
synced 2025-04-17 06:26:55 +00:00
Auto merge of #32780 - soltanmm:consider-the-following, r=nikomatsakis
Replace consider_unification_despite_ambiguity with new obligation variant Is work towards #32730. Addresses part one of #32286. Addresses #24210 and #26046 to some degree. r? @nikomatsakis
This commit is contained in:
commit
35dca7fb7b
@ -1543,4 +1543,5 @@ register_diagnostics! {
|
||||
E0490, // a value of type `..` is borrowed for too long
|
||||
E0491, // in type `..`, reference has a longer lifetime than the data it...
|
||||
E0495, // cannot infer an appropriate lifetime due to conflicting requirements
|
||||
E0524, // expected a closure that implements `..` but this closure only implements `..`
|
||||
}
|
||||
|
@ -59,6 +59,7 @@ impl FreeRegionMap {
|
||||
ty::Predicate::Equate(..) |
|
||||
ty::Predicate::WellFormed(..) |
|
||||
ty::Predicate::ObjectSafe(..) |
|
||||
ty::Predicate::ClosureKind(..) |
|
||||
ty::Predicate::TypeOutlives(..) => {
|
||||
// No region bounds here
|
||||
}
|
||||
|
@ -495,6 +495,21 @@ pub fn report_selection_error<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
|
||||
err.emit();
|
||||
}
|
||||
|
||||
ty::Predicate::ClosureKind(closure_def_id, kind) => {
|
||||
let found_kind = infcx.closure_kind(closure_def_id).unwrap();
|
||||
let closure_span = infcx.tcx.map.span_if_local(closure_def_id).unwrap();
|
||||
let mut err = struct_span_err!(
|
||||
infcx.tcx.sess, closure_span, E0524,
|
||||
"expected a closure that implements the `{}` trait, but this closure \
|
||||
only implements `{}`",
|
||||
kind,
|
||||
found_kind);
|
||||
err.span_note(
|
||||
obligation.cause.span,
|
||||
&format!("the requirement to implement `{}` derives from here", kind));
|
||||
err.emit();
|
||||
}
|
||||
|
||||
ty::Predicate::WellFormed(ty) => {
|
||||
// WF predicates cannot themselves make
|
||||
// errors. They can only block due to
|
||||
|
@ -652,6 +652,21 @@ fn process_predicate1<'a,'tcx>(selcx: &mut SelectionContext<'a,'tcx>,
|
||||
}
|
||||
}
|
||||
|
||||
ty::Predicate::ClosureKind(closure_def_id, kind) => {
|
||||
match selcx.infcx().closure_kind(closure_def_id) {
|
||||
Some(closure_kind) => {
|
||||
if closure_kind.extends(kind) {
|
||||
Ok(Some(vec![]))
|
||||
} else {
|
||||
Err(CodeSelectionError(Unimplemented))
|
||||
}
|
||||
}
|
||||
None => {
|
||||
Ok(None)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ty::Predicate::WellFormed(ty) => {
|
||||
match ty::wf::obligations(selcx.infcx(), obligation.cause.body_id,
|
||||
ty, obligation.cause.span) {
|
||||
|
@ -165,6 +165,7 @@ pub fn supertraits_reference_self<'tcx>(tcx: &TyCtxt<'tcx>,
|
||||
ty::Predicate::ObjectSafe(..) |
|
||||
ty::Predicate::TypeOutlives(..) |
|
||||
ty::Predicate::RegionOutlives(..) |
|
||||
ty::Predicate::ClosureKind(..) |
|
||||
ty::Predicate::Equate(..) => {
|
||||
false
|
||||
}
|
||||
@ -207,6 +208,7 @@ fn generics_require_sized_self<'tcx>(tcx: &TyCtxt<'tcx>,
|
||||
ty::Predicate::RegionOutlives(..) |
|
||||
ty::Predicate::WellFormed(..) |
|
||||
ty::Predicate::ObjectSafe(..) |
|
||||
ty::Predicate::ClosureKind(..) |
|
||||
ty::Predicate::TypeOutlives(..) => {
|
||||
false
|
||||
}
|
||||
|
@ -198,9 +198,10 @@ enum SelectionCandidate<'tcx> {
|
||||
/// we found an applicable bound in the trait definition.
|
||||
ProjectionCandidate,
|
||||
|
||||
/// Implementation of a `Fn`-family trait by one of the
|
||||
/// anonymous types generated for a `||` expression.
|
||||
ClosureCandidate(/* closure */ DefId, &'tcx ty::ClosureSubsts<'tcx>),
|
||||
/// Implementation of a `Fn`-family trait by one of the anonymous types
|
||||
/// generated for a `||` expression. The ty::ClosureKind informs the
|
||||
/// confirmation step what ClosureKind obligation to emit.
|
||||
ClosureCandidate(/* closure */ DefId, &'tcx ty::ClosureSubsts<'tcx>, ty::ClosureKind),
|
||||
|
||||
/// Implementation of a `Fn`-family trait by one of the anonymous
|
||||
/// types generated for a fn pointer type (e.g., `fn(int)->int`)
|
||||
@ -321,75 +322,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||
|
||||
let stack = self.push_stack(TraitObligationStackList::empty(), obligation);
|
||||
match self.candidate_from_obligation(&stack)? {
|
||||
None => {
|
||||
self.consider_unification_despite_ambiguity(obligation);
|
||||
Ok(None)
|
||||
}
|
||||
None => Ok(None),
|
||||
Some(candidate) => Ok(Some(self.confirm_candidate(obligation, candidate)?)),
|
||||
}
|
||||
}
|
||||
|
||||
/// In the particular case of unboxed closure obligations, we can
|
||||
/// sometimes do some amount of unification for the
|
||||
/// argument/return types even though we can't yet fully match obligation.
|
||||
/// The particular case we are interesting in is an obligation of the form:
|
||||
///
|
||||
/// C : FnFoo<A>
|
||||
///
|
||||
/// where `C` is an unboxed closure type and `FnFoo` is one of the
|
||||
/// `Fn` traits. Because we know that users cannot write impls for closure types
|
||||
/// themselves, the only way that `C : FnFoo` can fail to match is under two
|
||||
/// conditions:
|
||||
///
|
||||
/// 1. The closure kind for `C` is not yet known, because inference isn't complete.
|
||||
/// 2. The closure kind for `C` *is* known, but doesn't match what is needed.
|
||||
/// For example, `C` may be a `FnOnce` closure, but a `Fn` closure is needed.
|
||||
///
|
||||
/// In either case, we always know what argument types are
|
||||
/// expected by `C`, no matter what kind of `Fn` trait it
|
||||
/// eventually matches. So we can go ahead and unify the argument
|
||||
/// types, even though the end result is ambiguous.
|
||||
///
|
||||
/// Note that this is safe *even if* the trait would never be
|
||||
/// matched (case 2 above). After all, in that case, an error will
|
||||
/// result, so it kind of doesn't matter what we do --- unifying
|
||||
/// the argument types can only be helpful to the user, because
|
||||
/// once they patch up the kind of closure that is expected, the
|
||||
/// argment types won't really change.
|
||||
fn consider_unification_despite_ambiguity(&mut self, obligation: &TraitObligation<'tcx>) {
|
||||
// Is this a `C : FnFoo(...)` trait reference for some trait binding `FnFoo`?
|
||||
match self.tcx().lang_items.fn_trait_kind(obligation.predicate.0.def_id()) {
|
||||
Some(_) => { }
|
||||
None => { return; }
|
||||
}
|
||||
|
||||
// Is the self-type a closure type? We ignore bindings here
|
||||
// because if it is a closure type, it must be a closure type from
|
||||
// within this current fn, and hence none of the higher-ranked
|
||||
// lifetimes can appear inside the self-type.
|
||||
let self_ty = self.infcx.shallow_resolve(*obligation.self_ty().skip_binder());
|
||||
let (closure_def_id, substs) = match self_ty.sty {
|
||||
ty::TyClosure(id, ref substs) => (id, substs),
|
||||
_ => { return; }
|
||||
};
|
||||
assert!(!substs.has_escaping_regions());
|
||||
|
||||
// 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(),
|
||||
obligation.predicate.to_poly_trait_ref(),
|
||||
closure_trait_ref) {
|
||||
Ok(()) => { }
|
||||
Err(_) => { /* Silently ignore errors. */ }
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// EVALUATION
|
||||
//
|
||||
@ -532,6 +469,21 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ty::Predicate::ClosureKind(closure_def_id, kind) => {
|
||||
match self.infcx.closure_kind(closure_def_id) {
|
||||
Some(closure_kind) => {
|
||||
if closure_kind.extends(kind) {
|
||||
EvaluatedToOk
|
||||
} else {
|
||||
EvaluatedToErr
|
||||
}
|
||||
}
|
||||
None => {
|
||||
EvaluatedToAmbig
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1282,12 +1234,12 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||
Some(closure_kind) => {
|
||||
debug!("assemble_unboxed_candidates: closure_kind = {:?}", closure_kind);
|
||||
if closure_kind.extends(kind) {
|
||||
candidates.vec.push(ClosureCandidate(closure_def_id, substs));
|
||||
candidates.vec.push(ClosureCandidate(closure_def_id, substs, kind));
|
||||
}
|
||||
}
|
||||
None => {
|
||||
debug!("assemble_unboxed_candidates: closure_kind not yet known");
|
||||
candidates.ambiguous = true;
|
||||
candidates.vec.push(ClosureCandidate(closure_def_id, substs, kind));
|
||||
}
|
||||
}
|
||||
|
||||
@ -2071,9 +2023,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||
Ok(VtableImpl(vtable_impl))
|
||||
}
|
||||
|
||||
ClosureCandidate(closure_def_id, substs) => {
|
||||
ClosureCandidate(closure_def_id, substs, kind) => {
|
||||
let vtable_closure =
|
||||
self.confirm_closure_candidate(obligation, closure_def_id, substs)?;
|
||||
self.confirm_closure_candidate(obligation, closure_def_id, substs, kind)?;
|
||||
Ok(VtableClosure(vtable_closure))
|
||||
}
|
||||
|
||||
@ -2430,7 +2382,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||
fn confirm_closure_candidate(&mut self,
|
||||
obligation: &TraitObligation<'tcx>,
|
||||
closure_def_id: DefId,
|
||||
substs: &ty::ClosureSubsts<'tcx>)
|
||||
substs: &ty::ClosureSubsts<'tcx>,
|
||||
kind: ty::ClosureKind)
|
||||
-> Result<VtableClosureData<'tcx, PredicateObligation<'tcx>>,
|
||||
SelectionError<'tcx>>
|
||||
{
|
||||
@ -2441,7 +2394,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||
|
||||
let Normalized {
|
||||
value: trait_ref,
|
||||
obligations
|
||||
mut obligations
|
||||
} = self.closure_trait_ref(obligation, closure_def_id, substs);
|
||||
|
||||
debug!("confirm_closure_candidate(closure_def_id={:?}, trait_ref={:?}, obligations={:?})",
|
||||
@ -2453,6 +2406,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||
obligation.predicate.to_poly_trait_ref(),
|
||||
trait_ref)?;
|
||||
|
||||
obligations.push(Obligation::new(
|
||||
obligation.cause.clone(),
|
||||
ty::Predicate::ClosureKind(closure_def_id, kind)));
|
||||
|
||||
Ok(VtableClosureData {
|
||||
closure_def_id: closure_def_id,
|
||||
substs: substs.clone(),
|
||||
|
@ -60,6 +60,9 @@ impl<'a,'tcx> PredicateSet<'a,'tcx> {
|
||||
|
||||
ty::Predicate::ObjectSafe(data) =>
|
||||
ty::Predicate::ObjectSafe(data),
|
||||
|
||||
ty::Predicate::ClosureKind(closure_def_id, kind) =>
|
||||
ty::Predicate::ClosureKind(closure_def_id, kind)
|
||||
};
|
||||
self.set.insert(normalized_pred)
|
||||
}
|
||||
@ -156,6 +159,9 @@ impl<'cx, 'tcx> Elaborator<'cx, 'tcx> {
|
||||
ty::Predicate::Projection(..) => {
|
||||
// Nothing to elaborate in a projection predicate.
|
||||
}
|
||||
ty::Predicate::ClosureKind(..) => {
|
||||
// Nothing to elaborate when waiting for a closure's kind to be inferred.
|
||||
}
|
||||
ty::Predicate::RegionOutlives(..) |
|
||||
ty::Predicate::TypeOutlives(..) => {
|
||||
// Currently, we do not "elaborate" predicates like
|
||||
|
@ -832,6 +832,11 @@ pub enum Predicate<'tcx> {
|
||||
|
||||
/// trait must be object-safe
|
||||
ObjectSafe(DefId),
|
||||
|
||||
/// No direct syntax. May be thought of as `where T : FnFoo<...>` for some 'TypeSpace'
|
||||
/// substitutions `...` and T being a closure type. Satisfied (or refuted) once we know the
|
||||
/// closure's kind.
|
||||
ClosureKind(DefId, ClosureKind),
|
||||
}
|
||||
|
||||
impl<'tcx> Predicate<'tcx> {
|
||||
@ -921,6 +926,8 @@ impl<'tcx> Predicate<'tcx> {
|
||||
Predicate::WellFormed(data.subst(tcx, substs)),
|
||||
Predicate::ObjectSafe(trait_def_id) =>
|
||||
Predicate::ObjectSafe(trait_def_id),
|
||||
Predicate::ClosureKind(closure_def_id, kind) =>
|
||||
Predicate::ClosureKind(closure_def_id, kind),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1108,6 +1115,9 @@ impl<'tcx> Predicate<'tcx> {
|
||||
ty::Predicate::ObjectSafe(_trait_def_id) => {
|
||||
vec![]
|
||||
}
|
||||
ty::Predicate::ClosureKind(_closure_def_id, _kind) => {
|
||||
vec![]
|
||||
}
|
||||
};
|
||||
|
||||
// The only reason to collect into a vector here is that I was
|
||||
@ -1128,6 +1138,7 @@ impl<'tcx> Predicate<'tcx> {
|
||||
Predicate::RegionOutlives(..) |
|
||||
Predicate::WellFormed(..) |
|
||||
Predicate::ObjectSafe(..) |
|
||||
Predicate::ClosureKind(..) |
|
||||
Predicate::TypeOutlives(..) => {
|
||||
None
|
||||
}
|
||||
@ -1783,7 +1794,7 @@ pub struct ItemSubsts<'tcx> {
|
||||
pub substs: Substs<'tcx>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, PartialOrd, Ord, PartialEq, Eq, Debug, RustcEncodable, RustcDecodable)]
|
||||
#[derive(Clone, Copy, PartialOrd, Ord, PartialEq, Eq, Hash, Debug, RustcEncodable, RustcDecodable)]
|
||||
pub enum ClosureKind {
|
||||
// Warning: Ordering is significant here! The ordering is chosen
|
||||
// because the trait Fn is a subtrait of FnMut and so in turn, and
|
||||
|
@ -644,6 +644,8 @@ impl<'tcx> TypeFoldable<'tcx> for ty::Predicate<'tcx> {
|
||||
ty::Predicate::Projection(binder.fold_with(folder)),
|
||||
ty::Predicate::WellFormed(data) =>
|
||||
ty::Predicate::WellFormed(data.fold_with(folder)),
|
||||
ty::Predicate::ClosureKind(closure_def_id, kind) =>
|
||||
ty::Predicate::ClosureKind(closure_def_id, kind),
|
||||
ty::Predicate::ObjectSafe(trait_def_id) =>
|
||||
ty::Predicate::ObjectSafe(trait_def_id),
|
||||
}
|
||||
@ -657,6 +659,7 @@ impl<'tcx> TypeFoldable<'tcx> for ty::Predicate<'tcx> {
|
||||
ty::Predicate::TypeOutlives(ref binder) => binder.visit_with(visitor),
|
||||
ty::Predicate::Projection(ref binder) => binder.visit_with(visitor),
|
||||
ty::Predicate::WellFormed(data) => data.visit_with(visitor),
|
||||
ty::Predicate::ClosureKind(_closure_def_id, _kind) => false,
|
||||
ty::Predicate::ObjectSafe(_trait_def_id) => false,
|
||||
}
|
||||
}
|
||||
|
@ -301,6 +301,7 @@ impl<'tcx> TyCtxt<'tcx> {
|
||||
ty::Predicate::Equate(..) |
|
||||
ty::Predicate::WellFormed(..) |
|
||||
ty::Predicate::ObjectSafe(..) |
|
||||
ty::Predicate::ClosureKind(..) |
|
||||
ty::Predicate::RegionOutlives(..) => {
|
||||
None
|
||||
}
|
||||
|
@ -92,6 +92,8 @@ pub fn predicate_obligations<'a,'tcx>(infcx: &InferCtxt<'a, 'tcx>,
|
||||
}
|
||||
ty::Predicate::ObjectSafe(_) => {
|
||||
}
|
||||
ty::Predicate::ClosureKind(..) => {
|
||||
}
|
||||
}
|
||||
|
||||
wf.normalize()
|
||||
@ -155,6 +157,7 @@ pub fn implied_bounds<'a,'tcx>(
|
||||
ty::Predicate::Trait(..) |
|
||||
ty::Predicate::Equate(..) |
|
||||
ty::Predicate::Projection(..) |
|
||||
ty::Predicate::ClosureKind(..) |
|
||||
ty::Predicate::ObjectSafe(..) =>
|
||||
vec![],
|
||||
|
||||
|
@ -467,6 +467,9 @@ impl<'tcx> fmt::Debug for ty::Predicate<'tcx> {
|
||||
ty::Predicate::ObjectSafe(trait_def_id) => {
|
||||
write!(f, "ObjectSafe({:?})", trait_def_id)
|
||||
}
|
||||
ty::Predicate::ClosureKind(closure_def_id, kind) => {
|
||||
write!(f, "ClosureKind({:?}, {:?})", closure_def_id, kind)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1039,6 +1042,16 @@ impl<'tcx> fmt::Display for ty::ProjectionTy<'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for ty::ClosureKind {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
match *self {
|
||||
ty::ClosureKind::Fn => write!(f, "Fn"),
|
||||
ty::ClosureKind::FnMut => write!(f, "FnMut"),
|
||||
ty::ClosureKind::FnOnce => write!(f, "FnOnce"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> fmt::Display for ty::Predicate<'tcx> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
match *self {
|
||||
@ -1052,6 +1065,11 @@ impl<'tcx> fmt::Display for ty::Predicate<'tcx> {
|
||||
ty::tls::with(|tcx| {
|
||||
write!(f, "the trait `{}` is object-safe", tcx.item_path_str(trait_def_id))
|
||||
}),
|
||||
ty::Predicate::ClosureKind(closure_def_id, kind) =>
|
||||
ty::tls::with(|tcx| {
|
||||
write!(f, "the closure `{}` implements the trait `{}`",
|
||||
tcx.item_path_str(closure_def_id), kind)
|
||||
}),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -553,6 +553,18 @@ impl<'a,'tcx> TyDecoder<'a,'tcx> {
|
||||
assert_eq!(self.next(), '|');
|
||||
ty::Predicate::ObjectSafe(def_id)
|
||||
}
|
||||
'c' => {
|
||||
let def_id = self.parse_def();
|
||||
assert_eq!(self.next(), '|');
|
||||
let kind = match self.next() {
|
||||
'f' => ty::ClosureKind::Fn,
|
||||
'm' => ty::ClosureKind::FnMut,
|
||||
'o' => ty::ClosureKind::FnOnce,
|
||||
c => bug!("Encountered invalid character in metadata: {}", c)
|
||||
};
|
||||
assert_eq!(self.next(), '|');
|
||||
ty::Predicate::ClosureKind(def_id, kind)
|
||||
}
|
||||
c => bug!("Encountered invalid character in metadata: {}", c)
|
||||
}
|
||||
}
|
||||
|
@ -479,6 +479,14 @@ pub fn enc_predicate<'a, 'tcx>(w: &mut Cursor<Vec<u8>>,
|
||||
ty::Predicate::ObjectSafe(trait_def_id) => {
|
||||
write!(w, "O{}|", (cx.ds)(cx.tcx, trait_def_id));
|
||||
}
|
||||
ty::Predicate::ClosureKind(closure_def_id, kind) => {
|
||||
let kind_char = match kind {
|
||||
ty::ClosureKind::Fn => 'f',
|
||||
ty::ClosureKind::FnMut => 'm',
|
||||
ty::ClosureKind::FnOnce => 'o',
|
||||
};
|
||||
write!(w, "c{}|{}|", (cx.ds)(cx.tcx, closure_def_id), kind_char);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -179,6 +179,16 @@ fn deduce_expectations_from_obligations<'a,'tcx>(
|
||||
ty::Predicate::TypeOutlives(..) => None,
|
||||
ty::Predicate::WellFormed(..) => None,
|
||||
ty::Predicate::ObjectSafe(..) => None,
|
||||
|
||||
// NB: This predicate is created by breaking down a
|
||||
// `ClosureType: FnFoo()` predicate, where
|
||||
// `ClosureType` represents some `TyClosure`. It can't
|
||||
// possibly be referring to the current closure,
|
||||
// because we haven't produced the `TyClosure` for
|
||||
// this closure yet; this is exactly why the other
|
||||
// code is looking for a self type of a unresolved
|
||||
// inference variable.
|
||||
ty::Predicate::ClosureKind(..) => None,
|
||||
};
|
||||
opt_trait_ref
|
||||
.and_then(|trait_ref| self_type_matches_expected_vid(fcx, trait_ref, expected_vid))
|
||||
|
@ -491,6 +491,7 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> {
|
||||
ty::Predicate::RegionOutlives(..) |
|
||||
ty::Predicate::WellFormed(..) |
|
||||
ty::Predicate::ObjectSafe(..) |
|
||||
ty::Predicate::ClosureKind(..) |
|
||||
ty::Predicate::TypeOutlives(..) => {
|
||||
None
|
||||
}
|
||||
|
@ -449,6 +449,7 @@ impl<'tcx> GetTypeParameterBounds<'tcx> for ty::GenericPredicates<'tcx> {
|
||||
ty::Predicate::RegionOutlives(..) |
|
||||
ty::Predicate::WellFormed(..) |
|
||||
ty::Predicate::ObjectSafe(..) |
|
||||
ty::Predicate::ClosureKind(..) |
|
||||
ty::Predicate::Projection(..) => {
|
||||
false
|
||||
}
|
||||
|
@ -849,6 +849,7 @@ impl<'a> Clean<WherePredicate> for ty::Predicate<'a> {
|
||||
Predicate::Projection(ref pred) => pred.clean(cx),
|
||||
Predicate::WellFormed(_) => panic!("not user writable"),
|
||||
Predicate::ObjectSafe(_) => panic!("not user writable"),
|
||||
Predicate::ClosureKind(..) => panic!("not user writable"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
22
src/test/compile-fail/closure-wrong-kind.rs
Normal file
22
src/test/compile-fail/closure-wrong-kind.rs
Normal file
@ -0,0 +1,22 @@
|
||||
// Copyright 2016 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.
|
||||
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
struct X;
|
||||
fn foo<T>(_: T) {}
|
||||
fn bar<T: Fn(u32)>(_: T) {}
|
||||
|
||||
fn main() {
|
||||
let x = X;
|
||||
let closure = |_| foo(x); //~ ERROR E0524
|
||||
bar(closure);
|
||||
}
|
Loading…
Reference in New Issue
Block a user