Skip to content

Commit 57da937

Browse files
committed
borrowck: wf-check fn item args
1 parent 492e57c commit 57da937

File tree

17 files changed

+241
-24
lines changed

17 files changed

+241
-24
lines changed

compiler/rustc_borrowck/src/type_check/mod.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -414,6 +414,16 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'tcx> {
414414
instantiated_predicates,
415415
locations,
416416
);
417+
418+
assert!(!matches!(
419+
tcx.impl_of_method(def_id).map(|imp| tcx.def_kind(imp)),
420+
Some(DefKind::Impl { of_trait: true })
421+
));
422+
self.cx.prove_predicates(
423+
args.types().map(|ty| ty::ClauseKind::WellFormed(ty.into())),
424+
locations,
425+
ConstraintCategory::Boring,
426+
);
417427
}
418428
}
419429
}

library/std/src/collections/hash/map.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3052,8 +3052,9 @@ where
30523052
#[stable(feature = "hash_extend_copy", since = "1.4.0")]
30533053
impl<'a, K, V, S> Extend<(&'a K, &'a V)> for HashMap<K, V, S>
30543054
where
3055-
K: Eq + Hash + Copy,
3056-
V: Copy,
3055+
// FIXME(aliemjay): the bound `+ 'a` should not be necessary.
3056+
K: Eq + Hash + Copy + 'a,
3057+
V: Copy + 'a,
30573058
S: BuildHasher,
30583059
{
30593060
#[inline]
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// The method `assert_static` should be callable only for static values,
2+
// because the impl has an implied bound `where T: 'static`.
3+
4+
// check-fail
5+
6+
trait AnyStatic<Witness>: Sized {
7+
fn assert_static(self) {}
8+
}
9+
10+
impl<T> AnyStatic<&'static T> for T {}
11+
12+
fn main() {
13+
(&String::new()).assert_static();
14+
//~^ ERROR temporary value dropped while borrowed
15+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
error[E0716]: temporary value dropped while borrowed
2+
--> $DIR/fn-item-check-trait-ref.rs:13:7
3+
|
4+
LL | (&String::new()).assert_static();
5+
| --^^^^^^^^^^^^^------------------ temporary value is freed at the end of this statement
6+
| | |
7+
| | creates a temporary value which is freed while still in use
8+
| argument requires that borrow lasts for `'static`
9+
10+
error: aborting due to previous error
11+
12+
For more information about this error, try `rustc --explain E0716`.
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
// Regression test for #104005.
2+
//
3+
// Previously, different borrowck implementations used to disagree here.
4+
// The status of each is documented on `fn test_*`.
5+
6+
// check-fail
7+
8+
use std::fmt::Display;
9+
10+
trait Displayable {
11+
fn display(self) -> Box<dyn Display>;
12+
}
13+
14+
impl<T: Display> Displayable for (T, Option<&'static T>) {
15+
fn display(self) -> Box<dyn Display> {
16+
Box::new(self.0)
17+
}
18+
}
19+
20+
fn extend_lt<T, U>(val: T) -> Box<dyn Display>
21+
where
22+
(T, Option<U>): Displayable,
23+
{
24+
Displayable::display((val, None))
25+
}
26+
27+
// AST: fail
28+
// HIR: pass
29+
// MIR: pass
30+
pub fn test_call<'a>(val: &'a str) {
31+
extend_lt(val);
32+
//~^ ERROR borrowed data escapes outside of function
33+
}
34+
35+
// AST: fail
36+
// HIR: fail
37+
// MIR: pass
38+
pub fn test_coercion<'a>() {
39+
let _: fn(&'a str) -> _ = extend_lt;
40+
//~^ ERROR lifetime may not live long enough
41+
}
42+
43+
// AST: fail
44+
// HIR: fail
45+
// MIR: fail
46+
pub fn test_arg() {
47+
fn want<I, O>(_: I, _: impl Fn(I) -> O) {}
48+
want(&String::new(), extend_lt);
49+
//~^ ERROR temporary value dropped while borrowed
50+
}
51+
52+
// An exploit of the unsoundness.
53+
fn main() {
54+
let val = extend_lt(&String::from("blah blah blah"));
55+
//~^ ERROR temporary value dropped while borrowed
56+
println!("{}", val);
57+
}
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
error[E0521]: borrowed data escapes outside of function
2+
--> $DIR/fn-item-check-type-params.rs:31:5
3+
|
4+
LL | pub fn test_call<'a>(val: &'a str) {
5+
| -- --- `val` is a reference that is only valid in the function body
6+
| |
7+
| lifetime `'a` defined here
8+
LL | extend_lt(val);
9+
| ^^^^^^^^^^^^^^
10+
| |
11+
| `val` escapes the function body here
12+
| argument requires that `'a` must outlive `'static`
13+
14+
error: lifetime may not live long enough
15+
--> $DIR/fn-item-check-type-params.rs:39:12
16+
|
17+
LL | pub fn test_coercion<'a>() {
18+
| -- lifetime `'a` defined here
19+
LL | let _: fn(&'a str) -> _ = extend_lt;
20+
| ^^^^^^^^^^^^^^^^ type annotation requires that `'a` must outlive `'static`
21+
22+
error[E0716]: temporary value dropped while borrowed
23+
--> $DIR/fn-item-check-type-params.rs:48:11
24+
|
25+
LL | want(&String::new(), extend_lt);
26+
| ------^^^^^^^^^^^^^------------- temporary value is freed at the end of this statement
27+
| | |
28+
| | creates a temporary value which is freed while still in use
29+
| argument requires that borrow lasts for `'static`
30+
31+
error[E0716]: temporary value dropped while borrowed
32+
--> $DIR/fn-item-check-type-params.rs:54:26
33+
|
34+
LL | let val = extend_lt(&String::from("blah blah blah"));
35+
| -----------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-- temporary value is freed at the end of this statement
36+
| | |
37+
| | creates a temporary value which is freed while still in use
38+
| argument requires that borrow lasts for `'static`
39+
40+
error: aborting due to 4 previous errors
41+
42+
Some errors have detailed explanations: E0521, E0716.
43+
For more information about an error, try `rustc --explain E0521`.

tests/ui/higher-ranked/trait-bounds/issue-59311.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ where
1717
v.t(|| {});
1818
//~^ ERROR: higher-ranked lifetime error
1919
//~| ERROR: higher-ranked lifetime error
20+
//~| ERROR: higher-ranked lifetime error
2021
}
2122

2223
fn main() {}

tests/ui/higher-ranked/trait-bounds/issue-59311.stderr

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,15 @@ LL | v.t(|| {});
66
|
77
= note: could not prove `{closure@$DIR/issue-59311.rs:17:9: 17:11} well-formed`
88

9+
error: higher-ranked lifetime error
10+
--> $DIR/issue-59311.rs:17:5
11+
|
12+
LL | v.t(|| {});
13+
| ^^^^^^^^^^
14+
|
15+
= note: could not prove `{closure@$DIR/issue-59311.rs:17:9: 17:11} well-formed`
16+
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
17+
918
error: higher-ranked lifetime error
1019
--> $DIR/issue-59311.rs:17:9
1120
|
@@ -14,5 +23,5 @@ LL | v.t(|| {});
1423
|
1524
= note: could not prove `for<'a> &'a V: 'static`
1625

17-
error: aborting due to 2 previous errors
26+
error: aborting due to 3 previous errors
1827

tests/ui/implied-bounds/implied-bounds-on-trait-hierarchy.rs

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,7 @@
1-
// check-pass
2-
// known-bug: #84591
1+
// issue: #84591
32

4-
// Should fail. Subtrait can incorrectly extend supertrait lifetimes even when
5-
// supertrait has weaker implied bounds than subtrait. Strongly related to
6-
// issue #25860.
3+
// Subtrait was able to incorrectly extend supertrait lifetimes even when
4+
// supertrait had weaker implied bounds than subtrait.
75

86
trait Subtrait<T>: Supertrait {}
97
trait Supertrait {
@@ -34,6 +32,7 @@ fn main() {
3432
{
3533
let x = "Hello World".to_string();
3634
subs_to_soup((x.as_str(), &mut d));
35+
//~^ does not live long enough
3736
}
3837
println!("{}", d);
3938
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
error[E0597]: `x` does not live long enough
2+
--> $DIR/implied-bounds-on-trait-hierarchy.rs:34:23
3+
|
4+
LL | let x = "Hello World".to_string();
5+
| - binding `x` declared here
6+
LL | subs_to_soup((x.as_str(), &mut d));
7+
| ^ borrowed value does not live long enough
8+
LL |
9+
LL | }
10+
| - `x` dropped here while still borrowed
11+
LL | println!("{}", d);
12+
| - borrow later used here
13+
14+
error: aborting due to previous error
15+
16+
For more information about this error, try `rustc --explain E0597`.

tests/ui/lifetimes/lifetime-errors/issue_74400.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ fn f<T, S>(data: &[T], key: impl Fn(&T) -> S) {
1111
fn g<T>(data: &[T]) {
1212
f(data, identity)
1313
//~^ ERROR the parameter type
14+
//~| ERROR the parameter type
15+
//~| ERROR the parameter type
1416
//~| ERROR mismatched types
1517
//~| ERROR implementation of `FnOnce` is not general
1618
}

tests/ui/lifetimes/lifetime-errors/issue_74400.stderr

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,36 @@ help: consider adding an explicit lifetime bound
1212
LL | fn g<T: 'static>(data: &[T]) {
1313
| +++++++++
1414

15+
error[E0310]: the parameter type `T` may not live long enough
16+
--> $DIR/issue_74400.rs:12:5
17+
|
18+
LL | f(data, identity)
19+
| ^^^^^^^^^^^^^^^^^
20+
| |
21+
| the parameter type `T` must be valid for the static lifetime...
22+
| ...so that the type `T` will meet its required lifetime bounds
23+
|
24+
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
25+
help: consider adding an explicit lifetime bound
26+
|
27+
LL | fn g<T: 'static>(data: &[T]) {
28+
| +++++++++
29+
30+
error[E0310]: the parameter type `T` may not live long enough
31+
--> $DIR/issue_74400.rs:12:5
32+
|
33+
LL | f(data, identity)
34+
| ^^^^^^^^^^^^^^^^^
35+
| |
36+
| the parameter type `T` must be valid for the static lifetime...
37+
| ...so that the type `T` will meet its required lifetime bounds
38+
|
39+
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
40+
help: consider adding an explicit lifetime bound
41+
|
42+
LL | fn g<T: 'static>(data: &[T]) {
43+
| +++++++++
44+
1545
error[E0308]: mismatched types
1646
--> $DIR/issue_74400.rs:12:5
1747
|
@@ -35,7 +65,7 @@ LL | f(data, identity)
3565
= note: `fn(&'2 T) -> &'2 T {identity::<&'2 T>}` must implement `FnOnce<(&'1 T,)>`, for any lifetime `'1`...
3666
= note: ...but it actually implements `FnOnce<(&'2 T,)>`, for some specific lifetime `'2`
3767

38-
error: aborting due to 3 previous errors
68+
error: aborting due to 5 previous errors
3969

4070
Some errors have detailed explanations: E0308, E0310.
4171
For more information about an error, try `rustc --explain E0308`.

tests/ui/type-alias-impl-trait/wf-nested.fail.stderr

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
error[E0310]: the parameter type `T` may not live long enough
2-
--> $DIR/wf-nested.rs:55:27
2+
--> $DIR/wf-nested.rs:57:27
33
|
44
LL | type InnerOpaque<T> = impl Sized;
55
| ^^^^^^^^^^

tests/ui/type-alias-impl-trait/wf-nested.pass_sound.stderr

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,21 @@ help: consider adding an explicit lifetime bound
1212
LL | fn test<T: 'static>() {
1313
| +++++++++
1414

15-
error: aborting due to previous error
15+
error[E0310]: the parameter type `T` may not live long enough
16+
--> $DIR/wf-nested.rs:46:17
17+
|
18+
LL | let _ = outer.get();
19+
| ^^^^^^^^^^^
20+
| |
21+
| the parameter type `T` must be valid for the static lifetime...
22+
| ...so that the type `T` will meet its required lifetime bounds
23+
|
24+
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
25+
help: consider adding an explicit lifetime bound
26+
|
27+
LL | fn test<T: 'static>() {
28+
| +++++++++
29+
30+
error: aborting due to 2 previous errors
1631

1732
For more information about this error, try `rustc --explain E0310`.

tests/ui/type-alias-impl-trait/wf-nested.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,9 @@ mod pass_sound {
4343

4444
fn test<T>() {
4545
let outer = define::<T>();
46-
let _ = outer.get(); //[pass_sound]~ ERROR `T` may not live long enough
46+
let _ = outer.get();
47+
//[pass_sound]~^ ERROR `T` may not live long enough
48+
//[pass_sound]~| ERROR `T` may not live long enough
4749
}
4850
}
4951

tests/ui/wf/wf-in-fn-type-implicit.rs

Lines changed: 5 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,7 @@
1-
// check-pass
2-
// known-bug: #104005
1+
// issue: #104005
32

4-
// Should fail. Function type parameters with implicit type annotations are not
5-
// checked for well-formedness, which allows incorrect borrowing.
6-
7-
// In contrast, user annotations are always checked for well-formedness, and the
8-
// commented code below is correctly rejected by the borrow checker.
3+
// Function type parameters with implicit type annotations were not
4+
// checked for well-formedness, which allowed incorrect borrowing.
95

106
use std::fmt::Display;
117

@@ -27,11 +23,8 @@ where
2723
}
2824

2925
fn main() {
30-
// *incorrectly* compiles
26+
// This used to compile
3127
let val = extend_lt(&String::from("blah blah blah"));
28+
//~^ ERROR temporary value dropped while borrowed
3229
println!("{}", val);
33-
34-
// *correctly* fails to compile
35-
// let val = extend_lt::<_, &_>(&String::from("blah blah blah"));
36-
// println!("{}", val);
3730
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
error[E0716]: temporary value dropped while borrowed
2+
--> $DIR/wf-in-fn-type-implicit.rs:27:26
3+
|
4+
LL | let val = extend_lt(&String::from("blah blah blah"));
5+
| -----------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-- temporary value is freed at the end of this statement
6+
| | |
7+
| | creates a temporary value which is freed while still in use
8+
| argument requires that borrow lasts for `'static`
9+
10+
error: aborting due to previous error
11+
12+
For more information about this error, try `rustc --explain E0716`.

0 commit comments

Comments
 (0)