1
Fork 0

Add a minimal working append_const_msg argument

This commit is contained in:
Deadbeef 2022-01-16 02:44:57 +08:00
parent fdf7d01088
commit 8b76cad0a7
No known key found for this signature in database
GPG key ID: 6D017A96D8E6C2F9
8 changed files with 112 additions and 22 deletions

View file

@ -321,6 +321,7 @@ symbols! {
and, and,
and_then, and_then,
any, any,
append_const_msg,
arbitrary_enum_discriminant, arbitrary_enum_discriminant,
arbitrary_self_types, arbitrary_self_types,
arith_offset, arith_offset,

View file

@ -310,13 +310,18 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
}) })
.unwrap_or_default(); .unwrap_or_default();
let OnUnimplementedNote { message, label, note, enclosing_scope } = let OnUnimplementedNote {
self.on_unimplemented_note(trait_ref, &obligation); 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 have_alt_message = message.is_some() || label.is_some();
let is_try_conversion = self.is_try_conversion(span, trait_ref.def_id()); let is_try_conversion = self.is_try_conversion(span, trait_ref.def_id());
let is_unsize = let is_unsize =
{ Some(trait_ref.def_id()) == self.tcx.lang_items().unsize_trait() }; { 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!( Some(format!(
"`?` couldn't convert the error to `{}`", "`?` couldn't convert the error to `{}`",
@ -327,9 +332,10 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
conversion on the error value using the `From` trait" conversion on the error value using the `From` trait"
.to_owned(), .to_owned(),
), ),
Some(None),
) )
} else { } else {
(message, note) (message, note, append_const_msg)
}; };
let mut err = struct_span_err!( let mut err = struct_span_err!(
@ -337,12 +343,27 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
span, span,
E0277, E0277,
"{}", "{}",
(!predicate_is_const).then(|| message).flatten().unwrap_or_else( message
|| format!( .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{}", "the trait bound `{}` is not satisfied{}",
trait_predicate, post_message, trait_predicate, post_message,
) ))
)
); );
if is_try_conversion { if is_try_conversion {

View file

@ -19,6 +19,7 @@ pub struct OnUnimplementedDirective {
pub label: Option<OnUnimplementedFormatString>, pub label: Option<OnUnimplementedFormatString>,
pub note: Option<OnUnimplementedFormatString>, pub note: Option<OnUnimplementedFormatString>,
pub enclosing_scope: Option<OnUnimplementedFormatString>, pub enclosing_scope: Option<OnUnimplementedFormatString>,
pub append_const_msg: Option<Option<Symbol>>,
} }
#[derive(Default)] #[derive(Default)]
@ -27,6 +28,11 @@ pub struct OnUnimplementedNote {
pub label: Option<String>, pub label: Option<String>,
pub note: Option<String>, pub note: Option<String>,
pub enclosing_scope: Option<String>, pub enclosing_scope: Option<String>,
/// 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<Option<Symbol>>,
} }
fn parse_error( fn parse_error(
@ -89,6 +95,7 @@ impl<'tcx> OnUnimplementedDirective {
let mut note = None; let mut note = None;
let mut enclosing_scope = None; let mut enclosing_scope = None;
let mut subcommands = vec![]; let mut subcommands = vec![];
let mut append_const_msg = None;
let parse_value = |value_str| { let parse_value = |value_str| {
OnUnimplementedFormatString::try_parse(tcx, trait_def_id, value_str, span).map(Some) OnUnimplementedFormatString::try_parse(tcx, trait_def_id, value_str, span).map(Some)
@ -131,6 +138,14 @@ impl<'tcx> OnUnimplementedDirective {
} }
continue; 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 // nothing found
@ -153,6 +168,7 @@ impl<'tcx> OnUnimplementedDirective {
label, label,
note, note,
enclosing_scope, enclosing_scope,
append_const_msg,
}) })
} }
} }
@ -183,6 +199,7 @@ impl<'tcx> OnUnimplementedDirective {
)?), )?),
note: None, note: None,
enclosing_scope: None, enclosing_scope: None,
append_const_msg: None,
})) }))
} else { } else {
return Err(ErrorReported); return Err(ErrorReported);
@ -201,6 +218,7 @@ impl<'tcx> OnUnimplementedDirective {
let mut label = None; let mut label = None;
let mut note = None; let mut note = None;
let mut enclosing_scope = None; let mut enclosing_scope = None;
let mut append_const_msg = None;
info!("evaluate({:?}, trait_ref={:?}, options={:?})", self, trait_ref, options); info!("evaluate({:?}, trait_ref={:?}, options={:?})", self, trait_ref, options);
for command in self.subcommands.iter().chain(Some(self)).rev() { for command in self.subcommands.iter().chain(Some(self)).rev() {
@ -235,6 +253,8 @@ impl<'tcx> OnUnimplementedDirective {
if let Some(ref enclosing_scope_) = command.enclosing_scope { if let Some(ref enclosing_scope_) = command.enclosing_scope {
enclosing_scope = Some(enclosing_scope_.clone()); enclosing_scope = Some(enclosing_scope_.clone());
} }
append_const_msg = command.append_const_msg.clone();
} }
let options: FxHashMap<Symbol, String> = let options: FxHashMap<Symbol, String> =
@ -244,6 +264,7 @@ impl<'tcx> OnUnimplementedDirective {
message: message.map(|m| m.format(tcx, trait_ref, &options)), message: message.map(|m| m.format(tcx, trait_ref, &options)),
note: note.map(|n| n.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)), enclosing_scope: enclosing_scope.map(|e_s| e_s.format(tcx, trait_ref, &options)),
append_const_msg,
} }
} }
} }

