Skip to content

Commit 2fe936f

Browse files
committedMar 27, 2024
Stop doing expensive work in opt_suggest_box_span eagerly
1 parent 10a7aa1 commit 2fe936f

File tree

11 files changed

+217
-191
lines changed

11 files changed

+217
-191
lines changed
 

‎compiler/rustc_hir_typeck/messages.ftl

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,10 @@ hir_typeck_return_stmt_outside_of_fn_body =
122122
.encl_body_label = the {$statement_kind} is part of this body...
123123
.encl_fn_label = ...not the enclosing function body
124124
125+
hir_typeck_rpit_box_return_expr = if you change the return type to expect trait objects, box the returned expressions
126+
127+
hir_typeck_rpit_change_return_type = you could change the return type to be a boxed trait object
128+
125129
hir_typeck_rustcall_incorrect_args =
126130
functions with the "rust-call" ABI must take a single non-self tuple argument
127131

‎compiler/rustc_hir_typeck/src/_match.rs

Lines changed: 37 additions & 102 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,13 @@
11
use crate::coercion::{AsCoercionSite, CoerceMany};
22
use crate::{Diverges, Expectation, FnCtxt, Needs};
33
use rustc_errors::{Applicability, Diag};
4-
use rustc_hir::{
5-
self as hir,
6-
def::{CtorOf, DefKind, Res},
7-
ExprKind, PatKind,
8-
};
4+
use rustc_hir::def::{CtorOf, DefKind, Res};
5+
use rustc_hir::def_id::LocalDefId;
6+
use rustc_hir::{self as hir, ExprKind, PatKind};
97
use rustc_hir_pretty::ty_to_string;
108
use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
11-
use rustc_infer::traits::Obligation;
129
use rustc_middle::ty::{self, Ty};
1310
use rustc_span::Span;
14-
use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt;
1511
use rustc_trait_selection::traits::{
1612
IfExpressionCause, MatchExpressionArmCause, ObligationCause, ObligationCauseCode,
1713
};
@@ -91,10 +87,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
9187

9288
let arm_ty = self.check_expr_with_expectation(arm.body, expected);
9389
all_arms_diverge &= self.diverges.get();
94-
95-
let opt_suggest_box_span = prior_arm.and_then(|(_, prior_arm_ty, _)| {
96-
self.opt_suggest_box_span(prior_arm_ty, arm_ty, orig_expected)
97-
});
90+
let tail_defines_return_position_impl_trait =
91+
self.return_position_impl_trait_from_match_expectation(orig_expected);
9892

9993
let (arm_block_id, arm_span) = if let hir::ExprKind::Block(blk, _) = arm.body.kind {
10094
(Some(blk.hir_id), self.find_block_span(blk))
@@ -120,7 +114,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
120114
scrut_span: scrut.span,
121115
source: match_src,
122116
prior_non_diverging_arms: prior_non_diverging_arms.clone(),
123-
opt_suggest_box_span,
117+
tail_defines_return_position_impl_trait,
124118
})),
125119
),
126120
};
@@ -422,7 +416,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
422416
else_expr: &'tcx hir::Expr<'tcx>,
423417
then_ty: Ty<'tcx>,
424418
else_ty: Ty<'tcx>,
425-
opt_suggest_box_span: Option<Span>,
419+
tail_defines_return_position_impl_trait: Option<LocalDefId>,
426420
) -> ObligationCause<'tcx> {
427421
let mut outer_span = if self.tcx.sess.source_map().is_multiline(span) {
428422
// The `if`/`else` isn't in one line in the output, include some context to make it
@@ -513,7 +507,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
513507
then_ty,
514508
else_ty,
515509
outer_span,
516-
opt_suggest_box_span,
510+
tail_defines_return_position_impl_trait,
517511
})),
518512
)
519513
}
@@ -593,96 +587,37 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
593587
}
594588
}
595589

