Skip to content

Commit b88a612

Browse files
committed
Change error for pub in fn decl if already present
1 parent 1796de7 commit b88a612

File tree

2 files changed

+39
-14
lines changed

2 files changed

+39
-14
lines changed

compiler/rustc_parse/src/parser/item.rs

Lines changed: 37 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -223,7 +223,7 @@ impl<'a> Parser<'a> {
223223
(Ident::empty(), ItemKind::Use(tree))
224224
} else if self.check_fn_front_matter(def_final) {
225225
// FUNCTION ITEM
226-
let (ident, sig, generics, body) = self.parse_fn(attrs, fn_parse_mode, lo)?;
226+
let (ident, sig, generics, body) = self.parse_fn(attrs, fn_parse_mode, lo, Some(vis))?;
227227
(ident, ItemKind::Fn(Box::new(Fn { defaultness: def(), sig, generics, body })))
228228
} else if self.eat_keyword(kw::Extern) {
229229
if self.eat_keyword(kw::Crate) {
@@ -1513,7 +1513,7 @@ impl<'a> Parser<'a> {
15131513
let err = if self.check_fn_front_matter(false) {
15141514
// We use `parse_fn` to get a span for the function
15151515
let fn_parse_mode = FnParseMode { req_name: |_| true, req_body: true };
1516-
if let Err(mut db) = self.parse_fn(&mut Vec::new(), fn_parse_mode, lo) {
1516+
if let Err(mut db) = self.parse_fn(&mut Vec::new(), fn_parse_mode, lo, None) {
15171517
db.delay_as_bug();
15181518
}
15191519
let mut err = self.struct_span_err(
@@ -1793,8 +1793,9 @@ impl<'a> Parser<'a> {
17931793
attrs: &mut Vec<Attribute>,
17941794
fn_parse_mode: FnParseMode,
17951795
sig_lo: Span,
1796+
vis: Option<&Visibility>,
17961797
) -> PResult<'a, (Ident, FnSig, Generics, Option<P<Block>>)> {
1797-
let header = self.parse_fn_front_matter()?; // `const ... fn`
1798+
let header = self.parse_fn_front_matter(vis)?; // `const ... fn`
17981799
let ident = self.parse_ident()?; // `foo`
17991800
let mut generics = self.parse_generics()?; // `<'a, T, ...>`
18001801
let decl =
@@ -1903,12 +1904,15 @@ impl<'a> Parser<'a> {
19031904
/// Parses all the "front matter" (or "qualifiers") for a `fn` declaration,
19041905
/// up to and including the `fn` keyword. The formal grammar is:
19051906
///
1906-
/// ```
1907+
/// ```text
19071908
/// Extern = "extern" StringLit? ;
19081909
/// FnQual = "const"? "async"? "unsafe"? Extern? ;
19091910
/// FnFrontMatter = FnQual "fn" ;
19101911
/// ```
1911-
pub(super) fn parse_fn_front_matter(&mut self) -> PResult<'a, FnHeader> {
1912+
pub(super) fn parse_fn_front_matter(
1913+
&mut self,
1914+
vis: Option<&Visibility>,
1915+
) -> PResult<'a, FnHeader> {
19121916
let sp_start = self.token.span;
19131917
let constness = self.parse_constness();
19141918

@@ -1962,23 +1966,43 @@ impl<'a> Parser<'a> {
19621966
}
19631967
// Recover incorrect visibility order such as `async pub`.
19641968
else if self.check_keyword(kw::Pub) {
1969+
let orig_vis = vis.unwrap_or(&Visibility {
1970+
span: rustc_span::DUMMY_SP,
1971+
kind: VisibilityKind::Inherited,
1972+
tokens: None,
1973+
});
1974+
19651975
let sp = sp_start.to(self.prev_token.span);
19661976
if let Ok(snippet) = self.span_to_snippet(sp) {
1967-
let vis = match self.parse_visibility(FollowedByType::No) {
1977+
let current_vis = match self.parse_visibility(FollowedByType::No) {
19681978
Ok(v) => v,
19691979
Err(mut d) => {
19701980
d.cancel();
19711981
return Err(err);
19721982
}
19731983
};
1974-
let vs = pprust::vis_to_string(&vis);
1984+
let vs = pprust::vis_to_string(&current_vis);
19751985
let vs = vs.trim_end();
1976-
err.span_suggestion(
1977-
sp_start.to(self.prev_token.span),
1978-
&format!("visibility `{}` must come before `{}`", vs, snippet),
1979-
format!("{} {}", vs, snippet),
1980-
Applicability::MachineApplicable,
1981-
);
1986+
1987+
// There was no explicit visibility
1988+
if matches!(orig_vis.kind, VisibilityKind::Inherited) {
1989+
err.span_suggestion(
1990+
sp,
1991+
&format!("visibility `{}` must come before `{}`", vs, snippet),
1992+
format!("{} {}", vs, snippet),
1993+
Applicability::MachineApplicable,
1994+
);
1995+
}
1996+
// There was an explicit visibility
1997+
else {
1998+
err.span_suggestion(
1999+
current_vis.span,
2000+
"there is already a visibility, remove this one",
2001+
"".to_string(),
2002+
Applicability::MachineApplicable,
2003+
)
2004+
.span_note(orig_vis.span, "explicit visibility first seen here");
2005+
}
19822006
}
19832007
}
19842008
return Err(err);

compiler/rustc_parse/src/parser/ty.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -474,7 +474,8 @@ impl<'a> Parser<'a> {
474474
params: Vec<GenericParam>,
475475
recover_return_sign: RecoverReturnSign,
476476
) -> PResult<'a, TyKind> {
477-
let ast::FnHeader { ext, unsafety, constness, asyncness } = self.parse_fn_front_matter()?;
477+
let ast::FnHeader { ext, unsafety, constness, asyncness } =
478+
self.parse_fn_front_matter(None)?;
478479
let decl = self.parse_fn_decl(|_| false, AllowPlus::No, recover_return_sign)?;
479480
let whole_span = lo.to(self.prev_token.span);
480481
if let ast::Const::Yes(span) = constness {

0 commit comments

Comments
 (0)