Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Miscellaneous HIR typeck nits #114396

Merged
merged 4 commits into from
Aug 3, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 4 additions & 16 deletions compiler/rustc_hir_typeck/src/_match.rs
Original file line number Diff line number Diff line change
Expand Up @@ -136,15 +136,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
&cause,
Some(&arm.body),
arm_ty,
Some(&mut |err| {
self.suggest_removing_semicolon_for_coerce(
err,
expr,
orig_expected,
arm_ty,
prior_arm,
)
}),
|err| self.suggest_removing_semicolon_for_coerce(err, expr, arm_ty, prior_arm),
false,
);

Expand Down Expand Up @@ -181,7 +173,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
&self,
diag: &mut Diagnostic,
expr: &hir::Expr<'tcx>,
expectation: Expectation<'tcx>,
arm_ty: Ty<'tcx>,
prior_arm: Option<(Option<hir::HirId>, Ty<'tcx>, Span)>,
) {
Expand All @@ -195,7 +186,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let hir::ExprKind::Block(block, _) = body.value.kind else {
return;
};
let Some(hir::Stmt { kind: hir::StmtKind::Semi(last_expr), .. }) =
let Some(hir::Stmt { kind: hir::StmtKind::Semi(last_expr), span: semi_span, .. }) =
block.innermost_block().stmts.last()
else {
return;
Expand All @@ -212,9 +203,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
else {
return;
};
let Expectation::IsLast(stmt) = expectation else {
return;
};

let can_coerce_to_return_ty = match self.ret_coercion.as_ref() {
Some(ret_coercion) => {
Expand All @@ -231,7 +219,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
return;
}

let semi_span = expr.span.shrink_to_hi().with_hi(stmt.hi());
let semi_span = expr.span.shrink_to_hi().with_hi(semi_span.hi());
let mut ret_span: MultiSpan = semi_span.into();
ret_span.push_span_label(
expr.span,
Expand Down Expand Up @@ -279,7 +267,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
coercion.coerce_forced_unit(
self,
&cause,
&mut |err| {
|err| {
if let Some((span, msg)) = &ret_reason {
err.span_label(*span, msg.clone());
} else if let ExprKind::Block(block, _) = &then_expr.kind
Expand Down
12 changes: 5 additions & 7 deletions compiler/rustc_hir_typeck/src/coercion.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1418,7 +1418,7 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> {
expression: &'tcx hir::Expr<'tcx>,
expression_ty: Ty<'tcx>,
) {
self.coerce_inner(fcx, cause, Some(expression), expression_ty, None, false)
self.coerce_inner(fcx, cause, Some(expression), expression_ty, |_| {}, false)
}

/// Indicates that one of the inputs is a "forced unit". This
Expand All @@ -1437,15 +1437,15 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> {
&mut self,
fcx: &FnCtxt<'a, 'tcx>,
cause: &ObligationCause<'tcx>,
augment_error: &mut dyn FnMut(&mut Diagnostic),
augment_error: impl FnOnce(&mut Diagnostic),
label_unit_as_expected: bool,
) {
self.coerce_inner(
fcx,
cause,
None,
Ty::new_unit(fcx.tcx),
Some(augment_error),
augment_error,
label_unit_as_expected,
)
}
Expand All @@ -1460,7 +1460,7 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> {
cause: &ObligationCause<'tcx>,
expression: Option<&'tcx hir::Expr<'tcx>>,
mut expression_ty: Ty<'tcx>,
augment_error: Option<&mut dyn FnMut(&mut Diagnostic)>,
augment_error: impl FnOnce(&mut Diagnostic),
label_expression_as_expected: bool,
) {
// Incorporate whatever type inference information we have
Expand Down Expand Up @@ -1639,9 +1639,7 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> {
}
}

if let Some(augment_error) = augment_error {
augment_error(&mut err);
}
augment_error(&mut err);

let is_insufficiently_polymorphic =
matches!(coercion_error, TypeError::RegionsInsufficientlyPolymorphic(..));
Expand Down
9 changes: 2 additions & 7 deletions compiler/rustc_hir_typeck/src/expectation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,6 @@ pub enum Expectation<'tcx> {
/// This rvalue expression will be wrapped in `&` or `Box` and coerced
/// to `&Ty` or `Box<Ty>`, respectively. `Ty` is `[A]` or `Trait`.
ExpectRvalueLikeUnsized(Ty<'tcx>),

IsLast(Span),
}

impl<'a, 'tcx> Expectation<'tcx> {
Expand Down Expand Up @@ -88,13 +86,12 @@ impl<'a, 'tcx> Expectation<'tcx> {
ExpectCastableToType(t) => ExpectCastableToType(fcx.resolve_vars_if_possible(t)),
ExpectHasType(t) => ExpectHasType(fcx.resolve_vars_if_possible(t)),
ExpectRvalueLikeUnsized(t) => ExpectRvalueLikeUnsized(fcx.resolve_vars_if_possible(t)),
IsLast(sp) => IsLast(sp),
}
}

pub(super) fn to_option(self, fcx: &FnCtxt<'a, 'tcx>) -> Option<Ty<'tcx>> {
match self.resolve(fcx) {
NoExpectation | IsLast(_) => None,
NoExpectation => None,
ExpectCastableToType(ty) | ExpectHasType(ty) | ExpectRvalueLikeUnsized(ty) => Some(ty),
}
}
Expand All @@ -106,9 +103,7 @@ impl<'a, 'tcx> Expectation<'tcx> {
pub(super) fn only_has_type(self, fcx: &FnCtxt<'a, 'tcx>) -> Option<Ty<'tcx>> {
match self {
ExpectHasType(ty) => Some(fcx.resolve_vars_if_possible(ty)),
NoExpectation | ExpectCastableToType(_) | ExpectRvalueLikeUnsized(_) | IsLast(_) => {
None
}
NoExpectation | ExpectCastableToType(_) | ExpectRvalueLikeUnsized(_) => None,
}
}

Expand Down
34 changes: 10 additions & 24 deletions compiler/rustc_hir_typeck/src/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,28 +60,13 @@ use rustc_trait_selection::traits::ObligationCtxt;
use rustc_trait_selection::traits::{self, ObligationCauseCode};

impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
fn check_expr_eq_type(&self, expr: &'tcx hir::Expr<'tcx>, expected: Ty<'tcx>) {
let ty = self.check_expr_with_hint(expr, expected);
self.demand_eqtype(expr.span, expected, ty);
}

pub fn check_expr_has_type_or_error(
&self,
expr: &'tcx hir::Expr<'tcx>,
expected: Ty<'tcx>,
extend_err: impl FnMut(&mut Diagnostic),
) -> Ty<'tcx> {
self.check_expr_meets_expectation_or_error(expr, ExpectHasType(expected), extend_err)
}

fn check_expr_meets_expectation_or_error(
&self,
expr: &'tcx hir::Expr<'tcx>,
expected: Expectation<'tcx>,
mut extend_err: impl FnMut(&mut Diagnostic),
expected_ty: Ty<'tcx>,
extend_err: impl FnOnce(&mut Diagnostic),
) -> Ty<'tcx> {
let expected_ty = expected.to_option(&self).unwrap_or(self.tcx.types.bool);
let mut ty = self.check_expr_with_expectation(expr, expected);
let mut ty = self.check_expr_with_expectation(expr, ExpectHasType(expected_ty));

// While we don't allow *arbitrary* coercions here, we *do* allow
// coercions from ! to `expected`.
Expand Down Expand Up @@ -341,9 +326,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}
ExprKind::Cast(e, t) => self.check_expr_cast(e, t, expr),
ExprKind::Type(e, t) => {
let ty = self.to_ty_saving_user_provided_ty(&t);
self.check_expr_eq_type(&e, ty);
ty
let ascribed_ty = self.to_ty_saving_user_provided_ty(&t);
let ty = self.check_expr_with_hint(e, ascribed_ty);
self.demand_eqtype(e.span, ascribed_ty, ty);
ascribed_ty
}
ExprKind::If(cond, then_expr, opt_else_expr) => {
self.check_then_else(cond, then_expr, opt_else_expr, expr.span, expected)
Expand Down Expand Up @@ -666,7 +652,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
coerce.coerce_forced_unit(
self,
&cause,
&mut |mut err| {
|mut err| {
self.suggest_mismatched_types_on_tail(
&mut err, expr, ty, e_ty, target_id,
);
Expand Down Expand Up @@ -762,7 +748,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
coercion.coerce_forced_unit(
self,
&cause,
&mut |db| {
|db| {
let span = fn_decl.output.span();
if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span) {
db.span_label(
Expand All @@ -774,7 +760,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
true,
);
} else {
coercion.coerce_forced_unit(self, &cause, &mut |_| (), true);
coercion.coerce_forced_unit(self, &cause, |_| (), true);
}
}
self.tcx.types.never
Expand Down
21 changes: 7 additions & 14 deletions compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1485,7 +1485,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
self.check_decl(local.into());
}

pub fn check_stmt(&self, stmt: &'tcx hir::Stmt<'tcx>, is_last: bool) {
pub fn check_stmt(&self, stmt: &'tcx hir::Stmt<'tcx>) {
// Don't do all the complex logic below for `DeclItem`.
match stmt.kind {
hir::StmtKind::Item(..) => return,
Expand All @@ -1512,14 +1512,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
});
}
hir::StmtKind::Semi(ref expr) => {
// All of this is equivalent to calling `check_expr`, but it is inlined out here
// in order to capture the fact that this `match` is the last statement in its
// function. This is done for better suggestions to remove the `;`.
let expectation = match expr.kind {
hir::ExprKind::Match(..) if is_last => IsLast(stmt.span),
_ => NoExpectation,
};
self.check_expr_with_expectation(expr, expectation);
self.check_expr(expr);
}
}

Expand Down Expand Up @@ -1570,8 +1563,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let ctxt = BreakableCtxt { coerce: Some(coerce), may_break: false };

let (ctxt, ()) = self.with_breakable_ctxt(blk.hir_id, ctxt, || {
for (pos, s) in blk.stmts.iter().enumerate() {
self.check_stmt(s, blk.stmts.len() - 1 == pos);
for s in blk.stmts {
self.check_stmt(s);
}

// check the tail expression **without** holding the
Expand All @@ -1594,9 +1587,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
&cause,
Some(tail_expr),
tail_expr_ty,
Some(&mut |diag: &mut Diagnostic| {
|diag| {
self.suggest_block_to_brackets(diag, blk, tail_expr_ty, ty_for_diagnostic);
}),
},
false,
);
} else {
Expand Down Expand Up @@ -1633,7 +1626,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
coerce.coerce_forced_unit(
self,
&self.misc(sp),
&mut |err| {
|err| {
if let Some(expected_ty) = expected.only_has_type(self) {
if blk.stmts.is_empty() && blk.expr.is_none() {
self.suggest_boxing_when_appropriate(
Expand Down