Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rollup of 5 pull requests #57792

Merged
merged 20 commits into from
Jan 21, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
f8bd80a
Change bounds on `TryFrom` blanket impl to use `Into` instead of `From`
RustyYato Dec 13, 2018
7a25a7c
Changed expected error message for TryFrom
RustyYato Dec 16, 2018
a1be813
Fixed `Into` bound on `TryFrom` error.
RustyYato Dec 16, 2018
db9fe1c
added test to show motivation for modified TryFrom impl
RustyYato Dec 19, 2018
7dd078f
fixed test, now it doesn't use a fundemental type
RustyYato Dec 19, 2018
ea68b3f
update to reflect changes recommended by @shepmaster his review
RustyYato Jan 3, 2019
d38e700
Continune parsing after encountering Trait with paren args
estebank Jan 19, 2019
3235446
Accept parenthesized type args for error recovery
estebank Jan 20, 2019
d37a6d8
Suggest usage of angle brackets
estebank Jan 20, 2019
b36bf76
Suggest correct cast for struct fields with shorthand syntax
estebank Jan 20, 2019
2ab6cef
Do not suggest angle brackets when there are no type arguments
estebank Jan 20, 2019
5b44b3c
review comment
estebank Jan 20, 2019
ce0e555
Add span for bad doc comment
JohnTitor Jan 20, 2019
b97c964
Fix tests
JohnTitor Jan 20, 2019
f13fe5f
Add "dereference boxed value" suggestion.
davidtwco Jan 20, 2019
ebc70e2
Rollup merge of #56796 - KrishnaSannasi:try_from_impl_change, r=shepm…
Centril Jan 21, 2019
627e001
Rollup merge of #57768 - estebank:type-args-sugg, r=zackmdavis
Centril Jan 21, 2019
3bb9fc4
Rollup merge of #57769 - estebank:cast-suggestion-struct-field, r=mat…
Centril Jan 21, 2019
74b8cd4
Rollup merge of #57783 - davidtwco:issue-57741, r=estebank
Centril Jan 21, 2019
00c60d1
Rollup merge of #57784 - JohnTitor:improve-error-message, r=estebank
Centril Jan 21, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions src/libcore/convert.rs
Original file line number Diff line number Diff line change
Expand Up @@ -463,11 +463,11 @@ impl<T, U> TryInto<U> for T where U: TryFrom<T>
// Infallible conversions are semantically equivalent to fallible conversions
// with an uninhabited error type.
#[unstable(feature = "try_from", issue = "33417")]
impl<T, U> TryFrom<U> for T where T: From<U> {
impl<T, U> TryFrom<U> for T where U: Into<T> {
type Error = !;

fn try_from(value: U) -> Result<Self, Self::Error> {
Ok(T::from(value))
Ok(U::into(value))
}
}

Expand Down
26 changes: 21 additions & 5 deletions src/librustc/hir/lowering.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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};
Expand Down Expand Up @@ -1806,7 +1807,7 @@ impl<'a> LoweringContext<'a> {
explicit_owner: Option<NodeId>,
) -> 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)
Expand All @@ -1823,10 +1824,25 @@ 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();
(hir::GenericArgs::none(), true)
let mut err = struct_span_err!(self.sess, data.span, E0214, "{}", msg);
err.span_label(data.span, "only `Fn` traits may use parentheses");
if let Ok(snippet) = self.sess.source_map().span_to_snippet(data.span) {
// 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(
&data.as_angle_bracketed_args(),
param_mode,
itctx).0,
false)
}
},
}
Expand Down
21 changes: 19 additions & 2 deletions src/librustc/infer/error_reporting/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<ty::error::ExpectedFound<Ty<'tcx>>>,
) {
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 { .. } => {
Expand Down Expand Up @@ -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,
Expand Down
48 changes: 36 additions & 12 deletions src/librustc_typeck/check/demand.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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 && field.is_shorthand {
// 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 { "" },
Expand Down
10 changes: 10 additions & 0 deletions src/libsyntax/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,16 @@ pub struct ParenthesisedArgs {
pub output: Option<P<Ty>>,
}

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;
Expand Down
14 changes: 9 additions & 5 deletions src/libsyntax/parse/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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>`
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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()
Expand Down Expand Up @@ -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)
}
Expand Down
37 changes: 37 additions & 0 deletions src/test/run-pass/try_from.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
// 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 blanket impl for all `T: From`

#![feature(try_from, never_type)]

use std::convert::TryInto;

struct Foo<T> {
t: T,
}

// This fails to compile due to coherence restrictions
// 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<T> From<Foo<T>> for Box<T> {
fn from(foo: Foo<T>) -> Box<T> {
Box::new(foo.t)
}
}
*/

impl<T> Into<Vec<T>> for Foo<T> {
fn into(self) -> Vec<T> {
vec![self.t]
}
}

pub fn main() {
let _: Result<Vec<i32>, !> = Foo { t: 10 }.try_into();
}

2 changes: 1 addition & 1 deletion src/test/ui/e0119/conflict-with-std.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ LL | impl TryFrom<X> for X { //~ ERROR conflicting implementations
|
= note: conflicting implementation in crate `core`:
- impl<T, U> std::convert::TryFrom<U> for T
where T: std::convert::From<U>;
where U: std::convert::Into<T>;

error: aborting due to 3 previous errors

Expand Down
7 changes: 5 additions & 2 deletions src/test/ui/error-codes/E0214.stderr
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
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

Expand Down
3 changes: 2 additions & 1 deletion src/test/ui/issues/issue-23589.rs
Original file line number Diff line number Diff line change
@@ -1,4 +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
}
21 changes: 17 additions & 4 deletions src/test/ui/issues/issue-23589.stderr
Original file line number Diff line number Diff line change
@@ -1,9 +1,22 @@
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: aborting due to previous error
error[E0308]: mismatched types
--> $DIR/issue-23589.rs:2:29
|
LL | let v: Vec(&str) = vec!['1', '2'];
| ^^^ expected &str, found char
|
= note: expected type `&str`
found type `char`

error: aborting due to 2 previous errors

For more information about this error, try `rustc --explain E0214`.
Some errors occurred: E0214, E0308.
For more information about an error, try `rustc --explain E0214`.
6 changes: 3 additions & 3 deletions src/test/ui/issues/issue-32995-2.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,17 @@

fn main() {
{ fn f<X: ::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

{ 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
}

#[derive(Clone)]
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
6 changes: 3 additions & 3 deletions src/test/ui/issues/issue-32995-2.stderr
Original file line number Diff line number Diff line change
@@ -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<X: ::std::marker()::Send>() {} }
Expand All @@ -8,7 +8,7 @@ LL | { fn f<X: ::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 <https://github.com/rust-lang/rust/issues/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 { } }
Expand All @@ -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 <https://github.com/rust-lang/rust/issues/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 {}
Expand Down
Loading