596-
/// When we have a `match` as a tail expression in a `fn` with a returned `impl Trait`
597-
/// we check if the different arms would work with boxed trait objects instead and
598-
/// provide a structured suggestion in that case.
599-
pub(crate) fn opt_suggest_box_span(
590+
// Does the expectation of the match define an RPIT?
591+
// (e.g. we're in the tail of a function body)
592+
//
593+
// Returns the `LocalDefId` of the RPIT, which is always identity-substituted.
594+
pub fn return_position_impl_trait_from_match_expectation(
600595
&self,
601-
first_ty: Ty<'tcx>,
602-
second_ty: Ty<'tcx>,
603-
orig_expected: Expectation<'tcx>,
604-
) -> Option<Span> {
605-
// FIXME(compiler-errors): This really shouldn't need to be done during the
606-
// "good" path of typeck, but here we are.
607-
match orig_expected {
608-
Expectation::ExpectHasType(expected) => {
609-
let TypeVariableOrigin {
610-
span,
611-
kind: TypeVariableOriginKind::OpaqueTypeInference(rpit_def_id),
612-
..
613-
} = self.type_var_origin(expected)?
614-
else {
615-
return None;
616-
};
617-
618-
let Some(rpit_local_def_id) = rpit_def_id.as_local() else {
619-
return None;
620-
};
621-
if !matches!(
622-
self.tcx.hir().expect_item(rpit_local_def_id).expect_opaque_ty().origin,
623-
hir::OpaqueTyOrigin::FnReturn(..)
624-
) {
625-
return None;
626-
}
627-
628-
let sig = self.body_fn_sig()?;
629-
630-
let args = sig.output().walk().find_map(|arg| {
631-
if let ty::GenericArgKind::Type(ty) = arg.unpack()
632-
&& let ty::Alias(ty::Opaque, ty::AliasTy { def_id, args, .. }) = *ty.kind()
633-
&& def_id == rpit_def_id
634-
{
635-
Some(args)
636-
} else {
637-
None
638-
}
639-
})?;
640-
641-
if !self.can_coerce(first_ty, expected) || !self.can_coerce(second_ty, expected) {
642-
return None;
643-
}
644-
645-
for ty in [first_ty, second_ty] {
646-
for (clause, _) in self
647-
.tcx
648-
.explicit_item_super_predicates(rpit_def_id)
649-
.iter_instantiated_copied(self.tcx, args)
650-
{
651-
let pred = clause.kind().rebind(match clause.kind().skip_binder() {
652-
ty::ClauseKind::Trait(trait_pred) => {
653-
assert!(matches!(
654-
*trait_pred.trait_ref.self_ty().kind(),
655-
ty::Alias(ty::Opaque, ty::AliasTy { def_id, args: alias_args, .. })
656-
if def_id == rpit_def_id && args == alias_args
657-
));
658-
ty::ClauseKind::Trait(trait_pred.with_self_ty(self.tcx, ty))
659-
}
660-
ty::ClauseKind::Projection(mut proj_pred) => {
661-
assert!(matches!(
662-
*proj_pred.projection_ty.self_ty().kind(),
663-
ty::Alias(ty::Opaque, ty::AliasTy { def_id, args: alias_args, .. })
664-
if def_id == rpit_def_id && args == alias_args
665-
));
666-
proj_pred = proj_pred.with_self_ty(self.tcx, ty);
667-
ty::ClauseKind::Projection(proj_pred)
668-
}
669-
_ => continue,
670-
});
671-
if !self.predicate_must_hold_modulo_regions(&Obligation::new(
672-
self.tcx,
673-
ObligationCause::misc(span, self.body_id),
674-
self.param_env,
675-
pred,
676-
)) {
677-
return None;
678-
}
679-
}
680-
}
681-
682-
Some(span)
683-
}
684-
_ => None,
596+
expectation: Expectation<'tcx>,
597+
) -> Option<LocalDefId> {
598+
let expected_ty = expectation.to_option(self)?;
599+
let (def_id, args) = match *expected_ty.kind() {
600+
// FIXME: Could also check that the RPIT is not defined
601+
ty::Alias(ty::Opaque, alias_ty) => (alias_ty.def_id.as_local()?, alias_ty.args),
602+
// FIXME(-Znext-solver): Remove this branch once `replace_opaque_types_with_infer` is gone.
603+
ty::Infer(ty::TyVar(_)) => self
604+
.inner
605+
.borrow()
606+
.iter_opaque_types()
607+
.find(|(_, v)| v.ty == expected_ty)
608+
.map(|(k, _)| (k.def_id, k.args))?,
609+
_ => return None,
610+
};
611+
let hir::OpaqueTyOrigin::FnReturn(parent_def_id) = self.tcx.opaque_type_origin(def_id)
612+
else {
613+
return None;
614+
};
615+
if &args[0..self.tcx.generics_of(parent_def_id).count()]
616+
!= ty::GenericArgs::identity_for_item(self.tcx, parent_def_id).as_slice()
617+
{
618+
return None;
685619
}
620+
Some(def_id)
686621
}
687622
}
688623

‎compiler/rustc_hir_typeck/src/coercion.rs

Lines changed: 139 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,17 +35,18 @@
3535
//! // and are then unable to coerce `&7i32` to `&mut i32`.
3636
//! ```
3737
38+
use crate::errors::SuggestBoxingForReturnImplTrait;
3839
use crate::FnCtxt;
3940
use rustc_errors::{codes::*, struct_span_code_err, Applicability, Diag, MultiSpan};
4041
use rustc_hir as hir;
41-
use rustc_hir::def_id::DefId;
42+
use rustc_hir::def_id::{DefId, LocalDefId};
4243
use rustc_hir::intravisit::{self, Visitor};
4344
use rustc_hir::Expr;
4445
use rustc_hir_analysis::hir_ty_lowering::HirTyLowerer;
4546
use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
4647
use rustc_infer::infer::{Coercion, DefineOpaqueTypes, InferOk, InferResult};
47-
use rustc_infer::traits::TraitEngine;
4848
use rustc_infer::traits::TraitEngineExt as _;
49+
use rustc_infer::traits::{IfExpressionCause, MatchExpressionArmCause, TraitEngine};
4950
use rustc_infer::traits::{Obligation, PredicateObligation};
5051
use rustc_middle::lint::in_external_macro;
5152
use rustc_middle::traits::BuiltinImplSource;
@@ -59,6 +60,7 @@ use rustc_middle::ty::{self, GenericArgsRef, Ty, TyCtxt};
5960
use rustc_session::parse::feature_err;
6061
use rustc_span::symbol::sym;
6162
use rustc_span::DesugaringKind;
63+
use rustc_span::{BytePos, Span};
6264
use rustc_target::spec::abi::Abi;
6365
use rustc_trait_selection::infer::InferCtxtExt as _;
6466
use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt as _;
@@ -1638,6 +1640,77 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> {
16381640
unsized_return = self.is_return_ty_definitely_unsized(fcx);
16391641
}
16401642
}
1643+
ObligationCauseCode::MatchExpressionArm(box MatchExpressionArmCause {
1644+
arm_span,
1645+
arm_ty,
1646+
prior_arm_ty,
1647+
ref prior_non_diverging_arms,
1648+
tail_defines_return_position_impl_trait: Some(rpit_def_id),
1649+
..
1650+
}) => {
1651+
err = fcx.err_ctxt().report_mismatched_types(
1652+
cause,
1653+
expected,
1654+
found,
1655+
coercion_error,
1656+
);
1657+
// Check that we're actually in the second or later arm
1658+
if prior_non_diverging_arms.len() > 0 {
1659+
self.suggest_boxing_tail_for_return_position_impl_trait(
1660+
fcx,
1661+
&mut err,
1662+
rpit_def_id,
1663+
arm_ty,
1664+
prior_arm_ty,
1665+
prior_non_diverging_arms
1666+
.iter()
1667+
.chain(std::iter::once(&arm_span))
1668+
.copied(),
1669+
);
1670+
}
1671+
}
1672+
ObligationCauseCode::IfExpression(box IfExpressionCause {
1673+
then_id,
1674+
else_id,
1675+
then_ty,
1676+
else_ty,
1677+
tail_defines_return_position_impl_trait: Some(rpit_def_id),
1678+
..
1679+
}) => {
1680+
err = fcx.err_ctxt().report_mismatched_types(
1681+
cause,
1682+
expected,
1683+
found,
1684+
coercion_error,
1685+
);
1686+
let then_span = fcx.find_block_span_from_hir_id(then_id);
1687+
let else_span = fcx.find_block_span_from_hir_id(else_id);
1688+
// don't suggest wrapping either blocks in `if .. {} else {}`
1689+
let is_empty_arm = |id| {
1690+
let hir::Node::Block(blk) = fcx.tcx.hir_node(id) else {
1691+
return false;
1692+
};
1693+
if blk.expr.is_some() || !blk.stmts.is_empty() {
1694+
return false;
1695+
}
1696+
let Some((_, hir::Node::Expr(expr))) =
1697+
fcx.tcx.hir().parent_iter(id).nth(1)
1698+
else {
1699+
return false;
1700+
};
1701+
matches!(expr.kind, hir::ExprKind::If(..))
1702+
};
1703+
if !is_empty_arm(then_id) && !is_empty_arm(else_id) {
1704+
self.suggest_boxing_tail_for_return_position_impl_trait(
1705+
fcx,
1706+
&mut err,
1707+
rpit_def_id,
1708+
then_ty,
1709+
else_ty,
1710+
[then_span, else_span].into_iter(),
1711+
);
1712+
}
1713+
}
16411714
_ => {
16421715
err = fcx.err_ctxt().report_mismatched_types(
16431716
cause,
@@ -1677,6 +1750,70 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> {
16771750
}
16781751
}
16791752

1753+
fn suggest_boxing_tail_for_return_position_impl_trait(
1754+
&self,
1755+
fcx: &FnCtxt<'_, 'tcx>,
1756+
err: &mut Diag<'_>,
1757+
rpit_def_id: LocalDefId,
1758+
a_ty: Ty<'tcx>,
1759+
b_ty: Ty<'tcx>,
1760+
arm_spans: impl Iterator<Item = Span>,
1761+
) {
1762+
let compatible = |ty: Ty<'tcx>| {
1763+
fcx.probe(|_| {
1764+
let ocx = ObligationCtxt::new(fcx);
1765+
ocx.register_obligations(
1766+
fcx.tcx
1767+
.item_super_predicates(rpit_def_id)
1768+
.instantiate_identity_iter()
1769+
.filter_map(|clause| {
1770+
let predicate = clause
1771+
.kind()
1772+
.map_bound(|clause| match clause {
1773+
ty::ClauseKind::Trait(trait_pred) => Some(
1774+
ty::ClauseKind::Trait(trait_pred.with_self_ty(fcx.tcx, ty)),
1775+
),
1776+
ty::ClauseKind::Projection(proj_pred) => {
1777+
Some(ty::ClauseKind::Projection(
1778+
proj_pred.with_self_ty(fcx.tcx, ty),
1779+
))
1780+
}
1781+
_ => None,
1782+
})
1783+
.transpose()?;
1784+
Some(Obligation::new(
1785+
fcx.tcx,
1786+
ObligationCause::dummy(),
1787+
fcx.param_env,
1788+
predicate,
1789+
))
1790+
}),
1791+
);
1792+
ocx.select_where_possible().is_empty()
1793+
})
1794+
};
1795+
1796+
if !compatible(a_ty) || !compatible(b_ty) {
1797+
return;
1798+
}
1799+
1800+
let rpid_def_span = fcx.tcx.def_span(rpit_def_id);
1801+
err.subdiagnostic(
1802+
fcx.tcx.dcx(),
1803+
SuggestBoxingForReturnImplTrait::ChangeReturnType {
1804+
start_sp: rpid_def_span.with_hi(rpid_def_span.lo() + BytePos(4)),
1805+
end_sp: rpid_def_span.shrink_to_hi(),
1806+
},
1807+
);
1808+
1809+
let (starts, ends) =
1810+
arm_spans.map(|span| (span.shrink_to_lo(), span.shrink_to_hi())).unzip();
1811+
err.subdiagnostic(
1812+
fcx.tcx.dcx(),
1813+
SuggestBoxingForReturnImplTrait::BoxReturnExpr { starts, ends },
1814+
);
1815+
}
1816+
16801817
fn note_unreachable_loop_return(
16811818
&self,
16821819
err: &mut Diag<'_>,

‎compiler/rustc_hir_typeck/src/errors.rs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -621,3 +621,21 @@ pub struct NoteCallerChoosesTyForTyParam<'tcx> {
621621
pub ty_param_name: Symbol,
622622
pub found_ty: Ty<'tcx>,
623623
}
624+
625+
#[derive(Subdiagnostic)]
626+
pub enum SuggestBoxingForReturnImplTrait {
627+
#[multipart_suggestion(hir_typeck_rpit_change_return_type, applicability = "maybe-incorrect")]
628+
ChangeReturnType {
629+
#[suggestion_part(code = "Box<dyn")]
630+
start_sp: Span,
631+
#[suggestion_part(code = ">")]
632+
end_sp: Span,
633+
},
634+
#[multipart_suggestion(hir_typeck_rpit_box_return_expr, applicability = "maybe-incorrect")]
635+
BoxReturnExpr {
636+
#[suggestion_part(code = "Box::new(")]
637+
starts: Vec<Span>,
638+
#[suggestion_part(code = ")")]
639+
ends: Vec<Span>,
640+
},
641+
}

