fix subtle bug in NLL type checker

The bug was revealed by the behavior of the old-lub-glb-hr-noteq1.rs
test. The old-lub-glb-hr-noteq2 test shows the current 'order dependent'
behavior of coercions around higher-ranked functions, at least when
running with `-Zborrowck=mir`.

Also, run compare-mode=nll.
This commit is contained in:
Niko Matsakis 2020-06-08 23:12:01 +00:00
parent c88a76e37b
commit 6929013b85
30 changed files with 472 additions and 61 deletions

View file

@ -0,0 +1,33 @@
error[E0271]: type mismatch resolving `for<'x> <UintStruct as TheTrait<&'x isize>>::A == &'x isize`
--> $DIR/associated-types-eq-hr.rs:87:5
|
LL | fn foo<T>()
| --- required by a bound in this
LL | where
LL | T: for<'x> TheTrait<&'x isize, A = &'x isize>,
| ------------- required by this bound in `foo`
...
LL | foo::<UintStruct>();
| ^^^^^^^^^^^^^^^^^ expected `isize`, found `usize`
|
= note: expected reference `&isize`
found reference `&usize`
error[E0271]: type mismatch resolving `for<'x> <IntStruct as TheTrait<&'x isize>>::A == &'x usize`
--> $DIR/associated-types-eq-hr.rs:91:5
|
LL | fn bar<T>()
| --- required by a bound in this
LL | where
LL | T: for<'x> TheTrait<&'x isize, A = &'x usize>,
| ------------- required by this bound in `bar`
...
LL | bar::<IntStruct>();
| ^^^^^^^^^^^^^^^^ expected `usize`, found `isize`
|
= note: expected reference `&usize`
found reference `&isize`
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0271`.

View file

@ -0,0 +1,8 @@
error: higher-ranked subtype error
--> $DIR/higher-ranked-projection.rs:25:5
|
LL | foo(());
| ^^^^^^^
error: aborting due to previous error

View file

@ -0,0 +1,8 @@
error: higher-ranked subtype error
--> $DIR/resume-arg-late-bound.rs:15:5
|
LL | test(gen);
| ^^^^^^^^^
error: aborting due to previous error

View file

@ -0,0 +1,14 @@
error: higher-ranked subtype error
--> $DIR/hr-subtype.rs:45:13
|
LL | gimme::<$t1>(None::<$t2>);
| ^^^^^^^^^^^^^^^^^^^^^^^^^
...
LL | / check! { bound_a_b_ret_a_vs_bound_a_ret_a: (for<'a,'b> fn(&'a u32, &'b u32) -> &'a u32,
LL | | for<'a> fn(&'a u32, &'a u32) -> &'a u32) }
| |_____________________________________________- in this macro invocation
|
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
error: aborting due to previous error

View file

@ -0,0 +1,14 @@
error: higher-ranked subtype error
--> $DIR/hr-subtype.rs:45:13
|
LL | gimme::<$t1>(None::<$t2>);
| ^^^^^^^^^^^^^^^^^^^^^^^^^
...
LL | / check! { bound_a_vs_free_x: (for<'a> fn(&'a u32),
LL | | fn(&'x u32)) }
| |______________- in this macro invocation
|
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
error: aborting due to previous error

View file

@ -0,0 +1,26 @@
error: higher-ranked subtype error
--> $DIR/hr-subtype.rs:45:13
|
LL | gimme::<$t1>(None::<$t2>);
| ^^^^^^^^^^^^^^^^^^^^^^^^^
...
LL | / check! { bound_inv_a_b_vs_bound_inv_a: (for<'a,'b> fn(Inv<'a>, Inv<'b>),
LL | | for<'a> fn(Inv<'a>, Inv<'a>)) }
| |__________________________________- in this macro invocation
|
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
error: higher-ranked subtype error
--> $DIR/hr-subtype.rs:45:13
|
LL | gimme::<$t1>(None::<$t2>);
| ^^^^^^^^^^^^^^^^^^^^^^^^^
...
LL | / check! { bound_inv_a_b_vs_bound_inv_a: (for<'a,'b> fn(Inv<'a>, Inv<'b>),
LL | | for<'a> fn(Inv<'a>, Inv<'a>)) }
| |__________________________________- in this macro invocation
|
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
error: aborting due to 2 previous errors

View file

@ -0,0 +1,14 @@
error: higher-ranked subtype error
--> $DIR/hrtb-conflate-regions.rs:27:10
|
LL | fn b() { want_foo2::<SomeStruct>(); }
| ^^^^^^^^^^^^^^^^^^^^^^^^^
error: higher-ranked subtype error
--> $DIR/hrtb-conflate-regions.rs:27:10
|
LL | fn b() { want_foo2::<SomeStruct>(); }
| ^^^^^^^^^^^^^^^^^^^^^^^^^
error: aborting due to 2 previous errors

View file

@ -0,0 +1,8 @@
error: higher-ranked subtype error
--> $DIR/hrtb-exists-forall-fn.rs:17:12
|
LL | let _: for<'b> fn(&'b u32) = foo();
| ^^^^^^^^^^^^^^^^^^^
error: aborting due to previous error

View file

@ -0,0 +1,8 @@
error: higher-ranked subtype error
--> $DIR/hrtb-exists-forall-trait-contravariant.rs:34:5
|
LL | foo::<()>();
| ^^^^^^^^^^^
error: aborting due to previous error

View file

@ -0,0 +1,8 @@
error: higher-ranked subtype error
--> $DIR/hrtb-exists-forall-trait-invariant.rs:28:5
|
LL | foo::<()>();
| ^^^^^^^^^^^
error: aborting due to previous error

View file

@ -0,0 +1,24 @@
error: higher-ranked subtype error
--> $DIR/hrtb-just-for-static.rs:24:5
|
LL | want_hrtb::<StaticInt>()
| ^^^^^^^^^^^^^^^^^^^^^^^^
error: lifetime may not live long enough
--> $DIR/hrtb-just-for-static.rs:30:5
|
LL | fn give_some<'a>() {
| -- lifetime `'a` defined here
LL | want_hrtb::<&'a u32>()
| ^^^^^^^^^^^^^^^^^^^^ requires that `'a` must outlive `'static`
|
= help: consider replacing `'a` with `'static`
error: higher-ranked subtype error
--> $DIR/hrtb-just-for-static.rs:30:5
|
LL | want_hrtb::<&'a u32>()
| ^^^^^^^^^^^^^^^^^^^^
error: aborting due to 3 previous errors

