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 #51379

Closed
wants to merge 27 commits into from
Closed
Changes from 4 commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
daa5b81
Issue #50974: Suboptimal error in case of duplicate `,` in struct con…
lambtowolf May 29, 2018
a66597d
Issue #50974: Change text of suggestion to be more direct
lambtowolf May 29, 2018
4558a62
Issue #50974: Adding tests
lambtowolf May 29, 2018
4b32ddd
Issue #50974: Adding issue number in the test
lambtowolf May 29, 2018
8e956e1
Fix when the help message is displayed
lambtowolf May 30, 2018
18580e2
Issue #50974: Fix compilation error and test
lambtowolf May 30, 2018
dcc4b16
When NLL has illegal move due to borrowed content, provide feedback a…
pnkfelix May 31, 2018
74002d1
Drive-by: Make assignment conflict tests in borrowck-vec-pattern-nest…
pnkfelix May 31, 2018
e99f5ec
Update the expected error output to reflect changes in this PR.
pnkfelix May 31, 2018
8f4a542
Accept `..` in incorrect position to avoid further errors
estebank May 29, 2018
cbc70a0
Improve diagnostics for incorrect `..` usage
estebank May 30, 2018
d66d35b
Account for comma in suggestion
estebank May 30, 2018
aa23aba
[fuchsia] Migrate from launchpad to fdio_spawn_etc
Jun 1, 2018
01559fb
add an explanatory comment for recovery behavior
nikomatsakis Jun 5, 2018
5c0d135
Refactor the const eval diagnostic API
oli-obk Jun 2, 2018
9cb47de
Referring to erroneous constants in promoteds must abort the build
oli-obk Jun 3, 2018
78d4886
Properly report transitive errors
oli-obk Jun 3, 2018
13a55e8
Satisfy the untiring tidy
oli-obk Jun 3, 2018
848080d
Remove unused IndexOutOfBounds variant
oli-obk Jun 5, 2018
5950496
Remove another unused error variant
oli-obk Jun 5, 2018
8a74be6
Add source information the const propagation of places
oli-obk Jun 5, 2018
14d08e5
Rebase fallout
oli-obk Jun 5, 2018
8e9a5e9
Rollup merge of #51184 - lambtowolf:master, r=nikomatsakis
Mark-Simulacrum Jun 5, 2018
8ec9f4c
Rollup merge of #51201 - estebank:dotdot, r=petrochenkov
Mark-Simulacrum Jun 5, 2018
26ad9e2
Rollup merge of #51247 - pnkfelix:issue-51190-report-type-moved-from-…
Mark-Simulacrum Jun 5, 2018
7d0d7ea
Rollup merge of #51316 - oli-obk:const_err, r=nikomatsakis
Mark-Simulacrum Jun 5, 2018
5f2de72
Rollup merge of #51359 - cramertj:fdio_spawn, r=sfackler
Mark-Simulacrum Jun 5, 2018
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
204 changes: 135 additions & 69 deletions src/libsyntax/parse/parser.rs
Original file line number Diff line number Diff line change
@@ -3719,26 +3719,89 @@ impl<'a> Parser<'a> {
Ok((before, slice, after))
}

fn parse_pat_field(
&mut self,
lo: Span,
attrs: Vec<Attribute>
) -> PResult<'a, codemap::Spanned<ast::FieldPat>> {
// Check if a colon exists one ahead. This means we're parsing a fieldname.
let hi;
let (subpat, fieldname, is_shorthand) = if self.look_ahead(1, |t| t == &token::Colon) {
// Parsing a pattern of the form "fieldname: pat"
let fieldname = self.parse_field_name()?;
self.bump();
let pat = self.parse_pat()?;
hi = pat.span;
(pat, fieldname, false)
} else {
// Parsing a pattern of the form "(box) (ref) (mut) fieldname"
let is_box = self.eat_keyword(keywords::Box);
let boxed_span = self.span;
let is_ref = self.eat_keyword(keywords::Ref);
let is_mut = self.eat_keyword(keywords::Mut);
let fieldname = self.parse_ident()?;
hi = self.prev_span;

let bind_type = match (is_ref, is_mut) {
(true, true) => BindingMode::ByRef(Mutability::Mutable),
(true, false) => BindingMode::ByRef(Mutability::Immutable),
(false, true) => BindingMode::ByValue(Mutability::Mutable),
(false, false) => BindingMode::ByValue(Mutability::Immutable),
};
let fieldpat = P(Pat {
id: ast::DUMMY_NODE_ID,
node: PatKind::Ident(bind_type, fieldname, None),
span: boxed_span.to(hi),
});

let subpat = if is_box {
P(Pat {
id: ast::DUMMY_NODE_ID,
node: PatKind::Box(fieldpat),
span: lo.to(hi),
})
} else {
fieldpat
};
(subpat, fieldname, true)
};