‎compiler/rustc_hir_typeck/src/expr.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1088,15 +1088,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
10881088
let else_ty = self.check_expr_with_expectation(else_expr, expected);
10891089
let else_diverges = self.diverges.get();
10901090

1091-
let opt_suggest_box_span = self.opt_suggest_box_span(then_ty, else_ty, orig_expected);
1091+
let tail_defines_return_position_impl_trait =
1092+
self.return_position_impl_trait_from_match_expectation(orig_expected);
10921093
let if_cause = self.if_cause(
10931094
sp,
10941095
cond_expr.span,
10951096
then_expr,
10961097
else_expr,
10971098
then_ty,
10981099
else_ty,
1099-
opt_suggest_box_span,
1100+
tail_defines_return_position_impl_trait,
11001101
);
11011102

11021103
coerce.coerce(self, &if_cause, else_expr, else_ty);

‎compiler/rustc_infer/messages.ftl

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -270,9 +270,6 @@ infer_ril_introduced_by = requirement introduced by this return type
270270
infer_ril_introduced_here = `'static` requirement introduced here
271271
infer_ril_static_introduced_by = "`'static` lifetime requirement introduced by the return type
272272
273-
infer_sbfrit_box_return_expr = if you change the return type to expect trait objects, box the returned expressions
274-
275-
infer_sbfrit_change_return_type = you could change the return type to be a boxed trait object
276273
infer_source_kind_closure_return =
277274
try giving this closure an explicit return type
278275

