From 9e42d3e43494c3cef646dacafa9908d7413c8e53 Mon Sep 17 00:00:00 2001 From: Steven Malis Date: Sat, 25 Jul 2020 02:03:50 -0700 Subject: [PATCH 1/2] Pull out some shared code into a new function --- src/librustc_typeck/astconv.rs | 84 ++++++++++++++++++---------------- 1 file changed, 44 insertions(+), 40 deletions(-) diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index e6d59d30e2f58..ccacd7a6aba6a 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 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 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, + referenced_regions: FxHashSet, + 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 From 617dd0a8b9d848f468bc762bd12adc4f2a4af3cb Mon Sep 17 00:00:00 2001 From: Steven Malis Date: Sat, 25 Jul 2020 02:47:16 -0700 Subject: [PATCH 2/2] Fix commas. --- src/librustc_typeck/astconv.rs | 2 +- src/test/ui/issues/issue-47511.stderr | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index ccacd7a6aba6a..21b5f5c9033e6 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -3080,7 +3080,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { tcx.sess, decl.output.span(), E0581, - "return type references {} which is not constrained by the fn input types", + "return type references {}, which is not constrained by the fn input types", br_name ) }); diff --git a/src/test/ui/issues/issue-47511.stderr b/src/test/ui/issues/issue-47511.stderr index 42f2cd1bb1401..4473c0e68cfc8 100644 --- a/src/test/ui/issues/issue-47511.stderr +++ b/src/test/ui/issues/issue-47511.stderr @@ -1,4 +1,4 @@ -error[E0581]: return type references an anonymous lifetime which is not constrained by the fn input types +error[E0581]: return type references an anonymous lifetime, which is not constrained by the fn input types --> $DIR/issue-47511.rs:5:15 | LL | fn f(_: X) -> X {