Skip to content

Commit

Permalink
Rollup merge of rust-lang#47668 - nikomatsakis:issue-47511, r=eddyb
Browse files Browse the repository at this point in the history
do not ICE when return type includes unconstrained anon region

It turns out that this *can* happen after all, if the region is only
used in projections from the input types.

Fixes rust-lang#47511

r? @eddyb
  • Loading branch information
alexcrichton committed Jan 25, 2018
2 parents 014931b + 215d66b commit 0ee698e
Show file tree
Hide file tree
Showing 3 changed files with 71 additions and 15 deletions.
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

0 comments on commit 0ee698e

Please sign in to comment.