Skip to content

Commit 9fec409

Browse files
committed
register the obligations from wf::implied_bounds
Fixes #42552. Fixes #42545.
1 parent a65d8d3 commit 9fec409

File tree

3 files changed

+68
-1
lines changed

3 files changed

+68
-1
lines changed

src/librustc_typeck/check/mod.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -614,7 +614,8 @@ impl<'a, 'gcx, 'tcx> Inherited<'a, 'gcx, 'tcx> {
614614
.register_predicate_obligation(self, obligation);
615615
}
616616

617-
fn register_predicates(&self, obligations: Vec<traits::PredicateObligation<'tcx>>) {
617+
fn register_predicates<I>(&self, obligations: I)
618+
where I: IntoIterator<Item = traits::PredicateObligation<'tcx>> {
618619
for obligation in obligations {
619620
self.register_predicate(obligation);
620621
}

src/librustc_typeck/check/regionck.rs

+26
Original file line numberDiff line numberDiff line change
@@ -471,6 +471,32 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> {
471471
wf::obligations(self, self.fcx.param_env, body_id, ty, span)
472472
.unwrap_or(vec![]);
473473

474+
// NB: All of these predicates *ought* to be easily proven
475+
// true. In fact, their correctness is (mostly) implied by
476+
// other parts of the program. However, in #42552, we had
477+
// an annoying scenario where:
478+
//
479+
// - Some `T::Foo` gets normalized, resulting in a
480+
// variable `_1` and a `T: Trait<Foo=_1>` constraint
481+
// (not sure why it couldn't immediately get
482+
// solved). This result of `_1` got cached.
483+
// - These obligations were dropped on the floor here,
484+
// rather than being registered.
485+
// - Then later we would get a request to normalize
486+
// `T::Foo` which would result in `_1` being used from
487+
// the cache, but hence without the `T: Trait<Foo=_1>`
488+
// constraint. As a result, `_1` never gets resolved,
489+
// and we get an ICE (in dropck).
490+
//
491+
// Therefore, we register any predicates involving
492+
// inference variables. We restrict ourselves to those
493+
// involving inference variables both for efficiency and
494+
// to avoids duplicate errors that otherwise show up.
495+
self.fcx.register_predicates(
496+
obligations.iter()
497+
.filter(|o| o.predicate.has_infer_types())
498+
.cloned());
499+
474500
// From the full set of obligations, just filter down to the
475501
// region relationships.
476502
implied_bounds.extend(

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

+40
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
// Copyright 2016 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+
// Regression test for an obscure issue with the projection cache.
12+
13+
fn into_iter<I: Iterator>(a: &I) -> Groups<I> {
14+
Groups { _a: a }
15+
}
16+
17+
pub struct Groups<'a, I: 'a> {
18+
_a: &'a I,
19+
}
20+
21+
impl<'a, I: Iterator> Iterator for Groups<'a, I> {
22+
type Item = Group<'a, I>;
23+
fn next(&mut self) -> Option<Self::Item> {
24+
None
25+
}
26+
}
27+
28+
pub struct Group<'a, I: Iterator + 'a>
29+
where I::Item: 'a // <-- needed to trigger ICE!
30+
{
31+
_phantom: &'a (),
32+
_ice_trigger: I::Item, // <-- needed to trigger ICE!
33+
}
34+
35+
36+
fn main() {
37+
let _ = into_iter(&[0].iter().map(|_| 0)).map(|grp| {
38+
let _g = grp;
39+
});
40+
}

0 commit comments

Comments
 (0)