Skip to content

Commit 35dca7f

Browse files
committed
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
2 parents 525aa61 + de82fc4 commit 35dca7f

File tree

19 files changed

+163
-75
lines changed

19 files changed

+163
-75
lines changed

src/librustc/diagnostics.rs

+1
Original file line numberDiff line numberDiff line change
@@ -1543,4 +1543,5 @@ register_diagnostics! {
15431543
E0490, // a value of type `..` is borrowed for too long
15441544
E0491, // in type `..`, reference has a longer lifetime than the data it...
15451545
E0495, // cannot infer an appropriate lifetime due to conflicting requirements
1546+
E0524, // expected a closure that implements `..` but this closure only implements `..`
15461547
}

src/librustc/middle/free_region.rs

+1
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ impl FreeRegionMap {
5959
ty::Predicate::Equate(..) |
6060
ty::Predicate::WellFormed(..) |
6161
ty::Predicate::ObjectSafe(..) |
62+
ty::Predicate::ClosureKind(..) |
6263
ty::Predicate::TypeOutlives(..) => {
6364
// No region bounds here
6465
}

src/librustc/traits/error_reporting.rs

+15
Original file line numberDiff line numberDiff line change
@@ -495,6 +495,21 @@ pub fn report_selection_error<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
495495
err.emit();
496496
}
497497

498+
ty::Predicate::ClosureKind(closure_def_id, kind) => {
499+
let found_kind = infcx.closure_kind(closure_def_id).unwrap();
500+
let closure_span = infcx.tcx.map.span_if_local(closure_def_id).unwrap();
501+
let mut err = struct_span_err!(
502+
infcx.tcx.sess, closure_span, E0524,
503+
"expected a closure that implements the `{}` trait, but this closure \
504+
only implements `{}`",
505+
kind,
506+
found_kind);
507+
err.span_note(
508+
obligation.cause.span,
509+
&format!("the requirement to implement `{}` derives from here", kind));
510+
err.emit();
511+
}
512+
498513
ty::Predicate::WellFormed(ty) => {
499514
// WF predicates cannot themselves make
500515
// errors. They can only block due to

src/librustc/traits/fulfill.rs

+15
Original file line numberDiff line numberDiff line change
@@ -652,6 +652,21 @@ fn process_predicate1<'a,'tcx>(selcx: &mut SelectionContext<'a,'tcx>,
652652
}
653653
}
654654