Ok(codemap::Spanned {
span: lo.to(hi),
node: ast::FieldPat {
ident: fieldname,
pat: subpat,
is_shorthand,
attrs: attrs.into(),
}
})
}

/// Parse the fields of a struct-like pattern
fn parse_pat_fields(&mut self) -> PResult<'a, (Vec<codemap::Spanned<ast::FieldPat>>, bool)> {
let mut fields = Vec::new();
let mut etc = false;
let mut first = true;
while self.token != token::CloseDelim(token::Brace) {
if first {
first = false;
} else {
self.expect(&token::Comma)?;
// accept trailing commas
if self.check(&token::CloseDelim(token::Brace)) { break }
}
let mut ate_comma = true;
let mut delayed_err: Option<DiagnosticBuilder<'a>> = None;
let mut etc_span = None;

while self.token != token::CloseDelim(token::Brace) {
let attrs = self.parse_outer_attributes()?;
let lo = self.span;
let hi;

// check that a comma comes after every field
if !ate_comma {
let err = self.struct_span_err(self.prev_span, "expected `,`");
return Err(err);
}
ate_comma = false;

if self.check(&token::DotDot) || self.token == token::DotDotDot {
etc = true;
let mut etc_sp = self.span;

if self.token == token::DotDotDot { // Issue #46718
// Accept `...` as if it were `..` to avoid further errors
let mut err = self.struct_span_err(self.span,
"expected field pattern, found `...`");
err.span_suggestion_with_applicability(
@@ -3749,73 +3812,76 @@ impl<'a> Parser<'a> {
);
err.emit();
}
self.bump(); // `..` || `...`:w

self.bump();
if self.token != token::CloseDelim(token::Brace) {
let token_str = self.this_token_to_string();
let mut err = self.fatal(&format!("expected `{}`, found `{}`", "}", token_str));
if self.token == token::Comma { // Issue #49257
err.span_label(self.span,
"`..` must be in the last position, \
and cannot have a trailing comma");
if self.token == token::CloseDelim(token::Brace) {
etc_span = Some(etc_sp);
break;
}
let token_str = self.this_token_to_string();
let mut err = self.fatal(&format!("expected `}}`, found `{}`", token_str));

err.span_label(self.span, "expected `}`");
let mut comma_sp = None;
if self.token == token::Comma { // Issue #49257
etc_sp = etc_sp.to(self.sess.codemap().span_until_non_whitespace(self.span));
err.span_label(etc_sp,
"`..` must be at the end and cannot have a trailing comma");
comma_sp = Some(self.span);
self.bump();
ate_comma = true;
}

etc_span = Some(etc_sp);
if self.token == token::CloseDelim(token::Brace) {
// If the struct looks otherwise well formed, recover and continue.
if let Some(sp) = comma_sp {
err.span_suggestion_short(sp, "remove this comma", "".into());
}
err.emit();
break;
} else if self.token.is_ident() && ate_comma {
// Accept fields coming after `..,`.
// This way we avoid "pattern missing fields" errors afterwards.
// We delay this error until the end in order to have a span for a
// suggested fix.
if let Some(mut delayed_err) = delayed_err {
delayed_err.emit();
return Err(err);
} else {
err.span_label(self.span, "expected `}`");
delayed_err = Some(err);
}
} else {
if let Some(mut err) = delayed_err {
err.emit();
}
return Err(err);
}
etc = true;
break;
}

// Check if a colon exists one ahead. This means we're parsing a fieldname.
let (subpat, fieldname, is_shorthand) = if self.look_ahead(1, |t| t == &token::Colon) {
// Parsing a pattern of the form "fieldname: pat"
let fieldname = self.parse_field_name()?;
self.bump();
let pat = self.parse_pat()?;
hi = pat.span;
(pat, fieldname, false)
} else {
// Parsing a pattern of the form "(box) (ref) (mut) fieldname"
let is_box = self.eat_keyword(keywords::Box);
let boxed_span = self.span;
let is_ref = self.eat_keyword(keywords::Ref);
let is_mut = self.eat_keyword(keywords::Mut);
let fieldname = self.parse_ident()?;
hi = self.prev_span;

let bind_type = match (is_ref, is_mut) {
(true, true) => BindingMode::ByRef(Mutability::Mutable),
(true, false) => BindingMode::ByRef(Mutability::Immutable),
(false, true) => BindingMode::ByValue(Mutability::Mutable),
(false, false) => BindingMode::ByValue(Mutability::Immutable),
};
let fieldpat = P(Pat {
id: ast::DUMMY_NODE_ID,
node: PatKind::Ident(bind_type, fieldname, None),
span: boxed_span.to(hi),
});

let subpat = if is_box {
P(Pat {
id: ast::DUMMY_NODE_ID,
node: PatKind::Box(fieldpat),
span: lo.to(hi),
})
} else {
fieldpat
};
(subpat, fieldname, true)
};

fields.push(codemap::Spanned { span: lo.to(hi),
node: ast::FieldPat {
ident: fieldname,
pat: subpat,
is_shorthand,
attrs: attrs.into(),
}
fields.push(match self.parse_pat_field(lo, attrs) {
Ok(field) => field,
Err(err) => {
if let Some(mut delayed_err) = delayed_err {
delayed_err.emit();
}
return Err(err);
}
});
ate_comma = self.eat(&token::Comma);
}

if let Some(mut err) = delayed_err {
if let Some(etc_span) = etc_span {
err.multipart_suggestion(
"move the `..` to the end of the field list",
vec![
(etc_span, "".into()),
(self.span, format!("{}.. }}", if ate_comma { "" } else { ", " })),
],
);
}
err.emit();
}
return Ok((fields, etc));
}
2 changes: 1 addition & 1 deletion src/test/parse-fail/bind-struct-early-modifiers.rs
Original file line number Diff line number Diff line change
@@ -13,7 +13,7 @@
fn main() {
struct Foo { x: isize }
match (Foo { x: 10 }) {
Foo { ref x: ref x } => {}, //~ ERROR expected `,`, found `:`
Foo { ref x: ref x } => {}, //~ ERROR expected `,`
_ => {}
}
}
4 changes: 3 additions & 1 deletion src/test/ui/issue-49257.rs
Original file line number Diff line number Diff line change
@@ -17,6 +17,8 @@ struct Point { x: u8, y: u8 }

fn main() {
let p = Point { x: 0, y: 0 };
let Point { .., y, } = p; //~ ERROR expected `}`, found `,`
let Point { .., y } = p; //~ ERROR expected `}`, found `,`
//~| ERROR pattern does not mention fields `x`, `y`
let Point { .., } = p; //~ ERROR expected `}`, found `,`
let Point { .. } = p;
}
37 changes: 30 additions & 7 deletions src/test/ui/issue-49257.stderr
Original file line number Diff line number Diff line change
@@ -1,15 +1,38 @@
error: expected `}`, found `,`
--> $DIR/issue-49257.rs:20:19
|
LL | let Point { .., y } = p; //~ ERROR expected `}`, found `,`
| ^ `..` must be in the last position, and cannot have a trailing comma
LL | let Point { .., y, } = p; //~ ERROR expected `}`, found `,`
| --^
| | |
| | expected `}`
| `..` must be at the end and cannot have a trailing comma
help: move the `..` to the end of the field list
|
LL | let Point { y, .. } = p; //~ ERROR expected `}`, found `,`
| -- ^^^^

error[E0027]: pattern does not mention fields `x`, `y`
--> $DIR/issue-49257.rs:20:9
error: expected `}`, found `,`
--> $DIR/issue-49257.rs:21:19
|
LL | let Point { .., y } = p; //~ ERROR expected `}`, found `,`
| ^^^^^^^^^^^^^^^ missing fields `x`, `y`
| --^
| | |
| | expected `}`
| `..` must be at the end and cannot have a trailing comma
help: move the `..` to the end of the field list
|
LL | let Point { y , .. } = p; //~ ERROR expected `}`, found `,`
| -- ^^^^^^

error: expected `}`, found `,`
--> $DIR/issue-49257.rs:22:19
|
LL | let Point { .., } = p; //~ ERROR expected `}`, found `,`
| --^
| | |
| | expected `}`
| | help: remove this comma
| `..` must be at the end and cannot have a trailing comma

error: aborting due to 2 previous errors
error: aborting due to 3 previous errors

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