From d4fe9553f65df51a18999e956fd507e26271e74e Mon Sep 17 00:00:00 2001
From: mibac138 <5672750+mibac138@users.noreply.github.com>
Date: Thu, 7 May 2020 03:57:31 +0200
Subject: [PATCH 01/32] Implement partial error recovery for `let` with
`BinOpEq`
When parsing `let x: i8 += 1` the compiler interprets `i8` as a trait
which makes it more complicated to do error recovery. More advanced
error recovery is not implemented in this commit.
---
src/librustc_parse/parser/stmt.rs | 29 ++++++++++++++++++++++--
src/test/ui/parser/let-binop-plus.rs | 7 ++++++
src/test/ui/parser/let-binop-plus.stderr | 9 ++++++++
src/test/ui/parser/let-binop.rs | 8 +++++++
src/test/ui/parser/let-binop.stderr | 21 +++++++++++++++++
5 files changed, 72 insertions(+), 2 deletions(-)
create mode 100644 src/test/ui/parser/let-binop-plus.rs
create mode 100644 src/test/ui/parser/let-binop-plus.stderr
create mode 100644 src/test/ui/parser/let-binop.rs
create mode 100644 src/test/ui/parser/let-binop.stderr
diff --git a/src/librustc_parse/parser/stmt.rs b/src/librustc_parse/parser/stmt.rs
index 849193151c335..049aa7447f4db 100644
--- a/src/librustc_parse/parser/stmt.rs
+++ b/src/librustc_parse/parser/stmt.rs
@@ -12,7 +12,7 @@ use rustc_ast::ast::{Block, BlockCheckMode, Expr, ExprKind, Local, Stmt, StmtKin
use rustc_ast::ptr::P;
use rustc_ast::token::{self, TokenKind};
use rustc_ast::util::classify;
-use rustc_errors::{Applicability, PResult};
+use rustc_errors::{struct_span_err, Applicability, PResult};
use rustc_span::source_map::{BytePos, Span};
use rustc_span::symbol::{kw, sym};
@@ -217,7 +217,32 @@ impl<'a> Parser<'a> {
/// Parses the RHS of a local variable declaration (e.g., '= 14;').
fn parse_initializer(&mut self, skip_eq: bool) -> PResult<'a, Option
>> {
- if self.eat(&token::Eq) || skip_eq { Ok(Some(self.parse_expr()?)) } else { Ok(None) }
+ let parse = if !self.eat(&token::Eq) && !skip_eq {
+ // Error recovery for `let x += 1`
+ if matches!(self.token.kind, TokenKind::BinOpEq(_)) {
+ struct_span_err!(
+ self.sess.span_diagnostic,
+ self.token.span,
+ E0067,
+ "can't reassign to a uninitialized variable"
+ )
+ .span_suggestion_short(
+ self.token.span,
+ "replace with `=` to initialize the variable",
+ "=".to_string(),
+ Applicability::MaybeIncorrect,
+ )
+ .emit();
+ self.bump();
+ true
+ } else {
+ false
+ }
+ } else {
+ true
+ };
+
+ if parse { Ok(Some(self.parse_expr()?)) } else { Ok(None) }
}
/// Parses a block. No inner attributes are allowed.
diff --git a/src/test/ui/parser/let-binop-plus.rs b/src/test/ui/parser/let-binop-plus.rs
new file mode 100644
index 0000000000000..8d883d6e24894
--- /dev/null
+++ b/src/test/ui/parser/let-binop-plus.rs
@@ -0,0 +1,7 @@
+#![allow(bare_trait_objects)]
+
+fn main() {
+ let a: i8 += 1;
+ //~^ ERROR expected trait, found builtin type `i8`
+ let _ = a;
+}
diff --git a/src/test/ui/parser/let-binop-plus.stderr b/src/test/ui/parser/let-binop-plus.stderr
new file mode 100644
index 0000000000000..baa935aff713c
--- /dev/null
+++ b/src/test/ui/parser/let-binop-plus.stderr
@@ -0,0 +1,9 @@
+error[E0404]: expected trait, found builtin type `i8`
+ --> $DIR/let-binop-plus.rs:4:12
+ |
+LL | let a: i8 += 1;
+ | ^^ not a trait
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0404`.
diff --git a/src/test/ui/parser/let-binop.rs b/src/test/ui/parser/let-binop.rs
new file mode 100644
index 0000000000000..d445ab6bb8a1f
--- /dev/null
+++ b/src/test/ui/parser/let-binop.rs
@@ -0,0 +1,8 @@
+fn main() {
+ let a: i8 *= 1; //~ ERROR can't reassign to a uninitialized variable
+ let _ = a;
+ let b += 1; //~ ERROR can't reassign to a uninitialized variable
+ let _ = b;
+ let c *= 1; //~ ERROR can't reassign to a uninitialized variable
+ let _ = c;
+}
diff --git a/src/test/ui/parser/let-binop.stderr b/src/test/ui/parser/let-binop.stderr
new file mode 100644
index 0000000000000..3e9d4a80a70ef
--- /dev/null
+++ b/src/test/ui/parser/let-binop.stderr
@@ -0,0 +1,21 @@
+error[E0067]: can't reassign to a uninitialized variable
+ --> $DIR/let-binop.rs:2:15
+ |
+LL | let a: i8 *= 1;
+ | ^^ help: replace with `=` to initialize the variable
+
+error[E0067]: can't reassign to a uninitialized variable
+ --> $DIR/let-binop.rs:4:11
+ |
+LL | let b += 1;
+ | ^^ help: replace with `=` to initialize the variable
+
+error[E0067]: can't reassign to a uninitialized variable
+ --> $DIR/let-binop.rs:6:11
+ |
+LL | let c *= 1;
+ | ^^ help: replace with `=` to initialize the variable
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0067`.
From 48ff12acb184672393692e087927a66ff7907d71 Mon Sep 17 00:00:00 2001
From: mibac138 <5672750+mibac138@users.noreply.github.com>
Date: Thu, 7 May 2020 04:09:57 +0200
Subject: [PATCH 02/32] Expand partial error recovery for `let` with `BinOpEq`
---
src/librustc_parse/parser/stmt.rs | 40 +++++++++++++++++++++--------
src/test/ui/parser/let-binop.stderr | 22 ++++++++++++++--
2 files changed, 50 insertions(+), 12 deletions(-)
diff --git a/src/librustc_parse/parser/stmt.rs b/src/librustc_parse/parser/stmt.rs
index 049aa7447f4db..aceee81432896 100644
--- a/src/librustc_parse/parser/stmt.rs
+++ b/src/librustc_parse/parser/stmt.rs
@@ -145,12 +145,12 @@ impl<'a> Parser<'a> {
}
fn parse_local_mk(&mut self, lo: Span, attrs: AttrVec) -> PResult<'a, Stmt> {
- let local = self.parse_local(attrs)?;
+ let local = self.parse_local(lo, attrs)?;
Ok(self.mk_stmt(lo.to(self.prev_token.span), StmtKind::Local(local)))
}
/// Parses a local variable declaration.
- fn parse_local(&mut self, attrs: AttrVec) -> PResult<'a, P> {
+ fn parse_local(&mut self, let_span: Span, attrs: AttrVec) -> PResult<'a, P> {
let lo = self.prev_token.span;
let pat = self.parse_top_pat(GateOr::Yes)?;
@@ -174,7 +174,7 @@ impl<'a> Parser<'a> {
} else {
(None, None)
};
- let init = match (self.parse_initializer(err.is_some()), err) {
+ let init = match (self.parse_initializer(let_span, ty.is_some(), err.is_some()), err) {
(Ok(init), None) => {
// init parsed, ty parsed
init
@@ -216,23 +216,43 @@ impl<'a> Parser<'a> {
}
/// Parses the RHS of a local variable declaration (e.g., '= 14;').
- fn parse_initializer(&mut self, skip_eq: bool) -> PResult<'a, Option>> {
+ fn parse_initializer(
+ &mut self,
+ let_span: Span,
+ has_ty: bool,
+ skip_eq: bool,
+ ) -> PResult<'a, Option
>> {
let parse = if !self.eat(&token::Eq) && !skip_eq {
// Error recovery for `let x += 1`
if matches!(self.token.kind, TokenKind::BinOpEq(_)) {
- struct_span_err!(
+ let mut err = struct_span_err!(
self.sess.span_diagnostic,
self.token.span,
E0067,
"can't reassign to a uninitialized variable"
- )
- .span_suggestion_short(
+ );
+ err.span_suggestion_short(
self.token.span,
"replace with `=` to initialize the variable",
"=".to_string(),
- Applicability::MaybeIncorrect,
- )
- .emit();
+ if has_ty {
+ // for `let x: i8 += 1` it's highly likely that the `+` is a typo
+ Applicability::MachineApplicable
+ } else {
+ // for `let x += 1` it's a bit less likely that the `+` is a typo
+ Applicability::MaybeIncorrect
+ },
+ );
+ // In case of code like `let x += 1` it's possible the user may have meant to write `x += 1`
+ if !has_ty {
+ err.span_suggestion_short(
+ let_span,
+ "remove to reassign to a previously initialized variable",
+ "".to_string(),
+ Applicability::MaybeIncorrect,
+ );
+ }
+ err.emit();
self.bump();
true
} else {
diff --git a/src/test/ui/parser/let-binop.stderr b/src/test/ui/parser/let-binop.stderr
index 3e9d4a80a70ef..c37612430cef1 100644
--- a/src/test/ui/parser/let-binop.stderr
+++ b/src/test/ui/parser/let-binop.stderr
@@ -8,13 +8,31 @@ error[E0067]: can't reassign to a uninitialized variable
--> $DIR/let-binop.rs:4:11
|
LL | let b += 1;
- | ^^ help: replace with `=` to initialize the variable
+ | ^^
+ |
+help: replace with `=` to initialize the variable
+ |
+LL | let b = 1;
+ | ^
+help: remove to reassign to a previously initialized variable
+ |
+LL | b += 1;
+ | --
error[E0067]: can't reassign to a uninitialized variable
--> $DIR/let-binop.rs:6:11
|
LL | let c *= 1;
- | ^^ help: replace with `=` to initialize the variable
+ | ^^
+ |
+help: replace with `=` to initialize the variable
+ |
+LL | let c = 1;
+ | ^
+help: remove to reassign to a previously initialized variable
+ |
+LL | c *= 1;
+ | --
error: aborting due to 3 previous errors
From 05d653199871955eba90abdd3b176603f030ab60 Mon Sep 17 00:00:00 2001
From: mibac138 <5672750+mibac138@users.noreply.github.com>
Date: Thu, 7 May 2020 05:00:59 +0200
Subject: [PATCH 03/32] Error recovery for `let` with `+=`
---
src/librustc_parse/parser/stmt.rs | 65 ++++++++++++------------
src/test/ui/parser/let-binop-plus.rs | 1 +
src/test/ui/parser/let-binop-plus.stderr | 11 +++-
3 files changed, 42 insertions(+), 35 deletions(-)
diff --git a/src/librustc_parse/parser/stmt.rs b/src/librustc_parse/parser/stmt.rs
index aceee81432896..224f4ebf53828 100644
--- a/src/librustc_parse/parser/stmt.rs
+++ b/src/librustc_parse/parser/stmt.rs
@@ -222,44 +222,43 @@ impl<'a> Parser<'a> {
has_ty: bool,
skip_eq: bool,
) -> PResult<'a, Option
>> {
- let parse = if !self.eat(&token::Eq) && !skip_eq {
+ // In case of code like `let x: i8 += 1`, `i8` is interpreted as a trait consuming the `+`
+ // from `+=`.
+ let ate_plus = self.prev_token.is_like_plus() && has_ty;
+ let parse = if !skip_eq && (ate_plus || matches!(self.token.kind, TokenKind::BinOpEq(_))) {
// Error recovery for `let x += 1`
- if matches!(self.token.kind, TokenKind::BinOpEq(_)) {
- let mut err = struct_span_err!(
- self.sess.span_diagnostic,
- self.token.span,
- E0067,
- "can't reassign to a uninitialized variable"
- );
+ let mut err = struct_span_err!(
+ self.sess.span_diagnostic,
+ self.token.span,
+ E0067,
+ "can't reassign to a uninitialized variable"
+ );
+ err.span_suggestion_short(
+ self.token.span,
+ "replace with `=` to initialize the variable",
+ "=".to_string(),
+ if has_ty {
+ // for `let x: i8 += 1` it's highly likely that the `+` is a typo
+ Applicability::MachineApplicable
+ } else {
+ // for `let x += 1` it's a bit less likely that the `+` is a typo
+ Applicability::MaybeIncorrect
+ },
+ );
+ // In case of code like `let x += 1` it's possible the user may have meant to write `x += 1`
+ if !has_ty {
err.span_suggestion_short(
- self.token.span,
- "replace with `=` to initialize the variable",
- "=".to_string(),
- if has_ty {
- // for `let x: i8 += 1` it's highly likely that the `+` is a typo
- Applicability::MachineApplicable
- } else {
- // for `let x += 1` it's a bit less likely that the `+` is a typo
- Applicability::MaybeIncorrect
- },
+ let_span,
+ "remove to reassign to a previously initialized variable",
+ "".to_string(),
+ Applicability::MaybeIncorrect,
);
- // In case of code like `let x += 1` it's possible the user may have meant to write `x += 1`
- if !has_ty {
- err.span_suggestion_short(
- let_span,
- "remove to reassign to a previously initialized variable",
- "".to_string(),
- Applicability::MaybeIncorrect,
- );
- }
- err.emit();
- self.bump();
- true
- } else {
- false
}
- } else {
+ err.emit();
+ self.bump();
true
+ } else {
+ self.eat(&token::Eq) || skip_eq
};
if parse { Ok(Some(self.parse_expr()?)) } else { Ok(None) }
diff --git a/src/test/ui/parser/let-binop-plus.rs b/src/test/ui/parser/let-binop-plus.rs
index 8d883d6e24894..98473e9f096d8 100644
--- a/src/test/ui/parser/let-binop-plus.rs
+++ b/src/test/ui/parser/let-binop-plus.rs
@@ -3,5 +3,6 @@
fn main() {
let a: i8 += 1;
//~^ ERROR expected trait, found builtin type `i8`
+ //~| ERROR can't reassign to a uninitialized variable
let _ = a;
}
diff --git a/src/test/ui/parser/let-binop-plus.stderr b/src/test/ui/parser/let-binop-plus.stderr
index baa935aff713c..d7d84ff16a0a1 100644
--- a/src/test/ui/parser/let-binop-plus.stderr
+++ b/src/test/ui/parser/let-binop-plus.stderr
@@ -1,9 +1,16 @@
+error[E0067]: can't reassign to a uninitialized variable
+ --> $DIR/let-binop-plus.rs:4:16
+ |
+LL | let a: i8 += 1;
+ | ^ help: replace with `=` to initialize the variable
+
error[E0404]: expected trait, found builtin type `i8`
--> $DIR/let-binop-plus.rs:4:12
|
LL | let a: i8 += 1;
| ^^ not a trait
-error: aborting due to previous error
+error: aborting due to 2 previous errors
-For more information about this error, try `rustc --explain E0404`.
+Some errors have detailed explanations: E0067, E0404.
+For more information about an error, try `rustc --explain E0067`.
From 6ad24baf06c687517f188e8c6e6ce848924d001c Mon Sep 17 00:00:00 2001
From: mibac138 <5672750+mibac138@users.noreply.github.com>
Date: Thu, 7 May 2020 23:45:51 +0200
Subject: [PATCH 04/32] Adjust according to estebank's review comments
---
src/librustc_parse/parser/stmt.rs | 19 ++++++++-----------
src/test/ui/parser/let-binop-plus.rs | 2 +-
src/test/ui/parser/let-binop-plus.stderr | 4 ++--
src/test/ui/parser/let-binop.rs | 6 +++---
src/test/ui/parser/let-binop.stderr | 20 ++++++++++----------
5 files changed, 24 insertions(+), 27 deletions(-)
diff --git a/src/librustc_parse/parser/stmt.rs b/src/librustc_parse/parser/stmt.rs
index 224f4ebf53828..bec810fde081d 100644
--- a/src/librustc_parse/parser/stmt.rs
+++ b/src/librustc_parse/parser/stmt.rs
@@ -174,7 +174,10 @@ impl<'a> Parser<'a> {
} else {
(None, None)
};
- let init = match (self.parse_initializer(let_span, ty.is_some(), err.is_some()), err) {
+ let init = match (
+ self.parse_initializer(let_span.until(pat.span), ty.is_some(), err.is_some()),
+ err,
+ ) {
(Ok(init), None) => {
// init parsed, ty parsed
init
@@ -231,25 +234,19 @@ impl<'a> Parser<'a> {
self.sess.span_diagnostic,
self.token.span,
E0067,
- "can't reassign to a uninitialized variable"
+ "can't reassign to an uninitialized variable"
);
err.span_suggestion_short(
self.token.span,
- "replace with `=` to initialize the variable",
+ "initialize the variable",
"=".to_string(),
- if has_ty {
- // for `let x: i8 += 1` it's highly likely that the `+` is a typo
- Applicability::MachineApplicable
- } else {
- // for `let x += 1` it's a bit less likely that the `+` is a typo
- Applicability::MaybeIncorrect
- },
+ Applicability::MaybeIncorrect,
);
// In case of code like `let x += 1` it's possible the user may have meant to write `x += 1`
if !has_ty {
err.span_suggestion_short(
let_span,
- "remove to reassign to a previously initialized variable",
+ "otherwise, reassign to a previously initialized variable",
"".to_string(),
Applicability::MaybeIncorrect,
);
diff --git a/src/test/ui/parser/let-binop-plus.rs b/src/test/ui/parser/let-binop-plus.rs
index 98473e9f096d8..4d6d9b5c8d37f 100644
--- a/src/test/ui/parser/let-binop-plus.rs
+++ b/src/test/ui/parser/let-binop-plus.rs
@@ -3,6 +3,6 @@
fn main() {
let a: i8 += 1;
//~^ ERROR expected trait, found builtin type `i8`
- //~| ERROR can't reassign to a uninitialized variable
+ //~| ERROR can't reassign to an uninitialized variable
let _ = a;
}
diff --git a/src/test/ui/parser/let-binop-plus.stderr b/src/test/ui/parser/let-binop-plus.stderr
index d7d84ff16a0a1..91a59fe24fedc 100644
--- a/src/test/ui/parser/let-binop-plus.stderr
+++ b/src/test/ui/parser/let-binop-plus.stderr
@@ -1,8 +1,8 @@
-error[E0067]: can't reassign to a uninitialized variable
+error[E0067]: can't reassign to an uninitialized variable
--> $DIR/let-binop-plus.rs:4:16
|
LL | let a: i8 += 1;
- | ^ help: replace with `=` to initialize the variable
+ | ^ help: initialize the variable
error[E0404]: expected trait, found builtin type `i8`
--> $DIR/let-binop-plus.rs:4:12
diff --git a/src/test/ui/parser/let-binop.rs b/src/test/ui/parser/let-binop.rs
index d445ab6bb8a1f..7f58f5df2d412 100644
--- a/src/test/ui/parser/let-binop.rs
+++ b/src/test/ui/parser/let-binop.rs
@@ -1,8 +1,8 @@
fn main() {
- let a: i8 *= 1; //~ ERROR can't reassign to a uninitialized variable
+ let a: i8 *= 1; //~ ERROR can't reassign to an uninitialized variable
let _ = a;
- let b += 1; //~ ERROR can't reassign to a uninitialized variable
+ let b += 1; //~ ERROR can't reassign to an uninitialized variable
let _ = b;
- let c *= 1; //~ ERROR can't reassign to a uninitialized variable
+ let c *= 1; //~ ERROR can't reassign to an uninitialized variable
let _ = c;
}
diff --git a/src/test/ui/parser/let-binop.stderr b/src/test/ui/parser/let-binop.stderr
index c37612430cef1..8a90b7cf74a4a 100644
--- a/src/test/ui/parser/let-binop.stderr
+++ b/src/test/ui/parser/let-binop.stderr
@@ -1,37 +1,37 @@
-error[E0067]: can't reassign to a uninitialized variable
+error[E0067]: can't reassign to an uninitialized variable
--> $DIR/let-binop.rs:2:15
|
LL | let a: i8 *= 1;
- | ^^ help: replace with `=` to initialize the variable
+ | ^^ help: initialize the variable
-error[E0067]: can't reassign to a uninitialized variable
+error[E0067]: can't reassign to an uninitialized variable
--> $DIR/let-binop.rs:4:11
|
LL | let b += 1;
| ^^
|
-help: replace with `=` to initialize the variable
+help: initialize the variable
|
LL | let b = 1;
| ^
-help: remove to reassign to a previously initialized variable
+help: otherwise, reassign to a previously initialized variable
|
-LL | b += 1;
+LL | b += 1;
| --
-error[E0067]: can't reassign to a uninitialized variable
+error[E0067]: can't reassign to an uninitialized variable
--> $DIR/let-binop.rs:6:11
|
LL | let c *= 1;
| ^^
|
-help: replace with `=` to initialize the variable
+help: initialize the variable
|
LL | let c = 1;
| ^
-help: remove to reassign to a previously initialized variable
+help: otherwise, reassign to a previously initialized variable
|
-LL | c *= 1;
+LL | c *= 1;
| --
error: aborting due to 3 previous errors
From 98532a30901d7544c49fe82f499db53699645de0 Mon Sep 17 00:00:00 2001
From: mibac138 <5672750+mibac138@users.noreply.github.com>
Date: Wed, 20 May 2020 22:09:03 +0200
Subject: [PATCH 05/32] Adjust according to petrochenkov's review comments
---
src/librustc_parse/parser/stmt.rs | 65 ++++++++----------------
src/test/ui/parser/let-binop-plus.rs | 8 ---
src/test/ui/parser/let-binop-plus.stderr | 16 ------
src/test/ui/parser/let-binop.stderr | 29 ++---------
4 files changed, 27 insertions(+), 91 deletions(-)
delete mode 100644 src/test/ui/parser/let-binop-plus.rs
delete mode 100644 src/test/ui/parser/let-binop-plus.stderr
diff --git a/src/librustc_parse/parser/stmt.rs b/src/librustc_parse/parser/stmt.rs
index bec810fde081d..53f32b7c800bd 100644
--- a/src/librustc_parse/parser/stmt.rs
+++ b/src/librustc_parse/parser/stmt.rs
@@ -12,7 +12,7 @@ use rustc_ast::ast::{Block, BlockCheckMode, Expr, ExprKind, Local, Stmt, StmtKin
use rustc_ast::ptr::P;
use rustc_ast::token::{self, TokenKind};
use rustc_ast::util::classify;
-use rustc_errors::{struct_span_err, Applicability, PResult};
+use rustc_errors::{Applicability, PResult};
use rustc_span::source_map::{BytePos, Span};
use rustc_span::symbol::{kw, sym};
@@ -145,12 +145,12 @@ impl<'a> Parser<'a> {
}
fn parse_local_mk(&mut self, lo: Span, attrs: AttrVec) -> PResult<'a, Stmt> {
- let local = self.parse_local(lo, attrs)?;
+ let local = self.parse_local(attrs)?;
Ok(self.mk_stmt(lo.to(self.prev_token.span), StmtKind::Local(local)))
}
/// Parses a local variable declaration.
- fn parse_local(&mut self, let_span: Span, attrs: AttrVec) -> PResult<'a, P> {
+ fn parse_local(&mut self, attrs: AttrVec) -> PResult<'a, P> {
let lo = self.prev_token.span;
let pat = self.parse_top_pat(GateOr::Yes)?;
@@ -174,10 +174,7 @@ impl<'a> Parser<'a> {
} else {
(None, None)
};
- let init = match (
- self.parse_initializer(let_span.until(pat.span), ty.is_some(), err.is_some()),
- err,
- ) {
+ let init = match (self.parse_initializer(err.is_some()), err) {
(Ok(init), None) => {
// init parsed, ty parsed
init
@@ -219,46 +216,28 @@ impl<'a> Parser<'a> {
}
/// Parses the RHS of a local variable declaration (e.g., '= 14;').
- fn parse_initializer(
- &mut self,
- let_span: Span,
- has_ty: bool,
- skip_eq: bool,
- ) -> PResult<'a, Option>> {
- // In case of code like `let x: i8 += 1`, `i8` is interpreted as a trait consuming the `+`
- // from `+=`.
- let ate_plus = self.prev_token.is_like_plus() && has_ty;
- let parse = if !skip_eq && (ate_plus || matches!(self.token.kind, TokenKind::BinOpEq(_))) {
- // Error recovery for `let x += 1`
- let mut err = struct_span_err!(
- self.sess.span_diagnostic,
- self.token.span,
- E0067,
- "can't reassign to an uninitialized variable"
- );
- err.span_suggestion_short(
- self.token.span,
- "initialize the variable",
- "=".to_string(),
- Applicability::MaybeIncorrect,
- );
- // In case of code like `let x += 1` it's possible the user may have meant to write `x += 1`
- if !has_ty {
- err.span_suggestion_short(
- let_span,
- "otherwise, reassign to a previously initialized variable",
- "".to_string(),
+ fn parse_initializer(&mut self, eq_optional: bool) -> PResult<'a, Option
>> {
+ let eq_consumed = match self.token.kind {
+ token::BinOpEq(..) => {
+ // Recover `let x = 1` as `let x = 1`
+ self.struct_span_err(
+ self.token.span,
+ "can't reassign to an uninitialized variable",
+ )
+ .span_suggestion_short(
+ self.token.span,
+ "initialize the variable",
+ "=".to_string(),
Applicability::MaybeIncorrect,
- );
+ )
+ .emit();
+ self.bump();
+ true
}
- err.emit();
- self.bump();
- true
- } else {
- self.eat(&token::Eq) || skip_eq
+ _ => self.eat(&token::Eq),
};
- if parse { Ok(Some(self.parse_expr()?)) } else { Ok(None) }
+ Ok(if eq_consumed || eq_optional { Some(self.parse_expr()?) } else { None })
}
/// Parses a block. No inner attributes are allowed.
diff --git a/src/test/ui/parser/let-binop-plus.rs b/src/test/ui/parser/let-binop-plus.rs
deleted file mode 100644
index 4d6d9b5c8d37f..0000000000000
--- a/src/test/ui/parser/let-binop-plus.rs
+++ /dev/null
@@ -1,8 +0,0 @@
-#![allow(bare_trait_objects)]
-
-fn main() {
- let a: i8 += 1;
- //~^ ERROR expected trait, found builtin type `i8`
- //~| ERROR can't reassign to an uninitialized variable
- let _ = a;
-}
diff --git a/src/test/ui/parser/let-binop-plus.stderr b/src/test/ui/parser/let-binop-plus.stderr
deleted file mode 100644
index 91a59fe24fedc..0000000000000
--- a/src/test/ui/parser/let-binop-plus.stderr
+++ /dev/null
@@ -1,16 +0,0 @@
-error[E0067]: can't reassign to an uninitialized variable
- --> $DIR/let-binop-plus.rs:4:16
- |
-LL | let a: i8 += 1;
- | ^ help: initialize the variable
-
-error[E0404]: expected trait, found builtin type `i8`
- --> $DIR/let-binop-plus.rs:4:12
- |
-LL | let a: i8 += 1;
- | ^^ not a trait
-
-error: aborting due to 2 previous errors
-
-Some errors have detailed explanations: E0067, E0404.
-For more information about an error, try `rustc --explain E0067`.
diff --git a/src/test/ui/parser/let-binop.stderr b/src/test/ui/parser/let-binop.stderr
index 8a90b7cf74a4a..71431499ac70b 100644
--- a/src/test/ui/parser/let-binop.stderr
+++ b/src/test/ui/parser/let-binop.stderr
@@ -1,39 +1,20 @@
-error[E0067]: can't reassign to an uninitialized variable
+error: can't reassign to an uninitialized variable
--> $DIR/let-binop.rs:2:15
|
LL | let a: i8 *= 1;
| ^^ help: initialize the variable
-error[E0067]: can't reassign to an uninitialized variable
+error: can't reassign to an uninitialized variable
--> $DIR/let-binop.rs:4:11
|
LL | let b += 1;
- | ^^
- |
-help: initialize the variable
- |
-LL | let b = 1;
- | ^
-help: otherwise, reassign to a previously initialized variable
- |
-LL | b += 1;
- | --
+ | ^^ help: initialize the variable
-error[E0067]: can't reassign to an uninitialized variable
+error: can't reassign to an uninitialized variable
--> $DIR/let-binop.rs:6:11
|
LL | let c *= 1;
- | ^^
- |
-help: initialize the variable
- |
-LL | let c = 1;
- | ^
-help: otherwise, reassign to a previously initialized variable
- |
-LL | c *= 1;
- | --
+ | ^^ help: initialize the variable
error: aborting due to 3 previous errors
-For more information about this error, try `rustc --explain E0067`.
From 3da3d15f9f150dafd7d635859795c4c714e7b7ad Mon Sep 17 00:00:00 2001
From: Sam Elliott
Date: Sat, 30 May 2020 18:24:19 +0100
Subject: [PATCH 06/32] [RISC-V] Do not force frame pointers
We have been seeing some very inefficient code that went away when using
`-Cforce-frame-pointers=no`. For instance `core::ptr::drop_in_place` at
`-Oz` was compiled into a function which consisted entirely of saving
registers to the stack, then using the frame pointer to restore the same
registers (without any instructions between the prolog and epilog).
The RISC-V LLVM backend supports frame pointer elimination, so it makes
sense to allow this to happen when using Rust. It's not clear to me that
frame pointers have ever been required in the general case.
In rust-lang/rust#61675 it was pointed out that this made reassembling
stack traces easier, which is true, but there is a code generation
option for forcing frame pointers, and I feel the default should not be
to require frame pointers, given it demonstrably makes code size worse
(around 10% in some embedded applications).
The kinds of targets mentioned in rust-lang/rust#61675 are popular, but
should not dictate that code generation should be worse for all RISC-V
targets, especially as there is a way to use CFI information to
reconstruct the stack when the frame pointer is eliminated. It is also
a misconception that `fp` is always used for the frame pointer. `fp` is
an ABI name for `x8` (aka `s0`), and if no frame pointer is required,
`x8` may be used for other callee-saved values.
This commit does ensure that the standard library is built with unwind
tables, so that users do not need to rebuild the standard library in
order to get a backtrace that includes standard library calls (which is
the original reason for forcing frame pointers).
---
src/bootstrap/compile.rs | 10 ++++++++++
src/librustc_target/spec/riscv32i_unknown_none_elf.rs | 1 -
.../spec/riscv32imac_unknown_none_elf.rs | 1 -
.../spec/riscv32imc_unknown_none_elf.rs | 1 -
src/librustc_target/spec/riscv64gc_unknown_none_elf.rs | 1 -
.../spec/riscv64imac_unknown_none_elf.rs | 1 -
6 files changed, 10 insertions(+), 5 deletions(-)
diff --git a/src/bootstrap/compile.rs b/src/bootstrap/compile.rs
index b3999118e3de4..46c43be992ded 100644
--- a/src/bootstrap/compile.rs
+++ b/src/bootstrap/compile.rs
@@ -244,6 +244,16 @@ pub fn std_cargo(builder: &Builder<'_>, target: Interned, stage: u32, ca
if stage >= 1 {
cargo.rustflag("-Cembed-bitcode=yes");
}
+
+ // By default, rustc does not include unwind tables unless they are required
+ // for a particular target. They are not required by RISC-V targets, but
+ // compiling the standard library with them means that users can get
+ // backtraces without having to recompile the standard library themselves.
+ //
+ // This choice was discussed in https://github.com/rust-lang/rust/pull/69890
+ if target.contains("riscv") {
+ cargo.rustflag("-Cforce-unwind-tables=yes");
+ }
}
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
diff --git a/src/librustc_target/spec/riscv32i_unknown_none_elf.rs b/src/librustc_target/spec/riscv32i_unknown_none_elf.rs
index aade1e708232e..d7b3e7e15307a 100644
--- a/src/librustc_target/spec/riscv32i_unknown_none_elf.rs
+++ b/src/librustc_target/spec/riscv32i_unknown_none_elf.rs
@@ -25,7 +25,6 @@ pub fn target() -> TargetResult {
relocation_model: RelocModel::Static,
emit_debug_gdb_scripts: false,
abi_blacklist: super::riscv_base::abi_blacklist(),
- eliminate_frame_pointer: false,
..Default::default()
},
})
diff --git a/src/librustc_target/spec/riscv32imac_unknown_none_elf.rs b/src/librustc_target/spec/riscv32imac_unknown_none_elf.rs
index e2990eeb826f7..b93b6fcf8002a 100644
--- a/src/librustc_target/spec/riscv32imac_unknown_none_elf.rs
+++ b/src/librustc_target/spec/riscv32imac_unknown_none_elf.rs
@@ -25,7 +25,6 @@ pub fn target() -> TargetResult {
relocation_model: RelocModel::Static,
emit_debug_gdb_scripts: false,
abi_blacklist: super::riscv_base::abi_blacklist(),
- eliminate_frame_pointer: false,
..Default::default()
},
})
diff --git a/src/librustc_target/spec/riscv32imc_unknown_none_elf.rs b/src/librustc_target/spec/riscv32imc_unknown_none_elf.rs
index 55a4d58dfccca..a16e7e31c6619 100644
--- a/src/librustc_target/spec/riscv32imc_unknown_none_elf.rs
+++ b/src/librustc_target/spec/riscv32imc_unknown_none_elf.rs
@@ -25,7 +25,6 @@ pub fn target() -> TargetResult {
relocation_model: RelocModel::Static,
emit_debug_gdb_scripts: false,
abi_blacklist: super::riscv_base::abi_blacklist(),
- eliminate_frame_pointer: false,
..Default::default()
},
})
diff --git a/src/librustc_target/spec/riscv64gc_unknown_none_elf.rs b/src/librustc_target/spec/riscv64gc_unknown_none_elf.rs
index 7376a14e951f5..e5147a12ed320 100644
--- a/src/librustc_target/spec/riscv64gc_unknown_none_elf.rs
+++ b/src/librustc_target/spec/riscv64gc_unknown_none_elf.rs
@@ -26,7 +26,6 @@ pub fn target() -> TargetResult {
code_model: Some(CodeModel::Medium),
emit_debug_gdb_scripts: false,
abi_blacklist: super::riscv_base::abi_blacklist(),
- eliminate_frame_pointer: false,
..Default::default()
},
})
diff --git a/src/librustc_target/spec/riscv64imac_unknown_none_elf.rs b/src/librustc_target/spec/riscv64imac_unknown_none_elf.rs
index a3b0eb5334f40..dc056b55b3868 100644
--- a/src/librustc_target/spec/riscv64imac_unknown_none_elf.rs
+++ b/src/librustc_target/spec/riscv64imac_unknown_none_elf.rs
@@ -26,7 +26,6 @@ pub fn target() -> TargetResult {
code_model: Some(CodeModel::Medium),
emit_debug_gdb_scripts: false,
abi_blacklist: super::riscv_base::abi_blacklist(),
- eliminate_frame_pointer: false,
..Default::default()
},
})
From f0d2e78d39d0efdb431af0b59c498d532d8146e2 Mon Sep 17 00:00:00 2001
From: Ralf Jung
Date: Fri, 12 Jun 2020 18:17:30 +0200
Subject: [PATCH 07/32] add raw_ref macros
---
src/libcore/ptr/mod.rs | 67 ++++++++++++++++++++++++++++++++++++++++++
src/libstd/lib.rs | 1 +
2 files changed, 68 insertions(+)
diff --git a/src/libcore/ptr/mod.rs b/src/libcore/ptr/mod.rs
index 777284ca5c096..199f08c3d5058 100644
--- a/src/libcore/ptr/mod.rs
+++ b/src/libcore/ptr/mod.rs
@@ -1399,3 +1399,70 @@ fnptr_impls_args! { A, B, C, D, E, F, G, H, I }
fnptr_impls_args! { A, B, C, D, E, F, G, H, I, J }
fnptr_impls_args! { A, B, C, D, E, F, G, H, I, J, K }
fnptr_impls_args! { A, B, C, D, E, F, G, H, I, J, K, L }
+
+/// Create a `const` raw pointer to a place, without creating an intermediate reference.
+///
+/// Creating a reference with `&`/`&mut` is only allowed if the pointer is properly aligned
+/// and points to initialized data. For cases where those requirements do not hold,
+/// raw pointers should be used instead. However, `&expr as *const _` creates a reference
+/// before casting it to a raw pointer, and that reference is subject to the same rules
+/// as all other references. This macro can create a raw pointer *without* creating
+/// a reference first.
+///
+/// # Example
+///
+/// ```
+/// #![feature(raw_ref_macros)]
+/// use std::ptr;
+///
+/// #[repr(packed)]
+/// struct Packed {
+/// f1: u8,
+/// f2: u16,
+/// }
+///
+/// let packed = Packed { f1: 1, f2: 2 };
+/// // `&packed.f2` would create an unaligned reference, and thus be Undefined Behavior!
+/// let raw_f2 = ptr::raw_const!(packed.f2);
+/// assert_eq!(unsafe { raw_f2.read_unaligned() }, 2);
+/// ```
+#[unstable(feature = "raw_ref_macros", issue = "none")]
+#[rustc_macro_transparency = "semitransparent"]
+#[allow_internal_unstable(raw_ref_op)]
+pub macro raw_const($e:expr) {
+ &raw const $e
+}
+
+/// Create a `mut` raw pointer to a place, without creating an intermediate reference.
+///
+/// Creating a reference with `&`/`&mut` is only allowed if the pointer is properly aligned
+/// and points to initialized data. For cases where those requirements do not hold,
+/// raw pointers should be used instead. However, `&mut expr as *mut _` creates a reference
+/// before casting it to a raw pointer, and that reference is subject to the same rules
+/// as all other references. This macro can create a raw pointer *without* creating
+/// a reference first.
+///
+/// # Example
+///
+/// ```
+/// #![feature(raw_ref_macros)]
+/// use std::ptr;
+///
+/// #[repr(packed)]
+/// struct Packed {
+/// f1: u8,
+/// f2: u16,
+/// }
+///
+/// let mut packed = Packed { f1: 1, f2: 2 };
+/// // `&mut packed.f2` would create an unaligned reference, and thus be Undefined Behavior!
+/// let raw_f2 = ptr::raw_mut!(packed.f2);
+/// unsafe { raw_f2.write_unaligned(42); }
+/// assert_eq!({packed.f2}, 42); // `{...}` forces copying the field instead of creating a reference.
+/// ```
+#[unstable(feature = "raw_ref_macros", issue = "none")]
+#[rustc_macro_transparency = "semitransparent"]
+#[allow_internal_unstable(raw_ref_op)]
+pub macro raw_mut($e:expr) {
+ &raw mut $e
+}
diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs
index d6493454db591..ef699ede2a140 100644
--- a/src/libstd/lib.rs
+++ b/src/libstd/lib.rs
@@ -298,6 +298,7 @@
#![feature(prelude_import)]
#![feature(ptr_internals)]
#![feature(raw)]
+#![feature(raw_ref_macros)]
#![feature(renamed_spin_loop)]
#![feature(rustc_attrs)]
#![feature(rustc_private)]
From 724dfba460e2c98311cacb5d4f6bb6da36ceec67 Mon Sep 17 00:00:00 2001
From: Guillaume Gomez
Date: Sat, 13 Jun 2020 15:05:37 +0200
Subject: [PATCH 08/32] Clean up some weird command strings
---
src/librustdoc/lib.rs | 16 +++++++---------
1 file changed, 7 insertions(+), 9 deletions(-)
diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs
index 82d6cda986a9a..95d113166e001 100644
--- a/src/librustdoc/lib.rs
+++ b/src/librustdoc/lib.rs
@@ -165,9 +165,8 @@ fn opts() -> Vec {
o.optmulti(
"",
"passes",
- "list of passes to also run, you might want \
- to pass it multiple times; a value of `list` \
- will print available passes",
+ "list of passes to also run, you might want to pass it multiple times; a value of \
+ `list` will print available passes",
"PASSES",
)
}),
@@ -248,8 +247,8 @@ fn opts() -> Vec {
"e",
"extend-css",
"To add some CSS rules with a given file to generate doc with your \
- own theme. However, your theme might break if the rustdoc's generated HTML \
- changes, so be careful!",
+ own theme. However, your theme might break if the rustdoc's generated HTML \
+ changes, so be careful!",
"PATH",
)
}),
@@ -262,7 +261,7 @@ fn opts() -> Vec {
"",
"playground-url",
"URL to send code snippets to, may be reset by --markdown-playground-url \
- or `#![doc(html_playground_url=...)]`",
+ or `#![doc(html_playground_url=...)]`",
"URL",
)
}),
@@ -276,8 +275,7 @@ fn opts() -> Vec {
o.optflag(
"",
"sort-modules-by-appearance",
- "sort modules by where they appear in the \
- program, rather than alphabetically",
+ "sort modules by where they appear in the program, rather than alphabetically",
)
}),
stable("theme", |o| {
@@ -358,7 +356,7 @@ fn opts() -> Vec {
"",
"static-root-path",
"Path string to force loading static files from in output pages. \
- If not set, uses combinations of '../' to reach the documentation root.",
+ If not set, uses combinations of '../' to reach the documentation root.",
"PATH",
)
}),
From d5ea0e9f8def9a3ec0eb2dd88f0465d4d1a81c21 Mon Sep 17 00:00:00 2001
From: oddg
Date: Thu, 14 May 2020 19:58:43 -0700
Subject: [PATCH 09/32] Report error when casting an C-like enum implementing
Drop
---
src/librustc_session/lint/builtin.rs | 11 ++++++++++
src/librustc_typeck/check/cast.rs | 30 +++++++++++++++++++++++++---
2 files changed, 38 insertions(+), 3 deletions(-)
diff --git a/src/librustc_session/lint/builtin.rs b/src/librustc_session/lint/builtin.rs
index 58388bafbeddf..5a8f5c1b9fbca 100644
--- a/src/librustc_session/lint/builtin.rs
+++ b/src/librustc_session/lint/builtin.rs
@@ -534,6 +534,16 @@ declare_lint! {
@feature_gate = sym::unsafe_block_in_unsafe_fn;
}
+declare_lint! {
+ pub CENUM_IMPL_DROP_CAST,
+ Warn,
+ "a C-like enum implementing Drop is cast",
+ @future_incompatible = FutureIncompatibleInfo {
+ reference: "issue #73333 ",
+ edition: None,
+ };
+}
+
declare_lint_pass! {
/// Does nothing as a lint pass, but registers some `Lint`s
/// that are used by other parts of the compiler.
@@ -607,6 +617,7 @@ declare_lint_pass! {
ASM_SUB_REGISTER,
UNSAFE_OP_IN_UNSAFE_FN,
INCOMPLETE_INCLUDE,
+ CENUM_IMPL_DROP_CAST,
]
}
diff --git a/src/librustc_typeck/check/cast.rs b/src/librustc_typeck/check/cast.rs
index 46d6706cbf429..bea5e0e996658 100644
--- a/src/librustc_typeck/check/cast.rs
+++ b/src/librustc_typeck/check/cast.rs
@@ -609,7 +609,10 @@ impl<'a, 'tcx> CastCheck<'tcx> {
(FnPtr, Ptr(mt)) => self.check_fptr_ptr_cast(fcx, mt),
// prim -> prim
- (Int(CEnum), Int(_)) => Ok(CastKind::EnumCast),
+ (Int(CEnum), Int(_)) => {
+ self.cenum_impl_drop_lint(fcx);
+ Ok(CastKind::EnumCast)
+ }
(Int(Char) | Int(Bool), Int(_)) => Ok(CastKind::PrimIntCast),
(Int(_) | Float, Int(_) | Float) => Ok(CastKind::NumericCast),
@@ -706,11 +709,13 @@ impl<'a, 'tcx> CastCheck<'tcx> {
// Coerce to a raw pointer so that we generate AddressOf in MIR.
let array_ptr_type = fcx.tcx.mk_ptr(m_expr);
fcx.try_coerce(self.expr, self.expr_ty, array_ptr_type, AllowTwoPhase::No)
- .unwrap_or_else(|_| bug!(
+ .unwrap_or_else(|_| {
+ bug!(
"could not cast from reference to array to pointer to array ({:?} to {:?})",
self.expr_ty,
array_ptr_type,
- ));
+ )
+ });
// this will report a type mismatch if needed
fcx.demand_eqtype(self.span, ety, m_cast.ty);
@@ -740,6 +745,25 @@ impl<'a, 'tcx> CastCheck<'tcx> {
Err(err) => Err(err),
}
}
+
+ fn cenum_impl_drop_lint(&self, fcx: &FnCtxt<'a, 'tcx>) {
+ if let ty::Adt(d, _) = self.expr_ty.kind {
+ if d.has_dtor(fcx.tcx) {
+ fcx.tcx.struct_span_lint_hir(
+ lint::builtin::CENUM_IMPL_DROP_CAST,
+ self.expr.hir_id,
+ self.span,
+ |err| {
+ err.build(&format!(
+ "Cast `enum` implementing `Drop` `{}` to integer `{}`",
+ self.expr_ty, self.cast_ty
+ ))
+ .emit();
+ },
+ );
+ }
+ }
+ }
}
impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
From a40156e5b7053dcc36ba1ad65fb567b183c4e1fb Mon Sep 17 00:00:00 2001
From: oddg
Date: Sun, 14 Jun 2020 15:49:20 -0700
Subject: [PATCH 10/32] UI test for deprecation warning of casting enum
implementing Drop
---
src/test/ui/cenum_impl_drop_cast.rs | 18 ++++++++++++++++++
src/test/ui/cenum_impl_drop_cast.stderr | 16 ++++++++++++++++
2 files changed, 34 insertions(+)
create mode 100644 src/test/ui/cenum_impl_drop_cast.rs
create mode 100644 src/test/ui/cenum_impl_drop_cast.stderr
diff --git a/src/test/ui/cenum_impl_drop_cast.rs b/src/test/ui/cenum_impl_drop_cast.rs
new file mode 100644
index 0000000000000..623460673bfa2
--- /dev/null
+++ b/src/test/ui/cenum_impl_drop_cast.rs
@@ -0,0 +1,18 @@
+#![deny(cenum_impl_drop_cast)]
+
+enum E {
+ A = 0,
+}
+
+impl Drop for E {
+ fn drop(&mut self) {
+ println!("Drop");
+ }
+}
+
+fn main() {
+ let e = E::A;
+ let i = e as u32;
+ //~^ ERROR Cast `enum` implementing `Drop` `E` to integer `u32`
+ //~| WARN this was previously accepted
+}
diff --git a/src/test/ui/cenum_impl_drop_cast.stderr b/src/test/ui/cenum_impl_drop_cast.stderr
new file mode 100644
index 0000000000000..5c8f86ffd72ad
--- /dev/null
+++ b/src/test/ui/cenum_impl_drop_cast.stderr
@@ -0,0 +1,16 @@
+error: Cast `enum` implementing `Drop` `E` to integer `u32`
+ --> $DIR/cenum_impl_drop_cast.rs:15:13
+ |
+LL | let i = e as u32;
+ | ^^^^^^^^
+ |
+note: the lint level is defined here
+ --> $DIR/cenum_impl_drop_cast.rs:1:9
+ |
+LL | #![deny(cenum_impl_drop_cast)]
+ | ^^^^^^^^^^^^^^^^^^^^
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = note: for more information, see issue #73333
+
+error: aborting due to previous error
+
From 0906066ae7d8a5e217e8cbf7f17de78a00d4ed83 Mon Sep 17 00:00:00 2001
From: Erik Desjardins
Date: Mon, 15 Jun 2020 00:50:56 -0400
Subject: [PATCH 11/32] Test that bounds checks are elided when slice len is
checked up-front
---
src/test/codegen/issue-69101-bounds-check.rs | 26 ++++++++++++++++++++
1 file changed, 26 insertions(+)
create mode 100644 src/test/codegen/issue-69101-bounds-check.rs
diff --git a/src/test/codegen/issue-69101-bounds-check.rs b/src/test/codegen/issue-69101-bounds-check.rs
new file mode 100644
index 0000000000000..cdbe51da03cc2
--- /dev/null
+++ b/src/test/codegen/issue-69101-bounds-check.rs
@@ -0,0 +1,26 @@
+// no-system-llvm
+// compile-flags: -O
+#![crate_type = "lib"]
+
+// CHECK-LABEL: @already_sliced_no_bounds_check
+#[no_mangle]
+pub fn already_sliced_no_bounds_check(a: &[u8], b: &[u8], c: &mut [u8]) {
+ // CHECK: slice_index_len_fail
+ // CHECK-NOT: panic_bounds_check
+ let _ = (&a[..2048], &b[..2048], &mut c[..2048]);
+ for i in 0..1024 {
+ c[i] = a[i] ^ b[i];
+ }
+}
+
+// make sure we're checking for the right thing: there can be a panic if the slice is too small
+// CHECK-LABEL: @already_sliced_bounds_check
+#[no_mangle]
+pub fn already_sliced_bounds_check(a: &[u8], b: &[u8], c: &mut [u8]) {
+ // CHECK: slice_index_len_fail
+ // CHECK: panic_bounds_check
+ let _ = (&a[..1023], &b[..2048], &mut c[..2048]);
+ for i in 0..1024 {
+ c[i] = a[i] ^ b[i];
+ }
+}
From 81c909488eebcba16610402349563380772e0d1d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Esteban=20K=C3=BCber?=
Date: Fri, 29 May 2020 15:09:43 -0700
Subject: [PATCH 12/32] Suggest substituting `'static` lifetime in impl/dyn
`Trait + 'static` return types
---
.../nice_region_error/static_impl_trait.rs | 64 ++++++++--
src/librustc_middle/ty/context.rs | 13 +-
src/librustc_middle/ty/diagnostics.rs | 8 +-
...t_outlive_least_region_or_bound.nll.stderr | 38 +++++-
.../must_outlive_least_region_or_bound.rs | 21 ++++
.../must_outlive_least_region_or_bound.stderr | 117 ++++++++++++++++--
6 files changed, 232 insertions(+), 29 deletions(-)
diff --git a/src/librustc_infer/infer/error_reporting/nice_region_error/static_impl_trait.rs b/src/librustc_infer/infer/error_reporting/nice_region_error/static_impl_trait.rs
index f4c86ddae604e..88d6c23d51441 100644
--- a/src/librustc_infer/infer/error_reporting/nice_region_error/static_impl_trait.rs
+++ b/src/librustc_infer/infer/error_reporting/nice_region_error/static_impl_trait.rs
@@ -4,6 +4,7 @@ use crate::infer::error_reporting::msg_span_from_free_region;
use crate::infer::error_reporting::nice_region_error::NiceRegionError;
use crate::infer::lexical_region_resolve::RegionResolutionError;
use rustc_errors::{Applicability, ErrorReported};
+use rustc_hir::{GenericBound, ItemKind, Lifetime, LifetimeName, TyKind};
use rustc_middle::ty::RegionKind;
impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
@@ -20,8 +21,9 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
) = error.clone()
{
let anon_reg_sup = self.tcx().is_suitable_region(sup_r)?;
- let (fn_return_span, is_dyn) =
- self.tcx().return_type_impl_or_dyn_trait(anon_reg_sup.def_id)?;
+ let fn_return = self.tcx().return_type_impl_or_dyn_trait(anon_reg_sup.def_id)?;
+ let is_dyn = matches!(fn_return.kind, TyKind::TraitObject(..));
+ let fn_return_span = fn_return.span;
if sub_r == &RegionKind::ReStatic {
let sp = var_origin.span();
let return_sp = sub_origin.span();
@@ -67,12 +69,58 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
lifetime,
);
// FIXME: account for the need of parens in `&(dyn Trait + '_)`
- err.span_suggestion_verbose(
- fn_return_span.shrink_to_hi(),
- &msg,
- format!(" + {}", lifetime_name),
- Applicability::MaybeIncorrect,
- );
+ match fn_return.kind {
+ TyKind::Def(item_id, _) => {
+ let item = self.tcx().hir().item(item_id.id);
+ let opaque = if let ItemKind::OpaqueTy(opaque) = &item.kind {
+ opaque
+ } else {
+ err.emit();
+ return Some(ErrorReported);
+ };
+ let (span, sugg) = opaque
+ .bounds
+ .iter()
+ .filter_map(|arg| match arg {
+ GenericBound::Outlives(Lifetime {
+ name: LifetimeName::Static,
+ span,
+ ..
+ }) => Some((*span, lifetime_name.clone())),
+ _ => None,
+ })
+ .next()
+ .unwrap_or_else(|| {
+ (
+ fn_return_span.shrink_to_hi(),
+ format!(" + {}", lifetime_name),
+ )
+ });
+
+ err.span_suggestion_verbose(
+ span,
+ &msg,
+ sugg,
+ Applicability::MaybeIncorrect,
+ );
+ }
+ TyKind::TraitObject(_, lt) => {
+ let (span, sugg) = match lt.name {
+ LifetimeName::ImplicitObjectLifetimeDefault => (
+ fn_return_span.shrink_to_hi(),
+ format!(" + {}", lifetime_name),
+ ),
+ _ => (lt.span, lifetime_name),
+ };
+ err.span_suggestion_verbose(
+ span,
+ &msg,
+ sugg,
+ Applicability::MaybeIncorrect,
+ );
+ }
+ _ => {}
+ }
}
err.emit();
return Some(ErrorReported);
diff --git a/src/librustc_middle/ty/context.rs b/src/librustc_middle/ty/context.rs
index d5be3508d2d80..4770993d9cb07 100644
--- a/src/librustc_middle/ty/context.rs
+++ b/src/librustc_middle/ty/context.rs
@@ -1383,7 +1383,10 @@ impl<'tcx> TyCtxt<'tcx> {
})
}
- pub fn return_type_impl_or_dyn_trait(&self, scope_def_id: DefId) -> Option<(Span, bool)> {
+ pub fn return_type_impl_or_dyn_trait(
+ &self,
+ scope_def_id: DefId,
+ ) -> Option<&'tcx hir::Ty<'tcx>> {
let hir_id = self.hir().as_local_hir_id(scope_def_id.expect_local());
let hir_output = match self.hir().get(hir_id) {
Node::Item(hir::Item {
@@ -1429,15 +1432,17 @@ impl<'tcx> TyCtxt<'tcx> {
let output = self.erase_late_bound_regions(&sig.output());
if output.is_impl_trait() {
let fn_decl = self.hir().fn_decl_by_hir_id(hir_id).unwrap();
- Some((fn_decl.output.span(), false))
+ if let hir::FnRetTy::Return(ty) = fn_decl.output {
+ return Some(ty);
+ }
} else {
let mut v = TraitObjectVisitor(vec![]);
rustc_hir::intravisit::walk_ty(&mut v, hir_output);
if v.0.len() == 1 {
- return Some((v.0[0], true));
+ return Some(v.0[0]);
}
- None
}
+ None
}
_ => None,
}
diff --git a/src/librustc_middle/ty/diagnostics.rs b/src/librustc_middle/ty/diagnostics.rs
index 2e9aa724ac5af..3ca506fe0d590 100644
--- a/src/librustc_middle/ty/diagnostics.rs
+++ b/src/librustc_middle/ty/diagnostics.rs
@@ -236,21 +236,21 @@ pub fn suggest_constraining_type_param(
}
}
-pub struct TraitObjectVisitor(pub Vec);
-impl<'v> hir::intravisit::Visitor<'v> for TraitObjectVisitor {
+pub struct TraitObjectVisitor<'tcx>(pub Vec<&'tcx hir::Ty<'tcx>>);
+impl<'v> hir::intravisit::Visitor<'v> for TraitObjectVisitor<'v> {
type Map = rustc_hir::intravisit::ErasedMap<'v>;
fn nested_visit_map(&mut self) -> hir::intravisit::NestedVisitorMap {
hir::intravisit::NestedVisitorMap::None
}
- fn visit_ty(&mut self, ty: &hir::Ty<'_>) {
+ fn visit_ty(&mut self, ty: &'v hir::Ty<'v>) {
if let hir::TyKind::TraitObject(
_,
hir::Lifetime { name: hir::LifetimeName::ImplicitObjectLifetimeDefault, .. },
) = ty.kind
{
- self.0.push(ty.span);
+ self.0.push(ty);
}
}
}
diff --git a/src/test/ui/impl-trait/must_outlive_least_region_or_bound.nll.stderr b/src/test/ui/impl-trait/must_outlive_least_region_or_bound.nll.stderr
index 1806d2607a3ac..ca9ca8a9debe2 100644
--- a/src/test/ui/impl-trait/must_outlive_least_region_or_bound.nll.stderr
+++ b/src/test/ui/impl-trait/must_outlive_least_region_or_bound.nll.stderr
@@ -26,7 +26,34 @@ LL | fn explicit<'a>(x: &'a i32) -> impl Copy + 'a { x }
| ^^^^^^^^^^^^^^
error: lifetime may not live long enough
- --> $DIR/must_outlive_least_region_or_bound.rs:12:69
+ --> $DIR/must_outlive_least_region_or_bound.rs:9:46
+ |
+LL | fn elided2(x: &i32) -> impl Copy + 'static { x }
+ | - ^ returning this value requires that `'1` must outlive `'static`
+ | |
+ | let's call the lifetime of this reference `'1`
+ |
+ = help: consider replacing `'1` with `'static`
+
+error: lifetime may not live long enough
+ --> $DIR/must_outlive_least_region_or_bound.rs:12:55
+ |
+LL | fn explicit2<'a>(x: &'a i32) -> impl Copy + 'static { x }
+ | -- lifetime `'a` defined here ^ returning this value requires that `'a` must outlive `'static`
+ |
+ = help: consider replacing `'a` with `'static`
+ = help: consider replacing `'a` with `'static`
+
+error[E0621]: explicit lifetime required in the type of `x`
+ --> $DIR/must_outlive_least_region_or_bound.rs:15:41
+ |
+LL | fn foo<'a>(x: &i32) -> impl Copy + 'a { x }
+ | ---- ^ lifetime `'a` required
+ | |
+ | help: add explicit lifetime `'a` to the type of `x`: `&'a i32`
+
+error: lifetime may not live long enough
+ --> $DIR/must_outlive_least_region_or_bound.rs:33:69
|
LL | fn with_bound<'a>(x: &'a i32) -> impl LifetimeTrait<'a> + 'static { x }
| -- lifetime `'a` defined here ^ returning this value requires that `'a` must outlive `'static`
@@ -35,7 +62,7 @@ LL | fn with_bound<'a>(x: &'a i32) -> impl LifetimeTrait<'a> + 'static { x }
= help: consider replacing `'a` with `'static`
error: lifetime may not live long enough
- --> $DIR/must_outlive_least_region_or_bound.rs:17:61
+ --> $DIR/must_outlive_least_region_or_bound.rs:38:61
|
LL | fn move_lifetime_into_fn<'a, 'b>(x: &'a u32, y: &'b u32) -> impl Fn(&'a u32) {
| -- -- lifetime `'b` defined here ^^^^^^^^^^^^^^^^ opaque type requires that `'b` must outlive `'a`
@@ -45,13 +72,14 @@ LL | fn move_lifetime_into_fn<'a, 'b>(x: &'a u32, y: &'b u32) -> impl Fn(&'a u32
= help: consider adding the following bound: `'b: 'a`
error[E0310]: the parameter type `T` may not live long enough
- --> $DIR/must_outlive_least_region_or_bound.rs:22:51
+ --> $DIR/must_outlive_least_region_or_bound.rs:43:51
|
LL | fn ty_param_wont_outlive_static(x: T) -> impl Debug + 'static {
| ^^^^^^^^^^^^^^^^^^^^
|
= help: consider adding an explicit lifetime bound `T: 'static`...
-error: aborting due to 5 previous errors
+error: aborting due to 8 previous errors
-For more information about this error, try `rustc --explain E0310`.
+Some errors have detailed explanations: E0310, E0621.
+For more information about an error, try `rustc --explain E0310`.
diff --git a/src/test/ui/impl-trait/must_outlive_least_region_or_bound.rs b/src/test/ui/impl-trait/must_outlive_least_region_or_bound.rs
index 00f3490991b52..beafe9258209d 100644
--- a/src/test/ui/impl-trait/must_outlive_least_region_or_bound.rs
+++ b/src/test/ui/impl-trait/must_outlive_least_region_or_bound.rs
@@ -6,6 +6,27 @@ fn elided(x: &i32) -> impl Copy { x }
fn explicit<'a>(x: &'a i32) -> impl Copy { x }
//~^ ERROR cannot infer an appropriate lifetime
+fn elided2(x: &i32) -> impl Copy + 'static { x }
+//~^ ERROR cannot infer an appropriate lifetime
+
+fn explicit2<'a>(x: &'a i32) -> impl Copy + 'static { x }
+//~^ ERROR cannot infer an appropriate lifetime
+
+fn foo<'a>(x: &i32) -> impl Copy + 'a { x }
+//~^ ERROR explicit lifetime required in the type of `x`
+
+fn elided3(x: &i32) -> Box { Box::new(x) }
+//~^ ERROR cannot infer an appropriate lifetime
+
+fn explicit3<'a>(x: &'a i32) -> Box { Box::new(x) }
+//~^ ERROR cannot infer an appropriate lifetime
+
+fn elided4(x: &i32) -> Box { Box::new(x) }
+//~^ ERROR explicit lifetime required in the type of `x`
+
+fn explicit4<'a>(x: &'a i32) -> Box { Box::new(x) }
+//~^ ERROR cannot infer an appropriate lifetime
+
trait LifetimeTrait<'a> {}
impl<'a> LifetimeTrait<'a> for &'a i32 {}
diff --git a/src/test/ui/impl-trait/must_outlive_least_region_or_bound.stderr b/src/test/ui/impl-trait/must_outlive_least_region_or_bound.stderr
index d7dae6a08a7b9..525e271bea9c3 100644
--- a/src/test/ui/impl-trait/must_outlive_least_region_or_bound.stderr
+++ b/src/test/ui/impl-trait/must_outlive_least_region_or_bound.stderr
@@ -27,7 +27,43 @@ LL | fn explicit<'a>(x: &'a i32) -> impl Copy + 'a { x }
| ^^^^
error: cannot infer an appropriate lifetime
- --> $DIR/must_outlive_least_region_or_bound.rs:12:69
+ --> $DIR/must_outlive_least_region_or_bound.rs:9:46
+ |
+LL | fn elided2(x: &i32) -> impl Copy + 'static { x }
+ | ---- ------------------- ^ ...and is captured here
+ | | |
+ | | ...is required to be `'static` by this...
+ | data with this lifetime...
+ |
+help: to permit non-static references in an `impl Trait` value, you can add an explicit bound for the anonymous lifetime #1 defined on the function body at 9:1
+ |
+LL | fn elided2(x: &i32) -> impl Copy + '_ { x }
+ | ^^
+
+error: cannot infer an appropriate lifetime
+ --> $DIR/must_outlive_least_region_or_bound.rs:12:55
+ |
+LL | fn explicit2<'a>(x: &'a i32) -> impl Copy + 'static { x }
+ | ------- ------------------- ^ ...and is captured here
+ | | |
+ | | ...is required to be `'static` by this...
+ | data with this lifetime...
+ |
+help: to permit non-static references in an `impl Trait` value, you can add an explicit bound for the lifetime `'a` as defined on the function body at 12:14
+ |
+LL | fn explicit2<'a>(x: &'a i32) -> impl Copy + 'a { x }
+ | ^^
+
+error[E0621]: explicit lifetime required in the type of `x`
+ --> $DIR/must_outlive_least_region_or_bound.rs:15:24
+ |
+LL | fn foo<'a>(x: &i32) -> impl Copy + 'a { x }
+ | ---- ^^^^^^^^^^^^^^ lifetime `'a` required
+ | |
+ | help: add explicit lifetime `'a` to the type of `x`: `&'a i32`
+
+error: cannot infer an appropriate lifetime
+ --> $DIR/must_outlive_least_region_or_bound.rs:33:69
|
LL | fn with_bound<'a>(x: &'a i32) -> impl LifetimeTrait<'a> + 'static { x }
| ------- -------------------------------- ^ ...and is captured here
@@ -35,13 +71,13 @@ LL | fn with_bound<'a>(x: &'a i32) -> impl LifetimeTrait<'a> + 'static { x }
| | ...is required to be `'static` by this...
| data with this lifetime...
|
-help: to permit non-static references in an `impl Trait` value, you can add an explicit bound for the lifetime `'a` as defined on the function body at 12:15
+help: to permit non-static references in an `impl Trait` value, you can add an explicit bound for the lifetime `'a` as defined on the function body at 33:15
|
-LL | fn with_bound<'a>(x: &'a i32) -> impl LifetimeTrait<'a> + 'static + 'a { x }
- | ^^^^
+LL | fn with_bound<'a>(x: &'a i32) -> impl LifetimeTrait<'a> + 'a { x }
+ | ^^
error[E0623]: lifetime mismatch
- --> $DIR/must_outlive_least_region_or_bound.rs:17:61
+ --> $DIR/must_outlive_least_region_or_bound.rs:38:61
|
LL | fn move_lifetime_into_fn<'a, 'b>(x: &'a u32, y: &'b u32) -> impl Fn(&'a u32) {
| ------- ^^^^^^^^^^^^^^^^
@@ -50,14 +86,79 @@ LL | fn move_lifetime_into_fn<'a, 'b>(x: &'a u32, y: &'b u32) -> impl Fn(&'a u32
| this parameter and the return type are declared with different lifetimes...
error[E0310]: the parameter type `T` may not live long enough
- --> $DIR/must_outlive_least_region_or_bound.rs:22:51
+ --> $DIR/must_outlive_least_region_or_bound.rs:43:51
|
LL | fn ty_param_wont_outlive_static(x: T) -> impl Debug + 'static {
| -- ^^^^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds
| |
| help: consider adding an explicit lifetime bound...: `T: 'static +`
-error: aborting due to 5 previous errors
+error: cannot infer an appropriate lifetime
+ --> $DIR/must_outlive_least_region_or_bound.rs:18:50
+ |
+LL | fn elided3(x: &i32) -> Box { Box::new(x) }
+ | ---- ---------^-
+ | | | |
+ | | | ...and is captured here
+ | | ...is required to be `'static` by this...
+ | data with this lifetime...
+ |
+help: to permit non-static references in a `dyn Trait` value, you can add an explicit bound for the anonymous lifetime #1 defined on the function body at 18:1
+ |
+LL | fn elided3(x: &i32) -> Box { Box::new(x) }
+ | ^^^^
+
+error: cannot infer an appropriate lifetime
+ --> $DIR/must_outlive_least_region_or_bound.rs:21:59
+ |
+LL | fn explicit3<'a>(x: &'a i32) -> Box { Box::new(x) }
+ | ------- ---------^-
+ | | | |
+ | | | ...and is captured here
+ | | ...is required to be `'static` by this...
+ | data with this lifetime...
+ |
+help: to permit non-static references in a `dyn Trait` value, you can add an explicit bound for the lifetime `'a` as defined on the function body at 21:14
+ |
+LL | fn explicit3<'a>(x: &'a i32) -> Box { Box::new(x) }
+ | ^^^^
+
+error[E0621]: explicit lifetime required in the type of `x`
+ --> $DIR/must_outlive_least_region_or_bound.rs:24:51
+ |
+LL | fn elided4(x: &i32) -> Box { Box::new(x) }
+ | ---- ^^^^^^^^^^^ lifetime `'static` required
+ | |
+ | help: add explicit lifetime `'static` to the type of `x`: `&'static i32`
+
+error[E0495]: cannot infer an appropriate lifetime due to conflicting requirements
+ --> $DIR/must_outlive_least_region_or_bound.rs:27:69
+ |
+LL | fn explicit4<'a>(x: &'a i32) -> Box { Box::new(x) }
+ | ^
+ |
+note: first, the lifetime cannot outlive the lifetime `'a` as defined on the function body at 27:14...
+ --> $DIR/must_outlive_least_region_or_bound.rs:27:14
+ |
+LL | fn explicit4<'a>(x: &'a i32) -> Box { Box::new(x) }
+ | ^^
+note: ...so that the expression is assignable
+ --> $DIR/must_outlive_least_region_or_bound.rs:27:69
+ |
+LL | fn explicit4<'a>(x: &'a i32) -> Box { Box::new(x) }
+ | ^
+ = note: expected `&i32`
+ found `&'a i32`
+ = note: but, the lifetime must be valid for the static lifetime...
+note: ...so that the expression is assignable
+ --> $DIR/must_outlive_least_region_or_bound.rs:27:60
+ |
+LL | fn explicit4<'a>(x: &'a i32) -> Box { Box::new(x) }
+ | ^^^^^^^^^^^
+ = note: expected `std::boxed::Box<(dyn std::fmt::Debug + 'static)>`
+ found `std::boxed::Box`
+
+error: aborting due to 12 previous errors
-Some errors have detailed explanations: E0310, E0623.
+Some errors have detailed explanations: E0310, E0495, E0621, E0623.
For more information about an error, try `rustc --explain E0310`.
From 4e90f177cc530371a314f51f522a4c2e70885e03 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Esteban=20K=C3=BCber?=
Date: Fri, 29 May 2020 18:05:20 -0700
Subject: [PATCH 13/32] When `'static` is explicit, suggest constraining
argument with it
---
.../infer/error_reporting/mod.rs | 3 +-
.../nice_region_error/static_impl_trait.rs | 115 +++++++++++-------
src/librustc_middle/ty/diagnostics.rs | 5 +-
.../must_outlive_least_region_or_bound.rs | 2 +-
.../must_outlive_least_region_or_bound.stderr | 75 +++++++-----
src/test/ui/issues/issue-16922.stderr | 2 +-
...ect-lifetime-default-from-box-error.stderr | 2 +-
...ion-object-lifetime-in-coercion.nll.stderr | 19 ++-
.../region-object-lifetime-in-coercion.rs | 5 +-
.../region-object-lifetime-in-coercion.stderr | 61 +++++++---
.../regions-close-object-into-object-2.stderr | 32 ++---
.../regions-close-object-into-object-4.stderr | 32 ++---
.../regions-proc-bound-capture.nll.stderr | 11 ++
.../ui/regions/regions-proc-bound-capture.rs | 4 +-
.../regions/regions-proc-bound-capture.stderr | 25 ++--
.../dyn-trait-underscore.stderr | 2 +-
16 files changed, 237 insertions(+), 158 deletions(-)
create mode 100644 src/test/ui/regions/regions-proc-bound-capture.nll.stderr
diff --git a/src/librustc_infer/infer/error_reporting/mod.rs b/src/librustc_infer/infer/error_reporting/mod.rs
index 12f7a9c0ca502..9cfa11dd7c813 100644
--- a/src/librustc_infer/infer/error_reporting/mod.rs
+++ b/src/librustc_infer/infer/error_reporting/mod.rs
@@ -2035,8 +2035,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
self.tcx.sess,
var_origin.span(),
E0495,
- "cannot infer an appropriate lifetime{} \
- due to conflicting requirements",
+ "cannot infer an appropriate lifetime{} due to conflicting requirements",
var_description
)
}
diff --git a/src/librustc_infer/infer/error_reporting/nice_region_error/static_impl_trait.rs b/src/librustc_infer/infer/error_reporting/nice_region_error/static_impl_trait.rs
index 88d6c23d51441..e24535bba5fdc 100644
--- a/src/librustc_infer/infer/error_reporting/nice_region_error/static_impl_trait.rs
+++ b/src/librustc_infer/infer/error_reporting/nice_region_error/static_impl_trait.rs
@@ -10,6 +10,7 @@ use rustc_middle::ty::RegionKind;
impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
/// Print the error message for lifetime errors when the return type is a static impl Trait.
pub(super) fn try_report_static_impl_trait(&self) -> Option {
+ debug!("try_report_static_impl_trait(error={:?})", self.error);
if let Some(ref error) = self.error {
if let RegionResolutionError::SubSupConflict(
_,
@@ -18,19 +19,24 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
sub_r,
sup_origin,
sup_r,
- ) = error.clone()
+ ) = error
{
+ debug!(
+ "try_report_static_impl_trait(var={:?}, sub={:?} {:?} sup={:?} {:?})",
+ var_origin, sub_origin, sub_r, sup_origin, sup_r
+ );
let anon_reg_sup = self.tcx().is_suitable_region(sup_r)?;
+ debug!("try_report_static_impl_trait: anon_reg_sup={:?}", anon_reg_sup);
let fn_return = self.tcx().return_type_impl_or_dyn_trait(anon_reg_sup.def_id)?;
- let is_dyn = matches!(fn_return.kind, TyKind::TraitObject(..));
- let fn_return_span = fn_return.span;
- if sub_r == &RegionKind::ReStatic {
+ debug!("try_report_static_impl_trait: fn_return={:?}", fn_return);
+ if **sub_r == RegionKind::ReStatic {
let sp = var_origin.span();
let return_sp = sub_origin.span();
+ let param_info = self.find_param_with_region(sup_r, sub_r)?;
let mut err =
self.tcx().sess.struct_span_err(sp, "cannot infer an appropriate lifetime");
- let param_info = self.find_param_with_region(sup_r, sub_r)?;
err.span_label(param_info.param_ty_span, "data with this lifetime...");
+ debug!("try_report_static_impl_trait: param_info={:?}", param_info);
// We try to make the output have fewer overlapping spans if possible.
if (sp == sup_origin.span() || !return_sp.overlaps(sup_origin.span()))
@@ -60,14 +66,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
if sup_r.has_name() { sup_r.to_string() } else { "'_".to_owned() };
// only apply this suggestion onto functions with
// explicit non-desugar'able return.
- if fn_return_span.desugaring_kind().is_none() {
- let msg = format!(
- "to permit non-static references in {} `{} Trait` value, you can add \
- an explicit bound for {}",
- if is_dyn { "a" } else { "an" },
- if is_dyn { "dyn" } else { "impl" },
- lifetime,
- );
+ if fn_return.span.desugaring_kind().is_none() {
// FIXME: account for the need of parens in `&(dyn Trait + '_)`
match fn_return.kind {
TyKind::Def(item_id, _) => {
@@ -78,7 +77,8 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
err.emit();
return Some(ErrorReported);
};
- let (span, sugg) = opaque
+
+ if let Some(span) = opaque
.bounds
.iter()
.filter_map(|arg| match arg {
@@ -86,38 +86,71 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
name: LifetimeName::Static,
span,
..
- }) => Some((*span, lifetime_name.clone())),
+ }) => Some(*span),
_ => None,
})
.next()
- .unwrap_or_else(|| {
- (
- fn_return_span.shrink_to_hi(),
- format!(" + {}", lifetime_name),
- )
- });
-
- err.span_suggestion_verbose(
- span,
- &msg,
- sugg,
- Applicability::MaybeIncorrect,
- );
- }
- TyKind::TraitObject(_, lt) => {
- let (span, sugg) = match lt.name {
- LifetimeName::ImplicitObjectLifetimeDefault => (
- fn_return_span.shrink_to_hi(),
+ {
+ err.span_suggestion_verbose(
+ span,
+ "consider changing the `impl Trait`'s explicit \
+ `'static` bound",
+ lifetime_name,
+ Applicability::MaybeIncorrect,
+ );
+ err.span_suggestion_verbose(
+ param_info.param_ty_span,
+ "alternatively, set an explicit `'static` lifetime to \
+ this parameter",
+ param_info.param_ty.to_string(),
+ Applicability::MaybeIncorrect,
+ );
+ } else {
+ err.span_suggestion_verbose(
+ fn_return.span.shrink_to_hi(),
+ &format!(
+ "to permit non-static references in an `impl Trait` \
+ value, you can add an explicit bound for {}",
+ lifetime,
+ ),
format!(" + {}", lifetime_name),
- ),
- _ => (lt.span, lifetime_name),
+ Applicability::MaybeIncorrect,
+ );
};
- err.span_suggestion_verbose(
- span,
- &msg,
- sugg,
- Applicability::MaybeIncorrect,
- );
+ }
+ TyKind::TraitObject(_, lt) => {
+ match lt.name {
+ LifetimeName::ImplicitObjectLifetimeDefault => {
+ err.span_suggestion_verbose(
+ fn_return.span.shrink_to_hi(),
+ &format!(
+ "to permit non-static references in a trait object \
+ value, you can add an explicit bound for {}",
+ lifetime,
+ ),
+ format!(" + {}", lifetime_name),
+ Applicability::MaybeIncorrect,
+ );
+ }
+ _ => {
+ err.span_suggestion_verbose(
+ lt.span,
+ "consider changing the trait object's explicit \
+ `'static` bound",
+ lifetime_name,
+ Applicability::MaybeIncorrect,
+ );
+ err.span_suggestion_verbose(
+ param_info.param_ty_span,
+ &format!(
+ "alternatively, set an explicit `'static` lifetime \
+ in this parameter",
+ ),
+ param_info.param_ty.to_string(),
+ Applicability::MaybeIncorrect,
+ );
+ }
+ }
}
_ => {}
}
diff --git a/src/librustc_middle/ty/diagnostics.rs b/src/librustc_middle/ty/diagnostics.rs
index 3ca506fe0d590..a2812e117ed39 100644
--- a/src/librustc_middle/ty/diagnostics.rs
+++ b/src/librustc_middle/ty/diagnostics.rs
@@ -247,7 +247,10 @@ impl<'v> hir::intravisit::Visitor<'v> for TraitObjectVisitor<'v> {
fn visit_ty(&mut self, ty: &'v hir::Ty<'v>) {
if let hir::TyKind::TraitObject(
_,
- hir::Lifetime { name: hir::LifetimeName::ImplicitObjectLifetimeDefault, .. },
+ hir::Lifetime {
+ name: hir::LifetimeName::ImplicitObjectLifetimeDefault | hir::LifetimeName::Static,
+ ..
+ },
) = ty.kind
{
self.0.push(ty);
diff --git a/src/test/ui/impl-trait/must_outlive_least_region_or_bound.rs b/src/test/ui/impl-trait/must_outlive_least_region_or_bound.rs
index beafe9258209d..837244b022721 100644
--- a/src/test/ui/impl-trait/must_outlive_least_region_or_bound.rs
+++ b/src/test/ui/impl-trait/must_outlive_least_region_or_bound.rs
@@ -22,7 +22,7 @@ fn explicit3<'a>(x: &'a i32) -> Box { Box::new(x) }
//~^ ERROR cannot infer an appropriate lifetime
fn elided4(x: &i32) -> Box { Box::new(x) }
-//~^ ERROR explicit lifetime required in the type of `x`
+//~^ ERROR cannot infer an appropriate lifetime
fn explicit4<'a>(x: &'a i32) -> Box { Box::new(x) }
//~^ ERROR cannot infer an appropriate lifetime
diff --git a/src/test/ui/impl-trait/must_outlive_least_region_or_bound.stderr b/src/test/ui/impl-trait/must_outlive_least_region_or_bound.stderr
index 525e271bea9c3..96d4a121c16af 100644
--- a/src/test/ui/impl-trait/must_outlive_least_region_or_bound.stderr
+++ b/src/test/ui/impl-trait/must_outlive_least_region_or_bound.stderr
@@ -35,10 +35,14 @@ LL | fn elided2(x: &i32) -> impl Copy + 'static { x }
| | ...is required to be `'static` by this...
| data with this lifetime...
|
-help: to permit non-static references in an `impl Trait` value, you can add an explicit bound for the anonymous lifetime #1 defined on the function body at 9:1
+help: consider changing the `impl Trait`'s explicit `'static` bound
|
LL | fn elided2(x: &i32) -> impl Copy + '_ { x }
| ^^
+help: alternatively, set an explicit `'static` lifetime to this parameter
+ |
+LL | fn elided2(x: &'static i32) -> impl Copy + 'static { x }
+ | ^^^^^^^^^^^^
error: cannot infer an appropriate lifetime
--> $DIR/must_outlive_least_region_or_bound.rs:12:55
@@ -49,10 +53,14 @@ LL | fn explicit2<'a>(x: &'a i32) -> impl Copy + 'static { x }
| | ...is required to be `'static` by this...
| data with this lifetime...
|
-help: to permit non-static references in an `impl Trait` value, you can add an explicit bound for the lifetime `'a` as defined on the function body at 12:14
+help: consider changing the `impl Trait`'s explicit `'static` bound
|
LL | fn explicit2<'a>(x: &'a i32) -> impl Copy + 'a { x }
| ^^
+help: alternatively, set an explicit `'static` lifetime to this parameter
+ |
+LL | fn explicit2<'a>(x: &'static i32) -> impl Copy + 'static { x }
+ | ^^^^^^^^^^^^
error[E0621]: explicit lifetime required in the type of `x`
--> $DIR/must_outlive_least_region_or_bound.rs:15:24
@@ -71,10 +79,14 @@ LL | fn with_bound<'a>(x: &'a i32) -> impl LifetimeTrait<'a> + 'static { x }
| | ...is required to be `'static` by this...
| data with this lifetime...
|
-help: to permit non-static references in an `impl Trait` value, you can add an explicit bound for the lifetime `'a` as defined on the function body at 33:15
+help: consider changing the `impl Trait`'s explicit `'static` bound
|
LL | fn with_bound<'a>(x: &'a i32) -> impl LifetimeTrait<'a> + 'a { x }
| ^^
+help: alternatively, set an explicit `'static` lifetime to this parameter
+ |
+LL | fn with_bound<'a>(x: &'static i32) -> impl LifetimeTrait<'a> + 'static { x }
+ | ^^^^^^^^^^^^
error[E0623]: lifetime mismatch
--> $DIR/must_outlive_least_region_or_bound.rs:38:61
@@ -103,7 +115,7 @@ LL | fn elided3(x: &i32) -> Box { Box::new(x) }
| | ...is required to be `'static` by this...
| data with this lifetime...
|
-help: to permit non-static references in a `dyn Trait` value, you can add an explicit bound for the anonymous lifetime #1 defined on the function body at 18:1
+help: to permit non-static references in a trait object value, you can add an explicit bound for the anonymous lifetime #1 defined on the function body at 18:1
|
LL | fn elided3(x: &i32) -> Box { Box::new(x) }
| ^^^^
@@ -118,47 +130,48 @@ LL | fn explicit3<'a>(x: &'a i32) -> Box { Box::new(x) }
| | ...is required to be `'static` by this...
| data with this lifetime...
|
-help: to permit non-static references in a `dyn Trait` value, you can add an explicit bound for the lifetime `'a` as defined on the function body at 21:14
+help: to permit non-static references in a trait object value, you can add an explicit bound for the lifetime `'a` as defined on the function body at 21:14
|
LL | fn explicit3<'a>(x: &'a i32) -> Box { Box::new(x) }
| ^^^^
-error[E0621]: explicit lifetime required in the type of `x`
- --> $DIR/must_outlive_least_region_or_bound.rs:24:51
+error: cannot infer an appropriate lifetime
+ --> $DIR/must_outlive_least_region_or_bound.rs:24:60
|
LL | fn elided4(x: &i32) -> Box { Box::new(x) }
- | ---- ^^^^^^^^^^^ lifetime `'static` required
- | |
- | help: add explicit lifetime `'static` to the type of `x`: `&'static i32`
-
-error[E0495]: cannot infer an appropriate lifetime due to conflicting requirements
- --> $DIR/must_outlive_least_region_or_bound.rs:27:69
+ | ---- ---------^-
+ | | | |
+ | | | ...and is captured here
+ | data with this lifetime... ...is required to be `'static` by this...
|
-LL | fn explicit4<'a>(x: &'a i32) -> Box { Box::new(x) }
- | ^
+help: consider changing the trait object's explicit `'static` bound
|
-note: first, the lifetime cannot outlive the lifetime `'a` as defined on the function body at 27:14...
- --> $DIR/must_outlive_least_region_or_bound.rs:27:14
+LL | fn elided4(x: &i32) -> Box { Box::new(x) }
+ | ^^
+help: alternatively, set an explicit `'static` lifetime in this parameter
|
-LL | fn explicit4<'a>(x: &'a i32) -> Box { Box::new(x) }
- | ^^
-note: ...so that the expression is assignable
+LL | fn elided4(x: &'static i32) -> Box { Box::new(x) }
+ | ^^^^^^^^^^^^
+
+error: cannot infer an appropriate lifetime
--> $DIR/must_outlive_least_region_or_bound.rs:27:69
|
LL | fn explicit4<'a>(x: &'a i32) -> Box { Box::new(x) }
- | ^
- = note: expected `&i32`
- found `&'a i32`
- = note: but, the lifetime must be valid for the static lifetime...
-note: ...so that the expression is assignable
- --> $DIR/must_outlive_least_region_or_bound.rs:27:60
+ | ------- ---------^-
+ | | | |
+ | | | ...and is captured here
+ | data with this lifetime... ...is required to be `'static` by this...
|
-LL | fn explicit4<'a>(x: &'a i32) -> Box { Box::new(x) }
- | ^^^^^^^^^^^
- = note: expected `std::boxed::Box<(dyn std::fmt::Debug + 'static)>`
- found `std::boxed::Box`
+help: consider changing the trait object's explicit `'static` bound
+ |
+LL | fn explicit4<'a>(x: &'a i32) -> Box { Box::new(x) }
+ | ^^
+help: alternatively, set an explicit `'static` lifetime in this parameter
+ |
+LL | fn explicit4<'a>(x: &'static i32) -> Box { Box::new(x) }
+ | ^^^^^^^^^^^^
error: aborting due to 12 previous errors
-Some errors have detailed explanations: E0310, E0495, E0621, E0623.
+Some errors have detailed explanations: E0310, E0621, E0623.
For more information about an error, try `rustc --explain E0310`.
diff --git a/src/test/ui/issues/issue-16922.stderr b/src/test/ui/issues/issue-16922.stderr
index 02d33aae023ff..038df47e1bd98 100644
--- a/src/test/ui/issues/issue-16922.stderr
+++ b/src/test/ui/issues/issue-16922.stderr
@@ -9,7 +9,7 @@ LL | Box::new(value) as Box
| | ...and is captured here
| ...is required to be `'static` by this...
|
-help: to permit non-static references in a `dyn Trait` value, you can add an explicit bound for the anonymous lifetime #1 defined on the function body at 3:1
+help: to permit non-static references in a trait object value, you can add an explicit bound for the anonymous lifetime #1 defined on the function body at 3:1
|
LL | fn foo(value: &T) -> Box {
| ^^^^
diff --git a/src/test/ui/object-lifetime/object-lifetime-default-from-box-error.stderr b/src/test/ui/object-lifetime/object-lifetime-default-from-box-error.stderr
index 70a9bf22b8db3..555622c9d13c1 100644
--- a/src/test/ui/object-lifetime/object-lifetime-default-from-box-error.stderr
+++ b/src/test/ui/object-lifetime/object-lifetime-default-from-box-error.stderr
@@ -7,7 +7,7 @@ LL | fn load(ss: &mut SomeStruct) -> Box {
LL | ss.r
| ^^^^ ...is captured and required to be `'static` here
|
-help: to permit non-static references in a `dyn Trait` value, you can add an explicit bound for the anonymous lifetime #2 defined on the function body at 14:1
+help: to permit non-static references in a trait object value, you can add an explicit bound for the anonymous lifetime #2 defined on the function body at 14:1
|
LL | fn load(ss: &mut SomeStruct) -> Box {
| ^^^^
diff --git a/src/test/ui/regions/region-object-lifetime-in-coercion.nll.stderr b/src/test/ui/regions/region-object-lifetime-in-coercion.nll.stderr
index bf02ba8eb9199..7e8f78067e08a 100644
--- a/src/test/ui/regions/region-object-lifetime-in-coercion.nll.stderr
+++ b/src/test/ui/regions/region-object-lifetime-in-coercion.nll.stderr
@@ -1,21 +1,21 @@
-error[E0621]: explicit lifetime required in the type of `v`
+error: lifetime may not live long enough
--> $DIR/region-object-lifetime-in-coercion.rs:8:12
|
LL | fn a(v: &[u8]) -> Box {
- | ----- help: add explicit lifetime `'static` to the type of `v`: `&'static [u8]`
+ | - let's call the lifetime of this reference `'1`
LL | let x: Box = Box::new(v);
- | ^^^^^^^^^^^^^^^^^^^^^^ lifetime `'static` required
+ | ^^^^^^^^^^^^^^^^^^^^^^ type annotation requires that `'1` must outlive `'static`
-error[E0621]: explicit lifetime required in the type of `v`
- --> $DIR/region-object-lifetime-in-coercion.rs:14:5
+error: lifetime may not live long enough
+ --> $DIR/region-object-lifetime-in-coercion.rs:13:5
|
LL | fn b(v: &[u8]) -> Box {
- | ----- help: add explicit lifetime `'static` to the type of `v`: `&'static [u8]`
+ | - let's call the lifetime of this reference `'1`
LL | Box::new(v)
- | ^^^^^^^^^^^ lifetime `'static` required
+ | ^^^^^^^^^^^ returning this value requires that `'1` must outlive `'static`
error: lifetime may not live long enough
- --> $DIR/region-object-lifetime-in-coercion.rs:20:5
+ --> $DIR/region-object-lifetime-in-coercion.rs:19:5
|
LL | fn c(v: &[u8]) -> Box {
| - let's call the lifetime of this reference `'1`
@@ -24,7 +24,7 @@ LL | Box::new(v)
| ^^^^^^^^^^^ returning this value requires that `'1` must outlive `'static`
error: lifetime may not live long enough
- --> $DIR/region-object-lifetime-in-coercion.rs:24:5
+ --> $DIR/region-object-lifetime-in-coercion.rs:23:5
|
LL | fn d<'a,'b>(v: &'a [u8]) -> Box {
| -- -- lifetime `'b` defined here
@@ -37,4 +37,3 @@ LL | Box::new(v)
error: aborting due to 4 previous errors
-For more information about this error, try `rustc --explain E0621`.
diff --git a/src/test/ui/regions/region-object-lifetime-in-coercion.rs b/src/test/ui/regions/region-object-lifetime-in-coercion.rs
index d56eaf77b6646..5d199149c39b8 100644
--- a/src/test/ui/regions/region-object-lifetime-in-coercion.rs
+++ b/src/test/ui/regions/region-object-lifetime-in-coercion.rs
@@ -5,13 +5,12 @@ trait Foo {}
impl<'a> Foo for &'a [u8] {}
fn a(v: &[u8]) -> Box {
- let x: Box = Box::new(v);
- //~^ ERROR explicit lifetime required in the type of `v` [E0621]
+ let x: Box = Box::new(v); //~ ERROR cannot infer an appropriate lifetime
x
}
fn b(v: &[u8]) -> Box {
- Box::new(v) //~ ERROR explicit lifetime required in the type of `v` [E0621]
+ Box::new(v) //~ ERROR cannot infer an appropriate lifetime
}
fn c(v: &[u8]) -> Box {
diff --git a/src/test/ui/regions/region-object-lifetime-in-coercion.stderr b/src/test/ui/regions/region-object-lifetime-in-coercion.stderr
index 1462af44cb15a..673300cebc26c 100644
--- a/src/test/ui/regions/region-object-lifetime-in-coercion.stderr
+++ b/src/test/ui/regions/region-object-lifetime-in-coercion.stderr
@@ -1,21 +1,45 @@
-error[E0621]: explicit lifetime required in the type of `v`
- --> $DIR/region-object-lifetime-in-coercion.rs:8:37
+error: cannot infer an appropriate lifetime
+ --> $DIR/region-object-lifetime-in-coercion.rs:8:46
|
LL | fn a(v: &[u8]) -> Box {
- | ----- help: add explicit lifetime `'static` to the type of `v`: `&'static [u8]`
+ | ----- data with this lifetime...
LL | let x: Box = Box::new(v);
- | ^^^^^^^^^^^ lifetime `'static` required
+ | ---------^-
+ | | |
+ | | ...and is captured here
+ | ...is required to be `'static` by this...
+ |
+help: consider changing the trait object's explicit `'static` bound
+ |
+LL | fn a(v: &[u8]) -> Box {
+ | ^^
+help: alternatively, set an explicit `'static` lifetime in this parameter
+ |
+LL | fn a(v: &'static [u8]) -> Box {
+ | ^^^^^^^^^^^^^
-error[E0621]: explicit lifetime required in the type of `v`
- --> $DIR/region-object-lifetime-in-coercion.rs:14:5
+error: cannot infer an appropriate lifetime
+ --> $DIR/region-object-lifetime-in-coercion.rs:13:14
|
LL | fn b(v: &[u8]) -> Box {
- | ----- help: add explicit lifetime `'static` to the type of `v`: `&'static [u8]`
+ | ----- data with this lifetime...
LL | Box::new(v)
- | ^^^^^^^^^^^ lifetime `'static` required
+ | ---------^-
+ | | |
+ | | ...and is captured here
+ | ...is required to be `'static` by this...
+ |
+help: consider changing the trait object's explicit `'static` bound
+ |
+LL | fn b(v: &[u8]) -> Box {
+ | ^^
+help: alternatively, set an explicit `'static` lifetime in this parameter
+ |
+LL | fn b(v: &'static [u8]) -> Box {
+ | ^^^^^^^^^^^^^
error: cannot infer an appropriate lifetime
- --> $DIR/region-object-lifetime-in-coercion.rs:20:14
+ --> $DIR/region-object-lifetime-in-coercion.rs:19:14
|
LL | fn c(v: &[u8]) -> Box {
| ----- data with this lifetime...
@@ -26,36 +50,36 @@ LL | Box::new(v)
| | ...and is captured here
| ...is required to be `'static` by this...
|
-help: to permit non-static references in a `dyn Trait` value, you can add an explicit bound for the anonymous lifetime #1 defined on the function body at 17:1
+help: to permit non-static references in a trait object value, you can add an explicit bound for the anonymous lifetime #1 defined on the function body at 16:1
|
LL | fn c(v: &[u8]) -> Box {
| ^^^^
error[E0495]: cannot infer an appropriate lifetime due to conflicting requirements
- --> $DIR/region-object-lifetime-in-coercion.rs:24:14
+ --> $DIR/region-object-lifetime-in-coercion.rs:23:14
|
LL | Box::new(v)
| ^
|
-note: first, the lifetime cannot outlive the lifetime `'a` as defined on the function body at 23:6...
- --> $DIR/region-object-lifetime-in-coercion.rs:23:6
+note: first, the lifetime cannot outlive the lifetime `'a` as defined on the function body at 22:6...
+ --> $DIR/region-object-lifetime-in-coercion.rs:22:6
|
LL | fn d<'a,'b>(v: &'a [u8]) -> Box {
| ^^
note: ...so that the expression is assignable
- --> $DIR/region-object-lifetime-in-coercion.rs:24:14
+ --> $DIR/region-object-lifetime-in-coercion.rs:23:14
|
LL | Box::new(v)
| ^
= note: expected `&[u8]`
found `&'a [u8]`
-note: but, the lifetime must be valid for the lifetime `'b` as defined on the function body at 23:9...
- --> $DIR/region-object-lifetime-in-coercion.rs:23:9
+note: but, the lifetime must be valid for the lifetime `'b` as defined on the function body at 22:9...
+ --> $DIR/region-object-lifetime-in-coercion.rs:22:9
|
LL | fn d<'a,'b>(v: &'a [u8]) -> Box {
| ^^
note: ...so that the expression is assignable
- --> $DIR/region-object-lifetime-in-coercion.rs:24:5
+ --> $DIR/region-object-lifetime-in-coercion.rs:23:5
|
LL | Box::new(v)
| ^^^^^^^^^^^
@@ -64,5 +88,4 @@ LL | Box::new(v)
error: aborting due to 4 previous errors
-Some errors have detailed explanations: E0495, E0621.
-For more information about an error, try `rustc --explain E0495`.
+For more information about this error, try `rustc --explain E0495`.
diff --git a/src/test/ui/regions/regions-close-object-into-object-2.stderr b/src/test/ui/regions/regions-close-object-into-object-2.stderr
index 147f7f3541816..982ed07232a80 100644
--- a/src/test/ui/regions/regions-close-object-into-object-2.stderr
+++ b/src/test/ui/regions/regions-close-object-into-object-2.stderr
@@ -1,28 +1,22 @@
-error[E0495]: cannot infer an appropriate lifetime for borrow expression due to conflicting requirements
+error: cannot infer an appropriate lifetime
--> $DIR/regions-close-object-into-object-2.rs:10:11
|
+LL | fn g<'a, T: 'static>(v: Box + 'a>) -> Box {
+ | ------------------ data with this lifetime...
LL | box B(&*v) as Box
- | ^^^
- |
-note: first, the lifetime cannot outlive the lifetime `'a` as defined on the function body at 9:6...
- --> $DIR/regions-close-object-into-object-2.rs:9:6
+ | ------^^^---------------
+ | | |
+ | | ...and is captured here
+ | ...is required to be `'static` by this...
|
-LL | fn g<'a, T: 'static>(v: Box + 'a>) -> Box {
- | ^^
-note: ...so that the type `(dyn A + 'a)` is not borrowed for too long
- --> $DIR/regions-close-object-into-object-2.rs:10:11
+help: consider changing the trait object's explicit `'static` bound
|
-LL | box B(&*v) as Box
- | ^^^
- = note: but, the lifetime must be valid for the static lifetime...
-note: ...so that the expression is assignable
- --> $DIR/regions-close-object-into-object-2.rs:10:5
+LL | fn g<'a, T: 'static>(v: Box + 'a>) -> Box {
+ | ^^
+help: alternatively, set an explicit `'static` lifetime in this parameter
|
-LL | box B(&*v) as Box
- | ^^^^^^^^^^^^^^^^^^^^^^^^
- = note: expected `std::boxed::Box<(dyn X + 'static)>`
- found `std::boxed::Box`
+LL | fn g<'a, T: 'static>(v: std::boxed::Box<(dyn A + 'static)>) -> Box {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: aborting due to previous error
-For more information about this error, try `rustc --explain E0495`.
diff --git a/src/test/ui/regions/regions-close-object-into-object-4.stderr b/src/test/ui/regions/regions-close-object-into-object-4.stderr
index 6e7d6152cd09a..1b82098ee13c2 100644
--- a/src/test/ui/regions/regions-close-object-into-object-4.stderr
+++ b/src/test/ui/regions/regions-close-object-into-object-4.stderr
@@ -1,28 +1,22 @@
-error[E0495]: cannot infer an appropriate lifetime for borrow expression due to conflicting requirements
+error: cannot infer an appropriate lifetime
--> $DIR/regions-close-object-into-object-4.rs:10:11
|
+LL | fn i<'a, T, U>(v: Box+'a>) -> Box {
+ | ---------------- data with this lifetime...
LL | box B(&*v) as Box
- | ^^^
- |
-note: first, the lifetime cannot outlive the lifetime `'a` as defined on the function body at 9:6...
- --> $DIR/regions-close-object-into-object-4.rs:9:6
+ | ------^^^---------------
+ | | |
+ | | ...and is captured here
+ | ...is required to be `'static` by this...
|
-LL | fn i<'a, T, U>(v: Box+'a>) -> Box {
- | ^^
-note: ...so that the type `(dyn A + 'a)` is not borrowed for too long
- --> $DIR/regions-close-object-into-object-4.rs:10:11
+help: consider changing the trait object's explicit `'static` bound
|
-LL | box B(&*v) as Box
- | ^^^
- = note: but, the lifetime must be valid for the static lifetime...
-note: ...so that the expression is assignable
- --> $DIR/regions-close-object-into-object-4.rs:10:5
+LL | fn i<'a, T, U>(v: Box+'a>) -> Box {
+ | ^^
+help: alternatively, set an explicit `'static` lifetime in this parameter
|
-LL | box B(&*v) as Box
- | ^^^^^^^^^^^^^^^^^^^^^^^^
- = note: expected `std::boxed::Box<(dyn X + 'static)>`
- found `std::boxed::Box`
+LL | fn i<'a, T, U>(v: std::boxed::Box<(dyn A + 'static)>) -> Box {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: aborting due to previous error
-For more information about this error, try `rustc --explain E0495`.
diff --git a/src/test/ui/regions/regions-proc-bound-capture.nll.stderr b/src/test/ui/regions/regions-proc-bound-capture.nll.stderr
new file mode 100644
index 0000000000000..75890b8581537
--- /dev/null
+++ b/src/test/ui/regions/regions-proc-bound-capture.nll.stderr
@@ -0,0 +1,11 @@
+error: lifetime may not live long enough
+ --> $DIR/regions-proc-bound-capture.rs:9:5
+ |
+LL | fn static_proc(x: &isize) -> Box (isize) + 'static> {
+ | - let's call the lifetime of this reference `'1`
+LL | // This is illegal, because the region bound on `proc` is 'static.
+LL | Box::new(move || { *x })
+ | ^^^^^^^^^^^^^^^^^^^^^^^^ returning this value requires that `'1` must outlive `'static`
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/regions/regions-proc-bound-capture.rs b/src/test/ui/regions/regions-proc-bound-capture.rs
index 0c903b7384992..8617c0e9da8f7 100644
--- a/src/test/ui/regions/regions-proc-bound-capture.rs
+++ b/src/test/ui/regions/regions-proc-bound-capture.rs
@@ -4,9 +4,9 @@ fn borrowed_proc<'a>(x: &'a isize) -> Box(isize) + 'a> {
Box::new(move|| { *x })
}
-fn static_proc(x: &isize) -> Box(isize) + 'static> {
+fn static_proc(x: &isize) -> Box (isize) + 'static> {
// This is illegal, because the region bound on `proc` is 'static.
- Box::new(move|| { *x }) //~ ERROR explicit lifetime required in the type of `x` [E0621]
+ Box::new(move || { *x }) //~ ERROR cannot infer an appropriate lifetime
}
fn main() { }
diff --git a/src/test/ui/regions/regions-proc-bound-capture.stderr b/src/test/ui/regions/regions-proc-bound-capture.stderr
index c53af34456ef3..e7bbfaababe8a 100644
--- a/src/test/ui/regions/regions-proc-bound-capture.stderr
+++ b/src/test/ui/regions/regions-proc-bound-capture.stderr
@@ -1,12 +1,23 @@
-error[E0621]: explicit lifetime required in the type of `x`
- --> $DIR/regions-proc-bound-capture.rs:9:5
+error: cannot infer an appropriate lifetime
+ --> $DIR/regions-proc-bound-capture.rs:9:14
|
-LL | fn static_proc(x: &isize) -> Box(isize) + 'static> {
- | ------ help: add explicit lifetime `'static` to the type of `x`: `&'static isize`
+LL | fn static_proc(x: &isize) -> Box (isize) + 'static> {
+ | ------ data with this lifetime...
LL | // This is illegal, because the region bound on `proc` is 'static.
-LL | Box::new(move|| { *x })
- | ^^^^^^^^^^^^^^^^^^^^^^^ lifetime `'static` required
+LL | Box::new(move || { *x })
+ | ---------^^^^^^^^^^^^^^-
+ | | |
+ | | ...and is captured here
+ | ...is required to be `'static` by this...
+ |
+help: consider changing the trait object's explicit `'static` bound
+ |
+LL | fn static_proc(x: &isize) -> Box (isize) + '_> {
+ | ^^
+help: alternatively, set an explicit `'static` lifetime in this parameter
+ |
+LL | fn static_proc(x: &'static isize) -> Box (isize) + 'static> {
+ | ^^^^^^^^^^^^^^
error: aborting due to previous error
-For more information about this error, try `rustc --explain E0621`.
diff --git a/src/test/ui/underscore-lifetime/dyn-trait-underscore.stderr b/src/test/ui/underscore-lifetime/dyn-trait-underscore.stderr
index 3577dd59289e5..4dc4aac6ceac4 100644
--- a/src/test/ui/underscore-lifetime/dyn-trait-underscore.stderr
+++ b/src/test/ui/underscore-lifetime/dyn-trait-underscore.stderr
@@ -7,7 +7,7 @@ LL | // ^^^^^^^^^^^^^^^^^^^^^ bound *here* defaults to
LL | Box::new(items.iter())
| ---------------^^^^--- ...is captured and required to be `'static` here
|
-help: to permit non-static references in a `dyn Trait` value, you can add an explicit bound for the anonymous lifetime #1 defined on the function body at 6:1
+help: to permit non-static references in a trait object value, you can add an explicit bound for the anonymous lifetime #1 defined on the function body at 6:1
|
LL | fn a(items: &[T]) -> Box + '_> {
| ^^^^
From 921f35fe73e8749dee8531f7fbaf2cb4958fa799 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Esteban=20K=C3=BCber?=
Date: Fri, 29 May 2020 18:59:42 -0700
Subject: [PATCH 14/32] Reduce verbosity of suggestion message and mention
lifetime in label
---
.../nice_region_error/static_impl_trait.rs | 87 ++++++++++---------
.../ui/async-await/issues/issue-62097.stderr | 2 +-
.../must_outlive_least_region_or_bound.stderr | 38 ++++----
.../static-return-lifetime-infered.stderr | 8 +-
src/test/ui/issues/issue-16922.stderr | 4 +-
...ect-lifetime-default-from-box-error.stderr | 4 +-
.../region-object-lifetime-in-coercion.stderr | 12 +--
.../regions-close-object-into-object-2.stderr | 4 +-
.../regions-close-object-into-object-4.stderr | 4 +-
.../regions/regions-proc-bound-capture.stderr | 4 +-
...types_pin_lifetime_impl_trait-async.stderr | 2 +-
..._self_types_pin_lifetime_impl_trait.stderr | 4 +-
.../missing-lifetimes-in-signature.stderr | 4 +-
.../dyn-trait-underscore.stderr | 4 +-
14 files changed, 95 insertions(+), 86 deletions(-)
diff --git a/src/librustc_infer/infer/error_reporting/nice_region_error/static_impl_trait.rs b/src/librustc_infer/infer/error_reporting/nice_region_error/static_impl_trait.rs
index e24535bba5fdc..e9f165d309f8f 100644
--- a/src/librustc_infer/infer/error_reporting/nice_region_error/static_impl_trait.rs
+++ b/src/librustc_infer/infer/error_reporting/nice_region_error/static_impl_trait.rs
@@ -1,6 +1,5 @@
//! Error Reporting for static impl Traits.
-use crate::infer::error_reporting::msg_span_from_free_region;
use crate::infer::error_reporting::nice_region_error::NiceRegionError;
use crate::infer::lexical_region_resolve::RegionResolutionError;
use rustc_errors::{Applicability, ErrorReported};
@@ -33,9 +32,17 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
let sp = var_origin.span();
let return_sp = sub_origin.span();
let param_info = self.find_param_with_region(sup_r, sub_r)?;
+ let (lifetime_name, lifetime) = if sup_r.has_name() {
+ (sup_r.to_string(), format!("lifetime `{}`", sup_r))
+ } else {
+ ("'_".to_owned(), "the anonymous lifetime `'_`".to_string())
+ };
let mut err =
self.tcx().sess.struct_span_err(sp, "cannot infer an appropriate lifetime");
- err.span_label(param_info.param_ty_span, "data with this lifetime...");
+ err.span_label(
+ param_info.param_ty_span,
+ &format!("this data with {}...", lifetime),
+ );
debug!("try_report_static_impl_trait: param_info={:?}", param_info);
// We try to make the output have fewer overlapping spans if possible.
@@ -60,10 +67,6 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
);
}
- let (lifetime, _) = msg_span_from_free_region(self.tcx(), sup_r);
-
- let lifetime_name =
- if sup_r.has_name() { sup_r.to_string() } else { "'_".to_owned() };
// only apply this suggestion onto functions with
// explicit non-desugar'able return.
if fn_return.span.desugaring_kind().is_none() {
@@ -93,8 +96,11 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
{
err.span_suggestion_verbose(
span,
- "consider changing the `impl Trait`'s explicit \
- `'static` bound",
+ &format!(
+ "consider changing the `impl Trait`'s explicit \
+ `'static` bound to {}",
+ lifetime,
+ ),
lifetime_name,
Applicability::MaybeIncorrect,
);
@@ -118,40 +124,41 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
);
};
}
- TyKind::TraitObject(_, lt) => {
- match lt.name {
- LifetimeName::ImplicitObjectLifetimeDefault => {
- err.span_suggestion_verbose(
- fn_return.span.shrink_to_hi(),
- &format!(
- "to permit non-static references in a trait object \
- value, you can add an explicit bound for {}",
- lifetime,
- ),
- format!(" + {}", lifetime_name),
- Applicability::MaybeIncorrect,
- );
- }
- _ => {
- err.span_suggestion_verbose(
- lt.span,
+ TyKind::TraitObject(_, lt) => match lt.name {
+ LifetimeName::ImplicitObjectLifetimeDefault => {
+ err.span_suggestion_verbose(
+ fn_return.span.shrink_to_hi(),
+ &format!(
+ "to permit non-static references in a trait object \
+ value, you can add an explicit bound for {}",
+ lifetime,
+ ),
+ format!(" + {}", lifetime_name),
+ Applicability::MaybeIncorrect,
+ );
+ }
+ _ => {
+ err.span_suggestion_verbose(
+ lt.span,
+ &format!(
"consider changing the trait object's explicit \
- `'static` bound",
- lifetime_name,
- Applicability::MaybeIncorrect,
- );
- err.span_suggestion_verbose(
- param_info.param_ty_span,
- &format!(
- "alternatively, set an explicit `'static` lifetime \
- in this parameter",
- ),
- param_info.param_ty.to_string(),
- Applicability::MaybeIncorrect,
- );
- }
+ `'static` bound to {}",
+ lifetime,
+ ),
+ lifetime_name,
+ Applicability::MaybeIncorrect,
+ );
+ err.span_suggestion_verbose(
+ param_info.param_ty_span,
+ &format!(
+ "alternatively, set an explicit `'static` lifetime \
+ in this parameter",
+ ),
+ param_info.param_ty.to_string(),
+ Applicability::MaybeIncorrect,
+ );
}
- }
+ },
_ => {}
}
}
diff --git a/src/test/ui/async-await/issues/issue-62097.stderr b/src/test/ui/async-await/issues/issue-62097.stderr
index af8fc2cd2ab45..fff43ae9f47bc 100644
--- a/src/test/ui/async-await/issues/issue-62097.stderr
+++ b/src/test/ui/async-await/issues/issue-62097.stderr
@@ -4,7 +4,7 @@ error: cannot infer an appropriate lifetime
LL | pub async fn run_dummy_fn(&self) {
| ^^^^^
| |
- | data with this lifetime...
+ | this data with the anonymous lifetime `'_`...
| ...is captured here...
LL | foo(|| self.bar()).await;
| --- ...and required to be `'static` by this
diff --git a/src/test/ui/impl-trait/must_outlive_least_region_or_bound.stderr b/src/test/ui/impl-trait/must_outlive_least_region_or_bound.stderr
index 96d4a121c16af..00b6ec38323c3 100644
--- a/src/test/ui/impl-trait/must_outlive_least_region_or_bound.stderr
+++ b/src/test/ui/impl-trait/must_outlive_least_region_or_bound.stderr
@@ -5,9 +5,9 @@ LL | fn elided(x: &i32) -> impl Copy { x }
| ---- --------- ^ ...and is captured here
| | |
| | ...is required to be `'static` by this...
- | data with this lifetime...
+ | this data with the anonymous lifetime `'_`...
|
-help: to permit non-static references in an `impl Trait` value, you can add an explicit bound for the anonymous lifetime #1 defined on the function body at 3:1
+help: to permit non-static references in an `impl Trait` value, you can add an explicit bound for the anonymous lifetime `'_`
|
LL | fn elided(x: &i32) -> impl Copy + '_ { x }
| ^^^^
@@ -19,9 +19,9 @@ LL | fn explicit<'a>(x: &'a i32) -> impl Copy { x }
| ------- --------- ^ ...and is captured here
| | |
| | ...is required to be `'static` by this...
- | data with this lifetime...
+ | this data with lifetime `'a`...
|
-help: to permit non-static references in an `impl Trait` value, you can add an explicit bound for the lifetime `'a` as defined on the function body at 6:13
+help: to permit non-static references in an `impl Trait` value, you can add an explicit bound for lifetime `'a`
|
LL | fn explicit<'a>(x: &'a i32) -> impl Copy + 'a { x }
| ^^^^
@@ -33,9 +33,9 @@ LL | fn elided2(x: &i32) -> impl Copy + 'static { x }
| ---- ------------------- ^ ...and is captured here
| | |
| | ...is required to be `'static` by this...
- | data with this lifetime...
+ | this data with the anonymous lifetime `'_`...
|
-help: consider changing the `impl Trait`'s explicit `'static` bound
+help: consider changing the `impl Trait`'s explicit `'static` bound to the anonymous lifetime `'_`
|
LL | fn elided2(x: &i32) -> impl Copy + '_ { x }
| ^^
@@ -51,9 +51,9 @@ LL | fn explicit2<'a>(x: &'a i32) -> impl Copy + 'static { x }
| ------- ------------------- ^ ...and is captured here
| | |
| | ...is required to be `'static` by this...
- | data with this lifetime...
+ | this data with lifetime `'a`...
|
-help: consider changing the `impl Trait`'s explicit `'static` bound
+help: consider changing the `impl Trait`'s explicit `'static` bound to lifetime `'a`
|
LL | fn explicit2<'a>(x: &'a i32) -> impl Copy + 'a { x }
| ^^
@@ -77,9 +77,9 @@ LL | fn with_bound<'a>(x: &'a i32) -> impl LifetimeTrait<'a> + 'static { x }
| ------- -------------------------------- ^ ...and is captured here
| | |
| | ...is required to be `'static` by this...
- | data with this lifetime...
+ | this data with lifetime `'a`...
|
-help: consider changing the `impl Trait`'s explicit `'static` bound
+help: consider changing the `impl Trait`'s explicit `'static` bound to lifetime `'a`
|
LL | fn with_bound<'a>(x: &'a i32) -> impl LifetimeTrait<'a> + 'a { x }
| ^^
@@ -113,9 +113,9 @@ LL | fn elided3(x: &i32) -> Box { Box::new(x) }
| | | |
| | | ...and is captured here
| | ...is required to be `'static` by this...
- | data with this lifetime...
+ | this data with the anonymous lifetime `'_`...
|
-help: to permit non-static references in a trait object value, you can add an explicit bound for the anonymous lifetime #1 defined on the function body at 18:1
+help: to permit non-static references in a trait object value, you can add an explicit bound for the anonymous lifetime `'_`
|
LL | fn elided3(x: &i32) -> Box { Box::new(x) }
| ^^^^
@@ -128,9 +128,9 @@ LL | fn explicit3<'a>(x: &'a i32) -> Box { Box::new(x) }
| | | |
| | | ...and is captured here
| | ...is required to be `'static` by this...
- | data with this lifetime...
+ | this data with lifetime `'a`...
|
-help: to permit non-static references in a trait object value, you can add an explicit bound for the lifetime `'a` as defined on the function body at 21:14
+help: to permit non-static references in a trait object value, you can add an explicit bound for lifetime `'a`
|
LL | fn explicit3<'a>(x: &'a i32) -> Box { Box::new(x) }
| ^^^^
@@ -142,9 +142,10 @@ LL | fn elided4(x: &i32) -> Box { Box::new(x) }
| ---- ---------^-
| | | |
| | | ...and is captured here
- | data with this lifetime... ...is required to be `'static` by this...
+ | | ...is required to be `'static` by this...
+ | this data with the anonymous lifetime `'_`...
|
-help: consider changing the trait object's explicit `'static` bound
+help: consider changing the trait object's explicit `'static` bound to the anonymous lifetime `'_`
|
LL | fn elided4(x: &i32) -> Box { Box::new(x) }
| ^^
@@ -160,9 +161,10 @@ LL | fn explicit4<'a>(x: &'a i32) -> Box { Box::new(x) }
| ------- ---------^-
| | | |
| | | ...and is captured here
- | data with this lifetime... ...is required to be `'static` by this...
+ | | ...is required to be `'static` by this...
+ | this data with lifetime `'a`...
|
-help: consider changing the trait object's explicit `'static` bound
+help: consider changing the trait object's explicit `'static` bound to lifetime `'a`
|
LL | fn explicit4<'a>(x: &'a i32) -> Box { Box::new(x) }
| ^^
diff --git a/src/test/ui/impl-trait/static-return-lifetime-infered.stderr b/src/test/ui/impl-trait/static-return-lifetime-infered.stderr
index 1c3a5979ee55b..67d4f60dff6f1 100644
--- a/src/test/ui/impl-trait/static-return-lifetime-infered.stderr
+++ b/src/test/ui/impl-trait/static-return-lifetime-infered.stderr
@@ -4,13 +4,13 @@ error: cannot infer an appropriate lifetime
LL | fn iter_values_anon(&self) -> impl Iterator- {
| ----- ----------------------- ...is required to be `'static` by this...
| |
- | data with this lifetime...
+ | this data with the anonymous lifetime `'_`...
LL | self.x.iter().map(|a| a.0)
| ------ ^^^^
| |
| ...and is captured here
|
-help: to permit non-static references in an `impl Trait` value, you can add an explicit bound for the anonymous lifetime #1 defined on the method body at 6:5
+help: to permit non-static references in an `impl Trait` value, you can add an explicit bound for the anonymous lifetime `'_`
|
LL | fn iter_values_anon(&self) -> impl Iterator
- + '_ {
| ^^^^
@@ -21,13 +21,13 @@ error: cannot infer an appropriate lifetime
LL | fn iter_values<'a>(&'a self) -> impl Iterator
- {
| -------- ----------------------- ...is required to be `'static` by this...
| |
- | data with this lifetime...
+ | this data with lifetime `'a`...
LL | self.x.iter().map(|a| a.0)
| ------ ^^^^
| |
| ...and is captured here
|
-help: to permit non-static references in an `impl Trait` value, you can add an explicit bound for the lifetime `'a` as defined on the method body at 10:20
+help: to permit non-static references in an `impl Trait` value, you can add an explicit bound for lifetime `'a`
|
LL | fn iter_values<'a>(&'a self) -> impl Iterator
- + 'a {
| ^^^^
diff --git a/src/test/ui/issues/issue-16922.stderr b/src/test/ui/issues/issue-16922.stderr
index 038df47e1bd98..c533a72dfc014 100644
--- a/src/test/ui/issues/issue-16922.stderr
+++ b/src/test/ui/issues/issue-16922.stderr
@@ -2,14 +2,14 @@ error: cannot infer an appropriate lifetime
--> $DIR/issue-16922.rs:4:14
|
LL | fn foo(value: &T) -> Box {
- | -- data with this lifetime...
+ | -- this data with the anonymous lifetime `'_`...
LL | Box::new(value) as Box
| ---------^^^^^-
| | |
| | ...and is captured here
| ...is required to be `'static` by this...
|
-help: to permit non-static references in a trait object value, you can add an explicit bound for the anonymous lifetime #1 defined on the function body at 3:1
+help: to permit non-static references in a trait object value, you can add an explicit bound for the anonymous lifetime `'_`
|
LL | fn foo(value: &T) -> Box {
| ^^^^
diff --git a/src/test/ui/object-lifetime/object-lifetime-default-from-box-error.stderr b/src/test/ui/object-lifetime/object-lifetime-default-from-box-error.stderr
index 555622c9d13c1..6edef8086b937 100644
--- a/src/test/ui/object-lifetime/object-lifetime-default-from-box-error.stderr
+++ b/src/test/ui/object-lifetime/object-lifetime-default-from-box-error.stderr
@@ -2,12 +2,12 @@ error: cannot infer an appropriate lifetime
--> $DIR/object-lifetime-default-from-box-error.rs:18:5
|
LL | fn load(ss: &mut SomeStruct) -> Box {
- | --------------- data with this lifetime...
+ | --------------- this data with the anonymous lifetime `'_`...
...
LL | ss.r
| ^^^^ ...is captured and required to be `'static` here
|
-help: to permit non-static references in a trait object value, you can add an explicit bound for the anonymous lifetime #2 defined on the function body at 14:1
+help: to permit non-static references in a trait object value, you can add an explicit bound for the anonymous lifetime `'_`
|
LL | fn load(ss: &mut SomeStruct) -> Box {
| ^^^^
diff --git a/src/test/ui/regions/region-object-lifetime-in-coercion.stderr b/src/test/ui/regions/region-object-lifetime-in-coercion.stderr
index 673300cebc26c..4b08c4bff2ebc 100644
--- a/src/test/ui/regions/region-object-lifetime-in-coercion.stderr
+++ b/src/test/ui/regions/region-object-lifetime-in-coercion.stderr
@@ -2,14 +2,14 @@ error: cannot infer an appropriate lifetime
--> $DIR/region-object-lifetime-in-coercion.rs:8:46
|
LL | fn a(v: &[u8]) -> Box {
- | ----- data with this lifetime...
+ | ----- this data with the anonymous lifetime `'_`...
LL | let x: Box = Box::new(v);
| ---------^-
| | |
| | ...and is captured here
| ...is required to be `'static` by this...
|
-help: consider changing the trait object's explicit `'static` bound
+help: consider changing the trait object's explicit `'static` bound to the anonymous lifetime `'_`
|
LL | fn a(v: &[u8]) -> Box {
| ^^
@@ -22,14 +22,14 @@ error: cannot infer an appropriate lifetime
--> $DIR/region-object-lifetime-in-coercion.rs:13:14
|
LL | fn b(v: &[u8]) -> Box {
- | ----- data with this lifetime...
+ | ----- this data with the anonymous lifetime `'_`...
LL | Box::new(v)
| ---------^-
| | |
| | ...and is captured here
| ...is required to be `'static` by this...
|
-help: consider changing the trait object's explicit `'static` bound
+help: consider changing the trait object's explicit `'static` bound to the anonymous lifetime `'_`
|
LL | fn b(v: &[u8]) -> Box {
| ^^
@@ -42,7 +42,7 @@ error: cannot infer an appropriate lifetime
--> $DIR/region-object-lifetime-in-coercion.rs:19:14
|
LL | fn c(v: &[u8]) -> Box {
- | ----- data with this lifetime...
+ | ----- this data with the anonymous lifetime `'_`...
...
LL | Box::new(v)
| ---------^-
@@ -50,7 +50,7 @@ LL | Box::new(v)
| | ...and is captured here
| ...is required to be `'static` by this...
|
-help: to permit non-static references in a trait object value, you can add an explicit bound for the anonymous lifetime #1 defined on the function body at 16:1
+help: to permit non-static references in a trait object value, you can add an explicit bound for the anonymous lifetime `'_`
|
LL | fn c(v: &[u8]) -> Box {
| ^^^^
diff --git a/src/test/ui/regions/regions-close-object-into-object-2.stderr b/src/test/ui/regions/regions-close-object-into-object-2.stderr
index 982ed07232a80..894be310fd14b 100644
--- a/src/test/ui/regions/regions-close-object-into-object-2.stderr
+++ b/src/test/ui/regions/regions-close-object-into-object-2.stderr
@@ -2,14 +2,14 @@ error: cannot infer an appropriate lifetime
--> $DIR/regions-close-object-into-object-2.rs:10:11
|
LL | fn g<'a, T: 'static>(v: Box + 'a>) -> Box {
- | ------------------ data with this lifetime...
+ | ------------------ this data with lifetime `'a`...
LL | box B(&*v) as Box
| ------^^^---------------
| | |
| | ...and is captured here
| ...is required to be `'static` by this...
|
-help: consider changing the trait object's explicit `'static` bound
+help: consider changing the trait object's explicit `'static` bound to lifetime `'a`
|
LL | fn g<'a, T: 'static>(v: Box + 'a>) -> Box {
| ^^
diff --git a/src/test/ui/regions/regions-close-object-into-object-4.stderr b/src/test/ui/regions/regions-close-object-into-object-4.stderr
index 1b82098ee13c2..ce261d78c2909 100644
--- a/src/test/ui/regions/regions-close-object-into-object-4.stderr
+++ b/src/test/ui/regions/regions-close-object-into-object-4.stderr
@@ -2,14 +2,14 @@ error: cannot infer an appropriate lifetime
--> $DIR/regions-close-object-into-object-4.rs:10:11
|
LL | fn i<'a, T, U>(v: Box+'a>) -> Box {
- | ---------------- data with this lifetime...
+ | ---------------- this data with lifetime `'a`...
LL | box B(&*v) as Box
| ------^^^---------------
| | |
| | ...and is captured here
| ...is required to be `'static` by this...
|
-help: consider changing the trait object's explicit `'static` bound
+help: consider changing the trait object's explicit `'static` bound to lifetime `'a`
|
LL | fn i<'a, T, U>(v: Box+'a>) -> Box {
| ^^
diff --git a/src/test/ui/regions/regions-proc-bound-capture.stderr b/src/test/ui/regions/regions-proc-bound-capture.stderr
index e7bbfaababe8a..a0df1815247c3 100644
--- a/src/test/ui/regions/regions-proc-bound-capture.stderr
+++ b/src/test/ui/regions/regions-proc-bound-capture.stderr
@@ -2,7 +2,7 @@ error: cannot infer an appropriate lifetime
--> $DIR/regions-proc-bound-capture.rs:9:14
|
LL | fn static_proc(x: &isize) -> Box (isize) + 'static> {
- | ------ data with this lifetime...
+ | ------ this data with the anonymous lifetime `'_`...
LL | // This is illegal, because the region bound on `proc` is 'static.
LL | Box::new(move || { *x })
| ---------^^^^^^^^^^^^^^-
@@ -10,7 +10,7 @@ LL | Box::new(move || { *x })
| | ...and is captured here
| ...is required to be `'static` by this...
|
-help: consider changing the trait object's explicit `'static` bound
+help: consider changing the trait object's explicit `'static` bound to the anonymous lifetime `'_`
|
LL | fn static_proc(x: &isize) -> Box (isize) + '_> {
| ^^
diff --git a/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.stderr b/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.stderr
index 1aeabce5e8aaf..5520341b5b1c3 100644
--- a/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.stderr
+++ b/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.stderr
@@ -4,7 +4,7 @@ error: cannot infer an appropriate lifetime
LL | async fn f(self: Pin<&Self>) -> impl Clone { self }
| ^^^^ ---------- ---------- ...and required to be `'static` by this
| | |
- | | data with this lifetime...
+ | | this data with the anonymous lifetime `'_`...
| ...is captured here...
error: aborting due to previous error
diff --git a/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait.stderr b/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait.stderr
index 04c475be787b8..5374929f3a45f 100644
--- a/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait.stderr
+++ b/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait.stderr
@@ -5,9 +5,9 @@ LL | fn f(self: Pin<&Self>) -> impl Clone { self }
| ---------- ---------- ^^^^ ...and is captured here
| | |
| | ...is required to be `'static` by this...
- | data with this lifetime...
+ | this data with the anonymous lifetime `'_`...
|
-help: to permit non-static references in an `impl Trait` value, you can add an explicit bound for the anonymous lifetime #1 defined on the method body at 6:5
+help: to permit non-static references in an `impl Trait` value, you can add an explicit bound for the anonymous lifetime `'_`
|
LL | fn f(self: Pin<&Self>) -> impl Clone + '_ { self }
| ^^^^
diff --git a/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.stderr b/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.stderr
index 5cf170d566ca9..471f3cd14aa3e 100644
--- a/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.stderr
+++ b/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.stderr
@@ -12,14 +12,14 @@ error: cannot infer an appropriate lifetime
LL | fn foo(g: G, dest: &mut T) -> impl FnOnce()
| ------ ------------- ...is required to be `'static` by this...
| |
- | data with this lifetime...
+ | this data with the anonymous lifetime `'_`...
...
LL | / move || {
LL | | *dest = g.get();
LL | | }
| |_____^ ...and is captured here
|
-help: to permit non-static references in an `impl Trait` value, you can add an explicit bound for the anonymous lifetime #1 defined on the function body at 15:1
+help: to permit non-static references in an `impl Trait` value, you can add an explicit bound for the anonymous lifetime `'_`
|
LL | fn foo(g: G, dest: &mut T) -> impl FnOnce() + '_
| ^^^^
diff --git a/src/test/ui/underscore-lifetime/dyn-trait-underscore.stderr b/src/test/ui/underscore-lifetime/dyn-trait-underscore.stderr
index 4dc4aac6ceac4..5fd03f9770e5d 100644
--- a/src/test/ui/underscore-lifetime/dyn-trait-underscore.stderr
+++ b/src/test/ui/underscore-lifetime/dyn-trait-underscore.stderr
@@ -2,12 +2,12 @@ error: cannot infer an appropriate lifetime
--> $DIR/dyn-trait-underscore.rs:8:20
|
LL | fn a(items: &[T]) -> Box> {
- | ---- data with this lifetime...
+ | ---- this data with the anonymous lifetime `'_`...
LL | // ^^^^^^^^^^^^^^^^^^^^^ bound *here* defaults to `'static`
LL | Box::new(items.iter())
| ---------------^^^^--- ...is captured and required to be `'static` here
|
-help: to permit non-static references in a trait object value, you can add an explicit bound for the anonymous lifetime #1 defined on the function body at 6:1
+help: to permit non-static references in a trait object value, you can add an explicit bound for the anonymous lifetime `'_`
|
LL | fn a(items: &[T]) -> Box + '_> {
| ^^^^
From e75588934c01d6bc9abb02979eb61168a7b5c598 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Esteban=20K=C3=BCber?=
Date: Fri, 29 May 2020 19:46:22 -0700
Subject: [PATCH 15/32] Move overlapping span to a note
---
.../nice_region_error/static_impl_trait.rs | 31 ++++++++++++-
.../must_outlive_least_region_or_bound.stderr | 44 ++++++++++++-------
src/test/ui/issues/issue-16922.stderr | 10 +++--
.../region-object-lifetime-in-coercion.stderr | 30 ++++++++-----
.../regions-close-object-into-object-2.stderr | 10 +++--
.../regions-close-object-into-object-4.stderr | 10 +++--
.../regions/regions-proc-bound-capture.stderr | 10 +++--
7 files changed, 99 insertions(+), 46 deletions(-)
diff --git a/src/librustc_infer/infer/error_reporting/nice_region_error/static_impl_trait.rs b/src/librustc_infer/infer/error_reporting/nice_region_error/static_impl_trait.rs
index e9f165d309f8f..cc95441b68a03 100644
--- a/src/librustc_infer/infer/error_reporting/nice_region_error/static_impl_trait.rs
+++ b/src/librustc_infer/infer/error_reporting/nice_region_error/static_impl_trait.rs
@@ -53,7 +53,36 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
// Customize the spans and labels depending on their relative order so
// that split sentences flow correctly.
- if sup_origin.span().shrink_to_hi() <= return_sp.shrink_to_lo() {
+ if sup_origin.span().overlaps(return_sp) && sp == sup_origin.span() {
+ // Avoid the following:
+ //
+ // error: cannot infer an appropriate lifetime
+ // --> $DIR/must_outlive_least_region_or_bound.rs:18:50
+ // |
+ // LL | fn foo(x: &i32) -> Box { Box::new(x) }
+ // | ---- ---------^-
+ // | | | |
+ // | | | ...and is captured here
+ // | | ...is required to be `'static` by this...
+ // | this data with the anonymous lifetime `'_`...
+ //
+ // and instead show:
+ //
+ // error: cannot infer an appropriate lifetime
+ // --> $DIR/must_outlive_least_region_or_bound.rs:18:50
+ // |
+ // LL | fn foo(x: &i32) -> Box { Box::new(x) }
+ // | ---- ^ ...is captured here with a `'static` requirement
+ // | |
+ // | this data with the anonymous lifetime `'_`...
+ // |
+ // note: ...is required to be `'static` by this
+ // |
+ // LL | fn elided3(x: &i32) -> Box { Box::new(x) }
+ // | ^^^^^^^^^^^
+ err.span_label(sup_origin.span(), "...is captured here...");
+ err.span_note(return_sp, "...and required to be `'static` by this");
+ } else if sup_origin.span() <= return_sp {
err.span_label(sup_origin.span(), "...is captured here...");
err.span_label(return_sp, "...and required to be `'static` by this");
} else {
diff --git a/src/test/ui/impl-trait/must_outlive_least_region_or_bound.stderr b/src/test/ui/impl-trait/must_outlive_least_region_or_bound.stderr
index 00b6ec38323c3..2da49379ea8c2 100644
--- a/src/test/ui/impl-trait/must_outlive_least_region_or_bound.stderr
+++ b/src/test/ui/impl-trait/must_outlive_least_region_or_bound.stderr
@@ -109,12 +109,15 @@ error: cannot infer an appropriate lifetime
--> $DIR/must_outlive_least_region_or_bound.rs:18:50
|
LL | fn elided3(x: &i32) -> Box { Box::new(x) }
- | ---- ---------^-
- | | | |
- | | | ...and is captured here
- | | ...is required to be `'static` by this...
+ | ---- ^ ...is captured here...
+ | |
| this data with the anonymous lifetime `'_`...
|
+note: ...and required to be `'static` by this
+ --> $DIR/must_outlive_least_region_or_bound.rs:18:41
+ |
+LL | fn elided3(x: &i32) -> Box { Box::new(x) }
+ | ^^^^^^^^^^^
help: to permit non-static references in a trait object value, you can add an explicit bound for the anonymous lifetime `'_`
|
LL | fn elided3(x: &i32) -> Box { Box::new(x) }
@@ -124,12 +127,15 @@ error: cannot infer an appropriate lifetime
--> $DIR/must_outlive_least_region_or_bound.rs:21:59
|
LL | fn explicit3<'a>(x: &'a i32) -> Box { Box::new(x) }
- | ------- ---------^-
- | | | |
- | | | ...and is captured here
- | | ...is required to be `'static` by this...
+ | ------- ^ ...is captured here...
+ | |
| this data with lifetime `'a`...
|
+note: ...and required to be `'static` by this
+ --> $DIR/must_outlive_least_region_or_bound.rs:21:50
+ |
+LL | fn explicit3<'a>(x: &'a i32) -> Box { Box::new(x) }
+ | ^^^^^^^^^^^
help: to permit non-static references in a trait object value, you can add an explicit bound for lifetime `'a`
|
LL | fn explicit3<'a>(x: &'a i32) -> Box { Box::new(x) }
@@ -139,12 +145,15 @@ error: cannot infer an appropriate lifetime
--> $DIR/must_outlive_least_region_or_bound.rs:24:60
|
LL | fn elided4(x: &i32) -> Box { Box::new(x) }
- | ---- ---------^-
- | | | |
- | | | ...and is captured here
- | | ...is required to be `'static` by this...
+ | ---- ^ ...is captured here...
+ | |
| this data with the anonymous lifetime `'_`...
|
+note: ...and required to be `'static` by this
+ --> $DIR/must_outlive_least_region_or_bound.rs:24:51
+ |
+LL | fn elided4(x: &i32) -> Box { Box::new(x) }
+ | ^^^^^^^^^^^
help: consider changing the trait object's explicit `'static` bound to the anonymous lifetime `'_`
|
LL | fn elided4(x: &i32) -> Box { Box::new(x) }
@@ -158,12 +167,13 @@ error: cannot infer an appropriate lifetime
--> $DIR/must_outlive_least_region_or_bound.rs:27:69
|
LL | fn explicit4<'a>(x: &'a i32) -> Box { Box::new(x) }
- | ------- ---------^-
- | | | |
- | | | ...and is captured here
- | | ...is required to be `'static` by this...
- | this data with lifetime `'a`...
+ | ------- this data with lifetime `'a`... ^ ...is captured here...
|
+note: ...and required to be `'static` by this
+ --> $DIR/must_outlive_least_region_or_bound.rs:27:60
+ |
+LL | fn explicit4<'a>(x: &'a i32) -> Box { Box::new(x) }
+ | ^^^^^^^^^^^
help: consider changing the trait object's explicit `'static` bound to lifetime `'a`
|
LL | fn explicit4<'a>(x: &'a i32) -> Box { Box::new(x) }
diff --git a/src/test/ui/issues/issue-16922.stderr b/src/test/ui/issues/issue-16922.stderr
index c533a72dfc014..6c0b26a86b651 100644
--- a/src/test/ui/issues/issue-16922.stderr
+++ b/src/test/ui/issues/issue-16922.stderr
@@ -4,11 +4,13 @@ error: cannot infer an appropriate lifetime
LL | fn foo(value: &T) -> Box {
| -- this data with the anonymous lifetime `'_`...
LL | Box::new(value) as Box
- | ---------^^^^^-
- | | |
- | | ...and is captured here
- | ...is required to be `'static` by this...
+ | ^^^^^ ...is captured here...
|
+note: ...and required to be `'static` by this
+ --> $DIR/issue-16922.rs:4:5
+ |
+LL | Box::new(value) as Box
+ | ^^^^^^^^^^^^^^^
help: to permit non-static references in a trait object value, you can add an explicit bound for the anonymous lifetime `'_`
|
LL | fn foo(value: &T) -> Box {
diff --git a/src/test/ui/regions/region-object-lifetime-in-coercion.stderr b/src/test/ui/regions/region-object-lifetime-in-coercion.stderr
index 4b08c4bff2ebc..b333c314c57c9 100644
--- a/src/test/ui/regions/region-object-lifetime-in-coercion.stderr
+++ b/src/test/ui/regions/region-object-lifetime-in-coercion.stderr
@@ -4,11 +4,13 @@ error: cannot infer an appropriate lifetime
LL | fn a(v: &[u8]) -> Box {
| ----- this data with the anonymous lifetime `'_`...
LL | let x: Box = Box::new(v);
- | ---------^-
- | | |
- | | ...and is captured here
- | ...is required to be `'static` by this...
+ | ^ ...is captured here...
|
+note: ...and required to be `'static` by this
+ --> $DIR/region-object-lifetime-in-coercion.rs:8:37
+ |
+LL | let x: Box = Box::new(v);
+ | ^^^^^^^^^^^
help: consider changing the trait object's explicit `'static` bound to the anonymous lifetime `'_`
|
LL | fn a(v: &[u8]) -> Box {
@@ -24,11 +26,13 @@ error: cannot infer an appropriate lifetime
LL | fn b(v: &[u8]) -> Box {
| ----- this data with the anonymous lifetime `'_`...
LL | Box::new(v)
- | ---------^-
- | | |
- | | ...and is captured here
- | ...is required to be `'static` by this...
+ | ^ ...is captured here...
|
+note: ...and required to be `'static` by this
+ --> $DIR/region-object-lifetime-in-coercion.rs:13:5
+ |
+LL | Box::new(v)
+ | ^^^^^^^^^^^
help: consider changing the trait object's explicit `'static` bound to the anonymous lifetime `'_`
|
LL | fn b(v: &[u8]) -> Box {
@@ -45,11 +49,13 @@ LL | fn c(v: &[u8]) -> Box {
| ----- this data with the anonymous lifetime `'_`...
...
LL | Box::new(v)
- | ---------^-
- | | |
- | | ...and is captured here
- | ...is required to be `'static` by this...
+ | ^ ...is captured here...
+ |
+note: ...and required to be `'static` by this
+ --> $DIR/region-object-lifetime-in-coercion.rs:19:5
|
+LL | Box::new(v)
+ | ^^^^^^^^^^^
help: to permit non-static references in a trait object value, you can add an explicit bound for the anonymous lifetime `'_`
|
LL | fn c(v: &[u8]) -> Box {
diff --git a/src/test/ui/regions/regions-close-object-into-object-2.stderr b/src/test/ui/regions/regions-close-object-into-object-2.stderr
index 894be310fd14b..3127ae65ace7d 100644
--- a/src/test/ui/regions/regions-close-object-into-object-2.stderr
+++ b/src/test/ui/regions/regions-close-object-into-object-2.stderr
@@ -4,11 +4,13 @@ error: cannot infer an appropriate lifetime
LL | fn g<'a, T: 'static>(v: Box + 'a>) -> Box {
| ------------------ this data with lifetime `'a`...
LL | box B(&*v) as Box
- | ------^^^---------------
- | | |
- | | ...and is captured here
- | ...is required to be `'static` by this...
+ | ^^^ ...is captured here...
|
+note: ...and required to be `'static` by this
+ --> $DIR/regions-close-object-into-object-2.rs:10:5
+ |
+LL | box B(&*v) as Box
+ | ^^^^^^^^^^^^^^^^^^^^^^^^
help: consider changing the trait object's explicit `'static` bound to lifetime `'a`
|
LL | fn g<'a, T: 'static>(v: Box + 'a>) -> Box {
diff --git a/src/test/ui/regions/regions-close-object-into-object-4.stderr b/src/test/ui/regions/regions-close-object-into-object-4.stderr
index ce261d78c2909..b18c61f137694 100644
--- a/src/test/ui/regions/regions-close-object-into-object-4.stderr
+++ b/src/test/ui/regions/regions-close-object-into-object-4.stderr
@@ -4,11 +4,13 @@ error: cannot infer an appropriate lifetime
LL | fn i<'a, T, U>(v: Box+'a>) -> Box {
| ---------------- this data with lifetime `'a`...
LL | box B(&*v) as Box
- | ------^^^---------------
- | | |
- | | ...and is captured here
- | ...is required to be `'static` by this...
+ | ^^^ ...is captured here...
|
+note: ...and required to be `'static` by this
+ --> $DIR/regions-close-object-into-object-4.rs:10:5
+ |
+LL | box B(&*v) as Box
+ | ^^^^^^^^^^^^^^^^^^^^^^^^
help: consider changing the trait object's explicit `'static` bound to lifetime `'a`
|
LL | fn i<'a, T, U>(v: Box+'a>) -> Box {
diff --git a/src/test/ui/regions/regions-proc-bound-capture.stderr b/src/test/ui/regions/regions-proc-bound-capture.stderr
index a0df1815247c3..5cb9506afd351 100644
--- a/src/test/ui/regions/regions-proc-bound-capture.stderr
+++ b/src/test/ui/regions/regions-proc-bound-capture.stderr
@@ -5,11 +5,13 @@ LL | fn static_proc(x: &isize) -> Box (isize) + 'static> {
| ------ this data with the anonymous lifetime `'_`...
LL | // This is illegal, because the region bound on `proc` is 'static.
LL | Box::new(move || { *x })
- | ---------^^^^^^^^^^^^^^-
- | | |
- | | ...and is captured here
- | ...is required to be `'static` by this...
+ | ^^^^^^^^^^^^^^ ...is captured here...
|
+note: ...and required to be `'static` by this
+ --> $DIR/regions-proc-bound-capture.rs:9:5
+ |
+LL | Box::new(move || { *x })
+ | ^^^^^^^^^^^^^^^^^^^^^^^^
help: consider changing the trait object's explicit `'static` bound to the anonymous lifetime `'_`
|
LL | fn static_proc(x: &isize) -> Box (isize) + '_> {
From bc1579060981b5e95a18409e876c92bf0c9307e6 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Esteban=20K=C3=BCber?=
Date: Sat, 30 May 2020 09:54:05 -0700
Subject: [PATCH 16/32] Tweak output for overlapping required/captured spans
---
.../nice_region_error/static_impl_trait.rs | 10 +++----
.../must_outlive_least_region_or_bound.stderr | 28 +++----------------
src/test/ui/issues/issue-16922.stderr | 7 +----
.../region-object-lifetime-in-coercion.stderr | 21 ++------------
.../regions-close-object-into-object-2.stderr | 7 +----
.../regions-close-object-into-object-4.stderr | 7 +----
.../regions/regions-proc-bound-capture.stderr | 7 +----
7 files changed, 15 insertions(+), 72 deletions(-)
diff --git a/src/librustc_infer/infer/error_reporting/nice_region_error/static_impl_trait.rs b/src/librustc_infer/infer/error_reporting/nice_region_error/static_impl_trait.rs
index cc95441b68a03..253057536f133 100644
--- a/src/librustc_infer/infer/error_reporting/nice_region_error/static_impl_trait.rs
+++ b/src/librustc_infer/infer/error_reporting/nice_region_error/static_impl_trait.rs
@@ -76,12 +76,10 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
// | |
// | this data with the anonymous lifetime `'_`...
// |
- // note: ...is required to be `'static` by this
- // |
- // LL | fn elided3(x: &i32) -> Box { Box::new(x) }
- // | ^^^^^^^^^^^
- err.span_label(sup_origin.span(), "...is captured here...");
- err.span_note(return_sp, "...and required to be `'static` by this");
+ err.span_label(
+ sup_origin.span(),
+ "...is captured here with a `'static` requirement",
+ );
} else if sup_origin.span() <= return_sp {
err.span_label(sup_origin.span(), "...is captured here...");
err.span_label(return_sp, "...and required to be `'static` by this");
diff --git a/src/test/ui/impl-trait/must_outlive_least_region_or_bound.stderr b/src/test/ui/impl-trait/must_outlive_least_region_or_bound.stderr
index 2da49379ea8c2..82e44cff9cc44 100644
--- a/src/test/ui/impl-trait/must_outlive_least_region_or_bound.stderr
+++ b/src/test/ui/impl-trait/must_outlive_least_region_or_bound.stderr
@@ -109,15 +109,10 @@ error: cannot infer an appropriate lifetime
--> $DIR/must_outlive_least_region_or_bound.rs:18:50
|
LL | fn elided3(x: &i32) -> Box { Box::new(x) }
- | ---- ^ ...is captured here...
+ | ---- ^ ...is captured here with a `'static` requirement
| |
| this data with the anonymous lifetime `'_`...
|
-note: ...and required to be `'static` by this
- --> $DIR/must_outlive_least_region_or_bound.rs:18:41
- |
-LL | fn elided3(x: &i32) -> Box { Box::new(x) }
- | ^^^^^^^^^^^
help: to permit non-static references in a trait object value, you can add an explicit bound for the anonymous lifetime `'_`
|
LL | fn elided3(x: &i32) -> Box { Box::new(x) }
@@ -127,15 +122,10 @@ error: cannot infer an appropriate lifetime
--> $DIR/must_outlive_least_region_or_bound.rs:21:59
|
LL | fn explicit3<'a>(x: &'a i32) -> Box { Box::new(x) }
- | ------- ^ ...is captured here...
+ | ------- ^ ...is captured here with a `'static` requirement
| |
| this data with lifetime `'a`...
|
-note: ...and required to be `'static` by this
- --> $DIR/must_outlive_least_region_or_bound.rs:21:50
- |
-LL | fn explicit3<'a>(x: &'a i32) -> Box { Box::new(x) }
- | ^^^^^^^^^^^
help: to permit non-static references in a trait object value, you can add an explicit bound for lifetime `'a`
|
LL | fn explicit3<'a>(x: &'a i32) -> Box { Box::new(x) }
@@ -145,15 +135,10 @@ error: cannot infer an appropriate lifetime
--> $DIR/must_outlive_least_region_or_bound.rs:24:60
|
LL | fn elided4(x: &i32) -> Box { Box::new(x) }
- | ---- ^ ...is captured here...
+ | ---- ^ ...is captured here with a `'static` requirement
| |
| this data with the anonymous lifetime `'_`...
|
-note: ...and required to be `'static` by this
- --> $DIR/must_outlive_least_region_or_bound.rs:24:51
- |
-LL | fn elided4(x: &i32) -> Box { Box::new(x) }
- | ^^^^^^^^^^^
help: consider changing the trait object's explicit `'static` bound to the anonymous lifetime `'_`
|
LL | fn elided4(x: &i32) -> Box { Box::new(x) }
@@ -167,13 +152,8 @@ error: cannot infer an appropriate lifetime
--> $DIR/must_outlive_least_region_or_bound.rs:27:69
|
LL | fn explicit4<'a>(x: &'a i32) -> Box { Box::new(x) }
- | ------- this data with lifetime `'a`... ^ ...is captured here...
+ | ------- this data with lifetime `'a`... ^ ...is captured here with a `'static` requirement
|
-note: ...and required to be `'static` by this
- --> $DIR/must_outlive_least_region_or_bound.rs:27:60
- |
-LL | fn explicit4<'a>(x: &'a i32) -> Box { Box::new(x) }
- | ^^^^^^^^^^^
help: consider changing the trait object's explicit `'static` bound to lifetime `'a`
|
LL | fn explicit4<'a>(x: &'a i32) -> Box { Box::new(x) }
diff --git a/src/test/ui/issues/issue-16922.stderr b/src/test/ui/issues/issue-16922.stderr
index 6c0b26a86b651..a254343cd1bb7 100644
--- a/src/test/ui/issues/issue-16922.stderr
+++ b/src/test/ui/issues/issue-16922.stderr
@@ -4,13 +4,8 @@ error: cannot infer an appropriate lifetime
LL | fn foo(value: &T) -> Box {
| -- this data with the anonymous lifetime `'_`...
LL | Box::new(value) as Box
- | ^^^^^ ...is captured here...
+ | ^^^^^ ...is captured here with a `'static` requirement
|
-note: ...and required to be `'static` by this
- --> $DIR/issue-16922.rs:4:5
- |
-LL | Box::new(value) as Box
- | ^^^^^^^^^^^^^^^
help: to permit non-static references in a trait object value, you can add an explicit bound for the anonymous lifetime `'_`
|
LL | fn foo(value: &T) -> Box {
diff --git a/src/test/ui/regions/region-object-lifetime-in-coercion.stderr b/src/test/ui/regions/region-object-lifetime-in-coercion.stderr
index b333c314c57c9..97d1f3579fcd8 100644
--- a/src/test/ui/regions/region-object-lifetime-in-coercion.stderr
+++ b/src/test/ui/regions/region-object-lifetime-in-coercion.stderr
@@ -4,13 +4,8 @@ error: cannot infer an appropriate lifetime
LL | fn a(v: &[u8]) -> Box {
| ----- this data with the anonymous lifetime `'_`...
LL | let x: Box = Box::new(v);
- | ^ ...is captured here...
+ | ^ ...is captured here with a `'static` requirement
|
-note: ...and required to be `'static` by this
- --> $DIR/region-object-lifetime-in-coercion.rs:8:37
- |
-LL | let x: Box = Box::new(v);
- | ^^^^^^^^^^^
help: consider changing the trait object's explicit `'static` bound to the anonymous lifetime `'_`
|
LL | fn a(v: &[u8]) -> Box {
@@ -26,13 +21,8 @@ error: cannot infer an appropriate lifetime
LL | fn b(v: &[u8]) -> Box {
| ----- this data with the anonymous lifetime `'_`...
LL | Box::new(v)
- | ^ ...is captured here...
+ | ^ ...is captured here with a `'static` requirement
|
-note: ...and required to be `'static` by this
- --> $DIR/region-object-lifetime-in-coercion.rs:13:5
- |
-LL | Box::new(v)
- | ^^^^^^^^^^^
help: consider changing the trait object's explicit `'static` bound to the anonymous lifetime `'_`
|
LL | fn b(v: &[u8]) -> Box {
@@ -49,13 +39,8 @@ LL | fn c(v: &[u8]) -> Box {
| ----- this data with the anonymous lifetime `'_`...
...
LL | Box::new(v)
- | ^ ...is captured here...
- |
-note: ...and required to be `'static` by this
- --> $DIR/region-object-lifetime-in-coercion.rs:19:5
+ | ^ ...is captured here with a `'static` requirement
|
-LL | Box::new(v)
- | ^^^^^^^^^^^
help: to permit non-static references in a trait object value, you can add an explicit bound for the anonymous lifetime `'_`
|
LL | fn c(v: &[u8]) -> Box {
diff --git a/src/test/ui/regions/regions-close-object-into-object-2.stderr b/src/test/ui/regions/regions-close-object-into-object-2.stderr
index 3127ae65ace7d..3d707f2d99941 100644
--- a/src/test/ui/regions/regions-close-object-into-object-2.stderr
+++ b/src/test/ui/regions/regions-close-object-into-object-2.stderr
@@ -4,13 +4,8 @@ error: cannot infer an appropriate lifetime
LL | fn g<'a, T: 'static>(v: Box + 'a>) -> Box {
| ------------------ this data with lifetime `'a`...
LL | box B(&*v) as Box
- | ^^^ ...is captured here...
+ | ^^^ ...is captured here with a `'static` requirement
|
-note: ...and required to be `'static` by this
- --> $DIR/regions-close-object-into-object-2.rs:10:5
- |
-LL | box B(&*v) as Box
- | ^^^^^^^^^^^^^^^^^^^^^^^^
help: consider changing the trait object's explicit `'static` bound to lifetime `'a`
|
LL | fn g<'a, T: 'static>(v: Box + 'a>) -> Box {
diff --git a/src/test/ui/regions/regions-close-object-into-object-4.stderr b/src/test/ui/regions/regions-close-object-into-object-4.stderr
index b18c61f137694..70282c8cbdb30 100644
--- a/src/test/ui/regions/regions-close-object-into-object-4.stderr
+++ b/src/test/ui/regions/regions-close-object-into-object-4.stderr
@@ -4,13 +4,8 @@ error: cannot infer an appropriate lifetime
LL | fn i<'a, T, U>(v: Box+'a>) -> Box {
| ---------------- this data with lifetime `'a`...
LL | box B(&*v) as Box
- | ^^^ ...is captured here...
+ | ^^^ ...is captured here with a `'static` requirement
|
-note: ...and required to be `'static` by this
- --> $DIR/regions-close-object-into-object-4.rs:10:5
- |
-LL | box B(&*v) as Box
- | ^^^^^^^^^^^^^^^^^^^^^^^^
help: consider changing the trait object's explicit `'static` bound to lifetime `'a`
|
LL | fn i<'a, T, U>(v: Box+'a>) -> Box {
diff --git a/src/test/ui/regions/regions-proc-bound-capture.stderr b/src/test/ui/regions/regions-proc-bound-capture.stderr
index 5cb9506afd351..8f93fad7fe9d8 100644
--- a/src/test/ui/regions/regions-proc-bound-capture.stderr
+++ b/src/test/ui/regions/regions-proc-bound-capture.stderr
@@ -5,13 +5,8 @@ LL | fn static_proc(x: &isize) -> Box (isize) + 'static> {
| ------ this data with the anonymous lifetime `'_`...
LL | // This is illegal, because the region bound on `proc` is 'static.
LL | Box::new(move || { *x })
- | ^^^^^^^^^^^^^^ ...is captured here...
+ | ^^^^^^^^^^^^^^ ...is captured here with a `'static` requirement
|
-note: ...and required to be `'static` by this
- --> $DIR/regions-proc-bound-capture.rs:9:5
- |
-LL | Box::new(move || { *x })
- | ^^^^^^^^^^^^^^^^^^^^^^^^
help: consider changing the trait object's explicit `'static` bound to the anonymous lifetime `'_`
|
LL | fn static_proc(x: &isize) -> Box (isize) + '_> {
From 539e9783dfb713b3af0a9967af8fd0639d700555 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Esteban=20K=C3=BCber?=