about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_hir_analysis/src/check/compare_impl_item.rs48
-rw-r--r--tests/ui/impl-trait/in-trait/do-not-imply-from-trait-impl.rs30
-rw-r--r--tests/ui/impl-trait/in-trait/do-not-imply-from-trait-impl.stderr22
-rw-r--r--tests/ui/impl-trait/in-trait/method-signature-matches.lt.stderr8
-rw-r--r--tests/ui/impl-trait/in-trait/rpitit-hidden-types-self-implied-wf.stderr4
-rw-r--r--tests/ui/impl-trait/in-trait/signature-mismatch.failure.stderr15
-rw-r--r--tests/ui/impl-trait/in-trait/signature-mismatch.rs2
-rw-r--r--tests/ui/impl-trait/precise-capturing/rpitit-impl-captures-too-much.stderr7
8 files changed, 92 insertions, 44 deletions
diff --git a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs
index 2891b48a154..06dee6bda54 100644
--- a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs
+++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs
@@ -523,8 +523,9 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>(
     let impl_sig = ocx.normalize(
         &misc_cause,
         param_env,
-        tcx.liberate_late_bound_regions(
-            impl_m.def_id,
+        infcx.instantiate_binder_with_fresh_vars(
+            return_span,
+            infer::HigherRankedType,
             tcx.fn_sig(impl_m.def_id).instantiate_identity(),
         ),
     );
@@ -536,10 +537,9 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>(
     // them with inference variables.
     // We will use these inference variables to collect the hidden types of RPITITs.
     let mut collector = ImplTraitInTraitCollector::new(&ocx, return_span, param_env, impl_m_def_id);
-    let unnormalized_trait_sig = infcx
-        .instantiate_binder_with_fresh_vars(
-            return_span,
-            infer::HigherRankedType,
+    let unnormalized_trait_sig = tcx
+        .liberate_late_bound_regions(
+            impl_m.def_id,
             tcx.fn_sig(trait_m.def_id).instantiate(tcx, trait_to_impl_args),
         )
         .fold_with(&mut collector);
@@ -702,8 +702,8 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>(
 
     let mut remapped_types = DefIdMap::default();
     for (def_id, (ty, args)) in collected_types {
-        match infcx.fully_resolve((ty, args)) {
-            Ok((ty, args)) => {
+        match infcx.fully_resolve(ty) {
+            Ok(ty) => {
                 // `ty` contains free regions that we created earlier while liberating the
                 // trait fn signature. However, projection normalization expects `ty` to
                 // contains `def_id`'s early-bound regions.
@@ -883,33 +883,27 @@ impl<'tcx> ty::FallibleTypeFolder<TyCtxt<'tcx>> for RemapHiddenTyRegions<'tcx> {
         self.tcx
     }
 
-    fn try_fold_ty(&mut self, t: Ty<'tcx>) -> Result<Ty<'tcx>, Self::Error> {
-        if let ty::Alias(ty::Opaque, ty::AliasTy { args, def_id, .. }) = *t.kind() {
-            let mut mapped_args = Vec::with_capacity(args.len());
-            for (arg, v) in std::iter::zip(args, self.tcx.variances_of(def_id)) {
-                mapped_args.push(match (arg.unpack(), v) {
-                    // Skip uncaptured opaque args
-                    (ty::GenericArgKind::Lifetime(_), ty::Bivariant) => arg,
-                    _ => arg.try_fold_with(self)?,
-                });
-            }
-            Ok(Ty::new_opaque(self.tcx, def_id, self.tcx.mk_args(&mapped_args)))
-        } else {
-            t.try_super_fold_with(self)
-        }
-    }
-
     fn try_fold_region(
         &mut self,
         region: ty::Region<'tcx>,
     ) -> Result<ty::Region<'tcx>, Self::Error> {
         match region.kind() {
-            // Remap late-bound regions from the function.
+            // Never remap bound regions or `'static`
+            ty::ReBound(..) | ty::ReStatic | ty::ReError(_) => return Ok(region),
+            // We always remap liberated late-bound regions from the function.
             ty::ReLateParam(_) => {}
             // Remap early-bound regions as long as they don't come from the `impl` itself,
             // in which case we don't really need to renumber them.
-            ty::ReEarlyParam(ebr) if ebr.index as usize >= self.num_impl_args => {}
-            _ => return Ok(region),
+            ty::ReEarlyParam(ebr) => {
+                if ebr.index as usize >= self.num_impl_args {
+                    // Remap
+                } else {
+                    return Ok(region);
+                }
+            }
+            ty::ReVar(_) | ty::RePlaceholder(_) | ty::ReErased => unreachable!(
+                "should not have leaked vars or placeholders into hidden type of RPITIT"
+            ),
         }
 
         let e = if let Some(id_region) = self.map.get(&region) {
diff --git a/tests/ui/impl-trait/in-trait/do-not-imply-from-trait-impl.rs b/tests/ui/impl-trait/in-trait/do-not-imply-from-trait-impl.rs
new file mode 100644
index 00000000000..30ca3d271b8
--- /dev/null
+++ b/tests/ui/impl-trait/in-trait/do-not-imply-from-trait-impl.rs
@@ -0,0 +1,30 @@
+// Make sure that we don't accidentally collect an RPITIT hidden type that does not
+// hold for all instantiations of the trait signature.
+
+trait MkStatic {
+    fn mk_static(self) -> &'static str;
+}
+
+impl MkStatic for &'static str {
+    fn mk_static(self) -> &'static str { self }
+}
+
+trait Foo {
+    fn foo<'a: 'static, 'late>(&'late self) -> impl MkStatic;
+}
+
+impl Foo for str {
+    fn foo<'a: 'static>(&'a self) -> impl MkStatic + 'static {
+    //~^ ERROR method not compatible with trait
+        self
+    }
+}
+
+fn call_foo<T: Foo + ?Sized>(t: &T) -> &'static str {
+    t.foo().mk_static()
+}
+
+fn main() {
+    let s = call_foo(String::from("hello, world").as_str());
+    println!("> {s}");
+}
diff --git a/tests/ui/impl-trait/in-trait/do-not-imply-from-trait-impl.stderr b/tests/ui/impl-trait/in-trait/do-not-imply-from-trait-impl.stderr
new file mode 100644
index 00000000000..95d8699e19f
--- /dev/null
+++ b/tests/ui/impl-trait/in-trait/do-not-imply-from-trait-impl.stderr
@@ -0,0 +1,22 @@
+error[E0308]: method not compatible with trait
+  --> $DIR/do-not-imply-from-trait-impl.rs:17:38
+   |
+LL |     fn foo<'a: 'static>(&'a self) -> impl MkStatic + 'static {
+   |                                      ^^^^^^^^^^^^^^^^^^^^^^^ lifetime mismatch
+   |
+   = note: expected signature `fn(&'late _) -> _`
+              found signature `fn(&'a _) -> _`
+note: the lifetime `'late` as defined here...
+  --> $DIR/do-not-imply-from-trait-impl.rs:13:25
+   |
+LL |     fn foo<'a: 'static, 'late>(&'late self) -> impl MkStatic;
+   |                         ^^^^^
+note: ...does not necessarily outlive the lifetime `'a` as defined here
+  --> $DIR/do-not-imply-from-trait-impl.rs:17:12
+   |
+LL |     fn foo<'a: 'static>(&'a self) -> impl MkStatic + 'static {
+   |            ^^
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/impl-trait/in-trait/method-signature-matches.lt.stderr b/tests/ui/impl-trait/in-trait/method-signature-matches.lt.stderr
index 6f6b787b6fe..a23879eb6c3 100644
--- a/tests/ui/impl-trait/in-trait/method-signature-matches.lt.stderr
+++ b/tests/ui/impl-trait/in-trait/method-signature-matches.lt.stderr
@@ -11,12 +11,12 @@ note: type in trait
    |
 LL |     fn early<'early, T>(x: &'early T) -> impl Sized;
    |                            ^^^^^^^^^
-   = note: expected signature `fn(&T)`
-              found signature `fn(&'late ())`
+   = note: expected signature `fn(&'early T)`
+              found signature `fn(&())`
 help: change the parameter type to match the trait
    |
-LL |     fn early<'late, T>(_: &T) {}
-   |                           ~~
+LL |     fn early<'late, T>(_: &'early T) {}
+   |                           ~~~~~~~~~
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/impl-trait/in-trait/rpitit-hidden-types-self-implied-wf.stderr b/tests/ui/impl-trait/in-trait/rpitit-hidden-types-self-implied-wf.stderr
index 3430055dab1..4c10422f985 100644
--- a/tests/ui/impl-trait/in-trait/rpitit-hidden-types-self-implied-wf.stderr
+++ b/tests/ui/impl-trait/in-trait/rpitit-hidden-types-self-implied-wf.stderr
@@ -6,9 +6,9 @@ LL |     fn extend(s: &str) -> (Option<&'static &'_ ()>, &'static str) {
    |
    = note: the pointer is valid for the static lifetime
 note: but the referenced data is only valid for the anonymous lifetime defined here
-  --> $DIR/rpitit-hidden-types-self-implied-wf.rs:6:18
+  --> $DIR/rpitit-hidden-types-self-implied-wf.rs:2:18
    |
-LL |     fn extend(s: &str) -> (Option<&'static &'_ ()>, &'static str) {
+LL |     fn extend(_: &str) -> (impl Sized + '_, &'static str);
    |                  ^^^^
 
 error: aborting due to 1 previous error
diff --git a/tests/ui/impl-trait/in-trait/signature-mismatch.failure.stderr b/tests/ui/impl-trait/in-trait/signature-mismatch.failure.stderr
index 56b83cbca77..b27d7870955 100644
--- a/tests/ui/impl-trait/in-trait/signature-mismatch.failure.stderr
+++ b/tests/ui/impl-trait/in-trait/signature-mismatch.failure.stderr
@@ -1,14 +1,15 @@
-error[E0623]: lifetime mismatch
+error[E0477]: the type `impl Future<Output = Vec<u8>>` does not fulfill the required lifetime
   --> $DIR/signature-mismatch.rs:77:10
    |
-LL |         &'a self,
-   |         -------- this parameter and the return type are declared with different lifetimes...
-...
 LL |     ) -> impl Future<Output = Vec<u8>> {
    |          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |          |
-   |          ...but data from `buff` is returned here
+   |
+note: type must outlive the lifetime `'a` as defined here as required by this binding
+  --> $DIR/signature-mismatch.rs:73:32
+   |
+LL |     fn async_fn_reduce_outlive<'a, 'b, T>(
+   |                                ^^
 
 error: aborting due to 1 previous error
 
-For more information about this error, try `rustc --explain E0623`.
+For more information about this error, try `rustc --explain E0477`.
diff --git a/tests/ui/impl-trait/in-trait/signature-mismatch.rs b/tests/ui/impl-trait/in-trait/signature-mismatch.rs
index 55b9a0de5ff..a9885c6a298 100644
--- a/tests/ui/impl-trait/in-trait/signature-mismatch.rs
+++ b/tests/ui/impl-trait/in-trait/signature-mismatch.rs
@@ -75,7 +75,7 @@ impl AsyncTrait for Struct {
         buff: &'b [u8],
         t: T,
     ) -> impl Future<Output = Vec<u8>> {
-        //[failure]~^ ERROR lifetime mismatch
+        //[failure]~^ ERROR the type `impl Future<Output = Vec<u8>>` does not fulfill the required lifetime
         async move {
             let _t = t;
             vec![]
diff --git a/tests/ui/impl-trait/precise-capturing/rpitit-impl-captures-too-much.stderr b/tests/ui/impl-trait/precise-capturing/rpitit-impl-captures-too-much.stderr
index e1856b92910..360f0d7e7f3 100644
--- a/tests/ui/impl-trait/precise-capturing/rpitit-impl-captures-too-much.stderr
+++ b/tests/ui/impl-trait/precise-capturing/rpitit-impl-captures-too-much.stderr
@@ -1,10 +1,11 @@
 error: return type captures more lifetimes than trait definition
   --> $DIR/rpitit-impl-captures-too-much.rs:10:39
    |
+LL |     fn hello(self_: Invariant<'_>) -> impl Sized + use<Self>;
+   |                               -- this lifetime was captured
+...
 LL |     fn hello(self_: Invariant<'_>) -> impl Sized + use<'_> {}
-   |                               --      ^^^^^^^^^^^^^^^^^^^^
-   |                               |
-   |                               this lifetime was captured
+   |                                       ^^^^^^^^^^^^^^^^^^^^
    |
 note: hidden type must only reference lifetimes captured by this impl trait
   --> $DIR/rpitit-impl-captures-too-much.rs:6:39