register the obligations from wf::implied_bounds

Fixes #42552.
Fixes #42545.
This commit is contained in:
Niko Matsakis 2017-06-14 14:25:41 -04:00
parent a65d8d3d71
commit 9fec4093df
3 changed files with 68 additions and 1 deletions

View File

@ -614,7 +614,8 @@ fn register_predicate(&self, obligation: traits::PredicateObligation<'tcx>) {
.register_predicate_obligation(self, obligation);
}
fn register_predicates(&self, obligations: Vec<traits::PredicateObligation<'tcx>>) {
fn register_predicates<I>(&self, obligations: I)
where I: IntoIterator<Item = traits::PredicateObligation<'tcx>> {
for obligation in obligations {
self.register_predicate(obligation);
}

View File

@ -471,6 +471,32 @@ fn implied_bounds(&mut self, body_id: ast::NodeId, ty: Ty<'tcx>, span: Span)
wf::obligations(self, self.fcx.param_env, body_id, ty, span)
.unwrap_or(vec![]);
// NB: All of these predicates *ought* to be easily proven
// true. In fact, their correctness is (mostly) implied by
// other parts of the program. However, in #42552, we had
// an annoying scenario where:
//
// - Some `T::Foo` gets normalized, resulting in a
// variable `_1` and a `T: Trait<Foo=_1>` constraint
// (not sure why it couldn't immediately get
// solved). This result of `_1` got cached.
// - These obligations were dropped on the floor here,
// rather than being registered.
// - Then later we would get a request to normalize
// `T::Foo` which would result in `_1` being used from
// the cache, but hence without the `T: Trait<Foo=_1>`
// constraint. As a result, `_1` never gets resolved,
// and we get an ICE (in dropck).
//
// Therefore, we register any predicates involving
// inference variables. We restrict ourselves to those
// involving inference variables both for efficiency and
// to avoids duplicate errors that otherwise show up.
self.fcx.register_predicates(
obligations.iter()
.filter(|o| o.predicate.has_infer_types())
.cloned());
// From the full set of obligations, just filter down to the
// region relationships.
implied_bounds.extend(

View File

@ -0,0 +1,40 @@
// 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.
// Regression test for an obscure issue with the projection cache.
fn into_iter<I: Iterator>(a: &I) -> Groups<I> {
Groups { _a: a }
}
pub struct Groups<'a, I: 'a> {
_a: &'a I,
}
impl<'a, I: Iterator> Iterator for Groups<'a, I> {
type Item = Group<'a, I>;
fn next(&mut self) -> Option<Self::Item> {
None
}
}
pub struct Group<'a, I: Iterator + 'a>
where I::Item: 'a // <-- needed to trigger ICE!
{
_phantom: &'a (),
_ice_trigger: I::Item, // <-- needed to trigger ICE!
}
fn main() {
let _ = into_iter(&[0].iter().map(|_| 0)).map(|grp| {
let _g = grp;
});
}