Skip to content

Rollup of 8 pull requests #65115

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

Closed
wants to merge 31 commits into from
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
0797712
Stabilize Option::deref and Option::deref_mut
SimonSapin Sep 23, 2019
e8796ca
Do not ICE when dereferencing non-Copy raw pointer
estebank Oct 2, 2019
1222cc9
permit asyncawait-ondeck to be added by anyone
nikomatsakis Oct 3, 2019
1fcbd90
Update triagebot.toml
nikomatsakis Oct 3, 2019
ed60cf2
When encountering chained operators use heuristics to recover from ba…
estebank Sep 30, 2019
6c9f298
review comments
estebank Sep 30, 2019
d7dceaa
Account for missing turbofish in paths too
estebank Sep 30, 2019
d27683a
Prove bad turbofish parser recovery in test
estebank Sep 30, 2019
dfdc369
review comments
estebank Oct 1, 2019
f1499a8
review comments
estebank Oct 1, 2019
02f57f8
review comments
estebank Oct 3, 2019
76456e7
review comments
estebank Oct 4, 2019
2d87bac
replace GeneratorSubsts with SubstsRef
csmoe Oct 3, 2019
fa7a87b
generate GeneratorSubsts from SubstsRef
csmoe Oct 3, 2019
774ea80
replace GeneratorSubsts inside related types
csmoe Oct 3, 2019
ef9fe10
remove GeneratorSubsts visitors
csmoe Oct 3, 2019
afc0bb9
clean up GeneratorSubsts
csmoe Oct 3, 2019
e9009c8
[const-prop] Fix ICE when trying to eval polymorphic promoted MIR
wesleywiser Oct 3, 2019
91a096a
move middle::liveness to rustc_passes
Mark-Simulacrum Oct 4, 2019
bb70782
middle::dead -> rustc_passes
Mark-Simulacrum Oct 4, 2019
82bfd8e
middle::entry -> rustc_passes
Mark-Simulacrum Oct 4, 2019
7c3f65b
middle::intrinsicck -> rustc_passes
Mark-Simulacrum Oct 4, 2019
d0a6805
Allow unused attributes to avoid incremental bug
Mark-Simulacrum Oct 4, 2019
bf8eb09
Rollup merge of #64708 - SimonSapin:option-deref, r=Centril
Centril Oct 4, 2019
db4ad42
Rollup merge of #64909 - estebank:turbofish-reloaded, r=Centril
Centril Oct 4, 2019
21e57ee
Rollup merge of #65011 - estebank:ice-o-matic, r=zackmdavis
Centril Oct 4, 2019
fad8a7b
Rollup merge of #65064 - rust-lang:permit-asyncawait-ondeck-by-anyone…
Centril Oct 4, 2019
6967617
Rollup merge of #65066 - wesleywiser:fix_const_prop_ice_on_polymorphi…
Centril Oct 4, 2019
cfd51ca
Rollup merge of #65100 - csmoe:generator, r=nikomatsakis
Centril Oct 4, 2019
7f520da
Rollup merge of #65105 - Mark-Simulacrum:split-librustc, r=nikomatsakis
Centril Oct 4, 2019
f320add
Rollup merge of #65106 - Mark-Simulacrum:unused-attr-allow, r=Centril
Centril Oct 4, 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
Prev Previous commit
Next Next commit
When encountering chained operators use heuristics to recover from ba…
…d turbofish
  • Loading branch information
estebank committed Oct 3, 2019
commit ed60cf2475cabd3d9ad1afdc03bd6952d99b744c
100 changes: 88 additions & 12 deletions src/libsyntax/parse/diagnostics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -543,16 +543,25 @@ impl<'a> Parser<'a> {
}