View file

@ -0,0 +1,8 @@
error: higher-ranked subtype error
--> $DIR/issue-46989.rs:38:5
|
LL | assert_foo::<fn(&i32)>();
| ^^^^^^^^^^^^^^^^^^^^^^^^
error: aborting due to previous error

View file

@ -0,0 +1,8 @@
error: higher-ranked subtype error
--> $DIR/issue-40000.rs:6:9
|
LL | foo(bar);
| ^^^
error: aborting due to previous error

View file

@ -0,0 +1,27 @@
// Test that we give a note when the old LUB/GLB algorithm would have
// succeeded but the new code (which requires equality) gives an
// error. However, now that we handle subtyping correctly, we no
// longer get an error, because we recognize these two types as
// equivalent!
//
// check-pass
fn foo(x: fn(&u8, &u8), y: for<'a> fn(&'a u8, &'a u8)) {
// The two types above are actually equivalent. With the older
// leak check, though, we didn't consider them as equivalent, and
// hence we gave errors. But now we've fixed that.
let z = match 22 {
0 => x,
_ => y,
};
}
fn foo_cast(x: fn(&u8, &u8), y: for<'a> fn(&'a u8, &'a u8)) {
let z = match 22 {
// No error with an explicit cast:
0 => x as for<'a> fn(&'a u8, &'a u8),
_ => y,
};
}
fn main() {}

View file

@ -0,0 +1,8 @@
error: higher-ranked subtype error
--> $DIR/old-lub-glb-hr-noteq1.rs:11:14
|
LL | _ => y,
| ^
error: aborting due to previous error

View file

@ -0,0 +1,24 @@
// Test taking the LUB of two function types that are not equatable but where one is more
// general than the other. Test the case where the more general type (`x`) is the first
// match arm specifically.
fn foo(x: for<'a, 'b> fn(&'a u8, &'b u8) -> &'a u8, y: for<'a> fn(&'a u8, &'a u8) -> &'a u8) {
// The two types above are not equivalent. With the older LUB/GLB
// algorithm, this may have worked (I don't remember), but now it
// doesn't because we require equality.
let z = match 22 {
0 => x,
_ => y, //~ ERROR `match` arms have incompatible types
};
}
fn foo_cast(x: for<'a, 'b> fn(&'a u8, &'b u8) -> &'a u8, y: for<'a> fn(&'a u8, &'a u8) -> &'a u8) {
// But we can *upcast* explicitly the type of `x` and figure
// things out:
let z = match 22 {
0 => x as for<'a> fn(&'a u8, &'a u8) -> &'a u8,
_ => y,
};
}
fn main() {}

View file

@ -1,5 +1,5 @@
error[E0308]: `match` arms have incompatible types
--> $DIR/old-lub-glb-hr.rs:40:14
--> $DIR/old-lub-glb-hr-noteq1.rs:11:14
|
LL | let z = match 22 {
| _____________-

View file

@ -0,0 +1,33 @@
// Test taking the LUB of two function types that are not equatable but where
// one is more general than the other. Test the case where the more general type
// (`x`) is the second match arm specifically.
//
// Skip for compare-mode because the pure NLL checker accepts this test. (Note
// that it still errors in old-lub-glb-hr-noteq1.rs). What happens is that, due
// to the ordering of the match arms, we pick the correct "more general" fn
// type, and we ignore the errors from the non-NLL type checker that requires
// equality. The NLL type checker only requires a subtyping relationship, and
// that holds.
//
// ignore-compare-mode-nll
fn foo(x: for<'a, 'b> fn(&'a u8, &'b u8) -> &'a u8, y: for<'a> fn(&'a u8, &'a u8) -> &'a u8) {
// The two types above are not equivalent. With the older LUB/GLB
// algorithm, this may have worked (I don't remember), but now it
// doesn't because we require equality.
let z = match 22 {
0 => y,
_ => x, //~ ERROR `match` arms have incompatible types
};
}
fn foo_cast(x: for<'a, 'b> fn(&'a u8, &'b u8) -> &'a u8, y: for<'a> fn(&'a u8, &'a u8) -> &'a u8) {
// But we can *upcast* explicitly the type of `x` and figure
// things out:
let z = match 22 {
0 => x as for<'a> fn(&'a u8, &'a u8) -> &'a u8,
_ => y,
};
}
fn main() {}

View file

@ -0,0 +1,18 @@
error[E0308]: `match` arms have incompatible types
--> $DIR/old-lub-glb-hr-noteq2.rs:20:14
|
LL | let z = match 22 {
| _____________-
LL | | 0 => y,
| | - this is found to be of type `for<'a> fn(&'a u8, &'a u8) -> &'a u8`
LL | | _ => x,
| | ^ one type is more general than the other
LL | | };
| |_____- `match` arms have incompatible types
|
= note: expected fn pointer `for<'a> fn(&'a u8, &'a u8) -> &'a u8`
found fn pointer `for<'a, 'b> fn(&'a u8, &'b u8) -> &'a u8`
error: aborting due to previous error
For more information about this error, try `rustc --explain E0308`.

View file

@ -1,57 +0,0 @@
// Test that we give a note when the old LUB/GLB algorithm would have
// succeeded but the new code (which requires equality) gives an
// error. However, now that we handle subtyping correctly, we no
// longer get an error, because we recognize these two types as
// equivalent!
fn foo(
x: fn(&u8, &u8),
y: for<'a> fn(&'a u8, &'a u8),
) {
// The two types above are actually equivalent. With the older
// leak check, though, we didn't consider them as equivalent, and
// hence we gave errors. But now we've fixed that.
let z = match 22 {
0 => x,
_ => y,
};
}
fn foo_cast(
x: fn(&u8, &u8),
y: for<'a> fn(&'a u8, &'a u8),
) {
let z = match 22 {
// No error with an explicit cast:
0 => x as for<'a> fn(&'a u8, &'a u8),
_ => y,
};
}
fn bar(
x: for<'a, 'b> fn(&'a u8, &'b u8)-> &'a u8,
y: for<'a> fn(&'a u8, &'a u8) -> &'a u8,
) {
// The two types above are not equivalent. With the older LUB/GLB
// algorithm, this may have worked (I don't remember), but now it
// doesn't because we require equality.
let z = match 22 {
0 => x,
_ => y, //~ ERROR `match` arms have incompatible types
};
}
fn bar_cast(
x: for<'a, 'b> fn(&'a u8, &'b u8)-> &'a u8,
y: for<'a> fn(&'a u8, &'a u8) -> &'a u8,
) {
// But we can *upcast* explicitly the type of `x` and figure
// things out:
let z = match 22 {
0 => x as for<'a> fn(&'a u8, &'a u8) -> &'a u8,
_ => y,
};
}
fn main() {
}

View file

@ -0,0 +1,14 @@
error: higher-ranked subtype error
--> $DIR/old-lub-glb-object.rs:10:14
|
LL | _ => y,
| ^
error: higher-ranked subtype error
--> $DIR/old-lub-glb-object.rs:10:14
|
LL | _ => y,
| ^
error: aborting due to 2 previous errors

View file

@ -0,0 +1,27 @@
error[E0631]: type mismatch in closure arguments
--> $DIR/closure-arg-type-mismatch.rs:3:14
|
LL | a.iter().map(|_: (u32, u32)| 45);
| ^^^ ------------------ found signature of `fn((u32, u32)) -> _`
| |
| expected signature of `fn(&(u32, u32)) -> _`
error[E0631]: type mismatch in closure arguments
--> $DIR/closure-arg-type-mismatch.rs:4:14
|
LL | a.iter().map(|_: &(u16, u16)| 45);
| ^^^ ------------------- found signature of `for<'r> fn(&'r (u16, u16)) -> _`
| |
| expected signature of `fn(&(u32, u32)) -> _`
error[E0631]: type mismatch in closure arguments
--> $DIR/closure-arg-type-mismatch.rs:5:14
|
LL | a.iter().map(|_: (u16, u16)| 45);
| ^^^ ------------------ found signature of `fn((u16, u16)) -> _`
| |
| expected signature of `fn(&(u32, u32)) -> _`
error: aborting due to 3 previous errors
For more information about this error, try `rustc --explain E0631`.

View file

@ -0,0 +1,14 @@
error: higher-ranked subtype error
--> $DIR/closure-mismatch.rs:8:5
|
LL | baz(|_| ());
| ^^^^^^^^^^^
error: higher-ranked subtype error
--> $DIR/closure-mismatch.rs:8:5
|
LL | baz(|_| ());
| ^^^^^^^^^^^
error: aborting due to 2 previous errors

View file

@ -0,0 +1,8 @@
error: higher-ranked subtype error
--> $DIR/regions-fn-subtyping-return-static-fail.rs:48:5
|
LL | want_G(baz);
| ^^^^^^^^^^^
error: aborting due to previous error

View file

@ -0,0 +1,68 @@
error[E0277]: `dyn for<'a, 'b> std::ops::Fn(&'a Foo<'b>) -> &'a Foo<'b>` cannot be shared between threads safely
--> $DIR/rfc1623.rs:21:1
|
LL | / static SOME_STRUCT: &SomeStruct = &SomeStruct {
LL | | foo: &Foo { bools: &[false, true] },
LL | | bar: &Bar { bools: &[true, true] },
LL | | f: &id,
LL | |
LL | | };
| |__^ `dyn for<'a, 'b> std::ops::Fn(&'a Foo<'b>) -> &'a Foo<'b>` cannot be shared between threads safely
|
= help: within `&SomeStruct`, the trait `std::marker::Sync` is not implemented for `dyn for<'a, 'b> std::ops::Fn(&'a Foo<'b>) -> &'a Foo<'b>`
= note: required because it appears within the type `&dyn for<'a, 'b> std::ops::Fn(&'a Foo<'b>) -> &'a Foo<'b>`
= note: required because it appears within the type `SomeStruct`
= note: required because it appears within the type `&SomeStruct`
= note: shared static variables must have a type that implements `Sync`
error: higher-ranked subtype error
--> $DIR/rfc1623.rs:21:35
|
LL | static SOME_STRUCT: &SomeStruct = &SomeStruct {
| ___________________________________^
LL | | foo: &Foo { bools: &[false, true] },
LL | | bar: &Bar { bools: &[true, true] },
LL | | f: &id,
LL | |
LL | | };
| |_^
error: higher-ranked subtype error
--> $DIR/rfc1623.rs:21:35
|
LL | static SOME_STRUCT: &SomeStruct = &SomeStruct {
| ___________________________________^
LL | | foo: &Foo { bools: &[false, true] },
LL | | bar: &Bar { bools: &[true, true] },
LL | | f: &id,
LL | |
LL | | };
| |_^
error: higher-ranked subtype error
--> $DIR/rfc1623.rs:21:35
|
LL | static SOME_STRUCT: &SomeStruct = &SomeStruct {
| ___________________________________^
LL | | foo: &Foo { bools: &[false, true] },
LL | | bar: &Bar { bools: &[true, true] },
LL | | f: &id,
LL | |
LL | | };
| |_^
error: higher-ranked subtype error
--> $DIR/rfc1623.rs:21:35
|
LL | static SOME_STRUCT: &SomeStruct = &SomeStruct {
| ___________________________________^
LL | | foo: &Foo { bools: &[false, true] },
LL | | bar: &Bar { bools: &[true, true] },
LL | | f: &id,
LL | |
LL | | };
| |_^
error: aborting due to 5 previous errors
For more information about this error, try `rustc --explain E0277`.

View file

@ -0,0 +1,14 @@
error: higher-ranked subtype error
--> $DIR/issue-57611-trait-alias.rs:21:9
|
LL | |x| x
| ^^^^^
error: higher-ranked subtype error
--> $DIR/issue-57611-trait-alias.rs:21:9
|
LL | |x| x
| ^^^^^
error: aborting due to 2 previous errors

View file

@ -0,0 +1,8 @@
error: higher-ranked subtype error
--> $DIR/where-for-self-2.rs:23:5
|
LL | foo(&X);
| ^^^^^^^
error: aborting due to previous error