Skip to content

Commit 2574f31

Browse files
nikomatsakisalexcrichton
authored andcommitted
save the subobligations as well
1 parent 477e9f0 commit 2574f31

File tree

2 files changed

+86
-6
lines changed

2 files changed

+86
-6
lines changed

src/librustc/traits/project.rs

+12-6
Original file line numberDiff line numberDiff line change
@@ -462,13 +462,19 @@ fn opt_normalize_projection_type<'a, 'b, 'gcx, 'tcx>(
462462
selcx.infcx().report_overflow_error(&obligation, false);
463463
}
464464
Err(ProjectionCacheEntry::NormalizedTy(ty)) => {
465-
// If we find the value in the cache, then the obligations
466-
// have already been returned from the previous entry (and
467-
// should therefore have been honored).
465+
// If we find the value in the cache, then return it along
466+
// with the obligations that went along with it. Note
467+
// that, when using a fulfillment context, these
468+
// obligations could in principle be ignored: they have
469+
// already been registered when the cache entry was
470+
// created (and hence the new ones will quickly be
471+
// discarded as duplicated). But when doing trait
472+
// evaluation this is not the case, and dropping the trait
473+
// evaluations can causes ICEs (e.g. #43132).
468474
debug!("opt_normalize_projection_type: \
469475
found normalized ty `{:?}`",
470476
ty);
471-
return Some(NormalizedTy { value: ty, obligations: vec![] });
477+
return Some(ty);
472478
}
473479
Err(ProjectionCacheEntry::Error) => {
474480
debug!("opt_normalize_projection_type: \
@@ -1326,7 +1332,7 @@ enum ProjectionCacheEntry<'tcx> {
13261332
InProgress,
13271333
Ambiguous,
13281334
Error,
1329-
NormalizedTy(Ty<'tcx>),
1335+
NormalizedTy(NormalizedTy<'tcx>),
13301336
}
13311337

13321338
// NB: intentionally not Clone
@@ -1374,7 +1380,7 @@ impl<'tcx> ProjectionCache<'tcx> {
13741380
fn complete(&mut self, key: ty::ProjectionTy<'tcx>, value: &NormalizedTy<'tcx>) {
13751381
debug!("ProjectionCacheEntry::complete: adding cache entry: key={:?}, value={:?}",
13761382
key, value);
1377-
let fresh_key = self.map.insert(key, ProjectionCacheEntry::NormalizedTy(value.value));
1383+
let fresh_key = self.map.insert(key, ProjectionCacheEntry::NormalizedTy(value.clone()));
13781384
assert!(!fresh_key, "never started projecting `{:?}`", key);
13791385
}
13801386

src/test/run-pass/issue-43132.rs

+74
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
#![allow(unused)]
12+
13+
fn main() {
14+
}
15+
16+
fn foo() {
17+
let b = mk::<
18+
Forward<(Box<Future<Error = u32>>,)>,
19+
>();
20+
b.map_err(|_| ()).join();
21+
}
22+
23+
fn mk<T>() -> T {
24+
loop {}
25+
}
26+
27+
impl<I: Future<Error = E>, E> Future for (I,) {
28+
type Error = E;
29+
}
30+
31+
struct Forward<T: Future> {
32+
_a: T,
33+
}
34+
35+
impl<T: Future> Future for Forward<T>
36+
where
37+
T::Error: From<u32>,
38+
{
39+
type Error = T::Error;
40+
}
41+
42+
trait Future {
43+
type Error;
44+
45+
fn map_err<F, E>(self, _: F) -> (Self, F)
46+
where
47+
F: FnOnce(Self::Error) -> E,
48+
Self: Sized,
49+
{
50+
loop {}
51+
}
52+
53+
fn join(self) -> (MaybeDone<Self>, ())
54+
where
55+
Self: Sized,
56+
{
57+
loop {}
58+
}
59+
}
60+
61+
impl<S: ?Sized + Future> Future for Box<S> {
62+
type Error = S::Error;
63+
}
64+
65+
enum MaybeDone<A: Future> {
66+
_Done(A::Error),
67+
}
68+
69+
impl<U, A: Future, F> Future for (A, F)
70+
where
71+
F: FnOnce(A::Error) -> U,
72+
{
73+
type Error = U;
74+
}

0 commit comments

Comments
 (0)