1
Fork 0

Rollup merge of #104903 - spastorino:consolidate-normalize-in-report_projection_error, r=lcnr

Use ocx.normalize in report_projection_error

r? `@lcnr`

cc `@compiler-errors`
This commit is contained in:
Yuki Okushi 2022-12-03 12:51:27 +09:00 committed by GitHub
commit 52e886279a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 48 additions and 21 deletions

View file

@ -112,6 +112,24 @@ impl<'a, 'tcx> ObligationCtxt<'a, 'tcx> {
self.register_infer_ok_obligations(infer_ok) self.register_infer_ok_obligations(infer_ok)
} }
/// Makes `expected <: actual`.
pub fn eq_exp<T>(
&self,
cause: &ObligationCause<'tcx>,
param_env: ty::ParamEnv<'tcx>,
a_is_expected: bool,
a: T,
b: T,
) -> Result<(), TypeError<'tcx>>
where
T: ToTrace<'tcx>,
{
self.infcx
.at(cause, param_env)
.eq_exp(a_is_expected, a, b)
.map(|infer_ok| self.register_infer_ok_obligations(infer_ok))
}
pub fn eq<T: ToTrace<'tcx>>( pub fn eq<T: ToTrace<'tcx>>(
&self, &self,
cause: &ObligationCause<'tcx>, cause: &ObligationCause<'tcx>,

View file

@ -1577,32 +1577,26 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
} }
self.probe(|_| { self.probe(|_| {
let mut err = error.err; let ocx = ObligationCtxt::new_in_snapshot(self);
let mut values = None;
// try to find the mismatched types to report the error with. // try to find the mismatched types to report the error with.
// //
// this can fail if the problem was higher-ranked, in which // this can fail if the problem was higher-ranked, in which
// cause I have no idea for a good error message. // cause I have no idea for a good error message.
let bound_predicate = predicate.kind(); let bound_predicate = predicate.kind();
if let ty::PredicateKind::Clause(ty::Clause::Projection(data)) = let (values, err) = if let ty::PredicateKind::Clause(ty::Clause::Projection(data)) =
bound_predicate.skip_binder() bound_predicate.skip_binder()
{ {
let mut selcx = SelectionContext::new(self);
let data = self.replace_bound_vars_with_fresh_vars( let data = self.replace_bound_vars_with_fresh_vars(
obligation.cause.span, obligation.cause.span,
infer::LateBoundRegionConversionTime::HigherRankedType, infer::LateBoundRegionConversionTime::HigherRankedType,
bound_predicate.rebind(data), bound_predicate.rebind(data),
); );
let mut obligations = vec![]; let normalized_ty = ocx.normalize(
// FIXME(normalization): Change this to use `At::normalize` &obligation.cause,
let normalized_ty = super::normalize_projection_type(
&mut selcx,
obligation.param_env, obligation.param_env,
data.projection_ty, self.tcx
obligation.cause.clone(), .mk_projection(data.projection_ty.item_def_id, data.projection_ty.substs),
0,
&mut obligations,
); );
debug!(?obligation.cause, ?obligation.param_env); debug!(?obligation.cause, ?obligation.param_env);
@ -1618,19 +1612,34 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
| ObligationCauseCode::ObjectCastObligation(..) | ObligationCauseCode::ObjectCastObligation(..)
| ObligationCauseCode::OpaqueType | ObligationCauseCode::OpaqueType
); );
if let Err(new_err) = self.at(&obligation.cause, obligation.param_env).eq_exp( let expected_ty = data.term.ty().unwrap();
// constrain inference variables a bit more to nested obligations from normalize so
// we can have more helpful errors.
ocx.select_where_possible();
if let Err(new_err) = ocx.eq_exp(
&obligation.cause,
obligation.param_env,
is_normalized_ty_expected, is_normalized_ty_expected,
normalized_ty, normalized_ty,
data.term, expected_ty,
) { ) {
values = Some((data, is_normalized_ty_expected, normalized_ty, data.term)); (Some((data, is_normalized_ty_expected, normalized_ty, expected_ty)), new_err)
err = new_err; } else {
(None, error.err)
} }
} } else {
(None, error.err)
};
let msg = values let msg = values
.and_then(|(predicate, _, normalized_ty, expected_ty)| { .and_then(|(predicate, _, normalized_ty, expected_ty)| {
self.maybe_detailed_projection_msg(predicate, normalized_ty, expected_ty) self.maybe_detailed_projection_msg(
predicate,
normalized_ty.into(),
expected_ty.into(),
)
}) })
.unwrap_or_else(|| format!("type mismatch resolving `{}`", predicate)); .unwrap_or_else(|| format!("type mismatch resolving `{}`", predicate));
let mut diag = struct_span_err!(self.tcx.sess, obligation.cause.span, E0271, "{msg}"); let mut diag = struct_span_err!(self.tcx.sess, obligation.cause.span, E0271, "{msg}");
@ -1672,11 +1681,11 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
&mut diag, &mut diag,
&obligation.cause, &obligation.cause,
secondary_span, secondary_span,
values.map(|(_, is_normalized_ty_expected, normalized_ty, term)| { values.map(|(_, is_normalized_ty_expected, normalized_ty, expected_ty)| {
infer::ValuePairs::Terms(ExpectedFound::new( infer::ValuePairs::Terms(ExpectedFound::new(
is_normalized_ty_expected, is_normalized_ty_expected,
normalized_ty, normalized_ty.into(),
term, expected_ty.into(),
)) ))
}), }),
err, err,