From 8047f8fb519bb5d9bb3c29652bb77b30369de7b5 Mon Sep 17 00:00:00 2001 From: CAD97 Date: Tue, 12 Apr 2022 02:43:35 -0500 Subject: [PATCH 1/7] Add feature(str_from_utf16_endian) --- library/alloc/src/string.rs | 150 ++++++++++++++++++++++++++++++++++++ 1 file changed, 150 insertions(+) diff --git a/library/alloc/src/string.rs b/library/alloc/src/string.rs index ed43244ebda19..e29f5fb70ab57 100644 --- a/library/alloc/src/string.rs +++ b/library/alloc/src/string.rs @@ -714,6 +714,156 @@ impl String { .collect() } + /// Decode a UTF-16LEā€“encoded vector `v` into a `String`, returning [`Err`] + /// if `v` contains any invalid data. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(str_from_utf16_endian)] + /// // š¯„˛music + /// let v = &[0x34, 0xD8, 0x1E, 0xDD, 0x6d, 0x00, 0x75, 0x00, + /// 0x73, 0x00, 0x69, 0x00, 0x63, 0x00]; + /// assert_eq!(String::from("š¯„˛music"), + /// String::from_utf16le(v).unwrap()); + /// + /// // š¯„˛muic + /// let v = &[0x34, 0xD8, 0x1E, 0xDD, 0x6d, 0x00, 0x75, 0x00, + /// 0x00, 0xD8, 0x69, 0x00, 0x63, 0x00]; + /// assert!(String::from_utf16le(v).is_err()); + /// ``` + #[cfg(not(no_global_oom_handling))] + #[unstable(feature = "str_from_utf16_endian", issue = "none", reason = "recently added")] + pub fn from_utf16le(v: &[u8]) -> Result { + if v.len() % 2 != 0 { + return Err(FromUtf16Error(())); + } + match (cfg!(target_endian = "little"), unsafe { v.align_to::() }) { + (true, (&[], v, &[])) => Self::from_utf16(v), + _ => decode_utf16(v.array_chunks::<2>().copied().map(u16::from_le_bytes)) + .collect::>() + .map_err(|_| FromUtf16Error(())), + } + } + + /// Decode a UTF-16LEā€“encoded slice `v` into a `String`, replacing + /// invalid data with [the replacement character (`U+FFFD`)][U+FFFD]. + /// + /// Unlike [`from_utf8_lossy`] which returns a [`Cow<'a, str>`], + /// `from_utf16le_lossy` returns a `String` since the UTF-16 to UTF-8 + /// conversion requires a memory allocation. + /// + /// [`from_utf8_lossy`]: String::from_utf8_lossy + /// [`Cow<'a, str>`]: crate::borrow::Cow "borrow::Cow" + /// [U+FFFD]: core::char::REPLACEMENT_CHARACTER + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(str_from_utf16_endian)] + /// // š¯„˛music + /// let v = &[0x34, 0xD8, 0x1E, 0xDD, 0x6d, 0x00, 0x75, 0x00, + /// 0x73, 0x00, 0x1E, 0xDD, 0x69, 0x00, 0x63, 0x00, + /// 0x34, 0xD8]; + /// + /// assert_eq!(String::from("š¯„˛mus\u{FFFD}ic\u{FFFD}"), + /// String::from_utf16le_lossy(v)); + /// ``` + #[cfg(not(no_global_oom_handling))] + #[unstable(feature = "str_from_utf16_endian", issue = "none", reason = "recently added")] + pub fn from_utf16le_lossy(v: &[u8]) -> String { + match (cfg!(target_endian = "little"), unsafe { v.align_to::() }) { + (true, (&[], v, &[])) => Self::from_utf16_lossy(v), + (true, (&[], v, &[_remainder])) => Self::from_utf16_lossy(v) + "\u{FFFD}", + _ => { + let mut iter = v.array_chunks::<2>(); + let string = decode_utf16(iter.by_ref().copied().map(u16::from_le_bytes)) + .map(|r| r.unwrap_or(REPLACEMENT_CHARACTER)) + .collect(); + if iter.remainder().is_empty() { string } else { string + "\u{FFFD}" } + } + } + } + + /// Decode a UTF-16BEā€“encoded vector `v` into a `String`, returning [`Err`] + /// if `v` contains any invalid data. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(str_from_utf16_endian)] + /// // š¯„˛music + /// let v = &[0xD8, 0x34, 0xDD, 0x1E, 0x00, 0x6d, 0x00, 0x75, + /// 0x00, 0x73, 0x00, 0x69, 0x00, 0x63]; + /// assert_eq!(String::from("š¯„˛music"), + /// String::from_utf16be(v).unwrap()); + /// + /// // š¯„˛muic + /// let v = &[0xD8, 0x34, 0xDD, 0x1E, 0x00, 0x6d, 0x00, 0x75, + /// 0xD8, 0x00, 0x00, 0x69, 0x00, 0x63]; + /// assert!(String::from_utf16be(v).is_err()); + /// ``` + #[cfg(not(no_global_oom_handling))] + #[unstable(feature = "str_from_utf16_endian", issue = "none", reason = "recently added")] + pub fn from_utf16be(v: &[u8]) -> Result { + if v.len() % 2 != 0 { + return Err(FromUtf16Error(())); + } + match (cfg!(target_endian = "big"), unsafe { v.align_to::() }) { + (true, (&[], v, &[])) => Self::from_utf16(v), + _ => decode_utf16(v.array_chunks::<2>().copied().map(u16::from_be_bytes)) + .collect::>() + .map_err(|_| FromUtf16Error(())), + } + } + + /// Decode a UTF-16BEā€“encoded slice `v` into a `String`, replacing + /// invalid data with [the replacement character (`U+FFFD`)][U+FFFD]. + /// + /// Unlike [`from_utf8_lossy`] which returns a [`Cow<'a, str>`], + /// `from_utf16le_lossy` returns a `String` since the UTF-16 to UTF-8 + /// conversion requires a memory allocation. + /// + /// [`from_utf8_lossy`]: String::from_utf8_lossy + /// [`Cow<'a, str>`]: crate::borrow::Cow "borrow::Cow" + /// [U+FFFD]: core::char::REPLACEMENT_CHARACTER + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(str_from_utf16_endian)] + /// // š¯„˛music + /// let v = &[0xD8, 0x34, 0xDD, 0x1E, 0x00, 0x6d, 0x00, 0x75, + /// 0x00, 0x73, 0xDD, 0x1E, 0x00, 0x69, 0x00, 0x63, + /// 0xD8, 0x34]; + /// + /// assert_eq!(String::from("š¯„˛mus\u{FFFD}ic\u{FFFD}"), + /// String::from_utf16be_lossy(v)); + /// ``` + #[cfg(not(no_global_oom_handling))] + #[unstable(feature = "str_from_utf16_endian", issue = "none", reason = "recently added")] + pub fn from_utf16be_lossy(v: &[u8]) -> String { + match (cfg!(target_endian = "big"), unsafe { v.align_to::() }) { + (true, (&[], v, &[])) => Self::from_utf16_lossy(v), + (true, (&[], v, &[_remainder])) => Self::from_utf16_lossy(v) + "\u{FFFD}", + _ => { + let mut iter = v.array_chunks::<2>(); + let string = decode_utf16(iter.by_ref().copied().map(u16::from_be_bytes)) + .map(|r| r.unwrap_or(REPLACEMENT_CHARACTER)) + .collect(); + if iter.remainder().is_empty() { string } else { string + "\u{FFFD}" } + } + } + } + /// Decomposes a `String` into its raw components. /// /// Returns the raw pointer to the underlying data, the length of From 3d448bd067234283c32792bf2a96d63d65fb5e91 Mon Sep 17 00:00:00 2001 From: Christopher Durham Date: Thu, 28 Sep 2023 23:18:55 -0400 Subject: [PATCH 2/7] style nits Co-authored-by: David Tolnay --- library/alloc/src/string.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/library/alloc/src/string.rs b/library/alloc/src/string.rs index e29f5fb70ab57..9a7d8213f4279 100644 --- a/library/alloc/src/string.rs +++ b/library/alloc/src/string.rs @@ -741,7 +741,7 @@ impl String { return Err(FromUtf16Error(())); } match (cfg!(target_endian = "little"), unsafe { v.align_to::() }) { - (true, (&[], v, &[])) => Self::from_utf16(v), + (true, ([], v, [])) => Self::from_utf16(v), _ => decode_utf16(v.array_chunks::<2>().copied().map(u16::from_le_bytes)) .collect::>() .map_err(|_| FromUtf16Error(())), @@ -777,8 +777,8 @@ impl String { #[unstable(feature = "str_from_utf16_endian", issue = "none", reason = "recently added")] pub fn from_utf16le_lossy(v: &[u8]) -> String { match (cfg!(target_endian = "little"), unsafe { v.align_to::() }) { - (true, (&[], v, &[])) => Self::from_utf16_lossy(v), - (true, (&[], v, &[_remainder])) => Self::from_utf16_lossy(v) + "\u{FFFD}", + (true, ([], v, [])) => Self::from_utf16_lossy(v), + (true, ([], v, [_remainder])) => Self::from_utf16_lossy(v) + "\u{FFFD}", _ => { let mut iter = v.array_chunks::<2>(); let string = decode_utf16(iter.by_ref().copied().map(u16::from_le_bytes)) @@ -816,7 +816,7 @@ impl String { return Err(FromUtf16Error(())); } match (cfg!(target_endian = "big"), unsafe { v.align_to::() }) { - (true, (&[], v, &[])) => Self::from_utf16(v), + (true, ([], v, [])) => Self::from_utf16(v), _ => decode_utf16(v.array_chunks::<2>().copied().map(u16::from_be_bytes)) .collect::>() .map_err(|_| FromUtf16Error(())), @@ -852,8 +852,8 @@ impl String { #[unstable(feature = "str_from_utf16_endian", issue = "none", reason = "recently added")] pub fn from_utf16be_lossy(v: &[u8]) -> String { match (cfg!(target_endian = "big"), unsafe { v.align_to::() }) { - (true, (&[], v, &[])) => Self::from_utf16_lossy(v), - (true, (&[], v, &[_remainder])) => Self::from_utf16_lossy(v) + "\u{FFFD}", + (true, ([], v, [])) => Self::from_utf16_lossy(v), + (true, ([], v, [_remainder])) => Self::from_utf16_lossy(v) + "\u{FFFD}", _ => { let mut iter = v.array_chunks::<2>(); let string = decode_utf16(iter.by_ref().copied().map(u16::from_be_bytes)) From 1efea3138554e37874c098e497f59e8f955d2d3a Mon Sep 17 00:00:00 2001 From: Christopher Durham Date: Thu, 28 Sep 2023 23:44:39 -0400 Subject: [PATCH 3/7] add str_from_utf16_endian tracking issue --- library/alloc/src/string.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/library/alloc/src/string.rs b/library/alloc/src/string.rs index 9a7d8213f4279..4e4c358200e35 100644 --- a/library/alloc/src/string.rs +++ b/library/alloc/src/string.rs @@ -735,7 +735,7 @@ impl String { /// assert!(String::from_utf16le(v).is_err()); /// ``` #[cfg(not(no_global_oom_handling))] - #[unstable(feature = "str_from_utf16_endian", issue = "none", reason = "recently added")] + #[unstable(feature = "str_from_utf16_endian", issue = "116258")] pub fn from_utf16le(v: &[u8]) -> Result { if v.len() % 2 != 0 { return Err(FromUtf16Error(())); @@ -774,7 +774,7 @@ impl String { /// String::from_utf16le_lossy(v)); /// ``` #[cfg(not(no_global_oom_handling))] - #[unstable(feature = "str_from_utf16_endian", issue = "none", reason = "recently added")] + #[unstable(feature = "str_from_utf16_endian", issue = "116258")] pub fn from_utf16le_lossy(v: &[u8]) -> String { match (cfg!(target_endian = "little"), unsafe { v.align_to::() }) { (true, ([], v, [])) => Self::from_utf16_lossy(v), @@ -810,7 +810,7 @@ impl String { /// assert!(String::from_utf16be(v).is_err()); /// ``` #[cfg(not(no_global_oom_handling))] - #[unstable(feature = "str_from_utf16_endian", issue = "none", reason = "recently added")] + #[unstable(feature = "str_from_utf16_endian", issue = "116258")] pub fn from_utf16be(v: &[u8]) -> Result { if v.len() % 2 != 0 { return Err(FromUtf16Error(())); @@ -849,7 +849,7 @@ impl String { /// String::from_utf16be_lossy(v)); /// ``` #[cfg(not(no_global_oom_handling))] - #[unstable(feature = "str_from_utf16_endian", issue = "none", reason = "recently added")] + #[unstable(feature = "str_from_utf16_endian", issue = "116258")] pub fn from_utf16be_lossy(v: &[u8]) -> String { match (cfg!(target_endian = "big"), unsafe { v.align_to::() }) { (true, ([], v, [])) => Self::from_utf16_lossy(v), From 5facc32e22e8843a8c276305fff4ec84d718e1c0 Mon Sep 17 00:00:00 2001 From: Christopher Durham Date: Fri, 29 Sep 2023 00:04:57 -0400 Subject: [PATCH 4/7] fix char imports --- library/alloc/src/string.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/library/alloc/src/string.rs b/library/alloc/src/string.rs index 4e4c358200e35..844441ba3a764 100644 --- a/library/alloc/src/string.rs +++ b/library/alloc/src/string.rs @@ -742,7 +742,7 @@ impl String { } match (cfg!(target_endian = "little"), unsafe { v.align_to::() }) { (true, ([], v, [])) => Self::from_utf16(v), - _ => decode_utf16(v.array_chunks::<2>().copied().map(u16::from_le_bytes)) + _ => char::decode_utf16(v.array_chunks::<2>().copied().map(u16::from_le_bytes)) .collect::>() .map_err(|_| FromUtf16Error(())), } @@ -781,8 +781,8 @@ impl String { (true, ([], v, [_remainder])) => Self::from_utf16_lossy(v) + "\u{FFFD}", _ => { let mut iter = v.array_chunks::<2>(); - let string = decode_utf16(iter.by_ref().copied().map(u16::from_le_bytes)) - .map(|r| r.unwrap_or(REPLACEMENT_CHARACTER)) + let string = char::decode_utf16(iter.by_ref().copied().map(u16::from_le_bytes)) + .map(|r| r.unwrap_or(char::REPLACEMENT_CHARACTER)) .collect(); if iter.remainder().is_empty() { string } else { string + "\u{FFFD}" } } @@ -817,7 +817,7 @@ impl String { } match (cfg!(target_endian = "big"), unsafe { v.align_to::() }) { (true, ([], v, [])) => Self::from_utf16(v), - _ => decode_utf16(v.array_chunks::<2>().copied().map(u16::from_be_bytes)) + _ => char::decode_utf16(v.array_chunks::<2>().copied().map(u16::from_be_bytes)) .collect::>() .map_err(|_| FromUtf16Error(())), } @@ -856,8 +856,8 @@ impl String { (true, ([], v, [_remainder])) => Self::from_utf16_lossy(v) + "\u{FFFD}", _ => { let mut iter = v.array_chunks::<2>(); - let string = decode_utf16(iter.by_ref().copied().map(u16::from_be_bytes)) - .map(|r| r.unwrap_or(REPLACEMENT_CHARACTER)) + let string = char::decode_utf16(iter.by_ref().copied().map(u16::from_be_bytes)) + .map(|r| r.unwrap_or(char::REPLACEMENT_CHARACTER)) .collect(); if iter.remainder().is_empty() { string } else { string + "\u{FFFD}" } } From 710c073acb8f3d2187b5e8d71e4662c3c7786f82 Mon Sep 17 00:00:00 2001 From: Ali MJ Al-Nasrawy Date: Sun, 8 Oct 2023 09:14:12 +0000 Subject: [PATCH 5/7] delay a bug when encountering an ambiguity in MIR typeck --- .../src/traits/query/type_op/mod.rs | 16 +++++++++++---- ...equality_in_canonical_query.current.stderr | 20 +++++++++++++++++++ .../rpit_tait_equality_in_canonical_query.rs | 9 ++++++++- 3 files changed, 40 insertions(+), 5 deletions(-) create mode 100644 tests/ui/type-alias-impl-trait/rpit_tait_equality_in_canonical_query.current.stderr diff --git a/compiler/rustc_trait_selection/src/traits/query/type_op/mod.rs b/compiler/rustc_trait_selection/src/traits/query/type_op/mod.rs index 9d7933e23a8b2..a5ccf62608edb 100644 --- a/compiler/rustc_trait_selection/src/traits/query/type_op/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/query/type_op/mod.rs @@ -157,10 +157,18 @@ where } let mut region_constraints = QueryRegionConstraints::default(); - let (output, error_info, mut obligations, _) = - Q::fully_perform_into(self, infcx, &mut region_constraints).map_err(|_| { - infcx.tcx.sess.delay_span_bug(span, format!("error performing {self:?}")) - })?; + let (output, error_info, mut obligations) = + Q::fully_perform_into(self, infcx, &mut region_constraints) + .map_err(|_| { + infcx.tcx.sess.delay_span_bug(span, format!("error performing {self:?}")) + }) + .and_then(|(output, error_info, obligations, certainty)| match certainty { + Certainty::Proven => Ok((output, error_info, obligations)), + Certainty::Ambiguous => Err(infcx + .tcx + .sess + .delay_span_bug(span, format!("ambiguity performing {self:?}"))), + })?; // Typically, instantiating NLL query results does not // create obligations. However, in some cases there diff --git a/tests/ui/type-alias-impl-trait/rpit_tait_equality_in_canonical_query.current.stderr b/tests/ui/type-alias-impl-trait/rpit_tait_equality_in_canonical_query.current.stderr new file mode 100644 index 0000000000000..4b09a9e743b41 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/rpit_tait_equality_in_canonical_query.current.stderr @@ -0,0 +1,20 @@ +error: internal compiler error: no errors encountered even though `delay_span_bug` issued + +error: internal compiler error: ambiguity performing ParamEnvAnd { param_env: ParamEnv { caller_bounds: [], reveal: UserFacing }, value: ProvePredicate { predicate: Binder { value: ProjectionPredicate(AliasTy { args: [FnDef(DefId(get_rpit), []), ()], def_id: DefId(ops::function::FnOnce::Output) }, Term::Ty(Alias(Opaque, AliasTy { args: [], def_id: DefId(Opaque::{opaque#0}) }))), bound_vars: [] } } } + --> $DIR/rpit_tait_equality_in_canonical_query.rs:28:5 + | +LL | query(get_rpit); + | ^^^^^^^^^^^^^^^ + | + --> $DIR/rpit_tait_equality_in_canonical_query.rs:28:5 + | +LL | query(get_rpit); + | ^^^^^^^^^^^^^^^ + + + + +query stack during panic: +end of query stack +error: aborting due to 2 previous errors + diff --git a/tests/ui/type-alias-impl-trait/rpit_tait_equality_in_canonical_query.rs b/tests/ui/type-alias-impl-trait/rpit_tait_equality_in_canonical_query.rs index eefe333da4511..8dccd2ed46f8a 100644 --- a/tests/ui/type-alias-impl-trait/rpit_tait_equality_in_canonical_query.rs +++ b/tests/ui/type-alias-impl-trait/rpit_tait_equality_in_canonical_query.rs @@ -7,7 +7,14 @@ // revisions: current next //[next] compile-flags: -Ztrait-solver=next -// check-pass +//[next] check-pass + +//[current] known-bug: #108498 +//[current] failure-status: 101 +//[current] normalize-stderr-test: "DefId\(.*?\]::" -> "DefId(" +//[current] normalize-stderr-test: "(?m)^note: .*\n" -> "" +//[current] normalize-stderr-test: "(?m)^ *\d+: .*\n" -> "" +//[current] normalize-stderr-test: "(?m)^ *at .*\n" -> "" #![feature(type_alias_impl_trait)] From b61a6d59e4097f2677484f043553a9f82f9c77db Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Mi=C4=85sko?= Date: Tue, 10 Oct 2023 00:00:00 +0000 Subject: [PATCH 6/7] Remove unused dominator iterator --- .../src/graph/dominators/mod.rs | 27 +------------------ 1 file changed, 1 insertion(+), 26 deletions(-) diff --git a/compiler/rustc_data_structures/src/graph/dominators/mod.rs b/compiler/rustc_data_structures/src/graph/dominators/mod.rs index 9685ad24a9767..5dd414cfd41fa 100644 --- a/compiler/rustc_data_structures/src/graph/dominators/mod.rs +++ b/compiler/rustc_data_structures/src/graph/dominators/mod.rs @@ -349,7 +349,7 @@ struct Inner { post_order_rank: IndexVec, // Even though we track only the immediate dominator of each node, it's // possible to get its full list of dominators by looking up the dominator - // of each dominator. (See the `impl Iterator for Iter` definition). + // of each dominator. immediate_dominators: IndexVec>, time: IndexVec, } @@ -377,13 +377,6 @@ impl Dominators { } } - /// Provides an iterator over each dominator up the CFG, for the given Node. - /// See the `impl Iterator for Iter` definition to understand how this works. - pub fn dominators(&self, node: Node) -> Iter<'_, Node> { - assert!(self.is_reachable(node), "node {node:?} is not reachable"); - Iter { dom_tree: self, node: Some(node) } - } - /// Provide deterministic ordering of nodes such that, if any two nodes have a dominator /// relationship, the dominator will always precede the dominated. (The relative ordering /// of two unrelated nodes will also be consistent, but otherwise the order has no @@ -413,24 +406,6 @@ impl Dominators { } } -pub struct Iter<'dom, Node: Idx> { - dom_tree: &'dom Dominators, - node: Option, -} - -impl<'dom, Node: Idx> Iterator for Iter<'dom, Node> { - type Item = Node; - - fn next(&mut self) -> Option { - if let Some(node) = self.node { - self.node = self.dom_tree.immediate_dominator(node); - Some(node) - } else { - None - } - } -} - /// Describes the number of vertices discovered at the time when processing of a particular vertex /// started and when it finished. Both values are zero for unreachable vertices. #[derive(Copy, Clone, Default, Debug)] From ba02a9909b7e53245abe98981420ed721610b1ef Mon Sep 17 00:00:00 2001 From: mejrs <59372212+mejrs@users.noreply.github.com> Date: Wed, 11 Oct 2023 00:02:06 +0200 Subject: [PATCH 7/7] Document `diagnostic_namespace` feature --- .../language-features/diagnostic-namespace.md | 84 +++++++++++++++++++ 1 file changed, 84 insertions(+) create mode 100644 src/doc/unstable-book/src/language-features/diagnostic-namespace.md diff --git a/src/doc/unstable-book/src/language-features/diagnostic-namespace.md b/src/doc/unstable-book/src/language-features/diagnostic-namespace.md new file mode 100644 index 0000000000000..7c46811a27ab8 --- /dev/null +++ b/src/doc/unstable-book/src/language-features/diagnostic-namespace.md @@ -0,0 +1,84 @@ +# `diagnostic_namespace` + +The tracking issue for this feature is: [#111996] + +[#111996]: https://github.com/rust-lang/rust/issues/111996 + +------------------------ + +The `diagnostic_namespace` feature permits customization of compilation errors. + +## diagnostic::on_unimplemented + +With [#114452] support for `diagnostic::on_unimplemented` was added. + +When used on a trait declaration, the following options are available: + +* `message` to customize the primary error message +* `note` to add a customized note message to an error message +* `label` to customize the label part of the error message + +The attribute will hint to the compiler to use these in error messages: +```rust +// some library +#![feature(diagnostic_namespace)] + +#[diagnostic::on_unimplemented( + message = "cannot insert element", + label = "cannot be put into a table", + note = "see for more information about the Table api" +)] +pub trait Element { + // ... +} +``` + +```rust,compile_fail,E0277 +# #![feature(diagnostic_namespace)] +# +# #[diagnostic::on_unimplemented( +# message = "cannot insert element", +# label = "cannot be put into a table", +# note = "see for more information about the Table api" +# )] +# pub trait Element { +# // ... +# } +# struct Table; +# impl Table { +# fn insert(&self, element: T) { +# // .. +# } +# } +# fn main() { +# let table = Table; +# let element = (); +// user code +table.insert(element); +# } +``` + +```text +error[E0277]: cannot insert element + --> src/main.rs:24:18 + | +24 | table.insert(element); + | ------ ^^^^^^^ cannot be put into a table + | | + | required by a bound introduced by this call + | + = help: the trait `Element` is not implemented for `` + = note: see for more information about the Table api +note: required by a bound in `Table::insert` + --> src/main.rs:15:18 + | +15 | fn insert(&self, element: T) { + | ^^^^^^^ required by this bound in `Table::insert` + +For more information about this error, try `rustc --explain E0277`. +``` + +See [RFC 3368] for more information. + +[#114452]: https://github.com/rust-lang/rust/pull/114452 +[RFC 3368]: https://github.com/rust-lang/rfcs/blob/master/text/3368-diagnostic-attribute-namespace.md