-
Notifications
You must be signed in to change notification settings - Fork 12.8k
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 inference sometimes fails to recognize implied bound in closure #42508
Comments
Hmm the fix isn't quite as straightforward as I thought. There is some annoying feedback here as well. In particular, in this case, we add a given like The simplest patch I have come up with thus far is that we could "refresh" the givens with the result of inference and then incorporate those into the free region map. The downside of this is that those new relationships might have affected inference in the first place, since the LUB of (e.g.) I don't think that there is much we can do about this in the current setup though. It seems best to not worry about this for now until we try to make region inference more general. |
Argh. I just realized that the fix I had planned is probably not going to cut it. The real fix here is probably going to have to wait for a better model of region constraints, one that can carry the inference environment along with it. Which just happens to be what I'm working on in another context, so I guess that's good. So what I did is to:
but my fear is that we may be able to synthesize false relations this way, through some sort of setup like: fn foo<'a, 'b>(...) { // note: a and b have no relation
callback(|x| {
// x: &'a &'b i32, so we get an implied relationship that `'a: 'b`.
//
// this ought to be impossible, but maybe the closure is never called.
})
} I haven't been able to construct such a scenario yet, but it seems plausible. |
Nightly now shows a warning when the work-around of explicitly specifying lifetime parameters in the call is used: warning: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
--> src/rules_and_declarations.rs:458:42
|
458 | parse_nested_block::<'i, 't, _, _, _>(input, move |input| parser.parse_block(prelude, input))
| ^^
|
::: src/parser.rs
|
791 | pub fn parse_nested_block<'i: 't, 't, F, T, E>(parser: &mut Parser<'i, 't>, parse: F)
| - the late bound lifetime parameter is introduced here
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #42868 <https://github.com/rust-lang/rust/issues/42868> #42868 (comment) claims that specifying them explicitly does nothing, but that’s not the case here. |
@SimonSapin You can make them early-bound e.g. by writing |
@eddyb That doesn’t seem to change anything. The full definition is: https://github.com/servo/rust-cssparser/blob/v0.19.0/src/parser.rs#L790-L793 pub fn parse_nested_block<'i: 't, 't, F, T, E>(parser: &mut Parser<'i, 't>, parse: F)
-> Result <T, ParseError<'i, E>>
where F: for<'tt> FnOnce(&mut Parser<'i, 'tt>) -> Result<T, ParseError<'i, E>> { |
Okay I wasn't clear enough: you have to do that for each lifetime. So |
I think you could use something like |
Work around warning from `late_bound_lifetime_arguments` lint The generic parsing functions require lifetime annotations to build because of rust-lang/rust#42508. However, this creates a warning from the `late_bound_lifetime_arguments` compatibility lint, described in rust-lang/rust#42868, because they have both early-bound and late-bound lifetime parameters. This PR works around this warning, in a functional but sub-optimal way. The result is quite verbose, and I didn't manage to "convince" rustc to think all lifetimes were early-bound at the `fn` definitions, but manages to avoid triggering both rust-lang/rust#42508 and the lint, by passing these closures via variables at each call-site. Fixes #254
Triage: this still does not compile |
Following a bug sample from @jdm, I encountered this bug. The compiler errors out in this code:
specifically it reports a "cannot infer" lifetime error, complaining about how the lifetime
'tt2
in the callf(input)
must be some lifetime'x
where'i: 'x
and'x: 'tt1
(where'tt1
is the lifetime that appears in the type ofinput
in the closure). The compiler is upset because it does not know that'i: 'tt1
. Those constraints are correct, but in fact the compiler should be able to deduce that'i: 'tt1
based on the type ofinput
, which is is&mut Parser<'i, 'tt1>
. The implied bounds for this type suggest that'i: 'tt1
. But we fail to see it.The problem is an interaction with inference. When we call
callback1()
here, we do not specify the lifetime, and so we create a variable'x
-- that is, the actual type ofinput
is&mut Parser<'x, 'tt2>
, where'x
is the inference variable. We then recognize that this means'x: 'tt2
, and we add a "given", which is this hacky bit of code in region inference. Then we infer that'x
must be'i
. But when we go to check that'x: 'tt2
, we substitute'x
to'i
, and then report an error, because we never added anything that tells us that'i: 'tt2
. If you specifycallback::<'i>
manually, it will work fine.The most straightforward fix is to use the given logic here too. The better fix is to retool this part of region inference to be more robust, which I am in the process of trying to plan out right now for other reasons anyhow.
The text was updated successfully, but these errors were encountered: