Skip to content

Commit 33b0b71

Browse files
committed
Auto merge of #57792 - Centril:rollup, r=Centril
Rollup of 5 pull requests Successful merges: - #56796 (Change bounds on `TryFrom` blanket impl to use `Into` instead of `From`) - #57768 (Continue parsing after parent type args and suggest using angle brackets) - #57769 (Suggest correct cast for struct fields with shorthand syntax) - #57783 (Add "dereference boxed value" suggestion.) - #57784 (Add span for bad doc comment) Failed merges: r? @ghost
2 parents b5f5a27 + 00c60d1 commit 33b0b71

36 files changed

+484
-88
lines changed

Diff for: src/libcore/convert.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -463,11 +463,11 @@ impl<T, U> TryInto<U> for T where U: TryFrom<T>
463463
// Infallible conversions are semantically equivalent to fallible conversions
464464
// with an uninhabited error type.
465465
#[unstable(feature = "try_from", issue = "33417")]
466-
impl<T, U> TryFrom<U> for T where T: From<U> {
466+
impl<T, U> TryFrom<U> for T where U: Into<T> {
467467
type Error = !;
468468

469469
fn try_from(value: U) -> Result<Self, Self::Error> {
470-
Ok(T::from(value))
470+
Ok(U::into(value))
471471
}
472472
}
473473

Diff for: src/librustc/hir/lowering.rs

+21-5
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
//! in the HIR, especially for multiple identifiers.
3232
3333
use dep_graph::DepGraph;
34+
use errors::Applicability;
3435
use hir::{self, ParamName};
3536
use hir::HirVec;
3637
use hir::map::{DefKey, DefPathData, Definitions};
@@ -1806,7 +1807,7 @@ impl<'a> LoweringContext<'a> {
18061807
explicit_owner: Option<NodeId>,
18071808
) -> hir::PathSegment {
18081809
let (mut generic_args, infer_types) = if let Some(ref generic_args) = segment.args {
1809-
let msg = "parenthesized parameters may only be used with a trait";
1810+
let msg = "parenthesized type parameters may only be used with a `Fn` trait";
18101811
match **generic_args {
18111812
GenericArgs::AngleBracketed(ref data) => {
18121813
self.lower_angle_bracketed_parameter_data(data, param_mode, itctx)
@@ -1823,10 +1824,25 @@ impl<'a> LoweringContext<'a> {
18231824
(hir::GenericArgs::none(), true)
18241825
}
18251826
ParenthesizedGenericArgs::Err => {
1826-
struct_span_err!(self.sess, data.span, E0214, "{}", msg)
1827-
.span_label(data.span, "only traits may use parentheses")
1828-
.emit();
1829-
(hir::GenericArgs::none(), true)
1827+
let mut err = struct_span_err!(self.sess, data.span, E0214, "{}", msg);
1828+
err.span_label(data.span, "only `Fn` traits may use parentheses");
1829+
if let Ok(snippet) = self.sess.source_map().span_to_snippet(data.span) {
1830+
// Do not suggest going from `Trait()` to `Trait<>`
1831+
if data.inputs.len() > 0 {
1832+
err.span_suggestion_with_applicability(
1833+
data.span,
1834+
"use angle brackets instead",
1835+
format!("<{}>", &snippet[1..snippet.len() - 1]),
1836+
Applicability::MaybeIncorrect,
1837+
);
1838+
}
1839+
};
1840+
err.emit();
1841+
(self.lower_angle_bracketed_parameter_data(
1842+
&data.as_angle_bracketed_args(),
1843+
param_mode,
1844+
itctx).0,
1845+
false)
18301846
}
18311847
},
18321848
}

Diff for: src/librustc/infer/error_reporting/mod.rs

+19-2
Original file line numberDiff line numberDiff line change
@@ -485,12 +485,29 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
485485
}
486486
}
487487

488-
fn note_error_origin(&self, err: &mut DiagnosticBuilder<'tcx>, cause: &ObligationCause<'tcx>) {
488+
fn note_error_origin(
489+
&self,
490+
err: &mut DiagnosticBuilder<'tcx>,
491+
cause: &ObligationCause<'tcx>,
492+
exp_found: Option<ty::error::ExpectedFound<Ty<'tcx>>>,
493+
) {
489494
match cause.code {
490495
ObligationCauseCode::MatchExpressionArmPattern { span, ty } => {
491496
if ty.is_suggestable() { // don't show type `_`
492497
err.span_label(span, format!("this match expression has type `{}`", ty));
493498
}
499+
if let Some(ty::error::ExpectedFound { found, .. }) = exp_found {
500+
if ty.is_box() && ty.boxed_ty() == found {
501+
if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span) {
502+
err.span_suggestion_with_applicability(
503+
span,
504+
"consider dereferencing the boxed value",
505+
format!("*{}", snippet),
506+
Applicability::MachineApplicable,
507+
);
508+
}
509+
}
510+
}
494511
}
495512
ObligationCauseCode::MatchExpressionArm { arm_span, source } => match source {
496513
hir::MatchSource::IfLetDesugar { .. } => {
@@ -1013,7 +1030,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
10131030

10141031
// It reads better to have the error origin as the final
10151032
// thing.
1016-
self.note_error_origin(diag, &cause);
1033+
self.note_error_origin(diag, &cause, exp_found);
10171034
}
10181035

10191036
/// When encountering a case where `.as_ref()` on a `Result` or `Option` would be appropriate,

Diff for: src/librustc_typeck/check/demand.rs

+36-12
Original file line numberDiff line numberDiff line change
@@ -454,12 +454,13 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
454454
false
455455
}
456456

457-
pub fn check_for_cast(&self,
458-
err: &mut DiagnosticBuilder<'tcx>,
459-
expr: &hir::Expr,
460-
checked_ty: Ty<'tcx>,
461-
expected_ty: Ty<'tcx>)
462-
-> bool {
457+
pub fn check_for_cast(
458+
&self,
459+
err: &mut DiagnosticBuilder<'tcx>,
460+
expr: &hir::Expr,
461+
checked_ty: Ty<'tcx>,
462+
expected_ty: Ty<'tcx>,
463+
) -> bool {
463464
let parent_id = self.tcx.hir().get_parent_node(expr.id);
464465
if let Some(parent) = self.tcx.hir().find(parent_id) {
465466
// Shouldn't suggest `.into()` on `const`s.
@@ -487,17 +488,40 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
487488
// For now, don't suggest casting with `as`.
488489
let can_cast = false;
489490

491+
let mut prefix = String::new();
492+
if let Some(hir::Node::Expr(hir::Expr {
493+
node: hir::ExprKind::Struct(_, fields, _),
494+
..
495+
})) = self.tcx.hir().find(self.tcx.hir().get_parent_node(expr.id)) {
496+
// `expr` is a literal field for a struct, only suggest if appropriate
497+
for field in fields {
498+
if field.expr.id == expr.id && field.is_shorthand {
499+
// This is a field literal
500+
prefix = format!("{}: ", field.ident);
501+
break;
502+
}
503+
}
504+
if &prefix == "" {
505+
// Likely a field was meant, but this field wasn't found. Do not suggest anything.
506+
return false;
507+
}
508+
}
509+
490510
let needs_paren = expr.precedence().order() < (PREC_POSTFIX as i8);
491511

492512
if let Ok(src) = self.tcx.sess.source_map().span_to_snippet(expr.span) {
493513
let msg = format!("you can cast an `{}` to `{}`", checked_ty, expected_ty);
494-
let cast_suggestion = format!("{}{}{} as {}",
495-
if needs_paren { "(" } else { "" },
496-
src,
497-
if needs_paren { ")" } else { "" },
498-
expected_ty);
514+
let cast_suggestion = format!(
515+
"{}{}{}{} as {}",
516+
prefix,
517+
if needs_paren { "(" } else { "" },
518+
src,
519+
if needs_paren { ")" } else { "" },
520+
expected_ty,
521+
);
499522
let into_suggestion = format!(
500-
"{}{}{}.into()",
523+
"{}{}{}{}.into()",
524+
prefix,
501525
if needs_paren { "(" } else { "" },
502526
src,
503527
if needs_paren { ")" } else { "" },

Diff for: src/libsyntax/ast.rs

+10
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,16 @@ pub struct ParenthesisedArgs {
192192
pub output: Option<P<Ty>>,
193193
}
194194

195+
impl ParenthesisedArgs {
196+
pub fn as_angle_bracketed_args(&self) -> AngleBracketedArgs {
197+
AngleBracketedArgs {
198+
span: self.span,
199+
args: self.inputs.iter().cloned().map(|input| GenericArg::Type(input)).collect(),
200+
bindings: vec![],
201+
}
202+
}
203+
}
204+
195205
// hack to ensure that we don't try to access the private parts of `NodeId` in this module
196206
mod node_id_inner {
197207
use rustc_data_structures::indexed_vec::Idx;

Diff for: src/libsyntax/parse/parser.rs

+9-5
Original file line numberDiff line numberDiff line change
@@ -2176,11 +2176,11 @@ impl<'a> Parser<'a> {
21762176
style != PathStyle::Mod && self.check(&token::ModSep)
21772177
&& self.look_ahead(1, |t| is_args_start(t)) {
21782178
// Generic arguments are found - `<`, `(`, `::<` or `::(`.
2179-
let lo = self.span;
21802179
if self.eat(&token::ModSep) && style == PathStyle::Type && enable_warning {
21812180
self.diagnostic().struct_span_warn(self.prev_span, "unnecessary path disambiguator")
21822181
.span_label(self.prev_span, "try removing `::`").emit();
21832182
}
2183+
let lo = self.span;
21842184

21852185
let args = if self.eat_lt() {
21862186
// `<'a, T, A = U>`
@@ -4483,13 +4483,17 @@ impl<'a> Parser<'a> {
44834483
}
44844484

44854485
/// Emit an expected item after attributes error.
4486-
fn expected_item_err(&self, attrs: &[Attribute]) {
4486+
fn expected_item_err(&mut self, attrs: &[Attribute]) -> PResult<'a, ()> {
44874487
let message = match attrs.last() {
44884488
Some(&Attribute { is_sugared_doc: true, .. }) => "expected item after doc comment",
44894489
_ => "expected item after attributes",
44904490
};
44914491

4492-
self.span_err(self.prev_span, message);
4492+
let mut err = self.diagnostic().struct_span_err(self.prev_span, message);
4493+
if attrs.last().unwrap().is_sugared_doc {
4494+
err.span_label(self.prev_span, "this doc comment doesn't document anything");
4495+
}
4496+
Err(err)
44934497
}
44944498

44954499
/// Parse a statement. This stops just before trailing semicolons on everything but items.
@@ -7636,7 +7640,7 @@ impl<'a> Parser<'a> {
76367640
}
76377641
None => {
76387642
if !attrs.is_empty() {
7639-
self.expected_item_err(&attrs);
7643+
self.expected_item_err(&attrs)?;
76407644
}
76417645

76427646
self.unexpected()
@@ -7699,7 +7703,7 @@ impl<'a> Parser<'a> {
76997703
}
77007704

77017705
if !attributes_allowed && !attrs.is_empty() {
7702-
self.expected_item_err(&attrs);
7706+
self.expected_item_err(&attrs)?;
77037707
}
77047708
Ok(None)
77057709
}

Diff for: src/test/run-pass/try_from.rs

+37
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
// This test relies on `TryFrom` being blanket impl for all `T: Into`
2+
// and `TryInto` being blanket impl for all `U: TryFrom`
3+
4+
// This test was added to show the motivation for doing this
5+
// over `TryFrom` being blanket impl for all `T: From`
6+
7+
#![feature(try_from, never_type)]
8+
9+
use std::convert::TryInto;
10+
11+
struct Foo<T> {
12+
t: T,
13+
}
14+
15+
// This fails to compile due to coherence restrictions
16+
// as of Rust version 1.32.x, therefore it could not be used
17+
// instead of the `Into` version of the impl, and serves as
18+
// motivation for a blanket impl for all `T: Into`, instead
19+
// of a blanket impl for all `T: From`
20+
/*
21+
impl<T> From<Foo<T>> for Box<T> {
22+
fn from(foo: Foo<T>) -> Box<T> {
23+
Box::new(foo.t)
24+
}
25+
}
26+
*/
27+
28+
impl<T> Into<Vec<T>> for Foo<T> {
29+
fn into(self) -> Vec<T> {
30+
vec![self.t]
31+
}
32+
}
33+
34+
pub fn main() {
35+
let _: Result<Vec<i32>, !> = Foo { t: 10 }.try_into();
36+
}
37+

Diff for: src/test/ui/e0119/conflict-with-std.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ LL | impl TryFrom<X> for X { //~ ERROR conflicting implementations
2525
|
2626
= note: conflicting implementation in crate `core`:
2727
- impl<T, U> std::convert::TryFrom<U> for T
28-
where T: std::convert::From<U>;
28+
where U: std::convert::Into<T>;
2929

3030
error: aborting due to 3 previous errors
3131

Diff for: src/test/ui/error-codes/E0214.stderr

+5-2
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
1-
error[E0214]: parenthesized parameters may only be used with a trait
1+
error[E0214]: parenthesized type parameters may only be used with a `Fn` trait
22
--> $DIR/E0214.rs:2:15
33
|
44
LL | let v: Vec(&str) = vec!["foo"];
5-
| ^^^^^^ only traits may use parentheses
5+
| ^^^^^^
6+
| |
7+
| only `Fn` traits may use parentheses
8+
| help: use angle brackets instead: `<&str>`
69

710
error: aborting due to previous error
811

Diff for: src/test/ui/issues/issue-23589.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
fn main() {
22
let v: Vec(&str) = vec!['1', '2'];
3-
//~^ ERROR parenthesized parameters may only be used with a trait
3+
//~^ ERROR parenthesized type parameters may only be used with a `Fn` trait
4+
//~| ERROR mismatched types
45
}

Diff for: src/test/ui/issues/issue-23589.stderr

+17-4
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,22 @@
1-
error[E0214]: parenthesized parameters may only be used with a trait
1+
error[E0214]: parenthesized type parameters may only be used with a `Fn` trait
22
--> $DIR/issue-23589.rs:2:15
33
|
44
LL | let v: Vec(&str) = vec!['1', '2'];
5-
| ^^^^^^ only traits may use parentheses
5+
| ^^^^^^
6+
| |
7+
| only `Fn` traits may use parentheses
8+
| help: use angle brackets instead: `<&str>`
69

7-
error: aborting due to previous error
10+
error[E0308]: mismatched types
11+
--> $DIR/issue-23589.rs:2:29
12+
|
13+
LL | let v: Vec(&str) = vec!['1', '2'];
14+
| ^^^ expected &str, found char
15+
|
16+
= note: expected type `&str`
17+
found type `char`
18+
19+
error: aborting due to 2 previous errors
820

9-
For more information about this error, try `rustc --explain E0214`.
21+
Some errors occurred: E0214, E0308.
22+
For more information about an error, try `rustc --explain E0214`.

Diff for: src/test/ui/issues/issue-32995-2.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,17 @@
22

33
fn main() {
44
{ fn f<X: ::std::marker()::Send>() {} }
5-
//~^ ERROR parenthesized parameters may only be used with a trait
5+
//~^ ERROR parenthesized type parameters may only be used with a `Fn` trait
66
//~| WARN previously accepted
77

88
{ fn f() -> impl ::std::marker()::Send { } }
9-
//~^ ERROR parenthesized parameters may only be used with a trait
9+
//~^ ERROR parenthesized type parameters may only be used with a `Fn` trait
1010
//~| WARN previously accepted
1111
}
1212

1313
#[derive(Clone)]
1414
struct X;
1515

1616
impl ::std::marker()::Copy for X {}
17-
//~^ ERROR parenthesized parameters may only be used with a trait
17+
//~^ ERROR parenthesized type parameters may only be used with a `Fn` trait
1818
//~| WARN previously accepted

Diff for: src/test/ui/issues/issue-32995-2.stderr

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
error: parenthesized parameters may only be used with a trait
1+
error: parenthesized type parameters may only be used with a `Fn` trait
22
--> $DIR/issue-32995-2.rs:4:28
33
|
44
LL | { fn f<X: ::std::marker()::Send>() {} }
@@ -8,7 +8,7 @@ LL | { fn f<X: ::std::marker()::Send>() {} }
88
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
99
= note: for more information, see issue #42238 <https://github.com/rust-lang/rust/issues/42238>
1010

11-
error: parenthesized parameters may only be used with a trait
11+
error: parenthesized type parameters may only be used with a `Fn` trait
1212
--> $DIR/issue-32995-2.rs:8:35
1313
|
1414
LL | { fn f() -> impl ::std::marker()::Send { } }
@@ -17,7 +17,7 @@ LL | { fn f() -> impl ::std::marker()::Send { } }
1717
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
1818
= note: for more information, see issue #42238 <https://github.com/rust-lang/rust/issues/42238>
1919

20-
error: parenthesized parameters may only be used with a trait
20+
error: parenthesized type parameters may only be used with a `Fn` trait
2121
--> $DIR/issue-32995-2.rs:16:19
2222
|
2323
LL | impl ::std::marker()::Copy for X {}

0 commit comments

Comments
 (0)