Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 20 additions & 15 deletions src/librustc_typeck/astconv.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1206,22 +1206,27 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
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 br_name = match *br {
ty::BrNamed(_, name) => name,
_ => {
span_bug!(
decl.output.span(),
"anonymous bound region {:?} in return but not args",
br);
}
let lifetime_name = match *br {
ty::BrNamed(_, name) => format!("lifetime `{}`,", name),
ty::BrAnon(_) | ty::BrFresh(_) | ty::BrEnv => format!("an anonymous lifetime"),
};
struct_span_err!(tcx.sess,
decl.output.span(),
E0581,
"return type references lifetime `{}`, \
which does not appear in the fn input types",
br_name)
.emit();
let mut err = struct_span_err!(tcx.sess,
decl.output.span(),
E0581,
"return type references {} \
which is not constrained by the fn input types",
lifetime_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,
// 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
Expand Down
35 changes: 35 additions & 0 deletions src/test/ui/issue-47511.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

// Regression test for #47511: anonymous lifetimes can appear
// unconstrained in a return type, but only if they appear just once
// in the input, as the input to a projection.

fn f(_: X) -> X {
//~^ ERROR return type references an anonymous lifetime
unimplemented!()
}

fn g<'a>(_: X<'a>) -> X<'a> {
//~^ ERROR return type references lifetime `'a`, which is not constrained
unimplemented!()
}

type X<'a> = <&'a () as Trait>::Value;

trait Trait {
type Value;
}

impl<'a> Trait for &'a () {
type Value = ();
}

fn main() {}
16 changes: 16 additions & 0 deletions src/test/ui/issue-47511.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
error[E0581]: return type references an anonymous lifetime which is not constrained by the fn input types
--> $DIR/issue-47511.rs:15:15
|
15 | fn f(_: X) -> X {
| ^
|
= note: lifetimes appearing in an associated type are not considered constrained

error[E0581]: return type references lifetime `'a`, which is not constrained by the fn input types
--> $DIR/issue-47511.rs:20:23
|
20 | fn g<'a>(_: X<'a>) -> X<'a> {
| ^^^^^

error: aborting due to 2 previous errors