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/52] 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/52] 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/52] 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/52] 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/52] 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 591584e71f7d8a613d586066c8b01c1eecf08f35 Mon Sep 17 00:00:00 2001
From: Mikail Bagishov
Date: Tue, 26 May 2020 23:48:36 +0300
Subject: [PATCH 06/52] Add tests for 'impl Default for [T; N]'
---
src/libcore/tests/array.rs | 41 ++++++++++++++++++++++++++++++++++++++
1 file changed, 41 insertions(+)
diff --git a/src/libcore/tests/array.rs b/src/libcore/tests/array.rs
index c2a816f0a7d90..41855a9a8cbab 100644
--- a/src/libcore/tests/array.rs
+++ b/src/libcore/tests/array.rs
@@ -241,3 +241,44 @@ fn iterator_drops() {
}
assert_eq!(i.get(), 5);
}
+
+#[test]
+fn array_default_impl_avoids_leaks_on_panic() {
+ use core::sync::atomic::{AtomicUsize, Ordering::Relaxed};
+ static COUNTER: AtomicUsize = AtomicUsize::new(0);
+ #[derive(Debug)]
+ struct Bomb(usize);
+
+ impl Default for Bomb {
+ fn default() -> Bomb {
+ if COUNTER.load(Relaxed) == 3 {
+ panic!("bomb limit exceeded");
+ }
+
+ COUNTER.fetch_add(1, Relaxed);
+ Bomb(COUNTER.load(Relaxed))
+ }
+ }
+
+ impl Drop for Bomb {
+ fn drop(&mut self) {
+ COUNTER.fetch_sub(1, Relaxed);
+ }
+ }
+
+ let res = std::panic::catch_unwind(|| <[Bomb; 5]>::default());
+ let panic_msg = match res {
+ Ok(_) => unreachable!(),
+ Err(p) => p.downcast::<&'static str>().unwrap(),
+ };
+ assert_eq!(*panic_msg, "bomb limit exceeded");
+ // check that all bombs are successfully dropped
+ assert_eq!(COUNTER.load(Relaxed), 0);
+}
+
+#[test]
+fn empty_array_is_always_default() {
+ struct DoesNotImplDefault;
+
+ let _arr = <[DoesNotImplDefault; 0]>::default();
+}
From 3313bf62ac45fab2c39e49c788423153754087a9 Mon Sep 17 00:00:00 2001
From: Mikail Bagishov
Date: Thu, 28 May 2020 20:45:21 +0300
Subject: [PATCH 07/52] Skip leak test on targets without panic=unwind
---
src/libcore/tests/array.rs | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/src/libcore/tests/array.rs b/src/libcore/tests/array.rs
index 41855a9a8cbab..4bc44e98fc802 100644
--- a/src/libcore/tests/array.rs
+++ b/src/libcore/tests/array.rs
@@ -242,7 +242,14 @@ fn iterator_drops() {
assert_eq!(i.get(), 5);
}
+// This test does not work on targets without panic=unwind support.
+// To work around this problem, test is marked is should_panic, so it will
+// be automagically skipped on unsuitable targets, such as
+// wasm32-unknown-unkown.
+//
+// It means that we use panic for indicating success.
#[test]
+#[should_panic(expected = "test succeeded")]
fn array_default_impl_avoids_leaks_on_panic() {
use core::sync::atomic::{AtomicUsize, Ordering::Relaxed};
static COUNTER: AtomicUsize = AtomicUsize::new(0);
@@ -274,6 +281,7 @@ fn array_default_impl_avoids_leaks_on_panic() {
assert_eq!(*panic_msg, "bomb limit exceeded");
// check that all bombs are successfully dropped
assert_eq!(COUNTER.load(Relaxed), 0);
+ panic!("test succeeded")
}
#[test]
From 1bc4e45b3fe3a0817908bd7cc21ec23798d38d63 Mon Sep 17 00:00:00 2001
From: "Carol (Nichols || Goulding)"
Date: Mon, 1 Jun 2020 22:18:38 -0400
Subject: [PATCH 08/52] Only highlight results via mouseover if mouse has moved
---
src/librustdoc/html/static/main.js | 37 +++++++++++++++++++-----------
1 file changed, 24 insertions(+), 13 deletions(-)
diff --git a/src/librustdoc/html/static/main.js b/src/librustdoc/html/static/main.js
index ac5a2f96b26c6..fc31f6c760675 100644
--- a/src/librustdoc/html/static/main.js
+++ b/src/librustdoc/html/static/main.js
@@ -100,6 +100,8 @@ function defocusSearchBar() {
// 2 for "In Return Types"
var currentTab = 0;
+ var mouseMovedAfterSearch = true;
+
var titleBeforeSearch = document.title;
function clearInputTimeout() {
@@ -162,6 +164,7 @@ function defocusSearchBar() {
}
addClass(main, "hidden");
removeClass(search, "hidden");
+ mouseMovedAfterSearch = false;
}
function hideSearchResults(search) {
@@ -424,6 +427,12 @@ function defocusSearchBar() {
document.addEventListener("keypress", handleShortcut);
document.addEventListener("keydown", handleShortcut);
+ function resetMouseMoved(ev) {
+ mouseMovedAfterSearch = true;
+ }
+
+ document.addEventListener("mousemove", resetMouseMoved);
+
var handleSourceHighlight = (function() {
var prev_line_id = 0;
@@ -1353,20 +1362,22 @@ function defocusSearchBar() {
}
};
var mouseover_func = function(e) {
- var el = e.target;
- // to retrieve the real "owner" of the event.
- while (el.tagName !== "TR") {
- el = el.parentNode;
- }
- clearTimeout(hoverTimeout);
- hoverTimeout = setTimeout(function() {
- onEachLazy(document.getElementsByClassName("search-results"), function(e) {
- onEachLazy(e.getElementsByClassName("result"), function(i_e) {
- removeClass(i_e, "highlighted");
+ if (mouseMovedAfterSearch) {
+ var el = e.target;
+ // to retrieve the real "owner" of the event.
+ while (el.tagName !== "TR") {
+ el = el.parentNode;
+ }
+ clearTimeout(hoverTimeout);
+ hoverTimeout = setTimeout(function() {
+ onEachLazy(document.getElementsByClassName("search-results"), function(e) {
+ onEachLazy(e.getElementsByClassName("result"), function(i_e) {
+ removeClass(i_e, "highlighted");
+ });
});
- });
- addClass(el, "highlighted");
- }, 20);
+ addClass(el, "highlighted");
+ }, 20);
+ }
};
onEachLazy(document.getElementsByClassName("search-results"), function(e) {
onEachLazy(e.getElementsByClassName("result"), function(i_e) {
From f0d2e78d39d0efdb431af0b59c498d532d8146e2 Mon Sep 17 00:00:00 2001
From: Ralf Jung
Date: Fri, 12 Jun 2020 18:17:30 +0200
Subject: [PATCH 09/52] 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 10/52] 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 4606168dd508007fb1014b6ab12b27e320e07038 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Esteban=20K=C3=BCber?=
Date: Sat, 13 Jun 2020 11:12:29 -0700
Subject: [PATCH 11/52] Make new type param suggestion more targetted
Do not suggest new type param when encountering a missing type in an ADT
field with generic parameters.
Fix #72640.
---
src/librustc_resolve/build_reduced_graph.rs | 1 +
src/librustc_resolve/late/diagnostics.rs | 2 +-
src/librustc_resolve/lib.rs | 14 ++++++++------
.../ui/suggestions/type-not-found-in-adt-field.rs | 5 +++++
.../suggestions/type-not-found-in-adt-field.stderr | 9 +++++++++
5 files changed, 24 insertions(+), 7 deletions(-)
create mode 100644 src/test/ui/suggestions/type-not-found-in-adt-field.rs
create mode 100644 src/test/ui/suggestions/type-not-found-in-adt-field.stderr
diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs
index 2ae063660e38d..8661af6d7a1de 100644
--- a/src/librustc_resolve/build_reduced_graph.rs
+++ b/src/librustc_resolve/build_reduced_graph.rs
@@ -485,6 +485,7 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
module_path.push(Segment {
ident: Ident { name: kw::PathRoot, span: source.ident.span },
id: Some(self.r.next_node_id()),
+ has_args: false,
});
source.ident.name = crate_name;
}
diff --git a/src/librustc_resolve/late/diagnostics.rs b/src/librustc_resolve/late/diagnostics.rs
index b1a1f8725a180..28ff89f66925e 100644
--- a/src/librustc_resolve/late/diagnostics.rs
+++ b/src/librustc_resolve/late/diagnostics.rs
@@ -920,7 +920,7 @@ impl<'a> LateResolutionVisitor<'a, '_, '_> {
path: &[Segment],
) -> Option<(Span, &'static str, String, Applicability)> {
let ident = match path {
- [segment] => segment.ident,
+ [segment] if !segment.has_args => segment.ident,
_ => return None,
};
match (
diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs
index 6bd73877fab75..f7ec919fa04e3 100644
--- a/src/librustc_resolve/lib.rs
+++ b/src/librustc_resolve/lib.rs
@@ -225,13 +225,15 @@ enum VisResolutionError<'a> {
ModuleOnly(Span),
}
-// A minimal representation of a path segment. We use this in resolve because
-// we synthesize 'path segments' which don't have the rest of an AST or HIR
-// `PathSegment`.
+/// A minimal representation of a path segment. We use this in resolve because we synthesize 'path
+/// segments' which don't have the rest of an AST or HIR `PathSegment`.
#[derive(Clone, Copy, Debug)]
pub struct Segment {
ident: Ident,
id: Option,
+ /// Signals whether this `PathSegment` has generic arguments. Used to avoid providing
+ /// nonsensical suggestions.
+ has_args: bool,
}
impl Segment {
@@ -240,7 +242,7 @@ impl Segment {
}
fn from_ident(ident: Ident) -> Segment {
- Segment { ident, id: None }
+ Segment { ident, id: None, has_args: false }
}
fn names_to_string(segments: &[Segment]) -> String {
@@ -250,7 +252,7 @@ impl Segment {
impl<'a> From<&'a ast::PathSegment> for Segment {
fn from(seg: &'a ast::PathSegment) -> Segment {
- Segment { ident: seg.ident, id: Some(seg.id) }
+ Segment { ident: seg.ident, id: Some(seg.id), has_args: seg.args.is_some() }
}
}
@@ -2017,7 +2019,7 @@ impl<'a> Resolver<'a> {
path, opt_ns, record_used, path_span, crate_lint,
);
- for (i, &Segment { ident, id }) in path.iter().enumerate() {
+ for (i, &Segment { ident, id, has_args: _ }) in path.iter().enumerate() {
debug!("resolve_path ident {} {:?} {:?}", i, ident, id);
let record_segment_res = |this: &mut Self, res| {
if record_used {
diff --git a/src/test/ui/suggestions/type-not-found-in-adt-field.rs b/src/test/ui/suggestions/type-not-found-in-adt-field.rs
new file mode 100644
index 0000000000000..6bd42472f5a55
--- /dev/null
+++ b/src/test/ui/suggestions/type-not-found-in-adt-field.rs
@@ -0,0 +1,5 @@
+struct S {
+ m: Vec>, //~ ERROR cannot find type `Hashmap` in this scope
+ //~^ NOTE not found in this scope
+}
+fn main() {}
diff --git a/src/test/ui/suggestions/type-not-found-in-adt-field.stderr b/src/test/ui/suggestions/type-not-found-in-adt-field.stderr
new file mode 100644
index 0000000000000..cfad8c689d038
--- /dev/null
+++ b/src/test/ui/suggestions/type-not-found-in-adt-field.stderr
@@ -0,0 +1,9 @@
+error[E0412]: cannot find type `Hashmap` in this scope
+ --> $DIR/type-not-found-in-adt-field.rs:2:12
+ |
+LL | m: Vec>,
+ | ^^^^^^^ not found in this scope
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0412`.
From f62903b74a8630fa62e721f69e6621d1d441e7f1 Mon Sep 17 00:00:00 2001
From: Nathan Corbyn
Date: Fri, 5 Jun 2020 16:47:37 +0100
Subject: [PATCH 12/52] Export `#[inline] #[no_mangle]` fns in cdylibs and
staticlibs
---
src/librustc_codegen_ssa/back/symbol_export.rs | 9 +++++----
src/librustc_middle/mir/mono.rs | 1 +
src/librustc_middle/query/mod.rs | 4 ++++
src/librustc_typeck/collect.rs | 12 ++++++++++++
src/test/codegen/cdylib-external-no-mangle-fns.rs | 13 +++++++++++++
.../codegen/staticlib-external-no-mangle-fns.rs | 13 +++++++++++++
6 files changed, 48 insertions(+), 4 deletions(-)
create mode 100644 src/test/codegen/cdylib-external-no-mangle-fns.rs
create mode 100644 src/test/codegen/staticlib-external-no-mangle-fns.rs
diff --git a/src/librustc_codegen_ssa/back/symbol_export.rs b/src/librustc_codegen_ssa/back/symbol_export.rs
index 970d13b30c04e..bf8693f3547a4 100644
--- a/src/librustc_codegen_ssa/back/symbol_export.rs
+++ b/src/librustc_codegen_ssa/back/symbol_export.rs
@@ -89,10 +89,11 @@ fn reachable_non_generics_provider(tcx: TyCtxt<'_>, cnum: CrateNum) -> DefIdMap<
| Node::ImplItem(&hir::ImplItem { kind: hir::ImplItemKind::Fn(..), .. }) => {
let def_id = tcx.hir().local_def_id(hir_id);
let generics = tcx.generics_of(def_id);
- if !generics.requires_monomorphization(tcx) &&
- // Functions marked with #[inline] are only ever codegened
- // with "internal" linkage and are never exported.
- !Instance::mono(tcx, def_id.to_def_id()).def.generates_cgu_internal_copy(tcx)
+ if !generics.requires_monomorphization(tcx)
+ && (!Instance::mono(tcx, def_id.to_def_id())
+ .def
+ .generates_cgu_internal_copy(tcx)
+ || tcx.inline_exportable(def_id.to_def_id()))
{
Some(def_id)
} else {
diff --git a/src/librustc_middle/mir/mono.rs b/src/librustc_middle/mir/mono.rs
index c889dbc0a4498..d8dcf0dea8a5f 100644
--- a/src/librustc_middle/mir/mono.rs
+++ b/src/librustc_middle/mir/mono.rs
@@ -95,6 +95,7 @@ impl<'tcx> MonoItem<'tcx> {
// linkage, then we'll be creating a globally shared version.
if self.explicit_linkage(tcx).is_some()
|| !instance.def.generates_cgu_internal_copy(tcx)
+ || tcx.inline_exportable(instance.def_id())
|| Some(instance.def_id()) == entry_def_id.map(LocalDefId::to_def_id)
{
return InstantiationMode::GloballyShared { may_conflict: false };
diff --git a/src/librustc_middle/query/mod.rs b/src/librustc_middle/query/mod.rs
index be15e6c576f69..20487fdb6696d 100644
--- a/src/librustc_middle/query/mod.rs
+++ b/src/librustc_middle/query/mod.rs
@@ -697,6 +697,10 @@ rustc_queries! {
storage(ArenaCacheSelector<'tcx>)
cache_on_disk_if { true }
}
+
+ query inline_exportable(def_id: DefId) -> bool {
+ desc { |tcx| "computing whether `{}` should be explicitly exported", tcx.def_path_str(def_id) }
+ }
}
Other {
diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs
index 1d59d749634ee..08a6330e718e6 100644
--- a/src/librustc_typeck/collect.rs
+++ b/src/librustc_typeck/collect.rs
@@ -40,6 +40,7 @@ use rustc_middle::ty::util::Discr;
use rustc_middle::ty::util::IntTypeExt;
use rustc_middle::ty::{self, AdtKind, Const, ToPolyTraitRef, Ty, TyCtxt};
use rustc_middle::ty::{ReprOptions, ToPredicate, WithConstness};
+use rustc_session::config::CrateType;
use rustc_session::lint;
use rustc_session::parse::feature_err;
use rustc_span::symbol::{kw, sym, Ident, Symbol};
@@ -79,6 +80,7 @@ pub fn provide(providers: &mut Providers<'_>) {
static_mutability,
generator_kind,
codegen_fn_attrs,
+ inline_exportable,
collect_mod_item_types,
..*providers
};
@@ -2599,6 +2601,16 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, id: DefId) -> CodegenFnAttrs {
codegen_fn_attrs
}
+fn inline_exportable(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
+ // Functions marked with #[inline] are only ever codegened
+ // with "internal" linkage and are never exported unless we're
+ // building a `staticlib` or `cdylib` and they are marked
+ // `#[no_mangle]`.
+ tcx.codegen_fn_attrs(def_id).flags.contains(CodegenFnAttrFlags::NO_MANGLE)
+ && (tcx.sess.crate_types().contains(&CrateType::Cdylib)
+ || tcx.sess.crate_types().contains(&CrateType::Staticlib))
+}
+
/// Checks if the provided DefId is a method in a trait impl for a trait which has track_caller
/// applied to the method prototype.
fn should_inherit_track_caller(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
diff --git a/src/test/codegen/cdylib-external-no-mangle-fns.rs b/src/test/codegen/cdylib-external-no-mangle-fns.rs
new file mode 100644
index 0000000000000..827de7e5c11d9
--- /dev/null
+++ b/src/test/codegen/cdylib-external-no-mangle-fns.rs
@@ -0,0 +1,13 @@
+// compile-flags: -C no-prepopulate-passes
+
+#![crate_type = "cdylib"]
+
+// CHECK: define void @a()
+#[no_mangle]
+#[inline]
+pub extern "C" fn a() {
+ // side effect to keep `a` around
+ unsafe {
+ core::ptr::read_volatile(&42);
+ }
+}
diff --git a/src/test/codegen/staticlib-external-no-mangle-fns.rs b/src/test/codegen/staticlib-external-no-mangle-fns.rs
new file mode 100644
index 0000000000000..0b4a37febb209
--- /dev/null
+++ b/src/test/codegen/staticlib-external-no-mangle-fns.rs
@@ -0,0 +1,13 @@
+// compile-flags: -C no-prepopulate-passes
+
+#![crate_type = "staticlib"]
+
+// CHECK: define void @a()
+#[no_mangle]
+#[inline]
+pub extern "C" fn a() {
+ // side effect to keep `a` around
+ unsafe {
+ core::ptr::read_volatile(&42);
+ }
+}
From 6b7cacb2c99567a76cf0d5ce6833a129c8bb8814 Mon Sep 17 00:00:00 2001
From: Nathan Corbyn
Date: Mon, 8 Jun 2020 09:37:11 +0100
Subject: [PATCH 13/52] Export all fns with extern indicator
---
.../back/symbol_export.rs | 9 ++++----
src/librustc_middle/mir/mono.rs | 12 ++++++----
src/librustc_middle/query/mod.rs | 4 ----
src/librustc_typeck/collect.rs | 12 ----------
.../codegen/cdylib-external-inline-fns.rs | 23 +++++++++++++++++++
.../codegen/cdylib-external-no-mangle-fns.rs | 13 -----------
src/test/codegen/export-no-mangle.rs | 5 ++++
src/test/codegen/external-no-mangle-fns.rs | 10 ++++++++
.../codegen/staticlib-external-inline-fns.rs | 23 +++++++++++++++++++
.../staticlib-external-no-mangle-fns.rs | 13 -----------
10 files changed, 74 insertions(+), 50 deletions(-)
create mode 100644 src/test/codegen/cdylib-external-inline-fns.rs
delete mode 100644 src/test/codegen/cdylib-external-no-mangle-fns.rs
create mode 100644 src/test/codegen/staticlib-external-inline-fns.rs
delete mode 100644 src/test/codegen/staticlib-external-no-mangle-fns.rs
diff --git a/src/librustc_codegen_ssa/back/symbol_export.rs b/src/librustc_codegen_ssa/back/symbol_export.rs
index bf8693f3547a4..98f7da8361cc4 100644
--- a/src/librustc_codegen_ssa/back/symbol_export.rs
+++ b/src/librustc_codegen_ssa/back/symbol_export.rs
@@ -90,10 +90,11 @@ fn reachable_non_generics_provider(tcx: TyCtxt<'_>, cnum: CrateNum) -> DefIdMap<
let def_id = tcx.hir().local_def_id(hir_id);
let generics = tcx.generics_of(def_id);
if !generics.requires_monomorphization(tcx)
- && (!Instance::mono(tcx, def_id.to_def_id())
- .def
- .generates_cgu_internal_copy(tcx)
- || tcx.inline_exportable(def_id.to_def_id()))
+ // Functions marked with #[inline] are codegened with "internal"
+ // linkage and are not exported unless marked with an extern
+ // inidicator
+ && (!Instance::mono(tcx, def_id.to_def_id()).def.generates_cgu_internal_copy(tcx)
+ || tcx.codegen_fn_attrs(def_id.to_def_id()).contains_extern_indicator())
{
Some(def_id)
} else {
diff --git a/src/librustc_middle/mir/mono.rs b/src/librustc_middle/mir/mono.rs
index d8dcf0dea8a5f..886690da212d3 100644
--- a/src/librustc_middle/mir/mono.rs
+++ b/src/librustc_middle/mir/mono.rs
@@ -92,10 +92,10 @@ impl<'tcx> MonoItem<'tcx> {
MonoItem::Fn(ref instance) => {
let entry_def_id = tcx.entry_fn(LOCAL_CRATE).map(|(id, _)| id);
// If this function isn't inlined or otherwise has explicit
- // linkage, then we'll be creating a globally shared version.
+ // linkage or an extern indicator, then we'll be creating a
+ // globally shared version.
if self.explicit_linkage(tcx).is_some()
|| !instance.def.generates_cgu_internal_copy(tcx)
- || tcx.inline_exportable(instance.def_id())
|| Some(instance.def_id()) == entry_def_id.map(LocalDefId::to_def_id)
{
return InstantiationMode::GloballyShared { may_conflict: false };
@@ -103,8 +103,12 @@ impl<'tcx> MonoItem<'tcx> {
// At this point we don't have explicit linkage and we're an
// inlined function. If we're inlining into all CGUs then we'll
- // be creating a local copy per CGU
- if generate_cgu_internal_copies {
+ // be creating a local copy per CGU. We need to watch out here
+ // for an extern indicator as we don't want to optimise away
+ // inlined functions that should be exported.
+ if generate_cgu_internal_copies
+ && !tcx.codegen_fn_attrs(instance.def_id()).contains_extern_indicator()
+ {
return InstantiationMode::LocalCopy;
}
diff --git a/src/librustc_middle/query/mod.rs b/src/librustc_middle/query/mod.rs
index 20487fdb6696d..be15e6c576f69 100644
--- a/src/librustc_middle/query/mod.rs
+++ b/src/librustc_middle/query/mod.rs
@@ -697,10 +697,6 @@ rustc_queries! {
storage(ArenaCacheSelector<'tcx>)
cache_on_disk_if { true }
}
-
- query inline_exportable(def_id: DefId) -> bool {
- desc { |tcx| "computing whether `{}` should be explicitly exported", tcx.def_path_str(def_id) }
- }
}
Other {
diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs
index 08a6330e718e6..1d59d749634ee 100644
--- a/src/librustc_typeck/collect.rs
+++ b/src/librustc_typeck/collect.rs
@@ -40,7 +40,6 @@ use rustc_middle::ty::util::Discr;
use rustc_middle::ty::util::IntTypeExt;
use rustc_middle::ty::{self, AdtKind, Const, ToPolyTraitRef, Ty, TyCtxt};
use rustc_middle::ty::{ReprOptions, ToPredicate, WithConstness};
-use rustc_session::config::CrateType;
use rustc_session::lint;
use rustc_session::parse::feature_err;
use rustc_span::symbol::{kw, sym, Ident, Symbol};
@@ -80,7 +79,6 @@ pub fn provide(providers: &mut Providers<'_>) {
static_mutability,
generator_kind,
codegen_fn_attrs,
- inline_exportable,
collect_mod_item_types,
..*providers
};
@@ -2601,16 +2599,6 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, id: DefId) -> CodegenFnAttrs {
codegen_fn_attrs
}
-fn inline_exportable(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
- // Functions marked with #[inline] are only ever codegened
- // with "internal" linkage and are never exported unless we're
- // building a `staticlib` or `cdylib` and they are marked
- // `#[no_mangle]`.
- tcx.codegen_fn_attrs(def_id).flags.contains(CodegenFnAttrFlags::NO_MANGLE)
- && (tcx.sess.crate_types().contains(&CrateType::Cdylib)
- || tcx.sess.crate_types().contains(&CrateType::Staticlib))
-}
-
/// Checks if the provided DefId is a method in a trait impl for a trait which has track_caller
/// applied to the method prototype.
fn should_inherit_track_caller(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
diff --git a/src/test/codegen/cdylib-external-inline-fns.rs b/src/test/codegen/cdylib-external-inline-fns.rs
new file mode 100644
index 0000000000000..58f806b5a1f34
--- /dev/null
+++ b/src/test/codegen/cdylib-external-inline-fns.rs
@@ -0,0 +1,23 @@
+// compile-flags: -C no-prepopulate-passes
+
+#![crate_type = "cdylib"]
+
+// CHECK: define void @a()
+#[no_mangle]
+#[inline]
+pub extern "C" fn a() {}
+
+// CHECK: define void @b()
+#[export_name = "b"]
+#[inline]
+pub extern "C" fn b() {}
+
+// CHECK: define void @c()
+#[no_mangle]
+#[inline]
+extern "C" fn c() {}
+
+// CHECK: define void @d()
+#[export_name = "d"]
+#[inline]
+extern "C" fn d() {}
diff --git a/src/test/codegen/cdylib-external-no-mangle-fns.rs b/src/test/codegen/cdylib-external-no-mangle-fns.rs
deleted file mode 100644
index 827de7e5c11d9..0000000000000
--- a/src/test/codegen/cdylib-external-no-mangle-fns.rs
+++ /dev/null
@@ -1,13 +0,0 @@
-// compile-flags: -C no-prepopulate-passes
-
-#![crate_type = "cdylib"]
-
-// CHECK: define void @a()
-#[no_mangle]
-#[inline]
-pub extern "C" fn a() {
- // side effect to keep `a` around
- unsafe {
- core::ptr::read_volatile(&42);
- }
-}
diff --git a/src/test/codegen/export-no-mangle.rs b/src/test/codegen/export-no-mangle.rs
index 78d41e4be0ae9..793636bb1b030 100644
--- a/src/test/codegen/export-no-mangle.rs
+++ b/src/test/codegen/export-no-mangle.rs
@@ -18,4 +18,9 @@ mod private {
// CHECK: void @bar()
#[export_name = "bar"]
extern fn bar() {}
+
+ // CHECK: void @baz()
+ #[export_name = "baz"]
+ #[inline]
+ extern fn baz() {}
}
diff --git a/src/test/codegen/external-no-mangle-fns.rs b/src/test/codegen/external-no-mangle-fns.rs
index 902882144996f..aefa9ce21c3ee 100644
--- a/src/test/codegen/external-no-mangle-fns.rs
+++ b/src/test/codegen/external-no-mangle-fns.rs
@@ -53,3 +53,13 @@ fn x() {
core::ptr::read_volatile(&42);
}
}
+
+// CHECK: define void @i()
+#[no_mangle]
+#[inline]
+fn i() {}
+
+// CHECK: define void @j()
+#[no_mangle]
+#[inline]
+pub fn j() {}
diff --git a/src/test/codegen/staticlib-external-inline-fns.rs b/src/test/codegen/staticlib-external-inline-fns.rs
new file mode 100644
index 0000000000000..8f55a5303311c
--- /dev/null
+++ b/src/test/codegen/staticlib-external-inline-fns.rs
@@ -0,0 +1,23 @@
+// compile-flags: -C no-prepopulate-passes
+
+#![crate_type = "staticlib"]
+
+// CHECK: define void @a()
+#[no_mangle]
+#[inline]
+pub extern "C" fn a() {}
+
+// CHECK: define void @b()
+#[export_name = "b"]
+#[inline]
+pub extern "C" fn b() {}
+
+// CHECK: define void @c()
+#[no_mangle]
+#[inline]
+extern "C" fn c() {}
+
+// CHECK: define void @d()
+#[export_name = "d"]
+#[inline]
+extern "C" fn d() {}
diff --git a/src/test/codegen/staticlib-external-no-mangle-fns.rs b/src/test/codegen/staticlib-external-no-mangle-fns.rs
deleted file mode 100644
index 0b4a37febb209..0000000000000
--- a/src/test/codegen/staticlib-external-no-mangle-fns.rs
+++ /dev/null
@@ -1,13 +0,0 @@
-// compile-flags: -C no-prepopulate-passes
-
-#![crate_type = "staticlib"]
-
-// CHECK: define void @a()
-#[no_mangle]
-#[inline]
-pub extern "C" fn a() {
- // side effect to keep `a` around
- unsafe {
- core::ptr::read_volatile(&42);
- }
-}
From d23bedd13d70597a7db70ef5ea549fc7a4063d10 Mon Sep 17 00:00:00 2001
From: Nathan Corbyn
Date: Mon, 8 Jun 2020 09:54:33 +0100
Subject: [PATCH 14/52] Fix whitespace
---
src/test/codegen/export-no-mangle.rs | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/test/codegen/export-no-mangle.rs b/src/test/codegen/export-no-mangle.rs
index 793636bb1b030..a52fac37021dd 100644
--- a/src/test/codegen/export-no-mangle.rs
+++ b/src/test/codegen/export-no-mangle.rs
@@ -18,7 +18,7 @@ mod private {
// CHECK: void @bar()
#[export_name = "bar"]
extern fn bar() {}
-
+
// CHECK: void @baz()
#[export_name = "baz"]
#[inline]
From ee810a75e41368387918759ed191657f05650f05 Mon Sep 17 00:00:00 2001
From: Nathan Corbyn
Date: Tue, 9 Jun 2020 15:49:59 +0100
Subject: [PATCH 15/52] Fix exports with `#[inline(always)]`
---
src/librustc_middle/mir/mono.rs | 15 +++++--------
.../codegen/cdylib-external-inline-fns.rs | 20 ++++++++++++++++++
src/test/codegen/export-no-mangle.rs | 21 ++++++++++++-------
src/test/codegen/external-no-mangle-fns.rs | 10 +++++++++
.../codegen/staticlib-external-inline-fns.rs | 20 ++++++++++++++++++
5 files changed, 68 insertions(+), 18 deletions(-)
diff --git a/src/librustc_middle/mir/mono.rs b/src/librustc_middle/mir/mono.rs
index 886690da212d3..24d324ff09c4c 100644
--- a/src/librustc_middle/mir/mono.rs
+++ b/src/librustc_middle/mir/mono.rs
@@ -91,10 +91,9 @@ impl<'tcx> MonoItem<'tcx> {
match *self {
MonoItem::Fn(ref instance) => {
let entry_def_id = tcx.entry_fn(LOCAL_CRATE).map(|(id, _)| id);
- // If this function isn't inlined or otherwise has explicit
- // linkage or an extern indicator, then we'll be creating a
- // globally shared version.
- if self.explicit_linkage(tcx).is_some()
+ // If this function isn't inlined or otherwise has an extern
+ // indicator, then we'll be creating a globally shared version.
+ if tcx.codegen_fn_attrs(instance.def_id()).contains_extern_indicator()
|| !instance.def.generates_cgu_internal_copy(tcx)
|| Some(instance.def_id()) == entry_def_id.map(LocalDefId::to_def_id)
{
@@ -103,12 +102,8 @@ impl<'tcx> MonoItem<'tcx> {
// At this point we don't have explicit linkage and we're an
// inlined function. If we're inlining into all CGUs then we'll
- // be creating a local copy per CGU. We need to watch out here
- // for an extern indicator as we don't want to optimise away
- // inlined functions that should be exported.
- if generate_cgu_internal_copies
- && !tcx.codegen_fn_attrs(instance.def_id()).contains_extern_indicator()
- {
+ // be creating a local copy per CGU.
+ if generate_cgu_internal_copies {
return InstantiationMode::LocalCopy;
}
diff --git a/src/test/codegen/cdylib-external-inline-fns.rs b/src/test/codegen/cdylib-external-inline-fns.rs
index 58f806b5a1f34..519be6b6a99a4 100644
--- a/src/test/codegen/cdylib-external-inline-fns.rs
+++ b/src/test/codegen/cdylib-external-inline-fns.rs
@@ -21,3 +21,23 @@ extern "C" fn c() {}
#[export_name = "d"]
#[inline]
extern "C" fn d() {}
+
+// CHECK: define void @e()
+#[no_mangle]
+#[inline(always)]
+pub extern "C" fn e() {}
+
+// CHECK: define void @f()
+#[export_name = "f"]
+#[inline(always)]
+pub extern "C" fn f() {}
+
+// CHECK: define void @g()
+#[no_mangle]
+#[inline(always)]
+extern "C" fn g() {}
+
+// CHECK: define void @h()
+#[export_name = "h"]
+#[inline(always)]
+extern "C" fn h() {}
diff --git a/src/test/codegen/export-no-mangle.rs b/src/test/codegen/export-no-mangle.rs
index a52fac37021dd..11427ae38822f 100644
--- a/src/test/codegen/export-no-mangle.rs
+++ b/src/test/codegen/export-no-mangle.rs
@@ -11,16 +11,21 @@ mod private {
#[export_name = "BAR"]
static BAR: u32 = 3;
- // CHECK: void @foo()
+ // CHECK: void @a()
#[no_mangle]
- pub extern fn foo() {}
+ pub extern fn a() {}
- // CHECK: void @bar()
- #[export_name = "bar"]
- extern fn bar() {}
+ // CHECK: void @b()
+ #[export_name = "b"]
+ extern fn b() {}
- // CHECK: void @baz()
- #[export_name = "baz"]
+ // CHECK: void @c()
+ #[export_name = "c"]
#[inline]
- extern fn baz() {}
+ extern fn c() {}
+
+ // CHECK: void @d()
+ #[export_name = "d"]
+ #[inline(always)]
+ extern fn d() {}
}
diff --git a/src/test/codegen/external-no-mangle-fns.rs b/src/test/codegen/external-no-mangle-fns.rs
index aefa9ce21c3ee..41820b057f1ef 100644
--- a/src/test/codegen/external-no-mangle-fns.rs
+++ b/src/test/codegen/external-no-mangle-fns.rs
@@ -63,3 +63,13 @@ fn i() {}
#[no_mangle]
#[inline]
pub fn j() {}
+
+// CHECK: define void @k()
+#[no_mangle]
+#[inline(always)]
+fn k() {}
+
+// CHECK: define void @l()
+#[no_mangle]
+#[inline(always)]
+pub fn l() {}
diff --git a/src/test/codegen/staticlib-external-inline-fns.rs b/src/test/codegen/staticlib-external-inline-fns.rs
index 8f55a5303311c..8876ab7376afe 100644
--- a/src/test/codegen/staticlib-external-inline-fns.rs
+++ b/src/test/codegen/staticlib-external-inline-fns.rs
@@ -21,3 +21,23 @@ extern "C" fn c() {}
#[export_name = "d"]
#[inline]
extern "C" fn d() {}
+
+// CHECK: define void @e()
+#[no_mangle]
+#[inline(always)]
+pub extern "C" fn e() {}
+
+// CHECK: define void @f()
+#[export_name = "f"]
+#[inline(always)]
+pub extern "C" fn f() {}
+
+// CHECK: define void @g()
+#[no_mangle]
+#[inline(always)]
+extern "C" fn g() {}
+
+// CHECK: define void @h()
+#[export_name = "h"]
+#[inline(always)]
+extern "C" fn h() {}
From 11b56fbfb63ef8e2494b8631488e478794c80ed4 Mon Sep 17 00:00:00 2001
From: Nathan Corbyn
Date: Tue, 9 Jun 2020 15:54:34 +0100
Subject: [PATCH 16/52] Fix whitespace
---
src/librustc_middle/mir/mono.rs | 2 +-
src/test/codegen/export-no-mangle.rs | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/librustc_middle/mir/mono.rs b/src/librustc_middle/mir/mono.rs
index 24d324ff09c4c..f1c1b962ab997 100644
--- a/src/librustc_middle/mir/mono.rs
+++ b/src/librustc_middle/mir/mono.rs
@@ -102,7 +102,7 @@ impl<'tcx> MonoItem<'tcx> {
// At this point we don't have explicit linkage and we're an
// inlined function. If we're inlining into all CGUs then we'll
- // be creating a local copy per CGU.
+ // be creating a local copy per CGU.
if generate_cgu_internal_copies {
return InstantiationMode::LocalCopy;
}
diff --git a/src/test/codegen/export-no-mangle.rs b/src/test/codegen/export-no-mangle.rs
index 11427ae38822f..59e97601c838d 100644
--- a/src/test/codegen/export-no-mangle.rs
+++ b/src/test/codegen/export-no-mangle.rs
@@ -23,7 +23,7 @@ mod private {
#[export_name = "c"]
#[inline]
extern fn c() {}
-
+
// CHECK: void @d()
#[export_name = "d"]
#[inline(always)]
From babda9470ea1e5932d238b7f805e76379f01d37c Mon Sep 17 00:00:00 2001
From: Nathan Corbyn
Date: Mon, 15 Jun 2020 10:21:19 +0100
Subject: [PATCH 17/52] Fix sanitizer test
---
src/test/codegen/sanitizer-no-sanitize-inlining.rs | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/src/test/codegen/sanitizer-no-sanitize-inlining.rs b/src/test/codegen/sanitizer-no-sanitize-inlining.rs
index d96e76618d325..86e58c3c9bb17 100644
--- a/src/test/codegen/sanitizer-no-sanitize-inlining.rs
+++ b/src/test/codegen/sanitizer-no-sanitize-inlining.rs
@@ -13,7 +13,7 @@
#![feature(no_sanitize)]
// ASAN-LABEL: define void @test
-// ASAN: tail call fastcc void @random_inline
+// ASAN: tail call fastcc
// ASAN: }
//
// LSAN-LABEL: define void @test
@@ -26,7 +26,6 @@ pub fn test(n: &mut u32) {
#[no_sanitize(address)]
#[inline]
-#[no_mangle]
pub fn random_inline(n: &mut u32) {
*n = 42;
}
From e8e0a0e4e220533db31bc6a572ed9f1b99b31289 Mon Sep 17 00:00:00 2001
From: Nathan Corbyn
Date: Mon, 15 Jun 2020 11:12:19 +0100
Subject: [PATCH 18/52] Update sanitizer test
---
src/test/codegen/sanitizer-no-sanitize-inlining.rs | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/src/test/codegen/sanitizer-no-sanitize-inlining.rs b/src/test/codegen/sanitizer-no-sanitize-inlining.rs
index 86e58c3c9bb17..48231d6f7208d 100644
--- a/src/test/codegen/sanitizer-no-sanitize-inlining.rs
+++ b/src/test/codegen/sanitizer-no-sanitize-inlining.rs
@@ -13,7 +13,7 @@
#![feature(no_sanitize)]
// ASAN-LABEL: define void @test
-// ASAN: tail call fastcc
+// ASAN: call {{.*}} @random_inline
// ASAN: }
//
// LSAN-LABEL: define void @test
@@ -26,6 +26,7 @@ pub fn test(n: &mut u32) {
#[no_sanitize(address)]
#[inline]
+#[no_mangle]
pub fn random_inline(n: &mut u32) {
*n = 42;
}
From 9e510085ecaedaee86b44410a4b3e4c85d97d6e0 Mon Sep 17 00:00:00 2001
From: Alexis Bourget
Date: Mon, 15 Jun 2020 15:19:02 +0200
Subject: [PATCH 19/52] Complete the std::time documentation to warn about the
inconsistencies between OS
---
src/libstd/time.rs | 15 +++++++++++++++
1 file changed, 15 insertions(+)
diff --git a/src/libstd/time.rs b/src/libstd/time.rs
index c36e78b1d004e..c58168bd446d7 100644
--- a/src/libstd/time.rs
+++ b/src/libstd/time.rs
@@ -60,6 +60,21 @@ pub use core::time::Duration;
/// }
/// ```
///
+/// # OS-specific behaviors
+///
+/// An `Instant` is a wrapper around system-specific types and it may behave
+/// differently depending on the underlying operating system. For example,
+/// the following snippet is fine on Linux but panics on macOS:
+///
+/// ```no_run
+/// use std::time::{Instant, Duration};
+///
+/// let now = Instant::now();
+/// let max_nanoseconds = u64::MAX / 1_000_000_000;
+/// let duration = Duration::new(max_nanoseconds, 0);
+/// println!("{:?}", now + duration);
+/// ```
+///
/// # Underlying System calls
/// Currently, the following system calls are being used to get the current time using `now()`:
///
From e857696cf8c3b4a4381d00424f165c10f93a9ebd Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Esteban=20K=C3=BCber?=
Date: Sun, 14 Jun 2020 21:36:25 -0700
Subject: [PATCH 20/52] Tweak "non-primitive cast" error
- Suggest borrowing expression if it would allow cast to work.
- Suggest using `::from()` when appropriate.
- Minor tweak to `;` typo suggestion.
Partily address #47136.
---
src/libcore/convert/mod.rs | 1 +
src/librustc_parse/parser/diagnostics.rs | 2 +-
src/librustc_span/symbol.rs | 1 +
src/librustc_typeck/check/cast.rs | 107 ++++++++++++++----
src/test/ui/cast/cast-from-nil.stderr | 4 +-
src/test/ui/cast/cast-to-bare-fn.stderr | 8 +-
src/test/ui/cast/cast-to-nil.stderr | 4 +-
...-to-unsized-trait-object-suggestion.stderr | 2 +-
src/test/ui/closures/closure-no-fn-3.stderr | 4 +-
.../ui/coercion/coerce-to-bang-cast.stderr | 8 +-
.../const-eval/const-eval-overflow-4b.stderr | 2 +-
src/test/ui/error-codes/E0604.stderr | 2 +-
src/test/ui/error-codes/E0605.stderr | 8 +-
src/test/ui/error-festival.stderr | 6 +-
src/test/ui/fat-ptr-cast.stderr | 4 +-
src/test/ui/issues/issue-10991.stderr | 4 +-
src/test/ui/issues/issue-16048.rs | 4 +-
src/test/ui/issues/issue-16048.stderr | 8 +-
src/test/ui/issues/issue-17441.stderr | 2 +-
src/test/ui/issues/issue-22289.stderr | 7 +-
src/test/ui/issues/issue-22312.rs | 2 +-
src/test/ui/issues/issue-22312.stderr | 7 +-
src/test/ui/issues/issue-2995.stderr | 4 +-
src/test/ui/issues/issue-45730.stderr | 18 +--
.../ui/mismatched_types/cast-rfc0401.stderr | 22 +---
.../ui/mismatched_types/issue-26480.stderr | 3 +-
src/test/ui/nonscalar-cast.fixed | 16 +++
src/test/ui/nonscalar-cast.rs | 8 ++
src/test/ui/nonscalar-cast.stderr | 6 +-
.../ui/order-dependent-cast-inference.stderr | 6 +-
.../ui/tag-variant-cast-non-nullary.fixed | 20 ++++
src/test/ui/tag-variant-cast-non-nullary.rs | 11 ++
.../ui/tag-variant-cast-non-nullary.stderr | 6 +-
.../never_reveal_concrete_type.stderr | 4 +-
.../uninhabited/uninhabited-enum-cast.stderr | 4 +-
35 files changed, 204 insertions(+), 121 deletions(-)
create mode 100644 src/test/ui/nonscalar-cast.fixed
create mode 100644 src/test/ui/tag-variant-cast-non-nullary.fixed
diff --git a/src/libcore/convert/mod.rs b/src/libcore/convert/mod.rs
index eef9ee7cb0093..8ff1ced53b071 100644
--- a/src/libcore/convert/mod.rs
+++ b/src/libcore/convert/mod.rs
@@ -374,6 +374,7 @@ pub trait Into: Sized {
/// [`Into`]: trait.Into.html
/// [`from`]: trait.From.html#tymethod.from
/// [book]: ../../book/ch09-00-error-handling.html
+#[rustc_diagnostic_item = "from_trait"]
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_on_unimplemented(on(
all(_Self = "&str", T = "std::string::String"),
diff --git a/src/librustc_parse/parser/diagnostics.rs b/src/librustc_parse/parser/diagnostics.rs
index 660a63841bcef..dafc0a9e048a4 100644
--- a/src/librustc_parse/parser/diagnostics.rs
+++ b/src/librustc_parse/parser/diagnostics.rs
@@ -961,7 +961,7 @@ impl<'a> Parser<'a> {
self.bump();
let sp = self.prev_token.span;
self.struct_span_err(sp, &msg)
- .span_suggestion(sp, "change this to `;`", ";".to_string(), appl)
+ .span_suggestion_short(sp, "change this to `;`", ";".to_string(), appl)
.emit();
return Ok(());
} else if self.look_ahead(0, |t| {
diff --git a/src/librustc_span/symbol.rs b/src/librustc_span/symbol.rs
index d165409696eca..9925e631c5c20 100644
--- a/src/librustc_span/symbol.rs
+++ b/src/librustc_span/symbol.rs
@@ -343,6 +343,7 @@ symbols! {
from_method,
from_ok,
from_usize,
+ from_trait,
fundamental,
future,
Future,
diff --git a/src/librustc_typeck/check/cast.rs b/src/librustc_typeck/check/cast.rs
index 46d6706cbf429..bad009f4039af 100644
--- a/src/librustc_typeck/check/cast.rs
+++ b/src/librustc_typeck/check/cast.rs
@@ -43,6 +43,7 @@ use rustc_middle::ty::subst::SubstsRef;
use rustc_middle::ty::{self, Ty, TypeAndMut, TypeFoldable};
use rustc_session::lint;
use rustc_session::Session;
+use rustc_span::symbol::sym;
use rustc_span::Span;
use rustc_trait_selection::traits;
use rustc_trait_selection::traits::error_reporting::report_object_safety_error;
@@ -333,10 +334,11 @@ impl<'a, 'tcx> CastCheck<'tcx> {
"only `u8` can be cast as `char`, not `{}`",
self.expr_ty
)
+ .span_label(self.span, "invalid cast")
.emit();
}
CastError::NonScalar => {
- type_error_struct!(
+ let mut err = type_error_struct!(
fcx.tcx.sess,
self.span,
self.expr_ty,
@@ -344,12 +346,75 @@ impl<'a, 'tcx> CastCheck<'tcx> {
"non-primitive cast: `{}` as `{}`",
self.expr_ty,
fcx.ty_to_string(self.cast_ty)
- )
- .note(
- "an `as` expression can only be used to convert between \
- primitive types. Consider using the `From` trait",
- )
- .emit();
+ );
+ let mut sugg = None;
+ if let ty::Ref(reg, _, mutbl) = self.cast_ty.kind {
+ if fcx
+ .try_coerce(
+ self.expr,
+ fcx.tcx.mk_ref(reg, TypeAndMut { ty: self.expr_ty, mutbl }),
+ self.cast_ty,
+ AllowTwoPhase::No,
+ )
+ .is_ok()
+ {
+ sugg = Some(format!("&{}", mutbl.prefix_str()));
+ }
+ }
+ if let Some(sugg) = sugg {
+ err.span_label(self.span, "invalid cast");
+ err.span_suggestion_verbose(
+ self.expr.span.shrink_to_lo(),
+ "borrow the value for the cast to be valid",
+ sugg,
+ Applicability::MachineApplicable,
+ );
+ } else if !matches!(
+ self.cast_ty.kind,
+ ty::FnDef(..) | ty::FnPtr(..) | ty::Closure(..)
+ ) {
+ let mut label = true;
+ // Check `impl From for self.cast_ty {}` for accurate suggestion:
+ if let Ok(snippet) = fcx.tcx.sess.source_map().span_to_snippet(self.expr.span) {
+ if let Some(from_trait) = fcx.tcx.get_diagnostic_item(sym::from_trait) {
+ let ty = fcx.resolve_vars_if_possible(&self.cast_ty);
+ // Erase regions to avoid panic in `prove_value` when calling
+ // `type_implements_trait`.
+ let ty = fcx.tcx.erase_regions(&ty);
+ let expr_ty = fcx.resolve_vars_if_possible(&self.expr_ty);
+ let expr_ty = fcx.tcx.erase_regions(&expr_ty);
+ let ty_params = fcx.tcx.mk_substs_trait(expr_ty, &[]);
+ // Check for infer types because cases like `Option<{integer}>` would
+ // panic otherwise.
+ if !expr_ty.has_infer_types()
+ && fcx.tcx.type_implements_trait((
+ from_trait,
+ ty,
+ ty_params,
+ fcx.param_env,
+ ))
+ {
+ label = false;
+ err.span_suggestion(
+ self.span,
+ "consider using the `From` trait instead",
+ format!("{}::from({})", self.cast_ty, snippet),
+ Applicability::MaybeIncorrect,
+ );
+ }
+ }
+ }
+ let msg = "an `as` expression can only be used to convert between primitive \
+ types or to coerce to a specific trait object";
+ if label {
+ err.span_label(self.span, msg);
+ } else {
+ err.note(msg);
+ }
+ } else {
+ err.span_label(self.span, "invalid cast");
+ }
+ err.emit();
}
CastError::SizedUnsizedCast => {
use crate::structured_errors::{SizedUnsizedCastError, StructuredDiagnostic};
@@ -370,21 +435,22 @@ impl<'a, 'tcx> CastCheck<'tcx> {
};
let mut err = struct_span_err!(
fcx.tcx.sess,
- self.span,
+ if unknown_cast_to { self.cast_span } else { self.span },
E0641,
"cannot cast {} a pointer of an unknown kind",
if unknown_cast_to { "to" } else { "from" }
);
- err.note(
- "the type information given here is insufficient to check whether \
- the pointer cast is valid",
- );
if unknown_cast_to {
- err.span_suggestion_short(
- self.cast_span,
- "consider giving more type information",
- String::new(),
- Applicability::Unspecified,
+ err.span_label(self.cast_span, "needs more type information");
+ err.note(
+ "the type information given here is insufficient to check whether \
+ the pointer cast is valid",
+ );
+ } else {
+ err.span_label(
+ self.span,
+ "the type information given here is insufficient to check whether \
+ the pointer cast is valid",
);
}
err.emit();
@@ -438,13 +504,16 @@ impl<'a, 'tcx> CastCheck<'tcx> {
Ok(s) => {
err.span_suggestion(
self.cast_span,
- "try casting to a `Box` instead",
+ "you can cast to a `Box` instead",
format!("Box<{}>", s),
Applicability::MachineApplicable,
);
}
Err(_) => {
- err.span_help(self.cast_span, &format!("did you mean `Box<{}>`?", tstr));
+ err.span_help(
+ self.cast_span,
+ &format!("you might have meant `Box<{}>`", tstr),
+ );
}
}
}
diff --git a/src/test/ui/cast/cast-from-nil.stderr b/src/test/ui/cast/cast-from-nil.stderr
index c8e3628a7ded8..dab133cfb4b67 100644
--- a/src/test/ui/cast/cast-from-nil.stderr
+++ b/src/test/ui/cast/cast-from-nil.stderr
@@ -2,9 +2,7 @@ error[E0605]: non-primitive cast: `()` as `u32`
--> $DIR/cast-from-nil.rs:2:21
|
LL | fn main() { let u = (assert!(true) as u32); }
- | ^^^^^^^^^^^^^^^^^^^^^^
- |
- = note: an `as` expression can only be used to convert between primitive types. Consider using the `From` trait
+ | ^^^^^^^^^^^^^^^^^^^^^^ an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object
error: aborting due to previous error
diff --git a/src/test/ui/cast/cast-to-bare-fn.stderr b/src/test/ui/cast/cast-to-bare-fn.stderr
index 84933dca929a4..d97b0c5f8aadc 100644
--- a/src/test/ui/cast/cast-to-bare-fn.stderr
+++ b/src/test/ui/cast/cast-to-bare-fn.stderr
@@ -2,17 +2,13 @@ error[E0605]: non-primitive cast: `fn(isize) {foo}` as `extern "C" fn() -> isize
--> $DIR/cast-to-bare-fn.rs:5:13
|
LL | let x = foo as extern "C" fn() -> isize;
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- |
- = note: an `as` expression can only be used to convert between primitive types. Consider using the `From` trait
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ invalid cast
error[E0605]: non-primitive cast: `u64` as `fn(isize) -> (isize, isize)`
--> $DIR/cast-to-bare-fn.rs:7:13
|
LL | let y = v as extern "Rust" fn(isize) -> (isize, isize);
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- |
- = note: an `as` expression can only be used to convert between primitive types. Consider using the `From` trait
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ invalid cast
error: aborting due to 2 previous errors
diff --git a/src/test/ui/cast/cast-to-nil.stderr b/src/test/ui/cast/cast-to-nil.stderr
index 478f6b69dafc8..29a9baffd71d7 100644
--- a/src/test/ui/cast/cast-to-nil.stderr
+++ b/src/test/ui/cast/cast-to-nil.stderr
@@ -2,9 +2,7 @@ error[E0605]: non-primitive cast: `u32` as `()`
--> $DIR/cast-to-nil.rs:2:21
|
LL | fn main() { let u = 0u32 as (); }
- | ^^^^^^^^^^
- |
- = note: an `as` expression can only be used to convert between primitive types. Consider using the `From` trait
+ | ^^^^^^^^^^ an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object
error: aborting due to previous error
diff --git a/src/test/ui/cast/cast-to-unsized-trait-object-suggestion.stderr b/src/test/ui/cast/cast-to-unsized-trait-object-suggestion.stderr
index ffa02533d8b66..9b86f8d4def86 100644
--- a/src/test/ui/cast/cast-to-unsized-trait-object-suggestion.stderr
+++ b/src/test/ui/cast/cast-to-unsized-trait-object-suggestion.stderr
@@ -12,7 +12,7 @@ error[E0620]: cast to unsized type: `std::boxed::Box<{integer}>` as `dyn std::ma
LL | Box::new(1) as dyn Send;
| ^^^^^^^^^^^^^^^--------
| |
- | help: try casting to a `Box` instead: `Box`
+ | help: you can cast to a `Box` instead: `Box`
error: aborting due to 2 previous errors
diff --git a/src/test/ui/closures/closure-no-fn-3.stderr b/src/test/ui/closures/closure-no-fn-3.stderr
index ab6056b65473e..4b3b4be798fc1 100644
--- a/src/test/ui/closures/closure-no-fn-3.stderr
+++ b/src/test/ui/closures/closure-no-fn-3.stderr
@@ -2,9 +2,7 @@ error[E0605]: non-primitive cast: `[closure@$DIR/closure-no-fn-3.rs:6:27: 6:37 b
--> $DIR/closure-no-fn-3.rs:6:27
|
LL | let baz: fn() -> u8 = (|| { b }) as fn() -> u8;
- | ^^^^^^^^^^^^^^^^^^^^^^^^
- |
- = note: an `as` expression can only be used to convert between primitive types. Consider using the `From` trait
+ | ^^^^^^^^^^^^^^^^^^^^^^^^ invalid cast
error: aborting due to previous error
diff --git a/src/test/ui/coercion/coerce-to-bang-cast.stderr b/src/test/ui/coercion/coerce-to-bang-cast.stderr
index ff30ebc09c63a..d3adbd5158dbb 100644
--- a/src/test/ui/coercion/coerce-to-bang-cast.stderr
+++ b/src/test/ui/coercion/coerce-to-bang-cast.stderr
@@ -2,17 +2,13 @@ error[E0605]: non-primitive cast: `i32` as `!`
--> $DIR/coerce-to-bang-cast.rs:6:13
|
LL | let y = {return; 22} as !;
- | ^^^^^^^^^^^^^^^^^
- |
- = note: an `as` expression can only be used to convert between primitive types. Consider using the `From` trait
+ | ^^^^^^^^^^^^^^^^^ an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object
error[E0605]: non-primitive cast: `i32` as `!`
--> $DIR/coerce-to-bang-cast.rs:11:13
|
LL | let y = 22 as !;
- | ^^^^^^^
- |
- = note: an `as` expression can only be used to convert between primitive types. Consider using the `From` trait
+ | ^^^^^^^ an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object
error: aborting due to 2 previous errors
diff --git a/src/test/ui/consts/const-eval/const-eval-overflow-4b.stderr b/src/test/ui/consts/const-eval/const-eval-overflow-4b.stderr
index 5b2c4116c4b1d..e4d256c0ad192 100644
--- a/src/test/ui/consts/const-eval/const-eval-overflow-4b.stderr
+++ b/src/test/ui/consts/const-eval/const-eval-overflow-4b.stderr
@@ -16,7 +16,7 @@ error[E0604]: only `u8` can be cast as `char`, not `i8`
--> $DIR/const-eval-overflow-4b.rs:25:13
|
LL | : [u32; 5i8 as char as usize]
- | ^^^^^^^^^^^
+ | ^^^^^^^^^^^ invalid cast
error: aborting due to 3 previous errors
diff --git a/src/test/ui/error-codes/E0604.stderr b/src/test/ui/error-codes/E0604.stderr
index 5861bdcb7a953..18835310bd5e8 100644
--- a/src/test/ui/error-codes/E0604.stderr
+++ b/src/test/ui/error-codes/E0604.stderr
@@ -2,7 +2,7 @@ error[E0604]: only `u8` can be cast as `char`, not `u32`
--> $DIR/E0604.rs:2:5
|
LL | 1u32 as char;
- | ^^^^^^^^^^^^
+ | ^^^^^^^^^^^^ invalid cast
error: aborting due to previous error
diff --git a/src/test/ui/error-codes/E0605.stderr b/src/test/ui/error-codes/E0605.stderr
index 95e899db8b7e9..f23d2008e0b5f 100644
--- a/src/test/ui/error-codes/E0605.stderr
+++ b/src/test/ui/error-codes/E0605.stderr
@@ -2,17 +2,13 @@ error[E0605]: non-primitive cast: `u8` as `std::vec::Vec`
--> $DIR/E0605.rs:3:5
|
LL | x as Vec;
- | ^^^^^^^^^^^^
- |
- = note: an `as` expression can only be used to convert between primitive types. Consider using the `From` trait
+ | ^^^^^^^^^^^^ an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object
error[E0605]: non-primitive cast: `*const u8` as `&u8`
--> $DIR/E0605.rs:6:5
|
LL | v as &u8;
- | ^^^^^^^^
- |
- = note: an `as` expression can only be used to convert between primitive types. Consider using the `From` trait
+ | ^^^^^^^^ an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object
error: aborting due to 2 previous errors
diff --git a/src/test/ui/error-festival.stderr b/src/test/ui/error-festival.stderr
index 7f524230ef006..905195d4ad963 100644
--- a/src/test/ui/error-festival.stderr
+++ b/src/test/ui/error-festival.stderr
@@ -42,15 +42,13 @@ error[E0604]: only `u8` can be cast as `char`, not `u32`
--> $DIR/error-festival.rs:25:5
|
LL | 0u32 as char;
- | ^^^^^^^^^^^^
+ | ^^^^^^^^^^^^ invalid cast
error[E0605]: non-primitive cast: `u8` as `std::vec::Vec`
--> $DIR/error-festival.rs:29:5
|
LL | x as Vec;
- | ^^^^^^^^^^^^
- |
- = note: an `as` expression can only be used to convert between primitive types. Consider using the `From` trait
+ | ^^^^^^^^^^^^ an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object
error[E0054]: cannot cast as `bool`
--> $DIR/error-festival.rs:33:24
diff --git a/src/test/ui/fat-ptr-cast.stderr b/src/test/ui/fat-ptr-cast.stderr
index 93e1471838f72..56d5a26beb04e 100644
--- a/src/test/ui/fat-ptr-cast.stderr
+++ b/src/test/ui/fat-ptr-cast.stderr
@@ -34,9 +34,7 @@ error[E0605]: non-primitive cast: `std::boxed::Box<[i32]>` as `usize`
--> $DIR/fat-ptr-cast.rs:14:5
|
LL | b as usize;
- | ^^^^^^^^^^
- |
- = note: an `as` expression can only be used to convert between primitive types. Consider using the `From` trait
+ | ^^^^^^^^^^ an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object
error[E0606]: casting `*const [i32]` as `usize` is invalid
--> $DIR/fat-ptr-cast.rs:15:5
diff --git a/src/test/ui/issues/issue-10991.stderr b/src/test/ui/issues/issue-10991.stderr
index f12539b47cf44..5b8a182338693 100644
--- a/src/test/ui/issues/issue-10991.stderr
+++ b/src/test/ui/issues/issue-10991.stderr
@@ -2,9 +2,7 @@ error[E0605]: non-primitive cast: `()` as `usize`
--> $DIR/issue-10991.rs:3:14
|
LL | let _t = nil as usize;
- | ^^^^^^^^^^^^
- |
- = note: an `as` expression can only be used to convert between primitive types. Consider using the `From` trait
+ | ^^^^^^^^^^^^ an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object
error: aborting due to previous error
diff --git a/src/test/ui/issues/issue-16048.rs b/src/test/ui/issues/issue-16048.rs
index 7d24f3a40a742..eaf6acff26bf3 100644
--- a/src/test/ui/issues/issue-16048.rs
+++ b/src/test/ui/issues/issue-16048.rs
@@ -18,12 +18,12 @@ impl<'a> Test<'a> for Foo<'a> {
}
impl<'a> NoLifetime for Foo<'a> {
- fn get<'p, T : Test<'a>>(&self) -> T {
+ fn get<'p, T: Test<'a> + From>>(&self) -> T {
//~^ ERROR E0195
//~| NOTE lifetimes do not match method in trait
return *self as T;
//~^ ERROR non-primitive cast: `Foo<'a>` as `T`
- //~| NOTE an `as` expression can only be used to convert between primitive types.
+ //~| NOTE an `as` expression can only be used to convert between primitive types
}
}
diff --git a/src/test/ui/issues/issue-16048.stderr b/src/test/ui/issues/issue-16048.stderr
index a137bcdf1915e..73610942d7a7e 100644
--- a/src/test/ui/issues/issue-16048.stderr
+++ b/src/test/ui/issues/issue-16048.stderr
@@ -4,16 +4,16 @@ error[E0195]: lifetime parameters or bounds on method `get` do not match the tra
LL | fn get<'p, T : Test<'p>>(&self) -> T;
| ------------------ lifetimes in impl do not match this method in trait
...
-LL | fn get<'p, T : Test<'a>>(&self) -> T {
- | ^^^^^^^^^^^^^^^^^^ lifetimes do not match method in trait
+LL | fn get<'p, T: Test<'a> + From>>(&self) -> T {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ lifetimes do not match method in trait
error[E0605]: non-primitive cast: `Foo<'a>` as `T`
--> $DIR/issue-16048.rs:24:16
|
LL | return *self as T;
- | ^^^^^^^^^^
+ | ^^^^^^^^^^ help: consider using the `From` trait instead: `T::from(*self)`
|
- = note: an `as` expression can only be used to convert between primitive types. Consider using the `From` trait
+ = note: an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object
error: aborting due to 2 previous errors
diff --git a/src/test/ui/issues/issue-17441.stderr b/src/test/ui/issues/issue-17441.stderr
index 0ab035515a051..b63a3995d255d 100644
--- a/src/test/ui/issues/issue-17441.stderr
+++ b/src/test/ui/issues/issue-17441.stderr
@@ -16,7 +16,7 @@ error[E0620]: cast to unsized type: `std::boxed::Box` as `dyn std::fmt::D
LL | let _bar = Box::new(1_usize) as dyn std::fmt::Debug;
| ^^^^^^^^^^^^^^^^^^^^^-------------------
| |
- | help: try casting to a `Box` instead: `Box`
+ | help: you can cast to a `Box` instead: `Box`
error[E0620]: cast to unsized type: `usize` as `dyn std::fmt::Debug`
--> $DIR/issue-17441.rs:8:16
diff --git a/src/test/ui/issues/issue-22289.stderr b/src/test/ui/issues/issue-22289.stderr
index cc7ace30cabef..4c35deb1fbe4e 100644
--- a/src/test/ui/issues/issue-22289.stderr
+++ b/src/test/ui/issues/issue-22289.stderr
@@ -2,9 +2,12 @@ error[E0605]: non-primitive cast: `i32` as `&(dyn std::any::Any + 'static)`
--> $DIR/issue-22289.rs:2:5
|
LL | 0 as &dyn std::any::Any;
- | ^^^^^^^^^^^^^^^^^^^^^^^
+ | ^^^^^^^^^^^^^^^^^^^^^^^ invalid cast
|
- = note: an `as` expression can only be used to convert between primitive types. Consider using the `From` trait
+help: borrow the value for the cast to be valid
+ |
+LL | &0 as &dyn std::any::Any;
+ | ^
error: aborting due to previous error
diff --git a/src/test/ui/issues/issue-22312.rs b/src/test/ui/issues/issue-22312.rs
index 250fec2588702..4e359b3412a71 100644
--- a/src/test/ui/issues/issue-22312.rs
+++ b/src/test/ui/issues/issue-22312.rs
@@ -1,6 +1,6 @@
use std::ops::Index;
-pub trait Array2D: Index {
+pub trait Array2D: Index + Sized {
fn rows(&self) -> usize;
fn columns(&self) -> usize;
fn get<'a>(&'a self, y: usize, x: usize) -> Option<&'a >::Output> {
diff --git a/src/test/ui/issues/issue-22312.stderr b/src/test/ui/issues/issue-22312.stderr
index fc32fd376b75a..28564b074633b 100644
--- a/src/test/ui/issues/issue-22312.stderr
+++ b/src/test/ui/issues/issue-22312.stderr
@@ -2,9 +2,12 @@ error[E0605]: non-primitive cast: `Self` as `&dyn std::ops::Index $DIR/issue-22312.rs:11:24
|
LL | let indexer = &(*self as &dyn Index>::Output>);
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ invalid cast
|
- = note: an `as` expression can only be used to convert between primitive types. Consider using the `From` trait
+help: borrow the value for the cast to be valid
+ |
+LL | let indexer = &(&*self as &dyn Index>::Output>);
+ | ^
error: aborting due to previous error
diff --git a/src/test/ui/issues/issue-2995.stderr b/src/test/ui/issues/issue-2995.stderr
index c316780d5f6a5..9f5968399a37d 100644
--- a/src/test/ui/issues/issue-2995.stderr
+++ b/src/test/ui/issues/issue-2995.stderr
@@ -2,9 +2,7 @@ error[E0605]: non-primitive cast: `*const isize` as `&isize`
--> $DIR/issue-2995.rs:2:22
|
LL | let _q: &isize = p as &isize;
- | ^^^^^^^^^^^
- |
- = note: an `as` expression can only be used to convert between primitive types. Consider using the `From` trait
+ | ^^^^^^^^^^^ an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object
error: aborting due to previous error
diff --git a/src/test/ui/issues/issue-45730.stderr b/src/test/ui/issues/issue-45730.stderr
index d4ddba52df14a..d00f3d91b49da 100644
--- a/src/test/ui/issues/issue-45730.stderr
+++ b/src/test/ui/issues/issue-45730.stderr
@@ -1,30 +1,24 @@
error[E0641]: cannot cast to a pointer of an unknown kind
- --> $DIR/issue-45730.rs:3:23
+ --> $DIR/issue-45730.rs:3:28
|
LL | let x: *const _ = 0 as _;
- | ^^^^^-
- | |
- | help: consider giving more type information
+ | ^ needs more type information
|
= note: the type information given here is insufficient to check whether the pointer cast is valid
error[E0641]: cannot cast to a pointer of an unknown kind
- --> $DIR/issue-45730.rs:5:23
+ --> $DIR/issue-45730.rs:5:28
|
LL | let x: *const _ = 0 as *const _;
- | ^^^^^--------
- | |
- | help: consider giving more type information
+ | ^^^^^^^^ needs more type information
|
= note: the type information given here is insufficient to check whether the pointer cast is valid
error[E0641]: cannot cast to a pointer of an unknown kind
- --> $DIR/issue-45730.rs:8:13
+ --> $DIR/issue-45730.rs:8:44
|
LL | let x = 0 as *const i32 as *const _ as *mut _;
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^------
- | |
- | help: consider giving more type information
+ | ^^^^^^ needs more type information
|
= note: the type information given here is insufficient to check whether the pointer cast is valid
diff --git a/src/test/ui/mismatched_types/cast-rfc0401.stderr b/src/test/ui/mismatched_types/cast-rfc0401.stderr
index f94dfd100a6f4..95936de218b8f 100644
--- a/src/test/ui/mismatched_types/cast-rfc0401.stderr
+++ b/src/test/ui/mismatched_types/cast-rfc0401.stderr
@@ -24,41 +24,31 @@ error[E0605]: non-primitive cast: `*const u8` as `&u8`
--> $DIR/cast-rfc0401.rs:29:13
|
LL | let _ = v as &u8;
- | ^^^^^^^^
- |
- = note: an `as` expression can only be used to convert between primitive types. Consider using the `From` trait
+ | ^^^^^^^^ an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object
error[E0605]: non-primitive cast: `*const u8` as `E`
--> $DIR/cast-rfc0401.rs:30:13
|
LL | let _ = v as E;
- | ^^^^^^
- |
- = note: an `as` expression can only be used to convert between primitive types. Consider using the `From` trait
+ | ^^^^^^ an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object
error[E0605]: non-primitive cast: `*const u8` as `fn()`
--> $DIR/cast-rfc0401.rs:31:13
|
LL | let _ = v as fn();
- | ^^^^^^^^^
- |
- = note: an `as` expression can only be used to convert between primitive types. Consider using the `From` trait
+ | ^^^^^^^^^ invalid cast
error[E0605]: non-primitive cast: `*const u8` as `(u32,)`
--> $DIR/cast-rfc0401.rs:32:13
|
LL | let _ = v as (u32,);
- | ^^^^^^^^^^^
- |
- = note: an `as` expression can only be used to convert between primitive types. Consider using the `From` trait
+ | ^^^^^^^^^^^ an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object
error[E0605]: non-primitive cast: `std::option::Option<&*const u8>` as `*const u8`
--> $DIR/cast-rfc0401.rs:33:13
|
LL | let _ = Some(&v) as *const u8;
- | ^^^^^^^^^^^^^^^^^^^^^
- |
- = note: an `as` expression can only be used to convert between primitive types. Consider using the `From` trait
+ | ^^^^^^^^^^^^^^^^^^^^^ an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object
error[E0606]: casting `*const u8` as `f32` is invalid
--> $DIR/cast-rfc0401.rs:35:13
@@ -102,7 +92,7 @@ error[E0604]: only `u8` can be cast as `char`, not `u32`
--> $DIR/cast-rfc0401.rs:41:13
|
LL | let _ = 0x61u32 as char;
- | ^^^^^^^^^^^^^^^
+ | ^^^^^^^^^^^^^^^ invalid cast
error[E0606]: casting `bool` as `f32` is invalid
--> $DIR/cast-rfc0401.rs:43:13
diff --git a/src/test/ui/mismatched_types/issue-26480.stderr b/src/test/ui/mismatched_types/issue-26480.stderr
index 69a9d03e474ba..d39b0a3207763 100644
--- a/src/test/ui/mismatched_types/issue-26480.stderr
+++ b/src/test/ui/mismatched_types/issue-26480.stderr
@@ -17,12 +17,11 @@ error[E0605]: non-primitive cast: `{integer}` as `()`
--> $DIR/issue-26480.rs:22:19
|
LL | ($x:expr) => ($x as ())
- | ^^^^^^^^
+ | ^^^^^^^^ an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object
...
LL | cast!(2);
| --------- in this macro invocation
|
- = note: an `as` expression can only be used to convert between primitive types. Consider using the `From` trait
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
error: aborting due to 2 previous errors
diff --git a/src/test/ui/nonscalar-cast.fixed b/src/test/ui/nonscalar-cast.fixed
new file mode 100644
index 0000000000000..0a4b98469b2b6
--- /dev/null
+++ b/src/test/ui/nonscalar-cast.fixed
@@ -0,0 +1,16 @@
+// run-rustfix
+
+#[derive(Debug)]
+struct Foo {
+ x: isize
+}
+
+impl From for isize {
+ fn from(val: Foo) -> isize {
+ val.x
+ }
+}
+
+fn main() {
+ println!("{}", isize::from(Foo { x: 1 })); //~ non-primitive cast: `Foo` as `isize` [E0605]
+}
diff --git a/src/test/ui/nonscalar-cast.rs b/src/test/ui/nonscalar-cast.rs
index 7e6f1fd038fb7..59fcf09666b24 100644
--- a/src/test/ui/nonscalar-cast.rs
+++ b/src/test/ui/nonscalar-cast.rs
@@ -1,8 +1,16 @@
+// run-rustfix
+
#[derive(Debug)]
struct Foo {
x: isize
}
+impl From for isize {
+ fn from(val: Foo) -> isize {
+ val.x
+ }
+}
+
fn main() {
println!("{}", Foo { x: 1 } as isize); //~ non-primitive cast: `Foo` as `isize` [E0605]
}
diff --git a/src/test/ui/nonscalar-cast.stderr b/src/test/ui/nonscalar-cast.stderr
index 9338688b037ff..2a7037121876d 100644
--- a/src/test/ui/nonscalar-cast.stderr
+++ b/src/test/ui/nonscalar-cast.stderr
@@ -1,10 +1,10 @@
error[E0605]: non-primitive cast: `Foo` as `isize`
- --> $DIR/nonscalar-cast.rs:7:20
+ --> $DIR/nonscalar-cast.rs:15:20
|
LL | println!("{}", Foo { x: 1 } as isize);
- | ^^^^^^^^^^^^^^^^^^^^^
+ | ^^^^^^^^^^^^^^^^^^^^^ help: consider using the `From` trait instead: `isize::from(Foo { x: 1 })`
|
- = note: an `as` expression can only be used to convert between primitive types. Consider using the `From` trait
+ = note: an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object
error: aborting due to previous error
diff --git a/src/test/ui/order-dependent-cast-inference.stderr b/src/test/ui/order-dependent-cast-inference.stderr
index ad50b415869dd..9f4ac0fea36ef 100644
--- a/src/test/ui/order-dependent-cast-inference.stderr
+++ b/src/test/ui/order-dependent-cast-inference.stderr
@@ -1,10 +1,8 @@
error[E0641]: cannot cast to a pointer of an unknown kind
- --> $DIR/order-dependent-cast-inference.rs:5:17
+ --> $DIR/order-dependent-cast-inference.rs:5:22
|
LL | let mut y = 0 as *const _;
- | ^^^^^--------
- | |
- | help: consider giving more type information
+ | ^^^^^^^^ needs more type information
|
= note: the type information given here is insufficient to check whether the pointer cast is valid
diff --git a/src/test/ui/tag-variant-cast-non-nullary.fixed b/src/test/ui/tag-variant-cast-non-nullary.fixed
new file mode 100644
index 0000000000000..53e68c2ac6af6
--- /dev/null
+++ b/src/test/ui/tag-variant-cast-non-nullary.fixed
@@ -0,0 +1,20 @@
+// run-rustfix
+#![allow(dead_code, unused_variables)]
+enum NonNullary {
+ Nullary,
+ Other(isize),
+}
+
+impl From for isize {
+ fn from(val: NonNullary) -> isize {
+ match val {
+ NonNullary::Nullary => 0,
+ NonNullary::Other(i) => i,
+ }
+ }
+}
+
+fn main() {
+ let v = NonNullary::Nullary;
+ let val = isize::from(v); //~ ERROR non-primitive cast: `NonNullary` as `isize` [E0605]
+}
diff --git a/src/test/ui/tag-variant-cast-non-nullary.rs b/src/test/ui/tag-variant-cast-non-nullary.rs
index bb34e82cdca37..0d0c6188ad114 100644
--- a/src/test/ui/tag-variant-cast-non-nullary.rs
+++ b/src/test/ui/tag-variant-cast-non-nullary.rs
@@ -1,8 +1,19 @@
+// run-rustfix
+#![allow(dead_code, unused_variables)]
enum NonNullary {
Nullary,
Other(isize),
}
+impl From for isize {
+ fn from(val: NonNullary) -> isize {
+ match val {
+ NonNullary::Nullary => 0,
+ NonNullary::Other(i) => i,
+ }
+ }
+}
+
fn main() {
let v = NonNullary::Nullary;
let val = v as isize; //~ ERROR non-primitive cast: `NonNullary` as `isize` [E0605]
diff --git a/src/test/ui/tag-variant-cast-non-nullary.stderr b/src/test/ui/tag-variant-cast-non-nullary.stderr
index 87ec20f20d789..ae2f5a7aead55 100644
--- a/src/test/ui/tag-variant-cast-non-nullary.stderr
+++ b/src/test/ui/tag-variant-cast-non-nullary.stderr
@@ -1,10 +1,10 @@
error[E0605]: non-primitive cast: `NonNullary` as `isize`
- --> $DIR/tag-variant-cast-non-nullary.rs:8:15
+ --> $DIR/tag-variant-cast-non-nullary.rs:19:15
|
LL | let val = v as isize;
- | ^^^^^^^^^^
+ | ^^^^^^^^^^ help: consider using the `From` trait instead: `isize::from(v)`
|
- = note: an `as` expression can only be used to convert between primitive types. Consider using the `From` trait
+ = note: an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object
error: aborting due to previous error
diff --git a/src/test/ui/type-alias-impl-trait/never_reveal_concrete_type.stderr b/src/test/ui/type-alias-impl-trait/never_reveal_concrete_type.stderr
index 70c99c944d654..360633bba622b 100644
--- a/src/test/ui/type-alias-impl-trait/never_reveal_concrete_type.stderr
+++ b/src/test/ui/type-alias-impl-trait/never_reveal_concrete_type.stderr
@@ -16,9 +16,7 @@ error[E0605]: non-primitive cast: `NoReveal` as `&'static str`
--> $DIR/never_reveal_concrete_type.rs:14:13
|
LL | let _ = x as &'static str;
- | ^^^^^^^^^^^^^^^^^
- |
- = note: an `as` expression can only be used to convert between primitive types. Consider using the `From` trait
+ | ^^^^^^^^^^^^^^^^^ an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object
error: aborting due to 2 previous errors
diff --git a/src/test/ui/uninhabited/uninhabited-enum-cast.stderr b/src/test/ui/uninhabited/uninhabited-enum-cast.stderr
index a39af7832f8c9..a9f10dfec994a 100644
--- a/src/test/ui/uninhabited/uninhabited-enum-cast.stderr
+++ b/src/test/ui/uninhabited/uninhabited-enum-cast.stderr
@@ -2,9 +2,7 @@ error[E0605]: non-primitive cast: `E` as `isize`
--> $DIR/uninhabited-enum-cast.rs:4:20
|
LL | println!("{}", (e as isize).to_string());
- | ^^^^^^^^^^^^
- |
- = note: an `as` expression can only be used to convert between primitive types. Consider using the `From` trait
+ | ^^^^^^^^^^^^ an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object
error: aborting due to previous error
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 21/52] 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 22/52] 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 23/52] 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 24/52] 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 25/52] 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