655+
ty::Predicate::ClosureKind(closure_def_id, kind) => {
656+
match selcx.infcx().closure_kind(closure_def_id) {
657+
Some(closure_kind) => {
658+
if closure_kind.extends(kind) {
659+
Ok(Some(vec![]))
660+
} else {
661+
Err(CodeSelectionError(Unimplemented))
662+
}
663+
}
664+
None => {
665+
Ok(None)
666+
}
667+
}
668+
}
669+
655670
ty::Predicate::WellFormed(ty) => {
656671
match ty::wf::obligations(selcx.infcx(), obligation.cause.body_id,
657672
ty, obligation.cause.span) {

src/librustc/traits/object_safety.rs

+2
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,7 @@ pub fn supertraits_reference_self<'tcx>(tcx: &TyCtxt<'tcx>,
165165
ty::Predicate::ObjectSafe(..) |
166166
ty::Predicate::TypeOutlives(..) |
167167
ty::Predicate::RegionOutlives(..) |
168+
ty::Predicate::ClosureKind(..) |
168169
ty::Predicate::Equate(..) => {
169170
false
170171
}
@@ -207,6 +208,7 @@ fn generics_require_sized_self<'tcx>(tcx: &TyCtxt<'tcx>,
207208
ty::Predicate::RegionOutlives(..) |
208209
ty::Predicate::WellFormed(..) |
209210
ty::Predicate::ObjectSafe(..) |
211+
ty::Predicate::ClosureKind(..) |
210212
ty::Predicate::TypeOutlives(..) => {
211213
false
212214
}

src/librustc/traits/select.rs

+31-74
Original file line numberDiff line numberDiff line change
@@ -198,9 +198,10 @@ enum SelectionCandidate<'tcx> {
198198
/// we found an applicable bound in the trait definition.
199199
ProjectionCandidate,
200200

201-
/// Implementation of a `Fn`-family trait by one of the
202-
/// anonymous types generated for a `||` expression.
203-
ClosureCandidate(/* closure */ DefId, &'tcx ty::ClosureSubsts<'tcx>),
201+
/// Implementation of a `Fn`-family trait by one of the anonymous types
202+
/// generated for a `||` expression. The ty::ClosureKind informs the
203+
/// confirmation step what ClosureKind obligation to emit.
204+
ClosureCandidate(/* closure */ DefId, &'tcx ty::ClosureSubsts<'tcx>, ty::ClosureKind),
204205

205206
/// Implementation of a `Fn`-family trait by one of the anonymous
206207
/// types generated for a fn pointer type (e.g., `fn(int)->int`)
@@ -321,75 +322,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
321322

322323
let stack = self.push_stack(TraitObligationStackList::empty(), obligation);
323324
match self.candidate_from_obligation(&stack)? {
324-
None => {
325-
self.consider_unification_despite_ambiguity(obligation);
326-
Ok(None)
327-
}
325+
None => Ok(None),
328326
Some(candidate) => Ok(Some(self.confirm_candidate(obligation, candidate)?)),
329327
}
330328
}
331329

332-
/// In the particular case of unboxed closure obligations, we can
333-
/// sometimes do some amount of unification for the
334-
/// argument/return types even though we can't yet fully match obligation.
335-
/// The particular case we are interesting in is an obligation of the form:
336-
///
337-
/// C : FnFoo<A>
338-
///
339-
/// where `C` is an unboxed closure type and `FnFoo` is one of the
340-
/// `Fn` traits. Because we know that users cannot write impls for closure types
341-
/// themselves, the only way that `C : FnFoo` can fail to match is under two
342-
/// conditions:
343-
///
344-
/// 1. The closure kind for `C` is not yet known, because inference isn't complete.
345-
/// 2. The closure kind for `C` *is* known, but doesn't match what is needed.
346-
/// For example, `C` may be a `FnOnce` closure, but a `Fn` closure is needed.
347-
///
348-
/// In either case, we always know what argument types are
349-
/// expected by `C`, no matter what kind of `Fn` trait it
350-
/// eventually matches. So we can go ahead and unify the argument
351-
/// types, even though the end result is ambiguous.
352-
///
353-
/// Note that this is safe *even if* the trait would never be
354-
/// matched (case 2 above). After all, in that case, an error will
355-
/// result, so it kind of doesn't matter what we do --- unifying
356-
/// the argument types can only be helpful to the user, because
357-
/// once they patch up the kind of closure that is expected, the
358-
/// argment types won't really change.
359-
fn consider_unification_despite_ambiguity(&mut self, obligation: &TraitObligation<'tcx>) {
360-
// Is this a `C : FnFoo(...)` trait reference for some trait binding `FnFoo`?
361-
match self.tcx().lang_items.fn_trait_kind(obligation.predicate.0.def_id()) {
362-
Some(_) => { }
363-
None => { return; }
364-
}
365-
366-
// Is the self-type a closure type? We ignore bindings here
367-
// because if it is a closure type, it must be a closure type from
368-
// within this current fn, and hence none of the higher-ranked
369-
// lifetimes can appear inside the self-type.
370-
let self_ty = self.infcx.shallow_resolve(*obligation.self_ty().skip_binder());
371-
let (closure_def_id, substs) = match self_ty.sty {
372-
ty::TyClosure(id, ref substs) => (id, substs),
373-
_ => { return; }
374-
};
375-
assert!(!substs.has_escaping_regions());
376-
377-
// It is OK to call the unnormalized variant here - this is only
378-
// reached for TyClosure: Fn inputs where the closure kind is
379-
// still unknown, which should only occur in typeck where the
380-
// closure type is already normalized.
381-
let closure_trait_ref = self.closure_trait_ref_unnormalized(obligation,
382-
closure_def_id,
383-
substs);
384-
385-
match self.confirm_poly_trait_refs(obligation.cause.clone(),
386-
obligation.predicate.to_poly_trait_ref(),
387-
closure_trait_ref) {
388-
Ok(()) => { }
389-
Err(_) => { /* Silently ignore errors. */ }
390-
}
391-
}
392-
393330
///////////////////////////////////////////////////////////////////////////
394331
// EVALUATION
395332
//
@@ -532,6 +469,21 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
532469
}
533470
}
534471
}
472+
473+
ty::Predicate::ClosureKind(closure_def_id, kind) => {
474+
match self.infcx.closure_kind(closure_def_id) {
475+
Some(closure_kind) => {
476+
if closure_kind.extends(kind) {
477+
EvaluatedToOk
478+
} else {
479+
EvaluatedToErr
480+
}
481+
}
482+
None => {
483+
EvaluatedToAmbig
484+
}
485+
}
486+
}
535487
}
536488
}
537489

@@ -1282,12 +1234,12 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
12821234
Some(closure_kind) => {
12831235
debug!("assemble_unboxed_candidates: closure_kind = {:?}", closure_kind);
12841236
if closure_kind.extends(kind) {
1285-
candidates.vec.push(ClosureCandidate(closure_def_id, substs));
1237+
candidates.vec.push(ClosureCandidate(closure_def_id, substs, kind));
12861238
}
12871239
}
12881240
None => {
12891241
debug!("assemble_unboxed_candidates: closure_kind not yet known");
1290-
candidates.ambiguous = true;
1242+
candidates.vec.push(ClosureCandidate(closure_def_id, substs, kind));
12911243
}
12921244
}
12931245

@@ -2071,9 +2023,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
20712023
Ok(VtableImpl(vtable_impl))
20722024
}
20732025

2074-
ClosureCandidate(closure_def_id, substs) => {
2026+
ClosureCandidate(closure_def_id, substs, kind) => {
20752027
let vtable_closure =
2076-
self.confirm_closure_candidate(obligation, closure_def_id, substs)?;
2028+
self.confirm_closure_candidate(obligation, closure_def_id, substs, kind)?;
20772029
Ok(VtableClosure(vtable_closure))
20782030
}
20792031

@@ -2430,7 +2382,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
24302382
fn confirm_closure_candidate(&mut self,
24312383
obligation: &TraitObligation<'tcx>,
24322384
closure_def_id: DefId,
2433-
substs: &ty::ClosureSubsts<'tcx>)
2385+
substs: &ty::ClosureSubsts<'tcx>,
2386+
kind: ty::ClosureKind)
24342387
-> Result<VtableClosureData<'tcx, PredicateObligation<'tcx>>,
24352388
SelectionError<'tcx>>
24362389
{
@@ -2441,7 +2394,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
24412394

24422395
let Normalized {
24432396
value: trait_ref,
2444-
obligations
2397+
mut obligations
24452398
} = self.closure_trait_ref(obligation, closure_def_id, substs);
24462399

24472400
debug!("confirm_closure_candidate(closure_def_id={:?}, trait_ref={:?}, obligations={:?})",
@@ -2453,6 +2406,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
24532406
obligation.predicate.to_poly_trait_ref(),
24542407
trait_ref)?;
24552408

2409+
obligations.push(Obligation::new(
2410+
obligation.cause.clone(),
2411+
ty::Predicate::ClosureKind(closure_def_id, kind)));
2412+
24562413
Ok(VtableClosureData {
24572414
closure_def_id: closure_def_id,
24582415
substs: substs.clone(),

src/librustc/traits/util.rs

+6
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,9 @@ impl<'a,'tcx> PredicateSet<'a,'tcx> {
6060

6161
ty::Predicate::ObjectSafe(data) =>
6262
ty::Predicate::ObjectSafe(data),
63+
64+
ty::Predicate::ClosureKind(closure_def_id, kind) =>
65+
ty::Predicate::ClosureKind(closure_def_id, kind)
6366
};
6467
self.set.insert(normalized_pred)
6568
}
@@ -156,6 +159,9 @@ impl<'cx, 'tcx> Elaborator<'cx, 'tcx> {
156159
ty::Predicate::Projection(..) => {
157160
// Nothing to elaborate in a projection predicate.
158161
}
162+
ty::Predicate::ClosureKind(..) => {
163+
// Nothing to elaborate when waiting for a closure's kind to be inferred.
164+
}
159165
ty::Predicate::RegionOutlives(..) |
160166
ty::Predicate::TypeOutlives(..) => {
161167
// Currently, we do not "elaborate" predicates like

src/librustc/ty/mod.rs

+12-1
Original file line numberDiff line numberDiff line change
@@ -832,6 +832,11 @@ pub enum Predicate<'tcx> {
832832

833833
/// trait must be object-safe
834834
ObjectSafe(DefId),
835+
836+
/// No direct syntax. May be thought of as `where T : FnFoo<...>` for some 'TypeSpace'
837+
/// substitutions `...` and T being a closure type. Satisfied (or refuted) once we know the
838+
/// closure's kind.
839+
ClosureKind(DefId, ClosureKind),
835840
}
836841

837842
impl<'tcx> Predicate<'tcx> {
@@ -921,6 +926,8 @@ impl<'tcx> Predicate<'tcx> {
921926
Predicate::WellFormed(data.subst(tcx, substs)),
922927
Predicate::ObjectSafe(trait_def_id) =>
923928
Predicate::ObjectSafe(trait_def_id),
929+
Predicate::ClosureKind(closure_def_id, kind) =>
930+
Predicate::ClosureKind(closure_def_id, kind),
924931
}
925932
}
926933
}
@@ -1108,6 +1115,9 @@ impl<'tcx> Predicate<'tcx> {
11081115
ty::Predicate::ObjectSafe(_trait_def_id) => {
11091116
vec![]
11101117
}
1118+
ty::Predicate::ClosureKind(_closure_def_id, _kind) => {
1119+
vec![]
1120+
}
11111121
};
11121122

11131123
// The only reason to collect into a vector here is that I was
@@ -1128,6 +1138,7 @@ impl<'tcx> Predicate<'tcx> {
11281138
Predicate::RegionOutlives(..) |
11291139
Predicate::WellFormed(..) |
11301140
Predicate::ObjectSafe(..) |
1141+
Predicate::ClosureKind(..) |
11311142
Predicate::TypeOutlives(..) => {
11321143
None
11331144
}
@@ -1783,7 +1794,7 @@ pub struct ItemSubsts<'tcx> {
17831794
pub substs: Substs<'tcx>,
17841795
}
17851796

1786-
#[derive(Clone, Copy, PartialOrd, Ord, PartialEq, Eq, Debug, RustcEncodable, RustcDecodable)]
1797+
#[derive(Clone, Copy, PartialOrd, Ord, PartialEq, Eq, Hash, Debug, RustcEncodable, RustcDecodable)]
17871798
pub enum ClosureKind {
17881799
// Warning: Ordering is significant here! The ordering is chosen
17891800
// because the trait Fn is a subtrait of FnMut and so in turn, and

src/librustc/ty/structural_impls.rs

+3
Original file line numberDiff line numberDiff line change
@@ -644,6 +644,8 @@ impl<'tcx> TypeFoldable<'tcx> for ty::Predicate<'tcx> {
644644
ty::Predicate::Projection(binder.fold_with(folder)),
645645
ty::Predicate::WellFormed(data) =>
646646
ty::Predicate::WellFormed(data.fold_with(folder)),
647+
ty::Predicate::ClosureKind(closure_def_id, kind) =>
648+
ty::Predicate::ClosureKind(closure_def_id, kind),
647649
ty::Predicate::ObjectSafe(trait_def_id) =>
648650
ty::Predicate::ObjectSafe(trait_def_id),
649651
}
@@ -657,6 +659,7 @@ impl<'tcx> TypeFoldable<'tcx> for ty::Predicate<'tcx> {
657659
ty::Predicate::TypeOutlives(ref binder) => binder.visit_with(visitor),
658660
ty::Predicate::Projection(ref binder) => binder.visit_with(visitor),
659661
ty::Predicate::WellFormed(data) => data.visit_with(visitor),
662+
ty::Predicate::ClosureKind(_closure_def_id, _kind) => false,
660663
ty::Predicate::ObjectSafe(_trait_def_id) => false,
661664
}
662665
}

src/librustc/ty/util.rs

+1
Original file line numberDiff line numberDiff line change
@@ -301,6 +301,7 @@ impl<'tcx> TyCtxt<'tcx> {
301301
ty::Predicate::Equate(..) |
302302
ty::Predicate::WellFormed(..) |
303303
ty::Predicate::ObjectSafe(..) |
304+
ty::Predicate::ClosureKind(..) |
304305
ty::Predicate::RegionOutlives(..) => {
305306
None
306307
}

src/librustc/ty/wf.rs

+3
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,8 @@ pub fn predicate_obligations<'a,'tcx>(infcx: &InferCtxt<'a, 'tcx>,
9292
}
9393
ty::Predicate::ObjectSafe(_) => {
9494
}
95+
ty::Predicate::ClosureKind(..) => {
96+
}
9597
}
9698

9799
wf.normalize()
@@ -155,6 +157,7 @@ pub fn implied_bounds<'a,'tcx>(
155157
ty::Predicate::Trait(..) |
156158
ty::Predicate::Equate(..) |
157159
ty::Predicate::Projection(..) |
160+
ty::Predicate::ClosureKind(..) |
158161
ty::Predicate::ObjectSafe(..) =>
159162
vec![],
160163

src/librustc/util/ppaux.rs

+18
Original file line numberDiff line numberDiff line change
@@ -467,6 +467,9 @@ impl<'tcx> fmt::Debug for ty::Predicate<'tcx> {
467467
ty::Predicate::ObjectSafe(trait_def_id) => {
468468
write!(f, "ObjectSafe({:?})", trait_def_id)
469469
}
470+
ty::Predicate::ClosureKind(closure_def_id, kind) => {
471+
write!(f, "ClosureKind({:?}, {:?})", closure_def_id, kind)
472+
}
470473
}
471474
}
472475
}
@@ -1039,6 +1042,16 @@ impl<'tcx> fmt::Display for ty::ProjectionTy<'tcx> {
10391042
}
10401043
}
10411044

1045+
impl fmt::Display for ty::ClosureKind {
1046+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1047+
match *self {
1048+
ty::ClosureKind::Fn => write!(f, "Fn"),
1049+
ty::ClosureKind::FnMut => write!(f, "FnMut"),
1050+
ty::ClosureKind::FnOnce => write!(f, "FnOnce"),
1051+
}
1052+
}
1053+
}
1054+
10421055
impl<'tcx> fmt::Display for ty::Predicate<'tcx> {
10431056
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10441057
match *self {
@@ -1052,6 +1065,11 @@ impl<'tcx> fmt::Display for ty::Predicate<'tcx> {
10521065
ty::tls::with(|tcx| {
10531066
write!(f, "the trait `{}` is object-safe", tcx.item_path_str(trait_def_id))
10541067
}),
1068+
ty::Predicate::ClosureKind(closure_def_id, kind) =>
1069+
ty::tls::with(|tcx| {
1070+
write!(f, "the closure `{}` implements the trait `{}`",
1071+
tcx.item_path_str(closure_def_id), kind)
1072+
}),
10551073
}
10561074
}
10571075
}

0 commit comments

Comments
 (0)