‎compiler/rustc_infer/src/errors/mod.rs

Lines changed: 0 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1262,24 +1262,6 @@ pub enum SuggestAccessingField<'a> {
12621262
},
12631263
}
12641264

1265-
#[derive(Subdiagnostic)]
1266-
pub enum SuggestBoxingForReturnImplTrait {
1267-
#[multipart_suggestion(infer_sbfrit_change_return_type, applicability = "maybe-incorrect")]
1268-
ChangeReturnType {
1269-
#[suggestion_part(code = "Box<dyn")]
1270-
start_sp: Span,
1271-
#[suggestion_part(code = ">")]
1272-
end_sp: Span,
1273-
},
1274-
#[multipart_suggestion(infer_sbfrit_box_return_expr, applicability = "maybe-incorrect")]
1275-
BoxReturnExpr {
1276-
#[suggestion_part(code = "Box::new(")]
1277-
starts: Vec<Span>,
1278-
#[suggestion_part(code = ")")]
1279-
ends: Vec<Span>,
1280-
},
1281-
}
1282-
12831265
#[derive(Subdiagnostic)]
12841266
#[multipart_suggestion(infer_stp_wrap_one, applicability = "maybe-incorrect")]
12851267
pub struct SuggestTuplePatternOne {

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

Lines changed: 1 addition & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -784,7 +784,6 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
784784
prior_arm_ty,
785785
source,
786786
ref prior_non_diverging_arms,
787-
opt_suggest_box_span,
788787
scrut_span,
789788
..
790789
}) => match source {
@@ -853,17 +852,6 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
853852
) {
854853
err.subdiagnostic(self.dcx(), subdiag);
855854
}
856-
if let Some(ret_sp) = opt_suggest_box_span {
857-
// Get return type span and point to it.
858-
self.suggest_boxing_for_return_impl_trait(
859-
err,
860-
ret_sp,
861-
prior_non_diverging_arms
862-
.iter()
863-
.chain(std::iter::once(&arm_span))
864-
.copied(),
865-
);
866-
}
867855
}
868856
},
869857
ObligationCauseCode::IfExpression(box IfExpressionCause {
@@ -872,7 +860,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
872860
then_ty,
873861
else_ty,
874862
outer_span,
875-
opt_suggest_box_span,
863+
..
876864
}) => {
877865
let then_span = self.find_block_span_from_hir_id(then_id);
878866
let else_span = self.find_block_span_from_hir_id(else_id);
@@ -890,30 +878,6 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
890878
) {
891879
err.subdiagnostic(self.dcx(), subdiag);
892880
}
893-
// don't suggest wrapping either blocks in `if .. {} else {}`
894-
let is_empty_arm = |id| {
895-
let hir::Node::Block(blk) = self.tcx.hir_node(id) else {
896-
return false;
897-
};
898-
if blk.expr.is_some() || !blk.stmts.is_empty() {
899-
return false;
900-
}
901-
let Some((_, hir::Node::Expr(expr))) = self.tcx.hir().parent_iter(id).nth(1)
902-
else {
903-
return false;
904-
};
905-
matches!(expr.kind, hir::ExprKind::If(..))
906-
};
907-
if let Some(ret_sp) = opt_suggest_box_span
908-
&& !is_empty_arm(then_id)
909-
&& !is_empty_arm(else_id)
910-
{
911-
self.suggest_boxing_for_return_impl_trait(
912-
err,
913-
ret_sp,
914-
[then_span, else_span].into_iter(),
915-
);
916-
}
917881
}
918882
ObligationCauseCode::LetElse => {
919883
err.help("try adding a diverging expression, such as `return` or `panic!(..)`");

‎compiler/rustc_infer/src/infer/error_reporting/suggest.rs

Lines changed: 2 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,8 @@ use rustc_span::{sym, BytePos, Span};
1919

2020
use crate::errors::{
2121
ConsiderAddingAwait, FnConsiderCasting, FnItemsAreDistinct, FnUniqTypes,
22-
FunctionPointerSuggestion, SuggestAccessingField, SuggestBoxingForReturnImplTrait,
23-
SuggestRemoveSemiOrReturnBinding, SuggestTuplePatternMany, SuggestTuplePatternOne,
24-
TypeErrorAdditionalDiags,
22+
FunctionPointerSuggestion, SuggestAccessingField, SuggestRemoveSemiOrReturnBinding,
23+
SuggestTuplePatternMany, SuggestTuplePatternOne, TypeErrorAdditionalDiags,
2524
};
2625

2726
use super::TypeErrCtxt;
@@ -80,28 +79,6 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
8079
}
8180
}
8281

