Skip to content

Commit ff8fee1

Browse files
committed
Auto merge of #26147 - arielb1:assoc-trans, r=nikomatsakis
Fixes #25700 r? @nikomatsakis
2 parents 9cc0b22 + 21fd312 commit ff8fee1

File tree

9 files changed

+231
-107
lines changed

9 files changed

+231
-107
lines changed

src/librustc/middle/traits/mod.rs

+34-64
Original file line numberDiff line numberDiff line change
@@ -245,7 +245,7 @@ pub enum Vtable<'tcx, N> {
245245
/// Vtable automatically generated for a closure. The def ID is the ID
246246
/// of the closure expression. This is a `VtableImpl` in spirit, but the
247247
/// impl is generated by the compiler and does not appear in the source.
248-
VtableClosure(ast::DefId, subst::Substs<'tcx>),
248+
VtableClosure(VtableClosureData<'tcx, N>),
249249

250250
/// Same as above, but for a fn pointer type with the given signature.
251251
VtableFnPointer(ty::Ty<'tcx>),
@@ -268,7 +268,16 @@ pub struct VtableImplData<'tcx, N> {
268268
pub nested: Vec<N>
269269
}
270270

271-
#[derive(Debug,Clone)]
271+
#[derive(Clone, PartialEq, Eq)]
272+
pub struct VtableClosureData<'tcx, N> {
273+
pub closure_def_id: ast::DefId,
274+
pub substs: subst::Substs<'tcx>,
275+
/// Nested obligations. This can be non-empty if the closure
276+
/// signature contains associated types.
277+
pub nested: Vec<N>
278+
}
279+
280+
#[derive(Debug, Clone)]
272281
pub struct VtableDefaultImplData<N> {
273282
pub trait_def_id: ast::DefId,
274283
pub nested: Vec<N>
@@ -304,12 +313,12 @@ pub fn predicates_for_generics<'tcx>(tcx: &ty::ctxt<'tcx>,
304313
/// `bound` or is not known to meet bound (note that this is
305314
/// conservative towards *no impl*, which is the opposite of the
306315
/// `evaluate` methods).
307-
pub fn evaluate_builtin_bound<'a,'tcx>(infcx: &InferCtxt<'a,'tcx>,
308-
typer: &ty::ClosureTyper<'tcx>,
309-
ty: Ty<'tcx>,
310-
bound: ty::BuiltinBound,
311-
span: Span)
312-
-> SelectionResult<'tcx, ()>
316+
pub fn type_known_to_meet_builtin_bound<'a,'tcx>(infcx: &InferCtxt<'a,'tcx>,
317+
typer: &ty::ClosureTyper<'tcx>,
318+
ty: Ty<'tcx>,
319+
bound: ty::BuiltinBound,
320+
span: Span)
321+
-> bool
313322
{
314323
debug!("type_known_to_meet_builtin_bound(ty={}, bound={:?})",
315324
ty.repr(infcx.tcx),
@@ -327,61 +336,18 @@ pub fn evaluate_builtin_bound<'a,'tcx>(infcx: &InferCtxt<'a,'tcx>,
327336
// Note: we only assume something is `Copy` if we can
328337
// *definitively* show that it implements `Copy`. Otherwise,
329338
// assume it is move; linear is always ok.
330-
let result = match fulfill_cx.select_all_or_error(infcx, typer) {
331-
Ok(()) => Ok(Some(())), // Success, we know it implements Copy.
332-
Err(errors) => {
333-
// If there were any hard errors, propagate an arbitrary
334-
// one of those. If no hard errors at all, report
335-
// ambiguity.
336-
let sel_error =
337-
errors.iter()
338-
.filter_map(|err| {
339-
match err.code {
340-
CodeAmbiguity => None,
341-
CodeSelectionError(ref e) => Some(e.clone()),
342-
CodeProjectionError(_) => {
343-
infcx.tcx.sess.span_bug(
344-
span,
345-
"projection error while selecting?")
346-
}
347-
}
348-
})
349-
.next();
350-
match sel_error {
351-
None => { Ok(None) }
352-
Some(e) => { Err(e) }
353-
}
354-
}
355-
};
356-
357-
debug!("type_known_to_meet_builtin_bound: ty={} bound={:?} result={:?}",
358-
ty.repr(infcx.tcx),
359-
bound,
360-
result);
361-
362-
result
363-
}
364-
365-
pub fn type_known_to_meet_builtin_bound<'a,'tcx>(infcx: &InferCtxt<'a,'tcx>,
366-
typer: &ty::ClosureTyper<'tcx>,
367-
ty: Ty<'tcx>,
368-
bound: ty::BuiltinBound,
369-
span: Span)
370-
-> bool
371-
{
372-
match evaluate_builtin_bound(infcx, typer, ty, bound, span) {
373-
Ok(Some(())) => {
374-
// definitely impl'd
339+
match fulfill_cx.select_all_or_error(infcx, typer) {
340+
Ok(()) => {
341+
debug!("type_known_to_meet_builtin_bound: ty={} bound={:?} success",
342+
ty.repr(infcx.tcx),
343+
bound);
375344
true
376345
}
377-
Ok(None) => {
378-
// ambiguous: if coherence check was successful, shouldn't
379-
// happen, but we might have reported an error and been
380-
// soldering on, so just treat this like not implemented
381-
false
382-
}
383-
Err(_) => {
384-
// errors: not implemented.
346+
Err(e) => {
347+
debug!("type_known_to_meet_builtin_bound: ty={} bound={:?} errors={}",
348+
ty.repr(infcx.tcx),
349+
bound,
350+
e.repr(infcx.tcx));
385351
false
386352
}
387353
}
@@ -545,8 +511,8 @@ impl<'tcx, N> Vtable<'tcx, N> {
545511
VtableParam(n) => n,
546512
VtableBuiltin(i) => i.nested,
547513
VtableDefaultImpl(d) => d.nested,
548-
VtableObject(_) | VtableFnPointer(..) |
549-
VtableClosure(..) => vec![]
514+
VtableClosure(c) => c.nested,
515+
VtableObject(_) | VtableFnPointer(..) => vec![]
550516
}
551517
}
552518

@@ -567,7 +533,11 @@ impl<'tcx, N> Vtable<'tcx, N> {
567533
nested: d.nested.into_iter().map(f).collect()
568534
}),
569535
VtableFnPointer(f) => VtableFnPointer(f),
570-
VtableClosure(d, s) => VtableClosure(d, s),
536+
VtableClosure(c) => VtableClosure(VtableClosureData {
537+
closure_def_id: c.closure_def_id,
538+
substs: c.substs,
539+
nested: c.nested.into_iter().map(f).collect()
540+
})
571541
}
572542
}
573543
}

src/librustc/middle/traits/project.rs

+30-14
Original file line numberDiff line numberDiff line change
@@ -17,15 +17,15 @@ use super::ObligationCause;
1717
use super::PredicateObligation;
1818
use super::SelectionContext;
1919
use super::SelectionError;
20+
use super::VtableClosureData;
2021
use super::VtableImplData;
2122
use super::util;
2223

2324
use middle::infer;
24-
use middle::subst::{Subst, Substs};
25+
use middle::subst::Subst;
2526
use middle::ty::{self, AsPredicate, ReferencesError, RegionEscape,
2627
HasProjectionTypes, ToPolyTraitRef, Ty};
2728
use middle::ty_fold::{self, TypeFoldable, TypeFolder};
28-
use syntax::ast;
2929
use syntax::parse::token;
3030
use util::common::FN_OUTPUT_NAME;
3131
use util::ppaux::Repr;
@@ -57,7 +57,7 @@ pub struct MismatchedProjectionTypes<'tcx> {
5757
enum ProjectionTyCandidate<'tcx> {
5858
ParamEnv(ty::PolyProjectionPredicate<'tcx>),
5959
Impl(VtableImplData<'tcx, PredicateObligation<'tcx>>),
60-
Closure(ast::DefId, Substs<'tcx>),
60+
Closure(VtableClosureData<'tcx, PredicateObligation<'tcx>>),
6161
FnPointer(Ty<'tcx>),
6262
}
6363

@@ -162,11 +162,16 @@ fn consider_unification_despite_ambiguity<'cx,'tcx>(selcx: &mut SelectionContext
162162
self_ty,
163163
&closure_type.sig,
164164
util::TupleArgumentsFlag::No);
165+
// We don't have to normalize the return type here - this is only
166+
// reached for TyClosure: Fn inputs where the closure kind is
167+
// still unknown, which should only occur in typeck where the
168+
// closure type is already normalized.
165169
let (ret_type, _) =
166170
infcx.replace_late_bound_regions_with_fresh_var(
167171
obligation.cause.span,
168172
infer::AssocTypeProjection(obligation.predicate.projection_ty.item_name),
169173
&ty::Binder(ret_type));
174+
170175
debug!("consider_unification_despite_ambiguity: ret_type={:?}",
171176
ret_type.repr(selcx.tcx()));
172177
let origin = infer::RelateOutputImplTypes(obligation.cause.span);
@@ -686,9 +691,9 @@ fn assemble_candidates_from_impls<'cx,'tcx>(
686691
selcx, obligation, obligation_trait_ref, candidate_set,
687692
data.object_ty);
688693
}
689-
super::VtableClosure(closure_def_id, substs) => {
694+
super::VtableClosure(data) => {
690695
candidate_set.vec.push(
691-
ProjectionTyCandidate::Closure(closure_def_id, substs));
696+
ProjectionTyCandidate::Closure(data));
692697
}
693698
super::VtableFnPointer(fn_type) => {
694699
candidate_set.vec.push(
@@ -755,8 +760,8 @@ fn confirm_candidate<'cx,'tcx>(
755760
confirm_impl_candidate(selcx, obligation, impl_vtable)
756761
}
757762

758-
ProjectionTyCandidate::Closure(def_id, substs) => {
759-
confirm_closure_candidate(selcx, obligation, def_id, &substs)
763+
ProjectionTyCandidate::Closure(closure_vtable) => {
764+
confirm_closure_candidate(selcx, obligation, closure_vtable)
760765
}
761766

762767
ProjectionTyCandidate::FnPointer(fn_type) => {
@@ -779,13 +784,24 @@ fn confirm_fn_pointer_candidate<'cx,'tcx>(
779784
fn confirm_closure_candidate<'cx,'tcx>(
780785
selcx: &mut SelectionContext<'cx,'tcx>,
781786
obligation: &ProjectionTyObligation<'tcx>,
782-
closure_def_id: ast::DefId,
783-
substs: &Substs<'tcx>)
787+
vtable: VtableClosureData<'tcx, PredicateObligation<'tcx>>)
784788
-> (Ty<'tcx>, Vec<PredicateObligation<'tcx>>)
785789
{
786790
let closure_typer = selcx.closure_typer();
787-
let closure_type = closure_typer.closure_type(closure_def_id, substs);
788-
confirm_callable_candidate(selcx, obligation, &closure_type.sig, util::TupleArgumentsFlag::No)
791+
let closure_type = closure_typer.closure_type(vtable.closure_def_id, &vtable.substs);
792+
let Normalized {
793+
value: closure_type,
794+
mut obligations
795+
} = normalize_with_depth(selcx,
796+
obligation.cause.clone(),
797+
obligation.recursion_depth+1,
798+
&closure_type);
799+
let (ty, mut cc_obligations) = confirm_callable_candidate(selcx,
800+
obligation,
801+
&closure_type.sig,
802+
util::TupleArgumentsFlag::No);
803+
obligations.append(&mut cc_obligations);
804+
(ty, obligations)
789805
}
790806

791807
fn confirm_callable_candidate<'cx,'tcx>(
@@ -797,7 +813,7 @@ fn confirm_callable_candidate<'cx,'tcx>(
797813
{
798814
let tcx = selcx.tcx();
799815

800-
debug!("confirm_closure_candidate({},{})",
816+
debug!("confirm_callable_candidate({},{})",
801817
obligation.repr(tcx),
802818
fn_sig.repr(tcx));
803819

@@ -921,8 +937,8 @@ impl<'tcx> Repr<'tcx> for ProjectionTyCandidate<'tcx> {
921937
format!("ParamEnv({})", data.repr(tcx)),
922938
ProjectionTyCandidate::Impl(ref data) =>
923939
format!("Impl({})", data.repr(tcx)),
924-
ProjectionTyCandidate::Closure(ref a, ref b) =>
925-
format!("Closure(({},{}))", a.repr(tcx), b.repr(tcx)),
940+
ProjectionTyCandidate::Closure(ref data) =>
941+
format!("Closure({})", data.repr(tcx)),
926942
ProjectionTyCandidate::FnPointer(a) =>
927943
format!("FnPointer(({}))", a.repr(tcx)),
928944
}

src/librustc/middle/traits/select.rs

+53-19
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,8 @@ use super::Selection;
3131
use super::SelectionResult;
3232
use super::{VtableBuiltin, VtableImpl, VtableParam, VtableClosure,
3333
VtableFnPointer, VtableObject, VtableDefaultImpl};
34-
use super::{VtableImplData, VtableObjectData, VtableBuiltinData, VtableDefaultImplData};
34+
use super::{VtableImplData, VtableObjectData, VtableBuiltinData,
35+
VtableClosureData, VtableDefaultImplData};
3536
use super::object_safety;
3637
use super::util;
3738

@@ -355,7 +356,14 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
355356
};
356357
assert!(!substs.has_escaping_regions());
357358

358-
let closure_trait_ref = self.closure_trait_ref(obligation, closure_def_id, substs);
359+
// It is OK to call the unnormalized variant here - this is only
360+
// reached for TyClosure: Fn inputs where the closure kind is
361+
// still unknown, which should only occur in typeck where the
362+
// closure type is already normalized.
363+
let closure_trait_ref = self.closure_trait_ref_unnormalized(obligation,
364+
closure_def_id,
365+
substs);
366+
359367
match self.confirm_poly_trait_refs(obligation.cause.clone(),
360368
obligation.predicate.to_poly_trait_ref(),
361369
closure_trait_ref) {
@@ -2001,8 +2009,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
20012009
}
20022010

20032011
ClosureCandidate(closure_def_id, substs) => {
2004-
try!(self.confirm_closure_candidate(obligation, closure_def_id, &substs));
2005-
Ok(VtableClosure(closure_def_id, substs))
2012+
let vtable_closure =
2013+
try!(self.confirm_closure_candidate(obligation, closure_def_id, &substs));
2014+
Ok(VtableClosure(vtable_closure))
20062015
}
20072016

20082017
BuiltinObjectCandidate => {
@@ -2343,24 +2352,33 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
23432352
obligation: &TraitObligation<'tcx>,
23442353
closure_def_id: ast::DefId,
23452354
substs: &Substs<'tcx>)
2346-
-> Result<(),SelectionError<'tcx>>
2355+
-> Result<VtableClosureData<'tcx, PredicateObligation<'tcx>>,
2356+
SelectionError<'tcx>>
23472357
{
23482358
debug!("confirm_closure_candidate({},{},{})",
23492359
obligation.repr(self.tcx()),
23502360
closure_def_id.repr(self.tcx()),
23512361
substs.repr(self.tcx()));
23522362

2353-
let trait_ref = self.closure_trait_ref(obligation,
2354-
closure_def_id,
2355-
substs);
2363+
let Normalized {
2364+
value: trait_ref,
2365+
obligations
2366+
} = self.closure_trait_ref(obligation, closure_def_id, substs);
23562367

2357-
debug!("confirm_closure_candidate(closure_def_id={}, trait_ref={})",
2368+
debug!("confirm_closure_candidate(closure_def_id={}, trait_ref={}, obligations={})",
23582369
closure_def_id.repr(self.tcx()),
2359-
trait_ref.repr(self.tcx()));
2370+
trait_ref.repr(self.tcx()),
2371+
obligations.repr(self.tcx()));
2372+
2373+
try!(self.confirm_poly_trait_refs(obligation.cause.clone(),
2374+
obligation.predicate.to_poly_trait_ref(),
2375+
trait_ref));
23602376

2361-
self.confirm_poly_trait_refs(obligation.cause.clone(),
2362-
obligation.predicate.to_poly_trait_ref(),
2363-
trait_ref)
2377+
Ok(VtableClosureData {
2378+
closure_def_id: closure_def_id,
2379+
substs: substs.clone(),
2380+
nested: obligations
2381+
})
23642382
}
23652383

23662384
/// In the case of closure types and fn pointers,
@@ -2819,11 +2837,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
28192837
}
28202838
}
28212839

2822-
fn closure_trait_ref(&self,
2823-
obligation: &TraitObligation<'tcx>,
2824-
closure_def_id: ast::DefId,
2825-
substs: &Substs<'tcx>)
2826-
-> ty::PolyTraitRef<'tcx>
2840+
fn closure_trait_ref_unnormalized(&mut self,
2841+
obligation: &TraitObligation<'tcx>,
2842+
closure_def_id: ast::DefId,
2843+
substs: &Substs<'tcx>)
2844+
-> ty::PolyTraitRef<'tcx>
28272845
{
28282846
let closure_type = self.closure_typer.closure_type(closure_def_id, substs);
28292847
let ty::Binder((trait_ref, _)) =
@@ -2832,7 +2850,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
28322850
obligation.predicate.0.self_ty(), // (1)
28332851
&closure_type.sig,
28342852
util::TupleArgumentsFlag::No);
2835-
28362853
// (1) Feels icky to skip the binder here, but OTOH we know
28372854
// that the self-type is an unboxed closure type and hence is
28382855
// in fact unparameterized (or at least does not reference any
@@ -2842,6 +2859,23 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
28422859
ty::Binder(trait_ref)
28432860
}
28442861

2862+
fn closure_trait_ref(&mut self,
2863+
obligation: &TraitObligation<'tcx>,
2864+
closure_def_id: ast::DefId,
2865+
substs: &Substs<'tcx>)
2866+
-> Normalized<'tcx, ty::PolyTraitRef<'tcx>>
2867+
{
2868+
let trait_ref = self.closure_trait_ref_unnormalized(
2869+
obligation, closure_def_id, substs);
2870+
2871+
// A closure signature can contain associated types which
2872+
// must be normalized.
2873+
normalize_with_depth(self,
2874+
obligation.cause.clone(),
2875+
obligation.recursion_depth+1,
2876+
&trait_ref)
2877+
}
2878+
28452879
/// Returns the obligations that are implied by instantiating an
28462880
/// impl or trait. The obligations are substituted and fully
28472881
/// normalized. This is used when confirming an impl or default

0 commit comments

Comments
 (0)