Skip to content

Commit 8b76cad

Browse files
committed
Add a minimal working append_const_msg argument
1 parent fdf7d01 commit 8b76cad

File tree

8 files changed

+112
-22
lines changed

8 files changed

+112
-22
lines changed

compiler/rustc_span/src/symbol.rs

+1
Original file line numberDiff line numberDiff line change
@@ -321,6 +321,7 @@ symbols! {
321321
and,
322322
and_then,
323323
any,
324+
append_const_msg,
324325
arbitrary_enum_discriminant,
325326
arbitrary_self_types,
326327
arith_offset,

compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs

+29-8
Original file line numberDiff line numberDiff line change
@@ -310,13 +310,18 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
310310
})
311311
.unwrap_or_default();
312312

313-
let OnUnimplementedNote { message, label, note, enclosing_scope } =
314-
self.on_unimplemented_note(trait_ref, &obligation);
313+
let OnUnimplementedNote {
314+
message,
315+
label,
316+
note,
317+
enclosing_scope,
318+
append_const_msg,
319+
} = self.on_unimplemented_note(trait_ref, &obligation);
315320
let have_alt_message = message.is_some() || label.is_some();
316321
let is_try_conversion = self.is_try_conversion(span, trait_ref.def_id());
317322
let is_unsize =
318323
{ Some(trait_ref.def_id()) == self.tcx.lang_items().unsize_trait() };
319-
let (message, note) = if is_try_conversion {
324+
let (message, note, append_const_msg) = if is_try_conversion {
320325
(
321326
Some(format!(
322327
"`?` couldn't convert the error to `{}`",
@@ -327,22 +332,38 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
327332
conversion on the error value using the `From` trait"
328333
.to_owned(),
329334
),
335+
Some(None),
330336
)
331337
} else {
332-
(message, note)
338+
(message, note, append_const_msg)
333339
};
334340

335341
let mut err = struct_span_err!(
336342
self.tcx.sess,
337343
span,
338344
E0277,
339345
"{}",
340-
(!predicate_is_const).then(|| message).flatten().unwrap_or_else(
341-
|| format!(
346+
message
347+
.and_then(|cannot_do_this| {
348+
match (predicate_is_const, append_const_msg) {
349+
// do nothing if predicate is not const
350+
(false, _) => Some(cannot_do_this),
351+
// suggested using default post message
352+
(true, Some(None)) => {
353+
Some(format!("{cannot_do_this} in const contexts"))
354+
}
355+
// overriden post message
356+
(true, Some(Some(post_message))) => {
357+
Some(format!("{cannot_do_this}{post_message}"))
358+
}
359+
// fallback to generic message
360+
(true, None) => None,
361+
}
362+
})
363+
.unwrap_or_else(|| format!(
342364
"the trait bound `{}` is not satisfied{}",
343365
trait_predicate, post_message,
344-
)
345-
)
366+
))
346367
);
347368

348369
if is_try_conversion {

compiler/rustc_trait_selection/src/traits/on_unimplemented.rs

+21
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ pub struct OnUnimplementedDirective {
1919
pub label: Option<OnUnimplementedFormatString>,
2020
pub note: Option<OnUnimplementedFormatString>,
2121
pub enclosing_scope: Option<OnUnimplementedFormatString>,
22+
pub append_const_msg: Option<Option<Symbol>>,
2223
}
2324

2425
#[derive(Default)]
@@ -27,6 +28,11 @@ pub struct OnUnimplementedNote {
2728
pub label: Option<String>,
2829
pub note: Option<String>,
2930
pub enclosing_scope: Option<String>,
31+
/// Append a message for `~const Trait` errors. `None` means not requested and
32+
/// should fallback to a generic message, `Some(None)` suggests using the default
33+
/// appended message, `Some(Some(s))` suggests use the `s` message instead of the
34+
/// default one..
35+
pub append_const_msg: Option<Option<Symbol>>,
3036
}
3137

3238
fn parse_error(
@@ -89,6 +95,7 @@ impl<'tcx> OnUnimplementedDirective {
8995
let mut note = None;
9096
let mut enclosing_scope = None;
9197
let mut subcommands = vec![];
98+
let mut append_const_msg = None;
9299

93100
let parse_value = |value_str| {
94101
OnUnimplementedFormatString::try_parse(tcx, trait_def_id, value_str, span).map(Some)
@@ -131,6 +138,14 @@ impl<'tcx> OnUnimplementedDirective {
131138
}
132139
continue;
133140
}
141+
} else if item.has_name(sym::append_const_msg) && append_const_msg.is_none() {
142+
if let Some(msg) = item.value_str() {
143+
append_const_msg = Some(Some(msg));
144+
continue;
145+
} else if item.is_word() {
146+
append_const_msg = Some(None);
147+
continue;
148+
}
134149
}
135150

136151
// nothing found
@@ -153,6 +168,7 @@ impl<'tcx> OnUnimplementedDirective {
153168
label,
154169
note,
155170
enclosing_scope,
171+
append_const_msg,
156172
})
157173
}
158174
}
@@ -183,6 +199,7 @@ impl<'tcx> OnUnimplementedDirective {
183199
)?),
184200
note: None,
185201
enclosing_scope: None,
202+
append_const_msg: None,
186203
}))
187204
} else {
188205
return Err(ErrorReported);
@@ -201,6 +218,7 @@ impl<'tcx> OnUnimplementedDirective {
201218
let mut label = None;
202219
let mut note = None;
203220
let mut enclosing_scope = None;
221+
let mut append_const_msg = None;
204222
info!("evaluate({:?}, trait_ref={:?}, options={:?})", self, trait_ref, options);
205223

206224
for command in self.subcommands.iter().chain(Some(self)).rev() {
@@ -235,6 +253,8 @@ impl<'tcx> OnUnimplementedDirective {
235253
if let Some(ref enclosing_scope_) = command.enclosing_scope {
236254
enclosing_scope = Some(enclosing_scope_.clone());
237255
}
256+
257+
append_const_msg = command.append_const_msg.clone();
238258
}
239259

240260
let options: FxHashMap<Symbol, String> =
@@ -244,6 +264,7 @@ impl<'tcx> OnUnimplementedDirective {
244264
message: message.map(|m| m.format(tcx, trait_ref, &options)),
245265
note: note.map(|n| n.format(tcx, trait_ref, &options)),
246266
enclosing_scope: enclosing_scope.map(|e_s| e_s.format(tcx, trait_ref, &options)),
267+
append_const_msg,
247268
}
248269
}
249270
}

