-
Notifications
You must be signed in to change notification settings - Fork 12.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
region_obligations not empty #51649
Comments
I get a similar error when compiling actix-web with the same arguments:
|
I can repro this with #![feature(nll)]
use std::ops::Deref;
struct A<T>(T);
impl<T> Deref for A<T> {
type Target = T;
fn deref(&self) -> &Self::Target {
unimplemented!()
}
}
|
Reproduced on 1.28.0-nightly (2a1c4ee 2018-06-25) running on x86_64-unknown-linux-gnu.
|
I don't think #![feature(nll)]
use std::ops::Deref;
pub struct Foo<T>(T);
impl<T> Deref for Foo<T> {
type Target = T;
fn deref(&self) -> &Self::Target {
&self.0
}
} |
I think I know the problem, but my old minimizations were no longer reproducing. Thanks all for the test cases. I'll try to get this fixed ASAP. |
I can't reproduce the ICE on master (but I can with nightly) — however, I suspect there is still a bug here. Gonna dig a bit deeper. |
Latest |
OK so let me leave some notes on what's going wrong. As I thought, the ICE is gone, but the underlying problem remains. Explaining the problem, I fear, is a bit complex. First: in some parts, the NLL type checker uses a kind of gruesome hack to extract its constraints. Essentially, it is building on the old inference context, which accumulates various region constraints in a format designed for the old lexical solver. NLL hijacks this by running the type-check, generating those old-style constraints, and then "taking" them and converting them to the new format. We do this "take" operation frequently so that we can isolate where in the program the constraint arose. So we do something like this to process some point
(Since my latest PR, we are doing this a lot less, and instead we are using queries to do this isolation; this is much better. But anyway.) There is however an implicit assumption that the constriants we get from If you add this diff, though, you will start to see ICEs again: modified src/librustc/traits/query/type_op/custom.rs
@@ -75,6 +75,14 @@ fn scrape_region_constraints<'gcx, 'tcx, R>(
) -> Fallible<(R, Option<Rc<Vec<QueryRegionConstraint<'tcx>>>>)> {
let mut fulfill_cx = TraitEngine::new(infcx.tcx);
let dummy_body_id = ObligationCause::dummy().body_id;
+
+ let pre_obligations = infcx.take_registered_region_obligations();
+ assert!(
+ pre_obligations.is_empty(),
+ "scrape_region_constraints: incoming region obligations = {:#?}",
+ pre_obligations,
+ );
+
let InferOk { value, obligations } = infcx.commit_if_ok(|_| op())?;
debug_assert!(obligations.iter().all(|o| o.cause.body_id == dummy_body_id));
fulfill_cx.register_predicate_obligations(infcx, obligations); |
So what code is causing these wayward region obligations? The answer is that a very early part of the NLL process is causing the problem. Specifically, when we are creating the universal regions table: rust/src/librustc_mir/borrow_check/nll/mod.rs Lines 64 to 65 in e3bf634
During that process, we compute the implied bounds from the argument types: rust/src/librustc_mir/borrow_check/nll/universal_regions.rs Lines 686 to 687 in e3bf634
That code winds up (in some weird cases involving associated types) having to solve some obligations: rust/src/librustc/infer/outlives/bounds.rs Lines 76 to 112 in e3bf634
Solving those obligations may produce the region-obligations that are causing us trouble. But if you look carefully at that code, you'll notice a weird thing: these obligations that we are solving are basically the requirements that are needed for types to be well-formed. But we should already be guaranteeing that the types are WF (I can't, anyway, think of an exception off the top of my head... my comment suggests that there may have been one...) I think my preference here would be to make a (canonicalized) query for computing the implied region bounds from a ty. This query would be invoked from That said, we should first check whether this is "dead code" here (that is, the error reporting code): rust/src/librustc/infer/outlives/bounds.rs Line 154 in e3bf634
|
So this ICE doesn't occur on master, therefore I'm going to defer it, but the code is still kinda wrong. I may try to fix it in "spare time". I haven't yet finishd my essay series on the best fix yet, so I could start there. :) |
I'd like to see this fixed by the RC though. |
I checked this; it only occurs if there are other (already reported) errors in the program. I was only able to trigger this in a single test. Without any error handling, it has the same behavior. |
…sakis Turn implied_outlives_bounds into a query Right now all this does is remove the error reporting in `implied_outlives_bounds`, which seems to work. Farming out full tests to Travis. For #51649. That issue is deferred so not sure what's next. r? @nikomatsakis
when compiling syn v0.14.2 with
rustc 1.28.0-nightly (523097979 2018-06-18)
and compiler flags:-Z borrowck=mir -Z polonius
, the compiler panicked.The text was updated successfully, but these errors were encountered: