diff options
Diffstat (limited to 'compiler/rustc_hir_typeck/src/expr.rs')
-rw-r--r-- | compiler/rustc_hir_typeck/src/expr.rs | 83 |
1 files changed, 39 insertions, 44 deletions
diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index 7fc4ccb04..6ffa0134f 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -36,6 +36,7 @@ use rustc_hir_analysis::astconv::AstConv as _; use rustc_hir_analysis::check::ty_kind_suggestion; use rustc_infer::infer; use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; +use rustc_infer::infer::DefineOpaqueTypes; use rustc_infer::infer::InferOk; use rustc_infer::traits::ObligationCause; use rustc_middle::middle::stability; @@ -49,6 +50,7 @@ use rustc_span::edit_distance::find_best_match_for_name; use rustc_span::hygiene::DesugaringKind; use rustc_span::source_map::{Span, Spanned}; use rustc_span::symbol::{kw, sym, Ident, Symbol}; +use rustc_target::abi::FieldIdx; use rustc_target::spec::abi::Abi::RustIntrinsic; use rustc_trait_selection::infer::InferCtxtExt; use rustc_trait_selection::traits::{self, ObligationCauseCode}; @@ -118,7 +120,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ty } - pub(super) fn check_expr_coercable_to_type( + pub(super) fn check_expr_coercible_to_type( &self, expr: &'tcx hir::Expr<'tcx>, expected: Ty<'tcx>, @@ -230,7 +232,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let ty = ensure_sufficient_stack(|| match &expr.kind { hir::ExprKind::Path( - qpath @ hir::QPath::Resolved(..) | qpath @ hir::QPath::TypeRelative(..), + qpath @ (hir::QPath::Resolved(..) | hir::QPath::TypeRelative(..)), ) => self.check_expr_path(qpath, expr, args), _ => self.check_expr_kind(expr, expected), }); @@ -283,7 +285,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let tcx = self.tcx; match expr.kind { - ExprKind::Box(subexpr) => self.check_expr_box(subexpr, expected), ExprKind::Lit(ref lit) => self.check_lit(&lit, expected), ExprKind::Binary(op, lhs, rhs) => self.check_binop(expr, op, lhs, rhs, expected), ExprKind::Assign(lhs, rhs, span) => { @@ -358,16 +359,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } - fn check_expr_box(&self, expr: &'tcx hir::Expr<'tcx>, expected: Expectation<'tcx>) -> Ty<'tcx> { - let expected_inner = expected.to_option(self).map_or(NoExpectation, |ty| match ty.kind() { - ty::Adt(def, _) if def.is_box() => Expectation::rvalue_hint(self, ty.boxed_ty()), - _ => NoExpectation, - }); - let referent_ty = self.check_expr_with_expectation(expr, expected_inner); - self.require_type_is_sized(referent_ty, expr.span, traits::SizedBoxType); - self.tcx.mk_box(referent_ty) - } - fn check_expr_unary( &self, unop: hir::UnOp, @@ -798,7 +789,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.ret_coercion_span.set(Some(expr.span)); } let cause = self.cause(expr.span, ObligationCauseCode::ReturnNoExpression); - if let Some((fn_decl, _)) = self.get_fn_decl(expr.hir_id) { + if let Some((_, fn_decl, _)) = self.get_fn_decl(expr.hir_id) { coercion.coerce_forced_unit( self, &cause, @@ -1137,7 +1128,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } }; - // This is (basically) inlined `check_expr_coercable_to_type`, but we want + // This is (basically) inlined `check_expr_coercible_to_type`, but we want // to suggest an additional fixup here in `suggest_deref_binop`. let rhs_ty = self.check_expr_with_hint(&rhs, lhs_ty); if let (_, Some(mut diag)) = @@ -1410,7 +1401,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let (element_ty, t) = match uty { Some(uty) => { - self.check_expr_coercable_to_type(&element, uty, None); + self.check_expr_coercible_to_type(&element, uty, None); (uty, uty) } None => { @@ -1487,7 +1478,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let elt_ts_iter = elts.iter().enumerate().map(|(i, e)| match flds { Some(fs) if i < fs.len() => { let ety = fs[i]; - self.check_expr_coercable_to_type(&e, ety, None); + self.check_expr_coercible_to_type(&e, ety, None); ety } _ => self.check_expr_with_expectation(&e, NoExpectation), @@ -1571,8 +1562,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let mut remaining_fields = variant .fields - .iter() - .enumerate() + .iter_enumerated() .map(|(i, field)| (field.ident(tcx).normalize_to_macros_2_0(), (i, field))) .collect::<FxHashMap<_, _>>(); @@ -1683,7 +1673,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if let Some(_) = remaining_fields.remove(&ident) { let target_ty = self.field_ty(base_expr.span, f, substs); let cause = self.misc(base_expr.span); - match self.at(&cause, self.param_env).sup(target_ty, fru_ty) { + match self.at(&cause, self.param_env).sup( + DefineOpaqueTypes::No, + target_ty, + fru_ty, + ) { Ok(InferOk { obligations, value: () }) => { self.register_predicates(obligations) } @@ -1821,7 +1815,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { &self, adt_ty: Ty<'tcx>, span: Span, - remaining_fields: FxHashMap<Ident, (usize, &ty::FieldDef)>, + remaining_fields: FxHashMap<Ident, (FieldIdx, &ty::FieldDef)>, variant: &'tcx ty::VariantDef, ast_fields: &'tcx [hir::ExprField<'tcx>], substs: SubstsRef<'tcx>, @@ -2215,11 +2209,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let (ident, def_scope) = 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() - .position(|f| f.ident(self.tcx).normalize_to_macros_2_0() == ident) + if let Some((index, field)) = fields + .iter_enumerated() + .find(|(_, f)| f.ident(self.tcx).normalize_to_macros_2_0() == ident) { - let field = &fields[index]; let field_ty = self.field_ty(expr.span, field, substs); // Save the index of all fields regardless of their visibility in case // of error recovery. @@ -2236,15 +2229,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } ty::Tuple(tys) => { - let fstr = field.as_str(); - if let Ok(index) = fstr.parse::<usize>() { - if fstr == index.to_string() { + if let Ok(index) = field.as_str().parse::<usize>() { + if field.name == sym::integer(index) { if let Some(&field_ty) = tys.get(index) { let adjustments = self.adjust_steps(&autoderef); self.apply_adjustments(base, adjustments); self.register_predicates(autoderef.into_obligations()); - self.write_field_index(expr.hir_id, index); + self.write_field_index(expr.hir_id, FieldIdx::from_usize(index)); return field_ty; } } @@ -2818,23 +2810,26 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { "cannot index into a value of type `{base_t}`", ); // Try to give some advice about indexing tuples. - if let ty::Tuple(..) = base_t.kind() { + if let ty::Tuple(types) = base_t.kind() { let mut needs_note = true; // If the index is an integer, we can show the actual // fixed expression: - if let ExprKind::Lit(ref lit) = idx.kind { - if let ast::LitKind::Int(i, ast::LitIntType::Unsuffixed) = lit.node { - let snip = self.tcx.sess.source_map().span_to_snippet(base.span); - if let Ok(snip) = snip { - err.span_suggestion( - expr.span, - "to access tuple elements, use", - format!("{snip}.{i}"), - Applicability::MachineApplicable, - ); - needs_note = false; - } + if let ExprKind::Lit(ref lit) = idx.kind + && let ast::LitKind::Int(i, ast::LitIntType::Unsuffixed) = lit.node + && i < types.len().try_into().expect("expected tuple index to be < usize length") + { + let snip = self.tcx.sess.source_map().span_to_snippet(base.span); + if let Ok(snip) = snip { + err.span_suggestion( + expr.span, + "to access tuple elements, use", + format!("{snip}.{i}"), + Applicability::MachineApplicable, + ); + needs_note = false; } + } else if let ExprKind::Path(..) = idx.peel_borrows().kind { + err.span_label(idx.span, "cannot access tuple elements at a variable index"); } if needs_note { err.help( @@ -2874,7 +2869,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ) -> Ty<'tcx> { match self.resume_yield_tys { Some((resume_ty, yield_ty)) => { - self.check_expr_coercable_to_type(&value, yield_ty, None); + self.check_expr_coercible_to_type(&value, yield_ty, None); resume_ty } @@ -2883,7 +2878,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // information. Hence, we check the source of the yield expression here and check its // value's type against `()` (this check should always hold). None if src.is_await() => { - self.check_expr_coercable_to_type(&value, self.tcx.mk_unit(), None); + self.check_expr_coercible_to_type(&value, self.tcx.mk_unit(), None); self.tcx.mk_unit() } _ => { |