library/core/src/cmp.rs

+28-6
Original file line numberDiff line numberDiff line change
@@ -199,9 +199,20 @@ use self::Ordering::*;
199199
#[stable(feature = "rust1", since = "1.0.0")]
200200
#[doc(alias = "==")]
201201
#[doc(alias = "!=")]
202-
#[rustc_on_unimplemented(
203-
message = "can't compare `{Self}` with `{Rhs}`",
204-
label = "no implementation for `{Self} == {Rhs}`"
202+
#[cfg_attr(
203+
bootstrap,
204+
rustc_on_unimplemented(
205+
message = "can't compare `{Self}` with `{Rhs}`",
206+
label = "no implementation for `{Self} == {Rhs}`"
207+
)
208+
)]
209+
#[cfg_attr(
210+
not(bootstrap),
211+
rustc_on_unimplemented(
212+
message = "can't compare `{Self}` with `{Rhs}`",
213+
label = "no implementation for `{Self} == {Rhs}`",
214+
append_const_msg,
215+
)
205216
)]
206217
#[rustc_diagnostic_item = "PartialEq"]
207218
pub trait PartialEq<Rhs: ?Sized = Self> {
@@ -1031,9 +1042,20 @@ impl PartialOrd for Ordering {
10311042
#[doc(alias = "<")]
10321043
#[doc(alias = "<=")]
10331044
#[doc(alias = ">=")]
1034-
#[rustc_on_unimplemented(
1035-
message = "can't compare `{Self}` with `{Rhs}`",
1036-
label = "no implementation for `{Self} < {Rhs}` and `{Self} > {Rhs}`"
1045+
#[cfg_attr(
1046+
bootstrap,
1047+
rustc_on_unimplemented(
1048+
message = "can't compare `{Self}` with `{Rhs}`",
1049+
label = "no implementation for `{Self} < {Rhs}` and `{Self} > {Rhs}`",
1050+
)
1051+
)]
1052+
#[cfg_attr(
1053+
not(bootstrap),
1054+
rustc_on_unimplemented(
1055+
message = "can't compare `{Self}` with `{Rhs}`",
1056+
label = "no implementation for `{Self} < {Rhs}` and `{Self} > {Rhs}`",
1057+
append_const_msg,
1058+
)
10371059
)]
10381060
#[rustc_diagnostic_item = "PartialOrd"]
10391061
pub trait PartialOrd<Rhs: ?Sized = Self>: PartialEq<Rhs> {

library/core/src/ops/arith.rs

+30-5
Original file line numberDiff line numberDiff line change
@@ -65,11 +65,36 @@
6565
/// ```
6666
#[lang = "add"]
6767
#[stable(feature = "rust1", since = "1.0.0")]
68-
#[rustc_on_unimplemented(
69-
on(all(_Self = "{integer}", Rhs = "{float}"), message = "cannot add a float to an integer",),
70-
on(all(_Self = "{float}", Rhs = "{integer}"), message = "cannot add an integer to a float",),
71-
message = "cannot add `{Rhs}` to `{Self}`",
72-
label = "no implementation for `{Self} + {Rhs}`"
68+
#[cfg_attr(
69+
bootstrap,
70+
rustc_on_unimplemented(
71+
on(
72+
all(_Self = "{integer}", Rhs = "{float}"),
73+
message = "cannot add a float to an integer",
74+
),
75+
on(
76+
all(_Self = "{float}", Rhs = "{integer}"),
77+
message = "cannot add an integer to a float",
78+
),
79+
message = "cannot add `{Rhs}` to `{Self}`",
80+
label = "no implementation for `{Self} + {Rhs}`"
81+
)
82+
)]
83+
#[cfg_attr(
84+
not(bootstrap),
85+
rustc_on_unimplemented(
86+
on(
87+
all(_Self = "{integer}", Rhs = "{float}"),
88+
message = "cannot add a float to an integer",
89+
),
90+
on(
91+
all(_Self = "{float}", Rhs = "{integer}"),
92+
message = "cannot add an integer to a float",
93+
),
94+
message = "cannot add `{Rhs}` to `{Self}`",
95+
label = "no implementation for `{Self} + {Rhs}`",
96+
append_const_msg,
97+
)
7398
)]
7499
#[doc(alias = "+")]
75100
pub trait Add<Rhs = Self> {

src/test/ui/rfc-2632-const-trait-impl/assoc-type.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ trait Foo {
1616

1717
impl const Foo for NonConstAdd {
1818
type Bar = NonConstAdd;
19-
//~^ ERROR: the trait bound `NonConstAdd: ~const Add` is not satisfied
19+
//~^ ERROR: cannot add `NonConstAdd` to `NonConstAdd` in const contexts
2020
}
2121

2222
trait Baz {

src/test/ui/rfc-2632-const-trait-impl/assoc-type.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
error[E0277]: the trait bound `NonConstAdd: ~const Add` is not satisfied
1+
error[E0277]: cannot add `NonConstAdd` to `NonConstAdd` in const contexts
22
--> $DIR/assoc-type.rs:18:16
33
|
44
LL | type Bar = NonConstAdd;

src/test/ui/rfc-2632-const-trait-impl/call-generic-method-nonconst.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
error[E0277]: the trait bound `S: ~const PartialEq` is not satisfied
1+
error[E0277]: can't compare `S` with `S` in const contexts
22
--> $DIR/call-generic-method-nonconst.rs:19:34
33
|
44
LL | pub const EQ: bool = equals_self(&S);

0 commit comments

Comments
 (0)