From 7ae198b08dc422662136c5158b482859b159ec50 Mon Sep 17 00:00:00 2001 From: Yotam Ofek Date: Sat, 18 Jan 2025 07:43:31 +0000 Subject: [PATCH 01/10] don't use partial ordering on types that support total ordering --- compiler/rustc_resolve/src/diagnostics.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs index ba217b7c88a8e..66a04eb0617a8 100644 --- a/compiler/rustc_resolve/src/diagnostics.rs +++ b/compiler/rustc_resolve/src/diagnostics.rs @@ -1139,7 +1139,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { }); // Make sure error reporting is deterministic. - suggestions.sort_by(|a, b| a.candidate.as_str().partial_cmp(b.candidate.as_str()).unwrap()); + suggestions.sort_by(|a, b| a.candidate.as_str().cmp(b.candidate.as_str())); match find_best_match_for_name( &suggestions.iter().map(|suggestion| suggestion.candidate).collect::>(), @@ -2360,7 +2360,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { // 2) `std` suggestions before `core` suggestions. let mut extern_crate_names = self.extern_prelude.keys().map(|ident| ident.name).collect::>(); - extern_crate_names.sort_by(|a, b| b.as_str().partial_cmp(a.as_str()).unwrap()); + extern_crate_names.sort_by(|a, b| b.as_str().cmp(a.as_str())); for name in extern_crate_names.into_iter() { // Replace first ident with a crate name and check if that is valid. From ce0b72a99c4c71c3b72c85549fafe5d0beb4cee4 Mon Sep 17 00:00:00 2001 From: Yotam Ofek Date: Sat, 18 Jan 2025 07:44:37 +0000 Subject: [PATCH 02/10] use slice patterns for checking for elements of slice --- compiler/rustc_resolve/src/diagnostics.rs | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs index 66a04eb0617a8..0da27a9c0717d 100644 --- a/compiler/rustc_resolve/src/diagnostics.rs +++ b/compiler/rustc_resolve/src/diagnostics.rs @@ -2242,14 +2242,15 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { mut path: Vec, parent_scope: &ParentScope<'ra>, ) -> Option<(Vec, Option)> { - match (path.get(0), path.get(1)) { + match path[..] { // `{{root}}::ident::...` on both editions. // On 2015 `{{root}}` is usually added implicitly. - (Some(fst), Some(snd)) - if fst.ident.name == kw::PathRoot && !snd.ident.is_path_segment_keyword() => {} + [first, second, ..] + if first.ident.name == kw::PathRoot && !second.ident.is_path_segment_keyword() => {} // `ident::...` on 2018. - (Some(fst), _) - if fst.ident.span.at_least_rust_2018() && !fst.ident.is_path_segment_keyword() => + [first, ..] + if first.ident.span.at_least_rust_2018() + && !first.ident.is_path_segment_keyword() => { // Insert a placeholder that's later replaced by `self`/`super`/etc. path.insert(0, Segment::from_ident(Ident::empty())); From fbd30ea35fb79d73faa9d5b3feae391fed5336c8 Mon Sep 17 00:00:00 2001 From: Folkert de Vries Date: Wed, 29 Jan 2025 11:57:37 +0100 Subject: [PATCH 03/10] show supported register classes in inline assembly, show the supported register classes when an invalid one is found --- compiler/rustc_ast_lowering/messages.ftl | 3 ++- compiler/rustc_ast_lowering/src/asm.rs | 9 +++++++-- compiler/rustc_ast_lowering/src/errors.rs | 5 +++-- compiler/rustc_target/src/asm/mod.rs | 6 +++--- tests/ui/asm/aarch64/bad-reg.stderr | 2 ++ tests/ui/asm/x86_64/bad-reg.stderr | 2 ++ tests/ui/asm/x86_64/issue-82869.stderr | 4 ++++ 7 files changed, 23 insertions(+), 8 deletions(-) diff --git a/compiler/rustc_ast_lowering/messages.ftl b/compiler/rustc_ast_lowering/messages.ftl index f96c9fe8e3273..1b91c33742d8b 100644 --- a/compiler/rustc_ast_lowering/messages.ftl +++ b/compiler/rustc_ast_lowering/messages.ftl @@ -112,7 +112,8 @@ ast_lowering_invalid_register = invalid register `{$reg}`: {$error} ast_lowering_invalid_register_class = - invalid register class `{$reg_class}`: {$error} + invalid register class `{$reg_class}`: unknown register class + .note = the following register classes are supported on this target: {$supported_register_classes} ast_lowering_match_arm_with_no_body = `match` arm with no body diff --git a/compiler/rustc_ast_lowering/src/asm.rs b/compiler/rustc_ast_lowering/src/asm.rs index 2f1f1269ece57..96c230ec243a2 100644 --- a/compiler/rustc_ast_lowering/src/asm.rs +++ b/compiler/rustc_ast_lowering/src/asm.rs @@ -152,11 +152,16 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { InlineAsmRegOrRegClass::RegClass(reg_class) => { asm::InlineAsmRegOrRegClass::RegClass(if let Some(asm_arch) = asm_arch { asm::InlineAsmRegClass::parse(asm_arch, reg_class).unwrap_or_else( - |error| { + |supported_register_classes| { + let mut register_classes = + format!("`{}`", supported_register_classes[0]); + for m in &supported_register_classes[1..] { + let _ = write!(register_classes, ", `{m}`"); + } self.dcx().emit_err(InvalidRegisterClass { op_span: *op_sp, reg_class, - error, + supported_register_classes: register_classes, }); asm::InlineAsmRegClass::Err }, diff --git a/compiler/rustc_ast_lowering/src/errors.rs b/compiler/rustc_ast_lowering/src/errors.rs index f727691bf479c..953057681ab2e 100644 --- a/compiler/rustc_ast_lowering/src/errors.rs +++ b/compiler/rustc_ast_lowering/src/errors.rs @@ -212,12 +212,13 @@ pub(crate) struct InvalidRegister<'a> { } #[derive(Diagnostic)] +#[note] #[diag(ast_lowering_invalid_register_class)] -pub(crate) struct InvalidRegisterClass<'a> { +pub(crate) struct InvalidRegisterClass { #[primary_span] pub op_span: Span, pub reg_class: Symbol, - pub error: &'a str, + pub supported_register_classes: String, } #[derive(Diagnostic)] diff --git a/compiler/rustc_target/src/asm/mod.rs b/compiler/rustc_target/src/asm/mod.rs index 1292f46f0c913..45a67b10b633c 100644 --- a/compiler/rustc_target/src/asm/mod.rs +++ b/compiler/rustc_target/src/asm/mod.rs @@ -39,12 +39,12 @@ macro_rules! def_reg_class { } } - pub fn parse(name: rustc_span::Symbol) -> Result { + pub fn parse(name: rustc_span::Symbol) -> Result { match name { $( rustc_span::sym::$class => Ok(Self::$class), )* - _ => Err("unknown register class"), + _ => Err(&[$(rustc_span::sym::$class),*]), } } } @@ -635,7 +635,7 @@ impl InlineAsmRegClass { } } - pub fn parse(arch: InlineAsmArch, name: Symbol) -> Result { + pub fn parse(arch: InlineAsmArch, name: Symbol) -> Result { Ok(match arch { InlineAsmArch::X86 | InlineAsmArch::X86_64 => { Self::X86(X86InlineAsmRegClass::parse(name)?) diff --git a/tests/ui/asm/aarch64/bad-reg.stderr b/tests/ui/asm/aarch64/bad-reg.stderr index 370752ad0f11c..c76722f32a74e 100644 --- a/tests/ui/asm/aarch64/bad-reg.stderr +++ b/tests/ui/asm/aarch64/bad-reg.stderr @@ -3,6 +3,8 @@ error: invalid register class `foo`: unknown register class | LL | asm!("{}", in(foo) foo); | ^^^^^^^^^^^ + | + = note: the following register classes are supported on this target: `reg`, `vreg`, `vreg_low16`, `preg` error: invalid register `foo`: unknown register --> $DIR/bad-reg.rs:14:18 diff --git a/tests/ui/asm/x86_64/bad-reg.stderr b/tests/ui/asm/x86_64/bad-reg.stderr index 3df1f7b220869..6a02957210bb9 100644 --- a/tests/ui/asm/x86_64/bad-reg.stderr +++ b/tests/ui/asm/x86_64/bad-reg.stderr @@ -3,6 +3,8 @@ error: invalid register class `foo`: unknown register class | LL | asm!("{}", in(foo) foo); | ^^^^^^^^^^^ + | + = note: the following register classes are supported on this target: `reg`, `reg_abcd`, `reg_byte`, `xmm_reg`, `ymm_reg`, `zmm_reg`, `kreg`, `kreg0`, `mmx_reg`, `x87_reg`, `tmm_reg` error: invalid register `foo`: unknown register --> $DIR/bad-reg.rs:14:18 diff --git a/tests/ui/asm/x86_64/issue-82869.stderr b/tests/ui/asm/x86_64/issue-82869.stderr index 3cf9d6d1c1c00..56e4909956913 100644 --- a/tests/ui/asm/x86_64/issue-82869.stderr +++ b/tests/ui/asm/x86_64/issue-82869.stderr @@ -3,12 +3,16 @@ error: invalid register class `vreg`: unknown register class | LL | asm!("add {:d}, {:d}, d0", out(vreg) c, in(vreg) a, in("d0") { | ^^^^^^^^^^^ + | + = note: the following register classes are supported on this target: `reg`, `reg_abcd`, `reg_byte`, `xmm_reg`, `ymm_reg`, `zmm_reg`, `kreg`, `kreg0`, `mmx_reg`, `x87_reg`, `tmm_reg` error: invalid register class `vreg`: unknown register class --> $DIR/issue-82869.rs:11:45 | LL | asm!("add {:d}, {:d}, d0", out(vreg) c, in(vreg) a, in("d0") { | ^^^^^^^^^^ + | + = note: the following register classes are supported on this target: `reg`, `reg_abcd`, `reg_byte`, `xmm_reg`, `ymm_reg`, `zmm_reg`, `kreg`, `kreg0`, `mmx_reg`, `x87_reg`, `tmm_reg` error: invalid register `d0`: unknown register --> $DIR/issue-82869.rs:11:57 From 2e4391218476c0ffe092e4e32c9b6ae5057e5a0a Mon Sep 17 00:00:00 2001 From: Tobias Bucher Date: Thu, 9 Jan 2025 13:52:18 +0100 Subject: [PATCH 04/10] =?UTF-8?q?it-self=20=E2=86=92=20itself,=20build-sys?= =?UTF-8?q?tem=20=E2=86=92=20build=20system,=20type-alias=20=E2=86=92=20ty?= =?UTF-8?q?pe=20alias?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- compiler/rustc_session/src/config/cfg.rs | 2 +- src/doc/rustc/src/check-cfg.md | 2 +- src/librustdoc/passes/strip_aliased_non_local.rs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_session/src/config/cfg.rs b/compiler/rustc_session/src/config/cfg.rs index d586f913335e0..5defcf4ee9464 100644 --- a/compiler/rustc_session/src/config/cfg.rs +++ b/compiler/rustc_session/src/config/cfg.rs @@ -9,7 +9,7 @@ //! //! ## Adding a new cfg //! -//! Adding a new feature requires two new symbols one for the cfg it-self +//! Adding a new feature requires two new symbols one for the cfg itself //! and the second one for the unstable feature gate, those are defined in //! `rustc_span::symbol`. //! diff --git a/src/doc/rustc/src/check-cfg.md b/src/doc/rustc/src/check-cfg.md index c62ca9fd9ad6b..00add2651ae8b 100644 --- a/src/doc/rustc/src/check-cfg.md +++ b/src/doc/rustc/src/check-cfg.md @@ -135,7 +135,7 @@ As of `2025-01-02T`, the list of known names is as follows: - `windows` > Starting with 1.85.0, the `test` cfg is consider to be a "userspace" config -> despite being also set by `rustc` and should be managed by the build-system it-self. +> despite being also set by `rustc` and should be managed by the build system itself. Like with `values(any())`, well known names checking can be disabled by passing `cfg(any())` as argument to `--check-cfg`. diff --git a/src/librustdoc/passes/strip_aliased_non_local.rs b/src/librustdoc/passes/strip_aliased_non_local.rs index fa7737bc14386..7f5c7da363422 100644 --- a/src/librustdoc/passes/strip_aliased_non_local.rs +++ b/src/librustdoc/passes/strip_aliased_non_local.rs @@ -26,7 +26,7 @@ impl DocFolder for AliasedNonLocalStripper<'_> { Some(match i.kind { clean::TypeAliasItem(..) => { let mut stripper = NonLocalStripper { tcx: self.tcx }; - // don't call `fold_item` as that could strip the type-alias it-self + // don't call `fold_item` as that could strip the type alias itself // which we don't want to strip out stripper.fold_item_recur(i) } From a6dcfe3af43dce6762d0569e0effe1a9d8719d07 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sun, 9 Feb 2025 18:57:22 +0000 Subject: [PATCH 05/10] Remove the deduplicate_blocks pass --- .../src/deduplicate_blocks.rs | 195 ------------------ compiler/rustc_mir_transform/src/lib.rs | 2 - ...mment_2.DeduplicateBlocks.panic-abort.diff | 100 --------- ...ment_2.DeduplicateBlocks.panic-unwind.diff | 100 --------- tests/mir-opt/deduplicate_blocks.rs | 17 -- 5 files changed, 414 deletions(-) delete mode 100644 compiler/rustc_mir_transform/src/deduplicate_blocks.rs delete mode 100644 tests/mir-opt/deduplicate_blocks.is_line_doc_comment_2.DeduplicateBlocks.panic-abort.diff delete mode 100644 tests/mir-opt/deduplicate_blocks.is_line_doc_comment_2.DeduplicateBlocks.panic-unwind.diff delete mode 100644 tests/mir-opt/deduplicate_blocks.rs diff --git a/compiler/rustc_mir_transform/src/deduplicate_blocks.rs b/compiler/rustc_mir_transform/src/deduplicate_blocks.rs deleted file mode 100644 index 63257df66fb9b..0000000000000 --- a/compiler/rustc_mir_transform/src/deduplicate_blocks.rs +++ /dev/null @@ -1,195 +0,0 @@ -//! This pass finds basic blocks that are completely equal, -//! and replaces all uses with just one of them. - -use std::collections::hash_map::Entry; -use std::hash::{Hash, Hasher}; -use std::iter; - -use rustc_data_structures::fx::FxHashMap; -use rustc_middle::mir::visit::MutVisitor; -use rustc_middle::mir::*; -use rustc_middle::ty::TyCtxt; -use tracing::debug; - -use super::simplify::simplify_cfg; - -pub(super) struct DeduplicateBlocks; - -impl<'tcx> crate::MirPass<'tcx> for DeduplicateBlocks { - fn is_enabled(&self, sess: &rustc_session::Session) -> bool { - sess.mir_opt_level() >= 4 - } - - fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { - debug!("Running DeduplicateBlocks on `{:?}`", body.source); - let duplicates = find_duplicates(body); - let has_opts_to_apply = !duplicates.is_empty(); - - if has_opts_to_apply { - let mut opt_applier = OptApplier { tcx, duplicates }; - opt_applier.visit_body(body); - simplify_cfg(body); - } - } - - fn is_required(&self) -> bool { - false - } -} - -struct OptApplier<'tcx> { - tcx: TyCtxt<'tcx>, - duplicates: FxHashMap, -} - -impl<'tcx> MutVisitor<'tcx> for OptApplier<'tcx> { - fn tcx(&self) -> TyCtxt<'tcx> { - self.tcx - } - - fn visit_terminator(&mut self, terminator: &mut Terminator<'tcx>, location: Location) { - for target in terminator.successors_mut() { - if let Some(replacement) = self.duplicates.get(target) { - debug!("SUCCESS: Replacing: `{:?}` with `{:?}`", target, replacement); - *target = *replacement; - } - } - - self.super_terminator(terminator, location); - } -} - -fn find_duplicates(body: &Body<'_>) -> FxHashMap { - let mut duplicates = FxHashMap::default(); - - let bbs_to_go_through = - body.basic_blocks.iter_enumerated().filter(|(_, bbd)| !bbd.is_cleanup).count(); - - let mut same_hashes = - FxHashMap::with_capacity_and_hasher(bbs_to_go_through, Default::default()); - - // Go through the basic blocks backwards. This means that in case of duplicates, - // we can use the basic block with the highest index as the replacement for all lower ones. - // For example, if bb1, bb2 and bb3 are duplicates, we will first insert bb3 in same_hashes. - // Then we will see that bb2 is a duplicate of bb3, - // and insert bb2 with the replacement bb3 in the duplicates list. - // When we see bb1, we see that it is a duplicate of bb3, and therefore insert it in the - // duplicates list with replacement bb3. - // When the duplicates are removed, we will end up with only bb3. - for (bb, bbd) in body.basic_blocks.iter_enumerated().rev().filter(|(_, bbd)| !bbd.is_cleanup) { - // Basic blocks can get really big, so to avoid checking for duplicates in basic blocks - // that are unlikely to have duplicates, we stop early. The early bail number has been - // found experimentally by eprintln while compiling the crates in the rustc-perf suite. - if bbd.statements.len() > 10 { - continue; - } - - let to_hash = BasicBlockHashable { basic_block_data: bbd }; - let entry = same_hashes.entry(to_hash); - match entry { - Entry::Occupied(occupied) => { - // The basic block was already in the hashmap, which means we have a duplicate - let value = *occupied.get(); - debug!("Inserting {:?} -> {:?}", bb, value); - duplicates.try_insert(bb, value).expect("key was already inserted"); - } - Entry::Vacant(vacant) => { - vacant.insert(bb); - } - } - } - - duplicates -} - -struct BasicBlockHashable<'a, 'tcx> { - basic_block_data: &'a BasicBlockData<'tcx>, -} - -impl Hash for BasicBlockHashable<'_, '_> { - fn hash(&self, state: &mut H) { - hash_statements(state, self.basic_block_data.statements.iter()); - // Note that since we only hash the kind, we lose span information if we deduplicate the - // blocks. - self.basic_block_data.terminator().kind.hash(state); - } -} - -impl Eq for BasicBlockHashable<'_, '_> {} - -impl PartialEq for BasicBlockHashable<'_, '_> { - fn eq(&self, other: &Self) -> bool { - self.basic_block_data.statements.len() == other.basic_block_data.statements.len() - && &self.basic_block_data.terminator().kind == &other.basic_block_data.terminator().kind - && iter::zip(&self.basic_block_data.statements, &other.basic_block_data.statements) - .all(|(x, y)| statement_eq(&x.kind, &y.kind)) - } -} - -fn hash_statements<'a, 'tcx, H: Hasher>( - hasher: &mut H, - iter: impl Iterator>, -) where - 'tcx: 'a, -{ - for stmt in iter { - statement_hash(hasher, &stmt.kind); - } -} - -fn statement_hash(hasher: &mut H, stmt: &StatementKind<'_>) { - match stmt { - StatementKind::Assign(box (place, rvalue)) => { - place.hash(hasher); - rvalue_hash(hasher, rvalue) - } - x => x.hash(hasher), - }; -} - -fn rvalue_hash(hasher: &mut H, rvalue: &Rvalue<'_>) { - match rvalue { - Rvalue::Use(op) => operand_hash(hasher, op), - x => x.hash(hasher), - }; -} - -fn operand_hash(hasher: &mut H, operand: &Operand<'_>) { - match operand { - Operand::Constant(box ConstOperand { user_ty: _, const_, span: _ }) => const_.hash(hasher), - x => x.hash(hasher), - }; -} - -fn statement_eq<'tcx>(lhs: &StatementKind<'tcx>, rhs: &StatementKind<'tcx>) -> bool { - let res = match (lhs, rhs) { - ( - StatementKind::Assign(box (place, rvalue)), - StatementKind::Assign(box (place2, rvalue2)), - ) => place == place2 && rvalue_eq(rvalue, rvalue2), - (x, y) => x == y, - }; - debug!("statement_eq lhs: `{:?}` rhs: `{:?}` result: {:?}", lhs, rhs, res); - res -} - -fn rvalue_eq<'tcx>(lhs: &Rvalue<'tcx>, rhs: &Rvalue<'tcx>) -> bool { - let res = match (lhs, rhs) { - (Rvalue::Use(op1), Rvalue::Use(op2)) => operand_eq(op1, op2), - (x, y) => x == y, - }; - debug!("rvalue_eq lhs: `{:?}` rhs: `{:?}` result: {:?}", lhs, rhs, res); - res -} - -fn operand_eq<'tcx>(lhs: &Operand<'tcx>, rhs: &Operand<'tcx>) -> bool { - let res = match (lhs, rhs) { - ( - Operand::Constant(box ConstOperand { user_ty: _, const_, span: _ }), - Operand::Constant(box ConstOperand { user_ty: _, const_: const2, span: _ }), - ) => const_ == const2, - (x, y) => x == y, - }; - debug!("operand_eq lhs: `{:?}` rhs: `{:?}` result: {:?}", lhs, rhs, res); - res -} diff --git a/compiler/rustc_mir_transform/src/lib.rs b/compiler/rustc_mir_transform/src/lib.rs index b572f6ca0b36a..397d21a857f00 100644 --- a/compiler/rustc_mir_transform/src/lib.rs +++ b/compiler/rustc_mir_transform/src/lib.rs @@ -135,7 +135,6 @@ declare_passes! { Initial, Final }; - mod deduplicate_blocks : DeduplicateBlocks; mod deref_separator : Derefer; mod dest_prop : DestinationPropagation; pub mod dump_mir : Marker; @@ -700,7 +699,6 @@ fn run_optimization_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { &nrvo::RenameReturnPlace, &simplify::SimplifyLocals::Final, &multiple_return_terminators::MultipleReturnTerminators, - &deduplicate_blocks::DeduplicateBlocks, &large_enums::EnumSizeOpt { discrepancy: 128 }, // Some cleanup necessary at least for LLVM and potentially other codegen backends. &add_call_guards::CriticalCallEdges, diff --git a/tests/mir-opt/deduplicate_blocks.is_line_doc_comment_2.DeduplicateBlocks.panic-abort.diff b/tests/mir-opt/deduplicate_blocks.is_line_doc_comment_2.DeduplicateBlocks.panic-abort.diff deleted file mode 100644 index 60742ef0e9a90..0000000000000 --- a/tests/mir-opt/deduplicate_blocks.is_line_doc_comment_2.DeduplicateBlocks.panic-abort.diff +++ /dev/null @@ -1,100 +0,0 @@ -- // MIR for `is_line_doc_comment_2` before DeduplicateBlocks -+ // MIR for `is_line_doc_comment_2` after DeduplicateBlocks - - fn is_line_doc_comment_2(_1: &str) -> bool { - debug s => _1; - let mut _0: bool; - let mut _2: &[u8]; - let mut _3: &str; - let mut _4: usize; - let mut _5: usize; - let mut _6: bool; - let mut _7: usize; - let mut _8: usize; - let mut _9: bool; - - bb0: { - StorageLive(_2); - StorageLive(_3); - _3 = &(*_1); - _2 = core::str::::as_bytes(move _3) -> [return: bb1, unwind unreachable]; - } - - bb1: { - StorageDead(_3); - _4 = Len((*_2)); - _5 = const 4_usize; - _6 = Ge(move _4, move _5); - switchInt(move _6) -> [0: bb2, otherwise: bb3]; - } - - bb2: { - _7 = Len((*_2)); - _8 = const 3_usize; - _9 = Ge(move _7, move _8); -- switchInt(move _9) -> [0: bb7, otherwise: bb8]; -+ switchInt(move _9) -> [0: bb11, otherwise: bb7]; - } - - bb3: { - switchInt(copy (*_2)[0 of 4]) -> [47: bb4, otherwise: bb2]; - } - - bb4: { - switchInt(copy (*_2)[1 of 4]) -> [47: bb5, otherwise: bb2]; - } - - bb5: { - switchInt(copy (*_2)[2 of 4]) -> [47: bb6, otherwise: bb2]; - } - - bb6: { -- switchInt(copy (*_2)[3 of 4]) -> [47: bb13, otherwise: bb2]; -+ switchInt(copy (*_2)[3 of 4]) -> [47: bb11, otherwise: bb2]; - } - - bb7: { -- _0 = const false; -- goto -> bb14; -+ switchInt(copy (*_2)[0 of 3]) -> [47: bb8, otherwise: bb11]; - } - - bb8: { -- switchInt(copy (*_2)[0 of 3]) -> [47: bb9, otherwise: bb7]; -+ switchInt(copy (*_2)[1 of 3]) -> [47: bb9, otherwise: bb11]; - } - - bb9: { -- switchInt(copy (*_2)[1 of 3]) -> [47: bb10, otherwise: bb7]; -+ switchInt(copy (*_2)[2 of 3]) -> [47: bb10, 33: bb10, otherwise: bb11]; - } - - bb10: { -- switchInt(copy (*_2)[2 of 3]) -> [47: bb12, 33: bb11, otherwise: bb7]; -- } -- -- bb11: { - _0 = const true; -- goto -> bb14; -+ goto -> bb12; - } - -- bb12: { -- _0 = const true; -- goto -> bb14; -- } -- -- bb13: { -+ bb11: { - _0 = const false; -- goto -> bb14; -+ goto -> bb12; - } - -- bb14: { -+ bb12: { - StorageDead(_2); - return; - } - } - diff --git a/tests/mir-opt/deduplicate_blocks.is_line_doc_comment_2.DeduplicateBlocks.panic-unwind.diff b/tests/mir-opt/deduplicate_blocks.is_line_doc_comment_2.DeduplicateBlocks.panic-unwind.diff deleted file mode 100644 index 7337a32f525f9..0000000000000 --- a/tests/mir-opt/deduplicate_blocks.is_line_doc_comment_2.DeduplicateBlocks.panic-unwind.diff +++ /dev/null @@ -1,100 +0,0 @@ -- // MIR for `is_line_doc_comment_2` before DeduplicateBlocks -+ // MIR for `is_line_doc_comment_2` after DeduplicateBlocks - - fn is_line_doc_comment_2(_1: &str) -> bool { - debug s => _1; - let mut _0: bool; - let mut _2: &[u8]; - let mut _3: &str; - let mut _4: usize; - let mut _5: usize; - let mut _6: bool; - let mut _7: usize; - let mut _8: usize; - let mut _9: bool; - - bb0: { - StorageLive(_2); - StorageLive(_3); - _3 = &(*_1); - _2 = core::str::::as_bytes(move _3) -> [return: bb1, unwind continue]; - } - - bb1: { - StorageDead(_3); - _4 = Len((*_2)); - _5 = const 4_usize; - _6 = Ge(move _4, move _5); - switchInt(move _6) -> [0: bb2, otherwise: bb3]; - } - - bb2: { - _7 = Len((*_2)); - _8 = const 3_usize; - _9 = Ge(move _7, move _8); -- switchInt(move _9) -> [0: bb7, otherwise: bb8]; -+ switchInt(move _9) -> [0: bb11, otherwise: bb7]; - } - - bb3: { - switchInt(copy (*_2)[0 of 4]) -> [47: bb4, otherwise: bb2]; - } - - bb4: { - switchInt(copy (*_2)[1 of 4]) -> [47: bb5, otherwise: bb2]; - } - - bb5: { - switchInt(copy (*_2)[2 of 4]) -> [47: bb6, otherwise: bb2]; - } - - bb6: { -- switchInt(copy (*_2)[3 of 4]) -> [47: bb13, otherwise: bb2]; -+ switchInt(copy (*_2)[3 of 4]) -> [47: bb11, otherwise: bb2]; - } - - bb7: { -- _0 = const false; -- goto -> bb14; -+ switchInt(copy (*_2)[0 of 3]) -> [47: bb8, otherwise: bb11]; - } - - bb8: { -- switchInt(copy (*_2)[0 of 3]) -> [47: bb9, otherwise: bb7]; -+ switchInt(copy (*_2)[1 of 3]) -> [47: bb9, otherwise: bb11]; - } - - bb9: { -- switchInt(copy (*_2)[1 of 3]) -> [47: bb10, otherwise: bb7]; -+ switchInt(copy (*_2)[2 of 3]) -> [47: bb10, 33: bb10, otherwise: bb11]; - } - - bb10: { -- switchInt(copy (*_2)[2 of 3]) -> [47: bb12, 33: bb11, otherwise: bb7]; -- } -- -- bb11: { - _0 = const true; -- goto -> bb14; -+ goto -> bb12; - } - -- bb12: { -- _0 = const true; -- goto -> bb14; -- } -- -- bb13: { -+ bb11: { - _0 = const false; -- goto -> bb14; -+ goto -> bb12; - } - -- bb14: { -+ bb12: { - StorageDead(_2); - return; - } - } - diff --git a/tests/mir-opt/deduplicate_blocks.rs b/tests/mir-opt/deduplicate_blocks.rs deleted file mode 100644 index 3a164cb09a094..0000000000000 --- a/tests/mir-opt/deduplicate_blocks.rs +++ /dev/null @@ -1,17 +0,0 @@ -// skip-filecheck -// EMIT_MIR_FOR_EACH_PANIC_STRATEGY -//@ test-mir-pass: DeduplicateBlocks - -// EMIT_MIR deduplicate_blocks.is_line_doc_comment_2.DeduplicateBlocks.diff -pub const fn is_line_doc_comment_2(s: &str) -> bool { - match s.as_bytes() { - [b'/', b'/', b'/', b'/', ..] => false, - [b'/', b'/', b'/', ..] => true, - [b'/', b'/', b'!', ..] => true, - _ => false, - } -} - -fn main() { - is_line_doc_comment_2("asd"); -} From 17716be86e36720885a9918a1e08da7a5669ceca Mon Sep 17 00:00:00 2001 From: Jubilee Young Date: Mon, 10 Feb 2025 10:30:41 -0800 Subject: [PATCH 06/10] compiler: die immediately instead of handling unknown target codegen We cannot produce anything useful if asked to compile unknown targets. We should handle the error immediately at the point of discovery instead of propagating it upward, and preferably in the simplest way: Die. This allows cleaning up our "error-handling" spread across 5 crates. --- compiler/rustc_const_eval/src/errors.rs | 10 -------- .../src/interpret/eval_context.rs | 3 --- .../rustc_middle/src/mir/interpret/error.rs | 4 --- compiler/rustc_middle/src/ty/layout.rs | 7 ------ compiler/rustc_passes/src/abi_test.rs | 9 ------- compiler/rustc_target/src/callconv/mod.rs | 25 +++---------------- compiler/rustc_ty_utils/src/abi.rs | 12 +++------ 7 files changed, 7 insertions(+), 63 deletions(-) diff --git a/compiler/rustc_const_eval/src/errors.rs b/compiler/rustc_const_eval/src/errors.rs index 8df9877cabca2..c08495c012f83 100644 --- a/compiler/rustc_const_eval/src/errors.rs +++ b/compiler/rustc_const_eval/src/errors.rs @@ -16,7 +16,6 @@ use rustc_middle::mir::interpret::{ }; use rustc_middle::ty::{self, Mutability, Ty}; use rustc_span::{Span, Symbol}; -use rustc_target::callconv::AdjustForForeignAbiError; use crate::interpret::InternKind; @@ -936,9 +935,6 @@ impl<'tcx> ReportErrorExt for InvalidProgramInfo<'tcx> { InvalidProgramInfo::TooGeneric => const_eval_too_generic, InvalidProgramInfo::AlreadyReported(_) => const_eval_already_reported, InvalidProgramInfo::Layout(e) => e.diagnostic_message(), - InvalidProgramInfo::FnAbiAdjustForForeignAbi(_) => { - rustc_middle::error::middle_adjust_for_foreign_abi_error - } } } fn add_args(self, diag: &mut Diag<'_, G>) { @@ -953,12 +949,6 @@ impl<'tcx> ReportErrorExt for InvalidProgramInfo<'tcx> { } dummy_diag.cancel(); } - InvalidProgramInfo::FnAbiAdjustForForeignAbi( - AdjustForForeignAbiError::Unsupported { arch, abi }, - ) => { - diag.arg("arch", arch); - diag.arg("abi", abi.name()); - } } } } diff --git a/compiler/rustc_const_eval/src/interpret/eval_context.rs b/compiler/rustc_const_eval/src/interpret/eval_context.rs index 95a72d3cbc1d7..66a75113652f1 100644 --- a/compiler/rustc_const_eval/src/interpret/eval_context.rs +++ b/compiler/rustc_const_eval/src/interpret/eval_context.rs @@ -106,9 +106,6 @@ impl<'tcx, M: Machine<'tcx>> FnAbiOfHelpers<'tcx> for InterpCx<'tcx, M> { ) -> InterpErrorKind<'tcx> { match err { FnAbiError::Layout(err) => err_inval!(Layout(err)), - FnAbiError::AdjustForForeignAbi(err) => { - err_inval!(FnAbiAdjustForForeignAbi(err)) - } } } } diff --git a/compiler/rustc_middle/src/mir/interpret/error.rs b/compiler/rustc_middle/src/mir/interpret/error.rs index 1222ba052cceb..8861e31b0991c 100644 --- a/compiler/rustc_middle/src/mir/interpret/error.rs +++ b/compiler/rustc_middle/src/mir/interpret/error.rs @@ -216,10 +216,6 @@ pub enum InvalidProgramInfo<'tcx> { AlreadyReported(ReportedErrorInfo), /// An error occurred during layout computation. Layout(layout::LayoutError<'tcx>), - /// An error occurred during FnAbi computation: the passed --target lacks FFI support - /// (which unfortunately typeck does not reject). - /// Not using `FnAbiError` as that contains a nested `LayoutError`. - FnAbiAdjustForForeignAbi(rustc_target::callconv::AdjustForForeignAbiError), } /// Details of why a pointer had to be in-bounds. diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs index e5015ea3c3d1f..4b3e29b7c6cc8 100644 --- a/compiler/rustc_middle/src/ty/layout.rs +++ b/compiler/rustc_middle/src/ty/layout.rs @@ -24,7 +24,6 @@ use rustc_target::spec::{ use tracing::debug; use {rustc_abi as abi, rustc_hir as hir}; -use crate::error::UnsupportedFnAbi; use crate::middle::codegen_fn_attrs::CodegenFnAttrFlags; use crate::query::TyCtxtAt; use crate::ty::normalize_erasing_regions::NormalizationError; @@ -1275,18 +1274,12 @@ pub fn fn_can_unwind(tcx: TyCtxt<'_>, fn_def_id: Option, abi: ExternAbi) pub enum FnAbiError<'tcx> { /// Error produced by a `layout_of` call, while computing `FnAbi` initially. Layout(LayoutError<'tcx>), - - /// Error produced by attempting to adjust a `FnAbi`, for a "foreign" ABI. - AdjustForForeignAbi(rustc_target::callconv::AdjustForForeignAbiError), } impl<'a, 'b, G: EmissionGuarantee> Diagnostic<'a, G> for FnAbiError<'b> { fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a, G> { match self { Self::Layout(e) => e.into_diagnostic().into_diag(dcx, level), - Self::AdjustForForeignAbi( - rustc_target::callconv::AdjustForForeignAbiError::Unsupported { arch, abi }, - ) => UnsupportedFnAbi { arch, abi: abi.name() }.into_diag(dcx, level), } } } diff --git a/compiler/rustc_passes/src/abi_test.rs b/compiler/rustc_passes/src/abi_test.rs index 4601bb87b76f9..671b7d7ad76cf 100644 --- a/compiler/rustc_passes/src/abi_test.rs +++ b/compiler/rustc_passes/src/abi_test.rs @@ -46,15 +46,6 @@ fn unwrap_fn_abi<'tcx>( span: tcx.def_span(item_def_id), }); } - Err(FnAbiError::AdjustForForeignAbi(e)) => { - // Sadly there seems to be no `into_diagnostic` for this case... and I am not sure if - // this can even be reached. Anyway this is a perma-unstable debug attribute, an ICE - // isn't the worst thing. Also this matches what codegen does. - span_bug!( - tcx.def_span(item_def_id), - "error computing fn_abi_of_instance, cannot adjust for foreign ABI: {e:?}", - ) - } } } diff --git a/compiler/rustc_target/src/callconv/mod.rs b/compiler/rustc_target/src/callconv/mod.rs index 50ac6c8fcde16..b49dd2588692d 100644 --- a/compiler/rustc_target/src/callconv/mod.rs +++ b/compiler/rustc_target/src/callconv/mod.rs @@ -6,7 +6,6 @@ use rustc_abi::{ Size, TyAbiInterface, TyAndLayout, }; use rustc_macros::HashStable_Generic; -use rustc_span::Symbol; use crate::spec::{HasTargetSpec, HasWasmCAbiOpt, HasX86AbiOpt, WasmCAbi}; @@ -623,19 +622,8 @@ impl<'a, Ty: fmt::Display> fmt::Debug for FnAbi<'a, Ty> { } } -/// Error produced by attempting to adjust a `FnAbi`, for a "foreign" ABI. -#[derive(Copy, Clone, Debug, HashStable_Generic)] -pub enum AdjustForForeignAbiError { - /// Target architecture doesn't support "foreign" (i.e. non-Rust) ABIs. - Unsupported { arch: Symbol, abi: ExternAbi }, -} - impl<'a, Ty> FnAbi<'a, Ty> { - pub fn adjust_for_foreign_abi( - &mut self, - cx: &C, - abi: ExternAbi, - ) -> Result<(), AdjustForForeignAbiError> + pub fn adjust_for_foreign_abi(&mut self, cx: &C, abi: ExternAbi) where Ty: TyAbiInterface<'a, C> + Copy, C: HasDataLayout + HasTargetSpec + HasWasmCAbiOpt + HasX86AbiOpt, @@ -644,7 +632,7 @@ impl<'a, Ty> FnAbi<'a, Ty> { if let Some(arg) = self.args.first_mut() { arg.pass_by_stack_offset(None); } - return Ok(()); + return; } let spec = cx.target_spec(); @@ -719,15 +707,8 @@ impl<'a, Ty> FnAbi<'a, Ty> { } "wasm64" => wasm::compute_c_abi_info(cx, self), "bpf" => bpf::compute_abi_info(self), - arch => { - return Err(AdjustForForeignAbiError::Unsupported { - arch: Symbol::intern(arch), - abi, - }); - } + arch => panic!("no lowering implemented for {arch}"), } - - Ok(()) } pub fn adjust_for_rust_abi(&mut self, cx: &C, abi: ExternAbi) diff --git a/compiler/rustc_ty_utils/src/abi.rs b/compiler/rustc_ty_utils/src/abi.rs index 169f3a78c26a7..332b00e8423bb 100644 --- a/compiler/rustc_ty_utils/src/abi.rs +++ b/compiler/rustc_ty_utils/src/abi.rs @@ -650,7 +650,7 @@ fn fn_abi_new_uncached<'tcx>( conv, can_unwind: fn_can_unwind(cx.tcx(), fn_def_id, sig.abi), }; - fn_abi_adjust_for_abi(cx, &mut fn_abi, sig.abi, fn_def_id)?; + fn_abi_adjust_for_abi(cx, &mut fn_abi, sig.abi, fn_def_id); debug!("fn_abi_new_uncached = {:?}", fn_abi); fn_abi_sanity_check(cx, &fn_abi, sig.abi); Ok(tcx.arena.alloc(fn_abi)) @@ -662,7 +662,7 @@ fn fn_abi_adjust_for_abi<'tcx>( fn_abi: &mut FnAbi<'tcx, Ty<'tcx>>, abi: ExternAbi, fn_def_id: Option, -) -> Result<(), &'tcx FnAbiError<'tcx>> { +) { if abi == ExternAbi::Unadjusted { // The "unadjusted" ABI passes aggregates in "direct" mode. That's fragile but needed for // some LLVM intrinsics. @@ -682,7 +682,7 @@ fn fn_abi_adjust_for_abi<'tcx>( for arg in fn_abi.args.iter_mut() { unadjust(arg); } - return Ok(()); + return; } let tcx = cx.tcx(); @@ -723,12 +723,8 @@ fn fn_abi_adjust_for_abi<'tcx>( } } } else { - fn_abi - .adjust_for_foreign_abi(cx, abi) - .map_err(|err| &*tcx.arena.alloc(FnAbiError::AdjustForForeignAbi(err)))?; + fn_abi.adjust_for_foreign_abi(cx, abi); } - - Ok(()) } #[tracing::instrument(level = "debug", skip(cx))] From fd58652a7de3c04ca957dd8fdc580c16ad17a8d3 Mon Sep 17 00:00:00 2001 From: Jubilee Young Date: Mon, 10 Feb 2025 11:19:02 -0800 Subject: [PATCH 07/10] cg_gcc: stop caring about compiling for unknown targets --- compiler/rustc_codegen_gcc/src/int.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_codegen_gcc/src/int.rs b/compiler/rustc_codegen_gcc/src/int.rs index 4a1db8d662a9f..f3552d9b12fcb 100644 --- a/compiler/rustc_codegen_gcc/src/int.rs +++ b/compiler/rustc_codegen_gcc/src/int.rs @@ -400,7 +400,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { conv: Conv::C, can_unwind: false, }; - fn_abi.adjust_for_foreign_abi(self.cx, ExternAbi::C { unwind: false }).unwrap(); + fn_abi.adjust_for_foreign_abi(self.cx, ExternAbi::C { unwind: false }); let ret_indirect = matches!(fn_abi.ret.mode, PassMode::Indirect { .. }); From af6020320d32fb3491b8d30b580f675a2e1d16a6 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 11 Feb 2025 13:58:38 +1100 Subject: [PATCH 08/10] Simplify intra-crate qualifiers. The following is a weird pattern for a file within `rustc_middle`: ``` use rustc_middle::aaa; use crate::bbb; ``` More sensible and standard would be this: ``` use crate::{aaa, bbb}; ``` I.e. we generally prefer using `crate::` to using a crate's own name. (Exceptions are things like in macros where `crate::` doesn't work because the macro is used in multiple crates.) This commit fixes a bunch of these weird qualifiers. --- compiler/rustc_errors/src/diagnostic_impls.rs | 4 ++-- compiler/rustc_middle/src/hir/map/mod.rs | 3 +-- compiler/rustc_middle/src/middle/stability.rs | 2 +- .../rustc_middle/src/mir/generic_graph.rs | 3 ++- .../rustc_middle/src/mir/generic_graphviz.rs | 3 ++- compiler/rustc_middle/src/mir/graphviz.rs | 2 +- .../rustc_middle/src/mir/interpret/mod.rs | 2 +- compiler/rustc_middle/src/mir/patch.rs | 3 ++- compiler/rustc_middle/src/mir/pretty.rs | 13 ++++++------- compiler/rustc_middle/src/query/erase.rs | 4 ++-- .../rustc_middle/src/query/on_disk_cache.rs | 15 ++++++++------- compiler/rustc_middle/src/thir.rs | 19 ++++++++++--------- compiler/rustc_middle/src/ty/cast.rs | 2 +- compiler/rustc_middle/src/ty/codec.rs | 5 ++--- compiler/rustc_middle/src/ty/instance.rs | 2 +- compiler/rustc_middle/src/ty/print/pretty.rs | 4 ++-- .../rustc_middle/src/ty/typeck_results.rs | 2 +- compiler/rustc_middle/src/util/mod.rs | 8 ++++---- compiler/rustc_middle/src/values.rs | 2 +- .../src/relate/solver_relating.rs | 6 +++--- 20 files changed, 53 insertions(+), 51 deletions(-) diff --git a/compiler/rustc_errors/src/diagnostic_impls.rs b/compiler/rustc_errors/src/diagnostic_impls.rs index d179396398f01..14baf7554bcf6 100644 --- a/compiler/rustc_errors/src/diagnostic_impls.rs +++ b/compiler/rustc_errors/src/diagnostic_impls.rs @@ -108,13 +108,13 @@ impl IntoDiagArg for rustc_type_ir::ExistentialTrait } impl IntoDiagArg for rustc_type_ir::UnevaluatedConst { - fn into_diag_arg(self) -> rustc_errors::DiagArgValue { + fn into_diag_arg(self) -> DiagArgValue { format!("{self:?}").into_diag_arg() } } impl IntoDiagArg for rustc_type_ir::FnSig { - fn into_diag_arg(self) -> rustc_errors::DiagArgValue { + fn into_diag_arg(self) -> DiagArgValue { format!("{self:?}").into_diag_arg() } } diff --git a/compiler/rustc_middle/src/hir/map/mod.rs b/compiler/rustc_middle/src/hir/map/mod.rs index 4df4624971df1..83c7bb0f52f4a 100644 --- a/compiler/rustc_middle/src/hir/map/mod.rs +++ b/compiler/rustc_middle/src/hir/map/mod.rs @@ -10,11 +10,10 @@ use rustc_hir::definitions::{DefKey, DefPath, DefPathHash}; use rustc_hir::intravisit::Visitor; use rustc_hir::*; use rustc_hir_pretty as pprust_hir; -use rustc_middle::hir::nested_filter; use rustc_span::def_id::StableCrateId; use rustc_span::{ErrorGuaranteed, Ident, Span, Symbol, kw, sym, with_metavar_spans}; -use crate::hir::ModuleItems; +use crate::hir::{ModuleItems, nested_filter}; use crate::middle::debugger_visualizer::DebuggerVisualizerFile; use crate::query::LocalCrate; use crate::ty::TyCtxt; diff --git a/compiler/rustc_middle/src/middle/stability.rs b/compiler/rustc_middle/src/middle/stability.rs index 77a7da2c74bc2..93bbf6d7fa4ff 100644 --- a/compiler/rustc_middle/src/middle/stability.rs +++ b/compiler/rustc_middle/src/middle/stability.rs @@ -13,7 +13,6 @@ use rustc_feature::GateIssue; use rustc_hir::def_id::{DefId, LocalDefId, LocalDefIdMap}; use rustc_hir::{self as hir, HirId}; use rustc_macros::{Decodable, Encodable, HashStable, Subdiagnostic}; -use rustc_middle::ty::print::with_no_trimmed_paths; use rustc_session::Session; use rustc_session::lint::builtin::{DEPRECATED, DEPRECATED_IN_FUTURE, SOFT_UNSTABLE}; use rustc_session::lint::{BuiltinLintDiag, DeprecatedSinceKind, Level, Lint, LintBuffer}; @@ -23,6 +22,7 @@ use tracing::debug; pub use self::StabilityLevel::*; use crate::ty::TyCtxt; +use crate::ty::print::with_no_trimmed_paths; #[derive(PartialEq, Clone, Copy, Debug)] pub enum StabilityLevel { diff --git a/compiler/rustc_middle/src/mir/generic_graph.rs b/compiler/rustc_middle/src/mir/generic_graph.rs index a52ec58a1ee69..3fd73712b0968 100644 --- a/compiler/rustc_middle/src/mir/generic_graph.rs +++ b/compiler/rustc_middle/src/mir/generic_graph.rs @@ -1,5 +1,6 @@ use gsgdt::{Edge, Graph, Node, NodeStyle}; -use rustc_middle::mir::*; + +use crate::mir::*; /// Convert an MIR function into a gsgdt Graph pub(crate) fn mir_fn_to_generic_graph<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'_>) -> Graph { diff --git a/compiler/rustc_middle/src/mir/generic_graphviz.rs b/compiler/rustc_middle/src/mir/generic_graphviz.rs index e1c3d8156d83e..bce7beb521da4 100644 --- a/compiler/rustc_middle/src/mir/generic_graphviz.rs +++ b/compiler/rustc_middle/src/mir/generic_graphviz.rs @@ -2,7 +2,8 @@ use std::io::{self, Write}; use rustc_data_structures::graph::{self, iterate}; use rustc_graphviz as dot; -use rustc_middle::ty::TyCtxt; + +use crate::ty::TyCtxt; pub struct GraphvizWriter< 'a, diff --git a/compiler/rustc_middle/src/mir/graphviz.rs b/compiler/rustc_middle/src/mir/graphviz.rs index 7bb41193d5c9c..a64b122fbc9e5 100644 --- a/compiler/rustc_middle/src/mir/graphviz.rs +++ b/compiler/rustc_middle/src/mir/graphviz.rs @@ -2,10 +2,10 @@ use std::io::{self, Write}; use gsgdt::GraphvizSettings; use rustc_graphviz as dot; -use rustc_middle::mir::*; use super::generic_graph::mir_fn_to_generic_graph; use super::pretty::dump_mir_def_ids; +use crate::mir::*; /// Write a graphviz DOT graph of a list of MIRs. pub fn write_mir_graphviz(tcx: TyCtxt<'_>, single: Option, w: &mut W) -> io::Result<()> diff --git a/compiler/rustc_middle/src/mir/interpret/mod.rs b/compiler/rustc_middle/src/mir/interpret/mod.rs index 45c862e0d34bf..c48cfffa05cc4 100644 --- a/compiler/rustc_middle/src/mir/interpret/mod.rs +++ b/compiler/rustc_middle/src/mir/interpret/mod.rs @@ -20,7 +20,6 @@ use rustc_data_structures::sync::{AtomicU64, Lock}; use rustc_hir::def::DefKind; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_macros::{HashStable, TyDecodable, TyEncodable, TypeFoldable, TypeVisitable}; -use rustc_middle::ty::print::with_no_trimmed_paths; use rustc_serialize::{Decodable, Encodable}; use tracing::{debug, trace}; // Also make the error macros available from this module. @@ -46,6 +45,7 @@ pub use self::pointer::{CtfeProvenance, Pointer, PointerArithmetic, Provenance}; pub use self::value::Scalar; use crate::mir; use crate::ty::codec::{TyDecoder, TyEncoder}; +use crate::ty::print::with_no_trimmed_paths; use crate::ty::{self, Instance, Ty, TyCtxt}; /// Uniquely identifies one of the following: diff --git a/compiler/rustc_middle/src/mir/patch.rs b/compiler/rustc_middle/src/mir/patch.rs index 18c48d99b81ce..748797fbb8d5c 100644 --- a/compiler/rustc_middle/src/mir/patch.rs +++ b/compiler/rustc_middle/src/mir/patch.rs @@ -1,6 +1,7 @@ -use rustc_middle::mir::*; use tracing::debug; +use crate::mir::*; + /// This struct represents a patch to MIR, which can add /// new statements and basic blocks and patch over block /// terminators. diff --git a/compiler/rustc_middle/src/mir/pretty.rs b/compiler/rustc_middle/src/mir/pretty.rs index 11ebbbe807db7..b0df6c71014a3 100644 --- a/compiler/rustc_middle/src/mir/pretty.rs +++ b/compiler/rustc_middle/src/mir/pretty.rs @@ -5,17 +5,16 @@ use std::{fs, io}; use rustc_abi::Size; use rustc_ast::InlineAsmTemplatePiece; -use rustc_middle::mir::interpret::{ - AllocBytes, AllocId, Allocation, GlobalAlloc, Pointer, Provenance, alloc_range, - read_target_uint, -}; -use rustc_middle::mir::visit::Visitor; -use rustc_middle::mir::*; use tracing::trace; use ty::print::PrettyPrinter; use super::graphviz::write_mir_fn_graphviz; -use crate::mir::interpret::ConstAllocation; +use crate::mir::interpret::{ + AllocBytes, AllocId, Allocation, ConstAllocation, GlobalAlloc, Pointer, Provenance, + alloc_range, read_target_uint, +}; +use crate::mir::visit::Visitor; +use crate::mir::*; const INDENT: &str = " "; /// Alignment for lining up comments following MIR statements diff --git a/compiler/rustc_middle/src/query/erase.rs b/compiler/rustc_middle/src/query/erase.rs index 14f871cbbdcbc..cbd60920bc572 100644 --- a/compiler/rustc_middle/src/query/erase.rs +++ b/compiler/rustc_middle/src/query/erase.rs @@ -101,9 +101,9 @@ impl EraseType for Result<&'_ T, &'_ ty::layout::FnAbiError<'_>> { type Result = [u8; size_of::>>()]; } -impl EraseType for Result<(&'_ T, rustc_middle::thir::ExprId), rustc_errors::ErrorGuaranteed> { +impl EraseType for Result<(&'_ T, crate::thir::ExprId), rustc_errors::ErrorGuaranteed> { type Result = [u8; size_of::< - Result<(&'static (), rustc_middle::thir::ExprId), rustc_errors::ErrorGuaranteed>, + Result<(&'static (), crate::thir::ExprId), rustc_errors::ErrorGuaranteed>, >()]; } diff --git a/compiler/rustc_middle/src/query/on_disk_cache.rs b/compiler/rustc_middle/src/query/on_disk_cache.rs index 3247bdbf1050c..d9035efaf56d0 100644 --- a/compiler/rustc_middle/src/query/on_disk_cache.rs +++ b/compiler/rustc_middle/src/query/on_disk_cache.rs @@ -11,12 +11,6 @@ use rustc_hir::def_id::{CrateNum, DefId, DefIndex, LOCAL_CRATE, LocalDefId, Stab use rustc_hir::definitions::DefPathHash; use rustc_index::{Idx, IndexVec}; use rustc_macros::{Decodable, Encodable}; -use rustc_middle::dep_graph::{DepNodeIndex, SerializedDepNodeIndex}; -use rustc_middle::mir::interpret::{AllocDecodingSession, AllocDecodingState}; -use rustc_middle::mir::mono::MonoItem; -use rustc_middle::mir::{self, interpret}; -use rustc_middle::ty::codec::{RefDecodable, TyDecoder, TyEncoder}; -use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_query_system::query::QuerySideEffects; use rustc_serialize::opaque::{FileEncodeResult, FileEncoder, IntEncodedWithFixedSize, MemDecoder}; use rustc_serialize::{Decodable, Decoder, Encodable, Encoder}; @@ -30,6 +24,13 @@ use rustc_span::{ SpanDecoder, SpanEncoder, StableSourceFileId, Symbol, }; +use crate::dep_graph::{DepNodeIndex, SerializedDepNodeIndex}; +use crate::mir::interpret::{AllocDecodingSession, AllocDecodingState}; +use crate::mir::mono::MonoItem; +use crate::mir::{self, interpret}; +use crate::ty::codec::{RefDecodable, TyDecoder, TyEncoder}; +use crate::ty::{self, Ty, TyCtxt}; + const TAG_FILE_FOOTER: u128 = 0xC0FFEE_C0FFEE_C0FFEE_C0FFEE_C0FFEE; // A normal span encoded with both location information and a `SyntaxContext` @@ -563,7 +564,7 @@ impl<'a, 'tcx> TyDecoder for CacheDecoder<'a, 'tcx> { } } -rustc_middle::implement_ty_decoder!(CacheDecoder<'a, 'tcx>); +crate::implement_ty_decoder!(CacheDecoder<'a, 'tcx>); // This ensures that the `Decodable::decode` specialization for `Vec` is used // when a `CacheDecoder` is passed to `Decodable::decode`. Unfortunately, we have to manually opt diff --git a/compiler/rustc_middle/src/thir.rs b/compiler/rustc_middle/src/thir.rs index 4dc8f27955358..2ab8750f727c0 100644 --- a/compiler/rustc_middle/src/thir.rs +++ b/compiler/rustc_middle/src/thir.rs @@ -20,20 +20,21 @@ use rustc_hir::def_id::DefId; use rustc_hir::{BindingMode, ByRef, HirId, MatchSource, RangeEnd}; use rustc_index::{IndexVec, newtype_index}; use rustc_macros::{HashStable, TypeVisitable}; -use rustc_middle::middle::region; -use rustc_middle::mir::interpret::AllocId; -use rustc_middle::mir::{self, BinOp, BorrowKind, FakeReadCause, UnOp}; -use rustc_middle::ty::adjustment::PointerCoercion; -use rustc_middle::ty::layout::IntegerExt; -use rustc_middle::ty::{ - self, AdtDef, CanonicalUserType, CanonicalUserTypeAnnotation, FnSig, GenericArgsRef, List, Ty, - TyCtxt, UpvarArgs, -}; use rustc_span::def_id::LocalDefId; use rustc_span::{ErrorGuaranteed, Span, Symbol}; use rustc_target::asm::InlineAsmRegOrRegClass; use tracing::instrument; +use crate::middle::region; +use crate::mir::interpret::AllocId; +use crate::mir::{self, BinOp, BorrowKind, FakeReadCause, UnOp}; +use crate::ty::adjustment::PointerCoercion; +use crate::ty::layout::IntegerExt; +use crate::ty::{ + self, AdtDef, CanonicalUserType, CanonicalUserTypeAnnotation, FnSig, GenericArgsRef, List, Ty, + TyCtxt, UpvarArgs, +}; + pub mod visit; macro_rules! thir_with_elements { diff --git a/compiler/rustc_middle/src/ty/cast.rs b/compiler/rustc_middle/src/ty/cast.rs index b1316ceef5ac7..10f7d58963623 100644 --- a/compiler/rustc_middle/src/ty/cast.rs +++ b/compiler/rustc_middle/src/ty/cast.rs @@ -2,8 +2,8 @@ // typeck and codegen. use rustc_macros::{HashStable, TyDecodable, TyEncodable}; -use rustc_middle::mir; +use crate::mir; use crate::ty::{self, Ty}; /// Types that are represented as ints. diff --git a/compiler/rustc_middle/src/ty/codec.rs b/compiler/rustc_middle/src/ty/codec.rs index 94bf1aa4f0356..6b6e0ffc65646 100644 --- a/compiler/rustc_middle/src/ty/codec.rs +++ b/compiler/rustc_middle/src/ty/codec.rs @@ -13,8 +13,6 @@ use std::marker::DiscriminantKind; use rustc_abi::{FieldIdx, VariantIdx}; use rustc_data_structures::fx::FxHashMap; use rustc_hir::def_id::LocalDefId; -use rustc_middle::mir::mono::MonoItem; -use rustc_middle::ty::TyCtxt; use rustc_serialize::{Decodable, Encodable}; use rustc_span::Span; use rustc_span::source_map::Spanned; @@ -23,9 +21,10 @@ pub use rustc_type_ir::{TyDecoder, TyEncoder}; use crate::arena::ArenaAllocatable; use crate::infer::canonical::{CanonicalVarInfo, CanonicalVarInfos}; use crate::mir::interpret::{AllocId, ConstAllocation, CtfeProvenance}; +use crate::mir::mono::MonoItem; use crate::mir::{self}; use crate::traits; -use crate::ty::{self, AdtDef, GenericArgsRef, Ty}; +use crate::ty::{self, AdtDef, GenericArgsRef, Ty, TyCtxt}; /// The shorthand encoding uses an enum's variant index `usize` /// and is offset by this value so it never matches a real variant. diff --git a/compiler/rustc_middle/src/ty/instance.rs b/compiler/rustc_middle/src/ty/instance.rs index b7a648aae3f19..e9c19331e4a0b 100644 --- a/compiler/rustc_middle/src/ty/instance.rs +++ b/compiler/rustc_middle/src/ty/instance.rs @@ -10,13 +10,13 @@ use rustc_hir::def_id::{CrateNum, DefId}; use rustc_hir::lang_items::LangItem; use rustc_index::bit_set::FiniteBitSet; use rustc_macros::{Decodable, Encodable, HashStable, Lift, TyDecodable, TyEncodable}; -use rustc_middle::ty::normalize_erasing_regions::NormalizationError; use rustc_span::def_id::LOCAL_CRATE; use rustc_span::{DUMMY_SP, Span, Symbol}; use tracing::{debug, instrument}; use crate::error; use crate::middle::codegen_fn_attrs::CodegenFnAttrFlags; +use crate::ty::normalize_erasing_regions::NormalizationError; use crate::ty::print::{FmtPrinter, Printer, shrunk_instance_name}; use crate::ty::{ self, EarlyBinder, GenericArgs, GenericArgsRef, Ty, TyCtxt, TypeFoldable, TypeSuperVisitable, diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index feae8ea312eaa..343aabd7bbb36 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -1512,7 +1512,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write { ty::ExprKind::Binop(op) => { let (_, _, c1, c2) = expr.binop_args(); - let precedence = |binop: rustc_middle::mir::BinOp| { + let precedence = |binop: crate::mir::BinOp| { use rustc_ast::util::parser::AssocOp; AssocOp::from_ast_binop(binop.to_hir_binop()).precedence() }; @@ -1558,7 +1558,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write { ty::ExprKind::UnOp(op) => { let (_, ct) = expr.unop_args(); - use rustc_middle::mir::UnOp; + use crate::mir::UnOp; let formatted_op = match op { UnOp::Not => "!", UnOp::Neg => "-", diff --git a/compiler/rustc_middle/src/ty/typeck_results.rs b/compiler/rustc_middle/src/ty/typeck_results.rs index 49bdb5e9dc318..1b5b791bb24ae 100644 --- a/compiler/rustc_middle/src/ty/typeck_results.rs +++ b/compiler/rustc_middle/src/ty/typeck_results.rs @@ -14,13 +14,13 @@ use rustc_hir::{ }; use rustc_index::IndexVec; use rustc_macros::{HashStable, TyDecodable, TyEncodable, TypeFoldable, TypeVisitable}; -use rustc_middle::mir::FakeReadCause; use rustc_session::Session; use rustc_span::Span; use super::RvalueScopes; use crate::hir::place::Place as HirPlace; use crate::infer::canonical::Canonical; +use crate::mir::FakeReadCause; use crate::traits::ObligationCause; use crate::ty::{ self, BoundVar, CanonicalPolyFnSig, ClosureSizeProfileData, GenericArgKind, GenericArgs, diff --git a/compiler/rustc_middle/src/util/mod.rs b/compiler/rustc_middle/src/util/mod.rs index 8c875007b7fb9..85519fb0a7d2c 100644 --- a/compiler/rustc_middle/src/util/mod.rs +++ b/compiler/rustc_middle/src/util/mod.rs @@ -2,9 +2,9 @@ pub mod bug; #[derive(Default, Copy, Clone)] pub struct Providers { - pub queries: rustc_middle::query::Providers, - pub extern_queries: rustc_middle::query::ExternProviders, - pub hooks: rustc_middle::hooks::Providers, + pub queries: crate::query::Providers, + pub extern_queries: crate::query::ExternProviders, + pub hooks: crate::hooks::Providers, } /// Backwards compatibility hack to keep the diff small. This @@ -17,7 +17,7 @@ impl std::ops::DerefMut for Providers { } impl std::ops::Deref for Providers { - type Target = rustc_middle::query::Providers; + type Target = crate::query::Providers; fn deref(&self) -> &Self::Target { &self.queries diff --git a/compiler/rustc_middle/src/values.rs b/compiler/rustc_middle/src/values.rs index 867f8f639698c..433f7542bd704 100644 --- a/compiler/rustc_middle/src/values.rs +++ b/compiler/rustc_middle/src/values.rs @@ -7,7 +7,6 @@ use rustc_errors::codes::*; use rustc_errors::{Applicability, MultiSpan, pluralize, struct_span_code_err}; use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; -use rustc_middle::ty::{self, Representability, Ty, TyCtxt}; use rustc_query_system::Value; use rustc_query_system::query::{CycleError, report_cycle}; use rustc_span::def_id::LocalDefId; @@ -15,6 +14,7 @@ use rustc_span::{ErrorGuaranteed, Span}; use crate::dep_graph::dep_kinds; use crate::query::plumbing::CyclePlaceholder; +use crate::ty::{self, Representability, Ty, TyCtxt}; impl<'tcx> Value> for Ty<'_> { fn from_cycle_error(tcx: TyCtxt<'tcx>, _: &CycleError, guar: ErrorGuaranteed) -> Self { diff --git a/compiler/rustc_type_ir/src/relate/solver_relating.rs b/compiler/rustc_type_ir/src/relate/solver_relating.rs index dc2312b2da3a5..e42639c68075a 100644 --- a/compiler/rustc_type_ir/src/relate/solver_relating.rs +++ b/compiler/rustc_type_ir/src/relate/solver_relating.rs @@ -1,10 +1,10 @@ -pub use rustc_type_ir::relate::*; -use rustc_type_ir::solve::Goal; -use rustc_type_ir::{self as ty, InferCtxtLike, Interner}; use tracing::{debug, instrument}; use self::combine::{PredicateEmittingRelation, super_combine_consts, super_combine_tys}; use crate::data_structures::DelayedSet; +pub use crate::relate::*; +use crate::solve::Goal; +use crate::{self as ty, InferCtxtLike, Interner}; pub trait RelateExt: InferCtxtLike { fn relate>( From 166680c480182253affb34c8aa5d0572a43f8b01 Mon Sep 17 00:00:00 2001 From: Marijn Schouten Date: Fri, 31 Jan 2025 14:31:34 +0100 Subject: [PATCH 09/10] Update docs for impl keyword --- library/std/src/keyword_docs.rs | 41 +++++++++++++++++++++++++++------ 1 file changed, 34 insertions(+), 7 deletions(-) diff --git a/library/std/src/keyword_docs.rs b/library/std/src/keyword_docs.rs index 1d26bf37f4d28..825a89fc7f2c9 100644 --- a/library/std/src/keyword_docs.rs +++ b/library/std/src/keyword_docs.rs @@ -651,16 +651,24 @@ mod if_keyword {} #[doc(keyword = "impl")] // -/// Implement some functionality for a type. +/// Implementations of functionality for a type, or a type implementing some functionality. +/// +/// There are two uses of the keyword `impl`: +/// * An `impl` block is an item that is used to implement some functionality for a type. +/// * An `impl Trait` in a type-position can be used to designate a type that implements a trait called `Trait`. +/// +/// # Implementing Functionality for a Type /// /// The `impl` keyword is primarily used to define implementations on types. Inherent /// implementations are standalone, while trait implementations are used to implement traits for /// types, or other traits. /// -/// Functions and consts can both be defined in an implementation. A function defined in an -/// `impl` block can be standalone, meaning it would be called like `Foo::bar()`. If the function +/// An implementation consists of definitions of functions and consts. A function defined in an +/// `impl` block can be standalone, meaning it would be called like `Vec::new()`. If the function /// takes `self`, `&self`, or `&mut self` as its first argument, it can also be called using -/// method-call syntax, a familiar feature to any object oriented programmer, like `foo.bar()`. +/// method-call syntax, a familiar feature to any object-oriented programmer, like `vec.len()`. +/// +/// ## Inherent Implementations /// /// ```rust /// struct Example { @@ -680,6 +688,17 @@ mod if_keyword {} /// self.number /// } /// } +/// ``` +/// +/// It matters little where an inherent implementation is defined; +/// its functionality is in scope wherever its implementing type is. +/// +/// ## Trait Implementations +/// +/// ```rust +/// struct Example { +/// number: i32, +/// } /// /// trait Thingy { /// fn do_thingy(&self); @@ -692,11 +711,19 @@ mod if_keyword {} /// } /// ``` /// +/// It matters little where a trait implementation is defined; +/// its functionality can be brought into scope by importing the trait it implements. +/// /// For more information on implementations, see the [Rust book][book1] or the [Reference]. /// -/// The other use of the `impl` keyword is in `impl Trait` syntax, which can be seen as a shorthand -/// for "a concrete type that implements this trait". Its primary use is working with closures, -/// which have type definitions generated at compile time that can't be simply typed out. +/// # Designating a Type that Implements Some Functionality +/// +/// The other use of the `impl` keyword is in `impl Trait` syntax, which can be understood to mean +/// "any (or some) concrete type that implements Trait". +/// It can be used as the type of a variable declaration, +/// in [argument position](https://rust-lang.github.io/rfcs/1951-expand-impl-trait.html) +/// or in [return position](https://rust-lang.github.io/rfcs/3425-return-position-impl-trait-in-traits.html). +/// One pertinent use case is in working with closures, which have unnameable types. /// /// ```rust /// fn thing_returning_closure() -> impl Fn(i32) -> bool { From e279c4eadba97aaf6f64830b4a4a83be8f5879c4 Mon Sep 17 00:00:00 2001 From: Marijn Schouten Date: Wed, 29 Jan 2025 15:18:10 +0100 Subject: [PATCH 10/10] include note on variance and example Fixes #89150 Co-authored-by: Daniel Henry-Mantilla --- library/core/src/any.rs | 98 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 96 insertions(+), 2 deletions(-) diff --git a/library/core/src/any.rs b/library/core/src/any.rs index 17d9455592787..f90de1f5ced40 100644 --- a/library/core/src/any.rs +++ b/library/core/src/any.rs @@ -610,6 +610,101 @@ impl dyn Any + Send + Sync { /// While `TypeId` implements `Hash`, `PartialOrd`, and `Ord`, it is worth /// noting that the hashes and ordering will vary between Rust releases. Beware /// of relying on them inside of your code! +/// +/// # Danger of Improper Variance +/// +/// You might think that subtyping is impossible between two static types, +/// but this is false; there exists a static type with a static subtype. +/// To wit, `fn(&str)`, which is short for `for<'any> fn(&'any str)`, and +/// `fn(&'static str)`, are two distinct, static types, and yet, +/// `fn(&str)` is a subtype of `fn(&'static str)`, since any value of type +/// `fn(&str)` can be used where a value of type `fn(&'static str)` is needed. +/// +/// This means that abstractions around `TypeId`, despite its +/// `'static` bound on arguments, still need to worry about unnecessary +/// and improper variance: it is advisable to strive for invariance +/// first. The usability impact will be negligible, while the reduction +/// in the risk of unsoundness will be most welcome. +/// +/// ## Examples +/// +/// Suppose `SubType` is a subtype of `SuperType`, that is, +/// a value of type `SubType` can be used wherever +/// a value of type `SuperType` is expected. +/// Suppose also that `CoVar` is a generic type, which is covariant over `T` +/// (like many other types, including `PhantomData` and `Vec`). +/// +/// Then, by covariance, `CoVar` is a subtype of `CoVar`, +/// that is, a value of type `CoVar` can be used wherever +/// a value of type `CoVar` is expected. +/// +/// Then if `CoVar` relies on `TypeId::of::()` to uphold any invariants, +/// those invariants may be broken because a value of type `CoVar` can be created +/// without going through any of its methods, like so: +/// ``` +/// type SubType = fn(&()); +/// type SuperType = fn(&'static ()); +/// type CoVar = Vec; // imagine something more complicated +/// +/// let sub: CoVar = CoVar::new(); +/// // we have a `CoVar` instance without +/// // *ever* having called `CoVar::::new()`! +/// let fake_super: CoVar = sub; +/// ``` +/// +/// The following is an example program that tries to use `TypeId::of` to +/// implement a generic type `Unique` that guarantees unique instances for each `Unique`, +/// that is, and for each type `T` there can be at most one value of type `Unique` at any time. +/// +/// ``` +/// mod unique { +/// use std::any::TypeId; +/// use std::collections::BTreeSet; +/// use std::marker::PhantomData; +/// use std::sync::Mutex; +/// +/// static ID_SET: Mutex> = Mutex::new(BTreeSet::new()); +/// +/// // TypeId has only covariant uses, which makes Unique covariant over TypeAsId 🚨 +/// #[derive(Debug, PartialEq)] +/// pub struct Unique( +/// // private field prevents creation without `new` outside this module +/// PhantomData, +/// ); +/// +/// impl Unique { +/// pub fn new() -> Option { +/// let mut set = ID_SET.lock().unwrap(); +/// (set.insert(TypeId::of::())).then(|| Self(PhantomData)) +/// } +/// } +/// +/// impl Drop for Unique { +/// fn drop(&mut self) { +/// let mut set = ID_SET.lock().unwrap(); +/// (!set.remove(&TypeId::of::())).then(|| panic!("duplicity detected")); +/// } +/// } +/// } +/// +/// use unique::Unique; +/// +/// // `OtherRing` is a subtype of `TheOneRing`. Both are 'static, and thus have a TypeId. +/// type TheOneRing = fn(&'static ()); +/// type OtherRing = fn(&()); +/// +/// fn main() { +/// let the_one_ring: Unique = Unique::new().unwrap(); +/// assert_eq!(Unique::::new(), None); +/// +/// let other_ring: Unique = Unique::new().unwrap(); +/// // Use that `Unique` is a subtype of `Unique` 🚨 +/// let fake_one_ring: Unique = other_ring; +/// assert_eq!(fake_one_ring, the_one_ring); +/// +/// std::mem::forget(fake_one_ring); +/// } +/// ``` #[derive(Clone, Copy, Eq, PartialOrd, Ord)] #[stable(feature = "rust1", since = "1.0.0")] pub struct TypeId { @@ -627,8 +722,7 @@ impl PartialEq for TypeId { } impl TypeId { - /// Returns the `TypeId` of the type this generic function has been - /// instantiated with. + /// Returns the `TypeId` of the generic type parameter. /// /// # Examples ///