Skip to content

Commit 3b92583

Browse files
committed
try to create suggestions for mismatched consts in FulfillmentError::TooGeneric cases
1 parent 4bcd67c commit 3b92583

File tree

3 files changed

+60
-7
lines changed

3 files changed

+60
-7
lines changed

compiler/rustc_infer/src/infer/error_reporting/mod.rs

Lines changed: 33 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -856,7 +856,11 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
856856
.regions()
857857
.map(|lifetime| {
858858
let s = lifetime.to_string();
859-
if s.is_empty() { "'_".to_string() } else { s }
859+
if s.is_empty() {
860+
"'_".to_string()
861+
} else {
862+
s
863+
}
860864
})
861865
.collect::<Vec<_>>()
862866
.join(", ");
@@ -1175,7 +1179,11 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
11751179

11761180
fn lifetime_display(lifetime: Region<'_>) -> String {
11771181
let s = lifetime.to_string();
1178-
if s.is_empty() { "'_".to_string() } else { s }
1182+
if s.is_empty() {
1183+
"'_".to_string()
1184+
} else {
1185+
s
1186+
}
11791187
}
11801188
// At one point we'd like to elide all lifetimes here, they are irrelevant for
11811189
// all diagnostics that use this output
@@ -1449,7 +1457,6 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
14491457
swap_secondary_and_primary: bool,
14501458
) {
14511459
let span = cause.span(self.tcx);
1452-
debug!("note_type_err cause={:?} values={:?}, terr={:?}", cause, values, terr);
14531460

14541461
// For some types of errors, expected-found does not make
14551462
// sense, so just ignore the values we were given.
@@ -1581,11 +1588,11 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
15811588
}
15821589
}
15831590

