diff --git a/compiler/rustc_middle/src/mir/terminator.rs b/compiler/rustc_middle/src/mir/terminator.rs index 62711ad92372a..db8251c7d9dc8 100644 --- a/compiler/rustc_middle/src/mir/terminator.rs +++ b/compiler/rustc_middle/src/mir/terminator.rs @@ -501,6 +501,8 @@ pub use helper::*; mod helper { use super::*; + // Note: the methods below use a `slice.chain(Option).chain(Option)` pattern so that all paths + // produce an iterator with the same concrete type. pub type Successors<'a> = impl DoubleEndedIterator + 'a; impl SwitchTargets { @@ -510,7 +512,7 @@ mod helper { #[define_opaque(Successors)] pub fn successors_for_value(&self, value: u128) -> Successors<'_> { let target = self.target_for_value(value); - (&[]).into_iter().copied().chain(Some(target).into_iter().chain(None)) + (&[]).into_iter().copied().chain(Some(target)).chain(None) } } @@ -522,10 +524,7 @@ mod helper { match *self { // 3-successors for async drop: target, unwind, dropline (parent coroutine drop) Drop { target: ref t, unwind: UnwindAction::Cleanup(u), drop: Some(d), .. } => { - slice::from_ref(t) - .into_iter() - .copied() - .chain(Some(u).into_iter().chain(Some(d))) + slice::from_ref(t).into_iter().copied().chain(Some(u)).chain(Some(d)) } // 2-successors Call { target: Some(ref t), unwind: UnwindAction::Cleanup(u), .. } @@ -534,7 +533,7 @@ mod helper { | Drop { target: ref t, unwind: _, drop: Some(u), .. } | Assert { target: ref t, unwind: UnwindAction::Cleanup(u), .. } | FalseUnwind { real_target: ref t, unwind: UnwindAction::Cleanup(u) } => { - slice::from_ref(t).into_iter().copied().chain(Some(u).into_iter().chain(None)) + slice::from_ref(t).into_iter().copied().chain(Some(u)).chain(None) } // single successor Goto { target: ref t } @@ -544,7 +543,7 @@ mod helper { | Drop { target: ref t, unwind: _, .. } | Assert { target: ref t, unwind: _, .. } | FalseUnwind { real_target: ref t, unwind: _ } => { - slice::from_ref(t).into_iter().copied().chain(None.into_iter().chain(None)) + slice::from_ref(t).into_iter().copied().chain(None).chain(None) } // No successors UnwindResume @@ -554,23 +553,24 @@ mod helper { | Unreachable | TailCall { .. } | Call { target: None, unwind: _, .. } => { - (&[]).into_iter().copied().chain(None.into_iter().chain(None)) + (&[]).into_iter().copied().chain(None).chain(None) } // Multiple successors InlineAsm { ref targets, unwind: UnwindAction::Cleanup(u), .. } => { - targets.iter().copied().chain(Some(u).into_iter().chain(None)) + targets.iter().copied().chain(Some(u)).chain(None) } InlineAsm { ref targets, unwind: _, .. } => { - targets.iter().copied().chain(None.into_iter().chain(None)) + targets.iter().copied().chain(None).chain(None) } SwitchInt { ref targets, .. } => { - targets.targets.iter().copied().chain(None.into_iter().chain(None)) + targets.targets.iter().copied().chain(None).chain(None) } // FalseEdge FalseEdge { ref real_target, imaginary_target } => slice::from_ref(real_target) .into_iter() .copied() - .chain(Some(imaginary_target).into_iter().chain(None)), + .chain(Some(imaginary_target)) + .chain(None), } } diff --git a/library/alloc/src/borrow.rs b/library/alloc/src/borrow.rs index 4659fb2a8426d..d2ab5412eeabc 100644 --- a/library/alloc/src/borrow.rs +++ b/library/alloc/src/borrow.rs @@ -16,12 +16,13 @@ use crate::fmt; #[cfg(not(no_global_oom_handling))] use crate::string::String; +// FIXME(inference): const bounds removed due to inference regressions found by crater; +// see https://github.com/rust-lang/rust/issues/147964 +// #[rustc_const_unstable(feature = "const_convert", issue = "143773")] #[stable(feature = "rust1", since = "1.0.0")] -#[rustc_const_unstable(feature = "const_convert", issue = "143773")] -impl<'a, B: ?Sized> const Borrow for Cow<'a, B> -where - B: ToOwned, - B::Owned: [const] Borrow, +impl<'a, B: ?Sized + ToOwned> Borrow for Cow<'a, B> +// where +// B::Owned: [const] Borrow, { fn borrow(&self) -> &B { &**self @@ -327,11 +328,13 @@ impl Cow<'_, B> { } } +// FIXME(inference): const bounds removed due to inference regressions found by crater; +// see https://github.com/rust-lang/rust/issues/147964 +// #[rustc_const_unstable(feature = "const_convert", issue = "143773")] #[stable(feature = "rust1", since = "1.0.0")] -#[rustc_const_unstable(feature = "const_convert", issue = "143773")] -impl const Deref for Cow<'_, B> -where - B::Owned: [const] Borrow, +impl Deref for Cow<'_, B> +// where +// B::Owned: [const] Borrow, { type Target = B; diff --git a/src/librustdoc/html/render/print_item.rs b/src/librustdoc/html/render/print_item.rs index adfc7481c73ae..6bb8f2043f4bb 100644 --- a/src/librustdoc/html/render/print_item.rs +++ b/src/librustdoc/html/render/print_item.rs @@ -5,7 +5,7 @@ use std::iter; use askama::Template; use rustc_abi::VariantIdx; use rustc_ast::join_path_syms; -use rustc_data_structures::fx::{FxHashMap, FxIndexSet}; +use rustc_data_structures::fx::{FxHashMap, FxIndexMap, FxIndexSet}; use rustc_hir as hir; use rustc_hir::def::CtorKind; use rustc_hir::def_id::DefId; @@ -307,8 +307,12 @@ fn item_module(cx: &Context<'_>, item: &clean::Item, items: &[clean::Item]) -> i fmt::from_fn(|w| { write!(w, "{}", document(cx, item, None, HeadingOffset::H2))?; - let mut not_stripped_items = - items.iter().filter(|i| !i.is_stripped()).enumerate().collect::>(); + let mut not_stripped_items: FxIndexMap> = + FxIndexMap::default(); + + for (index, item) in items.iter().filter(|i| !i.is_stripped()).enumerate() { + not_stripped_items.entry(item.type_()).or_default().push((index, item)); + } // the order of item types in the listing fn reorder(ty: ItemType) -> u8 { @@ -331,11 +335,6 @@ fn item_module(cx: &Context<'_>, item: &clean::Item, items: &[clean::Item]) -> i } fn cmp(i1: &clean::Item, i2: &clean::Item, tcx: TyCtxt<'_>) -> Ordering { - let rty1 = reorder(i1.type_()); - let rty2 = reorder(i2.type_()); - if rty1 != rty2 { - return rty1.cmp(&rty2); - } let is_stable1 = i1.stability(tcx).as_ref().map(|s| s.level.is_stable()).unwrap_or(true); let is_stable2 = @@ -357,7 +356,9 @@ fn item_module(cx: &Context<'_>, item: &clean::Item, items: &[clean::Item]) -> i match cx.shared.module_sorting { ModuleSorting::Alphabetical => { - not_stripped_items.sort_by(|(_, i1), (_, i2)| cmp(i1, i2, tcx)); + for items in not_stripped_items.values_mut() { + items.sort_by(|(_, i1), (_, i2)| cmp(i1, i2, tcx)); + } } ModuleSorting::DeclarationOrder => {} } @@ -380,155 +381,152 @@ fn item_module(cx: &Context<'_>, item: &clean::Item, items: &[clean::Item]) -> i // can be identical even if the elements are different (mostly in imports). // So in case this is an import, we keep everything by adding a "unique id" // (which is the position in the vector). - not_stripped_items.dedup_by_key(|(idx, i)| { - ( - i.item_id, - if i.name.is_some() { Some(full_path(cx, i)) } else { None }, - i.type_(), - if i.is_import() { *idx } else { 0 }, - ) - }); + for items in not_stripped_items.values_mut() { + items.dedup_by_key(|(idx, i)| { + ( + i.item_id, + if i.name.is_some() { Some(full_path(cx, i)) } else { None }, + i.type_(), + if i.is_import() { *idx } else { 0 }, + ) + }); + } debug!("{not_stripped_items:?}"); - let mut last_section = None; - for (_, myitem) in ¬_stripped_items { - let my_section = item_ty_to_section(myitem.type_()); - if Some(my_section) != last_section { - if last_section.is_some() { - w.write_str(ITEM_TABLE_CLOSE)?; - } - last_section = Some(my_section); - let section_id = my_section.id(); - let tag = - if section_id == "reexports" { REEXPORTS_TABLE_OPEN } else { ITEM_TABLE_OPEN }; - write!( - w, - "{}", - write_section_heading(my_section.name(), &cx.derive_id(section_id), None, tag) - )?; - } - - match myitem.kind { - clean::ExternCrateItem { ref src } => { - use crate::html::format::print_anchor; + let mut types = not_stripped_items.keys().copied().collect::>(); + types.sort_unstable_by(|a, b| reorder(*a).cmp(&reorder(*b))); - match *src { - Some(src) => { - write!( - w, - "
{}extern crate {} as {};", - visibility_print_with_space(myitem, cx), - print_anchor(myitem.item_id.expect_def_id(), src, cx), - EscapeBodyTextWithWbr(myitem.name.unwrap().as_str()) - )?; - } - None => { - write!( - w, - "
{}extern crate {};", - visibility_print_with_space(myitem, cx), - print_anchor( - myitem.item_id.expect_def_id(), - myitem.name.unwrap(), - cx - ) - )?; - } - } - w.write_str("
")?; - } + for type_ in types { + let my_section = item_ty_to_section(type_); + let tag = if my_section == super::ItemSection::Reexports { + REEXPORTS_TABLE_OPEN + } else { + ITEM_TABLE_OPEN + }; + write!( + w, + "{}", + write_section_heading(my_section.name(), &cx.derive_id(my_section.id()), None, tag) + )?; - clean::ImportItem(ref import) => { - let stab_tags = import.source.did.map_or_else(String::new, |import_def_id| { - print_extra_info_tags(tcx, myitem, item, Some(import_def_id)).to_string() - }); + for (_, myitem) in ¬_stripped_items[&type_] { + match myitem.kind { + clean::ExternCrateItem { ref src } => { + use crate::html::format::print_anchor; - let id = match import.kind { - clean::ImportKind::Simple(s) => { - format!(" id=\"{}\"", cx.derive_id(format!("reexport.{s}"))) + match *src { + Some(src) => { + write!( + w, + "
{}extern crate {} as {};", + visibility_print_with_space(myitem, cx), + print_anchor(myitem.item_id.expect_def_id(), src, cx), + EscapeBodyTextWithWbr(myitem.name.unwrap().as_str()) + )?; + } + None => { + write!( + w, + "
{}extern crate {};", + visibility_print_with_space(myitem, cx), + print_anchor( + myitem.item_id.expect_def_id(), + myitem.name.unwrap(), + cx + ) + )?; + } } - clean::ImportKind::Glob => String::new(), - }; - write!( - w, - "\ - " - )?; - render_attributes_in_code(w, myitem, "", cx); - write!( - w, - "{vis}{imp}{stab_tags}\ -
", - vis = visibility_print_with_space(myitem, cx), - imp = import.print(cx) - )?; - } - - _ => { - if myitem.name.is_none() { - continue; } - - let unsafety_flag = match myitem.kind { - clean::FunctionItem(_) | clean::ForeignFunctionItem(..) - if myitem.fn_header(tcx).unwrap().safety - == hir::HeaderSafety::Normal(hir::Safety::Unsafe) => - { - "" - } - clean::ForeignStaticItem(_, hir::Safety::Unsafe) => { - "" - } - _ => "", - }; - - let visibility_and_hidden = match myitem.visibility(tcx) { - Some(ty::Visibility::Restricted(_)) => { - if myitem.is_doc_hidden() { - // Don't separate with a space when there are two of them - " 🔒👻 " - } else { - " 🔒 " + clean::ImportItem(ref import) => { + let stab_tags = + import.source.did.map_or_else(String::new, |import_def_id| { + print_extra_info_tags(tcx, myitem, item, Some(import_def_id)) + .to_string() + }); + let id = match import.kind { + clean::ImportKind::Simple(s) => { + format!(" id=\"{}\"", cx.derive_id(format!("reexport.{s}"))) } + clean::ImportKind::Glob => String::new(), + }; + write!( + w, + "\ + " + )?; + render_attributes_in_code(w, myitem, "", cx); + write!( + w, + "{vis}{imp}{stab_tags}\ + ", + vis = visibility_print_with_space(myitem, cx), + imp = import.print(cx) + )?; + } + _ => { + if myitem.name.is_none() { + continue; } - _ if myitem.is_doc_hidden() => { - " 👻 " - } - _ => "", - }; - let docs = - MarkdownSummaryLine(&myitem.doc_value(), &myitem.links(cx)).into_string(); - let (docs_before, docs_after) = - if docs.is_empty() { ("", "") } else { ("
", "
") }; - write!( - w, - "
\ - \ - {name}\ - \ - {visibility_and_hidden}\ - {unsafety_flag}\ - {stab_tags}\ -
\ - {docs_before}{docs}{docs_after}", - name = EscapeBodyTextWithWbr(myitem.name.unwrap().as_str()), - visibility_and_hidden = visibility_and_hidden, - stab_tags = print_extra_info_tags(tcx, myitem, item, None), - class = myitem.type_(), - unsafety_flag = unsafety_flag, - href = print_item_path(myitem.type_(), myitem.name.unwrap().as_str()), - title1 = myitem.type_(), - title2 = full_path(cx, myitem), - )?; + let unsafety_flag = match myitem.kind { + clean::FunctionItem(_) | clean::ForeignFunctionItem(..) + if myitem.fn_header(tcx).unwrap().safety + == hir::HeaderSafety::Normal(hir::Safety::Unsafe) => + { + "" + } + clean::ForeignStaticItem(_, hir::Safety::Unsafe) => { + "" + } + _ => "", + }; + let visibility_and_hidden = match myitem.visibility(tcx) { + Some(ty::Visibility::Restricted(_)) => { + if myitem.is_doc_hidden() { + // Don't separate with a space when there are two of them + " 🔒👻 " + } else { + " 🔒 " + } + } + _ if myitem.is_doc_hidden() => { + " 👻 " + } + _ => "", + }; + + let docs = MarkdownSummaryLine(&myitem.doc_value(), &myitem.links(cx)) + .into_string(); + let (docs_before, docs_after) = + if docs.is_empty() { ("", "") } else { ("
", "
") }; + write!( + w, + "
\ + \ + {name}\ + \ + {visibility_and_hidden}\ + {unsafety_flag}\ + {stab_tags}\ +
\ + {docs_before}{docs}{docs_after}", + name = EscapeBodyTextWithWbr(myitem.name.unwrap().as_str()), + visibility_and_hidden = visibility_and_hidden, + stab_tags = print_extra_info_tags(tcx, myitem, item, None), + class = type_, + unsafety_flag = unsafety_flag, + href = print_item_path(type_, myitem.name.unwrap().as_str()), + title1 = myitem.type_(), + title2 = full_path(cx, myitem), + )?; + } } } - } - - if last_section.is_some() { w.write_str(ITEM_TABLE_CLOSE)?; } + Ok(()) }) } diff --git a/tests/ui/frontmatter/space-in-infostring.rs b/tests/ui/frontmatter/space-in-infostring.rs new file mode 100644 index 0000000000000..a8448af113443 --- /dev/null +++ b/tests/ui/frontmatter/space-in-infostring.rs @@ -0,0 +1,9 @@ +--- cargo clippy +//~^ ERROR: invalid infostring for frontmatter +--- + +// infostrings cannot have spaces + +#![feature(frontmatter)] + +fn main() {} diff --git a/tests/ui/frontmatter/space-in-infostring.stderr b/tests/ui/frontmatter/space-in-infostring.stderr new file mode 100644 index 0000000000000..b876ddae782e9 --- /dev/null +++ b/tests/ui/frontmatter/space-in-infostring.stderr @@ -0,0 +1,10 @@ +error: invalid infostring for frontmatter + --> $DIR/space-in-infostring.rs:1:4 + | +LL | --- cargo clippy + | ^^^^^^^^^^^^^ + | + = note: frontmatter infostrings must be a single identifier immediately following the opening + +error: aborting due to 1 previous error + diff --git a/tests/ui/traits/generic-cow-inference-regression.rs b/tests/ui/traits/generic-cow-inference-regression.rs new file mode 100644 index 0000000000000..6fd4715f85bbd --- /dev/null +++ b/tests/ui/traits/generic-cow-inference-regression.rs @@ -0,0 +1,20 @@ +//@ run-pass + +// regression test for #147964: +// constification of these traits resulted in inference errors due to additional where clauses + +use std::borrow::{Cow, Borrow}; + +pub fn generic_deref<'a, T: ToOwned, U>(cow: Cow<'a, T>) { + let _: &T = &cow; +} + +pub fn generic_borrow<'a, T: ToOwned, U>(cow: Cow<'a, T>) { + let _: &T = cow.borrow(); +} + +pub fn generic_as_ref<'a, T: ToOwned, U>(cow: Cow<'a, T>) { + let _: &T = cow.as_ref(); +} + +fn main() {} diff --git a/triagebot.toml b/triagebot.toml index fbe29dd182452..a0d0b1892e4fe 100644 --- a/triagebot.toml +++ b/triagebot.toml @@ -1370,6 +1370,7 @@ compiler = [ "@jackh726", "@jieyouxu", "@jdonszelmann", + "@JonathanBrouwer", "@lcnr", "@madsmtm", "@Nadrieril",