use crate::cast;
use crate::coercion::CoerceMany;
use crate::coercion::DynamicCoerceMany;
+use crate::errors::TypeMismatchFruTypo;
use crate::errors::{AddressOfTemporaryTaken, ReturnStmtOutsideOfFnBody, StructExprNonExhaustive};
use crate::errors::{
FieldMultiplySpecifiedInInitializer, FunctionalRecordUpdateOnNonStruct,
use rustc_hir::def_id::DefId;
use rustc_hir::intravisit::Visitor;
use rustc_hir::lang_items::LangItem;
-use rustc_hir::{Closure, ExprKind, HirId, QPath};
+use rustc_hir::{ExprKind, HirId, QPath};
use rustc_hir_analysis::astconv::AstConv as _;
use rustc_hir_analysis::check::ty_kind_suggestion;
use rustc_infer::infer;
ExprKind::Match(discrim, arms, match_src) => {
self.check_match(expr, &discrim, arms, expected, match_src)
}
- ExprKind::Closure(&Closure { capture_clause, fn_decl, body, movability, .. }) => {
- self.check_expr_closure(expr, capture_clause, &fn_decl, body, movability, expected)
- }
+ ExprKind::Closure(closure) => self.check_expr_closure(closure, expr.span, expected),
ExprKind::Block(body, _) => self.check_block_with_expected(&body, expected),
ExprKind::Call(callee, args) => self.check_call(expr, &callee, args, expected),
ExprKind::MethodCall(segment, receiver, args, _) => {
self.resolve_ty_and_res_fully_qualified_call(qpath, expr.hir_id, expr.span);
let ty = match res {
Res::Err => {
- self.set_tainted_by_errors();
- tcx.ty_error()
+ let e =
+ self.tcx.sess.delay_span_bug(qpath.span(), "`Res::Err` but no error emitted");
+ self.set_tainted_by_errors(e);
+ tcx.ty_error_with_guaranteed(e)
}
Res::Def(DefKind::Ctor(_, CtorKind::Fictive), _) => {
- report_unexpected_variant_res(tcx, res, qpath, expr.span);
- tcx.ty_error()
+ let e = report_unexpected_variant_res(tcx, res, qpath, expr.span);
+ tcx.ty_error_with_guaranteed(e)
}
_ => self.instantiate_value_path(segs, opt_ty, res, expr.span, expr.hir_id).0,
};
self.demand_coerce_diag(&field.expr, ty, field_type, None, AllowTwoPhase::No);
if let Some(mut diag) = diag {
- if idx == ast_fields.len() - 1 && remaining_fields.is_empty() {
- self.suggest_fru_from_range(field, variant, substs, &mut diag);
+ if idx == ast_fields.len() - 1 {
+ if remaining_fields.is_empty() {
+ self.suggest_fru_from_range(field, variant, substs, &mut diag);
+ diag.emit();
+ } else {
+ diag.stash(field.span, StashKey::MaybeFruTypo);
+ }
+ } else {
+ diag.emit();
}
- diag.emit();
}
}
.map(|adt| adt.did())
!= range_def_id
{
- let instead = self
+ // Suppress any range expr type mismatches
+ if let Some(mut diag) = self
+ .tcx
+ .sess
+ .diagnostic()
+ .steal_diagnostic(last_expr_field.span, StashKey::MaybeFruTypo)
+ {
+ diag.delay_as_bug();
+ }
+
+ // Use a (somewhat arbitrary) filtering heuristic to avoid printing
+ // expressions that are either too long, or have control character
+ //such as newlines in them.
+ let expr = self
.tcx
.sess
.source_map()
.span_to_snippet(range_end.expr.span)
- .map(|s| format!(" from `{s}`"))
- .unwrap_or_default();
- err.span_suggestion(
- range_start.span.shrink_to_hi(),
- &format!("to set the remaining fields{instead}, separate the last named field with a comma"),
- ",",
- Applicability::MaybeIncorrect,
- );
+ .ok()
+ .filter(|s| s.len() < 25 && !s.contains(|c: char| c.is_control()));
+
+ let fru_span = self
+ .tcx
+ .sess
+ .source_map()
+ .span_extend_while(range_start.span, |c| c.is_whitespace())
+ .unwrap_or(range_start.span).shrink_to_hi().to(range_end.span);
+
+ err.subdiagnostic(TypeMismatchFruTypo {
+ expr_span: range_start.span,
+ fru_span,
+ expr,
+ });
}
}
expr_span: Span,
) {
if variant.is_recovered() {
- self.set_tainted_by_errors();
+ self.set_tainted_by_errors(
+ self.tcx
+ .sess
+ .delay_span_bug(expr_span, "parser recovered but no error was emitted"),
+ );
return;
}
let mut err = self.err_ctxt().type_error_struct_with_diag(