1584-
debug!("note_type_err(diag={:?})", diag);
15851591
enum Mismatch<'a> {
15861592
Variable(ty::error::ExpectedFound<Ty<'a>>),
15871593
Fixed(&'static str),
15881594
}
1595+
15891596
let (expected_found, exp_found, is_simple_error) = match values {
15901597
None => (None, Mismatch::Fixed("type"), false),
15911598
Some(values) => {
@@ -1652,6 +1659,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
16521659
}
16531660
}
16541661
};
1662+
16551663
if let Some((expected, found)) = expected_found {
16561664
let (expected_label, found_label, exp_found) = match exp_found {
16571665
Mismatch::Variable(ef) => (
@@ -1705,6 +1713,19 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
17051713
(TypeError::ObjectUnsafeCoercion(_), _) => {
17061714
diag.note_unsuccessful_coercion(found, expected);
17071715
}
1716+
(TypeError::ConstMismatchTooGeneric(_, Some(sugg)), _) => {
1717+
if !is_simple_error {
1718+
let found =
1719+
DiagnosticStyledString::highlighted(format!("{}", sugg.clone()));
1720+
1721+
diag.note_expected_found(
1722+
&expected_label,
1723+
expected,
1724+
&"type".to_string(),
1725+
found,
1726+
);
1727+
}
1728+
}
17081729
(_, _) => {
17091730
debug!(
17101731
"note_type_err: exp_found={:?}, expected={:?} found={:?}",
@@ -1716,10 +1737,12 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
17161737
}
17171738
}
17181739
}
1740+
17191741
let exp_found = match exp_found {
17201742
Mismatch::Variable(exp_found) => Some(exp_found),
17211743
Mismatch::Fixed(_) => None,
17221744
};
1745+
17231746
let exp_found = match terr {
17241747
// `terr` has more accurate type information than `exp_found` in match expressions.
17251748
ty::error::TypeError::Sorts(terr)
@@ -1730,6 +1753,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
17301753
_ => exp_found,
17311754
};
17321755
debug!("exp_found {:?} terr {:?} cause.code {:?}", exp_found, terr, cause.code());
1756+
17331757
if let Some(exp_found) = exp_found {
17341758
let should_suggest_fixes = if let ObligationCauseCode::Pattern { root_ty, .. } =
17351759
cause.code()
@@ -1756,6 +1780,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
17561780
self.tcx.hir().opt_local_def_id(cause.body_id).unwrap_or_else(|| {
17571781
self.tcx.hir().body_owner_def_id(hir::BodyId { hir_id: cause.body_id })
17581782
});
1783+
17591784
self.check_and_note_conflicting_crates(diag, terr);
17601785
self.tcx.note_and_explain_type_err(diag, terr, cause, span, body_owner_def_id.to_def_id());
17611786

@@ -2021,10 +2046,9 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
20212046
) -> DiagnosticBuilder<'tcx> {
20222047
use crate::traits::ObligationCauseCode::MatchExpressionArm;
20232048

2024-
debug!("report_and_explain_type_error(trace={:?}, terr={:?})", trace, terr);
2025-
20262049
let span = trace.cause.span(self.tcx);
20272050
let failure_code = trace.cause.as_failure_code(terr);
2051+
20282052
let mut diag = match failure_code {
20292053
FailureCode::Error0038(did) => {
20302054
let violations = self.tcx.object_safety_violations(did);
@@ -2038,9 +2062,12 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
20382062
}
20392063
FailureCode::Error0308(failure_str) => {
20402064
let mut err = struct_span_err!(self.tcx.sess, span, E0308, "{}", failure_str);
2065+
20412066
if let ValuePairs::Types(ty::error::ExpectedFound { expected, found }) =
20422067
trace.values
20432068
{
2069+
debug!(?expected, ?found);
2070+
20442071
// If a tuple of length one was expected and the found expression has
20452072
// parentheses around it, perhaps the user meant to write `(expr,)` to
20462073
// build a tuple (issue #86100)

compiler/rustc_infer/src/infer/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1484,6 +1484,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
14841484
self.report_and_explain_type_error(trace, &err)
14851485
}
14861486

1487+
#[instrument(skip(self), level = "debug")]
14871488
pub fn report_mismatched_consts(
14881489
&self,
14891490
cause: &ObligationCause<'tcx>,

compiler/rustc_trait_selection/src/traits/fulfill.rs

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ use super::{FulfillmentError, FulfillmentErrorCode};
2727
use super::{ObligationCause, PredicateObligation};
2828

2929
use crate::traits::error_reporting::InferCtxtExt as _;
30+
use crate::traits::error_reporting::InferCtxtPrivExt;
3031
use crate::traits::project::PolyProjectionObligation;
3132
use crate::traits::project::ProjectionCacheKeyExt as _;
3233
use crate::traits::query::evaluate_obligation::InferCtxtExt as _;
@@ -629,11 +630,35 @@ impl<'a, 'b, 'tcx> FulfillProcessor<'a, 'b, 'tcx> {
629630
if c1.has_infer_types_or_consts() || c2.has_infer_types_or_consts() {
630631
ProcessResult::Unchanged
631632
} else {
633+
debug!(
634+
"ConstEquate error found, expected {:?}, found {:?}",
635+
c1, c2
636+
);
637+
632638
// Two different constants using generic parameters ~> error.
633639
let expected_found = ExpectedFound::new(true, c1, c2);
640+
641+
let suggestion = self
642+
.selcx
643+
.infcx()
644+
.try_create_suggestion_for_mismatched_const(expected_found)
645+
.map(|sugg| {
646+
let found_is_uneval = match expected_found.found.val {
647+
ty::ConstKind::Unevaluated(_) => true,
648+
_ => false,
649+
};
650+
651+
if found_is_uneval {
652+
format!("{{ {} }}", sugg)
653+
} else {
654+
sugg
655+
}
656+
});
657+
debug!(?suggestion);
658+
634659
ProcessResult::Error(FulfillmentErrorCode::CodeConstEquateError(
635660
expected_found,
636-
TypeError::ConstMismatch(expected_found),
661+
TypeError::ConstMismatchTooGeneric(expected_found, suggestion),
637662
))
638663
}
639664
}

0 commit comments

Comments
 (0)