Skip to content

Commit

Permalink
improve lifetime errors with implicit trait object lifetimes
Browse files Browse the repository at this point in the history
  • Loading branch information
mark-i-m committed Nov 29, 2019
1 parent c4375c9 commit 1f853d2
Show file tree
Hide file tree
Showing 10 changed files with 114 additions and 98 deletions.
2 changes: 1 addition & 1 deletion src/librustc/ty/sty.rs
Expand Up @@ -69,7 +69,7 @@ pub enum BoundRegion {
impl BoundRegion {
pub fn is_named(&self) -> bool {
match *self {
BoundRegion::BrNamed(..) => true,
BoundRegion::BrNamed(_, name) => name != kw::UnderscoreLifetime,
_ => false,
}
}
Expand Down
Expand Up @@ -78,17 +78,7 @@ impl OutlivesSuggestionBuilder<'a> {
match name.source {
RegionNameSource::NamedEarlyBoundRegion(..)
| RegionNameSource::NamedFreeRegion(..)
| RegionNameSource::Static => {
// FIXME: This is a bit hacky. We should ideally have a semantic way for checking
// if the name is `'_`...
if name.name().with(|name| name != "'_") {
debug!("Region {:?} is suggestable", name);
true
} else {
debug!("Region {:?} is NOT suggestable", name);
false
}
}
| RegionNameSource::Static => true,

// Don't give suggestions for upvars, closure return types, or other unnamable
// regions.
Expand All @@ -98,7 +88,8 @@ impl OutlivesSuggestionBuilder<'a> {
| RegionNameSource::MatchedAdtAndSegment(..)
| RegionNameSource::AnonRegionFromUpvar(..)
| RegionNameSource::AnonRegionFromOutput(..)
| RegionNameSource::AnonRegionFromYieldTy(..) => {
| RegionNameSource::AnonRegionFromYieldTy(..)
| RegionNameSource::AnonRegionFromTraitObjAsync(..) => {
debug!("Region {:?} is NOT suggestable", name);
false
}
Expand Down
Expand Up @@ -55,7 +55,10 @@ crate enum RegionNameSource {
AnonRegionFromUpvar(Span, String),
/// The region corresponding to the return type of a closure.
AnonRegionFromOutput(Span, String, String),
/// The region from a type yielded by a generator.
AnonRegionFromYieldTy(Span, String),
/// An anonymous region from a trait object in an async fn.
AnonRegionFromTraitObjAsync(Span),
}

/// Records region names that have been assigned before so that we can use the same ones in later
Expand Down Expand Up @@ -113,7 +116,8 @@ impl RegionName {
RegionNameSource::MatchedAdtAndSegment(..) |
RegionNameSource::AnonRegionFromUpvar(..) |
RegionNameSource::AnonRegionFromOutput(..) |
RegionNameSource::AnonRegionFromYieldTy(..) => false,
RegionNameSource::AnonRegionFromYieldTy(..) |
RegionNameSource::AnonRegionFromTraitObjAsync(..) => false,
}
}

Expand All @@ -137,7 +141,8 @@ impl RegionName {
RegionNameSource::CannotMatchHirTy(span, type_name) => {
diag.span_label(*span, format!("has type `{}`", type_name));
}
RegionNameSource::MatchedHirTy(span) => {
RegionNameSource::MatchedHirTy(span) |
RegionNameSource::AnonRegionFromTraitObjAsync(span) => {
diag.span_label(
*span,
format!("let's call the lifetime of this reference `{}`", self),
Expand Down Expand Up @@ -287,11 +292,30 @@ impl<'tcx> RegionInferenceContext<'tcx> {

ty::ReFree(free_region) => match free_region.bound_region {
ty::BoundRegion::BrNamed(_, name) => {
// Get the span to point to, even if we don't use the name.
let span = self.get_named_span(tcx, error_region, name);
Some(RegionName {
name,
source: RegionNameSource::NamedFreeRegion(span),
})
debug!("bound region named: {:?}, is_named: {:?}",
name, free_region.bound_region.is_named());

if free_region.bound_region.is_named() {
// A named region that is actually named.
Some(RegionName {
name,
source: RegionNameSource::NamedFreeRegion(span),
})
} else {
// If we spuriously thought that the region is named, we should let the
// system generate a true name for error messages. Currently this can
// happen if we have an elided name in a trait object used in an async fn
// for example: the compiler will generate a region named `'_`, but
// reporting such a name is not actually useful, so we synthesize a name
// for it instead.
let name = self.synthesize_region_name(renctx);
Some(RegionName {
name,
source: RegionNameSource::AnonRegionFromTraitObjAsync(span),
})
}
}

ty::BoundRegion::BrEnv => {
Expand Down
4 changes: 2 additions & 2 deletions src/test/ui/async-await/issues/issue-63388-1.nll.stderr
Expand Up @@ -12,12 +12,12 @@ error: lifetime may not live long enough
LL | async fn do_sth<'a>(
| -- lifetime `'a` defined here
LL | &'a self, foo: &dyn Foo
| - lifetime `'_` defined here
| - let's call the lifetime of this reference `'1`
LL | ) -> &dyn Foo
LL | / {
LL | | foo
LL | | }
| |_____^ function was supposed to return data with lifetime `'a` but it is returning data with lifetime `'_`
| |_____^ function was supposed to return data with lifetime `'a` but it is returning data with lifetime `'1`

error: aborting due to 2 previous errors

Expand Down
Expand Up @@ -2,11 +2,11 @@ error: lifetime may not live long enough
--> $DIR/arbitrary_self_types_pin_lifetime_impl_trait-async.rs:8:48
|
LL | async fn f(self: Pin<&Self>) -> impl Clone { self }
| - ^^^^^^^^ returning this value requires that `'_` must outlive `'static`
| - ^^^^^^^^ returning this value requires that `'1` must outlive `'static`
| |
| lifetime `'_` defined here
| let's call the lifetime of this reference `'1`
|
help: to allow this `impl Trait` to capture borrowed data with lifetime `'_`, add `'_` as a constraint
help: to allow this `impl Trait` to capture borrowed data with lifetime `'1`, add `'_` as a constraint
|
LL | async fn f(self: Pin<&Self>) -> impl Clone + '_ { self }
| ^^^^^^^^^^^^^^^
Expand Down
Expand Up @@ -10,19 +10,19 @@ error: lifetime may not live long enough
--> $DIR/arbitrary_self_types_pin_lifetime_mismatch-async.rs:8:52
|
LL | async fn a(self: Pin<&Foo>, f: &Foo) -> &Foo { f }
| - ^ function was supposed to return data with lifetime `'_` but it is returning data with lifetime `'_`
| - ^ function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
| |
| lifetime `'_` defined here
| lifetime `'_` defined here
| let's call the lifetime of this reference `'1`
| let's call the lifetime of this reference `'2`

error: lifetime may not live long enough
--> $DIR/arbitrary_self_types_pin_lifetime_mismatch-async.rs:11:75
|
LL | async fn c(self: Pin<&Self>, f: &Foo, g: &Foo) -> (Pin<&Foo>, &Foo) { (self, f) }
| - ^^^^^^^^^ function was supposed to return data with lifetime `'_` but it is returning data with lifetime `'_`
| - ^^^^^^^^^ function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
| |
| lifetime `'_` defined here
| lifetime `'_` defined here
| let's call the lifetime of this reference `'1`
| let's call the lifetime of this reference `'2`

error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds
--> $DIR/arbitrary_self_types_pin_lifetime_mismatch-async.rs:17:58
Expand All @@ -36,8 +36,9 @@ error: lifetime may not live long enough
--> $DIR/arbitrary_self_types_pin_lifetime_mismatch-async.rs:17:64
|
LL | async fn bar<'a>(self: Alias<&Self>, arg: &'a ()) -> &() { arg }
| -- - lifetime `'_` defined here ^^^ function was supposed to return data with lifetime `'_` but it is returning data with lifetime `'a`
| |
| -- - ^^^ function was supposed to return data with lifetime `'1` but it is returning data with lifetime `'a`
| | |
| | let's call the lifetime of this reference `'1`
| lifetime `'a` defined here

error: aborting due to 5 previous errors
Expand Down
36 changes: 18 additions & 18 deletions src/test/ui/self/elision/lt-ref-self-async.nll.stderr
Expand Up @@ -12,10 +12,10 @@ error: lifetime may not live long enough
LL | async fn ref_self(&self, f: &u32) -> &u32 {
| -
| |
| lifetime `'_` defined here
| lifetime `'_` defined here
| let's call the lifetime of this reference `'1`
| let's call the lifetime of this reference `'2`
LL | f
| ^ function was supposed to return data with lifetime `'_` but it is returning data with lifetime `'_`
| ^ function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`

error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds
--> $DIR/lt-ref-self-async.rs:18:48
Expand All @@ -31,10 +31,10 @@ error: lifetime may not live long enough
LL | async fn ref_Self(self: &Self, f: &u32) -> &u32 {
| -
| |
| lifetime `'_` defined here
| lifetime `'_` defined here
| let's call the lifetime of this reference `'1`
| let's call the lifetime of this reference `'2`
LL | f
| ^ function was supposed to return data with lifetime `'_` but it is returning data with lifetime `'_`
| ^ function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`

error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds
--> $DIR/lt-ref-self-async.rs:22:57
Expand All @@ -50,10 +50,10 @@ error: lifetime may not live long enough
LL | async fn box_ref_Self(self: Box<&Self>, f: &u32) -> &u32 {
| -
| |
| lifetime `'_` defined here
| lifetime `'_` defined here
| let's call the lifetime of this reference `'1`
| let's call the lifetime of this reference `'2`
LL | f
| ^ function was supposed to return data with lifetime `'_` but it is returning data with lifetime `'_`
| ^ function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`

error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds
--> $DIR/lt-ref-self-async.rs:26:57
Expand All @@ -69,10 +69,10 @@ error: lifetime may not live long enough
LL | async fn pin_ref_Self(self: Pin<&Self>, f: &u32) -> &u32 {
| -
| |
| lifetime `'_` defined here
| lifetime `'_` defined here
| let's call the lifetime of this reference `'1`
| let's call the lifetime of this reference `'2`
LL | f
| ^ function was supposed to return data with lifetime `'_` but it is returning data with lifetime `'_`
| ^ function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`

error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds
--> $DIR/lt-ref-self-async.rs:30:66
Expand All @@ -88,10 +88,10 @@ error: lifetime may not live long enough
LL | async fn box_box_ref_Self(self: Box<Box<&Self>>, f: &u32) -> &u32 {
| -
| |
| lifetime `'_` defined here
| lifetime `'_` defined here
| let's call the lifetime of this reference `'1`
| let's call the lifetime of this reference `'2`
LL | f
| ^ function was supposed to return data with lifetime `'_` but it is returning data with lifetime `'_`
| ^ function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`

error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds
--> $DIR/lt-ref-self-async.rs:34:62
Expand All @@ -107,10 +107,10 @@ error: lifetime may not live long enough
LL | async fn box_pin_Self(self: Box<Pin<&Self>>, f: &u32) -> &u32 {
| -
| |
| lifetime `'_` defined here
| lifetime `'_` defined here
| let's call the lifetime of this reference `'1`
| let's call the lifetime of this reference `'2`
LL | f
| ^ function was supposed to return data with lifetime `'_` but it is returning data with lifetime `'_`
| ^ function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`

error: aborting due to 12 previous errors

Expand Down
36 changes: 18 additions & 18 deletions src/test/ui/self/elision/ref-mut-self-async.nll.stderr
Expand Up @@ -12,10 +12,10 @@ error: lifetime may not live long enough
LL | async fn ref_self(&mut self, f: &u32) -> &u32 {
| -
| |
| lifetime `'_` defined here
| lifetime `'_` defined here
| let's call the lifetime of this reference `'1`
| let's call the lifetime of this reference `'2`
LL | f
| ^ function was supposed to return data with lifetime `'_` but it is returning data with lifetime `'_`
| ^ function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`

error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds
--> $DIR/ref-mut-self-async.rs:18:52
Expand All @@ -31,10 +31,10 @@ error: lifetime may not live long enough
LL | async fn ref_Self(self: &mut Self, f: &u32) -> &u32 {
| -
| |
| lifetime `'_` defined here
| lifetime `'_` defined here
| let's call the lifetime of this reference `'1`
| let's call the lifetime of this reference `'2`
LL | f
| ^ function was supposed to return data with lifetime `'_` but it is returning data with lifetime `'_`
| ^ function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`

error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds
--> $DIR/ref-mut-self-async.rs:22:61
Expand All @@ -50,10 +50,10 @@ error: lifetime may not live long enough
LL | async fn box_ref_Self(self: Box<&mut Self>, f: &u32) -> &u32 {
| -
| |
| lifetime `'_` defined here
| lifetime `'_` defined here
| let's call the lifetime of this reference `'1`
| let's call the lifetime of this reference `'2`
LL | f
| ^ function was supposed to return data with lifetime `'_` but it is returning data with lifetime `'_`
| ^ function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`

error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds
--> $DIR/ref-mut-self-async.rs:26:61
Expand All @@ -69,10 +69,10 @@ error: lifetime may not live long enough
LL | async fn pin_ref_Self(self: Pin<&mut Self>, f: &u32) -> &u32 {
| -
| |
| lifetime `'_` defined here
| lifetime `'_` defined here
| let's call the lifetime of this reference `'1`
| let's call the lifetime of this reference `'2`
LL | f
| ^ function was supposed to return data with lifetime `'_` but it is returning data with lifetime `'_`
| ^ function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`

error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds
--> $DIR/ref-mut-self-async.rs:30:70
Expand All @@ -88,10 +88,10 @@ error: lifetime may not live long enough
LL | async fn box_box_ref_Self(self: Box<Box<&mut Self>>, f: &u32) -> &u32 {
| -
| |
| lifetime `'_` defined here
| lifetime `'_` defined here
| let's call the lifetime of this reference `'1`
| let's call the lifetime of this reference `'2`
LL | f
| ^ function was supposed to return data with lifetime `'_` but it is returning data with lifetime `'_`
| ^ function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`

error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds
--> $DIR/ref-mut-self-async.rs:34:70
Expand All @@ -107,10 +107,10 @@ error: lifetime may not live long enough
LL | async fn box_pin_ref_Self(self: Box<Pin<&mut Self>>, f: &u32) -> &u32 {
| -
| |
| lifetime `'_` defined here
| lifetime `'_` defined here
| let's call the lifetime of this reference `'1`
| let's call the lifetime of this reference `'2`
LL | f
| ^ function was supposed to return data with lifetime `'_` but it is returning data with lifetime `'_`
| ^ function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`

error: aborting due to 12 previous errors

Expand Down

0 comments on commit 1f853d2

Please sign in to comment.