Skip to content

Commit

Permalink
do not ICE when return type includes unconstrained anon region
Browse files Browse the repository at this point in the history
It turns out that this *can* happen after all, if the region is only
used in projections from the input types.
  • Loading branch information
nikomatsakis committed Jan 22, 2018
1 parent fdc18b3 commit 215d66b
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 215d66b

Please sign in to comment.