Skip to content

Commit

Permalink
Auto merge of #74737 - smmalis37:astconv-factor, r=davidtwco
Browse files Browse the repository at this point in the history
Pull out some duplicated code into a new function

I debated pulling the actual struct_span_err calls into the new method, but I felt like having to pass in multiple arguments for it and wiring up string formatting outweighed the benefits.

Viewing the diff with whitespace ignored is recommended.
  • Loading branch information
bors committed Jul 27, 2020
2 parents 1841fb9 + 617dd0a commit 9af6b3d
Show file tree
Hide file tree
Showing 2 changed files with 46 additions and 42 deletions.
86 changes: 45 additions & 41 deletions src/librustc_typeck/astconv.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
)
},
);
}
}

Expand Down Expand Up @@ -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
);
"return type references {}, which is not constrained by the fn input types",
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
Expand Down
2 changes: 1 addition & 1 deletion src/test/ui/issues/issue-47511.stderr
Original file line number Diff line number Diff line change
@@ -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 {
Expand Down

0 comments on commit 9af6b3d

Please sign in to comment.