Skip to content

Commit c312e04

Browse files
committed
Check user types are well-formed in MIR borrow check
Also update some tests so that they don't have user types on `_` in unreachable code.
1 parent 55ec104 commit c312e04

20 files changed

+249
-77
lines changed

src/librustc_mir/borrow_check/nll/type_check/mod.rs

+8-2
Original file line numberDiff line numberDiff line change
@@ -970,15 +970,21 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
970970
locations: Locations,
971971
category: ConstraintCategory,
972972
) -> Fallible<()> {
973-
relate_tys::relate_type_and_user_type(
973+
let ty = relate_tys::relate_type_and_user_type(
974974
self.infcx,
975975
a,
976976
v,
977977
b,
978978
locations,
979979
category,
980980
self.borrowck_context.as_mut().map(|x| &mut **x),
981-
)
981+
)?;
982+
self.prove_predicate(
983+
ty::Predicate::WellFormed(ty),
984+
locations,
985+
category,
986+
);
987+
Ok(())
982988
}
983989

984990
fn eq_opaque_type_and_type(

src/librustc_mir/borrow_check/nll/type_check/relate_tys.rs

+16-5
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010

1111
use borrow_check::nll::constraints::OutlivesConstraint;
1212
use borrow_check::nll::type_check::{BorrowCheckContext, Locations};
13-
use rustc::infer::canonical::{Canonical, CanonicalVarInfos};
13+
use rustc::infer::canonical::{Canonical, CanonicalVarInfos, CanonicalVarValues};
1414
use rustc::infer::{InferCtxt, NLLRegionVariableOrigin};
1515
use rustc::mir::ConstraintCategory;
1616
use rustc::traits::query::Fallible;
@@ -70,7 +70,7 @@ pub(super) fn relate_type_and_user_type<'tcx>(
7070
locations: Locations,
7171
category: ConstraintCategory,
7272
borrowck_context: Option<&mut BorrowCheckContext<'_, 'tcx>>,
73-
) -> Fallible<()> {
73+
) -> Fallible<Ty<'tcx>> {
7474
debug!(
7575
"sub_type_and_user_type(a={:?}, b={:?}, locations={:?})",
7676
a, b, locations
@@ -85,13 +85,24 @@ pub(super) fn relate_type_and_user_type<'tcx>(
8585
// variance to get the right relationship.
8686
let v1 = ty::Contravariant.xform(v);
8787

88-
TypeRelating::new(
88+
let mut type_relating = TypeRelating::new(
8989
infcx.tcx,
9090
NllTypeRelatingDelegate::new(infcx, borrowck_context, locations, category),
9191
v1,
9292
b_variables,
93-
).relate(&b_value, &a)?;
94-
Ok(())
93+
);
94+
type_relating.relate(&b_value, &a)?;
95+
96+
Ok(b.substitute(
97+
infcx.tcx,
98+
&CanonicalVarValues {
99+
var_values: type_relating
100+
.canonical_var_values
101+
.into_iter()
102+
.map(|x| x.expect("unsubstituted canonical variable"))
103+
.collect(),
104+
},
105+
))
95106
}
96107

97108
struct TypeRelating<'me, 'gcx: 'tcx, 'tcx: 'me, D>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
error: unsatisfied lifetime constraints
2+
--> $DIR/associated-types-subtyping-1.rs:36:13
3+
|
4+
LL | fn method2<'a,'b,T>(x: &'a T, y: &'b T)
5+
| -- -- lifetime `'b` defined here
6+
| |
7+
| lifetime `'a` defined here
8+
...
9+
LL | let _c: <T as Trait<'b>>::Type = a; //~ ERROR E0623
10+
| ^^^^^^^^^^^^^^^^^^^^^^ type annotation requires that `'b` must outlive `'a`
11+
12+
error: unsatisfied lifetime constraints
13+
--> $DIR/associated-types-subtyping-1.rs:44:12
14+
|
15+
LL | fn method3<'a,'b,T>(x: &'a T, y: &'b T)
16+
| -- -- lifetime `'b` defined here
17+
| |
18+
| lifetime `'a` defined here
19+
...
20+
LL | let b: <T as Trait<'b>>::Type = make_any();
21+
| ^^^^^^^^^^^^^^^^^^^^^^ type annotation requires that `'b` must outlive `'a`
22+
23+
error: aborting due to 2 previous errors
24+

