diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs index c44ccfadda52d..ee24286241468 100644 --- a/compiler/rustc_parse/src/parser/item.rs +++ b/compiler/rustc_parse/src/parser/item.rs @@ -1010,9 +1010,18 @@ impl<'a> Parser<'a> { ) -> PResult<'a, ItemInfo> { let impl_span = self.token.span; let mut err = self.expected_ident_found(); - let mut impl_info = self.parse_item_impl(attrs, defaultness)?; + + // Only try to recover if this is implementing a trait for a type + let mut impl_info = match self.parse_item_impl(attrs, defaultness) { + Ok(impl_info) => impl_info, + Err(mut recovery_error) => { + // Recovery failed, raise the "expected identifier" error + recovery_error.cancel(); + return Err(err); + } + }; + match impl_info.1 { - // only try to recover if this is implementing a trait for a type ItemKind::Impl(box ImplKind { of_trait: Some(ref trai), ref mut constness, .. }) => { @@ -1030,6 +1039,7 @@ impl<'a> Parser<'a> { ItemKind::Impl { .. } => return Err(err), _ => unreachable!(), } + Ok(impl_info) } diff --git a/src/bootstrap/install.rs b/src/bootstrap/install.rs index fd0acc3a919b0..22124ec67f5f3 100644 --- a/src/bootstrap/install.rs +++ b/src/bootstrap/install.rs @@ -29,7 +29,7 @@ fn install_sh( let prefix = default_path(&builder.config.prefix, "/usr/local"); let sysconfdir = prefix.join(default_path(&builder.config.sysconfdir, "/etc")); let datadir = prefix.join(default_path(&builder.config.datadir, "share")); - let docdir = prefix.join(default_path(&builder.config.docdir, "share/doc")); + let docdir = prefix.join(default_path(&builder.config.docdir, "share/doc/rust")); let mandir = prefix.join(default_path(&builder.config.mandir, "share/man")); let libdir = prefix.join(default_path(&builder.config.libdir, "lib")); let bindir = prefix.join(&builder.config.bindir); // Default in config.rs diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 03454bb8b7ff0..d14f15051413b 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -962,7 +962,7 @@ impl<'a> Clean for (&'a [hir::Ty<'a>], hir::BodyId) { .iter() .enumerate() .map(|(i, ty)| Argument { - name: Symbol::intern(&rustc_hir_pretty::param_to_string(&body.params[i])), + name: name_from_pat(&body.params[i].pat), type_: ty.clean(cx), }) .collect(), diff --git a/src/librustdoc/clean/utils.rs b/src/librustdoc/clean/utils.rs index e380d4672d055..7784a5d23422f 100644 --- a/src/librustdoc/clean/utils.rs +++ b/src/librustdoc/clean/utils.rs @@ -315,6 +315,25 @@ crate fn strip_path(path: &Path) -> Path { Path { global: path.global, res: path.res, segments } } +crate fn qpath_to_string(p: &hir::QPath<'_>) -> String { + let segments = match *p { + hir::QPath::Resolved(_, ref path) => &path.segments, + hir::QPath::TypeRelative(_, ref segment) => return segment.ident.to_string(), + hir::QPath::LangItem(lang_item, ..) => return lang_item.name().to_string(), + }; + + let mut s = String::new(); + for (i, seg) in segments.iter().enumerate() { + if i > 0 { + s.push_str("::"); + } + if seg.ident.name != kw::PathRoot { + s.push_str(&seg.ident.as_str()); + } + } + s +} + crate fn build_deref_target_impls(cx: &DocContext<'_>, items: &[Item], ret: &mut Vec) { let tcx = cx.tcx; @@ -352,6 +371,54 @@ impl ToSource for rustc_span::Span { } } +crate fn name_from_pat(p: &hir::Pat<'_>) -> Symbol { + use rustc_hir::*; + debug!("trying to get a name from pattern: {:?}", p); + + Symbol::intern(&match p.kind { + PatKind::Wild => return kw::Underscore, + PatKind::Binding(_, _, ident, _) => return ident.name, + PatKind::TupleStruct(ref p, ..) | PatKind::Path(ref p) => qpath_to_string(p), + PatKind::Struct(ref name, ref fields, etc) => format!( + "{} {{ {}{} }}", + qpath_to_string(name), + fields + .iter() + .map(|fp| format!("{}: {}", fp.ident, name_from_pat(&fp.pat))) + .collect::>() + .join(", "), + if etc { ", .." } else { "" } + ), + PatKind::Or(ref pats) => pats + .iter() + .map(|p| name_from_pat(&**p).to_string()) + .collect::>() + .join(" | "), + PatKind::Tuple(ref elts, _) => format!( + "({})", + elts.iter() + .map(|p| name_from_pat(&**p).to_string()) + .collect::>() + .join(", ") + ), + PatKind::Box(ref p) => return name_from_pat(&**p), + PatKind::Ref(ref p, _) => return name_from_pat(&**p), + PatKind::Lit(..) => { + warn!( + "tried to get argument name from PatKind::Lit, which is silly in function arguments" + ); + return Symbol::intern("()"); + } + PatKind::Range(..) => return kw::Underscore, + PatKind::Slice(ref begin, ref mid, ref end) => { + let begin = begin.iter().map(|p| name_from_pat(&**p).to_string()); + let mid = mid.as_ref().map(|p| format!("..{}", name_from_pat(&**p))).into_iter(); + let end = end.iter().map(|p| name_from_pat(&**p).to_string()); + format!("[{}]", begin.chain(mid).chain(end).collect::>().join(", ")) + } + }) +} + crate fn print_const(cx: &DocContext<'_>, n: &'tcx ty::Const<'_>) -> String { match n.val { ty::ConstKind::Unevaluated(def, _, promoted) => { diff --git a/src/stage0.txt b/src/stage0.txt index 3f1d7b576904e..a85f8550d4ebc 100644 --- a/src/stage0.txt +++ b/src/stage0.txt @@ -12,7 +12,7 @@ # stable release's version number. `date` is the date where the release we're # bootstrapping off was released. -date: 2021-02-09 +date: 2021-02-11 rustc: 1.50.0 # We use a nightly rustfmt to format the source because it solves some @@ -39,4 +39,4 @@ rustc: 1.50.0 # looking at a beta source tarball and it's uncommented we'll shortly comment it # out. -dev: 1 +#dev: 1 diff --git a/src/test/rustdoc/mut-params.rs b/src/test/rustdoc/mut-params.rs new file mode 100644 index 0000000000000..1ef7e304fa256 --- /dev/null +++ b/src/test/rustdoc/mut-params.rs @@ -0,0 +1,18 @@ +// Rustdoc shouldn't display `mut` in function arguments, which are +// implementation details. Regression test for #81289. + +#![crate_name = "foo"] + +pub struct Foo; + +// @count foo/struct.Foo.html '//*[@class="impl-items"]//*[@class="method"]' 2 +// @!has - '//*[@class="impl-items"]//*[@class="method"]' 'mut' +impl Foo { + pub fn foo(mut self) {} + + pub fn bar(mut bar: ()) {} +} + +// @count foo/fn.baz.html '//*[@class="rust fn"]' 1 +// @!has - '//*[@class="rust fn"]' 'mut' +pub fn baz(mut foo: Foo) {} diff --git a/src/test/rustdoc/range-arg-pattern.rs b/src/test/rustdoc/range-arg-pattern.rs index f4cc36b1055ad..c08faaad0eccf 100644 --- a/src/test/rustdoc/range-arg-pattern.rs +++ b/src/test/rustdoc/range-arg-pattern.rs @@ -1,5 +1,5 @@ #![crate_name = "foo"] // @has foo/fn.f.html -// @has - '//*[@class="rust fn"]' 'pub fn f(0u8 ...255: u8)' +// @has - '//*[@class="rust fn"]' 'pub fn f(_: u8)' pub fn f(0u8...255: u8) {} diff --git a/src/test/ui/parser/issue-81806.rs b/src/test/ui/parser/issue-81806.rs new file mode 100644 index 0000000000000..ca86788dff79c --- /dev/null +++ b/src/test/ui/parser/issue-81806.rs @@ -0,0 +1,5 @@ +trait T { const +impl //~ ERROR: expected identifier, found keyword `impl` +} + +fn main() {} diff --git a/src/test/ui/parser/issue-81806.stderr b/src/test/ui/parser/issue-81806.stderr new file mode 100644 index 0000000000000..b8ada11d922b2 --- /dev/null +++ b/src/test/ui/parser/issue-81806.stderr @@ -0,0 +1,17 @@ +error: expected identifier, found keyword `impl` + --> $DIR/issue-81806.rs:2:1 + | +LL | trait T { const + | - while parsing this item list starting here +LL | impl + | ^^^^ expected identifier, found keyword +LL | } + | - the item list ends here + | +help: you can escape reserved keywords to use them as identifiers + | +LL | r#impl + | ^^^^^^ + +error: aborting due to previous error +