Skip to content

Commit b8ff71a

Browse files
authored
Unrolled build for rust-lang#126403
Rollup merge of rust-lang#126403 - compiler-errors:better-type-errors, r=lcnr Actually report normalization-based type errors correctly for alias-relate obligations in new solver We have some special casing to report type mismatch errors that come from projection predicates, but we don't do that for alias-relate obligations. This PR implements that. There's a bit of code duplication, but 🤷 Best reviewed without whitespace. r? lcnr
2 parents d68fe4e + ecdaff2 commit b8ff71a

File tree

9 files changed

+140
-57
lines changed

9 files changed

+140
-57
lines changed

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

+101-48
Original file line numberDiff line numberDiff line change
@@ -1586,60 +1586,113 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
15861586
}
15871587

15881588
self.probe(|_| {
1589-
let ocx = ObligationCtxt::new(self);
1590-
15911589
// try to find the mismatched types to report the error with.
15921590
//
15931591
// this can fail if the problem was higher-ranked, in which
15941592
// cause I have no idea for a good error message.
15951593
let bound_predicate = predicate.kind();
1596-
let (values, err) = if let ty::PredicateKind::Clause(ty::ClauseKind::Projection(data)) =
1597-
bound_predicate.skip_binder()
1598-
{
1599-
let data = self.instantiate_binder_with_fresh_vars(
1600-
obligation.cause.span,
1601-
infer::BoundRegionConversionTime::HigherRankedType,
1602-
bound_predicate.rebind(data),
1603-
);
1604-
let unnormalized_term = data.projection_term.to_term(self.tcx);
1605-
// FIXME(-Znext-solver): For diagnostic purposes, it would be nice
1606-
// to deeply normalize this type.
1607-
let normalized_term =
1608-
ocx.normalize(&obligation.cause, obligation.param_env, unnormalized_term);
1609-
1610-
debug!(?obligation.cause, ?obligation.param_env);
1611-
1612-
debug!(?normalized_term, data.ty = ?data.term);
1594+
let (values, err) = match bound_predicate.skip_binder() {
1595+
ty::PredicateKind::Clause(ty::ClauseKind::Projection(data)) => {
1596+
let ocx = ObligationCtxt::new(self);
1597+
1598+
let data = self.instantiate_binder_with_fresh_vars(
1599+
obligation.cause.span,
1600+
infer::BoundRegionConversionTime::HigherRankedType,
1601+
bound_predicate.rebind(data),
1602+
);
1603+
let unnormalized_term = data.projection_term.to_term(self.tcx);
1604+
// FIXME(-Znext-solver): For diagnostic purposes, it would be nice
1605+
// to deeply normalize this type.
1606+
let normalized_term =
1607+
ocx.normalize(&obligation.cause, obligation.param_env, unnormalized_term);
1608+
1609+
let is_normalized_term_expected = !matches!(
1610+
obligation.cause.code().peel_derives(),
1611+
ObligationCauseCode::WhereClause(..)
1612+
| ObligationCauseCode::WhereClauseInExpr(..)
1613+
| ObligationCauseCode::Coercion { .. }
1614+
);
16131615

1614-
let is_normalized_term_expected = !matches!(
1615-
obligation.cause.code().peel_derives(),
1616-
|ObligationCauseCode::WhereClause(..)| ObligationCauseCode::WhereClauseInExpr(
1617-
..
1618-
) | ObligationCauseCode::Coercion { .. }
1619-
);
1616+
let (expected, actual) = if is_normalized_term_expected {
1617+
(normalized_term, data.term)
1618+
} else {
1619+
(data.term, normalized_term)
1620+
};
16201621

1621-
let (expected, actual) = if is_normalized_term_expected {
1622-
(normalized_term, data.term)
1623-
} else {
1624-
(data.term, normalized_term)
1625-
};
1622+
// constrain inference variables a bit more to nested obligations from normalize so
1623+
// we can have more helpful errors.
1624+
//
1625+
// we intentionally drop errors from normalization here,
1626+
// since the normalization is just done to improve the error message.
1627+
let _ = ocx.select_where_possible();
16261628

1627-
// constrain inference variables a bit more to nested obligations from normalize so
1628-
// we can have more helpful errors.
1629-
//
1630-
// we intentionally drop errors from normalization here,
1631-
// since the normalization is just done to improve the error message.
1632-
let _ = ocx.select_where_possible();
1629+
if let Err(new_err) =
1630+
ocx.eq(&obligation.cause, obligation.param_env, expected, actual)
1631+
{
1632+
(
1633+
Some((
1634+
data.projection_term,
1635+
is_normalized_term_expected,
1636+
self.resolve_vars_if_possible(normalized_term),
1637+
data.term,
1638+
)),
1639+
new_err,
1640+
)
1641+
} else {
1642+
(None, error.err)
1643+
}
1644+
}
1645+
ty::PredicateKind::AliasRelate(lhs, rhs, _) => {
1646+
let derive_better_type_error =
1647+
|alias_term: ty::AliasTerm<'tcx>, expected_term: ty::Term<'tcx>| {
1648+
let ocx = ObligationCtxt::new(self);
1649+
let normalized_term = match expected_term.unpack() {
1650+
ty::TermKind::Ty(_) => self.next_ty_var(DUMMY_SP).into(),
1651+
ty::TermKind::Const(_) => self.next_const_var(DUMMY_SP).into(),
1652+
};
1653+
ocx.register_obligation(Obligation::new(
1654+
self.tcx,
1655+
ObligationCause::dummy(),
1656+
obligation.param_env,
1657+
ty::PredicateKind::NormalizesTo(ty::NormalizesTo {
1658+
alias: alias_term,
1659+
term: normalized_term,
1660+
}),
1661+
));
1662+
let _ = ocx.select_where_possible();
1663+
if let Err(terr) = ocx.eq(
1664+
&ObligationCause::dummy(),
1665+
obligation.param_env,
1666+
expected_term,
1667+
normalized_term,
1668+
) {
1669+
Some((terr, self.resolve_vars_if_possible(normalized_term)))
1670+
} else {
1671+
None
1672+
}
1673+
};
16331674

1634-
if let Err(new_err) =
1635-
ocx.eq(&obligation.cause, obligation.param_env, expected, actual)
1636-
{
1637-
(Some((data, is_normalized_term_expected, normalized_term, data.term)), new_err)
1638-
} else {
1639-
(None, error.err)
1675+
if let Some(lhs) = lhs.to_alias_term()
1676+
&& let Some((better_type_err, expected_term)) =
1677+
derive_better_type_error(lhs, rhs)
1678+
{
1679+
(
1680+
Some((lhs, true, self.resolve_vars_if_possible(expected_term), rhs)),
1681+
better_type_err,
1682+
)
1683+
} else if let Some(rhs) = rhs.to_alias_term()
1684+
&& let Some((better_type_err, expected_term)) =
1685+
derive_better_type_error(rhs, lhs)
1686+
{
1687+
(
1688+
Some((rhs, true, self.resolve_vars_if_possible(expected_term), lhs)),
1689+
better_type_err,
1690+
)
1691+
} else {
1692+
(None, error.err)
1693+
}
16401694
}
1641-
} else {
1642-
(None, error.err)
1695+
_ => (None, error.err),
16431696
};
16441697

16451698
let msg = values
@@ -1737,15 +1790,15 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
17371790

17381791
fn maybe_detailed_projection_msg(
17391792
&self,
1740-
pred: ty::ProjectionPredicate<'tcx>,
1793+
projection_term: ty::AliasTerm<'tcx>,
17411794
normalized_ty: ty::Term<'tcx>,
17421795
expected_ty: ty::Term<'tcx>,
17431796
) -> Option<String> {
1744-
let trait_def_id = pred.projection_term.trait_def_id(self.tcx);
1745-
let self_ty = pred.projection_term.self_ty();
1797+
let trait_def_id = projection_term.trait_def_id(self.tcx);
1798+
let self_ty = projection_term.self_ty();
17461799

17471800
with_forced_trimmed_paths! {
1748-
if self.tcx.is_lang_item(pred.projection_term.def_id,LangItem::FnOnceOutput) {
1801+
if self.tcx.is_lang_item(projection_term.def_id, LangItem::FnOnceOutput) {
17491802
let fn_kind = self_ty.prefix_string(self.tcx);
17501803
let item = match self_ty.kind() {
17511804
ty::FnDef(def, _) => self.tcx.item_name(*def).to_string(),

tests/ui/diagnostic_namespace/do_not_recommend/as_expression.next.stderr

+4-1
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,10 @@ error[E0271]: type mismatch resolving `<SelectInt as Expression>::SqlType == Tex
2929
--> $DIR/as_expression.rs:57:5
3030
|
3131
LL | SelectInt.check("bar");
32-
| ^^^^^^^^^^^^^^^^^^^^^^ types differ
32+
| ^^^^^^^^^^^^^^^^^^^^^^ expected `Integer`, found `Text`
33+
|
34+
= note: expected struct `Integer`
35+
found struct `Text`
3336

3437
error: aborting due to 3 previous errors
3538

tests/ui/rfcs/rfc-2632-const-trait-impl/issue-100222.nn.stderr

+4-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,10 @@ error[E0271]: type mismatch resolving `<() as Index>::Output == &mut <() as Inde
22
--> $DIR/issue-100222.rs:34:12
33
|
44
LL | fn foo(&mut self, x: <Self as Index>::Output) -> <Self as Index>::Output
5-
| ^^^^^^^^^ types differ
5+
| ^^^^^^^^^ expected `()`, found `&mut <() as Index>::Output`
6+
|
7+
= note: expected unit type `()`
8+
found mutable reference `&mut <() as Index>::Output`
69

710
error: aborting due to 1 previous error
811

tests/ui/rfcs/rfc-2632-const-trait-impl/issue-100222.ny.stderr

+4-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,10 @@ error[E0271]: type mismatch resolving `<() as Index>::Output == &mut <() as Inde
22
--> $DIR/issue-100222.rs:25:12
33
|
44
LL | fn foo(&mut self, x: <Self as Index>::Output) -> <Self as Index>::Output
5-
| ^^^^^^^^^ types differ
5+
| ^^^^^^^^^ expected `()`, found `&mut <() as Index>::Output`
6+
|
7+
= note: expected unit type `()`
8+
found mutable reference `&mut <() as Index>::Output`
69

710
error: aborting due to 1 previous error
811

tests/ui/rfcs/rfc-2632-const-trait-impl/issue-100222.yn.stderr

+4-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,10 @@ error[E0271]: type mismatch resolving `<() as Index>::Output == &mut <() as Inde
22
--> $DIR/issue-100222.rs:34:12
33
|
44
LL | fn foo(&mut self, x: <Self as Index>::Output) -> <Self as Index>::Output
5-
| ^^^^^^^^^ types differ
5+
| ^^^^^^^^^ expected `()`, found `&mut <() as Index>::Output`
6+
|
7+
= note: expected unit type `()`
8+
found mutable reference `&mut <() as Index>::Output`
69

710
error: aborting due to 1 previous error
811

tests/ui/rfcs/rfc-2632-const-trait-impl/issue-100222.yy.stderr

+4-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,10 @@ error[E0271]: type mismatch resolving `<() as Index>::Output == &mut <() as Inde
22
--> $DIR/issue-100222.rs:25:12
33
|
44
LL | fn foo(&mut self, x: <Self as Index>::Output) -> <Self as Index>::Output
5-
| ^^^^^^^^^ types differ
5+
| ^^^^^^^^^ expected `()`, found `&mut <() as Index>::Output`
6+
|
7+
= note: expected unit type `()`
8+
found mutable reference `&mut <() as Index>::Output`
69

710
error: aborting due to 1 previous error
811

tests/ui/traits/next-solver/async.fail.stderr

+4-2
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
1-
error[E0271]: type mismatch resolving `<{async block@$DIR/async.rs:12:17: 12:22} as Future>::Output == i32`
1+
error[E0271]: expected `{async block@$DIR/async.rs:12:17: 12:22}` to be a future that resolves to `i32`, but it resolves to `()`
22
--> $DIR/async.rs:12:17
33
|
44
LL | needs_async(async {});
5-
| ----------- ^^^^^^^^ types differ
5+
| ----------- ^^^^^^^^ expected `()`, found `i32`
66
| |
77
| required by a bound introduced by this call
88
|
9+
= note: expected unit type `()`
10+
found type `i32`
911
note: required by a bound in `needs_async`
1012
--> $DIR/async.rs:8:31
1113
|

tests/ui/traits/next-solver/async.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ fn needs_async(_: impl Future<Output = i32>) {}
1010
#[cfg(fail)]
1111
fn main() {
1212
needs_async(async {});
13-
//[fail]~^ ERROR type mismatch
13+
//[fail]~^ ERROR expected `{async block@$DIR/async.rs:12:17: 12:22}` to be a future that resolves to `i32`, but it resolves to `()`
1414
}
1515

1616
#[cfg(pass)]

tests/ui/traits/next-solver/more-object-bound.stderr

+14-1
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,22 @@
11
error[E0271]: type mismatch resolving `<dyn Trait<A = A, B = B> as SuperTrait>::A == B`
22
--> $DIR/more-object-bound.rs:12:5
33
|
4+
LL | fn transmute<A, B>(x: A) -> B {
5+
| - -
6+
| | |
7+
| | expected type parameter
8+
| | found type parameter
9+
| found type parameter
10+
| expected type parameter
411
LL | foo::<A, B, dyn Trait<A = A, B = B>>(x)
5-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ types differ
12+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected type parameter `A`, found type parameter `B`
613
|
14+
= note: expected type parameter `A`
15+
found type parameter `B`
16+
= note: a type parameter was expected, but a different one was found; you might be missing a type parameter or trait bound
17+
= note: for more information, visit https://doc.rust-lang.org/book/ch10-02-traits.html#traits-as-parameters
18+
= note: a type parameter was expected, but a different one was found; you might be missing a type parameter or trait bound
19+
= note: for more information, visit https://doc.rust-lang.org/book/ch10-02-traits.html#traits-as-parameters
720
= note: required because it appears within the type `dyn Trait<A = A, B = B>`
821
note: required by a bound in `foo`
922
--> $DIR/more-object-bound.rs:18:8

0 commit comments

Comments
 (0)