Description
Spawned off of #55637 (comment)
Update: I had updated this description with a demo. But reading over it now, I don't know why I thought the "demo" had anything to do with this bug as described. That is, I believe demo is showing a bug, but not necessarily this bug...
Nonetheless, I'm not going to spawn off yet another bug quite yet. Instead, I am just going to mark the demo as wrong-headed and try to spend some time exploring _
itself later.
Potentially wrong-headed demo
Here's a demo of the problem (play):
#![allow(dead_code, unused_mut)]
type Pair<T> = (T, T);
fn static_to_a_to_static_through_tyvar<'a>(x: &'a u32, s: &'static u32) -> &'static u32 {
let (mut y, mut _z): Pair<&u32> = (s, x);
// I should be able to add the call to `swap` below at whim based
// on the above type annotation, which should coerce both `s` and
// `x` to `&'1 u32` (and then `'1` should be inferred to be `'a`).
// ::std::mem::swap(&mut y, &mut _z);
// Likewise, the same rules that caused `y` and `_z` to have the
// same `&'1 u32` type should likewise cause a borrow-check error
// at this attempt to return a `&'static u32`.
y
}
fn main() {
static_to_a_to_static_through_tyvar(&3, &4);
}
Under AST-borrowck, it errors.
Under NLL migration mode, it errors.
- Update: no, it was accepted there (just like NLL below).
Under #![feature(nll)]
, is is accepted (play), and should not be.
More details below:
PR #55637 fixes #55552 by ignoring occurrences of _
that it finds as it descends through the type.
A potential problem is that type variables can be repeated, e.g. in a type Foo<T> = (T, T)
and an annotation like Foo<_>
The problem then becomes: Is there some way that could lead to a scenario where one of the occurrences of the type variables gets unified with something that has a lifetime constraint like 'a
, and the other occurrence of the type variable is unchecked (due to #55637) but ends up missing a case where it should have imposed that constraint on an expression whose type has a different incompatible lifetime...
Activity
pnkfelix commentedon Nov 8, 2018
putting on Release milestone, to ensure we actually find out whether this is even a problem (i.e. make some examples of soundness bugs that are actually getting through due to this) before we do the Release.
pnkfelix commentedon Nov 9, 2018
Oddly, so far the instances of this problem that I have been able to identify are not leveraging the code injected in PR #55637 ...
nikomatsakis commentedon Nov 13, 2018
Removing from the milestone. This feels sufficiently obscure that it should not be categorized as a Release Blocker
pnkfelix commentedon Dec 10, 2018
Hmm. I claimed above that the example from above (play) causes an error to be signalled under migration mode.
But it appears that this was simply false; migration mode has (incorrectly) accepted the (potentially wrong-headed) "example" since the latter half of October. I must have been failing to test it properly.
So that's something that should be fixed. It should probably get its own separate bug, even.
pnkfelix commentedon Dec 11, 2018
An interesting twist: If I enable
#![feature(type_ascription)]
then the following variant of the (potentially wrong-headed) "example" is rejected by the compiler (play):From what I can tell from the MIR .nll dump, the set of constraints on the regions has changed in this variations, but the other big change is this: in the case where the compiler is "misbehaving" and accepting the code, we see this ascription statement:
In the case where the compiler is correctly rejecting the code, we see this ascription statement:
The only difference between those two lines, apart from column-span information, is the
+
variance (covariant) for the first case and theo
variance (invariant) for the second case. Interesting!pnkfelix commentedon Dec 11, 2018
Sweet, I think the fix to the bug illustrated by the "potentially wrong-headed demo" is actually trivial: there was a single type-ascription call that used
Covariant
that (maybe) should instead have usedInvariant
.(And furthermore, I think the demo itself probably illustrates that the problem I was originally worried about, namely soundness bugs injected by repeated wildcards, most likely do not arise)
let _: T = RHS
be synonymous withlet _ = RHS: T
? #56715pnkfelix commentedon Dec 17, 2018
Further discussion in issue #56715 led me to conclude that the fix proposed above (of changing an
Variance::Covariant
toVariance::Invariant
) is not the right way to resolve this.So I'll take a step back and won't continue to assume that the solution lies down that path.
Incidentally, there have been other proposals (to resolve other issues) that might just as well address the problem pointed out in the "potentially wrong-headed demo."
pnkfelix commentedon Dec 19, 2018
I now have a new approach issue-54943-with-fix-for-55748, built upon the foundation of PR #55937, that rejects the demo from this issue. Yay!
The heart of this approach, which I should document, is based on an insight that came from a recent conversation with @nikomatsakis :
Enforcing these two distinct constraints from a type annotation (or rather, adding the second constraint since we already had the first one) is what issue-54943-with-fix-for-55748 is doing.
21 remaining items