src/test/ui/associated-types/associated-types-subtyping-1.rs

+10-10
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,10 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11-
// ignore-compare-mode-nll
12-
1311
#![allow(unused_variables)]
1412

13+
fn make_any<T>() -> T { loop {} }
14+
1515
trait Trait<'a> {
1616
type Type;
1717

@@ -22,35 +22,35 @@ fn method1<'a,'b,T>(x: &'a T, y: &'b T)
2222
where T : for<'z> Trait<'z>, 'a : 'b
2323
{
2424
// Note that &'static T <: &'a T.
25-
let a: <T as Trait<'a>>::Type = loop { };
26-
let b: <T as Trait<'b>>::Type = loop { };
25+
let a: <T as Trait<'a>>::Type = make_any();
26+
let b: <T as Trait<'b>>::Type = make_any();
2727
let _c: <T as Trait<'a>>::Type = a;
2828
}
2929

3030
fn method2<'a,'b,T>(x: &'a T, y: &'b T)
3131
where T : for<'z> Trait<'z>, 'a : 'b
3232
{
3333
// Note that &'static T <: &'a T.
34-
let a: <T as Trait<'a>>::Type = loop { };
35-
let b: <T as Trait<'b>>::Type = loop { };
34+
let a: <T as Trait<'a>>::Type = make_any();
35+
let b: <T as Trait<'b>>::Type = make_any();
3636
let _c: <T as Trait<'b>>::Type = a; //~ ERROR E0623
3737
}
3838

3939
fn method3<'a,'b,T>(x: &'a T, y: &'b T)
4040
where T : for<'z> Trait<'z>, 'a : 'b
4141
{
4242
// Note that &'static T <: &'a T.
43-
let a: <T as Trait<'a>>::Type = loop { };
44-
let b: <T as Trait<'b>>::Type = loop { };
43+
let a: <T as Trait<'a>>::Type = make_any();
44+
let b: <T as Trait<'b>>::Type = make_any();
4545
let _c: <T as Trait<'a>>::Type = b; //~ ERROR E0623
4646
}
4747

