Add a minimal working append_const_msg
argument
This commit is contained in:
parent
fdf7d01088
commit
8b76cad0a7
8 changed files with 112 additions and 22 deletions
|
@ -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,
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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> {
|
||||||
|
|
|
@ -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> {
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue