diff options
Diffstat (limited to 'compiler/rustc_hir_typeck/src/expr.rs')
-rw-r--r-- | compiler/rustc_hir_typeck/src/expr.rs | 167 |
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(¶m, 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) } } } |