about summary refs log tree commit diff
diff options
context:
space:
mode:
authorSteven Malis <smmalis37@gmail.com>2020-07-25 02:03:50 -0700
committerSteven Malis <smmalis37@gmail.com>2020-07-25 02:09:00 -0700
commit9e42d3e43494c3cef646dacafa9908d7413c8e53 (patch)
tree95a4baeecae560b7bab744ed6d4a981ab709a964
parent0e11fc8053d32c44e7152865852acc5c3c54efb3 (diff)
downloadrust-9e42d3e43494c3cef646dacafa9908d7413c8e53.tar.gz
rust-9e42d3e43494c3cef646dacafa9908d7413c8e53.zip
Pull out some shared code into a new function
-rw-r--r--src/librustc_typeck/astconv.rs84
1 files changed, 44 insertions, 40 deletions
diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs
index e6d59d30e2f..ccacd7a6aba 100644
--- a/src/librustc_typeck/astconv.rs
+++ b/src/librustc_typeck/astconv.rs
@@ -1483,36 +1483,25 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                     tcx.collect_referenced_late_bound_regions(&ty::Binder::bind(ty));
                 debug!("late_bound_in_trait_ref = {:?}", late_bound_in_trait_ref);
                 debug!("late_bound_in_ty = {:?}", late_bound_in_ty);
-                for br in late_bound_in_ty.difference(&late_bound_in_trait_ref) {
-                    let br_name = match *br {
-                        ty::BrNamed(_, name) => format!("lifetime `{}`", name),
-                        _ => "an anonymous lifetime".to_string(),
-                    };
-                    // FIXME: point at the type params that don't have appropriate lifetimes:
-                    // struct S1<F: for<'a> Fn(&i32, &i32) -> &'a i32>(F);
-                    //                         ----  ----     ^^^^^^^
-                    let mut err = struct_span_err!(
-                        tcx.sess,
-                        binding.span,
-                        E0582,
-                        "binding for associated type `{}` references {}, \
-                         which does not appear in the trait input types",
-                        binding.item_name,
-                        br_name
-                    );
-
-                    if let ty::BrAnon(_) = *br {
-                        // The only way for an anonymous lifetime to wind up
-                        // in the return type but **also** be unconstrained is
-                        // if it only appears in "associated types" in the
-                        // input. See #62200 for an example. In this case,
-                        // though we can easily give a hint that ought to be
-                        // relevant.
-                        err.note("lifetimes appearing in an associated type are not considered constrained");
-                    }
 
-                    err.emit();
-                }
+                // FIXME: point at the type params that don't have appropriate lifetimes:
+                // struct S1<F: for<'a> Fn(&i32, &i32) -> &'a i32>(F);
+                //                         ----  ----     ^^^^^^^
+                self.validate_late_bound_regions(
+                    late_bound_in_trait_ref,
+                    late_bound_in_ty,
+                    |br_name| {
+                        struct_span_err!(
+                            tcx.sess,
+                            binding.span,
+                            E0582,
+                            "binding for associated type `{}` references {}, \
+                             which does not appear in the trait input types",
+                            binding.item_name,
+                            br_name
+                        )
+                    },
+                );
             }
         }
 
@@ -3085,33 +3074,48 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
             tcx.collect_constrained_late_bound_regions(&inputs.map_bound(|i| i.to_owned()));
         let output = bare_fn_ty.output();
         let late_bound_in_ret = tcx.collect_referenced_late_bound_regions(&output);
-        for br in late_bound_in_ret.difference(&late_bound_in_args) {
-            let lifetime_name = match *br {
-                ty::BrNamed(_, name) => format!("lifetime `{}`,", name),
-                ty::BrAnon(_) | ty::BrEnv => "an anonymous lifetime".to_string(),
-            };
-            let mut err = struct_span_err!(
+
+        self.validate_late_bound_regions(late_bound_in_args, late_bound_in_ret, |br_name| {
+            struct_span_err!(
                 tcx.sess,
                 decl.output.span(),
                 E0581,
                 "return type references {} which is not constrained by the fn input types",
-                lifetime_name
-            );
+                br_name
+            )
+        });
+
+        bare_fn_ty
+    }
+
+    fn validate_late_bound_regions(
+        &self,
+        constrained_regions: FxHashSet<ty::BoundRegion>,
+        referenced_regions: FxHashSet<ty::BoundRegion>,
+        generate_err: impl Fn(&str) -> rustc_errors::DiagnosticBuilder<'tcx>,
+    ) {
+        for br in referenced_regions.difference(&constrained_regions) {
+            let br_name = match *br {
+                ty::BrNamed(_, name) => format!("lifetime `{}`", name),
+                ty::BrAnon(_) | ty::BrEnv => "an anonymous lifetime".to_string(),
+            };
+
+            let mut err = generate_err(&br_name);
+
             if let ty::BrAnon(_) = *br {
                 // The only way for an anonymous lifetime to wind up
                 // in the return type but **also** be unconstrained is
                 // if it only appears in "associated types" in the
-                // input. See #47511 for an example. In this case,
+                // input. See #47511 and #62200 for examples. In this case,
                 // though we can easily give a hint that ought to be
                 // relevant.
                 err.note(
                     "lifetimes appearing in an associated type are not considered constrained",
                 );
             }
+
             err.emit();
         }
-
-        bare_fn_ty
     }
 
     /// Given the bounds on an object, determines what single region bound (if any) we can