View file

@ -199,9 +199,20 @@ use self::Ordering::*;
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
#[doc(alias = "==")] #[doc(alias = "==")]
#[doc(alias = "!=")] #[doc(alias = "!=")]
#[rustc_on_unimplemented( #[cfg_attr(
bootstrap,
rustc_on_unimplemented(
message = "can't compare `{Self}` with `{Rhs}`", message = "can't compare `{Self}` with `{Rhs}`",
label = "no implementation for `{Self} == {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"] #[rustc_diagnostic_item = "PartialEq"]
pub trait PartialEq<Rhs: ?Sized = Self> { pub trait PartialEq<Rhs: ?Sized = Self> {
@ -1031,9 +1042,20 @@ impl PartialOrd for Ordering {
#[doc(alias = "<")] #[doc(alias = "<")]
#[doc(alias = "<=")] #[doc(alias = "<=")]
#[doc(alias = ">=")] #[doc(alias = ">=")]
#[rustc_on_unimplemented( #[cfg_attr(
bootstrap,
rustc_on_unimplemented(
message = "can't compare `{Self}` with `{Rhs}`", message = "can't compare `{Self}` with `{Rhs}`",
label = "no implementation for `{Self} < {Rhs}` and `{Self} > {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"] #[rustc_diagnostic_item = "PartialOrd"]
pub trait PartialOrd<Rhs: ?Sized = Self>: PartialEq<Rhs> { pub trait PartialOrd<Rhs: ?Sized = Self>: PartialEq<Rhs> {

View file

@ -65,11 +65,36 @@
/// ``` /// ```
#[lang = "add"] #[lang = "add"]
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
#[rustc_on_unimplemented( #[cfg_attr(
on(all(_Self = "{integer}", Rhs = "{float}"), message = "cannot add a float to an integer",), bootstrap,
on(all(_Self = "{float}", Rhs = "{integer}"), message = "cannot add an integer to a float",), 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}`", message = "cannot add `{Rhs}` to `{Self}`",
label = "no implementation for `{Self} + {Rhs}`" 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 = "+")] #[doc(alias = "+")]
pub trait Add<Rhs = Self> { pub trait Add<Rhs = Self> {

View file

@ -16,7 +16,7 @@ trait Foo {
impl const Foo for NonConstAdd { impl const Foo for NonConstAdd {
type Bar = 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 { trait Baz {

View file

@ -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 --> $DIR/assoc-type.rs:18:16
| |
LL | type Bar = NonConstAdd; LL | type Bar = NonConstAdd;

View file

@ -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 --> $DIR/call-generic-method-nonconst.rs:19:34
| |
LL | pub const EQ: bool = equals_self(&S); LL | pub const EQ: bool = equals_self(&S);