From 48e812687e25955d62b1fb5e19f2f2ae4e728710 Mon Sep 17 00:00:00 2001 From: overlookmotel Date: Wed, 1 Mar 2023 23:36:41 +0000 Subject: [PATCH 1/6] Fix docs for `alloc::realloc` Fixes #108546 --- library/core/src/alloc/global.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/library/core/src/alloc/global.rs b/library/core/src/alloc/global.rs index 18da70451f299..c582111701a99 100644 --- a/library/core/src/alloc/global.rs +++ b/library/core/src/alloc/global.rs @@ -235,7 +235,8 @@ pub unsafe trait GlobalAlloc { /// * `new_size` must be greater than zero. /// /// * `new_size`, when rounded up to the nearest multiple of `layout.align()`, - /// must not overflow (i.e., the rounded value must be less than `usize::MAX`). + /// must not overflow isize (i.e., the rounded value must be less than or + /// equal to `isize::MAX`). /// /// (Extension subtraits might provide more specific bounds on /// behavior, e.g., guarantee a sentinel address or a null pointer From 272dc5a6d5967c0816564894b4fd86835a860d97 Mon Sep 17 00:00:00 2001 From: bohan Date: Thu, 4 May 2023 16:30:02 +0800 Subject: [PATCH 2/6] fix(parse): return unpected when current token is EOF --- compiler/rustc_parse/src/parser/mod.rs | 4 +++- tests/ui/parser/issues/issue-111148.rs | 2 ++ tests/ui/parser/issues/issue-111148.stderr | 8 ++++++++ 3 files changed, 13 insertions(+), 1 deletion(-) create mode 100644 tests/ui/parser/issues/issue-111148.rs create mode 100644 tests/ui/parser/issues/issue-111148.stderr diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs index 0c265d7af0e6e..c23420661fa59 100644 --- a/compiler/rustc_parse/src/parser/mod.rs +++ b/compiler/rustc_parse/src/parser/mod.rs @@ -536,7 +536,9 @@ impl<'a> Parser<'a> { } else if inedible.contains(&self.token.kind) { // leave it in the input Ok(false) - } else if self.last_unexpected_token_span == Some(self.token.span) { + } else if self.token.kind != token::Eof + && self.last_unexpected_token_span == Some(self.token.span) + { FatalError.raise(); } else { self.expected_one_of_not_found(edible, inedible) diff --git a/tests/ui/parser/issues/issue-111148.rs b/tests/ui/parser/issues/issue-111148.rs new file mode 100644 index 0000000000000..2502beab44373 --- /dev/null +++ b/tests/ui/parser/issues/issue-111148.rs @@ -0,0 +1,2 @@ +fn a<# +//~^ ERROR expected one of `#`, `>`, `const`, identifier, or lifetime, found `<` diff --git a/tests/ui/parser/issues/issue-111148.stderr b/tests/ui/parser/issues/issue-111148.stderr new file mode 100644 index 0000000000000..e6595a5cbcc45 --- /dev/null +++ b/tests/ui/parser/issues/issue-111148.stderr @@ -0,0 +1,8 @@ +error: expected one of `#`, `>`, `const`, identifier, or lifetime, found `<` + --> $DIR/issue-111148.rs:1:6 + | +LL | fn a<# + | ^ expected one of `#`, `>`, `const`, identifier, or lifetime + +error: aborting due to previous error + From f0c9c1eb19864d95e6348d79c54fa4a412019f3a Mon Sep 17 00:00:00 2001 From: Finn Bear Date: Tue, 16 May 2023 13:39:17 -0700 Subject: [PATCH 3/6] Use an unbounded lifetime in String::leak. --- library/alloc/src/string.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/library/alloc/src/string.rs b/library/alloc/src/string.rs index 088139a6907b8..559704d90af01 100644 --- a/library/alloc/src/string.rs +++ b/library/alloc/src/string.rs @@ -1851,7 +1851,7 @@ impl String { } /// Consumes and leaks the `String`, returning a mutable reference to the contents, - /// `&'static mut str`. + /// `&'a mut str`. /// /// This is mainly useful for data that lives for the remainder of /// the program's life. Dropping the returned reference will cause a memory @@ -1874,7 +1874,7 @@ impl String { /// ``` #[unstable(feature = "string_leak", issue = "102929")] #[inline] - pub fn leak(self) -> &'static mut str { + pub fn leak<'a>(self) -> &'a mut str { let slice = self.vec.leak(); unsafe { from_utf8_unchecked_mut(slice) } } From fbdc5118d55c05a7dfa1017c3f3ec2c1c9370d6e Mon Sep 17 00:00:00 2001 From: Nicky Lim Date: Thu, 25 May 2023 20:31:56 +0800 Subject: [PATCH 4/6] Add `ItemTemplate` trait --- src/librustdoc/html/render/print_item.rs | 95 +++++++++++-------- src/librustdoc/html/templates/item_union.html | 8 +- 2 files changed, 61 insertions(+), 42 deletions(-) diff --git a/src/librustdoc/html/render/print_item.rs b/src/librustdoc/html/render/print_item.rs index 4cc81e860f09a..b944dc7b26040 100644 --- a/src/librustdoc/html/render/print_item.rs +++ b/src/librustdoc/html/render/print_item.rs @@ -9,6 +9,8 @@ use rustc_middle::middle::stability; use rustc_middle::ty::{self, TyCtxt}; use rustc_span::hygiene::MacroKind; use rustc_span::symbol::{kw, sym, Symbol}; +use std::borrow::Borrow; +use std::cell::{RefCell, RefMut}; use std::cmp::Ordering; use std::fmt; use std::rc::Rc; @@ -216,6 +218,53 @@ fn toggle_close(mut w: impl fmt::Write) { w.write_str("").unwrap(); } +trait ItemTemplate<'a, 'cx: 'a>: askama::Template + fmt::Display { + fn item_and_mut_cx(&self) -> (&'a clean::Item, RefMut<'_, &'a mut Context<'cx>>); +} + +fn item_template_document<'a: 'b, 'b, 'cx: 'a>( + templ: &'b impl ItemTemplate<'a, 'cx>, +) -> impl fmt::Display + Captures<'a> + 'b + Captures<'cx> { + display_fn(move |f| { + let (item, mut cx) = templ.item_and_mut_cx(); + let v = document(*cx, item, None, HeadingOffset::H2); + write!(f, "{v}") + }) +} + +fn item_template_document_type_layout<'a: 'b, 'b, 'cx: 'a>( + templ: &'b impl ItemTemplate<'a, 'cx>, +) -> impl fmt::Display + Captures<'a> + 'b + Captures<'cx> { + display_fn(move |f| { + let (item, cx) = templ.item_and_mut_cx(); + let def_id = item.item_id.expect_def_id(); + let v = document_type_layout(*cx, def_id); + write!(f, "{v}") + }) +} + +fn item_template_render_attributes_in_pre<'a: 'b, 'b, 'cx: 'a>( + templ: &'b impl ItemTemplate<'a, 'cx>, +) -> impl fmt::Display + Captures<'a> + 'b + Captures<'cx> { + display_fn(move |f| { + let (item, cx) = templ.item_and_mut_cx(); + let tcx = cx.tcx(); + let v = render_attributes_in_pre(item, "", tcx); + write!(f, "{v}") + }) +} + +fn item_template_render_assoc_items<'a: 'b, 'b, 'cx: 'a>( + templ: &'b impl ItemTemplate<'a, 'cx>, +) -> impl fmt::Display + Captures<'a> + 'b + Captures<'cx> { + display_fn(move |f| { + let (item, mut cx) = templ.item_and_mut_cx(); + let def_id = item.item_id.expect_def_id(); + let v = render_assoc_items(*cx, item, def_id, AssocItemRender::All); + write!(f, "{v}") + }) +} + fn item_module(w: &mut Buffer, cx: &mut Context<'_>, item: &clean::Item, items: &[clean::Item]) { write!(w, "{}", document(cx, item, None, HeadingOffset::H2)); @@ -1131,32 +1180,18 @@ fn item_union(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, s: &clean: #[derive(Template)] #[template(path = "item_union.html")] struct ItemUnion<'a, 'cx> { - cx: std::cell::RefCell<&'a mut Context<'cx>>, + cx: RefCell<&'a mut Context<'cx>>, it: &'a clean::Item, s: &'a clean::Union, } - impl<'a, 'cx: 'a> ItemUnion<'a, 'cx> { - fn render_assoc_items<'b>( - &'b self, - ) -> impl fmt::Display + Captures<'a> + 'b + Captures<'cx> { - display_fn(move |f| { - let def_id = self.it.item_id.expect_def_id(); - let mut cx = self.cx.borrow_mut(); - let v = render_assoc_items(*cx, self.it, def_id, AssocItemRender::All); - write!(f, "{v}") - }) - } - fn document_type_layout<'b>( - &'b self, - ) -> impl fmt::Display + Captures<'a> + 'b + Captures<'cx> { - display_fn(move |f| { - let def_id = self.it.item_id.expect_def_id(); - let cx = self.cx.borrow_mut(); - let v = document_type_layout(*cx, def_id); - write!(f, "{v}") - }) + impl<'a, 'cx: 'a> ItemTemplate<'a, 'cx> for ItemUnion<'a, 'cx> { + fn item_and_mut_cx(&self) -> (&'a clean::Item, RefMut<'_, &'a mut Context<'cx>>) { + (self.it, self.cx.borrow_mut()) } + } + + impl<'a, 'cx: 'a> ItemUnion<'a, 'cx> { fn render_union<'b>(&'b self) -> impl fmt::Display + Captures<'a> + 'b + Captures<'cx> { display_fn(move |f| { let cx = self.cx.borrow_mut(); @@ -1164,22 +1199,6 @@ fn item_union(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, s: &clean: write!(f, "{v}") }) } - fn render_attributes_in_pre<'b>( - &'b self, - ) -> impl fmt::Display + Captures<'a> + 'b + Captures<'cx> { - display_fn(move |f| { - let tcx = self.cx.borrow().tcx(); - let v = render_attributes_in_pre(self.it, "", tcx); - write!(f, "{v}") - }) - } - fn document<'b>(&'b self) -> impl fmt::Display + Captures<'a> + 'b + Captures<'cx> { - display_fn(move |f| { - let mut cx = self.cx.borrow_mut(); - let v = document(*cx, self.it, None, HeadingOffset::H2); - write!(f, "{v}") - }) - } fn document_field<'b>( &'b self, field: &'a clean::Item, @@ -1219,7 +1238,7 @@ fn item_union(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, s: &clean: } } - ItemUnion { cx: std::cell::RefCell::new(cx), it, s }.render_into(w).unwrap(); + ItemUnion { cx: RefCell::new(cx), it, s }.render_into(w).unwrap(); } fn print_tuple_struct_fields<'a, 'cx: 'a>( diff --git a/src/librustdoc/html/templates/item_union.html b/src/librustdoc/html/templates/item_union.html index a01457971c178..c219670051332 100644 --- a/src/librustdoc/html/templates/item_union.html +++ b/src/librustdoc/html/templates/item_union.html @@ -1,8 +1,8 @@

