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;
+use rustc_middle::ty::error::{
+ ExpectedFound,
+ TypeError::{FieldMisMatch, Sorts},
+};
use rustc_middle::ty::GenericArgsRef;
use rustc_middle::ty::{self, AdtKind, Ty, TypeVisitableExt};
use rustc_session::errors::ExprParenthesesNeeded;
_ => self.instantiate_value_path(segs, opt_ty, res, expr.span, expr.hir_id).0,
};
- if let ty::FnDef(did, ..) = *ty.kind() {
+ if let ty::FnDef(did, callee_args) = *ty.kind() {
let fn_sig = ty.fn_sig(tcx);
+
+ // HACK: whenever we get a FnDef in a non-const context, enforce effects to get the
+ // default `host = true` to avoid inference errors later.
+ if tcx.hir().body_const_context(self.body_id).is_none() {
+ self.enforce_context_effects(expr.hir_id, qpath.span(), did, callee_args);
+ }
if tcx.fn_sig(did).skip_binder().abi() == RustIntrinsic
&& tcx.item_name(did) == sym::transmute
{
self.suggest_mismatched_types_on_tail(
&mut err, expr, ty, e_ty, target_id,
);
+ let error = Some(Sorts(ExpectedFound { expected: ty, found: e_ty }));
+ self.annotate_loop_expected_due_to_inference(&mut err, expr, error);
if let Some(val) = ty_kind_suggestion(ty) {
- let label = destination
- .label
- .map(|l| format!(" {}", l.ident))
- .unwrap_or_else(String::new);
- err.span_suggestion(
- expr.span,
+ err.span_suggestion_verbose(
+ expr.span.shrink_to_hi(),
"give it a value of the expected type",
- format!("break{label} {val}"),
+ format!(" {val}"),
Applicability::HasPlaceholders,
);
}
// ... except when we try to 'break rust;'.
// ICE this expression in particular (see #43162).
if let ExprKind::Path(QPath::Resolved(_, path)) = e.kind {
- if path.segments.len() == 1 && path.segments[0].ident.name == sym::rust {
+ if let [segment] = path.segments && segment.ident.name == sym::rust {
fatally_break_rust(self.tcx);
}
}
// otherwise check exactly as a let statement
self.check_decl(let_expr.into());
// but return a bool, for this is a boolean expression
- self.tcx.types.bool
+ if let Some(error_guaranteed) = let_expr.is_recovered {
+ self.set_tainted_by_errors(error_guaranteed);
+ Ty::new_error(self.tcx, error_guaranteed)
+ } else {
+ self.tcx.types.bool
+ }
}
fn check_expr_loop(
let guar = if field.name == kw::Empty {
self.tcx.sess.delay_span_bug(field.span, "field name with no name")
- } else if self.method_exists(
- field,
- base_ty,
- expr.hir_id,
- true,
- expected.only_has_type(self),
- ) {
+ } else if self.method_exists(field, base_ty, expr.hir_id, expected.only_has_type(self)) {
self.ban_take_value_of_method(expr, base_ty, field)
} else if !base_ty.is_primitive_ty() {
self.ban_nonexisting_field(field, base, expr, base_ty)
let mut err = self.private_field_err(field, base_did);
// Also check if an accessible method exists, which is often what is meant.
- if self.method_exists(field, expr_t, expr.hir_id, false, return_ty)
+ if self.method_exists(field, expr_t, expr.hir_id, return_ty)
&& !self.expr_in_place(expr.hir_id)
{
self.suggest_method_call(