2016-08-23 00:40:51 -05:00
|
|
|
#![allow(dead_code)]
|
|
|
|
|
2016-08-29 07:03:57 -05:00
|
|
|
fn non_elidable<'a, 'b>(a: &'a u8, b: &'b u8) -> &'a u8 {
|
|
|
|
a
|
|
|
|
}
|
2016-08-23 00:40:51 -05:00
|
|
|
|
2020-01-27 18:13:45 -06:00
|
|
|
// The incorrect case without `for<'a>` is tested for in `rfc1623-2.rs`
|
|
|
|
static NON_ELIDABLE_FN: &for<'a> fn(&'a u8, &'a u8) -> &'a u8 =
|
|
|
|
&(non_elidable as for<'a> fn(&'a u8, &'a u8) -> &'a u8);
|
|
|
|
|
2016-08-28 13:35:48 -05:00
|
|
|
struct SomeStruct<'x, 'y, 'z: 'x> {
|
|
|
|
foo: &'x Foo<'z>,
|
|
|
|
bar: &'x Bar<'z>,
|
2019-05-28 13:46:13 -05:00
|
|
|
f: &'y dyn for<'a, 'b> Fn(&'a Foo<'b>) -> &'a Bar<'b>,
|
2016-08-28 13:35:48 -05:00
|
|
|
}
|
|
|
|
|
2016-08-29 07:03:57 -05:00
|
|
|
fn id<T>(t: T) -> T {
|
|
|
|
t
|
|
|
|
}
|
2016-08-28 13:35:48 -05:00
|
|
|
|
move leak-check to during coherence, candidate eval
In particular, it no longer occurs during the subtyping check. This is
important for enabling lazy normalization, because the subtyping check
will be producing sub-obligations that could affect its results.
Consider an example like
for<'a> fn(<&'a as Mirror>::Item) =
fn(&'b u8)
where `<T as Mirror>::Item = T` for all `T`. We will wish to produce a
new subobligation like
<'!1 as Mirror>::Item = &'b u8
This will, after being solved, ultimately yield a constraint that `'!1
= 'b` which will fail. But with the leak-check being performed on
subtyping, there is no opportunity to normalize `<'!1 as
Mirror>::Item` (unless we invoke that normalization directly from
within subtyping, and I would prefer that subtyping and unification
are distinct operations rather than part of the trait solving stack).
The reason to keep the leak check during coherence and trait
evaluation is partly for backwards compatibility. The coherence change
permits impls for `fn(T)` and `fn(&T)` to co-exist, and the trait
evaluation change means that we can distinguish those two cases
without ambiguity errors. It also avoids recreating #57639, where we
were incorrectly choosing a where clause that would have failed the
leak check over the impl which succeeds.
The other reason to keep the leak check in those places is that I
think it is actually close to the model we want. To the point, I think
the trait solver ought to have the job of "breaking down"
higher-ranked region obligation like ``!1: '2` into into region
obligations that operate on things in the root universe, at which
point they should be handed off to polonius. The leak check isn't
*really* doing that -- these obligations are still handed to the
region solver to process -- but if/when we do adopt that model, the
decision to pass/fail would be happening in roughly this part of the
code.
This change had somewhat more side-effects than I anticipated. It
seems like there are cases where the leak-check was not being enforced
during method proving and trait selection. I haven't quite tracked
this down but I think it ought to be documented, so that we know what
precisely we are committing to.
One surprising test was `issue-30786.rs`. The behavior there seems a
bit "fishy" to me, but the problem is not related to the leak check
change as far as I can tell, but more to do with the closure signature
inference code and perhaps the associated type projection, which
together seem to be conspiring to produce an unexpected
signature. Nonetheless, it is an example of where changing the
leak-check can have some unexpected consequences: we're now failing to
resolve a method earlier than we were, which suggests we might change
some method resolutions that would have been ambiguous to be
successful.
TODO:
* figure out remainig test failures
* add new coherence tests for the patterns we ARE disallowing
2020-05-20 05:19:36 -05:00
|
|
|
static SOME_STRUCT: &SomeStruct = SomeStruct {
|
|
|
|
//~^ ERROR mismatched types
|
2016-08-28 13:35:48 -05:00
|
|
|
foo: &Foo { bools: &[false, true] },
|
|
|
|
bar: &Bar { bools: &[true, true] },
|
|
|
|
f: &id,
|
move leak-check to during coherence, candidate eval
In particular, it no longer occurs during the subtyping check. This is
important for enabling lazy normalization, because the subtyping check
will be producing sub-obligations that could affect its results.
Consider an example like
for<'a> fn(<&'a as Mirror>::Item) =
fn(&'b u8)
where `<T as Mirror>::Item = T` for all `T`. We will wish to produce a
new subobligation like
<'!1 as Mirror>::Item = &'b u8
This will, after being solved, ultimately yield a constraint that `'!1
= 'b` which will fail. But with the leak-check being performed on
subtyping, there is no opportunity to normalize `<'!1 as
Mirror>::Item` (unless we invoke that normalization directly from
within subtyping, and I would prefer that subtyping and unification
are distinct operations rather than part of the trait solving stack).
The reason to keep the leak check during coherence and trait
evaluation is partly for backwards compatibility. The coherence change
permits impls for `fn(T)` and `fn(&T)` to co-exist, and the trait
evaluation change means that we can distinguish those two cases
without ambiguity errors. It also avoids recreating #57639, where we
were incorrectly choosing a where clause that would have failed the
leak check over the impl which succeeds.
The other reason to keep the leak check in those places is that I
think it is actually close to the model we want. To the point, I think
the trait solver ought to have the job of "breaking down"
higher-ranked region obligation like ``!1: '2` into into region
obligations that operate on things in the root universe, at which
point they should be handed off to polonius. The leak check isn't
*really* doing that -- these obligations are still handed to the
region solver to process -- but if/when we do adopt that model, the
decision to pass/fail would be happening in roughly this part of the
code.
This change had somewhat more side-effects than I anticipated. It
seems like there are cases where the leak-check was not being enforced
during method proving and trait selection. I haven't quite tracked
this down but I think it ought to be documented, so that we know what
precisely we are committing to.
One surprising test was `issue-30786.rs`. The behavior there seems a
bit "fishy" to me, but the problem is not related to the leak check
change as far as I can tell, but more to do with the closure signature
inference code and perhaps the associated type projection, which
together seem to be conspiring to produce an unexpected
signature. Nonetheless, it is an example of where changing the
leak-check can have some unexpected consequences: we're now failing to
resolve a method earlier than we were, which suggests we might change
some method resolutions that would have been ambiguous to be
successful.
TODO:
* figure out remainig test failures
* add new coherence tests for the patterns we ARE disallowing
2020-05-20 05:19:36 -05:00
|
|
|
//~^ ERROR type mismatch resolving
|
2016-08-28 13:35:48 -05:00
|
|
|
};
|
|
|
|
|
|
|
|
// very simple test for a 'static static with default lifetime
|
2016-08-29 07:03:57 -05:00
|
|
|
static STATIC_STR: &'static str = "&'static str";
|
|
|
|
const CONST_STR: &'static str = "&'static str";
|
2016-08-28 13:35:48 -05:00
|
|
|
|
|
|
|
// this should be the same as without default:
|
2016-08-29 07:03:57 -05:00
|
|
|
static EXPLICIT_STATIC_STR: &'static str = "&'static str";
|
|
|
|
const EXPLICIT_CONST_STR: &'static str = "&'static str";
|
2016-08-28 13:35:48 -05:00
|
|
|
|
|
|
|
// a function that elides to an unbound lifetime for both in- and output
|
2016-08-29 07:03:57 -05:00
|
|
|
fn id_u8_slice(arg: &[u8]) -> &[u8] {
|
|
|
|
arg
|
|
|
|
}
|
2016-08-28 13:35:48 -05:00
|
|
|
|
|
|
|
// one with a function, argument elided
|
2016-08-29 07:03:57 -05:00
|
|
|
static STATIC_SIMPLE_FN: &'static fn(&[u8]) -> &[u8] = &(id_u8_slice as fn(&[u8]) -> &[u8]);
|
|
|
|
const CONST_SIMPLE_FN: &'static fn(&[u8]) -> &[u8] = &(id_u8_slice as fn(&[u8]) -> &[u8]);
|
2016-08-28 13:35:48 -05:00
|
|
|
|
|
|
|
// this should be the same as without elision
|
2016-08-29 07:03:57 -05:00
|
|
|
static STATIC_NON_ELIDED_fN: &'static for<'a> fn(&'a [u8]) -> &'a [u8] =
|
|
|
|
&(id_u8_slice as for<'a> fn(&'a [u8]) -> &'a [u8]);
|
|
|
|
const CONST_NON_ELIDED_fN: &'static for<'a> fn(&'a [u8]) -> &'a [u8] =
|
|
|
|
&(id_u8_slice as for<'a> fn(&'a [u8]) -> &'a [u8]);
|
2016-08-28 13:35:48 -05:00
|
|
|
|
|
|
|
// another function that elides, each to a different unbound lifetime
|
2016-08-29 07:03:57 -05:00
|
|
|
fn multi_args(a: &u8, b: &u8, c: &u8) {}
|
2016-08-28 13:35:48 -05:00
|
|
|
|
2016-08-29 07:03:57 -05:00
|
|
|
static STATIC_MULTI_FN: &'static fn(&u8, &u8, &u8) = &(multi_args as fn(&u8, &u8, &u8));
|
|
|
|
const CONST_MULTI_FN: &'static fn(&u8, &u8, &u8) = &(multi_args as fn(&u8, &u8, &u8));
|
2016-08-28 13:35:48 -05:00
|
|
|
|
|
|
|
struct Foo<'a> {
|
2016-08-29 07:03:57 -05:00
|
|
|
bools: &'a [bool],
|
2016-08-28 13:35:48 -05:00
|
|
|
}
|
|
|
|
|
2016-08-29 07:03:57 -05:00
|
|
|
static STATIC_FOO: Foo<'static> = Foo { bools: &[true, false] };
|
|
|
|
const CONST_FOO: Foo<'static> = Foo { bools: &[true, false] };
|
2016-08-28 13:35:48 -05:00
|
|
|
|
|
|
|
type Bar<'a> = Foo<'a>;
|
|
|
|
|
2016-08-29 07:03:57 -05:00
|
|
|
static STATIC_BAR: Bar<'static> = Bar { bools: &[true, false] };
|
|
|
|
const CONST_BAR: Bar<'static> = Bar { bools: &[true, false] };
|
2016-08-28 13:35:48 -05:00
|
|
|
|
2016-08-23 14:36:19 -05:00
|
|
|
type Baz<'a> = fn(&'a [u8]) -> Option<u8>;
|
|
|
|
|
2016-08-29 07:03:57 -05:00
|
|
|
fn baz(e: &[u8]) -> Option<u8> {
|
|
|
|
e.first().map(|x| *x)
|
|
|
|
}
|
2016-08-23 14:36:19 -05:00
|
|
|
|
2016-08-29 07:03:57 -05:00
|
|
|
static STATIC_BAZ: &'static Baz<'static> = &(baz as Baz);
|
|
|
|
const CONST_BAZ: &'static Baz<'static> = &(baz as Baz);
|
2016-08-28 13:35:48 -05:00
|
|
|
|
2016-08-29 07:03:57 -05:00
|
|
|
static BYTES: &'static [u8] = &[1, 2, 3];
|
2016-08-23 14:36:19 -05:00
|
|
|
|
2016-08-23 00:40:51 -05:00
|
|
|
fn main() {
|
2016-08-24 14:19:39 -05:00
|
|
|
let x = &[1u8, 2, 3];
|
|
|
|
let y = x;
|
2016-08-23 14:36:19 -05:00
|
|
|
|
2016-08-29 07:03:57 -05:00
|
|
|
// this works, so lifetime < `'static` is valid
|
2016-08-23 14:36:19 -05:00
|
|
|
assert_eq!(Some(1), STATIC_BAZ(y));
|
|
|
|
assert_eq!(Some(1), CONST_BAZ(y));
|
2016-08-28 13:35:48 -05:00
|
|
|
|
|
|
|
let y = &[1u8, 2, 3];
|
2016-08-29 09:45:22 -05:00
|
|
|
|
2016-08-28 13:35:48 -05:00
|
|
|
STATIC_BAZ(BYTES); // BYTES has static lifetime
|
2016-08-29 09:45:22 -05:00
|
|
|
CONST_BAZ(y); // interestingly this does not get reported
|
2016-08-23 00:40:51 -05:00
|
|
|
}
|