summaryrefslogtreecommitdiffstats
path: root/compiler/rustc_hir_typeck/src/expr.rs
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rustc_hir_typeck/src/expr.rs')
-rw-r--r--compiler/rustc_hir_typeck/src/expr.rs167
1 files changed, 96 insertions, 71 deletions
diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs
index bc7474cdf..7fc4ccb04 100644
--- a/compiler/rustc_hir_typeck/src/expr.rs
+++ b/compiler/rustc_hir_typeck/src/expr.rs
@@ -8,7 +8,7 @@ use crate::coercion::DynamicCoerceMany;
use crate::errors::TypeMismatchFruTypo;
use crate::errors::{AddressOfTemporaryTaken, ReturnStmtOutsideOfFnBody, StructExprNonExhaustive};
use crate::errors::{
- FieldMultiplySpecifiedInInitializer, FunctionalRecordUpdateOnNonStruct,
+ FieldMultiplySpecifiedInInitializer, FunctionalRecordUpdateOnNonStruct, HelpUseLatestEdition,
YieldExprOutsideOfGenerator,
};
use crate::fatally_break_rust;
@@ -23,8 +23,8 @@ use rustc_ast as ast;
use rustc_data_structures::fx::FxHashMap;
use rustc_data_structures::stack::ensure_sufficient_stack;
use rustc_errors::{
- pluralize, struct_span_err, Applicability, Diagnostic, DiagnosticBuilder, DiagnosticId,
- ErrorGuaranteed, StashKey,
+ pluralize, struct_span_err, AddToDiagnostic, Applicability, Diagnostic, DiagnosticBuilder,
+ DiagnosticId, ErrorGuaranteed, StashKey,
};
use rustc_hir as hir;
use rustc_hir::def::{CtorKind, DefKind, Res};
@@ -42,11 +42,11 @@ use rustc_middle::middle::stability;
use rustc_middle::ty::adjustment::{Adjust, Adjustment, AllowTwoPhase};
use rustc_middle::ty::error::TypeError::FieldMisMatch;
use rustc_middle::ty::subst::SubstsRef;
-use rustc_middle::ty::{self, AdtKind, Ty, TypeVisitable};
+use rustc_middle::ty::{self, AdtKind, Ty, TypeVisitableExt};
use rustc_session::errors::ExprParenthesesNeeded;
use rustc_session::parse::feature_err;
+use rustc_span::edit_distance::find_best_match_for_name;
use rustc_span::hygiene::DesugaringKind;
-use rustc_span::lev_distance::find_best_match_for_name;
use rustc_span::source_map::{Span, Spanned};
use rustc_span::symbol::{kw, sym, Ident, Symbol};
use rustc_target::spec::abi::Abi::RustIntrinsic;
@@ -88,7 +88,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
return if let [Adjustment { kind: Adjust::NeverToAny, target }] = &adjustments[..] {
target.to_owned()
} else {
- self.tcx().ty_error_with_guaranteed(reported)
+ self.tcx().ty_error(reported)
};
}
@@ -313,7 +313,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
tcx.types.never
} else {
// There was an error; make type-check fail.
- tcx.ty_error()
+ tcx.ty_error_misc()
}
}
ExprKind::Ret(ref expr_opt) => self.check_expr_return(expr_opt.as_deref(), expr),
@@ -354,7 +354,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
ExprKind::Field(base, field) => self.check_field(expr, &base, field, expected),
ExprKind::Index(base, idx) => self.check_expr_index(base, idx, expr),
ExprKind::Yield(value, ref src) => self.check_expr_yield(value, expr, src),
- hir::ExprKind::Err => tcx.ty_error(),
+ hir::ExprKind::Err(guar) => tcx.ty_error(guar),
}
}
@@ -402,7 +402,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
{
err.subdiagnostic(ExprParenthesesNeeded::surrounding(*sp));
}
- oprnd_t = tcx.ty_error_with_guaranteed(err.emit());
+ oprnd_t = tcx.ty_error(err.emit());
}
}
hir::UnOp::Not => {
@@ -452,7 +452,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let tm = ty::TypeAndMut { ty, mutbl };
match kind {
- _ if tm.ty.references_error() => self.tcx.ty_error(),
+ _ if tm.ty.references_error() => self.tcx.ty_error_misc(),
hir::BorrowKind::Raw => {
self.check_named_place_expr(oprnd);
self.tcx.mk_ptr(tm)
@@ -531,18 +531,20 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
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)
+ tcx.ty_error(e)
}
Res::Def(DefKind::Variant, _) => {
let e = report_unexpected_variant_res(tcx, res, qpath, expr.span, "E0533", "value");
- tcx.ty_error_with_guaranteed(e)
+ tcx.ty_error(e)
}
_ => self.instantiate_value_path(segs, opt_ty, res, expr.span, expr.hir_id).0,
};
if let ty::FnDef(did, ..) = *ty.kind() {
let fn_sig = ty.fn_sig(tcx);
- if tcx.fn_sig(did).abi() == RustIntrinsic && tcx.item_name(did) == sym::transmute {
+ if tcx.fn_sig(did).skip_binder().abi() == RustIntrinsic
+ && tcx.item_name(did) == sym::transmute
+ {
let from = fn_sig.inputs().skip_binder()[0];
let to = fn_sig.output().skip_binder();
// We defer the transmute to the end of typeck, once all inference vars have
@@ -566,7 +568,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// placeholder lifetimes with probing, we just replace higher lifetimes
// with fresh vars.
let span = args.get(i).map(|a| a.span).unwrap_or(expr.span);
- let input = self.replace_bound_vars_with_fresh_vars(
+ let input = self.instantiate_binder_with_fresh_vars(
span,
infer::LateBoundRegionConversionTime::FnCall,
fn_sig.input(i),
@@ -584,7 +586,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// Also, as we just want to check sizedness, instead of introducing
// placeholder lifetimes with probing, we just replace higher lifetimes
// with fresh vars.
- let output = self.replace_bound_vars_with_fresh_vars(
+ let output = self.instantiate_binder_with_fresh_vars(
expr.span,
infer::LateBoundRegionConversionTime::FnCall,
fn_sig.output(),
@@ -632,7 +634,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// If the loop context is not a `loop { }`, then break with
// a value is illegal, and `opt_coerce_to` will be `None`.
// Just set expectation to error in that case.
- let coerce_to = opt_coerce_to.unwrap_or_else(|| tcx.ty_error());
+ let coerce_to = opt_coerce_to.unwrap_or_else(|| tcx.ty_error_misc());
// Recurse without `enclosing_breakables` borrowed.
e_ty = self.check_expr_with_hint(e, coerce_to);
@@ -852,7 +854,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// Point any obligations that were registered due to opaque type
// inference at the return expression.
self.select_obligations_where_possible(|errors| {
- self.point_at_return_for_opaque_ty_error(errors, span, return_expr_ty);
+ self.point_at_return_for_opaque_ty_error(errors, span, return_expr_ty, return_expr.span);
});
}
}
@@ -862,9 +864,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
errors: &mut Vec<traits::FulfillmentError<'tcx>>,
span: Span,
return_expr_ty: Ty<'tcx>,
+ return_span: Span,
) {
// Don't point at the whole block if it's empty
- if span == self.tcx.hir().span(self.body_id) {
+ if span == return_span {
return;
}
for err in errors {
@@ -1030,7 +1033,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}
let result_ty = coerce.complete(self);
- if cond_ty.references_error() { self.tcx.ty_error() } else { result_ty }
+ if let Err(guar) = cond_ty.error_reported() { self.tcx.ty_error(guar) } else { result_ty }
}
/// Type check assignment expression `expr` of form `lhs = rhs`.
@@ -1106,7 +1109,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// If the assignment expression itself is ill-formed, don't
// bother emitting another error
let reported = err.emit_unless(lhs_ty.references_error() || rhs_ty.references_error());
- return self.tcx.ty_error_with_guaranteed(reported);
+ return self.tcx.ty_error(reported);
}
let lhs_ty = self.check_expr_with_needs(&lhs, Needs::MutPlace);
@@ -1152,8 +1155,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
self.require_type_is_sized(lhs_ty, lhs.span, traits::AssignmentLhsSized);
- if lhs_ty.references_error() || rhs_ty.references_error() {
- self.tcx.ty_error()
+ if let Err(guar) = (lhs_ty, rhs_ty).error_reported() {
+ self.tcx.ty_error(guar)
} else {
self.tcx.mk_unit()
}
@@ -1271,8 +1274,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let t_expr = self.resolve_vars_if_possible(t_expr);
// Eagerly check for some obvious errors.
- if t_expr.references_error() || t_cast.references_error() {
- self.tcx.ty_error()
+ if let Err(guar) = (t_expr, t_cast).error_reported() {
+ self.tcx.ty_error(guar)
} else {
// Defer other checks until we're done type checking.
let mut deferred_cast_checks = self.deferred_cast_checks.borrow_mut();
@@ -1293,7 +1296,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
deferred_cast_checks.push(cast_check);
t_cast
}
- Err(_) => self.tcx.ty_error(),
+ Err(guar) => self.tcx.ty_error(guar),
}
}
}
@@ -1374,7 +1377,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let body = self.tcx.hir().body(anon_const.body);
// Create a new function context.
- let fcx = FnCtxt::new(self, self.param_env.with_const(), body.value.hir_id);
+ let def_id = anon_const.def_id;
+ let fcx = FnCtxt::new(self, self.param_env.with_const(), def_id);
crate::GatherLocalsVisitor::new(&fcx).visit_body(body);
let ty = fcx.check_expr_with_expectation(&body.value, expected);
@@ -1392,7 +1396,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
) -> Ty<'tcx> {
let tcx = self.tcx;
let count = self.array_length_to_const(count);
- if let Some(count) = count.try_eval_usize(tcx, self.param_env) {
+ if let Some(count) = count.try_eval_target_usize(tcx, self.param_env) {
self.suggest_array_len(expr, count);
}
@@ -1419,13 +1423,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}
};
- if element_ty.references_error() {
- return tcx.ty_error();
+ if let Err(guar) = element_ty.error_reported() {
+ return tcx.ty_error(guar);
}
self.check_repeat_element_needs_copy_bound(element, count, element_ty);
- tcx.mk_ty(ty::Array(t, count))
+ tcx.mk_array_with_const_len(t, count)
}
fn check_repeat_element_needs_copy_bound(
@@ -1459,7 +1463,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// If the length is 0, we don't create any elements, so we don't copy any. If the length is 1, we
// don't copy that one element, we move it. Only check for Copy if the length is larger.
- if count.try_eval_usize(tcx, self.param_env).map_or(true, |len| len > 1) {
+ if count.try_eval_target_usize(tcx, self.param_env).map_or(true, |len| len > 1) {
let lang_item = self.tcx.require_lang_item(LangItem::Copy, None);
let code = traits::ObligationCauseCode::RepeatElementCopy { is_const_fn };
self.require_type_meets(element_ty, element.span, code, lang_item);
@@ -1488,9 +1492,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}
_ => self.check_expr_with_expectation(&e, NoExpectation),
});
- let tuple = self.tcx.mk_tup(elt_ts_iter);
- if tuple.references_error() {
- self.tcx.ty_error()
+ let tuple = self.tcx.mk_tup_from_iter(elt_ts_iter);
+ if let Err(guar) = tuple.error_reported() {
+ self.tcx.ty_error(guar)
} else {
self.require_type_is_sized(tuple, expr.span, traits::TupleInitializerSized);
tuple
@@ -1506,9 +1510,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
base_expr: &'tcx Option<&'tcx hir::Expr<'tcx>>,
) -> Ty<'tcx> {
// Find the relevant variant
- let Some((variant, adt_ty)) = self.check_struct_path(qpath, expr.hir_id) else {
- self.check_struct_fields_on_error(fields, base_expr);
- return self.tcx.ty_error();
+ let (variant, adt_ty) = match self.check_struct_path(qpath, expr.hir_id) {
+ Ok(data) => data,
+ Err(guar) => {
+ self.check_struct_fields_on_error(fields, base_expr);
+ return self.tcx.ty_error(guar);
+ }
};
// Prohibit struct expressions when non-exhaustive flag is set.
@@ -1590,12 +1597,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
self.field_ty(field.span, v_field, substs)
} else {
error_happened = true;
- if let Some(prev_span) = seen_fields.get(&ident) {
+ let guar = if let Some(prev_span) = seen_fields.get(&ident) {
tcx.sess.emit_err(FieldMultiplySpecifiedInInitializer {
span: field.ident.span,
prev_span: *prev_span,
ident,
- });
+ })
} else {
self.report_unknown_field(
adt_ty,
@@ -1604,10 +1611,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
ast_fields,
adt.variant_descr(),
expr_span,
- );
- }
+ )
+ };
- tcx.ty_error()
+ tcx.ty_error(guar)
};
// Make sure to give a type to the field even if there's
@@ -1990,14 +1997,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
skip_fields: &[hir::ExprField<'_>],
kind_name: &str,
expr_span: Span,
- ) {
+ ) -> ErrorGuaranteed {
if variant.is_recovered() {
- self.set_tainted_by_errors(
- self.tcx
- .sess
- .delay_span_bug(expr_span, "parser recovered but no error was emitted"),
- );
- return;
+ let guar = self
+ .tcx
+ .sess
+ .delay_span_bug(expr_span, "parser recovered but no error was emitted");
+ self.set_tainted_by_errors(guar);
+ return guar;
}
let mut err = self.err_ctxt().type_error_struct_with_diag(
field.ident.span,
@@ -2111,7 +2118,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
};
}
}
- err.emit();
+ err.emit()
}
// Return a hint about the closest match in field names
@@ -2151,13 +2158,18 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
variant: &'tcx ty::VariantDef,
access_span: Span,
) -> Vec<Symbol> {
+ let body_owner_hir_id = self.tcx.hir().local_def_id_to_hir_id(self.body_id);
variant
.fields
.iter()
.filter(|field| {
let def_scope = self
.tcx
- .adjust_ident_and_get_scope(field.ident(self.tcx), variant.def_id, self.body_id)
+ .adjust_ident_and_get_scope(
+ field.ident(self.tcx),
+ variant.def_id,
+ body_owner_hir_id,
+ )
.1;
field.vis.is_accessible_from(def_scope, self.tcx)
&& !matches!(
@@ -2199,8 +2211,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
match deref_base_ty.kind() {
ty::Adt(base_def, substs) if !base_def.is_enum() => {
debug!("struct named {:?}", deref_base_ty);
+ let body_hir_id = self.tcx.hir().local_def_id_to_hir_id(self.body_id);
let (ident, def_scope) =
- self.tcx.adjust_ident_and_get_scope(field, base_def.did(), self.body_id);
+ self.tcx.adjust_ident_and_get_scope(field, base_def.did(), body_hir_id);
let fields = &base_def.non_enum_variant().fields;
if let Some(index) = fields
.iter()
@@ -2246,11 +2259,18 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// (#90483) apply adjustments to avoid ExprUseVisitor from
// creating erroneous projection.
self.apply_adjustments(base, adjustments);
- self.ban_private_field_access(expr, base_ty, field, did, expected.only_has_type(self));
- return self.tcx().ty_error();
+ let guar = self.ban_private_field_access(
+ expr,
+ base_ty,
+ field,
+ did,
+ expected.only_has_type(self),
+ );
+ return self.tcx().ty_error(guar);
}
- if field.name == kw::Empty {
+ 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,
@@ -2258,9 +2278,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
true,
expected.only_has_type(self),
) {
- self.ban_take_value_of_method(expr, base_ty, field);
+ 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);
+ self.ban_nonexisting_field(field, base, expr, base_ty)
} else {
let field_name = field.to_string();
let mut err = type_error_struct!(
@@ -2329,10 +2349,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
);
}
}
- err.emit();
- }
+ err.emit()
+ };
- self.tcx().ty_error()
+ self.tcx().ty_error(guar)
}
fn suggest_await_on_field_access(
@@ -2378,7 +2398,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
base: &'tcx hir::Expr<'tcx>,
expr: &'tcx hir::Expr<'tcx>,
base_ty: Ty<'tcx>,
- ) {
+ ) -> ErrorGuaranteed {
debug!(
"ban_nonexisting_field: field={:?}, base={:?}, expr={:?}, base_ty={:?}",
ident, base, expr, base_ty
@@ -2423,10 +2443,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// We know by construction that `<expr>.await` is either on Rust 2015
// or results in `ExprKind::Await`. Suggest switching the edition to 2018.
err.note("to `.await` a `Future`, switch to Rust 2018 or later");
- err.help_use_latest_edition();
+ HelpUseLatestEdition::new().add_to_diagnostic(&mut err);
}
- err.emit();
+ err.emit()
}
fn ban_private_field_access(
@@ -2436,9 +2456,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
field: Ident,
base_did: DefId,
return_ty: Option<Ty<'tcx>>,
- ) {
+ ) -> ErrorGuaranteed {
let struct_path = self.tcx().def_path_str(base_did);
- let kind_name = self.tcx().def_kind(base_did).descr(base_did);
+ let kind_name = self.tcx().def_descr(base_did);
let mut err = struct_span_err!(
self.tcx().sess,
field.span,
@@ -2459,10 +2479,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
None,
);
}
- err.emit();
+ err.emit()
}
- fn ban_take_value_of_method(&self, expr: &hir::Expr<'tcx>, expr_t: Ty<'tcx>, field: Ident) {
+ fn ban_take_value_of_method(
+ &self,
+ expr: &hir::Expr<'tcx>,
+ expr_t: Ty<'tcx>,
+ field: Ident,
+ ) -> ErrorGuaranteed {
let mut err = type_error_struct!(
self.tcx().sess,
field.span,
@@ -2534,11 +2559,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
err.help("methods are immutable and cannot be assigned to");
}
- err.emit();
+ err.emit()
}
fn point_at_param_definition(&self, err: &mut Diagnostic, param: ty::ParamTy) {
- let generics = self.tcx.generics_of(self.body_id.owner.to_def_id());
+ let generics = self.tcx.generics_of(self.body_id);
let generic_param = generics.type_param(&param, self.tcx);
if let ty::GenericParamDefKind::Type { synthetic: true, .. } = generic_param.kind {
return;
@@ -2592,7 +2617,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
len: ty::Const<'tcx>,
) {
if let (Some(len), Ok(user_index)) =
- (len.try_eval_usize(self.tcx, self.param_env), field.as_str().parse::<u64>())
+ (len.try_eval_target_usize(self.tcx, self.param_env), field.as_str().parse::<u64>())
&& let Ok(base) = self.tcx.sess.source_map().span_to_snippet(base.span)
{
let help = "instead of using tuple indexing, use array indexing";
@@ -2819,7 +2844,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}
}
let reported = err.emit();
- self.tcx.ty_error_with_guaranteed(reported)
+ self.tcx.ty_error(reported)
}
}
}