Rollup merge of #97818 - compiler-errors:rpit-error-spanned, r=oli-obk
Point at return expression for RPIT-related error Certainly this needs some diagnostic refining, but I wanted to show that it was possible first and foremost. Not sure if this is the right approach. Open to feedback. Fixes #80583
This commit is contained in:
commit
dfc6d7ac76
14 changed files with 97 additions and 5 deletions
|
@ -5,7 +5,7 @@ use hir::{HirId, OpaqueTyOrigin};
|
|||
use rustc_data_structures::sync::Lrc;
|
||||
use rustc_data_structures::vec_map::VecMap;
|
||||
use rustc_hir as hir;
|
||||
use rustc_middle::traits::ObligationCause;
|
||||
use rustc_middle::traits::{ObligationCause, ObligationCauseCode};
|
||||
use rustc_middle::ty::fold::BottomUpFolder;
|
||||
use rustc_middle::ty::subst::{GenericArgKind, Subst};
|
||||
use rustc_middle::ty::{
|
||||
|
@ -46,6 +46,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
|||
value: T,
|
||||
body_id: HirId,
|
||||
span: Span,
|
||||
code: ObligationCauseCode<'tcx>,
|
||||
param_env: ty::ParamEnv<'tcx>,
|
||||
) -> InferOk<'tcx, T> {
|
||||
if !value.has_opaque_types() {
|
||||
|
@ -68,10 +69,13 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
|||
) =>
|
||||
{
|
||||
let span = if span.is_dummy() { self.tcx.def_span(def_id) } else { span };
|
||||
let cause = ObligationCause::misc(span, body_id);
|
||||
let cause = ObligationCause::new(span, body_id, code.clone());
|
||||
// FIXME(compiler-errors): We probably should add a new TypeVariableOriginKind
|
||||
// for opaque types, and then use that kind to fix the spans for type errors
|
||||
// that we see later on.
|
||||
let ty_var = self.next_ty_var(TypeVariableOrigin {
|
||||
kind: TypeVariableOriginKind::TypeInference,
|
||||
span: cause.span,
|
||||
span,
|
||||
});
|
||||
obligations.extend(
|
||||
self.handle_opaque_type(ty, ty_var, true, &cause, param_env)
|
||||
|
|
|
@ -387,6 +387,9 @@ pub enum ObligationCauseCode<'tcx> {
|
|||
/// Return type of this function
|
||||
ReturnType,
|
||||
|
||||
/// Opaque return type of this function
|
||||
OpaqueReturnType(Option<(Ty<'tcx>, Span)>),
|
||||
|
||||
/// Block implicit return
|
||||
BlockTailExpression(hir::HirId),
|
||||
|
||||
|
|
|
@ -2661,6 +2661,15 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
|
|||
err.help("add `#![feature(trivial_bounds)]` to the crate attributes to enable");
|
||||
}
|
||||
}
|
||||
ObligationCauseCode::OpaqueReturnType(expr_info) => {
|
||||
if let Some((expr_ty, expr_span)) = expr_info {
|
||||
let expr_ty = self.resolve_vars_if_possible(expr_ty);
|
||||
err.span_label(
|
||||
expr_span,
|
||||
format!("return type was inferred to be `{expr_ty}` here"),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -28,6 +28,7 @@ use rustc_hir::def::DefKind;
|
|||
use rustc_hir::def_id::DefId;
|
||||
use rustc_hir::lang_items::LangItem;
|
||||
use rustc_infer::infer::resolve::OpportunisticRegionResolver;
|
||||
use rustc_infer::traits::ObligationCauseCode;
|
||||
use rustc_middle::traits::select::OverflowError;
|
||||
use rustc_middle::ty::fold::{MaxUniverse, TypeFoldable, TypeFolder, TypeSuperFoldable};
|
||||
use rustc_middle::ty::subst::Subst;
|
||||
|
@ -261,6 +262,7 @@ fn project_and_unify_type<'cx, 'tcx>(
|
|||
actual,
|
||||
obligation.cause.body_id,
|
||||
obligation.cause.span,
|
||||
ObligationCauseCode::MiscObligation,
|
||||
obligation.param_env,
|
||||
);
|
||||
obligations.extend(new);
|
||||
|
|
|
@ -101,8 +101,13 @@ pub(super) fn check_fn<'a, 'tcx>(
|
|||
declared_ret_ty,
|
||||
body.value.hir_id,
|
||||
DUMMY_SP,
|
||||
traits::ObligationCauseCode::OpaqueReturnType(None),
|
||||
param_env,
|
||||
));
|
||||
// If we replaced declared_ret_ty with infer vars, then we must be infering
|
||||
// an opaque type, so set a flag so we can improve diagnostics.
|
||||
fcx.return_type_has_opaque = ret_ty != declared_ret_ty;
|
||||
|
||||
fcx.ret_coercion = Some(RefCell::new(CoerceMany::new(ret_ty)));
|
||||
fcx.ret_type_span = Some(decl.output.span());
|
||||
|
||||
|
|
|
@ -10,6 +10,7 @@ use rustc_hir::lang_items::LangItem;
|
|||
use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
|
||||
use rustc_infer::infer::LateBoundRegionConversionTime;
|
||||
use rustc_infer::infer::{InferOk, InferResult};
|
||||
use rustc_infer::traits::ObligationCauseCode;
|
||||
use rustc_middle::ty::fold::TypeFoldable;
|
||||
use rustc_middle::ty::subst::InternalSubsts;
|
||||
use rustc_middle::ty::{self, Ty};
|
||||
|
@ -645,8 +646,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
}
|
||||
|
||||
fn hide_parent_opaque_types(&self, ty: Ty<'tcx>, span: Span, body_id: hir::HirId) -> Ty<'tcx> {
|
||||
let InferOk { value, obligations } =
|
||||
self.replace_opaque_types_with_inference_vars(ty, body_id, span, self.param_env);
|
||||
let InferOk { value, obligations } = self.replace_opaque_types_with_inference_vars(
|
||||
ty,
|
||||
body_id,
|
||||
span,
|
||||
ObligationCauseCode::MiscObligation,
|
||||
self.param_env,
|
||||
);
|
||||
self.register_predicates(obligations);
|
||||
value
|
||||
}
|
||||
|
|
|
@ -39,6 +39,7 @@ use rustc_hir::{ExprKind, HirId, QPath};
|
|||
use rustc_infer::infer;
|
||||
use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
|
||||
use rustc_infer::infer::InferOk;
|
||||
use rustc_infer::traits::ObligationCause;
|
||||
use rustc_middle::middle::stability;
|
||||
use rustc_middle::ty::adjustment::{Adjust, Adjustment, AllowTwoPhase};
|
||||
use rustc_middle::ty::error::TypeError::FieldMisMatch;
|
||||
|
@ -839,6 +840,37 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
return_expr,
|
||||
return_expr_ty,
|
||||
);
|
||||
|
||||
if self.return_type_has_opaque {
|
||||
// Point any obligations that were registered due to opaque type
|
||||
// inference at the return expression.
|
||||
self.select_obligations_where_possible(false, |errors| {
|
||||
self.point_at_return_for_opaque_ty_error(errors, span, return_expr_ty);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
fn point_at_return_for_opaque_ty_error(
|
||||
&self,
|
||||
errors: &mut Vec<traits::FulfillmentError<'tcx>>,
|
||||
span: Span,
|
||||
return_expr_ty: Ty<'tcx>,
|
||||
) {
|
||||
// Don't point at the whole block if it's empty
|
||||
if span == self.tcx.hir().span(self.body_id) {
|
||||
return;
|
||||
}
|
||||
for err in errors {
|
||||
let cause = &mut err.obligation.cause;
|
||||
if let ObligationCauseCode::OpaqueReturnType(None) = cause.code() {
|
||||
let new_cause = ObligationCause::new(
|
||||
cause.span,
|
||||
cause.body_id,
|
||||
ObligationCauseCode::OpaqueReturnType(Some((return_expr_ty, span))),
|
||||
);
|
||||
*cause = new_cause;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn check_lhs_assignable(
|
||||
|
|
|
@ -115,6 +115,9 @@ pub struct FnCtxt<'a, 'tcx> {
|
|||
/// either given explicitly or inferred from, say, an `Fn*` trait
|
||||
/// bound. Used for diagnostic purposes only.
|
||||
pub(super) return_type_pre_known: bool,
|
||||
|
||||
/// True if the return type has an Opaque type
|
||||
pub(super) return_type_has_opaque: bool,
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
|
@ -141,6 +144,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
}),
|
||||
inh,
|
||||
return_type_pre_known: true,
|
||||
return_type_has_opaque: false,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue