about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_borrowck/src/type_check/mod.rs10
-rw-r--r--library/std/src/collections/hash/map.rs5
-rw-r--r--tests/ui/borrowck/fn-item-check-trait-ref.rs15
-rw-r--r--tests/ui/borrowck/fn-item-check-trait-ref.stderr12
-rw-r--r--tests/ui/borrowck/fn-item-check-type-params.rs57
-rw-r--r--tests/ui/borrowck/fn-item-check-type-params.stderr43
-rw-r--r--tests/ui/higher-ranked/trait-bounds/issue-59311.rs1
-rw-r--r--tests/ui/higher-ranked/trait-bounds/issue-59311.stderr11
-rw-r--r--tests/ui/implied-bounds/implied-bounds-on-trait-hierarchy-1.rs (renamed from tests/ui/implied-bounds/implied-bounds-on-trait-hierarchy.rs)9
-rw-r--r--tests/ui/implied-bounds/implied-bounds-on-trait-hierarchy-1.stderr16
-rw-r--r--tests/ui/implied-bounds/implied-bounds-on-trait-hierarchy-2.rs45
-rw-r--r--tests/ui/lifetimes/lifetime-errors/issue_74400.rs2
-rw-r--r--tests/ui/lifetimes/lifetime-errors/issue_74400.stderr32
-rw-r--r--tests/ui/type-alias-impl-trait/wf-nested.fail.stderr2
-rw-r--r--tests/ui/type-alias-impl-trait/wf-nested.pass_sound.stderr17
-rw-r--r--tests/ui/type-alias-impl-trait/wf-nested.rs4
-rw-r--r--tests/ui/wf/wf-in-fn-type-implicit.rs37
17 files changed, 269 insertions, 49 deletions
diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs
index 9c0f53ddb86..05979bfabbd 100644
--- a/compiler/rustc_borrowck/src/type_check/mod.rs
+++ b/compiler/rustc_borrowck/src/type_check/mod.rs
@@ -406,6 +406,16 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'tcx> {
                     instantiated_predicates,
                     locations,
                 );
+
+                assert!(!matches!(
+                    tcx.impl_of_method(def_id).map(|imp| tcx.def_kind(imp)),
+                    Some(DefKind::Impl { of_trait: true })
+                ));
+                self.cx.prove_predicates(
+                    args.types().map(|ty| ty::ClauseKind::WellFormed(ty.into())),
+                    locations,
+                    ConstraintCategory::Boring,
+                );
             }
         }
     }
diff --git a/library/std/src/collections/hash/map.rs b/library/std/src/collections/hash/map.rs
index 39e94902cfe..1a416a4d10b 100644
--- a/library/std/src/collections/hash/map.rs
+++ b/library/std/src/collections/hash/map.rs
@@ -3049,8 +3049,9 @@ where
 #[stable(feature = "hash_extend_copy", since = "1.4.0")]
 impl<'a, K, V, S> Extend<(&'a K, &'a V)> for HashMap<K, V, S>
 where