/// Produces an error if comparison operators are chained (RFC #558).
/// We only need to check the LHS, not the RHS, because all comparison ops
/// have same precedence and are left-associative.
crate fn check_no_chained_comparison(&self, lhs: &Expr, outer_op: &AssocOp) -> PResult<'a, ()> {
debug_assert!(outer_op.is_comparison(),
"check_no_chained_comparison: {:?} is not comparison",
outer_op);
/// We only need to check the LHS, not the RHS, because all comparison ops have same
/// precedence and are left-associative.
///
/// This can also be hit if someone incorrectly writes `foo<bar>()` when they should have used
/// the turbofish syntax. We attempt some heuristic recovery if that is the case.
crate fn check_no_chained_comparison(
&mut self,
lhs: &Expr,
outer_op: &AssocOp,
) -> PResult<'a, Option<P<Expr>>> {
debug_assert!(
outer_op.is_comparison(),
"check_no_chained_comparison: {:?} is not comparison",
outer_op,
);
match lhs.kind {
ExprKind::Binary(op, _, _) if op.node.is_comparison() => {
// Respan to include both operators.
let op_span = op.span.to(self.token.span);
let op_span = op.span.to(self.prev_span);
let mut err = self.struct_span_err(
op_span,
"chained comparison operators require parentheses",
Expand All @@ -561,17 +570,84 @@ impl<'a> Parser<'a> {
*outer_op == AssocOp::Less || // Include `<` to provide this recommendation
*outer_op == AssocOp::Greater // even in a case like the following:
{ // Foo<Bar<Baz<Qux, ()>>>
err.help(
"use `::<...>` instead of `<...>` if you meant to specify type arguments");
err.help("or use `(...)` if you meant to specify fn arguments");
// These cases cause too many knock-down errors, bail out (#61329).
let msg = "use `::<...>` instead of `<...>` if you meant to specify type \
arguments";
if *outer_op == AssocOp::Less {
// if self.look_ahead(1, |t| t.kind == token::Lt || t.kind == token::ModSep) {
let snapshot = self.clone();
self.bump();
// So far we have parsed `foo<bar<`
let mut acc = 1;
while acc > 0 {
match &self.token.kind {
token::Lt => {
acc += 1;
}
token::Gt => {
acc -= 1;
}
token::BinOp(token::Shr) => {
acc -= 2;
}
token::Eof => {
break;
}
_ => {}
}
self.bump();
}
if self.token.kind != token::OpenDelim(token::Paren) {
mem::replace(self, snapshot.clone());
}
}
if self.token.kind == token::OpenDelim(token::Paren) {
err.span_suggestion(
op_span.shrink_to_lo(),
msg,
"::".to_string(),
Applicability::MaybeIncorrect,
);
let snapshot = self.clone();
self.bump();
let mut acc = 1;
while acc > 0 {
match &self.token.kind {
token::OpenDelim(token::Paren) => {
acc += 1;
}
token::CloseDelim(token::Paren) => {
acc -= 1;
}
token::Eof => {
break;
}
_ => {}
}
self.bump();
}
if self.token.kind == token::Eof {
mem::replace(self, snapshot);
return Err(err);
} else {
err.emit();
return Ok(Some(self.mk_expr(
lhs.span.to(self.prev_span),
ExprKind::Err,
ThinVec::new(),
)));
}
} else {
err.help(msg);
err.help("or use `(...)` if you meant to specify fn arguments");
// These cases cause too many knock-down errors, bail out (#61329).
}
return Err(err);
}
err.emit();
}
_ => {}
}
Ok(())
Ok(None)
}

crate fn maybe_report_ambiguous_plus(
Expand Down
4 changes: 3 additions & 1 deletion src/libsyntax/parse/parser/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -238,7 +238,9 @@ impl<'a> Parser<'a> {

self.bump();
if op.is_comparison() {
self.check_no_chained_comparison(&lhs, &op)?;
if let Some(expr) = self.check_no_chained_comparison(&lhs, &op)? {
return Ok(expr);
}
}
// Special cases:
if op == AssocOp::As {
Expand Down
16 changes: 9 additions & 7 deletions src/test/ui/did_you_mean/issue-40396.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,17 @@ error: chained comparison operators require parentheses
--> $DIR/issue-40396.rs:2:20
|
LL | (0..13).collect<Vec<i32>>();
| ^^^^^^^^
| ^^^^^
help: use `::<...>` instead of `<...>` if you meant to specify type arguments
|
= help: use `::<...>` instead of `<...>` if you meant to specify type arguments
= help: or use `(...)` if you meant to specify fn arguments
LL | (0..13).collect::<Vec<i32>>();
| ^^

error: chained comparison operators require parentheses
--> $DIR/issue-40396.rs:7:8
|
LL | Vec<i32>::new();
| ^^^^^^^
| ^^^^^
|
= help: use `::<...>` instead of `<...>` if you meant to specify type arguments
= help: or use `(...)` if you meant to specify fn arguments
Expand All @@ -20,10 +21,11 @@ error: chained comparison operators require parentheses
--> $DIR/issue-40396.rs:12:20
|
LL | (0..13).collect<Vec<i32>();
| ^^^^^^^^
| ^^^^^
help: use `::<...>` instead of `<...>` if you meant to specify type arguments
|
= help: use `::<...>` instead of `<...>` if you meant to specify type arguments
= help: or use `(...)` if you meant to specify fn arguments
LL | (0..13).collect::<Vec<i32>();
| ^^

error: aborting due to 3 previous errors

5 changes: 4 additions & 1 deletion src/test/ui/parser/require-parens-for-chained-comparison.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,5 +13,8 @@ fn main() {
f<X>();
//~^ ERROR chained comparison operators require parentheses
//~| HELP: use `::<...>` instead of `<...>`
//~| HELP: or use `(...)`

f<Result<Option<X>, Option<Option<X>>>(1, 2);
//~^ ERROR chained comparison operators require parentheses
//~| HELP: use `::<...>` instead of `<...>`
}
23 changes: 17 additions & 6 deletions src/test/ui/parser/require-parens-for-chained-comparison.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -2,22 +2,33 @@ error: chained comparison operators require parentheses
--> $DIR/require-parens-for-chained-comparison.rs:5:11
|
LL | false == false == false;
| ^^^^^^^^^^^^^^^^^
| ^^^^^^^^^^^

error: chained comparison operators require parentheses
--> $DIR/require-parens-for-chained-comparison.rs:8:11
|
LL | false == 0 < 2;
| ^^^^^^^^
| ^^^^^^

error: chained comparison operators require parentheses
--> $DIR/require-parens-for-chained-comparison.rs:13:6
|
LL | f<X>();
| ^^^^
| ^^^
help: use `::<...>` instead of `<...>` if you meant to specify type arguments
|
= help: use `::<...>` instead of `<...>` if you meant to specify type arguments
= help: or use `(...)` if you meant to specify fn arguments
LL | f::<X>();
| ^^

error: chained comparison operators require parentheses
--> $DIR/require-parens-for-chained-comparison.rs:17:6
|
LL | f<Result<Option<X>, Option<Option<X>>>(1, 2);
| ^^^^^^^^
help: use `::<...>` instead of `<...>` if you meant to specify type arguments
|
LL | f::<Result<Option<X>, Option<Option<X>>>(1, 2);
| ^^

error[E0308]: mismatched types
--> $DIR/require-parens-for-chained-comparison.rs:8:14
Expand All @@ -37,6 +48,6 @@ LL | false == 0 < 2;
= note: expected type `bool`
found type `{integer}`

error: aborting due to 5 previous errors
error: aborting due to 6 previous errors

For more information about this error, try `rustc --explain E0308`.