-    {{ self.render_attributes_in_pre() | safe }}
+    {{ self::item_template_render_attributes_in_pre(self.borrow()) | safe }}
     {{ self.render_union() | safe }}
 
-{{ self.document() | safe }} +{{ self::item_template_document(self.borrow()) | safe }} {% if self.fields_iter().peek().is_some() %}

Fields§ @@ -19,5 +19,5 @@

{{ self.document_field(field) | safe }} {% endfor %} {% endif %} -{{ self.render_assoc_items() | safe }} -{{ self.document_type_layout() | safe }} +{{ self::item_template_render_assoc_items(self.borrow()) | safe }} +{{ self::item_template_document_type_layout(self.borrow()) | safe }} From b7db3de8d523145e2530619421eef2d10e116e96 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sat, 27 May 2023 14:46:54 +0200 Subject: [PATCH 5/6] Clean up usage of `cx.tcx` when `tcx` is already set into a variable --- src/librustdoc/clean/inline.rs | 4 +-- src/librustdoc/clean/utils.rs | 2 +- src/librustdoc/formats/cache.rs | 2 +- src/librustdoc/html/render/print_item.rs | 17 +++++----- src/librustdoc/html/render/type_layout.rs | 4 +-- .../passes/collect_intra_doc_links.rs | 4 +-- src/librustdoc/passes/collect_trait_impls.rs | 34 +++++++++---------- .../passes/lint/unescaped_backticks.rs | 2 +- src/librustdoc/visit_ast.rs | 13 ++++--- 9 files changed, 39 insertions(+), 43 deletions(-) diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index c852f9cca2bfd..7dc08b3b1ffa6 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -355,9 +355,9 @@ pub(crate) fn build_impl( return; } - let _prof_timer = cx.tcx.sess.prof.generic_activity("build_impl"); - let tcx = cx.tcx; + let _prof_timer = tcx.sess.prof.generic_activity("build_impl"); + let associated_trait = tcx.impl_trait_ref(did).map(ty::EarlyBinder::skip_binder); // Only inline impl if the implemented trait is diff --git a/src/librustdoc/clean/utils.rs b/src/librustdoc/clean/utils.rs index 17aa6b38e389c..366f93952963f 100644 --- a/src/librustdoc/clean/utils.rs +++ b/src/librustdoc/clean/utils.rs @@ -193,7 +193,7 @@ pub(crate) fn build_deref_target_impls( }; if let Some(prim) = target.primitive_type() { - let _prof_timer = cx.tcx.sess.prof.generic_activity("build_primitive_inherent_impls"); + let _prof_timer = tcx.sess.prof.generic_activity("build_primitive_inherent_impls"); for did in prim.impls(tcx).filter(|did| !did.is_local()) { inline::build_impl(cx, did, None, ret); } diff --git a/src/librustdoc/formats/cache.rs b/src/librustdoc/formats/cache.rs index c0730e90740eb..297e70a4b2f2a 100644 --- a/src/librustdoc/formats/cache.rs +++ b/src/librustdoc/formats/cache.rs @@ -147,7 +147,7 @@ impl Cache { // Cache where all our extern crates are located // FIXME: this part is specific to HTML so it'd be nice to remove it from the common code - for &crate_num in cx.tcx.crates(()) { + for &crate_num in tcx.crates(()) { let e = ExternalCrate { crate_num }; let name = e.name(tcx); diff --git a/src/librustdoc/html/render/print_item.rs b/src/librustdoc/html/render/print_item.rs index 4cc81e860f09a..dd23abf0e2c9b 100644 --- a/src/librustdoc/html/render/print_item.rs +++ b/src/librustdoc/html/render/print_item.rs @@ -356,18 +356,18 @@ fn item_module(w: &mut Buffer, cx: &mut Context<'_>, item: &clean::Item, items: clean::ImportItem(ref import) => { let stab_tags = if let Some(import_def_id) = import.source.did { - let ast_attrs = cx.tcx().get_attrs_unchecked(import_def_id); + let ast_attrs = tcx.get_attrs_unchecked(import_def_id); let import_attrs = Box::new(clean::Attributes::from_ast(ast_attrs)); // Just need an item with the correct def_id and attrs let import_item = clean::Item { item_id: import_def_id.into(), attrs: import_attrs, - cfg: ast_attrs.cfg(cx.tcx(), &cx.cache().hidden_cfg), + cfg: ast_attrs.cfg(tcx, &cx.cache().hidden_cfg), ..myitem.clone() }; - let stab_tags = Some(extra_info_tags(&import_item, item, cx.tcx()).to_string()); + let stab_tags = Some(extra_info_tags(&import_item, item, tcx).to_string()); stab_tags } else { None @@ -405,8 +405,7 @@ fn item_module(w: &mut Buffer, cx: &mut Context<'_>, item: &clean::Item, items: let unsafety_flag = match *myitem.kind { clean::FunctionItem(_) | clean::ForeignFunctionItem(_) - if myitem.fn_header(cx.tcx()).unwrap().unsafety - == hir::Unsafety::Unsafe => + if myitem.fn_header(tcx).unwrap().unsafety == hir::Unsafety::Unsafe => { "" } @@ -439,7 +438,7 @@ fn item_module(w: &mut Buffer, cx: &mut Context<'_>, item: &clean::Item, items: {docs_before}{docs}{docs_after}", name = myitem.name.unwrap(), visibility_emoji = visibility_emoji, - stab_tags = extra_info_tags(myitem, item, cx.tcx()), + stab_tags = extra_info_tags(myitem, item, tcx), class = myitem.type_(), unsafety_flag = unsafety_flag, href = item_path(myitem.type_(), myitem.name.unwrap().as_str()), @@ -886,7 +885,7 @@ fn item_trait(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean: write_small_section_header(w, "foreign-impls", "Implementations on Foreign Types", ""); for implementor in foreign { - let provided_methods = implementor.inner_impl().provided_trait_methods(cx.tcx()); + let provided_methods = implementor.inner_impl().provided_trait_methods(tcx); let assoc_link = AssocItemLink::GotoSource(implementor.impl_item.item_id, &provided_methods); render_impl( @@ -919,7 +918,7 @@ fn item_trait(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean: } w.write_str(""); - if t.is_auto(cx.tcx()) { + if t.is_auto(tcx) { write_small_section_header( w, "synthetic-implementors", @@ -948,7 +947,7 @@ fn item_trait(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean: "
", ); - if t.is_auto(cx.tcx()) { + if t.is_auto(tcx) { write_small_section_header( w, "synthetic-implementors", diff --git a/src/librustdoc/html/render/type_layout.rs b/src/librustdoc/html/render/type_layout.rs index 22aec623335e8..c9b95b1e64599 100644 --- a/src/librustdoc/html/render/type_layout.rs +++ b/src/librustdoc/html/render/type_layout.rs @@ -54,13 +54,13 @@ pub(crate) fn document_type_layout<'a, 'cx: 'a>( } else if let Primitive::Int(i, _) = tag.primitive() { i.size().bytes() } else { - span_bug!(cx.tcx().def_span(ty_def_id), "tag is neither niche nor int") + span_bug!(tcx.def_span(ty_def_id), "tag is neither niche nor int") }; variants .iter_enumerated() .map(|(variant_idx, variant_layout)| { let Adt(adt, _) = type_layout.ty.kind() else { - span_bug!(cx.tcx().def_span(ty_def_id), "not an adt") + span_bug!(tcx.def_span(ty_def_id), "not an adt") }; let name = adt.variant(variant_idx).name; let is_unsized = variant_layout.abi.is_unsized(); diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs index 9e6894a77dfa0..8ab7e58bf7498 100644 --- a/src/librustdoc/passes/collect_intra_doc_links.rs +++ b/src/librustdoc/passes/collect_intra_doc_links.rs @@ -723,7 +723,7 @@ fn resolve_associated_trait_item<'a>( .iter() .flat_map(|&(impl_, trait_)| { filter_assoc_items_by_name_and_namespace( - cx.tcx, + tcx, trait_, Ident::with_dummy_span(item_name), ns, @@ -1706,7 +1706,7 @@ fn resolution_failure( if let Ok(v_res) = collector.resolve(start, ns, item_id, module_id) { debug!("found partial_res={:?}", v_res); if !v_res.is_empty() { - *partial_res = Some(full_res(collector.cx.tcx, v_res[0])); + *partial_res = Some(full_res(tcx, v_res[0])); *unresolved = end.into(); break 'outer; } diff --git a/src/librustdoc/passes/collect_trait_impls.rs b/src/librustdoc/passes/collect_trait_impls.rs index 8d204ddb79e39..fbf827cce0984 100644 --- a/src/librustdoc/passes/collect_trait_impls.rs +++ b/src/librustdoc/passes/collect_trait_impls.rs @@ -19,9 +19,10 @@ pub(crate) const COLLECT_TRAIT_IMPLS: Pass = Pass { }; pub(crate) fn collect_trait_impls(mut krate: Crate, cx: &mut DocContext<'_>) -> Crate { + let tcx = cx.tcx; // We need to check if there are errors before running this pass because it would crash when // we try to get auto and blanket implementations. - if cx.tcx.sess.diagnostic().has_errors_or_lint_errors().is_some() { + if tcx.sess.diagnostic().has_errors_or_lint_errors().is_some() { return krate; } @@ -32,8 +33,7 @@ pub(crate) fn collect_trait_impls(mut krate: Crate, cx: &mut DocContext<'_>) -> }); let local_crate = ExternalCrate { crate_num: LOCAL_CRATE }; - let prims: FxHashSet = - local_crate.primitives(cx.tcx).iter().map(|p| p.1).collect(); + let prims: FxHashSet = local_crate.primitives(tcx).iter().map(|p| p.1).collect(); let crate_items = { let mut coll = ItemCollector::new(); @@ -46,9 +46,9 @@ pub(crate) fn collect_trait_impls(mut krate: Crate, cx: &mut DocContext<'_>) -> // External trait impls. { - let _prof_timer = cx.tcx.sess.prof.generic_activity("build_extern_trait_impls"); - for &cnum in cx.tcx.crates(()) { - for &impl_def_id in cx.tcx.trait_impls_in_crate(cnum) { + let _prof_timer = tcx.sess.prof.generic_activity("build_extern_trait_impls"); + for &cnum in tcx.crates(()) { + for &impl_def_id in tcx.trait_impls_in_crate(cnum) { inline::build_impl(cx, impl_def_id, None, &mut new_items_external); } } @@ -56,14 +56,13 @@ pub(crate) fn collect_trait_impls(mut krate: Crate, cx: &mut DocContext<'_>) -> // Local trait impls. { - let _prof_timer = cx.tcx.sess.prof.generic_activity("build_local_trait_impls"); + let _prof_timer = tcx.sess.prof.generic_activity("build_local_trait_impls"); let mut attr_buf = Vec::new(); - for &impl_def_id in cx.tcx.trait_impls_in_crate(LOCAL_CRATE) { - let mut parent = Some(cx.tcx.parent(impl_def_id)); + for &impl_def_id in tcx.trait_impls_in_crate(LOCAL_CRATE) { + let mut parent = Some(tcx.parent(impl_def_id)); while let Some(did) = parent { attr_buf.extend( - cx.tcx - .get_attrs(did, sym::doc) + tcx.get_attrs(did, sym::doc) .filter(|attr| { if let Some([attr]) = attr.meta_item_list().as_deref() { attr.has_name(sym::cfg) @@ -73,25 +72,24 @@ pub(crate) fn collect_trait_impls(mut krate: Crate, cx: &mut DocContext<'_>) -> }) .cloned(), ); - parent = cx.tcx.opt_parent(did); + parent = tcx.opt_parent(did); } inline::build_impl(cx, impl_def_id, Some((&attr_buf, None)), &mut new_items_local); attr_buf.clear(); } } - cx.tcx.sess.prof.generic_activity("build_primitive_trait_impls").run(|| { - for def_id in PrimitiveType::all_impls(cx.tcx) { + tcx.sess.prof.generic_activity("build_primitive_trait_impls").run(|| { + for def_id in PrimitiveType::all_impls(tcx) { // Try to inline primitive impls from other crates. if !def_id.is_local() { inline::build_impl(cx, def_id, None, &mut new_items_external); } } - for (prim, did) in PrimitiveType::primitive_locations(cx.tcx) { + for (prim, did) in PrimitiveType::primitive_locations(tcx) { // Do not calculate blanket impl list for docs that are not going to be rendered. // While the `impl` blocks themselves are only in `libcore`, the module with `doc` // attached is directly included in `libstd` as well. - let tcx = cx.tcx; if did.is_local() { for def_id in prim.impls(tcx).filter(|def_id| { // Avoid including impl blocks with filled-in generics. @@ -157,7 +155,7 @@ pub(crate) fn collect_trait_impls(mut krate: Crate, cx: &mut DocContext<'_>) -> // scan through included items ahead of time to splice in Deref targets to the "valid" sets for it in new_items_external.iter().chain(new_items_local.iter()) { if let ImplItem(box Impl { ref for_, ref trait_, ref items, .. }) = *it.kind && - trait_.as_ref().map(|t| t.def_id()) == cx.tcx.lang_items().deref_trait() && + trait_.as_ref().map(|t| t.def_id()) == tcx.lang_items().deref_trait() && cleaner.keep_impl(for_, true) { let target = items @@ -199,7 +197,7 @@ pub(crate) fn collect_trait_impls(mut krate: Crate, cx: &mut DocContext<'_>) -> if let ImplItem(box Impl { ref for_, ref trait_, ref kind, .. }) = *it.kind { cleaner.keep_impl( for_, - trait_.as_ref().map(|t| t.def_id()) == cx.tcx.lang_items().deref_trait(), + trait_.as_ref().map(|t| t.def_id()) == tcx.lang_items().deref_trait(), ) || trait_.as_ref().map_or(false, |t| cleaner.keep_impl_with_def_id(t.def_id().into())) || kind.is_blanket() } else { diff --git a/src/librustdoc/passes/lint/unescaped_backticks.rs b/src/librustdoc/passes/lint/unescaped_backticks.rs index 33cef82a60cbb..6feb6537dd7d1 100644 --- a/src/librustdoc/passes/lint/unescaped_backticks.rs +++ b/src/librustdoc/passes/lint/unescaped_backticks.rs @@ -56,7 +56,7 @@ pub(crate) fn visit_item(cx: &DocContext<'_>, item: &Item) { ) .unwrap_or_else(|| item.attr_span(tcx)); - cx.tcx.struct_span_lint_hir(crate::lint::UNESCAPED_BACKTICKS, hir_id, span, "unescaped backtick", |lint| { + tcx.struct_span_lint_hir(crate::lint::UNESCAPED_BACKTICKS, hir_id, span, "unescaped backtick", |lint| { let mut help_emitted = false; match element.prev_code_guess { diff --git a/src/librustdoc/visit_ast.rs b/src/librustdoc/visit_ast.rs index 8f8dc6b709053..1681386ce192e 100644 --- a/src/librustdoc/visit_ast.rs +++ b/src/librustdoc/visit_ast.rs @@ -280,9 +280,8 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { return false; }; - let is_private = - !self.cx.cache.effective_visibilities.is_directly_public(self.cx.tcx, ori_res_did); - let is_hidden = inherits_doc_hidden(self.cx.tcx, res_did, None); + let is_private = !self.cx.cache.effective_visibilities.is_directly_public(tcx, ori_res_did); + let is_hidden = inherits_doc_hidden(tcx, res_did, None); // Only inline if requested or if the item would otherwise be stripped. if (!please_inline && !is_private && !is_hidden) || is_no_inline { @@ -290,7 +289,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { } if !please_inline && - let Some(item_def_id) = reexport_chain(self.cx.tcx, def_id, res_did).iter() + let Some(item_def_id) = reexport_chain(tcx, def_id, res_did).iter() .flat_map(|reexport| reexport.id()).map(|id| id.expect_local()) .chain(iter::once(res_did)).nth(1) && item_def_id != def_id && @@ -298,8 +297,8 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { .cx .cache .effective_visibilities - .is_directly_public(self.cx.tcx, item_def_id.to_def_id()) && - !inherits_doc_hidden(self.cx.tcx, item_def_id, None) + .is_directly_public(tcx, item_def_id.to_def_id()) && + !inherits_doc_hidden(tcx, item_def_id, None) { // The imported item is public and not `doc(hidden)` so no need to inline it. return false; @@ -313,7 +312,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { Node::Item(&hir::Item { kind: hir::ItemKind::Mod(ref m), .. }) if glob => { let prev = mem::replace(&mut self.inlining, true); for &i in m.item_ids { - let i = self.cx.tcx.hir().item(i); + let i = tcx.hir().item(i); self.visit_item_inner(i, None, Some(def_id)); } self.inlining = prev; From 6240d4518930bdf20b44109e55d047eec3221c9a Mon Sep 17 00:00:00 2001 From: dekrain Date: Mon, 13 Mar 2023 18:28:59 +0100 Subject: [PATCH 6/6] Fix ICE caused by at-expanding argument 0 instead of removing it early --- compiler/rustc_driver_impl/src/args.rs | 3 +++ compiler/rustc_driver_impl/src/lib.rs | 13 ++++++++++--- src/librustdoc/config.rs | 1 - src/librustdoc/lib.rs | 12 +++++++++++- 4 files changed, 24 insertions(+), 5 deletions(-) diff --git a/compiler/rustc_driver_impl/src/args.rs b/compiler/rustc_driver_impl/src/args.rs index 42c97cc6a9d74..5ddacc388637b 100644 --- a/compiler/rustc_driver_impl/src/args.rs +++ b/compiler/rustc_driver_impl/src/args.rs @@ -18,6 +18,9 @@ fn arg_expand(arg: String) -> Result, Error> { } } +/// **Note:** This function doesn't interpret argument 0 in any special way. +/// If this function is intended to be used with command line arguments, +/// `argv[0]` must be removed prior to calling it manually. pub fn arg_expand_all(at_args: &[String]) -> Vec { let mut args = Vec::new(); for arg in at_args { diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs index 555917c8b5e9c..88f3b24bc9864 100644 --- a/compiler/rustc_driver_impl/src/lib.rs +++ b/compiler/rustc_driver_impl/src/lib.rs @@ -237,6 +237,16 @@ fn run_compiler( Box Box + Send>, >, ) -> interface::Result<()> { + // Throw away the first argument, the name of the binary. + // In case of at_args being empty, as might be the case by + // passing empty argument array to execve under some platforms, + // just use an empty slice. + // + // This situation was possible before due to arg_expand_all being + // called before removing the argument, enabling a crash by calling + // the compiler with @empty_file as argv[0] and no more arguments. + let at_args = at_args.get(1..).unwrap_or_default(); + let args = args::arg_expand_all(at_args); let Some(matches) = handle_options(&args) else { return Ok(()) }; @@ -993,9 +1003,6 @@ pub fn print_flag_list( /// So with all that in mind, the comments below have some more detail about the /// contortions done here to get things to work out correctly. pub fn handle_options(args: &[String]) -> Option { - // Throw away the first argument, the name of the binary - let args = &args[1..]; - if args.is_empty() { // user did not write `-v` nor `-Z unstable-options`, so do not // include that extra information. diff --git a/src/librustdoc/config.rs b/src/librustdoc/config.rs index 2c514a0c8267b..22356229d0576 100644 --- a/src/librustdoc/config.rs +++ b/src/librustdoc/config.rs @@ -321,7 +321,6 @@ impl Options { matches: &getopts::Matches, args: Vec, ) -> Result<(Options, RenderOptions), i32> { - let args = &args[1..]; // Check for unstable options. nightly_options::check_nightly_options(matches, &opts()); diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index 4fcf0873600ab..da32d429dac17 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -703,13 +703,23 @@ fn run_renderer<'tcx, T: formats::FormatRenderer<'tcx>>( } fn main_args(at_args: &[String]) -> MainResult { + // Throw away the first argument, the name of the binary. + // In case of at_args being empty, as might be the case by + // passing empty argument array to execve under some platforms, + // just use an empty slice. + // + // This situation was possible before due to arg_expand_all being + // called before removing the argument, enabling a crash by calling + // the compiler with @empty_file as argv[0] and no more arguments. + let at_args = at_args.get(1..).unwrap_or_default(); + let args = rustc_driver::args::arg_expand_all(at_args); let mut options = getopts::Options::new(); for option in opts() { (option.apply)(&mut options); } - let matches = match options.parse(&args[1..]) { + let matches = match options.parse(&args) { Ok(m) => m, Err(err) => { early_error(ErrorOutputType::default(), &err.to_string());