Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

do not ICE when return type includes unconstrained anon region #47668

Merged
merged 1 commit into from
Jan 26, 2018
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