From 8b76cad0a7e4a7743d4dd44dd53f077f3d0b8924 Mon Sep 17 00:00:00 2001 From: Deadbeef Date: Sun, 16 Jan 2022 02:44:57 +0800 Subject: [PATCH] Add a minimal working `append_const_msg` argument --- compiler/rustc_span/src/symbol.rs | 1 + .../src/traits/error_reporting/mod.rs | 37 +++++++++++++++---- .../src/traits/on_unimplemented.rs | 21 +++++++++++ library/core/src/cmp.rs | 34 ++++++++++++++--- library/core/src/ops/arith.rs | 35 +++++++++++++++--- .../rfc-2632-const-trait-impl/assoc-type.rs | 2 +- .../assoc-type.stderr | 2 +- .../call-generic-method-nonconst.stderr | 2 +- 8 files changed, 112 insertions(+), 22 deletions(-) diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 52d52752b15..d99bdd3bdd5 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -321,6 +321,7 @@ and, and_then, any, + append_const_msg, arbitrary_enum_discriminant, arbitrary_self_types, arith_offset, diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs index ffc742dd307..213084cdcd6 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs @@ -310,13 +310,18 @@ fn report_selection_error( }) .unwrap_or_default(); - let OnUnimplementedNote { message, label, note, enclosing_scope } = - self.on_unimplemented_note(trait_ref, &obligation); + let OnUnimplementedNote { + message, + label, + note, + enclosing_scope, + append_const_msg, + } = self.on_unimplemented_note(trait_ref, &obligation); let have_alt_message = message.is_some() || label.is_some(); let is_try_conversion = self.is_try_conversion(span, trait_ref.def_id()); let is_unsize = { Some(trait_ref.def_id()) == self.tcx.lang_items().unsize_trait() }; - let (message, note) = if is_try_conversion { + let (message, note, append_const_msg) = if is_try_conversion { ( Some(format!( "`?` couldn't convert the error to `{}`", @@ -327,9 +332,10 @@ fn report_selection_error( conversion on the error value using the `From` trait" .to_owned(), ), + Some(None), ) } else { - (message, note) + (message, note, append_const_msg) }; let mut err = struct_span_err!( @@ -337,12 +343,27 @@ fn report_selection_error( span, E0277, "{}", - (!predicate_is_const).then(|| message).flatten().unwrap_or_else( - || format!( + message + .and_then(|cannot_do_this| { + match (predicate_is_const, append_const_msg) { + // do nothing if predicate is not const + (false, _) => Some(cannot_do_this), + // suggested using default post message + (true, Some(None)) => { + Some(format!("{cannot_do_this} in const contexts")) + } + // overriden post message + (true, Some(Some(post_message))) => { + Some(format!("{cannot_do_this}{post_message}")) + } + // fallback to generic message + (true, None) => None, + } + }) + .unwrap_or_else(|| format!( "the trait bound `{}` is not satisfied{}", trait_predicate, post_message, - ) - ) + )) ); if is_try_conversion { diff --git a/compiler/rustc_trait_selection/src/traits/on_unimplemented.rs b/compiler/rustc_trait_selection/src/traits/on_unimplemented.rs index 4840995275a..6b20476b955 100644 --- a/compiler/rustc_trait_selection/src/traits/on_unimplemented.rs +++ b/compiler/rustc_trait_selection/src/traits/on_unimplemented.rs @@ -19,6 +19,7 @@ pub struct OnUnimplementedDirective { pub label: Option, pub note: Option, pub enclosing_scope: Option, + pub append_const_msg: Option>, } #[derive(Default)] @@ -27,6 +28,11 @@ pub struct OnUnimplementedNote { pub label: Option, pub note: Option, pub enclosing_scope: Option, + /// Append a message for `~const Trait` errors. `None` means not requested and + /// should fallback to a generic message, `Some(None)` suggests using the default + /// appended message, `Some(Some(s))` suggests use the `s` message instead of the + /// default one.. + pub append_const_msg: Option>, } fn parse_error( @@ -89,6 +95,7 @@ fn parse( let mut note = None; let mut enclosing_scope = None; let mut subcommands = vec![]; + let mut append_const_msg = None; let parse_value = |value_str| { OnUnimplementedFormatString::try_parse(tcx, trait_def_id, value_str, span).map(Some) @@ -131,6 +138,14 @@ fn parse( } continue; } + } else if item.has_name(sym::append_const_msg) && append_const_msg.is_none() { + if let Some(msg) = item.value_str() { + append_const_msg = Some(Some(msg)); + continue; + } else if item.is_word() { + append_const_msg = Some(None); + continue; + } } // nothing found @@ -153,6 +168,7 @@ fn parse( label, note, enclosing_scope, + append_const_msg, }) } } @@ -183,6 +199,7 @@ pub fn of_item( )?), note: None, enclosing_scope: None, + append_const_msg: None, })) } else { return Err(ErrorReported); @@ -201,6 +218,7 @@ pub fn evaluate( let mut label = None; let mut note = None; let mut enclosing_scope = None; + let mut append_const_msg = None; info!("evaluate({:?}, trait_ref={:?}, options={:?})", self, trait_ref, options); for command in self.subcommands.iter().chain(Some(self)).rev() { @@ -235,6 +253,8 @@ pub fn evaluate( if let Some(ref enclosing_scope_) = command.enclosing_scope { enclosing_scope = Some(enclosing_scope_.clone()); } + + append_const_msg = command.append_const_msg.clone(); } let options: FxHashMap = @@ -244,6 +264,7 @@ pub fn evaluate( message: message.map(|m| m.format(tcx, trait_ref, &options)), note: note.map(|n| n.format(tcx, trait_ref, &options)), enclosing_scope: enclosing_scope.map(|e_s| e_s.format(tcx, trait_ref, &options)), + append_const_msg, } } } diff --git a/library/core/src/cmp.rs b/library/core/src/cmp.rs index f89cf812e97..1af352d542a 100644 --- a/library/core/src/cmp.rs +++ b/library/core/src/cmp.rs @@ -199,9 +199,20 @@ #[stable(feature = "rust1", since = "1.0.0")] #[doc(alias = "==")] #[doc(alias = "!=")] -#[rustc_on_unimplemented( - message = "can't compare `{Self}` with `{Rhs}`", - label = "no implementation for `{Self} == {Rhs}`" +#[cfg_attr( + bootstrap, + rustc_on_unimplemented( + message = "can't compare `{Self}` with `{Rhs}`", + label = "no implementation for `{Self} == {Rhs}`" + ) +)] +#[cfg_attr( + not(bootstrap), + rustc_on_unimplemented( + message = "can't compare `{Self}` with `{Rhs}`", + label = "no implementation for `{Self} == {Rhs}`", + append_const_msg, + ) )] #[rustc_diagnostic_item = "PartialEq"] pub trait PartialEq { @@ -1031,9 +1042,20 @@ fn partial_cmp(&self, other: &Ordering) -> Option { #[doc(alias = "<")] #[doc(alias = "<=")] #[doc(alias = ">=")] -#[rustc_on_unimplemented( - message = "can't compare `{Self}` with `{Rhs}`", - label = "no implementation for `{Self} < {Rhs}` and `{Self} > {Rhs}`" +#[cfg_attr( + bootstrap, + rustc_on_unimplemented( + message = "can't compare `{Self}` with `{Rhs}`", + label = "no implementation for `{Self} < {Rhs}` and `{Self} > {Rhs}`", + ) +)] +#[cfg_attr( + not(bootstrap), + rustc_on_unimplemented( + message = "can't compare `{Self}` with `{Rhs}`", + label = "no implementation for `{Self} < {Rhs}` and `{Self} > {Rhs}`", + append_const_msg, + ) )] #[rustc_diagnostic_item = "PartialOrd"] pub trait PartialOrd: PartialEq { diff --git a/library/core/src/ops/arith.rs b/library/core/src/ops/arith.rs index e9547429389..e367be8c167 100644 --- a/library/core/src/ops/arith.rs +++ b/library/core/src/ops/arith.rs @@ -65,11 +65,36 @@ /// ``` #[lang = "add"] #[stable(feature = "rust1", since = "1.0.0")] -#[rustc_on_unimplemented( - on(all(_Self = "{integer}", Rhs = "{float}"), message = "cannot add a float to an integer",), - on(all(_Self = "{float}", Rhs = "{integer}"), message = "cannot add an integer to a float",), - message = "cannot add `{Rhs}` to `{Self}`", - label = "no implementation for `{Self} + {Rhs}`" +#[cfg_attr( + bootstrap, + rustc_on_unimplemented( + on( + all(_Self = "{integer}", Rhs = "{float}"), + message = "cannot add a float to an integer", + ), + on( + all(_Self = "{float}", Rhs = "{integer}"), + message = "cannot add an integer to a float", + ), + message = "cannot add `{Rhs}` to `{Self}`", + label = "no implementation for `{Self} + {Rhs}`" + ) +)] +#[cfg_attr( + not(bootstrap), + rustc_on_unimplemented( + on( + all(_Self = "{integer}", Rhs = "{float}"), + message = "cannot add a float to an integer", + ), + on( + all(_Self = "{float}", Rhs = "{integer}"), + message = "cannot add an integer to a float", + ), + message = "cannot add `{Rhs}` to `{Self}`", + label = "no implementation for `{Self} + {Rhs}`", + append_const_msg, + ) )] #[doc(alias = "+")] pub trait Add { diff --git a/src/test/ui/rfc-2632-const-trait-impl/assoc-type.rs b/src/test/ui/rfc-2632-const-trait-impl/assoc-type.rs index 2d6e7b39f57..99eacaa837f 100644 --- a/src/test/ui/rfc-2632-const-trait-impl/assoc-type.rs +++ b/src/test/ui/rfc-2632-const-trait-impl/assoc-type.rs @@ -16,7 +16,7 @@ trait Foo { impl const Foo for NonConstAdd { type Bar = NonConstAdd; - //~^ ERROR: the trait bound `NonConstAdd: ~const Add` is not satisfied + //~^ ERROR: cannot add `NonConstAdd` to `NonConstAdd` in const contexts } trait Baz { diff --git a/src/test/ui/rfc-2632-const-trait-impl/assoc-type.stderr b/src/test/ui/rfc-2632-const-trait-impl/assoc-type.stderr index 05fce15f10b..429b9f3364b 100644 --- a/src/test/ui/rfc-2632-const-trait-impl/assoc-type.stderr +++ b/src/test/ui/rfc-2632-const-trait-impl/assoc-type.stderr @@ -1,4 +1,4 @@ -error[E0277]: the trait bound `NonConstAdd: ~const Add` is not satisfied +error[E0277]: cannot add `NonConstAdd` to `NonConstAdd` in const contexts --> $DIR/assoc-type.rs:18:16 | LL | type Bar = NonConstAdd; diff --git a/src/test/ui/rfc-2632-const-trait-impl/call-generic-method-nonconst.stderr b/src/test/ui/rfc-2632-const-trait-impl/call-generic-method-nonconst.stderr index cf44b2a740a..13cffaba91a 100644 --- a/src/test/ui/rfc-2632-const-trait-impl/call-generic-method-nonconst.stderr +++ b/src/test/ui/rfc-2632-const-trait-impl/call-generic-method-nonconst.stderr @@ -1,4 +1,4 @@ -error[E0277]: the trait bound `S: ~const PartialEq` is not satisfied +error[E0277]: can't compare `S` with `S` in const contexts --> $DIR/call-generic-method-nonconst.rs:19:34 | LL | pub const EQ: bool = equals_self(&S);