diff --git a/compiler/rustc_parse/src/parser/ty.rs b/compiler/rustc_parse/src/parser/ty.rs index 1766b0293de52..867974672ea01 100644 --- a/compiler/rustc_parse/src/parser/ty.rs +++ b/compiler/rustc_parse/src/parser/ty.rs @@ -733,8 +733,9 @@ impl<'a> Parser<'a> { // `where`, so stop if it's it. // We also continue if we find types (not traits), again for error recovery. while self.can_begin_bound() - || self.token.can_begin_type() - || (self.token.is_reserved_ident() && !self.token.is_keyword(kw::Where)) + || (self.may_recover() + && (self.token.can_begin_type() + || (self.token.is_reserved_ident() && !self.token.is_keyword(kw::Where)))) { if self.token.is_keyword(kw::Dyn) { // Account for `&dyn Trait + dyn Other`. diff --git a/src/bootstrap/dist.rs b/src/bootstrap/dist.rs index 2e4f753965ded..6594b23c56b03 100644 --- a/src/bootstrap/dist.rs +++ b/src/bootstrap/dist.rs @@ -952,7 +952,7 @@ impl Step for PlainSourceTarball { "Cargo.toml", "Cargo.lock", ]; - let src_dirs = ["src", "compiler", "library"]; + let src_dirs = ["src", "compiler", "library", "tests"]; copy_src_dirs(builder, &builder.src, &src_dirs, &[], &plain_dst_src); diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 20984696b6c01..0f0e16265b468 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -2111,10 +2111,12 @@ fn get_all_import_attributes<'hir>( ) { let hir_map = tcx.hir(); let mut visitor = OneLevelVisitor::new(hir_map, target_hir_id); + let mut visited = FxHashSet::default(); // If the item is an import and has at least a path with two parts, we go into it. while let hir::ItemKind::Use(path, _) = item.kind && path.segments.len() > 1 && - let hir::def::Res::Def(_, def_id) = path.segments[path.segments.len() - 2].res + let hir::def::Res::Def(_, def_id) = path.segments[path.segments.len() - 2].res && + visited.insert(def_id) { if let Some(hir::Node::Item(parent_item)) = hir_map.get_if_local(def_id) { // We add the attributes from this import into the list. diff --git a/tests/rustdoc/issue-107350.rs b/tests/rustdoc/issue-107350.rs new file mode 100644 index 0000000000000..75f378ed24980 --- /dev/null +++ b/tests/rustdoc/issue-107350.rs @@ -0,0 +1,18 @@ +// This is a regression test for . +// It shouldn't loop indefinitely. + +#![crate_name = "foo"] + +// @has 'foo/oops/enum.OhNo.html' + +pub mod oops { + pub use crate::oops::OhNo; + + mod inner { + pub enum OhNo { + Item = 1, + } + } + + pub use self::inner::*; +} diff --git a/tests/ui/parser/bad-recover-kw-after-impl.rs b/tests/ui/parser/bad-recover-kw-after-impl.rs new file mode 100644 index 0000000000000..218cd7678594f --- /dev/null +++ b/tests/ui/parser/bad-recover-kw-after-impl.rs @@ -0,0 +1,15 @@ +// check-pass + +// edition:2021 +// for the `impl` + keyword test + +macro_rules! impl_primitive { + ($ty:ty) => { + compile_error!("whoops"); + }; + (impl async) => {}; +} + +impl_primitive!(impl async); + +fn main() {} diff --git a/tests/ui/parser/bad-recover-ty-after-impl.rs b/tests/ui/parser/bad-recover-ty-after-impl.rs new file mode 100644 index 0000000000000..510e08ba091a4 --- /dev/null +++ b/tests/ui/parser/bad-recover-ty-after-impl.rs @@ -0,0 +1,17 @@ +// check-pass + +macro_rules! impl_primitive { + ($ty:ty) => { impl_primitive!(impl $ty); }; + (impl $ty:ty) => { fn a(_: $ty) {} } +} + +impl_primitive! { u8 } + +macro_rules! test { + ($ty:ty) => { compile_error!("oh no"); }; + (impl &) => {}; +} + +test!(impl &); + +fn main() {}