diff --git a/.gitignore b/.gitignore index 87437a16fb392..ec6cb6ed2e4d3 100644 --- a/.gitignore +++ b/.gitignore @@ -71,6 +71,7 @@ __pycache__/ ## Node node_modules package-lock.json +package.json ## Rustdoc GUI tests src/test/rustdoc-gui/src/**.lock diff --git a/compiler/rustc_codegen_llvm/src/back/archive.rs b/compiler/rustc_codegen_llvm/src/back/archive.rs index 5703a72c686e5..8a1dea4d99bfe 100644 --- a/compiler/rustc_codegen_llvm/src/back/archive.rs +++ b/compiler/rustc_codegen_llvm/src/back/archive.rs @@ -219,7 +219,7 @@ impl<'a> ArchiveBuilder<'a> for LlvmArchiveBuilder<'a> { match result { Err(e) => { - self.config.sess.fatal(&format!("Error calling dlltool: {}", e.to_string())); + self.config.sess.fatal(&format!("Error calling dlltool: {}", e)); } Ok(output) if !output.status.success() => self.config.sess.fatal(&format!( "Dlltool could not create import library: {}\n{}", diff --git a/compiler/rustc_interface/src/interface.rs b/compiler/rustc_interface/src/interface.rs index 263435619590e..237aef1cf23aa 100644 --- a/compiler/rustc_interface/src/interface.rs +++ b/compiler/rustc_interface/src/interface.rs @@ -126,7 +126,7 @@ pub fn parse_cfgspecs(cfgspecs: Vec) -> FxHashSet<(String, Option AssocItems<'tcx> { &self, tcx: TyCtxt<'_>, ident: Ident, + // Sorted in order of what kinds to look at kinds: &[AssocKind], parent_def_id: DefId, ) -> Option<&ty::AssocItem> { - self.filter_by_name_unhygienic(ident.name) - .filter(|item| kinds.contains(&item.kind)) - .find(|item| tcx.hygienic_eq(ident, item.ident(tcx), parent_def_id)) + kinds.iter().find_map(|kind| self.find_by_name_and_kind(tcx, ident, *kind, parent_def_id)) } /// Returns the associated item with the given name in the given `Namespace`, if one exists. diff --git a/compiler/rustc_mir_dataflow/src/elaborate_drops.rs b/compiler/rustc_mir_dataflow/src/elaborate_drops.rs index 501bc96401aa5..a3294672f5470 100644 --- a/compiler/rustc_mir_dataflow/src/elaborate_drops.rs +++ b/compiler/rustc_mir_dataflow/src/elaborate_drops.rs @@ -8,7 +8,7 @@ use rustc_middle::ty::subst::SubstsRef; use rustc_middle::ty::util::IntTypeExt; use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_target::abi::VariantIdx; -use std::fmt; +use std::{fmt, iter}; /// The value of an inserted drop flag. #[derive(Debug, PartialEq, Eq, Copy, Clone)] @@ -329,8 +329,7 @@ where mut succ: BasicBlock, fields: &[(Place<'tcx>, Option)], ) -> Vec { - Some(succ) - .into_iter() + iter::once(succ) .chain(fields.iter().rev().zip(unwind_ladder).map(|(&(place, path), &unwind_succ)| { succ = self.drop_subpath(place, path, succ, unwind_succ); succ diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index 0115d498a7fb8..4898a4844b9f7 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -1702,11 +1702,11 @@ impl<'a> Parser<'a> { // Try to lowercase the prefix if it's a valid base prefix. fn fix_base_capitalisation(s: &str) -> Option { - if let Some(stripped) = s.strip_prefix("B") { + if let Some(stripped) = s.strip_prefix('B') { Some(format!("0b{stripped}")) - } else if let Some(stripped) = s.strip_prefix("O") { + } else if let Some(stripped) = s.strip_prefix('O') { Some(format!("0o{stripped}")) - } else if let Some(stripped) = s.strip_prefix("X") { + } else if let Some(stripped) = s.strip_prefix('X') { Some(format!("0x{stripped}")) } else { None diff --git a/compiler/rustc_typeck/src/astconv/mod.rs b/compiler/rustc_typeck/src/astconv/mod.rs index 3e2d7fc382050..0ad2242f6677c 100644 --- a/compiler/rustc_typeck/src/astconv/mod.rs +++ b/compiler/rustc_typeck/src/astconv/mod.rs @@ -887,15 +887,10 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { .find_by_name_and_kind(self.tcx(), assoc_name, ty::AssocKind::Type, trait_def_id) .is_some() } - fn trait_defines_associated_named(&self, trait_def_id: DefId, assoc_name: Ident) -> bool { + fn trait_defines_associated_const_named(&self, trait_def_id: DefId, assoc_name: Ident) -> bool { self.tcx() .associated_items(trait_def_id) - .find_by_name_and_kinds( - self.tcx(), - assoc_name, - &[ty::AssocKind::Type, ty::AssocKind::Const], - trait_def_id, - ) + .find_by_name_and_kind(self.tcx(), assoc_name, ty::AssocKind::Const, trait_def_id) .is_some() } @@ -1145,13 +1140,13 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { // We have already adjusted the item name above, so compare with `ident.normalize_to_macros_2_0()` instead // of calling `filter_by_name_and_kind`. - let assoc_item = tcx - .associated_items(candidate.def_id()) - .filter_by_name_unhygienic(assoc_ident.name) - .find(|i| { - (i.kind == ty::AssocKind::Type || i.kind == ty::AssocKind::Const) - && i.ident(tcx).normalize_to_macros_2_0() == assoc_ident - }) + let find_item_of_kind = |kind| { + tcx.associated_items(candidate.def_id()) + .filter_by_name_unhygienic(assoc_ident.name) + .find(|i| i.kind == kind && i.ident(tcx).normalize_to_macros_2_0() == assoc_ident) + }; + let assoc_item = find_item_of_kind(ty::AssocKind::Type) + .or_else(|| find_item_of_kind(ty::AssocKind::Const)) .expect("missing associated type"); if !assoc_item.vis.is_accessible_from(def_scope, tcx) { @@ -1657,11 +1652,14 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { I: Iterator>, { let mut matching_candidates = all_candidates() - .filter(|r| self.trait_defines_associated_named(r.def_id(), assoc_name)); - - let bound = match matching_candidates.next() { - Some(bound) => bound, - None => { + .filter(|r| self.trait_defines_associated_type_named(r.def_id(), assoc_name)); + let mut const_candidates = all_candidates() + .filter(|r| self.trait_defines_associated_const_named(r.def_id(), assoc_name)); + + let (bound, next_cand) = match (matching_candidates.next(), const_candidates.next()) { + (Some(bound), _) => (bound, matching_candidates.next()), + (None, Some(bound)) => (bound, const_candidates.next()), + (None, None) => { self.complain_about_assoc_type_not_found( all_candidates, &ty_param_name(), @@ -1671,10 +1669,9 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { return Err(ErrorReported); } }; - debug!("one_bound_for_assoc_type: bound = {:?}", bound); - if let Some(bound2) = matching_candidates.next() { + if let Some(bound2) = next_cand { debug!("one_bound_for_assoc_type: bound2 = {:?}", bound2); let is_equality = is_equality(); @@ -1759,6 +1756,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { return Err(ErrorReported); } } + Ok(bound) } @@ -1893,14 +1891,17 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { // We have already adjusted the item name above, so compare with `ident.normalize_to_macros_2_0()` instead // of calling `filter_by_name_and_kind`. - let item = tcx - .associated_items(trait_did) - .in_definition_order() - .find(|i| { - i.kind.namespace() == Namespace::TypeNS - && i.ident(tcx).normalize_to_macros_2_0() == assoc_ident - }) - .expect("missing associated type"); + let item = tcx.associated_items(trait_did).in_definition_order().find(|i| { + i.kind.namespace() == Namespace::TypeNS + && i.ident(tcx).normalize_to_macros_2_0() == assoc_ident + }); + // Assume that if it's not matched, there must be a const defined with the same name + // but it was used in a type position. + let Some(item) = item else { + let msg = format!("found associated const `{assoc_ident}` when type was expected"); + tcx.sess.struct_span_err(span, &msg).emit(); + return Err(ErrorReported); + }; let ty = self.projected_ty_from_poly_trait_ref(span, item.def_id, assoc_segment, bound); let ty = self.normalize_ty(span, ty); diff --git a/compiler/rustc_typeck/src/check/expr.rs b/compiler/rustc_typeck/src/check/expr.rs index 82cda5a2f2e73..0347b6a4ab82f 100644 --- a/compiler/rustc_typeck/src/check/expr.rs +++ b/compiler/rustc_typeck/src/check/expr.rs @@ -1587,10 +1587,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ) { let len = remaining_fields.len(); - let mut displayable_field_names = - remaining_fields.keys().map(|ident| ident.as_str()).collect::>(); - - displayable_field_names.sort(); + let mut displayable_field_names: Vec<&str> = + remaining_fields.keys().map(|ident| ident.as_str()).collect(); + // sorting &str primitives here, sort_unstable is ok + displayable_field_names.sort_unstable(); let mut truncated_fields_error = String::new(); let remaining_fields_names = match &displayable_field_names[..] { diff --git a/library/std/src/sys/solid/time.rs b/library/std/src/sys/solid/time.rs index c67a736a9032c..ab988be24442a 100644 --- a/library/std/src/sys/solid/time.rs +++ b/library/std/src/sys/solid/time.rs @@ -21,7 +21,7 @@ impl SystemTime { tm_min: rtc.tm_min, tm_hour: rtc.tm_hour, tm_mday: rtc.tm_mday, - tm_mon: rtc.tm_mon, + tm_mon: rtc.tm_mon - 1, tm_year: rtc.tm_year, tm_wday: rtc.tm_wday, tm_yday: 0, diff --git a/src/test/ui/associated-consts/shadowed-const.rs b/src/test/ui/associated-consts/shadowed-const.rs new file mode 100644 index 0000000000000..cfdb391d39d51 --- /dev/null +++ b/src/test/ui/associated-consts/shadowed-const.rs @@ -0,0 +1,23 @@ +// Checking that none of these ICE, which was introduced in +// https://github.com/rust-lang/rust/issues/93553 +trait Foo { + type Bar; +} + +trait Baz: Foo { + const Bar: Self::Bar; +} + +trait Baz2: Foo { + const Bar: u32; + + fn foo() -> Self::Bar; +} + +trait Baz3 { + const BAR: usize; + const QUX: Self::BAR; + //~^ ERROR found associated const +} + +fn main() {} diff --git a/src/test/ui/associated-consts/shadowed-const.stderr b/src/test/ui/associated-consts/shadowed-const.stderr new file mode 100644 index 0000000000000..fe21d2aec00bc --- /dev/null +++ b/src/test/ui/associated-consts/shadowed-const.stderr @@ -0,0 +1,8 @@ +error: found associated const `BAR` when type was expected + --> $DIR/shadowed-const.rs:19:14 + | +LL | const QUX: Self::BAR; + | ^^^^^^^^^ + +error: aborting due to previous error + diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index 00221b07f7464..f6ddac3a65e06 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -2424,7 +2424,10 @@ impl<'test> TestCx<'test> { ); if !res.status.success() { - self.fatal_proc_rec("jsondocck failed!", &res) + self.fatal_proc_rec_with_ctx("jsondocck failed!", &res, |_| { + println!("Rustdoc Output:"); + proc_res.print_info(); + }) } let mut json_out = out_dir.join(self.testpaths.file.file_stem().unwrap()); @@ -3738,10 +3741,7 @@ pub struct ProcRes { } impl ProcRes { - pub fn fatal(&self, err: Option<&str>, on_failure: impl FnOnce()) -> ! { - if let Some(e) = err { - println!("\nerror: {}", e); - } + pub fn print_info(&self) { print!( "\ status: {}\n\ @@ -3760,6 +3760,13 @@ impl ProcRes { json::extract_rendered(&self.stdout), json::extract_rendered(&self.stderr), ); + } + + pub fn fatal(&self, err: Option<&str>, on_failure: impl FnOnce()) -> ! { + if let Some(e) = err { + println!("\nerror: {}", e); + } + self.print_info(); on_failure(); // Use resume_unwind instead of panic!() to prevent a panic message + backtrace from // compiletest, which is unnecessary noise.