4848
fn method4<'a,'b,T>(x: &'a T, y: &'b T)
4949
where T : for<'z> Trait<'z>, 'a : 'b
5050
{
5151
// Note that &'static T <: &'a T.
52-
let a: <T as Trait<'a>>::Type = loop { };
53-
let b: <T as Trait<'b>>::Type = loop { };
52+
let a: <T as Trait<'a>>::Type = make_any();
53+
let b: <T as Trait<'b>>::Type = make_any();
5454
let _c: <T as Trait<'b>>::Type = b;
5555
}
5656

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
error: unsatisfied lifetime constraints
2+
--> $DIR/regions-assoc-type-in-supertrait-outlives-container.rs:52:13
3+
|
4+
LL | fn with_assoc<'a,'b>() {
5+
| -- -- lifetime `'b` defined here
6+
| |
7+
| lifetime `'a` defined here
8+
...
9+
LL | let _x: &'a WithAssoc<TheType<'b>> = loop { };
10+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ type annotation requires that `'b` must outlive `'a`
11+
12+
error: aborting due to previous error
13+

src/test/ui/regions/regions-assoc-type-in-supertrait-outlives-container.rs

+4-3
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,6 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11-
// ignore-compare-mode-nll
12-
1311
// Test that we are imposing the requirement that every associated
1412
// type of a bound that appears in the where clause on a struct must
1513
// outlive the location in which the type appears, even when the
@@ -49,7 +47,10 @@ fn with_assoc<'a,'b>() {
4947
// outlive 'a. In this case, that means TheType<'b>::TheAssocType,
5048
// which is &'b (), must outlive 'a.
5149

52-
let _: &'a WithAssoc<TheType<'b>> = loop { }; //~ ERROR reference has a longer lifetime
50+
// FIXME (#54943) NLL doesn't enforce WF condition in unreachable code if
51+
// `_x` is changed to `_`
52+
let _x: &'a WithAssoc<TheType<'b>> = loop { };
53+
//~^ ERROR reference has a longer lifetime
5354
}
5455

5556
fn main() {

src/test/ui/regions/regions-assoc-type-in-supertrait-outlives-container.stderr

+7-7
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,16 @@
11
error[E0491]: in type `&'a WithAssoc<TheType<'b>>`, reference has a longer lifetime than the data it references
2-
--> $DIR/regions-assoc-type-in-supertrait-outlives-container.rs:52:12
2+
--> $DIR/regions-assoc-type-in-supertrait-outlives-container.rs:52:13
33
|
4-
LL | let _: &'a WithAssoc<TheType<'b>> = loop { }; //~ ERROR reference has a longer lifetime
5-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
4+
LL | let _x: &'a WithAssoc<TheType<'b>> = loop { };
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
66
|
7-
note: the pointer is valid for the lifetime 'a as defined on the function body at 46:15
8-
--> $DIR/regions-assoc-type-in-supertrait-outlives-container.rs:46:15
7+
note: the pointer is valid for the lifetime 'a as defined on the function body at 44:15
8+
--> $DIR/regions-assoc-type-in-supertrait-outlives-container.rs:44:15
99
|
1010
LL | fn with_assoc<'a,'b>() {
1111
| ^^
12-
note: but the referenced data is only valid for the lifetime 'b as defined on the function body at 46:18
13-
--> $DIR/regions-assoc-type-in-supertrait-outlives-container.rs:46:18
12+
note: but the referenced data is only valid for the lifetime 'b as defined on the function body at 44:18
13+
--> $DIR/regions-assoc-type-in-supertrait-outlives-container.rs:44:18
1414
|
1515
LL | fn with_assoc<'a,'b>() {
1616
| ^^
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
error: unsatisfied lifetime constraints
2+
--> $DIR/regions-free-region-ordering-caller.rs:18:12
3+
|
4+
LL | fn call2<'a, 'b>(a: &'a usize, b: &'b usize) {
5+
| -- -- lifetime `'b` defined here
6+
| |
7+
| lifetime `'a` defined here
8+
LL | let z: Option<&'b &'a usize> = None;//~ ERROR E0623
9+
| ^^^^^^^^^^^^^^^^^^^^^ type annotation requires that `'a` must outlive `'b`
10+
11+
error: unsatisfied lifetime constraints
12+
--> $DIR/regions-free-region-ordering-caller.rs:23:12
13+
|
14+
LL | fn call3<'a, 'b>(a: &'a usize, b: &'b usize) {
15+
| -- -- lifetime `'b` defined here
16+
| |
17+
| lifetime `'a` defined here
18+
LL | let y: Paramd<'a> = Paramd { x: a };
19+
LL | let z: Option<&'b Paramd<'a>> = None;//~ ERROR E0623
20+
| ^^^^^^^^^^^^^^^^^^^^^^ type annotation requires that `'a` must outlive `'b`
21+
22+
error: unsatisfied lifetime constraints
23+
--> $DIR/regions-free-region-ordering-caller.rs:27:12
24+
|
25+
LL | fn call4<'a, 'b>(a: &'a usize, b: &'b usize) {
26+
| -- -- lifetime `'b` defined here
27+
| |
28+
| lifetime `'a` defined here
29+
LL | let z: Option<&'a &'b usize> = None;//~ ERROR E0623
30+
| ^^^^^^^^^^^^^^^^^^^^^ type annotation requires that `'b` must outlive `'a`
31+
32+
error: aborting due to 3 previous errors
33+

src/test/ui/regions/regions-free-region-ordering-caller.rs

-2
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,6 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11-
// ignore-compare-mode-nll
12-
1311
// Test various ways to construct a pointer with a longer lifetime
1412
// than the thing it points at and ensure that they result in
1513
// errors. See also regions-free-region-ordering-callee.rs

src/test/ui/regions/regions-free-region-ordering-caller.stderr

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
error[E0623]: lifetime mismatch
2-
--> $DIR/regions-free-region-ordering-caller.rs:20:12
2+
--> $DIR/regions-free-region-ordering-caller.rs:18:12
33
|
44
LL | fn call2<'a, 'b>(a: &'a usize, b: &'b usize) {
55
| --------- ---------
@@ -9,7 +9,7 @@ LL | let z: Option<&'b &'a usize> = None;//~ ERROR E0623
99
| ^^^^^^^^^^^^^^^^^^^^^ ...but data from `a` flows into `b` here
1010

1111
error[E0623]: lifetime mismatch
12-
--> $DIR/regions-free-region-ordering-caller.rs:25:12
12+
--> $DIR/regions-free-region-ordering-caller.rs:23:12
1313
|
1414
LL | fn call3<'a, 'b>(a: &'a usize, b: &'b usize) {
1515
| --------- ---------
@@ -20,7 +20,7 @@ LL | let z: Option<&'b Paramd<'a>> = None;//~ ERROR E0623
2020
| ^^^^^^^^^^^^^^^^^^^^^^ ...but data from `a` flows into `b` here
2121

2222
error[E0623]: lifetime mismatch
23-
--> $DIR/regions-free-region-ordering-caller.rs:29:12
23+
--> $DIR/regions-free-region-ordering-caller.rs:27:12
2424
|
2525
LL | fn call4<'a, 'b>(a: &'a usize, b: &'b usize) {
2626
| --------- --------- these two types are declared with different lifetimes...

src/test/ui/regions/regions-free-region-ordering-caller1.nll.stderr

+18-2
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,22 @@ note: borrowed value must be valid for the lifetime 'a as defined on the functio
1313
LL | fn call1<'a>(x: &'a usize) {
1414
| ^^
1515

16-
error: aborting due to previous error
16+
error[E0597]: `y` does not live long enough
17+
--> $DIR/regions-free-region-ordering-caller1.rs:19:27
18+
|
19+
LL | let z: &'a & usize = &(&y);
20+
| ^^^^ borrowed value does not live long enough
21+
...
22+
LL | }
23+
| - `y` dropped here while still borrowed
24+
|
25+
note: borrowed value must be valid for the lifetime 'a as defined on the function body at 15:10...
26+
--> $DIR/regions-free-region-ordering-caller1.rs:15:10
27+
|
28+
LL | fn call1<'a>(x: &'a usize) {
29+
| ^^
30+
31+
error: aborting due to 2 previous errors
1732

18-
For more information about this error, try `rustc --explain E0716`.
33+
Some errors occurred: E0597, E0716.
34+
For more information about an error, try `rustc --explain E0597`.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
error[E0309]: the parameter type `T` may not live long enough
2+
--> $DIR/regions-implied-bounds-projection-gap-1.rs:26:5
3+
|
4+
LL | wf::<&'x T>();
5+
| ^^^^^^^^^^^^^
6+
|
7+
= help: consider adding an explicit lifetime bound `T: 'x`...
8+
9+
error: aborting due to previous error
10+
11+
For more information about this error, try `rustc --explain E0309`.

src/test/ui/regions/regions-implied-bounds-projection-gap-1.rs

-2
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,6 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11-
// ignore-compare-mode-nll
12-
1311
// Illustrates the "projection gap": in this test, even though we know
1412
// that `T::Foo: 'x`, that does not tell us that `T: 'x`, because
1513
// there might be other ways for the caller of `func` to show that

src/test/ui/regions/regions-implied-bounds-projection-gap-1.stderr

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
error[E0309]: the parameter type `T` may not live long enough
2-
--> $DIR/regions-implied-bounds-projection-gap-1.rs:28:10
2+
--> $DIR/regions-implied-bounds-projection-gap-1.rs:26:10
33
|
44
LL | fn func<'x, T:Trait1<'x>>(t: &'x T::Foo)
55
| -- help: consider adding an explicit lifetime bound `T: 'x`...
@@ -8,7 +8,7 @@ LL | wf::<&'x T>();
88
| ^^^^^
99
|
1010
note: ...so that the reference type `&'x T` does not outlive the data it points at
11-
--> $DIR/regions-implied-bounds-projection-gap-1.rs:28:10
11+
--> $DIR/regions-implied-bounds-projection-gap-1.rs:26:10
1212
|
1313
LL | wf::<&'x T>();
1414
| ^^^^^
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
error: unsatisfied lifetime constraints
2+
--> $DIR/regions-outlives-projection-container-wc.rs:46:13
3+
|
4+
LL | fn with_assoc<'a,'b>() {
5+
| -- -- lifetime `'b` defined here
6+
| |
7+
| lifetime `'a` defined here
8+
...
9+
LL | let _x: &'a WithAssoc<TheType<'b>> = loop { };
10+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ type annotation requires that `'b` must outlive `'a`
11+
12+
error: aborting due to previous error
13+

src/test/ui/regions/regions-outlives-projection-container-wc.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,6 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11-
// ignore-compare-mode-nll
12-
1311
// Test that we are imposing the requirement that every associated
1412
// type of a bound that appears in the where clause on a struct must
1513
// outlive the location in which the type appears, even when the
@@ -43,7 +41,9 @@ fn with_assoc<'a,'b>() {
4341
// outlive 'a. In this case, that means TheType<'b>::TheAssocType,
4442
// which is &'b (), must outlive 'a.
4543

46-
let _: &'a WithAssoc<TheType<'b>> = loop { };
44+
// FIXME (#54943) NLL doesn't enforce WF condition in unreachable code if
45+
// `_x` is changed to `_`
46+
let _x: &'a WithAssoc<TheType<'b>> = loop { };
4747
//~^ ERROR reference has a longer lifetime
4848
}
4949

src/test/ui/regions/regions-outlives-projection-container-wc.stderr

+7-7
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,16 @@
11
error[E0491]: in type `&'a WithAssoc<TheType<'b>>`, reference has a longer lifetime than the data it references
2-
--> $DIR/regions-outlives-projection-container-wc.rs:46:12
2+
--> $DIR/regions-outlives-projection-container-wc.rs:46:13
33
|
4-
LL | let _: &'a WithAssoc<TheType<'b>> = loop { };
5-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
4+
LL | let _x: &'a WithAssoc<TheType<'b>> = loop { };
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
66
|
7-
note: the pointer is valid for the lifetime 'a as defined on the function body at 40:15
8-
--> $DIR/regions-outlives-projection-container-wc.rs:40:15
7+
note: the pointer is valid for the lifetime 'a as defined on the function body at 38:15
8+
--> $DIR/regions-outlives-projection-container-wc.rs:38:15
99
|
1010
LL | fn with_assoc<'a,'b>() {
1111
| ^^
12-
note: but the referenced data is only valid for the lifetime 'b as defined on the function body at 40:18
13-
--> $DIR/regions-outlives-projection-container-wc.rs:40:18
12+
note: but the referenced data is only valid for the lifetime 'b as defined on the function body at 38:18
13+
--> $DIR/regions-outlives-projection-container-wc.rs:38:18
1414
|
1515
LL | fn with_assoc<'a,'b>() {
1616
| ^^

0 commit comments

Comments
 (0)