-    K: Eq + Hash + Copy,
-    V: Copy,
+    // FIXME(aliemjay): the bound `+ 'a` should not be necessary.
+    K: Eq + Hash + Copy + 'a,
+    V: Copy + 'a,
     S: BuildHasher,
 {
     #[inline]
diff --git a/tests/ui/borrowck/fn-item-check-trait-ref.rs b/tests/ui/borrowck/fn-item-check-trait-ref.rs
new file mode 100644
index 00000000000..bdbb52e974f
--- /dev/null
+++ b/tests/ui/borrowck/fn-item-check-trait-ref.rs
@@ -0,0 +1,15 @@
+// The method `assert_static` should be callable only for static values,
+// because the impl has an implied bound `where T: 'static`.
+
+// check-fail
+
+trait AnyStatic<Witness>: Sized {
+    fn assert_static(self) {}
+}
+
+impl<T> AnyStatic<&'static T> for T {}
+
+fn main() {
+    (&String::new()).assert_static();
+    //~^ ERROR temporary value dropped while borrowed
+}
diff --git a/tests/ui/borrowck/fn-item-check-trait-ref.stderr b/tests/ui/borrowck/fn-item-check-trait-ref.stderr
new file mode 100644
index 00000000000..92fd67c316c
--- /dev/null
+++ b/tests/ui/borrowck/fn-item-check-trait-ref.stderr
@@ -0,0 +1,12 @@
+error[E0716]: temporary value dropped while borrowed
+  --> $DIR/fn-item-check-trait-ref.rs:13:7
+   |
+LL |     (&String::new()).assert_static();
+   |     --^^^^^^^^^^^^^------------------ temporary value is freed at the end of this statement
+   |     | |
+   |     | creates a temporary value which is freed while still in use
+   |     argument requires that borrow lasts for `'static`
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0716`.
diff --git a/tests/ui/borrowck/fn-item-check-type-params.rs b/tests/ui/borrowck/fn-item-check-type-params.rs
new file mode 100644
index 00000000000..805c0d00de5
--- /dev/null
+++ b/tests/ui/borrowck/fn-item-check-type-params.rs
@@ -0,0 +1,57 @@
+// Regression test for #104005.
+//
+// Previously, different borrowck implementations used to disagree here.
+// The status of each is documented on `fn test_*`.
+
+// check-fail
+
+use std::fmt::Display;
+
+trait Displayable {
+    fn display(self) -> Box<dyn Display>;
+}
+
+impl<T: Display> Displayable for (T, Option<&'static T>) {
+    fn display(self) -> Box<dyn Display> {
+        Box::new(self.0)
+    }
+}
+
+fn extend_lt<T, U>(val: T) -> Box<dyn Display>
+where
+    (T, Option<U>): Displayable,
+{
+    Displayable::display((val, None))
+}
+
+// AST: fail
+// HIR: pass
+// MIR: pass
+pub fn test_call<'a>(val: &'a str) {
+    extend_lt(val);
+    //~^ ERROR borrowed data escapes outside of function
+}
+
+// AST: fail
+// HIR: fail
+// MIR: pass
+pub fn test_coercion<'a>() {
+    let _: fn(&'a str) -> _ = extend_lt;
+    //~^ ERROR lifetime may not live long enough
+}
+
+// AST: fail
+// HIR: fail
+// MIR: fail
+pub fn test_arg() {
+    fn want<I, O>(_: I, _: impl Fn(I) -> O) {}
+    want(&String::new(), extend_lt);
+    //~^ ERROR temporary value dropped while borrowed
+}
+
+// An exploit of the unsoundness.
+fn main() {
+    let val = extend_lt(&String::from("blah blah blah"));
+    //~^ ERROR temporary value dropped while borrowed
+    println!("{}", val);
+}
diff --git a/tests/ui/borrowck/fn-item-check-type-params.stderr b/tests/ui/borrowck/fn-item-check-type-params.stderr
new file mode 100644
index 00000000000..3a29edc55c5
--- /dev/null
+++ b/tests/ui/borrowck/fn-item-check-type-params.stderr
@@ -0,0 +1,43 @@
+error[E0521]: borrowed data escapes outside of function
+  --> $DIR/fn-item-check-type-params.rs:31:5
+   |
+LL | pub fn test_call<'a>(val: &'a str) {
+   |                  --  --- `val` is a reference that is only valid in the function body
+   |                  |
+   |                  lifetime `'a` defined here
+LL |     extend_lt(val);
+   |     ^^^^^^^^^^^^^^
+   |     |
+   |     `val` escapes the function body here
+   |     argument requires that `'a` must outlive `'static`
+
+error: lifetime may not live long enough
+  --> $DIR/fn-item-check-type-params.rs:39:12
+   |
+LL | pub fn test_coercion<'a>() {
+   |                      -- lifetime `'a` defined here
+LL |     let _: fn(&'a str) -> _ = extend_lt;
+   |            ^^^^^^^^^^^^^^^^ type annotation requires that `'a` must outlive `'static`
+
+error[E0716]: temporary value dropped while borrowed
+  --> $DIR/fn-item-check-type-params.rs:48:11
+   |
+LL |     want(&String::new(), extend_lt);
+   |     ------^^^^^^^^^^^^^------------- temporary value is freed at the end of this statement
+   |     |     |
+   |     |     creates a temporary value which is freed while still in use
+   |     argument requires that borrow lasts for `'static`
+
+error[E0716]: temporary value dropped while borrowed
+  --> $DIR/fn-item-check-type-params.rs:54:26
+   |
+LL |     let val = extend_lt(&String::from("blah blah blah"));
+   |               -----------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-- temporary value is freed at the end of this statement
+   |               |          |
+   |               |          creates a temporary value which is freed while still in use
+   |               argument requires that borrow lasts for `'static`
+
+error: aborting due to 4 previous errors
+
+Some errors have detailed explanations: E0521, E0716.
+For more information about an error, try `rustc --explain E0521`.
diff --git a/tests/ui/higher-ranked/trait-bounds/issue-59311.rs b/tests/ui/higher-ranked/trait-bounds/issue-59311.rs
index 3ad548450e5..387c78a802a 100644
--- a/tests/ui/higher-ranked/trait-bounds/issue-59311.rs
+++ b/tests/ui/higher-ranked/trait-bounds/issue-59311.rs
@@ -17,6 +17,7 @@ where
     v.t(|| {});
     //~^ ERROR: higher-ranked lifetime error
     //~| ERROR: higher-ranked lifetime error
+    //~| ERROR: higher-ranked lifetime error
 }
 
 fn main() {}
diff --git a/tests/ui/higher-ranked/trait-bounds/issue-59311.stderr b/tests/ui/higher-ranked/trait-bounds/issue-59311.stderr
index e50aad876d8..3053a299802 100644
--- a/tests/ui/higher-ranked/trait-bounds/issue-59311.stderr
+++ b/tests/ui/higher-ranked/trait-bounds/issue-59311.stderr
@@ -7,6 +7,15 @@ LL |     v.t(|| {});
    = note: could not prove `{closure@$DIR/issue-59311.rs:17:9: 17:11} well-formed`
 
 error: higher-ranked lifetime error
+  --> $DIR/issue-59311.rs:17:5
+   |
+LL |     v.t(|| {});
+   |     ^^^^^^^^^^
+   |
+   = note: could not prove `{closure@$DIR/issue-59311.rs:17:9: 17:11} well-formed`
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+
+error: higher-ranked lifetime error
   --> $DIR/issue-59311.rs:17:9
    |
 LL |     v.t(|| {});
@@ -14,5 +23,5 @@ LL |     v.t(|| {});
    |
    = note: could not prove `for<'a> &'a V: 'b`
 
-error: aborting due to 2 previous errors
+error: aborting due to 3 previous errors
 
diff --git a/tests/ui/implied-bounds/implied-bounds-on-trait-hierarchy.rs b/tests/ui/implied-bounds/implied-bounds-on-trait-hierarchy-1.rs
index 9c26cd59d10..b532a110a1c 100644
--- a/tests/ui/implied-bounds/implied-bounds-on-trait-hierarchy.rs
+++ b/tests/ui/implied-bounds/implied-bounds-on-trait-hierarchy-1.rs
@@ -1,9 +1,7 @@
-// check-pass
-// known-bug: #84591
+// issue: #84591
 
-// Should fail. Subtrait can incorrectly extend supertrait lifetimes even when
-// supertrait has weaker implied bounds than subtrait. Strongly related to
-// issue #25860.
+// Subtrait was able to incorrectly extend supertrait lifetimes even when
+// supertrait had weaker implied bounds than subtrait.
 
 trait Subtrait<T>: Supertrait {}
 trait Supertrait {
@@ -34,6 +32,7 @@ fn main() {
     {
         let x = "Hello World".to_string();
         subs_to_soup((x.as_str(), &mut d));
+        //~^ does not live long enough
     }
     println!("{}", d);
 }
diff --git a/tests/ui/implied-bounds/implied-bounds-on-trait-hierarchy-1.stderr b/tests/ui/implied-bounds/implied-bounds-on-trait-hierarchy-1.stderr
new file mode 100644
index 00000000000..f44defccf58
--- /dev/null
+++ b/tests/ui/implied-bounds/implied-bounds-on-trait-hierarchy-1.stderr
@@ -0,0 +1,16 @@
+error[E0597]: `x` does not live long enough
+  --> $DIR/implied-bounds-on-trait-hierarchy-1.rs:34:23
+   |
+LL |         let x = "Hello World".to_string();
+   |             - binding `x` declared here
+LL |         subs_to_soup((x.as_str(), &mut d));
+   |                       ^ borrowed value does not live long enough
+LL |
+LL |     }
+   |     - `x` dropped here while still borrowed
+LL |     println!("{}", d);
+   |                    - borrow later used here
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/tests/ui/implied-bounds/implied-bounds-on-trait-hierarchy-2.rs b/tests/ui/implied-bounds/implied-bounds-on-trait-hierarchy-2.rs
new file mode 100644
index 00000000000..511a9ad9a2a
--- /dev/null
+++ b/tests/ui/implied-bounds/implied-bounds-on-trait-hierarchy-2.rs
@@ -0,0 +1,45 @@
+// check-pass
+// known-bug: #84591
+
+trait Subtrait<'a, 'b, R>: Supertrait<'a, 'b> {}
+trait Supertrait<'a, 'b> {
+    fn convert<T: ?Sized>(x: &'a T) -> &'b T;
+}
+
+fn need_hrtb_subtrait<'a_, 'b_, S, T: ?Sized>(x: &'a_ T) -> &'b_ T
+where
+    S: for<'a, 'b> Subtrait<'a, 'b, &'b &'a ()>,
+{
+    need_hrtb_supertrait::<S, T>(x)
+    // This call works and drops the implied bound `'a: 'b`
+    // of the where-bound. This means the where-bound can
+    // now be used to transmute any two lifetimes.
+}
+
+fn need_hrtb_supertrait<'a_, 'b_, S, T: ?Sized>(x: &'a_ T) -> &'b_ T
+where
+    S: for<'a, 'b> Supertrait<'a, 'b>,
+{
+    S::convert(x)
+}
+
+struct MyStruct;
+impl<'a: 'b, 'b> Supertrait<'a, 'b> for MyStruct {
+    fn convert<T: ?Sized>(x: &'a T) -> &'b T {
+        x
+    }
+}
+impl<'a, 'b> Subtrait<'a, 'b, &'b &'a ()> for MyStruct {}
+
+fn extend_lifetime<'a, 'b, T: ?Sized>(x: &'a T) -> &'b T {
+    need_hrtb_subtrait::<MyStruct, T>(x)
+}
+
+fn main() {
+    let d;
+    {
+        let x = "Hello World".to_string();
+        d = extend_lifetime(&x);
+    }
+    println!("{}", d);
+}
diff --git a/tests/ui/lifetimes/lifetime-errors/issue_74400.rs b/tests/ui/lifetimes/lifetime-errors/issue_74400.rs
index ddb8bacce8f..f17e0a678c9 100644
--- a/tests/ui/lifetimes/lifetime-errors/issue_74400.rs
+++ b/tests/ui/lifetimes/lifetime-errors/issue_74400.rs
@@ -11,6 +11,8 @@ fn f<T, S>(data: &[T], key: impl Fn(&T) -> S) {
 fn g<T>(data: &[T]) {
     f(data, identity)
     //~^ ERROR the parameter type
+    //~| ERROR the parameter type
+    //~| ERROR the parameter type
     //~| ERROR mismatched types
     //~| ERROR implementation of `FnOnce` is not general
 }
diff --git a/tests/ui/lifetimes/lifetime-errors/issue_74400.stderr b/tests/ui/lifetimes/lifetime-errors/issue_74400.stderr
index 677f918fe93..beb838d2ff8 100644
--- a/tests/ui/lifetimes/lifetime-errors/issue_74400.stderr
+++ b/tests/ui/lifetimes/lifetime-errors/issue_74400.stderr
@@ -12,6 +12,36 @@ help: consider adding an explicit lifetime bound
 LL | fn g<T: 'static>(data: &[T]) {
    |       +++++++++
 
+error[E0310]: the parameter type `T` may not live long enough
+  --> $DIR/issue_74400.rs:12:5
+   |
+LL |     f(data, identity)
+   |     ^^^^^^^^^^^^^^^^^
+   |     |
+   |     the parameter type `T` must be valid for the static lifetime...
+   |     ...so that the type `T` will meet its required lifetime bounds
+   |
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+help: consider adding an explicit lifetime bound
+   |
+LL | fn g<T: 'static>(data: &[T]) {
+   |       +++++++++
+
+error[E0310]: the parameter type `T` may not live long enough
+  --> $DIR/issue_74400.rs:12:5
+   |
+LL |     f(data, identity)
+   |     ^^^^^^^^^^^^^^^^^
+   |     |
+   |     the parameter type `T` must be valid for the static lifetime...
+   |     ...so that the type `T` will meet its required lifetime bounds
+   |
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+help: consider adding an explicit lifetime bound
+   |
+LL | fn g<T: 'static>(data: &[T]) {
+   |       +++++++++
+
 error[E0308]: mismatched types
   --> $DIR/issue_74400.rs:12:5
    |
@@ -35,7 +65,7 @@ LL |     f(data, identity)
    = note: `fn(&'2 T) -> &'2 T {identity::<&'2 T>}` must implement `FnOnce<(&'1 T,)>`, for any lifetime `'1`...
    = note: ...but it actually implements `FnOnce<(&'2 T,)>`, for some specific lifetime `'2`
 
-error: aborting due to 3 previous errors
+error: aborting due to 5 previous errors
 
 Some errors have detailed explanations: E0308, E0310.
 For more information about an error, try `rustc --explain E0308`.
diff --git a/tests/ui/type-alias-impl-trait/wf-nested.fail.stderr b/tests/ui/type-alias-impl-trait/wf-nested.fail.stderr
index dcc4b8021ea..17c1f8897bf 100644
--- a/tests/ui/type-alias-impl-trait/wf-nested.fail.stderr
+++ b/tests/ui/type-alias-impl-trait/wf-nested.fail.stderr
@@ -1,5 +1,5 @@
 error[E0310]: the parameter type `T` may not live long enough
-  --> $DIR/wf-nested.rs:55:27
+  --> $DIR/wf-nested.rs:57:27
    |
 LL |     type InnerOpaque<T> = impl Sized;
    |                           ^^^^^^^^^^
diff --git a/tests/ui/type-alias-impl-trait/wf-nested.pass_sound.stderr b/tests/ui/type-alias-impl-trait/wf-nested.pass_sound.stderr
index 121664bd956..f5d3a218542 100644
--- a/tests/ui/type-alias-impl-trait/wf-nested.pass_sound.stderr
+++ b/tests/ui/type-alias-impl-trait/wf-nested.pass_sound.stderr
@@ -12,6 +12,21 @@ help: consider adding an explicit lifetime bound
 LL |     fn test<T: 'static>() {
    |              +++++++++
 
-error: aborting due to 1 previous error
+error[E0310]: the parameter type `T` may not live long enough
+  --> $DIR/wf-nested.rs:46:17
+   |
+LL |         let _ = outer.get();
+   |                 ^^^^^^^^^^^
+   |                 |
+   |                 the parameter type `T` must be valid for the static lifetime...
+   |                 ...so that the type `T` will meet its required lifetime bounds
+   |
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+help: consider adding an explicit lifetime bound
+   |
+LL |     fn test<T: 'static>() {
+   |              +++++++++
+
+error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0310`.
diff --git a/tests/ui/type-alias-impl-trait/wf-nested.rs b/tests/ui/type-alias-impl-trait/wf-nested.rs
index de388329489..2f90c4e00e3 100644
--- a/tests/ui/type-alias-impl-trait/wf-nested.rs
+++ b/tests/ui/type-alias-impl-trait/wf-nested.rs
@@ -43,7 +43,9 @@ mod pass_sound {
 
     fn test<T>() {
         let outer = define::<T>();
-        let _ = outer.get(); //[pass_sound]~ ERROR `T` may not live long enough
+        let _ = outer.get();
+        //[pass_sound]~^ ERROR `T` may not live long enough
+        //[pass_sound]~| ERROR `T` may not live long enough
     }
 }
 
diff --git a/tests/ui/wf/wf-in-fn-type-implicit.rs b/tests/ui/wf/wf-in-fn-type-implicit.rs
deleted file mode 100644
index c5ff92c8875..00000000000
--- a/tests/ui/wf/wf-in-fn-type-implicit.rs
+++ /dev/null
@@ -1,37 +0,0 @@
-// check-pass
-// known-bug: #104005
-
-// Should fail. Function type parameters with implicit type annotations are not
-// checked for well-formedness, which allows incorrect borrowing.
-
-// In contrast, user annotations are always checked for well-formedness, and the
-// commented code below is correctly rejected by the borrow checker.
-
-use std::fmt::Display;
-
-trait Displayable {
-    fn display(self) -> Box<dyn Display>;
-}
-
-impl<T: Display> Displayable for (T, Option<&'static T>) {
-    fn display(self) -> Box<dyn Display> {
-        Box::new(self.0)
-    }
-}
-
-fn extend_lt<T, U>(val: T) -> Box<dyn Display>
-where
-    (T, Option<U>): Displayable,
-{
-    Displayable::display((val, None))
-}
-
-fn main() {
-    // *incorrectly* compiles
-    let val = extend_lt(&String::from("blah blah blah"));
-    println!("{}", val);
-
-    // *correctly* fails to compile
-    // let val = extend_lt::<_, &_>(&String::from("blah blah blah"));
-    // println!("{}", val);
-}