register the obligations from wf::implied_bounds
Fixes #42552. Fixes #42545.
This commit is contained in:
parent
a65d8d3d71
commit
9fec4093df
@ -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);
|
||||
}
|
||||
|
@ -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(
|
||||
|
40
src/test/run-pass/issue-42552.rs
Normal file
40
src/test/run-pass/issue-42552.rs
Normal 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;
|
||||
});
|
||||
}
|
Loading…
Reference in New Issue
Block a user