From f8bd80a830509d4356b76bc44a50c798db1bb3ea Mon Sep 17 00:00:00 2001 From: Ozaren Date: Thu, 13 Dec 2018 16:53:50 -0500 Subject: [PATCH 01/15] Change bounds on `TryFrom` blanket impl to use `Into` instead of `From` --- src/libcore/convert.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libcore/convert.rs b/src/libcore/convert.rs index 2d4813718f41a..18ead0877fe85 100644 --- a/src/libcore/convert.rs +++ b/src/libcore/convert.rs @@ -476,11 +476,11 @@ impl TryInto for T where U: TryFrom // Infallible conversions are semantically equivalent to fallible conversions // with an uninhabited error type. #[unstable(feature = "try_from", issue = "33417")] -impl TryFrom for T where T: From { +impl TryFrom for T where U: Into { type Error = !; fn try_from(value: U) -> Result { - Ok(T::from(value)) + Ok(U::into(value)) } } From 7a25a7ce8df3ba8b41915e240fedd8bf94867137 Mon Sep 17 00:00:00 2001 From: Ozaren Date: Sun, 16 Dec 2018 13:01:26 -0500 Subject: [PATCH 02/15] Changed expected error message for TryFrom Reason: Due to changes in bounds of `TryFrom` from `From` to `Into` --- src/test/ui/e0119/conflict-with-std.stderr | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/ui/e0119/conflict-with-std.stderr b/src/test/ui/e0119/conflict-with-std.stderr index e8b2c84c0df0b..8ca085c3a4bbf 100644 --- a/src/test/ui/e0119/conflict-with-std.stderr +++ b/src/test/ui/e0119/conflict-with-std.stderr @@ -25,7 +25,7 @@ LL | impl TryFrom for X { //~ ERROR conflicting implementations | = note: conflicting implementation in crate `core`: - impl std::convert::TryFrom for T - where T: std::convert::From; + where T: std::convert::Into; error: aborting due to 3 previous errors From a1be81300fdc6906dc3cb19019747e622901badc Mon Sep 17 00:00:00 2001 From: Ozaren Date: Sun, 16 Dec 2018 13:59:12 -0500 Subject: [PATCH 03/15] Fixed `Into` bound on `TryFrom` error. fix to last commit --- src/test/ui/e0119/conflict-with-std.stderr | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/ui/e0119/conflict-with-std.stderr b/src/test/ui/e0119/conflict-with-std.stderr index 8ca085c3a4bbf..fd016941d258e 100644 --- a/src/test/ui/e0119/conflict-with-std.stderr +++ b/src/test/ui/e0119/conflict-with-std.stderr @@ -25,7 +25,7 @@ LL | impl TryFrom for X { //~ ERROR conflicting implementations | = note: conflicting implementation in crate `core`: - impl std::convert::TryFrom for T - where T: std::convert::Into; + where U: std::convert::Into; error: aborting due to 3 previous errors From db9fe1c86ea3c45a459f2ff63db2aef658ee3b7f Mon Sep 17 00:00:00 2001 From: Ozaren Date: Tue, 18 Dec 2018 23:18:20 -0500 Subject: [PATCH 04/15] added test to show motivation for modified TryFrom impl --- src/test/run-pass/try_from.rs | 43 +++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) create mode 100644 src/test/run-pass/try_from.rs diff --git a/src/test/run-pass/try_from.rs b/src/test/run-pass/try_from.rs new file mode 100644 index 0000000000000..3f2eb98f861a0 --- /dev/null +++ b/src/test/run-pass/try_from.rs @@ -0,0 +1,43 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// This test relies on `TryFrom` being auto impl for all `T: Into` +// and `TryInto` being auto impl for all `U: TryFrom` + +// This test was added to show the motivation for doing this +// over `TryFrom` being auto impl for all `T: From` + +#![feature(try_from, never_type)] + +use std::convert::TryInto; + +struct Foo { + t: T +} + +/* +// This fails to compile due to coherence restrictions +// as of rust version 1.32.x +impl From> for Box { + fn from(foo: Foo) -> Box { + Box::new(foo.t) + } +} +*/ + +impl Into> for Foo { + fn into(self) -> Box { + Box::new(self.t) + } +} + +pub fn main() { + let _: Result, !> = Foo { t: 10 }.try_into(); +} From 7dd078f53f4e1817207b089fb08d6a00121ca05b Mon Sep 17 00:00:00 2001 From: Ozaren Date: Wed, 19 Dec 2018 00:19:07 -0500 Subject: [PATCH 05/15] fixed test, now it doesn't use a fundemental type i.e. `Box`, instead it now uses `Vec` --- src/test/run-pass/try_from.rs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/test/run-pass/try_from.rs b/src/test/run-pass/try_from.rs index 3f2eb98f861a0..767c2b9147174 100644 --- a/src/test/run-pass/try_from.rs +++ b/src/test/run-pass/try_from.rs @@ -32,12 +32,13 @@ impl From> for Box { } */ -impl Into> for Foo { - fn into(self) -> Box { - Box::new(self.t) +impl Into> for Foo { + fn into(self) -> Vec { + vec![self.t] } } pub fn main() { - let _: Result, !> = Foo { t: 10 }.try_into(); + let _: Result, !> = Foo { t: 10 }.try_into(); } + From ea68b3ff3dd5a49c5984c476570fb5404c342079 Mon Sep 17 00:00:00 2001 From: Ozaren Date: Wed, 2 Jan 2019 20:38:50 -0500 Subject: [PATCH 06/15] update to reflect changes recommended by @shepmaster his review --- src/test/run-pass/try_from.rs | 25 +++++++++---------------- 1 file changed, 9 insertions(+), 16 deletions(-) diff --git a/src/test/run-pass/try_from.rs b/src/test/run-pass/try_from.rs index 767c2b9147174..4522ce3a8d617 100644 --- a/src/test/run-pass/try_from.rs +++ b/src/test/run-pass/try_from.rs @@ -1,30 +1,23 @@ -// Copyright 2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// This test relies on `TryFrom` being auto impl for all `T: Into` -// and `TryInto` being auto impl for all `U: TryFrom` +// This test relies on `TryFrom` being blanket impl for all `T: Into` +// and `TryInto` being blanket impl for all `U: TryFrom` // This test was added to show the motivation for doing this -// over `TryFrom` being auto impl for all `T: From` +// over `TryFrom` being blanket impl for all `T: From` #![feature(try_from, never_type)] use std::convert::TryInto; struct Foo { - t: T + t: T, } -/* // This fails to compile due to coherence restrictions -// as of rust version 1.32.x +// as of Rust version 1.32.x, therefore it could not be used +// instead of the `Into` version of the impl, and serves as +// motivation for a blanket impl for all `T: Into`, instead +// of a blanket impl for all `T: From` +/* impl From> for Box { fn from(foo: Foo) -> Box { Box::new(foo.t) From d38e70036eee2187d93d8d760461a79aaa84489f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Sat, 19 Jan 2019 14:48:43 -0800 Subject: [PATCH 07/15] Continune parsing after encountering Trait with paren args --- src/librustc/hir/lowering.rs | 2 +- src/test/ui/error-codes/E0214.stderr | 11 +++++++++-- src/test/ui/issues/issue-23589.stderr | 11 +++++++++-- .../unboxed-closure-sugar-used-on-struct-1.stderr | 11 +++++++++-- .../unboxed-closure-sugar-used-on-struct-3.stderr | 11 +++++++++-- .../unboxed-closure-sugar-used-on-struct.stderr | 8 ++++---- 6 files changed, 41 insertions(+), 13 deletions(-) diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index 2f7d8f0984e6f..b8aeb6032ba65 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -1826,7 +1826,7 @@ impl<'a> LoweringContext<'a> { struct_span_err!(self.sess, data.span, E0214, "{}", msg) .span_label(data.span, "only traits may use parentheses") .emit(); - (hir::GenericArgs::none(), true) + (hir::GenericArgs::none(), false) } }, } diff --git a/src/test/ui/error-codes/E0214.stderr b/src/test/ui/error-codes/E0214.stderr index 08a98b1c3bf3d..f87502efe1b10 100644 --- a/src/test/ui/error-codes/E0214.stderr +++ b/src/test/ui/error-codes/E0214.stderr @@ -4,6 +4,13 @@ error[E0214]: parenthesized parameters may only be used with a trait LL | let v: Vec(&str) = vec!["foo"]; | ^^^^^^ only traits may use parentheses -error: aborting due to previous error +error[E0107]: wrong number of type arguments: expected 1, found 0 + --> $DIR/E0214.rs:2:12 + | +LL | let v: Vec(&str) = vec!["foo"]; + | ^^^^^^^^^ expected 1 type argument + +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0214`. +Some errors occurred: E0107, E0214. +For more information about an error, try `rustc --explain E0107`. diff --git a/src/test/ui/issues/issue-23589.stderr b/src/test/ui/issues/issue-23589.stderr index e6e07c167f349..15f2c524a7a9f 100644 --- a/src/test/ui/issues/issue-23589.stderr +++ b/src/test/ui/issues/issue-23589.stderr @@ -4,6 +4,13 @@ error[E0214]: parenthesized parameters may only be used with a trait LL | let v: Vec(&str) = vec!['1', '2']; | ^^^^^^ only traits may use parentheses -error: aborting due to previous error +error[E0107]: wrong number of type arguments: expected 1, found 0 + --> $DIR/issue-23589.rs:2:12 + | +LL | let v: Vec(&str) = vec!['1', '2']; + | ^^^^^^^^^ expected 1 type argument + +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0214`. +Some errors occurred: E0107, E0214. +For more information about an error, try `rustc --explain E0107`. diff --git a/src/test/ui/unboxed-closures/unboxed-closure-sugar-used-on-struct-1.stderr b/src/test/ui/unboxed-closures/unboxed-closure-sugar-used-on-struct-1.stderr index 3f1b37c282b7c..ab2a6f03cf7e7 100644 --- a/src/test/ui/unboxed-closures/unboxed-closure-sugar-used-on-struct-1.stderr +++ b/src/test/ui/unboxed-closures/unboxed-closure-sugar-used-on-struct-1.stderr @@ -4,6 +4,13 @@ error[E0214]: parenthesized parameters may only be used with a trait LL | let x: Box = panic!(); | ^^ only traits may use parentheses -error: aborting due to previous error +error[E0107]: wrong number of type arguments: expected 1, found 0 + --> $DIR/unboxed-closure-sugar-used-on-struct-1.rs:8:16 + | +LL | let x: Box = panic!(); + | ^^^^^ expected 1 type argument + +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0214`. +Some errors occurred: E0107, E0214. +For more information about an error, try `rustc --explain E0107`. diff --git a/src/test/ui/unboxed-closures/unboxed-closure-sugar-used-on-struct-3.stderr b/src/test/ui/unboxed-closures/unboxed-closure-sugar-used-on-struct-3.stderr index 395f6596cfd83..b4f7a97c3e5fb 100644 --- a/src/test/ui/unboxed-closures/unboxed-closure-sugar-used-on-struct-3.stderr +++ b/src/test/ui/unboxed-closures/unboxed-closure-sugar-used-on-struct-3.stderr @@ -4,6 +4,13 @@ error[E0214]: parenthesized parameters may only be used with a trait LL | let b = Bar::(isize, usize)::new(); // OK too (for the parser) | ^^^^^^^^^^^^^^^^ only traits may use parentheses -error: aborting due to previous error +error[E0107]: wrong number of type arguments: expected 2, found 0 + --> $DIR/unboxed-closure-sugar-used-on-struct-3.rs:14:13 + | +LL | let b = Bar::(isize, usize)::new(); // OK too (for the parser) + | ^^^^^^^^^^^^^^^^^^^^^^^^ expected 2 type arguments + +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0214`. +Some errors occurred: E0107, E0214. +For more information about an error, try `rustc --explain E0107`. diff --git a/src/test/ui/unboxed-closures/unboxed-closure-sugar-used-on-struct.stderr b/src/test/ui/unboxed-closures/unboxed-closure-sugar-used-on-struct.stderr index d0267092030d8..7bcf86774c7be 100644 --- a/src/test/ui/unboxed-closures/unboxed-closure-sugar-used-on-struct.stderr +++ b/src/test/ui/unboxed-closures/unboxed-closure-sugar-used-on-struct.stderr @@ -4,13 +4,13 @@ error[E0214]: parenthesized parameters may only be used with a trait LL | fn foo(b: Box) { | ^^ only traits may use parentheses -error[E0121]: the type placeholder `_` is not allowed within types on item signatures +error[E0107]: wrong number of type arguments: expected 1, found 0 --> $DIR/unboxed-closure-sugar-used-on-struct.rs:7:15 | LL | fn foo(b: Box) { - | ^^^^^ not allowed in type signatures + | ^^^^^ expected 1 type argument error: aborting due to 2 previous errors -Some errors occurred: E0121, E0214. -For more information about an error, try `rustc --explain E0121`. +Some errors occurred: E0107, E0214. +For more information about an error, try `rustc --explain E0107`. From 3235446b397a06596063f237ae864de8d95799e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Sat, 19 Jan 2019 18:44:20 -0800 Subject: [PATCH 08/15] Accept parenthesized type args for error recovery --- src/librustc/hir/lowering.rs | 6 +++++- src/libsyntax/ast.rs | 10 ++++++++++ src/test/ui/error-codes/E0214.stderr | 11 ++--------- src/test/ui/issues/issue-23589.rs | 1 + src/test/ui/issues/issue-23589.stderr | 13 ++++++++----- .../unboxed-closure-sugar-used-on-struct-1.rs | 1 + .../unboxed-closure-sugar-used-on-struct-3.stderr | 11 ++--------- .../unboxed-closure-sugar-used-on-struct.rs | 2 +- 8 files changed, 30 insertions(+), 25 deletions(-) diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index b8aeb6032ba65..b7624b09eeea9 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -1826,7 +1826,11 @@ impl<'a> LoweringContext<'a> { struct_span_err!(self.sess, data.span, E0214, "{}", msg) .span_label(data.span, "only traits may use parentheses") .emit(); - (hir::GenericArgs::none(), false) + (self.lower_angle_bracketed_parameter_data( + &data.as_angle_bracketed_args(), + param_mode, + itctx).0, + false) } }, } diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index bbcaaacbab523..d57f9247c0520 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -192,6 +192,16 @@ pub struct ParenthesisedArgs { pub output: Option>, } +impl ParenthesisedArgs { + pub fn as_angle_bracketed_args(&self) -> AngleBracketedArgs { + AngleBracketedArgs { + span: self.span, + args: self.inputs.iter().cloned().map(|input| GenericArg::Type(input)).collect(), + bindings: vec![], + } + } +} + // hack to ensure that we don't try to access the private parts of `NodeId` in this module mod node_id_inner { use rustc_data_structures::indexed_vec::Idx; diff --git a/src/test/ui/error-codes/E0214.stderr b/src/test/ui/error-codes/E0214.stderr index f87502efe1b10..08a98b1c3bf3d 100644 --- a/src/test/ui/error-codes/E0214.stderr +++ b/src/test/ui/error-codes/E0214.stderr @@ -4,13 +4,6 @@ error[E0214]: parenthesized parameters may only be used with a trait LL | let v: Vec(&str) = vec!["foo"]; | ^^^^^^ only traits may use parentheses -error[E0107]: wrong number of type arguments: expected 1, found 0 - --> $DIR/E0214.rs:2:12 - | -LL | let v: Vec(&str) = vec!["foo"]; - | ^^^^^^^^^ expected 1 type argument - -error: aborting due to 2 previous errors +error: aborting due to previous error -Some errors occurred: E0107, E0214. -For more information about an error, try `rustc --explain E0107`. +For more information about this error, try `rustc --explain E0214`. diff --git a/src/test/ui/issues/issue-23589.rs b/src/test/ui/issues/issue-23589.rs index a59710a1a3cde..fb765e453dcd6 100644 --- a/src/test/ui/issues/issue-23589.rs +++ b/src/test/ui/issues/issue-23589.rs @@ -1,4 +1,5 @@ fn main() { let v: Vec(&str) = vec!['1', '2']; //~^ ERROR parenthesized parameters may only be used with a trait + //~| ERROR mismatched types } diff --git a/src/test/ui/issues/issue-23589.stderr b/src/test/ui/issues/issue-23589.stderr index 15f2c524a7a9f..c71061606df51 100644 --- a/src/test/ui/issues/issue-23589.stderr +++ b/src/test/ui/issues/issue-23589.stderr @@ -4,13 +4,16 @@ error[E0214]: parenthesized parameters may only be used with a trait LL | let v: Vec(&str) = vec!['1', '2']; | ^^^^^^ only traits may use parentheses -error[E0107]: wrong number of type arguments: expected 1, found 0 - --> $DIR/issue-23589.rs:2:12 +error[E0308]: mismatched types + --> $DIR/issue-23589.rs:2:29 | LL | let v: Vec(&str) = vec!['1', '2']; - | ^^^^^^^^^ expected 1 type argument + | ^^^ expected &str, found char + | + = note: expected type `&str` + found type `char` error: aborting due to 2 previous errors -Some errors occurred: E0107, E0214. -For more information about an error, try `rustc --explain E0107`. +Some errors occurred: E0214, E0308. +For more information about an error, try `rustc --explain E0214`. diff --git a/src/test/ui/unboxed-closures/unboxed-closure-sugar-used-on-struct-1.rs b/src/test/ui/unboxed-closures/unboxed-closure-sugar-used-on-struct-1.rs index 5387dcb218cb9..2827e6eead5fd 100644 --- a/src/test/ui/unboxed-closures/unboxed-closure-sugar-used-on-struct-1.rs +++ b/src/test/ui/unboxed-closures/unboxed-closure-sugar-used-on-struct-1.rs @@ -7,6 +7,7 @@ struct Bar { fn bar() { let x: Box = panic!(); //~^ ERROR parenthesized parameters may only be used with a trait + //~| ERROR wrong number of type arguments: expected 1, found 0 } fn main() { } diff --git a/src/test/ui/unboxed-closures/unboxed-closure-sugar-used-on-struct-3.stderr b/src/test/ui/unboxed-closures/unboxed-closure-sugar-used-on-struct-3.stderr index b4f7a97c3e5fb..395f6596cfd83 100644 --- a/src/test/ui/unboxed-closures/unboxed-closure-sugar-used-on-struct-3.stderr +++ b/src/test/ui/unboxed-closures/unboxed-closure-sugar-used-on-struct-3.stderr @@ -4,13 +4,6 @@ error[E0214]: parenthesized parameters may only be used with a trait LL | let b = Bar::(isize, usize)::new(); // OK too (for the parser) | ^^^^^^^^^^^^^^^^ only traits may use parentheses -error[E0107]: wrong number of type arguments: expected 2, found 0 - --> $DIR/unboxed-closure-sugar-used-on-struct-3.rs:14:13 - | -LL | let b = Bar::(isize, usize)::new(); // OK too (for the parser) - | ^^^^^^^^^^^^^^^^^^^^^^^^ expected 2 type arguments - -error: aborting due to 2 previous errors +error: aborting due to previous error -Some errors occurred: E0107, E0214. -For more information about an error, try `rustc --explain E0107`. +For more information about this error, try `rustc --explain E0214`. diff --git a/src/test/ui/unboxed-closures/unboxed-closure-sugar-used-on-struct.rs b/src/test/ui/unboxed-closures/unboxed-closure-sugar-used-on-struct.rs index e795650447cc4..6da53585c9c4c 100644 --- a/src/test/ui/unboxed-closures/unboxed-closure-sugar-used-on-struct.rs +++ b/src/test/ui/unboxed-closures/unboxed-closure-sugar-used-on-struct.rs @@ -6,7 +6,7 @@ struct Bar { fn foo(b: Box) { //~^ ERROR parenthesized parameters may only be used with a trait - //~| ERROR the type placeholder `_` is not allowed within types on item signatures + //~| ERROR wrong number of type arguments: expected 1, found 0 } fn main() { } From d37a6d83e1626db51041b6337328cde603f1bc19 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Sat, 19 Jan 2019 19:25:28 -0800 Subject: [PATCH 09/15] Suggest usage of angle brackets --- src/librustc/hir/lowering.rs | 15 ++++++++++++--- src/libsyntax/parse/parser.rs | 2 +- src/test/ui/error-codes/E0214.stderr | 5 ++++- src/test/ui/issues/issue-23589.stderr | 5 ++++- src/test/ui/issues/issue-32995.stderr | 8 ++++---- .../parser/type-parameters-in-field-exprs.stderr | 12 ++++++------ src/test/ui/span/macro-ty-params.stderr | 8 ++++---- .../unboxed-closure-sugar-used-on-struct-1.stderr | 5 ++++- .../unboxed-closure-sugar-used-on-struct-3.stderr | 7 +++++-- .../unboxed-closure-sugar-used-on-struct.stderr | 5 ++++- 10 files changed, 48 insertions(+), 24 deletions(-) diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index b7624b09eeea9..9d3438289a0cd 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -31,6 +31,7 @@ //! in the HIR, especially for multiple identifiers. use dep_graph::DepGraph; +use errors::Applicability; use hir::{self, ParamName}; use hir::HirVec; use hir::map::{DefKey, DefPathData, Definitions}; @@ -1823,9 +1824,17 @@ impl<'a> LoweringContext<'a> { (hir::GenericArgs::none(), true) } ParenthesizedGenericArgs::Err => { - struct_span_err!(self.sess, data.span, E0214, "{}", msg) - .span_label(data.span, "only traits may use parentheses") - .emit(); + let mut err = struct_span_err!(self.sess, data.span, E0214, "{}", msg); + err.span_label(data.span, "only traits may use parentheses"); + if let Ok(snippet) = self.sess.source_map().span_to_snippet(data.span) { + err.span_suggestion_with_applicability( + data.span, + "use angle brackets instead", + format!("<{}>", &snippet[1..snippet.len() - 1]), + Applicability::MaybeIncorrect, + ); + }; + err.emit(); (self.lower_angle_bracketed_parameter_data( &data.as_angle_bracketed_args(), param_mode, diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 7e15b23127655..e09b7a9dd7b7f 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -2176,11 +2176,11 @@ impl<'a> Parser<'a> { style != PathStyle::Mod && self.check(&token::ModSep) && self.look_ahead(1, |t| is_args_start(t)) { // Generic arguments are found - `<`, `(`, `::<` or `::(`. - let lo = self.span; if self.eat(&token::ModSep) && style == PathStyle::Type && enable_warning { self.diagnostic().struct_span_warn(self.prev_span, "unnecessary path disambiguator") .span_label(self.prev_span, "try removing `::`").emit(); } + let lo = self.span; let args = if self.eat_lt() { // `<'a, T, A = U>` diff --git a/src/test/ui/error-codes/E0214.stderr b/src/test/ui/error-codes/E0214.stderr index 08a98b1c3bf3d..0172dc706ac5f 100644 --- a/src/test/ui/error-codes/E0214.stderr +++ b/src/test/ui/error-codes/E0214.stderr @@ -2,7 +2,10 @@ error[E0214]: parenthesized parameters may only be used with a trait --> $DIR/E0214.rs:2:15 | LL | let v: Vec(&str) = vec!["foo"]; - | ^^^^^^ only traits may use parentheses + | ^^^^^^ + | | + | only traits may use parentheses + | help: use angle brackets instead: `<&str>` error: aborting due to previous error diff --git a/src/test/ui/issues/issue-23589.stderr b/src/test/ui/issues/issue-23589.stderr index c71061606df51..932e8eedad1ca 100644 --- a/src/test/ui/issues/issue-23589.stderr +++ b/src/test/ui/issues/issue-23589.stderr @@ -2,7 +2,10 @@ error[E0214]: parenthesized parameters may only be used with a trait --> $DIR/issue-23589.rs:2:15 | LL | let v: Vec(&str) = vec!['1', '2']; - | ^^^^^^ only traits may use parentheses + | ^^^^^^ + | | + | only traits may use parentheses + | help: use angle brackets instead: `<&str>` error[E0308]: mismatched types --> $DIR/issue-23589.rs:2:29 diff --git a/src/test/ui/issues/issue-32995.stderr b/src/test/ui/issues/issue-32995.stderr index 12551bb7f1f00..e27f2d9553a93 100644 --- a/src/test/ui/issues/issue-32995.stderr +++ b/src/test/ui/issues/issue-32995.stderr @@ -18,19 +18,19 @@ LL | let b: ::std::boxed()::Box<_> = Box::new(1); = note: for more information, see issue #42238 error: parenthesized parameters may only be used with a trait - --> $DIR/issue-32995.rs:12:23 + --> $DIR/issue-32995.rs:12:25 | LL | let p = ::std::str::()::from_utf8(b"foo").unwrap(); - | ^^^^ + | ^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #42238 error: parenthesized parameters may only be used with a trait - --> $DIR/issue-32995.rs:16:34 + --> $DIR/issue-32995.rs:16:36 | LL | let p = ::std::str::from_utf8::()(b"foo").unwrap(); - | ^^^^ + | ^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #42238 diff --git a/src/test/ui/parser/type-parameters-in-field-exprs.stderr b/src/test/ui/parser/type-parameters-in-field-exprs.stderr index e68e1f3204ade..2183c74da0acb 100644 --- a/src/test/ui/parser/type-parameters-in-field-exprs.stderr +++ b/src/test/ui/parser/type-parameters-in-field-exprs.stderr @@ -1,20 +1,20 @@ error: field expressions may not have generic arguments - --> $DIR/type-parameters-in-field-exprs.rs:13:8 + --> $DIR/type-parameters-in-field-exprs.rs:13:10 | LL | f.x::; - | ^^^^^^^^^ + | ^^^^^^^ error: field expressions may not have generic arguments - --> $DIR/type-parameters-in-field-exprs.rs:15:8 + --> $DIR/type-parameters-in-field-exprs.rs:15:10 | LL | f.x::<>; - | ^^^^ + | ^^ error: field expressions may not have generic arguments - --> $DIR/type-parameters-in-field-exprs.rs:17:8 + --> $DIR/type-parameters-in-field-exprs.rs:17:10 | LL | f.x::(); - | ^^^^ + | ^^ error: aborting due to 3 previous errors diff --git a/src/test/ui/span/macro-ty-params.stderr b/src/test/ui/span/macro-ty-params.stderr index 23fdde06e8f9d..965ca7000be80 100644 --- a/src/test/ui/span/macro-ty-params.stderr +++ b/src/test/ui/span/macro-ty-params.stderr @@ -1,14 +1,14 @@ error: generic arguments in macro path - --> $DIR/macro-ty-params.rs:10:8 + --> $DIR/macro-ty-params.rs:10:10 | LL | foo::!(); //~ ERROR generic arguments in macro path - | ^^^^^ + | ^^^ error: generic arguments in macro path - --> $DIR/macro-ty-params.rs:11:8 + --> $DIR/macro-ty-params.rs:11:10 | LL | foo::<>!(); //~ ERROR generic arguments in macro path - | ^^^^ + | ^^ error: unexpected generic arguments in path --> $DIR/macro-ty-params.rs:12:8 diff --git a/src/test/ui/unboxed-closures/unboxed-closure-sugar-used-on-struct-1.stderr b/src/test/ui/unboxed-closures/unboxed-closure-sugar-used-on-struct-1.stderr index ab2a6f03cf7e7..87832d839b949 100644 --- a/src/test/ui/unboxed-closures/unboxed-closure-sugar-used-on-struct-1.stderr +++ b/src/test/ui/unboxed-closures/unboxed-closure-sugar-used-on-struct-1.stderr @@ -2,7 +2,10 @@ error[E0214]: parenthesized parameters may only be used with a trait --> $DIR/unboxed-closure-sugar-used-on-struct-1.rs:8:19 | LL | let x: Box = panic!(); - | ^^ only traits may use parentheses + | ^^ + | | + | only traits may use parentheses + | help: use angle brackets instead: `<>` error[E0107]: wrong number of type arguments: expected 1, found 0 --> $DIR/unboxed-closure-sugar-used-on-struct-1.rs:8:16 diff --git a/src/test/ui/unboxed-closures/unboxed-closure-sugar-used-on-struct-3.stderr b/src/test/ui/unboxed-closures/unboxed-closure-sugar-used-on-struct-3.stderr index 395f6596cfd83..c9cc60717a610 100644 --- a/src/test/ui/unboxed-closures/unboxed-closure-sugar-used-on-struct-3.stderr +++ b/src/test/ui/unboxed-closures/unboxed-closure-sugar-used-on-struct-3.stderr @@ -1,8 +1,11 @@ error[E0214]: parenthesized parameters may only be used with a trait - --> $DIR/unboxed-closure-sugar-used-on-struct-3.rs:14:16 + --> $DIR/unboxed-closure-sugar-used-on-struct-3.rs:14:18 | LL | let b = Bar::(isize, usize)::new(); // OK too (for the parser) - | ^^^^^^^^^^^^^^^^ only traits may use parentheses + | ^^^^^^^^^^^^^^ + | | + | only traits may use parentheses + | help: use angle brackets instead: `` error: aborting due to previous error diff --git a/src/test/ui/unboxed-closures/unboxed-closure-sugar-used-on-struct.stderr b/src/test/ui/unboxed-closures/unboxed-closure-sugar-used-on-struct.stderr index 7bcf86774c7be..a09c2b75386eb 100644 --- a/src/test/ui/unboxed-closures/unboxed-closure-sugar-used-on-struct.stderr +++ b/src/test/ui/unboxed-closures/unboxed-closure-sugar-used-on-struct.stderr @@ -2,7 +2,10 @@ error[E0214]: parenthesized parameters may only be used with a trait --> $DIR/unboxed-closure-sugar-used-on-struct.rs:7:18 | LL | fn foo(b: Box) { - | ^^ only traits may use parentheses + | ^^ + | | + | only traits may use parentheses + | help: use angle brackets instead: `<>` error[E0107]: wrong number of type arguments: expected 1, found 0 --> $DIR/unboxed-closure-sugar-used-on-struct.rs:7:15 From b36bf76dec593269b3c5006c38063315bed5ad51 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Sat, 19 Jan 2019 20:18:56 -0800 Subject: [PATCH 10/15] Suggest correct cast for struct fields with shorthand syntax --- src/librustc_typeck/check/demand.rs | 48 ++++++++++++++----- .../type-mismatch-struct-field-shorthand-2.rs | 9 ++++ ...e-mismatch-struct-field-shorthand-2.stderr | 30 ++++++++++++ ...type-mismatch-struct-field-shorthand.fixed | 12 +++++ .../type-mismatch-struct-field-shorthand.rs | 12 +++++ ...ype-mismatch-struct-field-shorthand.stderr | 33 +++++++++++++ 6 files changed, 132 insertions(+), 12 deletions(-) create mode 100644 src/test/ui/suggestions/type-mismatch-struct-field-shorthand-2.rs create mode 100644 src/test/ui/suggestions/type-mismatch-struct-field-shorthand-2.stderr create mode 100644 src/test/ui/suggestions/type-mismatch-struct-field-shorthand.fixed create mode 100644 src/test/ui/suggestions/type-mismatch-struct-field-shorthand.rs create mode 100644 src/test/ui/suggestions/type-mismatch-struct-field-shorthand.stderr diff --git a/src/librustc_typeck/check/demand.rs b/src/librustc_typeck/check/demand.rs index c0cedd77440d9..2aecc0f2ace6a 100644 --- a/src/librustc_typeck/check/demand.rs +++ b/src/librustc_typeck/check/demand.rs @@ -454,12 +454,13 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { false } - pub fn check_for_cast(&self, - err: &mut DiagnosticBuilder<'tcx>, - expr: &hir::Expr, - checked_ty: Ty<'tcx>, - expected_ty: Ty<'tcx>) - -> bool { + pub fn check_for_cast( + &self, + err: &mut DiagnosticBuilder<'tcx>, + expr: &hir::Expr, + checked_ty: Ty<'tcx>, + expected_ty: Ty<'tcx>, + ) -> bool { let parent_id = self.tcx.hir().get_parent_node(expr.id); if let Some(parent) = self.tcx.hir().find(parent_id) { // Shouldn't suggest `.into()` on `const`s. @@ -487,17 +488,40 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // For now, don't suggest casting with `as`. let can_cast = false; + let mut prefix = String::new(); + if let Some(hir::Node::Expr(hir::Expr { + node: hir::ExprKind::Struct(_, fields, _), + .. + })) = self.tcx.hir().find(self.tcx.hir().get_parent_node(expr.id)) { + // `expr` is a literal field for a struct, only suggest if appropriate + for field in fields { + if field.expr.id == expr.id { + // This is a field literal + prefix = format!("{}: ", field.ident); + break; + } + } + if &prefix == "" { + // Likely a field was meant, but this field wasn't found. Do not suggest anything. + return false; + } + } + let needs_paren = expr.precedence().order() < (PREC_POSTFIX as i8); if let Ok(src) = self.tcx.sess.source_map().span_to_snippet(expr.span) { let msg = format!("you can cast an `{}` to `{}`", checked_ty, expected_ty); - let cast_suggestion = format!("{}{}{} as {}", - if needs_paren { "(" } else { "" }, - src, - if needs_paren { ")" } else { "" }, - expected_ty); + let cast_suggestion = format!( + "{}{}{}{} as {}", + prefix, + if needs_paren { "(" } else { "" }, + src, + if needs_paren { ")" } else { "" }, + expected_ty, + ); let into_suggestion = format!( - "{}{}{}.into()", + "{}{}{}{}.into()", + prefix, if needs_paren { "(" } else { "" }, src, if needs_paren { ")" } else { "" }, diff --git a/src/test/ui/suggestions/type-mismatch-struct-field-shorthand-2.rs b/src/test/ui/suggestions/type-mismatch-struct-field-shorthand-2.rs new file mode 100644 index 0000000000000..2ce12220723df --- /dev/null +++ b/src/test/ui/suggestions/type-mismatch-struct-field-shorthand-2.rs @@ -0,0 +1,9 @@ +struct RGB { r: f64, g: f64, b: f64 } + +fn main() { + let (r, g, c): (f32, f32, f32) = (0., 0., 0.); + let _ = RGB { r, g, c }; + //~^ ERROR mismatched types + //~| ERROR mismatched types + //~| ERROR struct `RGB` has no field named `c` +} diff --git a/src/test/ui/suggestions/type-mismatch-struct-field-shorthand-2.stderr b/src/test/ui/suggestions/type-mismatch-struct-field-shorthand-2.stderr new file mode 100644 index 0000000000000..d0f9e1f7f7c8e --- /dev/null +++ b/src/test/ui/suggestions/type-mismatch-struct-field-shorthand-2.stderr @@ -0,0 +1,30 @@ +error[E0308]: mismatched types + --> $DIR/type-mismatch-struct-field-shorthand-2.rs:5:19 + | +LL | let _ = RGB { r, g, c }; + | ^ expected f64, found f32 +help: you can cast an `f32` to `f64` in a lossless way + | +LL | let _ = RGB { r: r.into(), g, c }; + | ^^^^^^^^^^^ + +error[E0308]: mismatched types + --> $DIR/type-mismatch-struct-field-shorthand-2.rs:5:22 + | +LL | let _ = RGB { r, g, c }; + | ^ expected f64, found f32 +help: you can cast an `f32` to `f64` in a lossless way + | +LL | let _ = RGB { r, g: g.into(), c }; + | ^^^^^^^^^^^ + +error[E0560]: struct `RGB` has no field named `c` + --> $DIR/type-mismatch-struct-field-shorthand-2.rs:5:25 + | +LL | let _ = RGB { r, g, c }; + | ^ help: a field with a similar name exists: `b` + +error: aborting due to 3 previous errors + +Some errors occurred: E0308, E0560. +For more information about an error, try `rustc --explain E0308`. diff --git a/src/test/ui/suggestions/type-mismatch-struct-field-shorthand.fixed b/src/test/ui/suggestions/type-mismatch-struct-field-shorthand.fixed new file mode 100644 index 0000000000000..91758c0b21882 --- /dev/null +++ b/src/test/ui/suggestions/type-mismatch-struct-field-shorthand.fixed @@ -0,0 +1,12 @@ +// run-rustfix +#![allow(dead_code)] + +struct RGB { r: f64, g: f64, b: f64 } + +fn main() { + let (r, g, b): (f32, f32, f32) = (0., 0., 0.); + let _ = RGB { r: r.into(), g: g.into(), b: b.into() }; + //~^ ERROR mismatched types + //~| ERROR mismatched types + //~| ERROR mismatched types +} diff --git a/src/test/ui/suggestions/type-mismatch-struct-field-shorthand.rs b/src/test/ui/suggestions/type-mismatch-struct-field-shorthand.rs new file mode 100644 index 0000000000000..9d3a17a72b21e --- /dev/null +++ b/src/test/ui/suggestions/type-mismatch-struct-field-shorthand.rs @@ -0,0 +1,12 @@ +// run-rustfix +#![allow(dead_code)] + +struct RGB { r: f64, g: f64, b: f64 } + +fn main() { + let (r, g, b): (f32, f32, f32) = (0., 0., 0.); + let _ = RGB { r, g, b }; + //~^ ERROR mismatched types + //~| ERROR mismatched types + //~| ERROR mismatched types +} diff --git a/src/test/ui/suggestions/type-mismatch-struct-field-shorthand.stderr b/src/test/ui/suggestions/type-mismatch-struct-field-shorthand.stderr new file mode 100644 index 0000000000000..6bc16ba8b70fa --- /dev/null +++ b/src/test/ui/suggestions/type-mismatch-struct-field-shorthand.stderr @@ -0,0 +1,33 @@ +error[E0308]: mismatched types + --> $DIR/type-mismatch-struct-field-shorthand.rs:8:19 + | +LL | let _ = RGB { r, g, b }; + | ^ expected f64, found f32 +help: you can cast an `f32` to `f64` in a lossless way + | +LL | let _ = RGB { r: r.into(), g, b }; + | ^^^^^^^^^^^ + +error[E0308]: mismatched types + --> $DIR/type-mismatch-struct-field-shorthand.rs:8:22 + | +LL | let _ = RGB { r, g, b }; + | ^ expected f64, found f32 +help: you can cast an `f32` to `f64` in a lossless way + | +LL | let _ = RGB { r, g: g.into(), b }; + | ^^^^^^^^^^^ + +error[E0308]: mismatched types + --> $DIR/type-mismatch-struct-field-shorthand.rs:8:25 + | +LL | let _ = RGB { r, g, b }; + | ^ expected f64, found f32 +help: you can cast an `f32` to `f64` in a lossless way + | +LL | let _ = RGB { r, g, b: b.into() }; + | ^^^^^^^^^^^ + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0308`. From 2ab6cefccfe3c5f2c97bf8bcab080a26089257e2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Sun, 20 Jan 2019 02:45:38 -0800 Subject: [PATCH 11/15] Do not suggest angle brackets when there are no type arguments --- src/librustc/hir/lowering.rs | 19 +++++++++++-------- src/test/ui/error-codes/E0214.stderr | 4 ++-- src/test/ui/issues/issue-23589.rs | 2 +- src/test/ui/issues/issue-23589.stderr | 4 ++-- src/test/ui/issues/issue-32995-2.rs | 6 +++--- src/test/ui/issues/issue-32995-2.stderr | 6 +++--- src/test/ui/issues/issue-32995.rs | 14 +++++++------- src/test/ui/issues/issue-32995.stderr | 14 +++++++------- .../unboxed-closure-sugar-used-on-struct-1.rs | 2 +- ...oxed-closure-sugar-used-on-struct-1.stderr | 7 ++----- .../unboxed-closure-sugar-used-on-struct-3.rs | 2 +- ...oxed-closure-sugar-used-on-struct-3.stderr | 4 ++-- .../unboxed-closure-sugar-used-on-struct.rs | 2 +- ...nboxed-closure-sugar-used-on-struct.stderr | 7 ++----- 14 files changed, 45 insertions(+), 48 deletions(-) diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index 9d3438289a0cd..f7af135bc7605 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -1807,7 +1807,7 @@ impl<'a> LoweringContext<'a> { explicit_owner: Option, ) -> hir::PathSegment { let (mut generic_args, infer_types) = if let Some(ref generic_args) = segment.args { - let msg = "parenthesized parameters may only be used with a trait"; + let msg = "parenthesized type parameters may only be used with a `Fn` trait"; match **generic_args { GenericArgs::AngleBracketed(ref data) => { self.lower_angle_bracketed_parameter_data(data, param_mode, itctx) @@ -1825,14 +1825,17 @@ impl<'a> LoweringContext<'a> { } ParenthesizedGenericArgs::Err => { let mut err = struct_span_err!(self.sess, data.span, E0214, "{}", msg); - err.span_label(data.span, "only traits may use parentheses"); + err.span_label(data.span, "only `Fn` traits may use parentheses"); if let Ok(snippet) = self.sess.source_map().span_to_snippet(data.span) { - err.span_suggestion_with_applicability( - data.span, - "use angle brackets instead", - format!("<{}>", &snippet[1..snippet.len() - 1]), - Applicability::MaybeIncorrect, - ); + // Do not suggest going from `Trait()` to `Trait<>` + if data.inputs.len() > 0 { + err.span_suggestion_with_applicability( + data.span, + "use angle brackets instead", + format!("<{}>", &snippet[1..snippet.len() - 1]), + Applicability::MaybeIncorrect, + ); + } }; err.emit(); (self.lower_angle_bracketed_parameter_data( diff --git a/src/test/ui/error-codes/E0214.stderr b/src/test/ui/error-codes/E0214.stderr index 0172dc706ac5f..a10f2c00578c6 100644 --- a/src/test/ui/error-codes/E0214.stderr +++ b/src/test/ui/error-codes/E0214.stderr @@ -1,10 +1,10 @@ -error[E0214]: parenthesized parameters may only be used with a trait +error[E0214]: parenthesized type parameters may only be used with a `Fn` trait --> $DIR/E0214.rs:2:15 | LL | let v: Vec(&str) = vec!["foo"]; | ^^^^^^ | | - | only traits may use parentheses + | only `Fn` traits may use parentheses | help: use angle brackets instead: `<&str>` error: aborting due to previous error diff --git a/src/test/ui/issues/issue-23589.rs b/src/test/ui/issues/issue-23589.rs index fb765e453dcd6..1c640af8d02b9 100644 --- a/src/test/ui/issues/issue-23589.rs +++ b/src/test/ui/issues/issue-23589.rs @@ -1,5 +1,5 @@ fn main() { let v: Vec(&str) = vec!['1', '2']; - //~^ ERROR parenthesized parameters may only be used with a trait + //~^ ERROR parenthesized type parameters may only be used with a `Fn` trait //~| ERROR mismatched types } diff --git a/src/test/ui/issues/issue-23589.stderr b/src/test/ui/issues/issue-23589.stderr index 932e8eedad1ca..bc2007ba39cc6 100644 --- a/src/test/ui/issues/issue-23589.stderr +++ b/src/test/ui/issues/issue-23589.stderr @@ -1,10 +1,10 @@ -error[E0214]: parenthesized parameters may only be used with a trait +error[E0214]: parenthesized type parameters may only be used with a `Fn` trait --> $DIR/issue-23589.rs:2:15 | LL | let v: Vec(&str) = vec!['1', '2']; | ^^^^^^ | | - | only traits may use parentheses + | only `Fn` traits may use parentheses | help: use angle brackets instead: `<&str>` error[E0308]: mismatched types diff --git a/src/test/ui/issues/issue-32995-2.rs b/src/test/ui/issues/issue-32995-2.rs index a4e333ec20ae0..2234f68f24629 100644 --- a/src/test/ui/issues/issue-32995-2.rs +++ b/src/test/ui/issues/issue-32995-2.rs @@ -2,11 +2,11 @@ fn main() { { fn f() {} } - //~^ ERROR parenthesized parameters may only be used with a trait + //~^ ERROR parenthesized type parameters may only be used with a `Fn` trait //~| WARN previously accepted { fn f() -> impl ::std::marker()::Send { } } - //~^ ERROR parenthesized parameters may only be used with a trait + //~^ ERROR parenthesized type parameters may only be used with a `Fn` trait //~| WARN previously accepted } @@ -14,5 +14,5 @@ fn main() { struct X; impl ::std::marker()::Copy for X {} -//~^ ERROR parenthesized parameters may only be used with a trait +//~^ ERROR parenthesized type parameters may only be used with a `Fn` trait //~| WARN previously accepted diff --git a/src/test/ui/issues/issue-32995-2.stderr b/src/test/ui/issues/issue-32995-2.stderr index 0ac12b78d3842..104b76cba2df9 100644 --- a/src/test/ui/issues/issue-32995-2.stderr +++ b/src/test/ui/issues/issue-32995-2.stderr @@ -1,4 +1,4 @@ -error: parenthesized parameters may only be used with a trait +error: parenthesized type parameters may only be used with a `Fn` trait --> $DIR/issue-32995-2.rs:4:28 | LL | { fn f() {} } @@ -8,7 +8,7 @@ LL | { fn f() {} } = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #42238 -error: parenthesized parameters may only be used with a trait +error: parenthesized type parameters may only be used with a `Fn` trait --> $DIR/issue-32995-2.rs:8:35 | LL | { fn f() -> impl ::std::marker()::Send { } } @@ -17,7 +17,7 @@ LL | { fn f() -> impl ::std::marker()::Send { } } = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #42238 -error: parenthesized parameters may only be used with a trait +error: parenthesized type parameters may only be used with a `Fn` trait --> $DIR/issue-32995-2.rs:16:19 | LL | impl ::std::marker()::Copy for X {} diff --git a/src/test/ui/issues/issue-32995.rs b/src/test/ui/issues/issue-32995.rs index 726cc85d3f479..c32fb63f1e584 100644 --- a/src/test/ui/issues/issue-32995.rs +++ b/src/test/ui/issues/issue-32995.rs @@ -2,32 +2,32 @@ fn main() { let x: usize() = 1; - //~^ ERROR parenthesized parameters may only be used with a trait + //~^ ERROR parenthesized type parameters may only be used with a `Fn` trait //~| WARN previously accepted let b: ::std::boxed()::Box<_> = Box::new(1); - //~^ ERROR parenthesized parameters may only be used with a trait + //~^ ERROR parenthesized type parameters may only be used with a `Fn` trait //~| WARN previously accepted let p = ::std::str::()::from_utf8(b"foo").unwrap(); - //~^ ERROR parenthesized parameters may only be used with a trait + //~^ ERROR parenthesized type parameters may only be used with a `Fn` trait //~| WARN previously accepted let p = ::std::str::from_utf8::()(b"foo").unwrap(); - //~^ ERROR parenthesized parameters may only be used with a trait + //~^ ERROR parenthesized type parameters may only be used with a `Fn` trait //~| WARN previously accepted let o : Box<::std::marker()::Send> = Box::new(1); - //~^ ERROR parenthesized parameters may only be used with a trait + //~^ ERROR parenthesized type parameters may only be used with a `Fn` trait //~| WARN previously accepted let o : Box = Box::new(1); - //~^ ERROR parenthesized parameters may only be used with a trait + //~^ ERROR parenthesized type parameters may only be used with a `Fn` trait //~| WARN previously accepted } fn foo() { let d : X() = Default::default(); - //~^ ERROR parenthesized parameters may only be used with a trait + //~^ ERROR parenthesized type parameters may only be used with a `Fn` trait //~| WARN previously accepted } diff --git a/src/test/ui/issues/issue-32995.stderr b/src/test/ui/issues/issue-32995.stderr index e27f2d9553a93..97b4b7fa76ca8 100644 --- a/src/test/ui/issues/issue-32995.stderr +++ b/src/test/ui/issues/issue-32995.stderr @@ -1,4 +1,4 @@ -error: parenthesized parameters may only be used with a trait +error: parenthesized type parameters may only be used with a `Fn` trait --> $DIR/issue-32995.rs:4:17 | LL | let x: usize() = 1; @@ -8,7 +8,7 @@ LL | let x: usize() = 1; = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #42238 -error: parenthesized parameters may only be used with a trait +error: parenthesized type parameters may only be used with a `Fn` trait --> $DIR/issue-32995.rs:8:24 | LL | let b: ::std::boxed()::Box<_> = Box::new(1); @@ -17,7 +17,7 @@ LL | let b: ::std::boxed()::Box<_> = Box::new(1); = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #42238 -error: parenthesized parameters may only be used with a trait +error: parenthesized type parameters may only be used with a `Fn` trait --> $DIR/issue-32995.rs:12:25 | LL | let p = ::std::str::()::from_utf8(b"foo").unwrap(); @@ -26,7 +26,7 @@ LL | let p = ::std::str::()::from_utf8(b"foo").unwrap(); = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #42238 -error: parenthesized parameters may only be used with a trait +error: parenthesized type parameters may only be used with a `Fn` trait --> $DIR/issue-32995.rs:16:36 | LL | let p = ::std::str::from_utf8::()(b"foo").unwrap(); @@ -35,7 +35,7 @@ LL | let p = ::std::str::from_utf8::()(b"foo").unwrap(); = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #42238 -error: parenthesized parameters may only be used with a trait +error: parenthesized type parameters may only be used with a `Fn` trait --> $DIR/issue-32995.rs:20:30 | LL | let o : Box<::std::marker()::Send> = Box::new(1); @@ -44,7 +44,7 @@ LL | let o : Box<::std::marker()::Send> = Box::new(1); = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #42238 -error: parenthesized parameters may only be used with a trait +error: parenthesized type parameters may only be used with a `Fn` trait --> $DIR/issue-32995.rs:24:37 | LL | let o : Box = Box::new(1); @@ -53,7 +53,7 @@ LL | let o : Box = Box::new(1); = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #42238 -error: parenthesized parameters may only be used with a trait +error: parenthesized type parameters may only be used with a `Fn` trait --> $DIR/issue-32995.rs:30:14 | LL | let d : X() = Default::default(); diff --git a/src/test/ui/unboxed-closures/unboxed-closure-sugar-used-on-struct-1.rs b/src/test/ui/unboxed-closures/unboxed-closure-sugar-used-on-struct-1.rs index 2827e6eead5fd..c96a6fa8b6c91 100644 --- a/src/test/ui/unboxed-closures/unboxed-closure-sugar-used-on-struct-1.rs +++ b/src/test/ui/unboxed-closures/unboxed-closure-sugar-used-on-struct-1.rs @@ -6,7 +6,7 @@ struct Bar { fn bar() { let x: Box = panic!(); - //~^ ERROR parenthesized parameters may only be used with a trait + //~^ ERROR parenthesized type parameters may only be used with a `Fn` trait //~| ERROR wrong number of type arguments: expected 1, found 0 } diff --git a/src/test/ui/unboxed-closures/unboxed-closure-sugar-used-on-struct-1.stderr b/src/test/ui/unboxed-closures/unboxed-closure-sugar-used-on-struct-1.stderr index 87832d839b949..fa52e66fb0349 100644 --- a/src/test/ui/unboxed-closures/unboxed-closure-sugar-used-on-struct-1.stderr +++ b/src/test/ui/unboxed-closures/unboxed-closure-sugar-used-on-struct-1.stderr @@ -1,11 +1,8 @@ -error[E0214]: parenthesized parameters may only be used with a trait +error[E0214]: parenthesized type parameters may only be used with a `Fn` trait --> $DIR/unboxed-closure-sugar-used-on-struct-1.rs:8:19 | LL | let x: Box = panic!(); - | ^^ - | | - | only traits may use parentheses - | help: use angle brackets instead: `<>` + | ^^ only `Fn` traits may use parentheses error[E0107]: wrong number of type arguments: expected 1, found 0 --> $DIR/unboxed-closure-sugar-used-on-struct-1.rs:8:16 diff --git a/src/test/ui/unboxed-closures/unboxed-closure-sugar-used-on-struct-3.rs b/src/test/ui/unboxed-closures/unboxed-closure-sugar-used-on-struct-3.rs index 3cada322b1ef2..79ced1ecfb1a0 100644 --- a/src/test/ui/unboxed-closures/unboxed-closure-sugar-used-on-struct-3.rs +++ b/src/test/ui/unboxed-closures/unboxed-closure-sugar-used-on-struct-3.rs @@ -12,7 +12,7 @@ fn bar() { let b = Bar::::new(); // OK let b = Bar::(isize, usize)::new(); // OK too (for the parser) - //~^ ERROR parenthesized parameters may only be used with a trait + //~^ ERROR parenthesized type parameters may only be used with a `Fn` trait } fn main() {} diff --git a/src/test/ui/unboxed-closures/unboxed-closure-sugar-used-on-struct-3.stderr b/src/test/ui/unboxed-closures/unboxed-closure-sugar-used-on-struct-3.stderr index c9cc60717a610..7d05ca55ffdb0 100644 --- a/src/test/ui/unboxed-closures/unboxed-closure-sugar-used-on-struct-3.stderr +++ b/src/test/ui/unboxed-closures/unboxed-closure-sugar-used-on-struct-3.stderr @@ -1,10 +1,10 @@ -error[E0214]: parenthesized parameters may only be used with a trait +error[E0214]: parenthesized type parameters may only be used with a `Fn` trait --> $DIR/unboxed-closure-sugar-used-on-struct-3.rs:14:18 | LL | let b = Bar::(isize, usize)::new(); // OK too (for the parser) | ^^^^^^^^^^^^^^ | | - | only traits may use parentheses + | only `Fn` traits may use parentheses | help: use angle brackets instead: `` error: aborting due to previous error diff --git a/src/test/ui/unboxed-closures/unboxed-closure-sugar-used-on-struct.rs b/src/test/ui/unboxed-closures/unboxed-closure-sugar-used-on-struct.rs index 6da53585c9c4c..1af7f55674c6a 100644 --- a/src/test/ui/unboxed-closures/unboxed-closure-sugar-used-on-struct.rs +++ b/src/test/ui/unboxed-closures/unboxed-closure-sugar-used-on-struct.rs @@ -5,7 +5,7 @@ struct Bar { } fn foo(b: Box) { - //~^ ERROR parenthesized parameters may only be used with a trait + //~^ ERROR parenthesized type parameters may only be used with a `Fn` trait //~| ERROR wrong number of type arguments: expected 1, found 0 } diff --git a/src/test/ui/unboxed-closures/unboxed-closure-sugar-used-on-struct.stderr b/src/test/ui/unboxed-closures/unboxed-closure-sugar-used-on-struct.stderr index a09c2b75386eb..b34237937ee1c 100644 --- a/src/test/ui/unboxed-closures/unboxed-closure-sugar-used-on-struct.stderr +++ b/src/test/ui/unboxed-closures/unboxed-closure-sugar-used-on-struct.stderr @@ -1,11 +1,8 @@ -error[E0214]: parenthesized parameters may only be used with a trait +error[E0214]: parenthesized type parameters may only be used with a `Fn` trait --> $DIR/unboxed-closure-sugar-used-on-struct.rs:7:18 | LL | fn foo(b: Box) { - | ^^ - | | - | only traits may use parentheses - | help: use angle brackets instead: `<>` + | ^^ only `Fn` traits may use parentheses error[E0107]: wrong number of type arguments: expected 1, found 0 --> $DIR/unboxed-closure-sugar-used-on-struct.rs:7:15 From 5b44b3cb1b2bc2f93520fe1339d93efe8439238c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Sun, 20 Jan 2019 09:11:42 -0800 Subject: [PATCH 12/15] review comment --- src/librustc_typeck/check/demand.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustc_typeck/check/demand.rs b/src/librustc_typeck/check/demand.rs index 2aecc0f2ace6a..d985bdae491d0 100644 --- a/src/librustc_typeck/check/demand.rs +++ b/src/librustc_typeck/check/demand.rs @@ -495,7 +495,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { })) = self.tcx.hir().find(self.tcx.hir().get_parent_node(expr.id)) { // `expr` is a literal field for a struct, only suggest if appropriate for field in fields { - if field.expr.id == expr.id { + if field.expr.id == expr.id && field.is_shorthand { // This is a field literal prefix = format!("{}: ", field.ident); break; From ce0e5558da1279baba8c744c56bd227b4d2d29d5 Mon Sep 17 00:00:00 2001 From: Yuki Okushi Date: Mon, 21 Jan 2019 04:52:16 +0900 Subject: [PATCH 13/15] Add span for bad doc comment --- src/libsyntax/parse/parser.rs | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 7e15b23127655..3195435bba5ad 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -4483,13 +4483,17 @@ impl<'a> Parser<'a> { } /// Emit an expected item after attributes error. - fn expected_item_err(&self, attrs: &[Attribute]) { + fn expected_item_err(&mut self, attrs: &[Attribute]) -> PResult<'a, ()> { let message = match attrs.last() { Some(&Attribute { is_sugared_doc: true, .. }) => "expected item after doc comment", _ => "expected item after attributes", }; - self.span_err(self.prev_span, message); + let mut err = self.diagnostic().struct_span_err(self.prev_span, message); + if attrs.last().unwrap().is_sugared_doc { + err.span_label(self.prev_span, "this doc comment doesn't document anything"); + } + Err(err) } /// Parse a statement. This stops just before trailing semicolons on everything but items. @@ -7636,7 +7640,7 @@ impl<'a> Parser<'a> { } None => { if !attrs.is_empty() { - self.expected_item_err(&attrs); + self.expected_item_err(&attrs)?; } self.unexpected() @@ -7699,7 +7703,7 @@ impl<'a> Parser<'a> { } if !attributes_allowed && !attrs.is_empty() { - self.expected_item_err(&attrs); + self.expected_item_err(&attrs)?; } Ok(None) } From b97c9641f51c6897ddded240c87e84f065f55588 Mon Sep 17 00:00:00 2001 From: Yuki Okushi Date: Mon, 21 Jan 2019 04:52:30 +0900 Subject: [PATCH 14/15] Fix tests --- src/test/ui/parser/doc-before-eof.stderr | 2 +- src/test/ui/parser/doc-before-extern-rbrace.stderr | 2 +- src/test/ui/parser/doc-before-mod-rbrace.stderr | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/test/ui/parser/doc-before-eof.stderr b/src/test/ui/parser/doc-before-eof.stderr index b764e9f7ae102..5809d64e80678 100644 --- a/src/test/ui/parser/doc-before-eof.stderr +++ b/src/test/ui/parser/doc-before-eof.stderr @@ -2,7 +2,7 @@ error: expected item after doc comment --> $DIR/doc-before-eof.rs:3:1 | LL | /// hi //~ERROR expected item after doc comment - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ this doc comment doesn't document anything error: aborting due to previous error diff --git a/src/test/ui/parser/doc-before-extern-rbrace.stderr b/src/test/ui/parser/doc-before-extern-rbrace.stderr index 47fab7b40f4cd..8cc9c916a7afd 100644 --- a/src/test/ui/parser/doc-before-extern-rbrace.stderr +++ b/src/test/ui/parser/doc-before-extern-rbrace.stderr @@ -2,7 +2,7 @@ error: expected item after doc comment --> $DIR/doc-before-extern-rbrace.rs:2:5 | LL | /// hi - | ^^^^^^ + | ^^^^^^ this doc comment doesn't document anything error: aborting due to previous error diff --git a/src/test/ui/parser/doc-before-mod-rbrace.stderr b/src/test/ui/parser/doc-before-mod-rbrace.stderr index 41c1d706b3a7e..4eaf351f676c8 100644 --- a/src/test/ui/parser/doc-before-mod-rbrace.stderr +++ b/src/test/ui/parser/doc-before-mod-rbrace.stderr @@ -2,7 +2,7 @@ error: expected item after doc comment --> $DIR/doc-before-mod-rbrace.rs:4:5 | LL | /// document - | ^^^^^^^^^^^^ + | ^^^^^^^^^^^^ this doc comment doesn't document anything error: aborting due to previous error From f13fe5f3f7e2e2ed689967e818ffadc9cdba8af6 Mon Sep 17 00:00:00 2001 From: David Wood Date: Sun, 20 Jan 2019 20:26:46 +0100 Subject: [PATCH 15/15] Add "dereference boxed value" suggestion. This commit adds a `help: consider dereferencing the boxed value` suggestion to discriminants of match statements when the match arms have type `T` and the discriminant has type `Box`. --- src/librustc/infer/error_reporting/mod.rs | 21 +++++++- src/test/ui/issues/issue-57741-1.rs | 18 +++++++ src/test/ui/issues/issue-57741-1.stderr | 25 ++++++++++ src/test/ui/issues/issue-57741.fixed | 31 ++++++++++++ src/test/ui/issues/issue-57741.rs | 31 ++++++++++++ src/test/ui/issues/issue-57741.stderr | 59 +++++++++++++++++++++++ 6 files changed, 183 insertions(+), 2 deletions(-) create mode 100644 src/test/ui/issues/issue-57741-1.rs create mode 100644 src/test/ui/issues/issue-57741-1.stderr create mode 100644 src/test/ui/issues/issue-57741.fixed create mode 100644 src/test/ui/issues/issue-57741.rs create mode 100644 src/test/ui/issues/issue-57741.stderr diff --git a/src/librustc/infer/error_reporting/mod.rs b/src/librustc/infer/error_reporting/mod.rs index 2995b25308d4c..35f6e6aa610ad 100644 --- a/src/librustc/infer/error_reporting/mod.rs +++ b/src/librustc/infer/error_reporting/mod.rs @@ -485,12 +485,29 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { } } - fn note_error_origin(&self, err: &mut DiagnosticBuilder<'tcx>, cause: &ObligationCause<'tcx>) { + fn note_error_origin( + &self, + err: &mut DiagnosticBuilder<'tcx>, + cause: &ObligationCause<'tcx>, + exp_found: Option>>, + ) { match cause.code { ObligationCauseCode::MatchExpressionArmPattern { span, ty } => { if ty.is_suggestable() { // don't show type `_` err.span_label(span, format!("this match expression has type `{}`", ty)); } + if let Some(ty::error::ExpectedFound { found, .. }) = exp_found { + if ty.is_box() && ty.boxed_ty() == found { + if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span) { + err.span_suggestion_with_applicability( + span, + "consider dereferencing the boxed value", + format!("*{}", snippet), + Applicability::MachineApplicable, + ); + } + } + } } ObligationCauseCode::MatchExpressionArm { arm_span, source } => match source { hir::MatchSource::IfLetDesugar { .. } => { @@ -1013,7 +1030,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { // It reads better to have the error origin as the final // thing. - self.note_error_origin(diag, &cause); + self.note_error_origin(diag, &cause, exp_found); } /// When encountering a case where `.as_ref()` on a `Result` or `Option` would be appropriate, diff --git a/src/test/ui/issues/issue-57741-1.rs b/src/test/ui/issues/issue-57741-1.rs new file mode 100644 index 0000000000000..d0aae23b2fce6 --- /dev/null +++ b/src/test/ui/issues/issue-57741-1.rs @@ -0,0 +1,18 @@ +#![allow(warnings)] + +// This tests that the `help: consider dereferencing the boxed value` suggestion isn't made +// because the box doesn't deref to the type of the arm. + +enum S { + A { a: usize }, + B { b: usize }, +} + +fn main() { + let x = Box::new(3u32); + let y = match x { + S::A { a } | S::B { b: a } => a, + //~^ ERROR mismatched types [E0308] + //~^^ ERROR mismatched types [E0308] + }; +} diff --git a/src/test/ui/issues/issue-57741-1.stderr b/src/test/ui/issues/issue-57741-1.stderr new file mode 100644 index 0000000000000..d36424b83b4e1 --- /dev/null +++ b/src/test/ui/issues/issue-57741-1.stderr @@ -0,0 +1,25 @@ +error[E0308]: mismatched types + --> $DIR/issue-57741-1.rs:14:9 + | +LL | let y = match x { + | - this match expression has type `std::boxed::Box` +LL | S::A { a } | S::B { b: a } => a, + | ^^^^^^^^^^ expected struct `std::boxed::Box`, found enum `S` + | + = note: expected type `std::boxed::Box` + found type `S` + +error[E0308]: mismatched types + --> $DIR/issue-57741-1.rs:14:22 + | +LL | let y = match x { + | - this match expression has type `std::boxed::Box` +LL | S::A { a } | S::B { b: a } => a, + | ^^^^^^^^^^^^^ expected struct `std::boxed::Box`, found enum `S` + | + = note: expected type `std::boxed::Box` + found type `S` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/issues/issue-57741.fixed b/src/test/ui/issues/issue-57741.fixed new file mode 100644 index 0000000000000..4cae080033ca2 --- /dev/null +++ b/src/test/ui/issues/issue-57741.fixed @@ -0,0 +1,31 @@ +// run-rustfix + +#![allow(warnings)] + +// This tests that the `help: consider dereferencing the boxed value` suggestion is made and works. + +enum S { + A { a: usize }, + B { b: usize }, +} + +enum T { + A(usize), + B(usize), +} + +fn main() { + let x = Box::new(T::A(3)); + let y = match *x { + T::A(a) | T::B(a) => a, + //~^ ERROR mismatched types [E0308] + //~^^ ERROR mismatched types [E0308] + }; + + let x = Box::new(S::A { a: 3 }); + let y = match *x { + S::A { a } | S::B { b: a } => a, + //~^ ERROR mismatched types [E0308] + //~^^ ERROR mismatched types [E0308] + }; +} diff --git a/src/test/ui/issues/issue-57741.rs b/src/test/ui/issues/issue-57741.rs new file mode 100644 index 0000000000000..e2658295af791 --- /dev/null +++ b/src/test/ui/issues/issue-57741.rs @@ -0,0 +1,31 @@ +// run-rustfix + +#![allow(warnings)] + +// This tests that the `help: consider dereferencing the boxed value` suggestion is made and works. + +enum S { + A { a: usize }, + B { b: usize }, +} + +enum T { + A(usize), + B(usize), +} + +fn main() { + let x = Box::new(T::A(3)); + let y = match x { + T::A(a) | T::B(a) => a, + //~^ ERROR mismatched types [E0308] + //~^^ ERROR mismatched types [E0308] + }; + + let x = Box::new(S::A { a: 3 }); + let y = match x { + S::A { a } | S::B { b: a } => a, + //~^ ERROR mismatched types [E0308] + //~^^ ERROR mismatched types [E0308] + }; +} diff --git a/src/test/ui/issues/issue-57741.stderr b/src/test/ui/issues/issue-57741.stderr new file mode 100644 index 0000000000000..a26b1d20ca3cb --- /dev/null +++ b/src/test/ui/issues/issue-57741.stderr @@ -0,0 +1,59 @@ +error[E0308]: mismatched types + --> $DIR/issue-57741.rs:20:9 + | +LL | let y = match x { + | - + | | + | this match expression has type `std::boxed::Box` + | help: consider dereferencing the boxed value: `*x` +LL | T::A(a) | T::B(a) => a, + | ^^^^^^^ expected struct `std::boxed::Box`, found enum `T` + | + = note: expected type `std::boxed::Box` + found type `T` + +error[E0308]: mismatched types + --> $DIR/issue-57741.rs:20:19 + | +LL | let y = match x { + | - + | | + | this match expression has type `std::boxed::Box` + | help: consider dereferencing the boxed value: `*x` +LL | T::A(a) | T::B(a) => a, + | ^^^^^^^ expected struct `std::boxed::Box`, found enum `T` + | + = note: expected type `std::boxed::Box` + found type `T` + +error[E0308]: mismatched types + --> $DIR/issue-57741.rs:27:9 + | +LL | let y = match x { + | - + | | + | this match expression has type `std::boxed::Box` + | help: consider dereferencing the boxed value: `*x` +LL | S::A { a } | S::B { b: a } => a, + | ^^^^^^^^^^ expected struct `std::boxed::Box`, found enum `S` + | + = note: expected type `std::boxed::Box` + found type `S` + +error[E0308]: mismatched types + --> $DIR/issue-57741.rs:27:22 + | +LL | let y = match x { + | - + | | + | this match expression has type `std::boxed::Box` + | help: consider dereferencing the boxed value: `*x` +LL | S::A { a } | S::B { b: a } => a, + | ^^^^^^^^^^^^^ expected struct `std::boxed::Box`, found enum `S` + | + = note: expected type `std::boxed::Box` + found type `S` + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0308`.