83-
pub(super) fn suggest_boxing_for_return_impl_trait(
84-
&self,
85-
err: &mut Diag<'_>,
86-
return_sp: Span,
87-
arm_spans: impl Iterator<Item = Span>,
88-
) {
89-
let sugg = SuggestBoxingForReturnImplTrait::ChangeReturnType {
90-
start_sp: return_sp.with_hi(return_sp.lo() + BytePos(4)),
91-
end_sp: return_sp.shrink_to_hi(),
92-
};
93-
err.subdiagnostic(self.dcx(), sugg);
94-
95-
let mut starts = Vec::new();
96-
let mut ends = Vec::new();
97-
for span in arm_spans {
98-
starts.push(span.shrink_to_lo());
99-
ends.push(span.shrink_to_hi());
100-
}
101-
let sugg = SuggestBoxingForReturnImplTrait::BoxReturnExpr { starts, ends };
102-
err.subdiagnostic(self.dcx(), sugg);
103-
}
104-
10582
pub(super) fn suggest_tuple_pattern(
10683
&self,
10784
cause: &ObligationCause<'tcx>,

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

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -229,6 +229,15 @@ impl<'tcx> InferCtxtInner<'tcx> {
229229
.expect("region constraints already solved")
230230
.with_log(&mut self.undo_log)
231231
}
232+
233+
// Iterates through the opaque type definitions without taking them; this holds the
234+
// `InferCtxtInner` lock, so make sure to not do anything with `InferCtxt` side-effects
235+
// while looping through this.
236+
pub fn iter_opaque_types(
237+
&self,
238+
) -> impl Iterator<Item = (ty::OpaqueTypeKey<'tcx>, ty::OpaqueHiddenType<'tcx>)> + '_ {
239+
self.opaque_type_storage.opaque_types.iter().map(|(&k, v)| (k, v.hidden_type))
240+
}
232241
}
233242

234243
pub struct InferCtxt<'tcx> {

‎compiler/rustc_middle/src/traits/mod.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -571,7 +571,8 @@ pub struct MatchExpressionArmCause<'tcx> {
571571
pub scrut_span: Span,
572572
pub source: hir::MatchSource,
573573
pub prior_non_diverging_arms: Vec<Span>,
574-
pub opt_suggest_box_span: Option<Span>,
574+
// Is the expectation of this match expression an RPIT?
575+
pub tail_defines_return_position_impl_trait: Option<LocalDefId>,
575576
}
576577

577578
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
@@ -582,7 +583,8 @@ pub struct IfExpressionCause<'tcx> {
582583
pub then_ty: Ty<'tcx>,
583584
pub else_ty: Ty<'tcx>,
584585
pub outer_span: Option<Span>,
585-
pub opt_suggest_box_span: Option<Span>,
586+
// Is the expectation of this match expression an RPIT?
587+
pub tail_defines_return_position_impl_trait: Option<LocalDefId>,
586588
}
587589

588590
#[derive(Clone, Debug, PartialEq, Eq, HashStable, TyEncodable, TyDecodable)]

0 commit comments

Comments
 (0)
Please sign in to comment.