summaryrefslogtreecommitdiffstats
path: root/compiler/rustc_hir_typeck/src/expr.rs
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--compiler/rustc_hir_typeck/src/expr.rs (renamed from compiler/rustc_typeck/src/check/expr.rs)118
1 files changed, 69 insertions, 49 deletions
diff --git a/compiler/rustc_typeck/src/check/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs
index 93b008500..9fde62a81 100644
--- a/compiler/rustc_typeck/src/check/expr.rs
+++ b/compiler/rustc_hir_typeck/src/expr.rs
@@ -2,23 +2,22 @@
//!
//! See `mod.rs` for more context on type checking in general.
-use crate::astconv::AstConv as _;
-use crate::check::cast::{self, CastCheckResult};
-use crate::check::coercion::CoerceMany;
-use crate::check::fatally_break_rust;
-use crate::check::method::SelfSource;
-use crate::check::Expectation::{self, ExpectCastableToType, ExpectHasType, NoExpectation};
-use crate::check::{
- report_unexpected_variant_res, BreakableCtxt, Diverges, DynamicCoerceMany, FnCtxt, Needs,
- TupleArgumentsFlag::DontTupleArguments,
-};
+use crate::cast;
+use crate::coercion::CoerceMany;
+use crate::coercion::DynamicCoerceMany;
+use crate::errors::{AddressOfTemporaryTaken, ReturnStmtOutsideOfFnBody, StructExprNonExhaustive};
use crate::errors::{
FieldMultiplySpecifiedInInitializer, FunctionalRecordUpdateOnNonStruct,
YieldExprOutsideOfGenerator,
};
+use crate::fatally_break_rust;
+use crate::method::SelfSource;
use crate::type_error_struct;
-
-use crate::errors::{AddressOfTemporaryTaken, ReturnStmtOutsideOfFnBody, StructExprNonExhaustive};
+use crate::Expectation::{self, ExpectCastableToType, ExpectHasType, NoExpectation};
+use crate::{
+ report_unexpected_variant_res, BreakableCtxt, Diverges, FnCtxt, Needs,
+ TupleArgumentsFlag::DontTupleArguments,
+};
use rustc_ast as ast;
use rustc_data_structures::fx::FxHashMap;
use rustc_data_structures::stack::ensure_sufficient_stack;
@@ -32,6 +31,8 @@ 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_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::InferOk;
@@ -41,6 +42,7 @@ 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_session::errors::ExprParenthesesNeeded;
use rustc_session::parse::feature_err;
use rustc_span::hygiene::DesugaringKind;
use rustc_span::lev_distance::find_best_match_for_name;
@@ -394,7 +396,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
if let Some(sp) =
tcx.sess.parse_sess.ambiguous_block_expr_parse.borrow().get(&sp)
{
- tcx.sess.parse_sess.expr_parentheses_needed(&mut err, *sp);
+ err.subdiagnostic(ExprParenthesesNeeded::surrounding(*sp));
}
err.emit();
oprnd_t = tcx.ty_error();
@@ -541,7 +543,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// been resolved or we errored. This is important as we can only check transmute
// on concrete types, but the output type may not be known yet (it would only
// be known if explicitly specified via turbofish).
- self.deferred_transmute_checks.borrow_mut().push((from, to, expr.span));
+ self.deferred_transmute_checks.borrow_mut().push((from, to, expr.hir_id));
}
if !tcx.features().unsized_fn_params {
// We want to remove some Sized bounds from std functions,
@@ -752,7 +754,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
kind: hir::ImplItemKind::Fn(..),
span: encl_fn_span,
..
- })) = self.tcx.hir().find_by_def_id(encl_item_id)
+ })) = self.tcx.hir().find_by_def_id(encl_item_id.def_id)
{
// We are inside a function body, so reporting "return statement
// outside of function body" needs an explanation.
@@ -761,7 +763,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// If this didn't hold, we would not have to report an error in
// the first place.
- assert_ne!(encl_item_id, encl_body_owner_id);
+ assert_ne!(encl_item_id.def_id, encl_body_owner_id);
let encl_body_id = self.tcx.hir().body_owned_by(encl_body_owner_id);
let encl_body = self.tcx.hir().body(encl_body_id);
@@ -881,7 +883,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
return;
}
- // FIXME: Make this use SessionDiagnostic once error codes can be dynamically set.
+ // FIXME: Make this use Diagnostic once error codes can be dynamically set.
let mut err = self.tcx.sess.struct_span_err_with_code(
op_span,
"invalid left-hand side of assignment",
@@ -1044,6 +1046,26 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let rhs_ty = self.check_expr(&rhs);
let (applicability, eq) = if self.can_coerce(rhs_ty, lhs_ty) {
(Applicability::MachineApplicable, true)
+ } else if let ExprKind::Binary(
+ Spanned { node: hir::BinOpKind::And | hir::BinOpKind::Or, .. },
+ _,
+ rhs_expr,
+ ) = lhs.kind
+ {
+ // if x == 1 && y == 2 { .. }
+ // +
+ let actual_lhs_ty = self.check_expr(&rhs_expr);
+ (Applicability::MaybeIncorrect, self.can_coerce(rhs_ty, actual_lhs_ty))
+ } else if let ExprKind::Binary(
+ Spanned { node: hir::BinOpKind::And | hir::BinOpKind::Or, .. },
+ lhs_expr,
+ _,
+ ) = rhs.kind
+ {
+ // if x == 1 && y == 2 { .. }
+ // +
+ let actual_rhs_ty = self.check_expr(&lhs_expr);
+ (Applicability::MaybeIncorrect, self.can_coerce(actual_rhs_ty, lhs_ty))
} else {
(Applicability::MaybeIncorrect, false)
};
@@ -1066,9 +1088,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}
if eq {
err.span_suggestion_verbose(
- span,
+ span.shrink_to_hi(),
"you might have meant to compare for equality",
- "==",
+ '=',
applicability,
);
}
@@ -1109,11 +1131,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}
};
- self.check_lhs_assignable(lhs, "E0070", span, |err| {
- let rhs_ty = self.check_expr(&rhs);
- suggest_deref_binop(err, rhs_ty);
- });
-
// This is (basically) inlined `check_expr_coercable_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);
@@ -1124,6 +1141,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
diag.emit();
}
+ self.check_lhs_assignable(lhs, "E0070", span, |err| {
+ if let Some(rhs_ty) = self.typeck_results.borrow().expr_ty_opt(rhs) {
+ suggest_deref_binop(err, rhs_ty);
+ }
+ });
+
self.require_type_is_sized(lhs_ty, lhs.span, traits::AssignmentLhsSized);
if lhs_ty.references_error() || rhs_ty.references_error() {
@@ -1249,9 +1272,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
} else {
// Defer other checks until we're done type checking.
let mut deferred_cast_checks = self.deferred_cast_checks.borrow_mut();
- match cast::check_cast(self, e, t_expr, t_cast, t.span, expr.span) {
- CastCheckResult::Ok => t_cast,
- CastCheckResult::Deferred(cast_check) => {
+ match cast::CastCheck::new(
+ self,
+ e,
+ t_expr,
+ t_cast,
+ t.span,
+ expr.span,
+ self.param_env.constness(),
+ ) {
+ Ok(cast_check) => {
debug!(
"check_expr_cast: deferring cast from {:?} to {:?}: {:?}",
t_cast, t_expr, cast_check,
@@ -1259,7 +1289,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
deferred_cast_checks.push(cast_check);
t_cast
}
- CastCheckResult::Err(ErrorGuaranteed { .. }) => self.tcx.ty_error(),
+ Err(_) => self.tcx.ty_error(),
}
}
}
@@ -1341,7 +1371,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// Create a new function context.
let fcx = FnCtxt::new(self, self.param_env.with_const(), body.value.hir_id);
- crate::check::GatherLocalsVisitor::new(&fcx).visit_body(body);
+ crate::GatherLocalsVisitor::new(&fcx).visit_body(body);
let ty = fcx.check_expr_with_expectation(&body.value, expected);
fcx.require_type_is_sized(ty, body.value.span, traits::ConstSized);
@@ -1640,13 +1670,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
Err(_) => {
// This should never happen, since we're just subtyping the
// remaining_fields, but it's fine to emit this, I guess.
- self.report_mismatched_types(
- &cause,
- target_ty,
- fru_ty,
- FieldMisMatch(variant.name, ident.name),
- )
- .emit();
+ self.err_ctxt()
+ .report_mismatched_types(
+ &cause,
+ target_ty,
+ fru_ty,
+ FieldMisMatch(variant.name, ident.name),
+ )
+ .emit();
}
}
}
@@ -1933,7 +1964,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
self.set_tainted_by_errors();
return;
}
- let mut err = self.type_error_struct_with_diag(
+ let mut err = self.err_ctxt().type_error_struct_with_diag(
field.ident.span,
|actual| match ty.kind() {
ty::Adt(adt, ..) if adt.is_enum() => struct_span_err!(
@@ -2338,7 +2369,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
if let ty::Adt(def, _) = output_ty.kind() && !def.is_enum() {
def.non_enum_variant().fields.iter().any(|field| {
field.ident(self.tcx) == ident
- && field.vis.is_accessible_from(expr.hir_id.owner, self.tcx)
+ && field.vis.is_accessible_from(expr.hir_id.owner.def_id, self.tcx)
})
} else if let ty::Tuple(tys) = output_ty.kind()
&& let Ok(idx) = ident.as_str().parse::<usize>()
@@ -2863,14 +2894,3 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}
}
}
-
-pub(super) fn ty_kind_suggestion(ty: Ty<'_>) -> Option<&'static str> {
- Some(match ty.kind() {
- ty::Bool => "true",
- ty::Char => "'a'",
- ty::Int(_) | ty::Uint(_) => "42",
- ty::Float(_) => "3.14159",
- ty::Error(_) | ty::Never => return None,
- _ => "value",
- })
-}