summaryrefslogtreecommitdiffstats
path: root/compiler/rustc_hir_typeck/src
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-06-19 09:26:03 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-06-19 09:26:03 +0000
commit9918693037dce8aa4bb6f08741b6812923486c18 (patch)
tree21d2b40bec7e6a7ea664acee056eb3d08e15a1cf /compiler/rustc_hir_typeck/src
parentReleasing progress-linux version 1.75.0+dfsg1-5~progress7.99u1. (diff)
downloadrustc-9918693037dce8aa4bb6f08741b6812923486c18.tar.xz
rustc-9918693037dce8aa4bb6f08741b6812923486c18.zip
Merging upstream version 1.76.0+dfsg1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'compiler/rustc_hir_typeck/src')
-rw-r--r--compiler/rustc_hir_typeck/src/_match.rs49
-rw-r--r--compiler/rustc_hir_typeck/src/callee.rs144
-rw-r--r--compiler/rustc_hir_typeck/src/cast.rs20
-rw-r--r--compiler/rustc_hir_typeck/src/check.rs44
-rw-r--r--compiler/rustc_hir_typeck/src/closure.rs24
-rw-r--r--compiler/rustc_hir_typeck/src/coercion.rs128
-rw-r--r--compiler/rustc_hir_typeck/src/demand.rs92
-rw-r--r--compiler/rustc_hir_typeck/src/diverges.rs2
-rw-r--r--compiler/rustc_hir_typeck/src/errors.rs8
-rw-r--r--compiler/rustc_hir_typeck/src/expectation.rs2
-rw-r--r--compiler/rustc_hir_typeck/src/expr.rs528
-rw-r--r--compiler/rustc_hir_typeck/src/expr_use_visitor.rs31
-rw-r--r--compiler/rustc_hir_typeck/src/fallback.rs35
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs61
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs8
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/arg_matrix.rs2
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs123
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs8
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs237
-rw-r--r--compiler/rustc_hir_typeck/src/gather_locals.rs2
-rw-r--r--compiler/rustc_hir_typeck/src/inherited.rs4
-rw-r--r--compiler/rustc_hir_typeck/src/intrinsicck.rs2
-rw-r--r--compiler/rustc_hir_typeck/src/lib.rs46
-rw-r--r--compiler/rustc_hir_typeck/src/mem_categorization.rs28
-rw-r--r--compiler/rustc_hir_typeck/src/method/confirm.rs16
-rw-r--r--compiler/rustc_hir_typeck/src/method/mod.rs4
-rw-r--r--compiler/rustc_hir_typeck/src/method/prelude2021.rs6
-rw-r--r--compiler/rustc_hir_typeck/src/method/probe.rs43
-rw-r--r--compiler/rustc_hir_typeck/src/method/suggest.rs373
-rw-r--r--compiler/rustc_hir_typeck/src/op.rs10
-rw-r--r--compiler/rustc_hir_typeck/src/pat.rs28
-rw-r--r--compiler/rustc_hir_typeck/src/place_op.rs12
-rw-r--r--compiler/rustc_hir_typeck/src/rvalue_scopes.rs5
-rw-r--r--compiler/rustc_hir_typeck/src/upvar.rs85
-rw-r--r--compiler/rustc_hir_typeck/src/writeback.rs160
35 files changed, 1390 insertions, 980 deletions
diff --git a/compiler/rustc_hir_typeck/src/_match.rs b/compiler/rustc_hir_typeck/src/_match.rs
index 84e986488..181de3728 100644
--- a/compiler/rustc_hir_typeck/src/_match.rs
+++ b/compiler/rustc_hir_typeck/src/_match.rs
@@ -42,7 +42,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// #55810: Type check patterns first so we get types for all bindings.
let scrut_span = scrut.span.find_ancestor_inside(expr.span).unwrap_or(scrut.span);
for arm in arms {
- self.check_pat_top(&arm.pat, scrutinee_ty, Some(scrut_span), Some(scrut), None);
+ self.check_pat_top(arm.pat, scrutinee_ty, Some(scrut_span), Some(scrut), None);
}
// Now typecheck the blocks.
@@ -92,7 +92,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
self.diverges.set(Diverges::Maybe);
- let arm_ty = self.check_expr_with_expectation(&arm.body, expected);
+ let arm_ty = self.check_expr_with_expectation(arm.body, expected);
all_arms_diverge &= self.diverges.get();
let opt_suggest_box_span = prior_arm.and_then(|(_, prior_arm_ty, _)| {
@@ -137,9 +137,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
coercion.coerce_inner(
self,
&cause,
- Some(&arm.body),
+ Some(arm.body),
arm_ty,
- |err| self.suggest_removing_semicolon_for_coerce(err, expr, arm_ty, prior_arm),
+ |err| {
+ self.explain_never_type_coerced_to_unit(err, arm, arm_ty, prior_arm, expr);
+ },
false,
);
@@ -177,6 +179,38 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
coercion.complete(self)
}
+ fn explain_never_type_coerced_to_unit(
+ &self,
+ err: &mut Diagnostic,
+ arm: &hir::Arm<'tcx>,
+ arm_ty: Ty<'tcx>,
+ prior_arm: Option<(Option<hir::HirId>, Ty<'tcx>, Span)>,
+ expr: &hir::Expr<'tcx>,
+ ) {
+ if let hir::ExprKind::Block(block, _) = arm.body.kind
+ && let Some(expr) = block.expr
+ && let arm_tail_ty = self.node_ty(expr.hir_id)
+ && arm_tail_ty.is_never()
+ && !arm_ty.is_never()
+ {
+ err.span_label(
+ expr.span,
+ format!(
+ "this expression is of type `!`, but it is coerced to `{arm_ty}` due to its \
+ surrounding expression",
+ ),
+ );
+ self.suggest_mismatched_types_on_tail(
+ err,
+ expr,
+ arm_ty,
+ prior_arm.map_or(arm_tail_ty, |(_, ty, _)| ty),
+ expr.hir_id,
+ );
+ }
+ self.suggest_removing_semicolon_for_coerce(err, expr, arm_ty, prior_arm)
+ }
+
fn suggest_removing_semicolon_for_coerce(
&self,
diag: &mut Diagnostic,
@@ -204,8 +238,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}
// Next, make sure that we have no type expectation.
- let Some(ret) = hir
- .find_by_def_id(self.body_id)
+ let Some(ret) = self
+ .tcx
+ .opt_hir_node_by_def_id(self.body_id)
.and_then(|owner| owner.fn_decl())
.map(|decl| decl.output.span())
else {
@@ -283,7 +318,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
hir_id: hir::HirId,
sp: Span,
) -> Option<(Span, String)> {
- let node = self.tcx.hir().get(hir_id);
+ let node = self.tcx.hir_node(hir_id);
if let hir::Node::Block(block) = node {
// check that the body's parent is an fn
let parent = self.tcx.hir().get_parent(self.tcx.hir().parent_id(block.hir_id));
diff --git a/compiler/rustc_hir_typeck/src/callee.rs b/compiler/rustc_hir_typeck/src/callee.rs
index 6b6d1574b..5e6b54950 100644
--- a/compiler/rustc_hir_typeck/src/callee.rs
+++ b/compiler/rustc_hir_typeck/src/callee.rs
@@ -6,9 +6,8 @@ use crate::errors;
use rustc_ast::util::parser::PREC_POSTFIX;
use rustc_errors::{Applicability, Diagnostic, ErrorGuaranteed, StashKey};
use rustc_hir as hir;
-use rustc_hir::def::{self, CtorKind, DefKind, Namespace, Res};
+use rustc_hir::def::{self, CtorKind, Namespace, Res};
use rustc_hir::def_id::DefId;
-use rustc_hir::HirId;
use rustc_hir_analysis::autoderef::Autoderef;
use rustc_infer::{
infer,
@@ -245,7 +244,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
) {
// Check for `self` receiver on the method, otherwise we can't use this as a `Fn*` trait.
if !self.tcx.associated_item(ok.value.def_id).fn_has_self_parameter {
- self.tcx.sess.delay_span_bug(
+ self.tcx.sess.span_delayed_bug(
call_expr.span,
"input to overloaded call fn is not a self receiver",
);
@@ -260,9 +259,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let ty::Ref(region, _, mutbl) = method.sig.inputs()[0].kind() else {
// The `fn`/`fn_mut` lang item is ill-formed, which should have
// caused an error elsewhere.
- self.tcx
- .sess
- .delay_span_bug(call_expr.span, "input to call/call_mut is not a ref");
+ self.tcx.sess.span_delayed_bug(
+ call_expr.span,
+ "input to call/call_mut is not a ref",
+ );
return None;
};
@@ -295,7 +295,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
) {
let hir = self.tcx.hir();
let parent_hir_id = hir.parent_id(hir_id);
- let parent_node = hir.get(parent_hir_id);
+ let parent_node = self.tcx.hir_node(parent_hir_id);
if let (
hir::Node::Expr(hir::Expr {
kind: hir::ExprKind::Closure(&hir::Closure { fn_decl_span, body, .. }),
@@ -313,7 +313,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
if let hir::Node::Expr(hir::Expr {
kind: hir::ExprKind::Closure(&hir::Closure { fn_decl_span, .. }),
..
- }) = hir.get(async_closure)
+ }) = self.tcx.hir_node(async_closure)
{
fn_decl_span
} else {
@@ -343,7 +343,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
callee_expr: &'tcx hir::Expr<'tcx>,
) -> bool {
let hir_id = self.tcx.hir().parent_id(call_expr.hir_id);
- let parent_node = self.tcx.hir().get(hir_id);
+ let parent_node = self.tcx.hir_node(hir_id);
if let (
hir::Node::Expr(hir::Expr { kind: hir::ExprKind::Array(_), .. }),
hir::ExprKind::Tup(exp),
@@ -373,7 +373,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
) -> Ty<'tcx> {
let (fn_sig, def_id) = match *callee_ty.kind() {
ty::FnDef(def_id, args) => {
- self.enforce_context_effects(call_expr.hir_id, call_expr.span, def_id, args);
+ self.enforce_context_effects(call_expr.span, def_id, args);
let fn_sig = self.tcx.fn_sig(def_id).instantiate(self.tcx, args);
// Unit testing: function items annotated with
@@ -417,7 +417,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
&& let Some(mut diag) = self
.tcx
.sess
- .diagnostic()
+ .dcx()
.steal_diagnostic(segment.ident.span, StashKey::CallIntoMethod)
{
// Try suggesting `foo(a)` -> `a.foo()` if possible.
@@ -471,6 +471,65 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}
}
+ if let Some(def_id) = def_id
+ && self.tcx.def_kind(def_id) == hir::def::DefKind::Fn
+ && self.tcx.is_intrinsic(def_id)
+ && self.tcx.item_name(def_id) == sym::const_eval_select
+ {
+ let fn_sig = self.resolve_vars_if_possible(fn_sig);
+ for idx in 0..=1 {
+ let arg_ty = fn_sig.inputs()[idx + 1];
+ let span = arg_exprs.get(idx + 1).map_or(call_expr.span, |arg| arg.span);
+ // Check that second and third argument of `const_eval_select` must be `FnDef`, and additionally that
+ // the second argument must be `const fn`. The first argument must be a tuple, but this is already expressed
+ // in the function signature (`F: FnOnce<ARG>`), so I did not bother to add another check here.
+ //
+ // This check is here because there is currently no way to express a trait bound for `FnDef` types only.
+ if let ty::FnDef(def_id, _args) = *arg_ty.kind() {
+ let fn_once_def_id =
+ self.tcx.require_lang_item(hir::LangItem::FnOnce, Some(span));
+ let fn_once_output_def_id =
+ self.tcx.require_lang_item(hir::LangItem::FnOnceOutput, Some(span));
+ if self.tcx.generics_of(fn_once_def_id).host_effect_index.is_none() {
+ if idx == 0 && !self.tcx.is_const_fn_raw(def_id) {
+ self.tcx.sess.emit_err(errors::ConstSelectMustBeConst { span });
+ }
+ } else {
+ let const_param: ty::GenericArg<'tcx> =
+ ([self.tcx.consts.false_, self.tcx.consts.true_])[idx].into();
+ self.register_predicate(traits::Obligation::new(
+ self.tcx,
+ self.misc(span),
+ self.param_env,
+ ty::TraitRef::new(
+ self.tcx,
+ fn_once_def_id,
+ [arg_ty.into(), fn_sig.inputs()[0].into(), const_param],
+ ),
+ ));
+
+ self.register_predicate(traits::Obligation::new(
+ self.tcx,
+ self.misc(span),
+ self.param_env,
+ ty::ProjectionPredicate {
+ projection_ty: ty::AliasTy::new(
+ self.tcx,
+ fn_once_output_def_id,
+ [arg_ty.into(), fn_sig.inputs()[0].into(), const_param],
+ ),
+ term: fn_sig.output().into(),
+ },
+ ));
+
+ self.select_obligations_where_possible(|_| {});
+ }
+ } else {
+ self.tcx.sess.emit_err(errors::ConstSelectMustBeFn { span, ty: arg_ty });
+ }
+ }
+ }
+
fn_sig.output()
}
@@ -625,12 +684,31 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
);
}
+ if let hir::ExprKind::Path(hir::QPath::Resolved(None, path)) = callee_expr.kind
+ && let Res::Local(_) = path.res
+ && let [segment] = &path.segments[..]
+ {
+ for id in self.tcx.hir().items() {
+ if let Some(node) = self.tcx.hir().get_if_local(id.owner_id.into())
+ && let hir::Node::Item(item) = node
+ && let hir::ItemKind::Fn(..) = item.kind
+ && item.ident.name == segment.ident.name
+ {
+ err.span_label(
+ self.tcx.def_span(id.owner_id),
+ "this function of the same name is available here, but it's shadowed by \
+ the local binding",
+ );
+ }
+ }
+ }
+
let mut inner_callee_path = None;
let def = match callee_expr.kind {
hir::ExprKind::Path(ref qpath) => {
self.typeck_results.borrow().qpath_res(qpath, callee_expr.hir_id)
}
- hir::ExprKind::Call(ref inner_callee, _) => {
+ hir::ExprKind::Call(inner_callee, _) => {
if let hir::ExprKind::Path(ref inner_qpath) = inner_callee.kind {
inner_callee_path = Some(inner_qpath);
self.typeck_results.borrow().qpath_res(inner_qpath, inner_callee.hir_id)
@@ -751,7 +829,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
#[tracing::instrument(level = "debug", skip(self, span))]
pub(super) fn enforce_context_effects(
&self,
- call_expr_hir: HirId,
span: Span,
callee_did: DefId,
callee_args: GenericArgsRef<'tcx>,
@@ -762,38 +839,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let generics = tcx.generics_of(callee_did);
let Some(host_effect_index) = generics.host_effect_index else { return };
- // if the callee does have the param, we need to equate the param to some const
- // value no matter whether the effects feature is enabled in the local crate,
- // because inference will fail if we don't.
- let mut host_always_on =
- !tcx.features().effects || tcx.sess.opts.unstable_opts.unleash_the_miri_inside_of_you;
-
- // Compute the constness required by the context.
- let context = tcx.hir().enclosing_body_owner(call_expr_hir);
- let const_context = tcx.hir().body_const_context(context);
-
- let kind = tcx.def_kind(context.to_def_id());
- debug_assert_ne!(kind, DefKind::ConstParam);
-
- if tcx.has_attr(context.to_def_id(), sym::rustc_do_not_const_check) {
- trace!("do not const check this context");
- host_always_on = true;
- }
-
- let effect = match const_context {
- _ if host_always_on => tcx.consts.true_,
- Some(hir::ConstContext::Static(_) | hir::ConstContext::Const { .. }) => {
- tcx.consts.false_
- }
- Some(hir::ConstContext::ConstFn) => {
- let host_idx = tcx
- .generics_of(context)
- .host_effect_index
- .expect("ConstContext::Maybe must have host effect param");
- ty::GenericArgs::identity_for_item(tcx, context).const_at(host_idx)
- }
- None => tcx.consts.true_,
- };
+ let effect = tcx.expected_host_effect_param_for_body(self.body_id);
trace!(?effect, ?generics, ?callee_args);
@@ -826,7 +872,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
expected,
);
- self.write_method_call(call_expr.hir_id, method_callee);
+ self.write_method_call_and_enforce_effects(call_expr.hir_id, call_expr.span, method_callee);
output_type
}
}
@@ -876,7 +922,11 @@ impl<'a, 'tcx> DeferredCallResolution<'tcx> {
adjustments.extend(autoref);
fcx.apply_adjustments(self.callee_expr, adjustments);
- fcx.write_method_call(self.call_expr.hir_id, method_callee);
+ fcx.write_method_call_and_enforce_effects(
+ self.call_expr.hir_id,
+ self.call_expr.span,
+ method_callee,
+ );
}
None => {
// This can happen if `#![no_core]` is used and the `fn/fn_mut/fn_once`
diff --git a/compiler/rustc_hir_typeck/src/cast.rs b/compiler/rustc_hir_typeck/src/cast.rs
index ee23f47c2..0de036536 100644
--- a/compiler/rustc_hir_typeck/src/cast.rs
+++ b/compiler/rustc_hir_typeck/src/cast.rs
@@ -101,7 +101,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
Ok(match *t.kind() {
ty::Slice(_) | ty::Str => Some(PointerKind::Length),
- ty::Dynamic(ref tty, _, ty::Dyn) => Some(PointerKind::VTable(tty.principal_def_id())),
+ ty::Dynamic(tty, _, ty::Dyn) => Some(PointerKind::VTable(tty.principal_def_id())),
ty::Adt(def, args) if def.is_struct() => match def.non_enum_variant().tail_opt() {
None => Some(PointerKind::Thin),
Some(f) => {
@@ -142,14 +142,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let reported = self
.tcx
.sess
- .delay_span_bug(span, format!("`{t:?}` should be sized but is not?"));
+ .span_delayed_bug(span, format!("`{t:?}` should be sized but is not?"));
return Err(reported);
}
})
}
}
-#[derive(Copy, Clone)]
+#[derive(Copy, Clone, Debug)]
pub enum CastError {
ErrorGuaranteed(ErrorGuaranteed),
@@ -271,7 +271,7 @@ impl<'a, 'tcx> CastCheck<'tcx> {
match e {
CastError::NeedViaPtr => "a raw pointer",
CastError::NeedViaThinPtr => "a thin pointer",
- _ => bug!(),
+ e => unreachable!("control flow means we should never encounter a {e:?}"),
}
));
}
@@ -288,13 +288,7 @@ impl<'a, 'tcx> CastCheck<'tcx> {
self.cast_ty,
fcx,
)
- .help(format!(
- "cast through {} first",
- match e {
- CastError::NeedViaInt => "an integer",
- _ => bug!(),
- }
- ))
+ .help("cast through an integer first")
.emit();
}
CastError::IllegalCast => {
@@ -506,7 +500,7 @@ impl<'a, 'tcx> CastCheck<'tcx> {
};
SizedUnsizedCast {
- sess: &fcx.tcx.sess,
+ sess: fcx.tcx.sess,
span: self.span,
expr_ty: self.expr_ty,
cast_ty: fcx.ty_to_string(self.cast_ty),
@@ -534,7 +528,7 @@ impl<'a, 'tcx> CastCheck<'tcx> {
let unknown_cast_to = match e {
CastError::UnknownCastPtrKind => true,
CastError::UnknownExprPtrKind => false,
- _ => bug!(),
+ e => unreachable!("control flow means we should never encounter a {e:?}"),
};
let (span, sub) = if unknown_cast_to {
(self.cast_span, errors::CastUnknownPointerSub::To(self.cast_span))
diff --git a/compiler/rustc_hir_typeck/src/check.rs b/compiler/rustc_hir_typeck/src/check.rs
index b8a265d49..2855cea80 100644
--- a/compiler/rustc_hir_typeck/src/check.rs
+++ b/compiler/rustc_hir_typeck/src/check.rs
@@ -8,7 +8,7 @@ use rustc_hir as hir;
use rustc_hir::def::DefKind;
use rustc_hir::intravisit::Visitor;
use rustc_hir::lang_items::LangItem;
-use rustc_hir_analysis::check::{check_function_signature, fn_maybe_err};
+use rustc_hir_analysis::check::{check_function_signature, forbid_intrinsic_abi};
use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
use rustc_infer::infer::RegionVariableOrigin;
use rustc_middle::ty::{self, Binder, Ty, TyCtxt};
@@ -34,7 +34,7 @@ pub(super) fn check_fn<'a, 'tcx>(
can_be_coroutine: Option<hir::Movability>,
params_can_be_unsized: bool,
) -> Option<CoroutineTypes<'tcx>> {
- let fn_id = fcx.tcx.hir().local_def_id_to_hir_id(fn_def_id);
+ let fn_id = fcx.tcx.local_def_id_to_hir_id(fn_def_id);
let tcx = fcx.tcx;
let hir = tcx.hir();
@@ -53,7 +53,7 @@ pub(super) fn check_fn<'a, 'tcx>(
let span = body.value.span;
- fn_maybe_err(tcx, span, fn_sig.abi);
+ forbid_intrinsic_abi(tcx, span, fn_sig.abi);
if let Some(kind) = body.coroutine_kind
&& can_be_coroutine.is_some()
@@ -67,6 +67,28 @@ pub(super) fn check_fn<'a, 'tcx>(
fcx.require_type_is_sized(yield_ty, span, traits::SizedYieldType);
yield_ty
}
+ // HACK(-Ztrait-solver=next): In the *old* trait solver, we must eagerly
+ // guide inference on the yield type so that we can handle `AsyncIterator`
+ // in this block in projection correctly. In the new trait solver, it is
+ // not a problem.
+ hir::CoroutineKind::AsyncGen(..) => {
+ let yield_ty = fcx.next_ty_var(TypeVariableOrigin {
+ kind: TypeVariableOriginKind::TypeInference,
+ span,
+ });
+ fcx.require_type_is_sized(yield_ty, span, traits::SizedYieldType);
+
+ Ty::new_adt(
+ tcx,
+ tcx.adt_def(tcx.require_lang_item(hir::LangItem::Poll, Some(span))),
+ tcx.mk_args(&[Ty::new_adt(
+ tcx,
+ tcx.adt_def(tcx.require_lang_item(hir::LangItem::Option, Some(span))),
+ tcx.mk_args(&[yield_ty.into()]),
+ )
+ .into()]),
+ )
+ }
hir::CoroutineKind::Async(..) => Ty::new_unit(tcx),
};
@@ -76,7 +98,7 @@ pub(super) fn check_fn<'a, 'tcx>(
fcx.resume_yield_tys = Some((resume_ty, yield_ty));
}
- GatherLocalsVisitor::new(&fcx).visit_body(body);
+ GatherLocalsVisitor::new(fcx).visit_body(body);
// C-variadic fns also have a `VaList` input that's not listed in `fn_sig`
// (as it's created inside the body itself, not passed in from outside).
@@ -94,7 +116,7 @@ pub(super) fn check_fn<'a, 'tcx>(
for (idx, (param_ty, param)) in inputs_fn.chain(maybe_va_list).zip(body.params).enumerate() {
// Check the pattern.
let ty_span = try { inputs_hir?.get(idx)?.span };
- fcx.check_pat_top(&param.pat, param_ty, ty_span, None, None);
+ fcx.check_pat_top(param.pat, param_ty, ty_span, None, None);
// Check that argument is Sized.
if !params_can_be_unsized {
@@ -123,7 +145,7 @@ pub(super) fn check_fn<'a, 'tcx>(
hir::FnRetTy::Return(ty) => ty.span,
};
fcx.require_type_is_sized(declared_ret_ty, return_or_body_span, traits::SizedReturnType);
- fcx.check_return_expr(&body.value, false);
+ fcx.check_return_expr(body.value, false);
// We insert the deferred_coroutine_interiors entry after visiting the body.
// This ensures that all nested coroutines appear before the entry of this coroutine.
@@ -156,7 +178,7 @@ pub(super) fn check_fn<'a, 'tcx>(
// really expected to fail, since the coercions would have failed
// earlier when trying to find a LUB.
let coercion = fcx.ret_coercion.take().unwrap().into_inner();
- let mut actual_return_ty = coercion.complete(&fcx);
+ let mut actual_return_ty = coercion.complete(fcx);
debug!("actual_return_ty = {:?}", actual_return_ty);
if let ty::Dynamic(..) = declared_ret_ty.kind() {
// We have special-cased the case where the function is declared
@@ -214,7 +236,7 @@ fn check_panic_info_fn(tcx: TyCtxt<'_>, fn_id: LocalDefId, fn_sig: ty::FnSig<'_>
// build type `for<'a, 'b> fn(&'a PanicInfo<'b>) -> !`
let panic_info_ty = tcx.type_of(panic_info_did).instantiate(
tcx,
- &[ty::GenericArg::from(ty::Region::new_late_bound(
+ &[ty::GenericArg::from(ty::Region::new_bound(
tcx,
ty::INNERMOST,
ty::BoundRegion { var: ty::BoundVar::from_u32(1), kind: ty::BrAnon },
@@ -222,7 +244,7 @@ fn check_panic_info_fn(tcx: TyCtxt<'_>, fn_id: LocalDefId, fn_sig: ty::FnSig<'_>
);
let panic_info_ref_ty = Ty::new_imm_ref(
tcx,
- ty::Region::new_late_bound(
+ ty::Region::new_bound(
tcx,
ty::INNERMOST,
ty::BoundRegion { var: ty::BoundVar::from_u32(0), kind: ty::BrAnon },
@@ -239,7 +261,7 @@ fn check_panic_info_fn(tcx: TyCtxt<'_>, fn_id: LocalDefId, fn_sig: ty::FnSig<'_>
bounds,
);
- check_function_signature(
+ let _ = check_function_signature(
tcx,
ObligationCause::new(
tcx.def_span(fn_id),
@@ -278,7 +300,7 @@ fn check_lang_start_fn<'tcx>(tcx: TyCtxt<'tcx>, fn_sig: ty::FnSig<'tcx>, def_id:
Abi::Rust,
));
- check_function_signature(
+ let _ = check_function_signature(
tcx,
ObligationCause::new(
tcx.def_span(def_id),
diff --git a/compiler/rustc_hir_typeck/src/closure.rs b/compiler/rustc_hir_typeck/src/closure.rs
index a70ead8e5..d19d30412 100644
--- a/compiler/rustc_hir_typeck/src/closure.rs
+++ b/compiler/rustc_hir_typeck/src/closure.rs
@@ -7,7 +7,7 @@ use rustc_hir as hir;
use rustc_hir::lang_items::LangItem;
use rustc_hir_analysis::astconv::AstConv;
use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
-use rustc_infer::infer::{DefineOpaqueTypes, LateBoundRegionConversionTime};
+use rustc_infer::infer::{BoundRegionConversionTime, DefineOpaqueTypes};
use rustc_infer::infer::{InferOk, InferResult};
use rustc_macros::{TypeFoldable, TypeVisitable};
use rustc_middle::ty::visit::{TypeVisitable, TypeVisitableExt};
@@ -141,7 +141,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
debug!(?sig, ?opt_kind);
let closure_kind_ty = match opt_kind {
- Some(kind) => kind.to_ty(self.tcx),
+ Some(kind) => Ty::from_closure_kind(self.tcx, kind),
// Create a type variable (for now) to represent the closure kind.
// It will be unified during the upvar inference phase (`upvar.rs`)
@@ -181,7 +181,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
.iter_instantiated_copied(self.tcx, args)
.map(|(c, s)| (c.as_predicate(), s)),
),
- ty::Dynamic(ref object_type, ..) => {
+ ty::Dynamic(object_type, ..) => {
let sig = object_type.projection_bounds().find_map(|pb| {
let pb = pb.with_self_ty(self.tcx, self.tcx.types.trait_object_dummy_self);
self.deduce_sig_from_projection(None, pb)
@@ -483,8 +483,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
body: &hir::Body<'_>,
expected_sig: ExpectedSig<'tcx>,
) -> ClosureSignatures<'tcx> {
- let hir = self.tcx.hir();
- let expr_map_node = hir.get_by_def_id(expr_def_id);
+ let expr_map_node = self.tcx.hir_node_by_def_id(expr_def_id);
let expected_args: Vec<_> = expected_sig
.sig
.skip_binder()
@@ -558,7 +557,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// Instantiate (this part of..) S to S', i.e., with fresh variables.
self.instantiate_binder_with_fresh_vars(
hir_ty.span,
- LateBoundRegionConversionTime::FnCall,
+ BoundRegionConversionTime::FnCall,
// (*) binder moved to here
supplied_sig.inputs().rebind(supplied_ty),
)
@@ -583,7 +582,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let supplied_output_ty = self.instantiate_binder_with_fresh_vars(
decl.output.span(),
- LateBoundRegionConversionTime::FnCall,
+ BoundRegionConversionTime::FnCall,
supplied_sig.output(),
);
let cause = &self.misc(decl.output.span());
@@ -624,13 +623,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
trace!("decl = {:#?}", decl);
debug!(?body.coroutine_kind);
- let hir_id = self.tcx.hir().local_def_id_to_hir_id(expr_def_id);
+ let hir_id = self.tcx.local_def_id_to_hir_id(expr_def_id);
let bound_vars = self.tcx.late_bound_vars(hir_id);
// First, convert the types that the user supplied (if any).
let supplied_arguments = decl.inputs.iter().map(|a| astconv.ast_ty_to_ty(a));
let supplied_return = match decl.output {
- hir::FnRetTy::Return(ref output) => astconv.ast_ty_to_ty(&output),
+ hir::FnRetTy::Return(ref output) => astconv.ast_ty_to_ty(output),
hir::FnRetTy::DefaultReturn(_) => match body.coroutine_kind {
// In the case of the async block that we create for a function body,
// we expect the return type of the block to match that of the enclosing
@@ -651,8 +650,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
},
)
}
- Some(hir::CoroutineKind::Gen(hir::CoroutineSource::Fn)) => {
- todo!("gen closures do not exist yet")
+ // All `gen {}` and `async gen {}` must return unit.
+ Some(hir::CoroutineKind::Gen(_) | hir::CoroutineKind::AsyncGen(_)) => {
+ self.tcx.types.unit
}
_ => astconv.ty_infer(None, decl.output.span()),
@@ -819,7 +819,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
});
if let hir::FnRetTy::Return(ref output) = decl.output {
- astconv.ast_ty_to_ty(&output);
+ astconv.ast_ty_to_ty(output);
}
let result = ty::Binder::dummy(self.tcx.mk_fn_sig(
diff --git a/compiler/rustc_hir_typeck/src/coercion.rs b/compiler/rustc_hir_typeck/src/coercion.rs
index 6c03bc3b5..f08af9edc 100644
--- a/compiler/rustc_hir_typeck/src/coercion.rs
+++ b/compiler/rustc_hir_typeck/src/coercion.rs
@@ -36,7 +36,9 @@
//! ```
use crate::FnCtxt;
-use rustc_errors::{struct_span_err, Diagnostic, DiagnosticBuilder, ErrorGuaranteed, MultiSpan};
+use rustc_errors::{
+ struct_span_err, Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed, MultiSpan,
+};
use rustc_hir as hir;
use rustc_hir::def_id::DefId;
use rustc_hir::intravisit::{self, Visitor};
@@ -53,11 +55,10 @@ use rustc_middle::ty::adjustment::{
use rustc_middle::ty::error::TypeError;
use rustc_middle::ty::relate::RelateResult;
use rustc_middle::ty::visit::TypeVisitableExt;
-use rustc_middle::ty::GenericArgsRef;
-use rustc_middle::ty::{self, Ty, TypeAndMut};
+use rustc_middle::ty::{self, GenericArgsRef, Ty, TyCtxt, TypeAndMut};
use rustc_session::parse::feature_err;
use rustc_span::symbol::sym;
-use rustc_span::{self, DesugaringKind};
+use rustc_span::DesugaringKind;
use rustc_target::spec::abi::Abi;
use rustc_trait_selection::infer::InferCtxtExt as _;
use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt as _;
@@ -85,7 +86,7 @@ struct Coerce<'a, 'tcx> {
impl<'a, 'tcx> Deref for Coerce<'a, 'tcx> {
type Target = FnCtxt<'a, 'tcx>;
fn deref(&self) -> &Self::Target {
- &self.fcx
+ self.fcx
}
}
@@ -158,7 +159,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
if self.next_trait_solver() {
if let Ok(res) = &res {
for obligation in &res.obligations {
- if !self.predicate_may_hold(&obligation) {
+ if !self.predicate_may_hold(obligation) {
return Err(TypeError::Mismatch);
}
}
@@ -1041,7 +1042,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
/// Returns false if the coercion creates any obligations that result in
/// errors.
pub fn can_coerce(&self, expr_ty: Ty<'tcx>, target: Ty<'tcx>) -> bool {
- // FIXME(-Ztrait-solver=next): We need to structurally resolve both types here.
+ // FIXME(-Znext-solver): We need to structurally resolve both types here.
let source = self.resolve_vars_with_obligations(expr_ty);
debug!("coercion::can_with_predicates({:?} -> {:?})", source, target);
@@ -1204,14 +1205,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
Adjust::Pointer(PointerCoercion::ClosureFnPointer(a_sig.unsafety()))
}
ty::FnDef(..) => Adjust::Pointer(PointerCoercion::ReifyFnPointer),
- _ => unreachable!(),
+ _ => span_bug!(cause.span, "should not try to coerce a {prev_ty} to a fn pointer"),
};
let next_adjustment = match new_ty.kind() {
ty::Closure(..) => {
Adjust::Pointer(PointerCoercion::ClosureFnPointer(b_sig.unsafety()))
}
ty::FnDef(..) => Adjust::Pointer(PointerCoercion::ReifyFnPointer),
- _ => unreachable!(),
+ _ => span_bug!(new.span, "should not try to coerce a {new_ty} to a fn pointer"),
};
for expr in exprs.iter().map(|e| e.as_coercion_site()) {
self.apply_adjustments(
@@ -1510,7 +1511,7 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> {
expression,
expression_ty,
),
- Expressions::UpFront(ref coercion_sites) => fcx.try_find_coercion_lub(
+ Expressions::UpFront(coercion_sites) => fcx.try_find_coercion_lub(
cause,
&coercion_sites[0..self.pushed],
self.merged_ty(),
@@ -1572,7 +1573,9 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> {
// any superfluous errors we might encounter while trying to
// emit or provide suggestions on how to fix the initial error.
fcx.set_tainted_by_errors(
- fcx.tcx.sess.delay_span_bug(cause.span, "coercion error but no error emitted"),
+ fcx.tcx
+ .sess
+ .span_delayed_bug(cause.span, "coercion error but no error emitted"),
);
let (expected, found) = if label_expression_as_expected {
// In the case where this is a "forced unit", like
@@ -1660,12 +1663,15 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> {
None,
Some(coercion_error),
);
- }
-
- if visitor.ret_exprs.len() > 0
- && let Some(expr) = expression
- {
- self.note_unreachable_loop_return(&mut err, &expr, &visitor.ret_exprs);
+ if visitor.ret_exprs.len() > 0 {
+ self.note_unreachable_loop_return(
+ &mut err,
+ fcx.tcx,
+ &expr,
+ &visitor.ret_exprs,
+ expected,
+ );
+ }
}
let reported = err.emit_unless(unsized_return);
@@ -1678,8 +1684,10 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> {
fn note_unreachable_loop_return(
&self,
err: &mut Diagnostic,
+ tcx: TyCtxt<'tcx>,
expr: &hir::Expr<'tcx>,
ret_exprs: &Vec<&'tcx hir::Expr<'tcx>>,
+ ty: Ty<'tcx>,
) {
let hir::ExprKind::Loop(_, _, _, loop_span) = expr.kind else {
return;
@@ -1704,10 +1712,77 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> {
ret_exprs.len() - MAXITER
));
}
- err.help(
- "return a value for the case when the loop has zero elements to iterate on, or \
- consider changing the return type to account for that possibility",
- );
+ let hir = tcx.hir();
+ let item = hir.get_parent_item(expr.hir_id);
+ let ret_msg = "return a value for the case when the loop has zero elements to iterate on";
+ let ret_ty_msg =
+ "otherwise consider changing the return type to account for that possibility";
+ if let Some(node) = tcx.opt_hir_node(item.into())
+ && let Some(body_id) = node.body_id()
+ && let Some(sig) = node.fn_sig()
+ && let hir::ExprKind::Block(block, _) = hir.body(body_id).value.kind
+ && !ty.is_never()
+ {
+ let indentation = if let None = block.expr
+ && let [.., last] = &block.stmts
+ {
+ tcx.sess.source_map().indentation_before(last.span).unwrap_or_else(String::new)
+ } else if let Some(expr) = block.expr {
+ tcx.sess.source_map().indentation_before(expr.span).unwrap_or_else(String::new)
+ } else {
+ String::new()
+ };
+ if let None = block.expr
+ && let [.., last] = &block.stmts
+ {
+ err.span_suggestion_verbose(
+ last.span.shrink_to_hi(),
+ ret_msg,
+ format!("\n{indentation}/* `{ty}` value */"),
+ Applicability::MaybeIncorrect,
+ );
+ } else if let Some(expr) = block.expr {
+ err.span_suggestion_verbose(
+ expr.span.shrink_to_hi(),
+ ret_msg,
+ format!("\n{indentation}/* `{ty}` value */"),
+ Applicability::MaybeIncorrect,
+ );
+ }
+ let mut sugg = match sig.decl.output {
+ hir::FnRetTy::DefaultReturn(span) => {
+ vec![(span, " -> Option<()>".to_string())]
+ }
+ hir::FnRetTy::Return(ty) => {
+ vec![
+ (ty.span.shrink_to_lo(), "Option<".to_string()),
+ (ty.span.shrink_to_hi(), ">".to_string()),
+ ]
+ }
+ };
+ for ret_expr in ret_exprs {
+ match ret_expr.kind {
+ hir::ExprKind::Ret(Some(expr)) => {
+ sugg.push((expr.span.shrink_to_lo(), "Some(".to_string()));
+ sugg.push((expr.span.shrink_to_hi(), ")".to_string()));
+ }
+ hir::ExprKind::Ret(None) => {
+ sugg.push((ret_expr.span.shrink_to_hi(), " Some(())".to_string()));
+ }
+ _ => {}
+ }
+ }
+ if let None = block.expr
+ && let [.., last] = &block.stmts
+ {
+ sugg.push((last.span.shrink_to_hi(), format!("\n{indentation}None")));
+ } else if let Some(expr) = block.expr {
+ sugg.push((expr.span.shrink_to_hi(), format!("\n{indentation}None")));
+ }
+ err.multipart_suggestion(ret_ty_msg, sugg, Applicability::MaybeIncorrect);
+ } else {
+ err.help(format!("{ret_msg}, {ret_ty_msg}"));
+ }
}
fn report_return_mismatched_types<'a>(
@@ -1724,7 +1799,7 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> {
let mut err = fcx.err_ctxt().report_mismatched_types(cause, expected, found, ty_err);
let parent_id = fcx.tcx.hir().parent_id(id);
- let parent = fcx.tcx.hir().get(parent_id);
+ let parent = fcx.tcx.hir_node(parent_id);
if let Some(expr) = expression
&& let hir::Node::Expr(hir::Expr {
kind: hir::ExprKind::Closure(&hir::Closure { body, .. }),
@@ -1738,6 +1813,7 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> {
// label pointing out the cause for the type coercion will be wrong
// as prior return coercions would not be relevant (#57664).
let fn_decl = if let (Some(expr), Some(blk_id)) = (expression, blk_id) {
+ fcx.suggest_missing_semicolon(&mut err, expr, expected, false);
let pointing_at_return_type =
fcx.suggest_mismatched_types_on_tail(&mut err, expr, expected, found, blk_id);
if let (Some(cond_expr), true, false) = (
@@ -1772,7 +1848,7 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> {
if blk_id.is_none() {
fcx.suggest_missing_return_type(
&mut err,
- &fn_decl,
+ fn_decl,
expected,
found,
can_suggest,
@@ -1782,7 +1858,7 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> {
}
let parent_id = fcx.tcx.hir().get_parent_item(id);
- let parent_item = fcx.tcx.hir().get_by_def_id(parent_id.def_id);
+ let parent_item = fcx.tcx.hir_node_by_def_id(parent_id.def_id);
if let (Some(expr), Some(_), Some((fn_id, fn_decl, _, _))) =
(expression, blk_id, fcx.get_node_fn_decl(parent_item))
@@ -1865,12 +1941,12 @@ where
impl AsCoercionSite for ! {
fn as_coercion_site(&self) -> &hir::Expr<'_> {
- unreachable!()
+ *self
}
}
impl AsCoercionSite for hir::Arm<'_> {
fn as_coercion_site(&self) -> &hir::Expr<'_> {
- &self.body
+ self.body
}
}
diff --git a/compiler/rustc_hir_typeck/src/demand.rs b/compiler/rustc_hir_typeck/src/demand.rs
index acaa3e02f..8b666c634 100644
--- a/compiler/rustc_hir_typeck/src/demand.rs
+++ b/compiler/rustc_hir_typeck/src/demand.rs
@@ -31,9 +31,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}
self.annotate_alternative_method_deref(err, expr, error);
+ self.explain_self_literal(err, expr, expected, expr_ty);
// Use `||` to give these suggestions a precedence
let suggested = self.suggest_missing_parentheses(err, expr)
+ || self.suggest_missing_unwrap_expect(err, expr, expected, expr_ty)
|| self.suggest_remove_last_method_call(err, expr, expected)
|| self.suggest_associated_const(err, expr, expected)
|| self.suggest_deref_ref_or_into(err, expr, expected, expr_ty, expected_ty_expr)
@@ -49,8 +51,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|| self.suggest_into(err, expr, expr_ty, expected)
|| self.suggest_floating_point_literal(err, expr, expected)
|| self.suggest_null_ptr_for_literal_zero_given_to_ptr_arg(err, expr, expected)
- || self.suggest_coercing_result_via_try_operator(err, expr, expected, expr_ty)
- || self.suggest_missing_unwrap_expect(err, expr, expected, expr_ty);
+ || self.suggest_coercing_result_via_try_operator(err, expr, expected, expr_ty);
if !suggested {
self.note_source_of_type_mismatch_constraint(
@@ -183,7 +184,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
self.register_predicates(obligations);
None
}
- Err(e) => Some(self.err_ctxt().report_mismatched_types(&cause, expected, actual, e)),
+ Err(e) => Some(self.err_ctxt().report_mismatched_types(cause, expected, actual, e)),
}
}
@@ -255,7 +256,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
self.adjust_expr_for_assert_eq_macro(&mut expr, &mut expected_ty_expr);
- self.set_tainted_by_errors(self.tcx.sess.delay_span_bug(
+ self.set_tainted_by_errors(self.tcx.sess.span_delayed_bug(
expr.span,
"`TypeError` when attempting coercion but no error emitted",
));
@@ -288,7 +289,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let hir::def::Res::Local(local_hir_id) = p.res else {
return false;
};
- let hir::Node::Pat(pat) = hir.get(local_hir_id) else {
+ let hir::Node::Pat(pat) = self.tcx.hir_node(local_hir_id) else {
return false;
};
let (init_ty_hir_id, init) = match hir.get_parent(pat.hir_id) {
@@ -330,13 +331,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
ty_op: |ty| {
if let ty::Infer(infer) = ty.kind() {
match infer {
- ty::InferTy::TyVar(_) => self.next_ty_var(TypeVariableOrigin {
+ ty::TyVar(_) => self.next_ty_var(TypeVariableOrigin {
kind: TypeVariableOriginKind::MiscVariable,
span: DUMMY_SP,
}),
- ty::InferTy::IntVar(_) => self.next_int_var(),
- ty::InferTy::FloatVar(_) => self.next_float_var(),
- _ => bug!(),
+ ty::IntVar(_) => self.next_int_var(),
+ ty::FloatVar(_) => self.next_float_var(),
+ ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_) => {
+ bug!("unexpected fresh ty outside of the trait solver")
+ }
}
} else {
ty
@@ -556,7 +559,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
hir::Node::Stmt(hir::Stmt { kind: hir::StmtKind::Semi(&ref p), .. })
| hir::Node::Block(hir::Block { expr: Some(&ref p), .. })
| hir::Node::Expr(&ref p),
- ) = self.tcx.hir().find(parent_id)
+ ) = self.tcx.opt_hir_node(parent_id)
else {
break;
};
@@ -569,7 +572,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let mut direct = false;
loop {
// Climb the HIR tree to find the (desugared) `loop` this `break` corresponds to.
- let parent = match self.tcx.hir().find(parent_id) {
+ let parent = match self.tcx.opt_hir_node(parent_id) {
Some(hir::Node::Expr(&ref parent)) => {
parent_id = self.tcx.hir().parent_id(parent.hir_id);
parent
@@ -671,7 +674,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
error: Option<TypeError<'tcx>>,
) {
let parent = self.tcx.hir().parent_id(expr.hir_id);
- match (self.tcx.hir().find(parent), error) {
+ match (self.tcx.opt_hir_node(parent), error) {
(Some(hir::Node::Local(hir::Local { ty: Some(ty), init: Some(init), .. })), _)
if init.hir_id == expr.hir_id =>
{
@@ -716,7 +719,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
None,
hir::Path { res: hir::def::Res::Local(hir_id), .. },
)) => {
- if let Some(hir::Node::Pat(pat)) = self.tcx.hir().find(*hir_id) {
+ if let Some(hir::Node::Pat(pat)) = self.tcx.opt_hir_node(*hir_id) {
primary_span = pat.span;
secondary_span = pat.span;
match self.tcx.hir().find_parent(pat.hir_id) {
@@ -789,7 +792,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
return;
};
let Some(hir::Node::Expr(hir::Expr { kind: hir::ExprKind::Assign(lhs, rhs, _), .. })) =
- self.tcx.hir().find(parent)
+ self.tcx.opt_hir_node(parent)
else {
return;
};
@@ -861,7 +864,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
mutability,
),
),
- match &args[..] {
+ match &args {
[] => (base.span.shrink_to_hi().with_hi(deref.span.hi()), ")".to_string()),
[first, ..] => (base.span.between(first.span), ", ".to_string()),
},
@@ -882,7 +885,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let container_id = pick.item.container_id(self.tcx);
let container = with_no_trimmed_paths!(self.tcx.def_path_str(container_id));
for def_id in pick.import_ids {
- let hir_id = self.tcx.hir().local_def_id_to_hir_id(def_id);
+ let hir_id = self.tcx.local_def_id_to_hir_id(def_id);
path_span.push_span_label(
self.tcx.hir().span(hir_id),
format!("`{container}` imported here"),
@@ -1013,8 +1016,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
hir::Path { res: hir::def::Res::Local(bind_hir_id), .. },
)) = expr.kind
{
- let bind = self.tcx.hir().find(*bind_hir_id);
- let parent = self.tcx.hir().find(self.tcx.hir().parent_id(*bind_hir_id));
+ let bind = self.tcx.opt_hir_node(*bind_hir_id);
+ let parent = self.tcx.opt_hir_node(self.tcx.hir().parent_id(*bind_hir_id));
if let Some(hir::Node::Pat(hir::Pat {
kind: hir::PatKind::Binding(_, _hir_id, _, _),
..
@@ -1027,6 +1030,59 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
return false;
}
+ fn explain_self_literal(
+ &self,
+ err: &mut Diagnostic,
+ expr: &hir::Expr<'tcx>,
+ expected: Ty<'tcx>,
+ found: Ty<'tcx>,
+ ) {
+ match expr.peel_drop_temps().kind {
+ hir::ExprKind::Struct(
+ hir::QPath::Resolved(
+ None,
+ hir::Path { res: hir::def::Res::SelfTyAlias { alias_to, .. }, span, .. },
+ ),
+ ..,
+ )
+ | hir::ExprKind::Call(
+ hir::Expr {
+ kind:
+ hir::ExprKind::Path(hir::QPath::Resolved(
+ None,
+ hir::Path {
+ res: hir::def::Res::SelfTyAlias { alias_to, .. },
+ span,
+ ..
+ },
+ )),
+ ..
+ },
+ ..,
+ ) => {
+ if let Some(hir::Node::Item(hir::Item {
+ kind: hir::ItemKind::Impl(hir::Impl { self_ty, .. }),
+ ..
+ })) = self.tcx.hir().get_if_local(*alias_to)
+ {
+ err.span_label(self_ty.span, "this is the type of the `Self` literal");
+ }
+ if let ty::Adt(e_def, e_args) = expected.kind()
+ && let ty::Adt(f_def, _f_args) = found.kind()
+ && e_def == f_def
+ {
+ err.span_suggestion_verbose(
+ *span,
+ "use the type name directly",
+ self.tcx.value_path_str_with_args(*alias_to, e_args),
+ Applicability::MaybeIncorrect,
+ );
+ }
+ }
+ _ => {}
+ }
+ }
+
fn note_wrong_return_ty_due_to_generic_arg(
&self,
err: &mut Diagnostic,
diff --git a/compiler/rustc_hir_typeck/src/diverges.rs b/compiler/rustc_hir_typeck/src/diverges.rs
index 29fcc61cb..0b559a085 100644
--- a/compiler/rustc_hir_typeck/src/diverges.rs
+++ b/compiler/rustc_hir_typeck/src/diverges.rs
@@ -1,4 +1,4 @@
-use rustc_span::{self, Span, DUMMY_SP};
+use rustc_span::{Span, DUMMY_SP};
use std::{cmp, ops};
/// Tracks whether executing a node may exit normally (versus
diff --git a/compiler/rustc_hir_typeck/src/errors.rs b/compiler/rustc_hir_typeck/src/errors.rs
index aff1baa19..ff03cf16a 100644
--- a/compiler/rustc_hir_typeck/src/errors.rs
+++ b/compiler/rustc_hir_typeck/src/errors.rs
@@ -573,13 +573,13 @@ impl rustc_errors::AddToDiagnostic for CastUnknownPointerSub {
{
match self {
CastUnknownPointerSub::To(span) => {
- let msg = f(diag, crate::fluent_generated::hir_typeck_label_to.into());
+ let msg = f(diag, crate::fluent_generated::hir_typeck_label_to);
diag.span_label(span, msg);
- let msg = f(diag, crate::fluent_generated::hir_typeck_note.into());
+ let msg = f(diag, crate::fluent_generated::hir_typeck_note);
diag.note(msg);
}
CastUnknownPointerSub::From(span) => {
- let msg = f(diag, crate::fluent_generated::hir_typeck_label_from.into());
+ let msg = f(diag, crate::fluent_generated::hir_typeck_label_from);
diag.span_label(span, msg);
}
}
@@ -626,7 +626,7 @@ pub struct SuggestConvertViaMethod<'tcx> {
pub span: Span,
#[suggestion_part(code = "")]
pub borrow_removal_span: Option<Span>,
- pub sugg: &'static str,
+ pub sugg: String,
pub expected: Ty<'tcx>,
pub found: Ty<'tcx>,
}
diff --git a/compiler/rustc_hir_typeck/src/expectation.rs b/compiler/rustc_hir_typeck/src/expectation.rs
index 35e5fb769..ff84e753d 100644
--- a/compiler/rustc_hir_typeck/src/expectation.rs
+++ b/compiler/rustc_hir_typeck/src/expectation.rs
@@ -1,6 +1,6 @@
use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
use rustc_middle::ty::{self, Ty};
-use rustc_span::{self, Span};
+use rustc_span::Span;
use super::Expectation::*;
use super::FnCtxt;
diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs
index 9f439a2b3..7bd2c3f8b 100644
--- a/compiler/rustc_hir_typeck/src/expr.rs
+++ b/compiler/rustc_hir_typeck/src/expr.rs
@@ -21,7 +21,7 @@ use crate::{
TupleArgumentsFlag::DontTupleArguments,
};
use rustc_ast as ast;
-use rustc_data_structures::fx::FxHashMap;
+use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_data_structures::stack::ensure_sufficient_stack;
use rustc_errors::{
pluralize, struct_span_err, AddToDiagnostic, Applicability, Diagnostic, DiagnosticBuilder,
@@ -75,7 +75,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// coercions from ! to `expected`.
if ty.is_never() {
if let Some(adjustments) = self.typeck_results.borrow().adjustments().get(expr.hir_id) {
- let reported = self.tcx().sess.delay_span_bug(
+ let reported = self.tcx().sess.span_delayed_bug(
expr.span,
"expression with never type wound up being adjusted",
);
@@ -277,7 +277,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let tcx = self.tcx;
match expr.kind {
- ExprKind::Lit(ref lit) => self.check_lit(&lit, 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) => {
self.check_expr_assign(expr, expected, lhs, rhs, span)
@@ -289,8 +289,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
ExprKind::AddrOf(kind, mutbl, oprnd) => {
self.check_expr_addr_of(kind, mutbl, oprnd, expected, expr)
}
- ExprKind::Path(QPath::LangItem(lang_item, _, hir_id)) => {
- self.check_lang_item_path(lang_item, expr, hir_id)
+ ExprKind::Path(QPath::LangItem(lang_item, _)) => {
+ self.check_lang_item_path(lang_item, expr)
}
ExprKind::Path(ref qpath) => self.check_expr_path(qpath, expr, &[]),
ExprKind::InlineAsm(asm) => {
@@ -298,9 +298,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
self.deferred_asm_checks.borrow_mut().push((asm, expr.hir_id));
self.check_expr_asm(asm)
}
- ExprKind::OffsetOf(container, ref fields) => {
- self.check_offset_of(container, fields, expr)
- }
+ ExprKind::OffsetOf(container, fields) => self.check_offset_of(container, fields, expr),
ExprKind::Break(destination, ref expr_opt) => {
self.check_expr_break(destination, expr_opt.as_deref(), expr)
}
@@ -319,17 +317,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
self.check_expr_loop(body, source, expected, expr)
}
ExprKind::Match(discrim, arms, match_src) => {
- self.check_match(expr, &discrim, arms, expected, match_src)
+ self.check_match(expr, discrim, arms, expected, match_src)
}
ExprKind::Closure(closure) => self.check_expr_closure(closure, expr.span, expected),
- ExprKind::Block(body, _) => self.check_block_with_expected(&body, expected),
- ExprKind::Call(callee, args) => self.check_call(expr, &callee, args, expected),
+ ExprKind::Block(body, _) => self.check_block_with_expected(body, expected),
+ ExprKind::Call(callee, args) => self.check_call(expr, callee, args, expected),
ExprKind::MethodCall(segment, receiver, args, _) => {
self.check_method_call(expr, segment, receiver, args, expected)
}
ExprKind::Cast(e, t) => self.check_expr_cast(e, t, expr),
ExprKind::Type(e, t) => {
- let ascribed_ty = self.to_ty_saving_user_provided_ty(&t);
+ let ascribed_ty = self.to_ty_saving_user_provided_ty(t);
let ty = self.check_expr_with_hint(e, ascribed_ty);
self.demand_eqtype(e.span, ascribed_ty, ty);
ascribed_ty
@@ -347,7 +345,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
ExprKind::Struct(qpath, fields, ref base_expr) => {
self.check_expr_struct(expr, expected, qpath, fields, base_expr)
}
- ExprKind::Field(base, field) => self.check_field(expr, &base, field, expected),
+ ExprKind::Field(base, field) => self.check_field(expr, base, field, expected),
ExprKind::Index(base, idx, brackets_span) => {
self.check_expr_index(base, idx, expr, brackets_span)
}
@@ -368,7 +366,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
hir::UnOp::Not | hir::UnOp::Neg => expected,
hir::UnOp::Deref => NoExpectation,
};
- let mut oprnd_t = self.check_expr_with_expectation(&oprnd, expected_inner);
+ let mut oprnd_t = self.check_expr_with_expectation(oprnd, expected_inner);
if !oprnd_t.references_error() {
oprnd_t = self.structurally_resolve_type(expr.span, oprnd_t);
@@ -436,7 +434,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}
});
let ty =
- self.check_expr_with_expectation_and_needs(&oprnd, hint, Needs::maybe_mut_place(mutbl));
+ self.check_expr_with_expectation_and_needs(oprnd, hint, Needs::maybe_mut_place(mutbl));
let tm = ty::TypeAndMut { ty, mutbl };
match kind {
@@ -499,9 +497,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
&self,
lang_item: hir::LangItem,
expr: &'tcx hir::Expr<'tcx>,
- hir_id: Option<hir::HirId>,
) -> Ty<'tcx> {
- self.resolve_lang_item_path(lang_item, expr.span, expr.hir_id, hir_id).1
+ self.resolve_lang_item_path(lang_item, expr.span, expr.hir_id).1
}
pub(crate) fn check_expr_path(
@@ -517,7 +514,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
Res::Err => {
self.suggest_assoc_method_call(segs);
let e =
- self.tcx.sess.delay_span_bug(qpath.span(), "`Res::Err` but no error emitted");
+ self.tcx.sess.span_delayed_bug(qpath.span(), "`Res::Err` but no error emitted");
self.set_tainted_by_errors(e);
Ty::new_error(tcx, e)
}
@@ -528,14 +525,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
_ => self.instantiate_value_path(segs, opt_ty, res, expr.span, expr.hir_id).0,
};
- if let ty::FnDef(did, callee_args) = *ty.kind() {
+ if let ty::FnDef(did, _) = *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
{
@@ -564,7 +556,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let span = args.get(i).map(|a| a.span).unwrap_or(expr.span);
let input = self.instantiate_binder_with_fresh_vars(
span,
- infer::LateBoundRegionConversionTime::FnCall,
+ infer::BoundRegionConversionTime::FnCall,
fn_sig.input(i),
);
self.require_type_is_sized_deferred(
@@ -582,7 +574,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// with fresh vars.
let output = self.instantiate_binder_with_fresh_vars(
expr.span,
- infer::LateBoundRegionConversionTime::FnCall,
+ infer::BoundRegionConversionTime::FnCall,
fn_sig.output(),
);
self.require_type_is_sized_deferred(output, expr.span, traits::SizedReturnType);
@@ -626,15 +618,18 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}
};
- let coerce_to = match opt_coerce_to {
- Some(c) => c,
- None => {
- // If the loop context is not a `loop { }`, then break with
- // a value is illegal, and `opt_coerce_to` will be `None`.
- // Return error in that case (#114529).
- return Ty::new_misc_error(tcx);
- }
- };
+ // If the loop context is not a `loop { }`, then break with
+ // a value is illegal, and `opt_coerce_to` will be `None`.
+ // Set expectation to error in that case and set tainted
+ // by error (#114529)
+ let coerce_to = opt_coerce_to.unwrap_or_else(|| {
+ let guar = tcx.sess.span_delayed_bug(
+ expr.span,
+ "illegal break with value found but no error reported",
+ );
+ self.set_tainted_by_errors(guar);
+ Ty::new_error(tcx, guar)
+ });
// Recurse without `enclosing_breakables` borrowed.
e_ty = self.check_expr_with_hint(e, coerce_to);
@@ -660,7 +655,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
};
if let Some(ref mut coerce) = ctxt.coerce {
- if let Some(ref e) = expr_opt {
+ if let Some(e) = expr_opt {
coerce.coerce(self, &cause, e, e_ty);
} else {
assert!(e_ty.is_unit());
@@ -669,11 +664,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
self,
&cause,
|mut err| {
+ self.suggest_missing_semicolon(&mut err, expr, e_ty, false);
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);
+ self.annotate_loop_expected_due_to_inference(err, expr, error);
if let Some(val) = ty_kind_suggestion(ty) {
err.span_suggestion_verbose(
expr.span.shrink_to_hi(),
@@ -887,7 +883,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.def_id)
+ })) = self.tcx.opt_hir_node_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.
@@ -1001,7 +997,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
then: impl FnOnce(&hir::Expr<'_>),
) {
let mut parent = self.tcx.hir().parent_id(original_expr_id);
- while let Some(node) = self.tcx.hir().find(parent) {
+ while let Some(node) = self.tcx.opt_hir_node(parent) {
match node {
hir::Node::Expr(hir::Expr {
kind:
@@ -1133,8 +1129,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// The likely cause of this is `if foo = bar { .. }`.
let actual_ty = Ty::new_unit(self.tcx);
let mut err = self.demand_suptype_diag(expr.span, expected_ty, actual_ty).unwrap();
- let lhs_ty = self.check_expr(&lhs);
- let rhs_ty = self.check_expr(&rhs);
+ let lhs_ty = self.check_expr(lhs);
+ 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(
@@ -1145,7 +1141,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
{
// if x == 1 && y == 2 { .. }
// +
- let actual_lhs_ty = self.check_expr(&rhs_expr);
+ 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, .. },
@@ -1155,7 +1151,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
{
// if x == 1 && y == 2 { .. }
// +
- let actual_rhs_ty = self.check_expr(&lhs_expr);
+ let actual_rhs_ty = self.check_expr(lhs_expr);
(Applicability::MaybeIncorrect, self.can_coerce(actual_rhs_ty, lhs_ty))
} else {
(Applicability::MaybeIncorrect, false)
@@ -1192,7 +1188,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
return Ty::new_error(self.tcx, reported);
}
- let lhs_ty = self.check_expr_with_needs(&lhs, Needs::MutPlace);
+ let lhs_ty = self.check_expr_with_needs(lhs, Needs::MutPlace);
let suggest_deref_binop = |err: &mut Diagnostic, rhs_ty: Ty<'tcx>| {
if let Some(lhs_deref_ty) = self.deref_once_mutably_for_diagnostic(lhs_ty) {
@@ -1219,7 +1215,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// 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);
+ let rhs_ty = self.check_expr_with_hint(rhs, lhs_ty);
if let (_, Some(mut diag)) =
self.demand_coerce_diag(rhs, rhs_ty, lhs_ty, Some(lhs), AllowTwoPhase::No)
{
@@ -1280,7 +1276,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
};
let (ctxt, ()) = self.with_breakable_ctxt(expr.hir_id, ctxt, || {
- self.check_block_no_value(&body);
+ self.check_block_no_value(body);
});
if ctxt.may_break {
@@ -1296,7 +1292,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// permit break with a value [1].
if ctxt.coerce.is_none() && !ctxt.may_break {
// [1]
- self.tcx.sess.delay_span_bug(body.span, "no coercion, but loop may not break");
+ self.tcx.sess.span_delayed_bug(body.span, "no coercion, but loop may not break");
}
ctxt.coerce.map(|c| c.complete(self)).unwrap_or_else(|| Ty::new_unit(self.tcx))
}
@@ -1310,7 +1306,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
args: &'tcx [hir::Expr<'tcx>],
expected: Expectation<'tcx>,
) -> Ty<'tcx> {
- let rcvr_t = self.check_expr(&rcvr);
+ let rcvr_t = self.check_expr(rcvr);
// no need to check for bot/err -- callee does that
let rcvr_t = self.structurally_resolve_type(rcvr.span, rcvr_t);
let span = segment.ident.span;
@@ -1319,9 +1315,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
Ok(method) => {
// We could add a "consider `foo::<params>`" suggestion here, but I wasn't able to
// trigger this codepath causing `structurally_resolve_type` to emit an error.
-
- self.enforce_context_effects(expr.hir_id, expr.span, method.def_id, method.args);
- self.write_method_call(expr.hir_id, method);
+ self.write_method_call_and_enforce_effects(expr.hir_id, expr.span, method);
Ok(method)
}
Err(error) => {
@@ -1344,7 +1338,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
};
// Call the generic checker.
- self.check_method_argument_types(span, expr, method, &args, DontTupleArguments, expected)
+ self.check_method_argument_types(span, expr, method, args, DontTupleArguments, expected)
}
fn check_expr_cast(
@@ -1442,12 +1436,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
&& let hir::ArrayLen::Body(hir::AnonConst { hir_id, .. }) = length
&& let Some(span) = self.tcx.hir().opt_span(hir_id)
{
- match self
- .tcx
- .sess
- .diagnostic()
- .steal_diagnostic(span, StashKey::UnderscoreForArrayLengths)
- {
+ match self.tcx.sess.dcx().steal_diagnostic(span, StashKey::UnderscoreForArrayLengths) {
Some(mut err) => {
err.span_suggestion(
span,
@@ -1475,7 +1464,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let fcx = FnCtxt::new(self, self.param_env, def_id);
crate::GatherLocalsVisitor::new(&fcx).visit_body(body);
- let ty = fcx.check_expr_with_expectation(&body.value, expected);
+ let ty = fcx.check_expr_with_expectation(body.value, expected);
fcx.require_type_is_sized(ty, body.value.span, traits::ConstSized);
fcx.write_ty(block.hir_id, ty);
ty
@@ -1504,7 +1493,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let (element_ty, t) = match uty {
Some(uty) => {
- self.check_expr_coercible_to_type(&element, uty, None);
+ self.check_expr_coercible_to_type(element, uty, None);
(uty, uty)
}
None => {
@@ -1512,7 +1501,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
kind: TypeVariableOriginKind::MiscVariable,
span: element.span,
});
- let element_ty = self.check_expr_has_type_or_error(&element, ty, |_| {});
+ let element_ty = self.check_expr_has_type_or_error(element, ty, |_| {});
(element_ty, ty)
}
};
@@ -1608,10 +1597,10 @@ 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_coercible_to_type(&e, ety, None);
+ self.check_expr_coercible_to_type(e, ety, None);
ety
}
- _ => self.check_expr_with_expectation(&e, NoExpectation),
+ _ => self.check_expr_with_expectation(e, NoExpectation),
});
let tuple = Ty::new_tup_from_iter(self.tcx, elt_ts_iter);
if let Err(guar) = tuple.error_reported() {
@@ -1737,9 +1726,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// Make sure to give a type to the field even if there's
// an error, so we can continue type-checking.
- let ty = self.check_expr_with_hint(&field.expr, field_type);
+ let ty = self.check_expr_with_hint(field.expr, field_type);
let (_, diag) =
- self.demand_coerce_diag(&field.expr, ty, field_type, None, AllowTwoPhase::No);
+ self.demand_coerce_diag(field.expr, ty, field_type, None, AllowTwoPhase::No);
if let Some(mut diag) = diag {
if idx == ast_fields.len() - 1 {
@@ -1897,7 +1886,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
.collect();
if !private_fields.is_empty() {
- self.report_private_fields(adt_ty, span, private_fields, ast_fields);
+ self.report_private_fields(adt_ty, span, expr.span, private_fields, ast_fields);
} else {
self.report_missing_fields(
adt_ty,
@@ -1917,10 +1906,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
base_expr: &'tcx Option<&'tcx hir::Expr<'tcx>>,
) {
for field in fields {
- self.check_expr(&field.expr);
+ self.check_expr(field.expr);
}
if let Some(base) = *base_expr {
- self.check_expr(&base);
+ self.check_expr(base);
}
}
@@ -1933,7 +1922,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
/// 8 | foo::Foo {};
/// | ^^^^^^^^ missing `you_can_use_this_field`
///
- /// error: aborting due to previous error
+ /// error: aborting due to 1 previous error
/// ```
fn report_missing_fields(
&self,
@@ -2008,11 +1997,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
!= range_def_id
{
// Suppress any range expr type mismatches
- if let Some(mut diag) = self
- .tcx
- .sess
- .diagnostic()
- .steal_diagnostic(last_expr_field.span, StashKey::MaybeFruTypo)
+ if let Some(mut diag) =
+ self.tcx.sess.dcx().steal_diagnostic(last_expr_field.span, StashKey::MaybeFruTypo)
{
diag.delay_as_bug();
}
@@ -2050,12 +2036,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
/// 8 | foo::Foo {};
/// | ^^^^^^^^
///
- /// error: aborting due to previous error
+ /// error: aborting due to 1 previous error
/// ```
fn report_private_fields(
&self,
adt_ty: Ty<'tcx>,
span: Span,
+ expr_span: Span,
private_fields: Vec<&ty::FieldDef>,
used_fields: &'tcx [hir::ExprField<'tcx>],
) {
@@ -2092,14 +2079,90 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let names = names.iter().map(|name| format!("`{name}`")).collect::<Vec<_>>();
format!("{} and `{last}` ", names.join(", "))
}
- [] => unreachable!(),
+ [] => bug!("expected at least one private field to report"),
};
err.note(format!(
- "... and other private field{s} {names}that {were} not provided",
+ "{}private field{s} {names}that {were} not provided",
+ if used_fields.is_empty() { "" } else { "...and other " },
s = pluralize!(remaining_private_fields_len),
were = pluralize!("was", remaining_private_fields_len),
));
}
+
+ if let ty::Adt(def, _) = adt_ty.kind() {
+ let def_id = def.did();
+ let mut items = self
+ .tcx
+ .inherent_impls(def_id)
+ .iter()
+ .flat_map(|i| self.tcx.associated_items(i).in_definition_order())
+ // Only assoc fn with no receivers.
+ .filter(|item| {
+ matches!(item.kind, ty::AssocKind::Fn) && !item.fn_has_self_parameter
+ })
+ .filter_map(|item| {
+ // Only assoc fns that return `Self`
+ let fn_sig = self.tcx.fn_sig(item.def_id).skip_binder();
+ let ret_ty = fn_sig.output();
+ let ret_ty =
+ self.tcx.normalize_erasing_late_bound_regions(self.param_env, ret_ty);
+ if !self.can_eq(self.param_env, ret_ty, adt_ty) {
+ return None;
+ }
+ let input_len = fn_sig.inputs().skip_binder().len();
+ let order = !item.name.as_str().starts_with("new");
+ Some((order, item.name, input_len))
+ })
+ .collect::<Vec<_>>();
+ items.sort_by_key(|(order, _, _)| *order);
+ let suggestion = |name, args| {
+ format!(
+ "::{name}({})",
+ std::iter::repeat("_").take(args).collect::<Vec<_>>().join(", ")
+ )
+ };
+ match &items[..] {
+ [] => {}
+ [(_, name, args)] => {
+ err.span_suggestion_verbose(
+ span.shrink_to_hi().with_hi(expr_span.hi()),
+ format!("you might have meant to use the `{name}` associated function"),
+ suggestion(name, *args),
+ Applicability::MaybeIncorrect,
+ );
+ }
+ _ => {
+ err.span_suggestions(
+ span.shrink_to_hi().with_hi(expr_span.hi()),
+ "you might have meant to use an associated function to build this type",
+ items
+ .iter()
+ .map(|(_, name, args)| suggestion(name, *args))
+ .collect::<Vec<String>>(),
+ Applicability::MaybeIncorrect,
+ );
+ }
+ }
+ if let Some(default_trait) = self.tcx.get_diagnostic_item(sym::Default)
+ && self
+ .infcx
+ .type_implements_trait(default_trait, [adt_ty], self.param_env)
+ .may_apply()
+ {
+ err.multipart_suggestion(
+ "consider using the `Default` trait",
+ vec![
+ (span.shrink_to_lo(), "<".to_string()),
+ (
+ span.shrink_to_hi().with_hi(expr_span.hi()),
+ " as std::default::Default>::default()".to_string(),
+ ),
+ ],
+ Applicability::MaybeIncorrect,
+ );
+ }
+ }
+
err.emit();
}
@@ -2116,7 +2179,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let guar = self
.tcx
.sess
- .delay_span_bug(expr.span, "parser recovered but no error was emitted");
+ .span_delayed_bug(expr.span, "parser recovered but no error was emitted");
self.set_tainted_by_errors(guar);
return guar;
}
@@ -2191,7 +2254,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
if let Some(field_name) =
find_best_match_for_name(&available_field_names, field.ident.name, None)
{
- err.span_suggestion(
+ err.span_label(field.ident.span, "unknown field");
+ err.span_suggestion_verbose(
field.ident.span,
"a field with a similar name exists",
field_name,
@@ -2274,7 +2338,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
match deref_base_ty.kind() {
ty::Adt(base_def, args) 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 body_hir_id = self.tcx.local_def_id_to_hir_id(self.body_id);
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;
@@ -2331,7 +2395,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}
let guar = if field.name == kw::Empty {
- self.tcx.sess.delay_span_bug(field.span, "field name with no name")
+ self.tcx.sess.span_delayed_bug(field.span, "field name with no name")
} 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() {
@@ -2420,35 +2484,32 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
ty: Ty<'tcx>,
) {
let Some(output_ty) = self.get_impl_future_output_ty(ty) else {
+ err.span_label(field_ident.span, "unknown field");
return;
};
- let mut add_label = true;
- if let ty::Adt(def, _) = output_ty.kind() {
- // no field access on enum type
- if !def.is_enum() {
- if def
- .non_enum_variant()
- .fields
- .iter()
- .any(|field| field.ident(self.tcx) == field_ident)
- {
- add_label = false;
- err.span_label(
- field_ident.span,
- "field not available in `impl Future`, but it is available in its `Output`",
- );
- err.span_suggestion_verbose(
- base.span.shrink_to_hi(),
- "consider `await`ing on the `Future` and access the field of its `Output`",
- ".await",
- Applicability::MaybeIncorrect,
- );
- }
- }
+ let ty::Adt(def, _) = output_ty.kind() else {
+ err.span_label(field_ident.span, "unknown field");
+ return;
+ };
+ // no field access on enum type
+ if def.is_enum() {
+ err.span_label(field_ident.span, "unknown field");
+ return;
}
- if add_label {
- err.span_label(field_ident.span, format!("field not found in `{ty}`"));
+ if !def.non_enum_variant().fields.iter().any(|field| field.ident(self.tcx) == field_ident) {
+ err.span_label(field_ident.span, "unknown field");
+ return;
}
+ err.span_label(
+ field_ident.span,
+ "field not available in `impl Future`, but it is available in its `Output`",
+ );
+ err.span_suggestion_verbose(
+ base.span.shrink_to_hi(),
+ "consider `await`ing on the `Future` and access the field of its `Output`",
+ ".await",
+ Applicability::MaybeIncorrect,
+ );
}
fn ban_nonexisting_field(
@@ -2471,16 +2532,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
ty::RawPtr(..) => {
self.suggest_first_deref_field(&mut err, expr, base, ident);
}
- ty::Adt(def, _) if !def.is_enum() => {
- self.suggest_fields_on_recordish(&mut err, expr, def, ident);
- }
ty::Param(param_ty) => {
+ err.span_label(ident.span, "unknown field");
self.point_at_param_definition(&mut err, param_ty);
}
ty::Alias(ty::Opaque, _) => {
self.suggest_await_on_field_access(&mut err, ident, base, base_ty.peel_refs());
}
- _ => {}
+ _ => {
+ err.span_label(ident.span, "unknown field");
+ }
}
self.suggest_fn_call(&mut err, base, base_ty, |output_ty| {
@@ -2624,7 +2685,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}
let param_def_id = generic_param.def_id;
let param_hir_id = match param_def_id.as_local() {
- Some(x) => self.tcx.hir().local_def_id_to_hir_id(x),
+ Some(x) => self.tcx.local_def_id_to_hir_id(x),
None => return,
};
let param_span = self.tcx.hir().span(param_hir_id);
@@ -2633,34 +2694,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
err.span_label(param_span, format!("type parameter '{param_name}' declared here"));
}
- fn suggest_fields_on_recordish(
- &self,
- err: &mut Diagnostic,
- expr: &hir::Expr<'_>,
- def: ty::AdtDef<'tcx>,
- field: Ident,
- ) {
- let available_field_names = self.available_field_names(def.non_enum_variant(), expr, &[]);
- if let Some(suggested_field_name) =
- find_best_match_for_name(&available_field_names, field.name, None)
- {
- err.span_suggestion(
- field.span,
- "a field with a similar name exists",
- suggested_field_name,
- Applicability::MaybeIncorrect,
- );
- } else {
- err.span_label(field.span, "unknown field");
- if !available_field_names.is_empty() {
- err.note(format!(
- "available fields are: {}",
- self.name_series_display(available_field_names),
- ));
- }
- }
- }
-
fn maybe_suggest_array_indexing(
&self,
err: &mut Diagnostic,
@@ -2669,6 +2702,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
field: Ident,
len: ty::Const<'tcx>,
) {
+ err.span_label(field.span, "unknown field");
if let (Some(len), Ok(user_index)) =
(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)
@@ -2691,6 +2725,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
base: &hir::Expr<'_>,
field: Ident,
) {
+ err.span_label(field.span, "unknown field");
if let Ok(base) = self.tcx.sess.source_map().span_to_snippet(base.span) {
let msg = format!("`{base}` is a raw pointer; try dereferencing it");
let suggestion = format!("(*{base}).{field}");
@@ -2709,7 +2744,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let mut err = type_error_struct!(
self.tcx().sess,
- field.span,
+ span,
expr_t,
E0609,
"no field `{field}` on type `{expr_t}`",
@@ -2717,10 +2752,22 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// try to add a suggestion in case the field is a nested field of a field of the Adt
let mod_id = self.tcx.parent_module(id).to_def_id();
- if let Some((fields, args)) =
- self.get_field_candidates_considering_privacy(span, expr_t, mod_id)
+ let (ty, unwrap) = if let ty::Adt(def, args) = expr_t.kind()
+ && (self.tcx.is_diagnostic_item(sym::Result, def.did())
+ || self.tcx.is_diagnostic_item(sym::Option, def.did()))
+ && let Some(arg) = args.get(0)
+ && let Some(ty) = arg.as_type()
+ {
+ (ty, "unwrap().")
+ } else {
+ (expr_t, "")
+ };
+ for (found_fields, args) in
+ self.get_field_candidates_considering_privacy(span, ty, mod_id, id)
{
- let candidate_fields: Vec<_> = fields
+ let field_names = found_fields.iter().map(|field| field.name).collect::<Vec<_>>();
+ let mut candidate_fields: Vec<_> = found_fields
+ .into_iter()
.filter_map(|candidate_field| {
self.check_for_nested_field_satisfying(
span,
@@ -2729,17 +2776,18 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
args,
vec![],
mod_id,
+ id,
)
})
.map(|mut field_path| {
field_path.pop();
field_path
.iter()
- .map(|id| id.name.to_ident_string())
- .collect::<Vec<String>>()
- .join(".")
+ .map(|id| format!("{}.", id.name.to_ident_string()))
+ .collect::<String>()
})
.collect::<Vec<_>>();
+ candidate_fields.sort();
let len = candidate_fields.len();
if len > 0 {
@@ -2750,9 +2798,24 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
if len > 1 { "some" } else { "one" },
if len > 1 { "have" } else { "has" },
),
- candidate_fields.iter().map(|path| format!("{path}.")),
+ candidate_fields.iter().map(|path| format!("{unwrap}{path}")),
Applicability::MaybeIncorrect,
);
+ } else {
+ if let Some(field_name) = find_best_match_for_name(&field_names, field.name, None) {
+ err.span_suggestion_verbose(
+ field.span,
+ "a field with a similar name exists",
+ format!("{unwrap}{}", field_name),
+ Applicability::MaybeIncorrect,
+ );
+ } else if !field_names.is_empty() {
+ let is = if field_names.len() == 1 { " is" } else { "s are" };
+ err.note(format!(
+ "available field{is}: {}",
+ self.name_series_display(field_names),
+ ));
+ }
}
}
err
@@ -2781,33 +2844,39 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
span: Span,
base_ty: Ty<'tcx>,
mod_id: DefId,
- ) -> Option<(impl Iterator<Item = &'tcx ty::FieldDef> + 'tcx, GenericArgsRef<'tcx>)> {
+ hir_id: hir::HirId,
+ ) -> Vec<(Vec<&'tcx ty::FieldDef>, GenericArgsRef<'tcx>)> {
debug!("get_field_candidates(span: {:?}, base_t: {:?}", span, base_ty);
- for (base_t, _) in self.autoderef(span, base_ty) {
- match base_t.kind() {
- ty::Adt(base_def, args) if !base_def.is_enum() => {
- let tcx = self.tcx;
- let fields = &base_def.non_enum_variant().fields;
- // Some struct, e.g. some that impl `Deref`, have all private fields
- // because you're expected to deref them to access the _real_ fields.
- // This, for example, will help us suggest accessing a field through a `Box<T>`.
- if fields.iter().all(|field| !field.vis.is_accessible_from(mod_id, tcx)) {
- continue;
+ self.autoderef(span, base_ty)
+ .filter_map(move |(base_t, _)| {
+ match base_t.kind() {
+ ty::Adt(base_def, args) if !base_def.is_enum() => {
+ let tcx = self.tcx;
+ let fields = &base_def.non_enum_variant().fields;
+ // Some struct, e.g. some that impl `Deref`, have all private fields
+ // because you're expected to deref them to access the _real_ fields.
+ // This, for example, will help us suggest accessing a field through a `Box<T>`.
+ if fields.iter().all(|field| !field.vis.is_accessible_from(mod_id, tcx)) {
+ return None;
+ }
+ return Some((
+ fields
+ .iter()
+ .filter(move |field| {
+ field.vis.is_accessible_from(mod_id, tcx)
+ && self.is_field_suggestable(field, hir_id, span)
+ })
+ // For compile-time reasons put a limit on number of fields we search
+ .take(100)
+ .collect::<Vec<_>>(),
+ *args,
+ ));
}
- return Some((
- fields
- .iter()
- .filter(move |field| field.vis.is_accessible_from(mod_id, tcx))
- // For compile-time reasons put a limit on number of fields we search
- .take(100),
- args,
- ));
+ _ => None,
}
- _ => {}
- }
- }
- None
+ })
+ .collect()
}
/// This method is called after we have encountered a missing field error to recursively
@@ -2820,6 +2889,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
subst: GenericArgsRef<'tcx>,
mut field_path: Vec<Ident>,
mod_id: DefId,
+ hir_id: HirId,
) -> Option<Vec<Ident>> {
debug!(
"check_for_nested_field_satisfying(span: {:?}, candidate_field: {:?}, field_path: {:?}",
@@ -2835,20 +2905,23 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let field_ty = candidate_field.ty(self.tcx, subst);
if matches(candidate_field, field_ty) {
return Some(field_path);
- } else if let Some((nested_fields, subst)) =
- self.get_field_candidates_considering_privacy(span, field_ty, mod_id)
- {
- // recursively search fields of `candidate_field` if it's a ty::Adt
- for field in nested_fields {
- if let Some(field_path) = self.check_for_nested_field_satisfying(
- span,
- matches,
- field,
- subst,
- field_path.clone(),
- mod_id,
- ) {
- return Some(field_path);
+ } else {
+ for (nested_fields, subst) in
+ self.get_field_candidates_considering_privacy(span, field_ty, mod_id, hir_id)
+ {
+ // recursively search fields of `candidate_field` if it's a ty::Adt
+ for field in nested_fields {
+ if let Some(field_path) = self.check_for_nested_field_satisfying(
+ span,
+ matches,
+ field,
+ subst,
+ field_path.clone(),
+ mod_id,
+ hir_id,
+ ) {
+ return Some(field_path);
+ }
}
}
}
@@ -2863,8 +2936,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
expr: &'tcx hir::Expr<'tcx>,
brackets_span: Span,
) -> Ty<'tcx> {
- let base_t = self.check_expr(&base);
- let idx_t = self.check_expr(&idx);
+ let base_t = self.check_expr(base);
+ let idx_t = self.check_expr(idx);
if base_t.references_error() {
base_t
@@ -2877,7 +2950,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// two-phase not needed because index_ty is never mutable
self.demand_coerce(idx, idx_t, index_ty, None, AllowTwoPhase::No);
self.select_obligations_where_possible(|errors| {
- self.point_at_index_if_possible(errors, idx.span)
+ self.point_at_index(errors, idx.span);
});
element_ty
}
@@ -2905,7 +2978,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
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 ExprKind::Lit(lit) = idx.kind
&& let ast::LitKind::Int(i, ast::LitIntType::Unsuffixed) = lit.node
&& i < types
.len()
@@ -2978,7 +3051,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
return None;
};
- self.commit_if_ok(|_| {
+ self.commit_if_ok(|snapshot| {
+ let outer_universe = self.universe();
+
let ocx = ObligationCtxt::new(self);
let impl_args = self.fresh_args_for_item(base_expr.span, impl_def_id);
let impl_trait_ref =
@@ -2988,7 +3063,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// Match the impl self type against the base ty. If this fails,
// we just skip this impl, since it's not particularly useful.
let impl_trait_ref = ocx.normalize(&cause, self.param_env, impl_trait_ref);
- ocx.eq(&cause, self.param_env, impl_trait_ref.self_ty(), base_ty)?;
+ ocx.eq(&cause, self.param_env, base_ty, impl_trait_ref.self_ty())?;
// Register the impl's predicates. One of these predicates
// must be unsatisfied, or else we wouldn't have gotten here
@@ -3024,11 +3099,23 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
Ty::new_projection(self.tcx, index_trait_output_def_id, impl_trait_ref.args),
);
- let errors = ocx.select_where_possible();
+ let true_errors = ocx.select_where_possible();
+
+ // Do a leak check -- we can't really report report a useful error here,
+ // but it at least avoids an ICE when the error has to do with higher-ranked
+ // lifetimes.
+ self.leak_check(outer_universe, Some(snapshot))?;
+
+ // Bail if we have ambiguity errors, which we can't report in a useful way.
+ let ambiguity_errors = ocx.select_all_or_error();
+ if true_errors.is_empty() && !ambiguity_errors.is_empty() {
+ return Err(NoSolution);
+ }
+
// There should be at least one error reported. If not, we
// will still delay a span bug in `report_fulfillment_errors`.
Ok::<_, NoSolution>((
- self.err_ctxt().report_fulfillment_errors(errors),
+ self.err_ctxt().report_fulfillment_errors(true_errors),
impl_trait_ref.args.type_at(1),
element_ty,
))
@@ -3036,16 +3123,28 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
.ok()
}
- fn point_at_index_if_possible(
- &self,
- errors: &mut Vec<traits::FulfillmentError<'tcx>>,
- span: Span,
- ) {
+ fn point_at_index(&self, errors: &mut Vec<traits::FulfillmentError<'tcx>>, span: Span) {
+ let mut seen_preds = FxHashSet::default();
+ // We re-sort here so that the outer most root obligations comes first, as we have the
+ // subsequent weird logic to identify *every* relevant obligation for proper deduplication
+ // of diagnostics.
+ errors.sort_by_key(|error| error.root_obligation.recursion_depth);
for error in errors {
- match error.obligation.predicate.kind().skip_binder() {
- ty::PredicateKind::Clause(ty::ClauseKind::Trait(predicate))
- if self.tcx.is_diagnostic_item(sym::SliceIndex, predicate.trait_ref.def_id) => {
+ match (
+ error.root_obligation.predicate.kind().skip_binder(),
+ error.obligation.predicate.kind().skip_binder(),
+ ) {
+ (ty::PredicateKind::Clause(ty::ClauseKind::Trait(predicate)), _)
+ if self.tcx.lang_items().index_trait() == Some(predicate.trait_ref.def_id) =>
+ {
+ seen_preds.insert(error.obligation.predicate.kind().skip_binder());
+ }
+ (_, ty::PredicateKind::Clause(ty::ClauseKind::Trait(predicate)))
+ if self.tcx.is_diagnostic_item(sym::SliceIndex, predicate.trait_ref.def_id) =>
+ {
+ seen_preds.insert(error.obligation.predicate.kind().skip_binder());
}
+ (root, pred) if seen_preds.contains(&pred) || seen_preds.contains(&root) => {}
_ => continue,
}
error.obligation.cause.span = span;
@@ -3060,7 +3159,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
) -> Ty<'tcx> {
match self.resume_yield_tys {
Some((resume_ty, yield_ty)) => {
- self.check_expr_coercible_to_type(&value, yield_ty, None);
+ self.check_expr_coercible_to_type(value, yield_ty, None);
resume_ty
}
@@ -3069,7 +3168,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_coercible_to_type(&value, Ty::new_unit(self.tcx), None);
+ self.check_expr_coercible_to_type(value, Ty::new_unit(self.tcx), None);
Ty::new_unit(self.tcx)
}
_ => {
@@ -3163,7 +3262,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
match container.kind() {
ty::Adt(container_def, args) if container_def.is_enum() => {
- let block = self.tcx.hir().local_def_id_to_hir_id(self.body_id);
+ let block = self.tcx.local_def_id_to_hir_id(self.body_id);
let (ident, _def_scope) =
self.tcx.adjust_ident_and_get_scope(field, container_def.did(), block);
@@ -3173,19 +3272,22 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
sym::offset_of_enum,
ident.span,
"using enums in offset_of is experimental",
- ).emit();
+ )
+ .emit();
}
- let Some((index, variant)) = container_def.variants()
+ let Some((index, variant)) = container_def
+ .variants()
.iter_enumerated()
- .find(|(_, v)| v.ident(self.tcx).normalize_to_macros_2_0() == ident) else {
+ .find(|(_, v)| v.ident(self.tcx).normalize_to_macros_2_0() == ident)
+ else {
let mut err = type_error_struct!(
self.tcx().sess,
ident.span,
container,
E0599,
"no variant named `{ident}` found for enum `{container}`",
- );
+ );
err.span_label(field.span, "variant not found");
err.emit();
break;
@@ -3197,7 +3299,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
container,
E0795,
"`{ident}` is an enum variant; expected field at end of `offset_of`",
- );
+ );
err.span_label(field.span, "enum variant");
err.emit();
break;
@@ -3205,16 +3307,18 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let (subident, sub_def_scope) =
self.tcx.adjust_ident_and_get_scope(subfield, variant.def_id, block);
- let Some((subindex, field)) = variant.fields
+ let Some((subindex, field)) = variant
+ .fields
.iter_enumerated()
- .find(|(_, f)| f.ident(self.tcx).normalize_to_macros_2_0() == subident) else {
+ .find(|(_, f)| f.ident(self.tcx).normalize_to_macros_2_0() == subident)
+ else {
let mut err = type_error_struct!(
self.tcx().sess,
ident.span,
container,
E0609,
"no field named `{subfield}` on enum variant `{container}::{ident}`",
- );
+ );
err.span_label(field.span, "this enum variant...");
err.span_label(subident.span, "...does not have this field");
err.emit();
@@ -3240,7 +3344,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
continue;
}
ty::Adt(container_def, args) => {
- let block = self.tcx.hir().local_def_id_to_hir_id(self.body_id);
+ let block = self.tcx.local_def_id_to_hir_id(self.body_id);
let (ident, def_scope) =
self.tcx.adjust_ident_and_get_scope(field, container_def.did(), block);
diff --git a/compiler/rustc_hir_typeck/src/expr_use_visitor.rs b/compiler/rustc_hir_typeck/src/expr_use_visitor.rs
index 6be3ad657..c22b15231 100644
--- a/compiler/rustc_hir_typeck/src/expr_use_visitor.rs
+++ b/compiler/rustc_hir_typeck/src/expr_use_visitor.rs
@@ -147,7 +147,7 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> {
self.walk_irrefutable_pat(&param_place, param.pat);
}
- self.consume_expr(&body.value);
+ self.consume_expr(body.value);
}
fn tcx(&self) -> TyCtxt<'tcx> {
@@ -237,10 +237,10 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> {
self.consume_exprs(exprs);
}
- hir::ExprKind::If(ref cond_expr, ref then_expr, ref opt_else_expr) => {
+ hir::ExprKind::If(cond_expr, then_expr, ref opt_else_expr) => {
self.consume_expr(cond_expr);
self.consume_expr(then_expr);
- if let Some(ref else_expr) = *opt_else_expr {
+ if let Some(else_expr) = *opt_else_expr {
self.consume_expr(else_expr);
}
}
@@ -249,7 +249,7 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> {
self.walk_local(init, pat, None, |t| t.borrow_expr(init, ty::ImmBorrow))
}
- hir::ExprKind::Match(ref discr, arms, _) => {
+ hir::ExprKind::Match(discr, arms, _) => {
let discr_place = return_if_err!(self.mc.cat_expr(discr));
return_if_err!(self.maybe_read_scrutinee(
discr,
@@ -267,7 +267,7 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> {
self.consume_exprs(exprs);
}
- hir::ExprKind::AddrOf(_, m, ref base) => {
+ hir::ExprKind::AddrOf(_, m, base) => {
// &base
// make sure that the thing we are pointing out stays valid
// for the lifetime `scope_r` of the resulting ptr:
@@ -379,7 +379,7 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> {
// only the fn body we were given.
}
- hir::StmtKind::Expr(ref expr) | hir::StmtKind::Semi(ref expr) => {
+ hir::StmtKind::Expr(expr) | hir::StmtKind::Semi(expr) => {
self.consume_expr(expr);
}
}
@@ -401,12 +401,17 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> {
mc.cat_pattern(discr_place.clone(), pat, |place, pat| {
match &pat.kind {
PatKind::Binding(.., opt_sub_pat) => {
- // If the opt_sub_pat is None, than the binding does not count as
+ // If the opt_sub_pat is None, then the binding does not count as
// a wildcard for the purpose of borrowing discr.
if opt_sub_pat.is_none() {
needs_to_be_read = true;
}
}
+ PatKind::Never => {
+ // A never pattern reads the value.
+ // FIXME(never_patterns): does this do what I expect?
+ needs_to_be_read = true;
+ }
PatKind::Path(qpath) => {
// A `Path` pattern is just a name like `Foo`. This is either a
// named constant or else it refers to an ADT variant
@@ -505,7 +510,7 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> {
));
self.walk_block(els)
}
- self.walk_irrefutable_pat(&expr_place, &pat);
+ self.walk_irrefutable_pat(&expr_place, pat);
}
/// Indicates that the value of `blk` will be consumed, meaning either copied or moved
@@ -517,7 +522,7 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> {
self.walk_stmt(stmt);
}
- if let Some(ref tail_expr) = blk.expr {
+ if let Some(tail_expr) = blk.expr {
self.consume_expr(tail_expr);
}
}
@@ -533,7 +538,7 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> {
// The struct path probably didn't resolve
if self.mc.typeck_results.opt_field_index(field.hir_id).is_none() {
- self.tcx().sess.delay_span_bug(field.span, "couldn't resolve index for field");
+ self.tcx().sess.span_delayed_bug(field.span, "couldn't resolve index for field");
}
}
@@ -665,8 +670,8 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> {
self.walk_pat(discr_place, arm.pat, arm.guard.is_some());
match arm.guard {
- Some(hir::Guard::If(ref e)) => self.consume_expr(e),
- Some(hir::Guard::IfLet(ref l)) => {
+ Some(hir::Guard::If(e)) => self.consume_expr(e),
+ Some(hir::Guard::IfLet(l)) => {
self.walk_local(l.init, l.pat, None, |t| t.borrow_expr(l.init, ty::ImmBorrow))
}
None => {}
@@ -848,7 +853,7 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> {
// be a local variable
PlaceBase::Local(*var_hir_id)
};
- let closure_hir_id = tcx.hir().local_def_id_to_hir_id(closure_def_id);
+ let closure_hir_id = tcx.local_def_id_to_hir_id(closure_def_id);
let place_with_id = PlaceWithHirId::new(
capture_info
.path_expr_id
diff --git a/compiler/rustc_hir_typeck/src/fallback.rs b/compiler/rustc_hir_typeck/src/fallback.rs
index 38b780367..023bd70be 100644
--- a/compiler/rustc_hir_typeck/src/fallback.rs
+++ b/compiler/rustc_hir_typeck/src/fallback.rs
@@ -24,9 +24,9 @@ impl<'tcx> FnCtxt<'_, 'tcx> {
self.fulfillment_cx.borrow_mut().pending_obligations()
);
- let fallback_occured = self.fallback_types() | self.fallback_effects();
+ let fallback_occurred = self.fallback_types() | self.fallback_effects();
- if !fallback_occured {
+ if !fallback_occurred {
return;
}
@@ -57,24 +57,25 @@ impl<'tcx> FnCtxt<'_, 'tcx> {
}
fn fallback_types(&self) -> bool {
- // Check if we have any unsolved variables. If not, no need for fallback.
- let unsolved_variables = self.unsolved_variables();
+ // Check if we have any unresolved variables. If not, no need for fallback.
+ let unresolved_variables = self.unresolved_variables();
- if unsolved_variables.is_empty() {
+ if unresolved_variables.is_empty() {
return false;
}
- let diverging_fallback = self.calculate_diverging_fallback(&unsolved_variables);
+ let diverging_fallback = self.calculate_diverging_fallback(&unresolved_variables);
// We do fallback in two passes, to try to generate
// better error messages.
// The first time, we do *not* replace opaque types.
- for ty in unsolved_variables {
+ let mut fallback_occurred = false;
+ for ty in unresolved_variables {
debug!("unsolved_variable = {:?}", ty);
- self.fallback_if_possible(ty, &diverging_fallback);
+ fallback_occurred |= self.fallback_if_possible(ty, &diverging_fallback);
}
- true
+ fallback_occurred
}
fn fallback_effects(&self) -> bool {
@@ -84,9 +85,8 @@ impl<'tcx> FnCtxt<'_, 'tcx> {
return false;
}
- // not setting `fallback_has_occured` here because that field is only used for type fallback
- // diagnostics.
-
+ // not setting the `fallback_has_occured` field here because
+ // that field is only used for type fallback diagnostics.
for effect in unsolved_effects {
let expected = self.tcx.consts.true_;
let cause = self.misc(rustc_span::DUMMY_SP);
@@ -122,7 +122,7 @@ impl<'tcx> FnCtxt<'_, 'tcx> {
&self,
ty: Ty<'tcx>,
diverging_fallback: &UnordMap<Ty<'tcx>, Ty<'tcx>>,
- ) {
+ ) -> bool {
// Careful: we do NOT shallow-resolve `ty`. We know that `ty`
// is an unsolved variable, and we determine its fallback
// based solely on how it was created, not what other type
@@ -147,7 +147,7 @@ impl<'tcx> FnCtxt<'_, 'tcx> {
ty::Infer(ty::FloatVar(_)) => self.tcx.types.f64,
_ => match diverging_fallback.get(&ty) {
Some(&fallback_ty) => fallback_ty,
- None => return,
+ None => return false,
},
};
debug!("fallback_if_possible(ty={:?}): defaulting to `{:?}`", ty, fallback);
@@ -159,6 +159,7 @@ impl<'tcx> FnCtxt<'_, 'tcx> {
.unwrap_or(rustc_span::DUMMY_SP);
self.demand_eqtype(span, ty, fallback);
self.fallback_has_occurred.set(true);
+ true
}
/// The "diverging fallback" system is rather complicated. This is
@@ -230,9 +231,9 @@ impl<'tcx> FnCtxt<'_, 'tcx> {
/// any variable that has an edge into `D`.
fn calculate_diverging_fallback(
&self,
- unsolved_variables: &[Ty<'tcx>],
+ unresolved_variables: &[Ty<'tcx>],
) -> UnordMap<Ty<'tcx>, Ty<'tcx>> {
- debug!("calculate_diverging_fallback({:?})", unsolved_variables);
+ debug!("calculate_diverging_fallback({:?})", unresolved_variables);
// Construct a coercion graph where an edge `A -> B` indicates
// a type variable is that is coerced
@@ -240,7 +241,7 @@ impl<'tcx> FnCtxt<'_, 'tcx> {
// Extract the unsolved type inference variable vids; note that some
// unsolved variables are integer/float variables and are excluded.
- let unsolved_vids = unsolved_variables.iter().filter_map(|ty| ty.ty_vid());
+ let unsolved_vids = unresolved_variables.iter().filter_map(|ty| ty.ty_vid());
// Compute the diverging root vids D -- that is, the root vid of
// those type variables that (a) are the target of a coercion from
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
index 750ed2c34..4bc237c23 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
@@ -72,7 +72,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
orig_span,
custom_note
.unwrap_or("any code following this expression is unreachable"),
- )
+ );
},
)
}
@@ -83,7 +83,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
/// version (resolve_vars_if_possible), this version will
/// also select obligations if it seems useful, in an effort
/// to get more type information.
- // FIXME(-Ztrait-solver=next): A lot of the calls to this method should
+ // FIXME(-Znext-solver): A lot of the calls to this method should
// probably be `try_structurally_resolve_type` or `structurally_resolve_type` instead.
#[instrument(skip(self), level = "debug", ret)]
pub(in super::super) fn resolve_vars_with_obligations(&self, mut ty: Ty<'tcx>) -> Ty<'tcx> {
@@ -159,7 +159,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}
#[instrument(level = "debug", skip(self))]
- pub fn write_method_call(&self, hir_id: hir::HirId, method: MethodCallee<'tcx>) {
+ pub fn write_method_call_and_enforce_effects(
+ &self,
+ hir_id: hir::HirId,
+ span: Span,
+ method: MethodCallee<'tcx>,
+ ) {
+ self.enforce_context_effects(span, method.def_id, method.args);
self.write_resolution(hir_id, Ok((DefKind::AssocFn, method.def_id)));
self.write_args(hir_id, method.args);
}
@@ -271,7 +277,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// FIXME: currently we never try to compose autoderefs
// and ReifyFnPointer/UnsafeFnPointer, but we could.
_ => {
- self.tcx.sess.delay_span_bug(
+ self.tcx.sess.span_delayed_bug(
expr.span,
format!(
"while adjusting {:?}, can't compose {:?} and {:?}",
@@ -505,7 +511,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
pub(in super::super) fn resolve_rvalue_scopes(&self, def_id: DefId) {
let scope_tree = self.tcx.region_scope_tree(def_id);
- let rvalue_scopes = { rvalue_scopes::resolve_rvalue_scopes(self, &scope_tree, def_id) };
+ let rvalue_scopes = { rvalue_scopes::resolve_rvalue_scopes(self, scope_tree, def_id) };
let mut typeck_results = self.inh.typeck_results.borrow_mut();
typeck_results.rvalue_scopes = rvalue_scopes;
}
@@ -651,20 +657,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
| ty::PredicateKind::Clause(ty::ClauseKind::TypeOutlives(..))
| ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(..))
| ty::PredicateKind::ObjectSafe(..)
+ | ty::PredicateKind::NormalizesTo(..)
| ty::PredicateKind::AliasRelate(..)
| ty::PredicateKind::Clause(ty::ClauseKind::ConstEvaluatable(..))
| ty::PredicateKind::ConstEquate(..)
- // N.B., this predicate is created by breaking down a
- // `ClosureType: FnFoo()` predicate, where
- // `ClosureType` represents some `Closure`. It can't
- // possibly be referring to the current closure,
- // because we haven't produced the `Closure` for
- // this closure yet; this is exactly why the other
- // code is looking for a self type of an unresolved
- // inference variable.
- | ty::PredicateKind::ClosureKind(..)
- | ty::PredicateKind::Ambiguous
- => None,
+ | ty::PredicateKind::Ambiguous => None,
},
)
}
@@ -754,7 +751,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
lang_item: hir::LangItem,
span: Span,
hir_id: hir::HirId,
- expr_hir_id: Option<hir::HirId>,
) -> (Res, Ty<'tcx>) {
let def_id = self.tcx.require_lang_item(lang_item, Some(span));
let def_kind = self.tcx.def_kind(def_id);
@@ -767,11 +763,18 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let args = self.fresh_args_for_item(span, def_id);
let ty = item_ty.instantiate(self.tcx, args);
+ self.write_args(hir_id, args);
self.write_resolution(hir_id, Ok((def_kind, def_id)));
let code = match lang_item {
hir::LangItem::IntoFutureIntoFuture => {
- Some(ObligationCauseCode::AwaitableExpr(expr_hir_id))
+ if let hir::Node::Expr(into_future_call) = self.tcx.hir().get_parent(hir_id)
+ && let hir::ExprKind::Call(_, [arg0]) = &into_future_call.kind
+ {
+ Some(ObligationCauseCode::AwaitableExpr(arg0.hir_id))
+ } else {
+ None
+ }
}
hir::LangItem::IteratorNext | hir::LangItem::IntoIterIntoIter => {
Some(ObligationCauseCode::ForLoopIterator)
@@ -804,7 +807,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
qpath, hir_id, span
);
let (ty, qself, item_segment) = match *qpath {
- QPath::Resolved(ref opt_qself, ref path) => {
+ QPath::Resolved(ref opt_qself, path) => {
return (
path.res,
opt_qself.as_ref().map(|qself| self.to_ty(qself)),
@@ -845,7 +848,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
&& let Some(mut diag) = self
.tcx
.sess
- .diagnostic()
+ .dcx()
.steal_diagnostic(qself.span, StashKey::TraitMissingMethod)
{
diag.emit();
@@ -856,7 +859,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let guar = self
.tcx
.sess
- .delay_span_bug(span, "method resolution should've emitted an error");
+ .span_delayed_bug(span, "method resolution should've emitted an error");
let result = match error {
method::MethodError::PrivateMatch(kind, def_id, _) => Ok((kind, def_id)),
_ => Err(guar),
@@ -881,7 +884,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
&& let Some(mut diag) = self
.tcx
.sess
- .diagnostic()
+ .dcx()
.steal_diagnostic(qself.span, StashKey::TraitMissingMethod)
{
if trait_missing_method {
@@ -991,7 +994,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// Get enclosing Fn, if it is a function or a trait method, unless there's a `loop` or
// `while` before reaching it, as block tail returns are not available in them.
self.tcx.hir().get_return_block(blk_id).and_then(|blk_id| {
- let parent = self.tcx.hir().get(blk_id);
+ let parent = self.tcx.hir_node(blk_id);
self.get_node_fn_decl(parent)
.map(|(fn_id, fn_decl, _, is_main)| (fn_id, fn_decl, is_main))
})
@@ -1186,7 +1189,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
tcx,
span,
def_id,
- &generics,
+ generics,
seg,
IsMethodCall::No,
);
@@ -1278,7 +1281,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// going to infer the arguments for better error messages.
if !self.infer_args_for_err.contains(&index) {
// Check whether the user has provided generic arguments.
- if let Some(ref data) = self.segments[index].args {
+ if let Some(data) = self.segments[index].args {
return (Some(data), self.segments[index].infer_args);
}
}
@@ -1406,7 +1409,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// Normalize only after registering type annotations.
let args = self.normalize(span, args_raw);
- self.add_required_obligations_for_hir(span, def_id, &args, hir_id);
+ self.add_required_obligations_for_hir(span, def_id, args, hir_id);
// Substitute the values for the type parameters into the type of
// the referenced item.
@@ -1430,7 +1433,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
) {
Ok(ok) => self.register_infer_ok_obligations(ok),
Err(_) => {
- self.tcx.sess.delay_span_bug(
+ self.tcx.sess.span_delayed_bug(
span,
format!(
"instantiate_value_path: (UFCS) {self_ty:?} was a subtype of {impl_ty:?} but now is not?",
@@ -1473,7 +1476,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
) {
let param_env = self.param_env;
- let bounds = self.instantiate_bounds(span, def_id, &args);
+ let bounds = self.instantiate_bounds(span, def_id, args);
for obligation in traits::predicates_for_generics(
|idx, predicate_span| {
@@ -1495,7 +1498,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let ty = self.resolve_vars_with_obligations(ty);
if self.next_trait_solver()
- && let ty::Alias(ty::Projection | ty::Inherent | ty::Weak, _) = ty.kind()
+ && let ty::Alias(..) = ty.kind()
{
match self
.at(&self.misc(sp), self.param_env)
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs
index facbeb8ba..76360239c 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs
@@ -4,7 +4,7 @@ use rustc_hir::def::{DefKind, Res};
use rustc_hir::def_id::DefId;
use rustc_infer::{infer::type_variable::TypeVariableOriginKind, traits::ObligationCauseCode};
use rustc_middle::ty::{self, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitor};
-use rustc_span::{self, symbol::kw, Span};
+use rustc_span::{symbol::kw, Span};
use rustc_trait_selection::traits;
use std::ops::ControlFlow;
@@ -94,7 +94,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}
let hir = self.tcx.hir();
- let (expr, qpath) = match hir.get(hir_id) {
+ let (expr, qpath) = match self.tcx.hir_node(hir_id) {
hir::Node::Expr(expr) => {
if self.closure_span_overlaps_error(error, expr.span) {
return false;
@@ -454,7 +454,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
.find_ancestor_in_same_ctxt(error.obligation.cause.span)
.unwrap_or(arg.span);
- if let hir::Node::Expr(arg_expr) = self.tcx.hir().get(arg.hir_id) {
+ if let hir::Node::Expr(arg_expr) = self.tcx.hir_node(arg.hir_id) {
// This is more specific than pointing at the entire argument.
self.blame_specific_expr_if_possible(error, arg_expr)
}
@@ -495,7 +495,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// Whether it succeeded or failed, it likely made some amount of progress.
// In the very worst case, it's just the same `expr` we originally passed in.
let expr = match self.blame_specific_expr_if_possible_for_obligation_cause_code(
- &error.obligation.cause.code(),
+ error.obligation.cause.code(),
expr,
) {
Ok(expr) => expr,
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/arg_matrix.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/arg_matrix.rs
index 7aadb95d9..566d407d2 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/arg_matrix.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/arg_matrix.rs
@@ -4,11 +4,13 @@ use rustc_middle::ty::error::TypeError;
use std::cmp;
rustc_index::newtype_index! {
+ #[orderable]
#[debug_format = "ExpectedIdx({})"]
pub(crate) struct ExpectedIdx {}
}
rustc_index::newtype_index! {
+ #[orderable]
#[debug_format = "ProvidedIdx({})"]
pub(crate) struct ProvidedIdx {}
}
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
index 33dfa16a6..4caa0df58 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
@@ -33,7 +33,7 @@ use rustc_middle::ty::visit::TypeVisitableExt;
use rustc_middle::ty::{self, IsSuggestable, Ty, TyCtxt};
use rustc_session::Session;
use rustc_span::symbol::{kw, Ident};
-use rustc_span::{self, sym, BytePos, Span};
+use rustc_span::{sym, BytePos, Span};
use rustc_trait_selection::traits::{self, ObligationCauseCode, SelectionContext};
use std::iter;
@@ -230,11 +230,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let minimum_input_count = expected_input_tys.len();
let provided_arg_count = provided_args.len();
- let is_const_eval_select = matches!(fn_def_id, Some(def_id) if
- self.tcx.def_kind(def_id) == hir::def::DefKind::Fn
- && self.tcx.is_intrinsic(def_id)
- && self.tcx.item_name(def_id) == sym::const_eval_select);
-
// We introduce a helper function to demand that a given argument satisfy a given input
// This is more complicated than just checking type equality, as arguments could be coerced
// This version writes those types back so further type checking uses the narrowed types
@@ -269,35 +264,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
return Compatibility::Incompatible(coerce_error);
}
- // Check that second and third argument of `const_eval_select` must be `FnDef`, and additionally that
- // the second argument must be `const fn`. The first argument must be a tuple, but this is already expressed
- // in the function signature (`F: FnOnce<ARG>`), so I did not bother to add another check here.
- //
- // This check is here because there is currently no way to express a trait bound for `FnDef` types only.
- if is_const_eval_select && (1..=2).contains(&idx) {
- if let ty::FnDef(def_id, args) = *checked_ty.kind() {
- if idx == 1 {
- if !self.tcx.is_const_fn_raw(def_id) {
- self.tcx.sess.emit_err(errors::ConstSelectMustBeConst {
- span: provided_arg.span,
- });
- } else {
- self.enforce_context_effects(
- provided_arg.hir_id,
- provided_arg.span,
- def_id,
- args,
- )
- }
- }
- } else {
- self.tcx.sess.emit_err(errors::ConstSelectMustBeFn {
- span: provided_arg.span,
- ty: checked_ty,
- });
- }
- }
-
// 3. Check if the formal type is a supertype of the checked one
// and register any such obligations for future type checks
let supertype_error = self.at(&self.misc(provided_arg.span), self.param_env).sup(
@@ -397,7 +363,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
for arg in provided_args.iter().skip(minimum_input_count) {
// Make sure we've checked this expr at least once.
- let arg_ty = self.check_expr(&arg);
+ let arg_ty = self.check_expr(arg);
// If the function is c-style variadic, we skipped a bunch of arguments
// so we need to check those, and write out the types
@@ -522,7 +488,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let tcx = self.tcx;
// FIXME: taint after emitting errors and pass through an `ErrorGuaranteed`
self.set_tainted_by_errors(
- tcx.sess.delay_span_bug(call_span, "no errors reported for args"),
+ tcx.sess.span_delayed_bug(call_span, "no errors reported for args"),
);
// Get the argument span in the context of the call span so that
@@ -796,7 +762,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let mut err = self.err_ctxt().report_and_explain_type_error(trace, *err);
self.emit_coerce_suggestions(
&mut err,
- &provided_args[*provided_idx],
+ provided_args[*provided_idx],
provided_ty,
Expectation::rvalue_hint(self, expected_ty)
.only_has_type(self)
@@ -925,7 +891,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
self.emit_coerce_suggestions(
&mut err,
- &provided_args[provided_idx],
+ provided_args[provided_idx],
provided_ty,
Expectation::rvalue_hint(self, expected_ty)
.only_has_type(self)
@@ -998,7 +964,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}) {
match e {
Error::Missing(expected_idx) => missing_idxs.push(expected_idx),
- _ => unreachable!(),
+ _ => unreachable!(
+ "control flow ensures that we should always get an `Error::Missing`"
+ ),
}
}
@@ -1366,7 +1334,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let variant = match def {
Res::Err => {
let guar =
- self.tcx.sess.delay_span_bug(path_span, "`Res::Err` but no error emitted");
+ self.tcx.sess.span_delayed_bug(path_span, "`Res::Err` but no error emitted");
self.set_tainted_by_errors(guar);
return Err(guar);
}
@@ -1469,7 +1437,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// Type check the initializer.
if let Some(ref init) = decl.init {
- let init_ty = self.check_decl_initializer(decl.hir_id, decl.pat, &init);
+ let init_ty = self.check_decl_initializer(decl.hir_id, decl.pat, init);
self.overwrite_local_ty_if_err(decl.hir_id, decl.pat, init_ty);
}
@@ -1483,7 +1451,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
};
// Type check the pattern. Override if necessary to avoid knock-on errors.
- self.check_pat_top(&decl.pat, decl_ty, ty_span, origin_expr, Some(decl.origin));
+ self.check_pat_top(decl.pat, decl_ty, ty_span, origin_expr, Some(decl.origin));
let pat_ty = self.node_ty(decl.pat.hir_id);
self.overwrite_local_ty_if_err(decl.hir_id, decl.pat, pat_ty);
@@ -1525,13 +1493,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
hir::StmtKind::Item(_) => {}
hir::StmtKind::Expr(ref expr) => {
// Check with expected type of `()`.
- self.check_expr_has_type_or_error(&expr, Ty::new_unit(self.tcx), |err| {
+ self.check_expr_has_type_or_error(expr, Ty::new_unit(self.tcx), |err| {
if expr.can_have_side_effects() {
self.suggest_semicolon_at_end(expr.span, err);
}
});
}
- hir::StmtKind::Semi(ref expr) => {
+ hir::StmtKind::Semi(expr) => {
self.check_expr(expr);
}
}
@@ -1739,7 +1707,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}
fn parent_item_span(&self, id: hir::HirId) -> Option<Span> {
- let node = self.tcx.hir().get_by_def_id(self.tcx.hir().get_parent_item(id).def_id);
+ let node = self.tcx.hir_node_by_def_id(self.tcx.hir().get_parent_item(id).def_id);
match node {
Node::Item(&hir::Item { kind: hir::ItemKind::Fn(_, _, body_id), .. })
| Node::ImplItem(&hir::ImplItem { kind: hir::ImplItemKind::Fn(_, body_id), .. }) => {
@@ -1755,7 +1723,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
/// Given a function block's `HirId`, returns its `FnDecl` if it exists, or `None` otherwise.
fn get_parent_fn_decl(&self, blk_id: hir::HirId) -> Option<(&'tcx hir::FnDecl<'tcx>, Ident)> {
- let parent = self.tcx.hir().get_by_def_id(self.tcx.hir().get_parent_item(blk_id).def_id);
+ let parent = self.tcx.hir_node_by_def_id(self.tcx.hir().get_parent_item(blk_id).def_id);
self.get_node_fn_decl(parent).map(|(_, fn_decl, ident, _)| (fn_decl, ident))
}
@@ -1820,12 +1788,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
hir_id: hir::HirId,
) -> (Res, RawTy<'tcx>) {
match *qpath {
- QPath::Resolved(ref maybe_qself, ref path) => {
+ QPath::Resolved(ref maybe_qself, path) => {
let self_ty = maybe_qself.as_ref().map(|qself| self.to_ty(qself).raw);
let ty = self.astconv().res_to_ty(self_ty, path, hir_id, true);
(path.res, self.handle_raw_ty(path_span, ty))
}
- QPath::TypeRelative(ref qself, ref segment) => {
+ QPath::TypeRelative(qself, segment) => {
let ty = self.to_ty(qself);
let result = self
@@ -1842,8 +1810,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
(result.map_or(Res::Err, |(kind, def_id)| Res::Def(kind, def_id)), ty)
}
- QPath::LangItem(lang_item, span, id) => {
- let (res, ty) = self.resolve_lang_item_path(lang_item, span, hir_id, id);
+ QPath::LangItem(lang_item, span) => {
+ let (res, ty) = self.resolve_lang_item_path(lang_item, span, hir_id);
(res, self.handle_raw_ty(path_span, ty))
}
}
@@ -1855,7 +1823,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
) {
for (span, code) in errors_causecode {
let Some(mut diag) =
- self.tcx.sess.diagnostic().steal_diagnostic(span, StashKey::MaybeForgetReturn)
+ self.tcx.sess.dcx().steal_diagnostic(span, StashKey::MaybeForgetReturn)
else {
continue;
};
@@ -1864,35 +1832,42 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
&& let ExprBindingObligation(_, _, hir_id, ..) = code
&& !fn_sig.output().is_unit()
{
- let mut block_num = 0;
- let mut found_semi = false;
- for (_, node) in self.tcx.hir().parent_iter(hir_id) {
- match node {
- hir::Node::Stmt(stmt) => if let hir::StmtKind::Semi(ref expr) = stmt.kind {
+ let mut block_num = 0;
+ let mut found_semi = false;
+ for (_, node) in self.tcx.hir().parent_iter(hir_id) {
+ match node {
+ hir::Node::Stmt(stmt) => {
+ if let hir::StmtKind::Semi(expr) = stmt.kind {
let expr_ty = self.typeck_results.borrow().expr_ty(expr);
let return_ty = fn_sig.output();
- if !matches!(expr.kind, hir::ExprKind::Ret(..)) &&
- self.can_coerce(expr_ty, return_ty) {
+ if !matches!(expr.kind, hir::ExprKind::Ret(..))
+ && self.can_coerce(expr_ty, return_ty)
+ {
found_semi = true;
}
- },
- hir::Node::Block(_block) => if found_semi {
+ }
+ }
+ hir::Node::Block(_block) => {
+ if found_semi {
block_num += 1;
}
- hir::Node::Item(item) => if let hir::ItemKind::Fn(..) = item.kind {
+ }
+ hir::Node::Item(item) => {
+ if let hir::ItemKind::Fn(..) = item.kind {
break;
}
- _ => {}
}
+ _ => {}
}
- if block_num > 1 && found_semi {
- diag.span_suggestion_verbose(
- span.shrink_to_lo(),
- "you might have meant to return this to infer its type parameters",
- "return ",
- Applicability::MaybeIncorrect,
- );
- }
+ }
+ if block_num > 1 && found_semi {
+ diag.span_suggestion_verbose(
+ span.shrink_to_lo(),
+ "you might have meant to return this to infer its type parameters",
+ "return ",
+ Applicability::MaybeIncorrect,
+ );
+ }
}
diag.emit();
}
@@ -2016,7 +1991,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let new_def_id = self.probe(|_| {
let trait_ref = ty::TraitRef::new(
self.tcx,
- call_kind.to_def_id(self.tcx),
+ self.tcx.fn_trait_kind_to_def_id(call_kind)?,
[
callee_ty,
self.next_ty_var(TypeVariableOrigin {
@@ -2031,7 +2006,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
self.param_env,
trait_ref,
);
- match SelectionContext::new(&self).select(&obligation) {
+ match SelectionContext::new(self).select(&obligation) {
Ok(Some(traits::ImplSource::UserDefined(impl_source))) => {
Some(impl_source.impl_def_id)
}
@@ -2082,7 +2057,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let node = self
.tcx
.opt_local_def_id_to_hir_id(self.tcx.hir().get_parent_item(call_expr.hir_id))
- .and_then(|hir_id| self.tcx.hir().find(hir_id));
+ .and_then(|hir_id| self.tcx.opt_hir_node(hir_id));
match node {
Some(hir::Node::Item(item)) => call_finder.visit_item(item),
Some(hir::Node::TraitItem(item)) => call_finder.visit_trait_item(item),
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs
index e93d180fc..072df1343 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs
@@ -143,7 +143,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}
pub fn sess(&self) -> &Session {
- &self.tcx.sess
+ self.tcx.sess
}
/// Creates an `TypeErrCtxt` with a reference to the in-progress
@@ -196,7 +196,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
impl<'a, 'tcx> Deref for FnCtxt<'a, 'tcx> {
type Target = Inherited<'tcx>;
fn deref(&self) -> &Self::Target {
- &self.inh
+ self.inh
}
}
@@ -238,7 +238,7 @@ impl<'a, 'tcx> AstConv<'tcx> for FnCtxt<'a, 'tcx> {
fn re_infer(&self, def: Option<&ty::GenericParamDef>, span: Span) -> Option<ty::Region<'tcx>> {
let v = match def {
- Some(def) => infer::EarlyBoundRegion(span, def.name),
+ Some(def) => infer::RegionParameterDefinition(span, def.name),
None => infer::MiscVariable(span),
};
Some(self.next_region_var(v))
@@ -289,7 +289,7 @@ impl<'a, 'tcx> AstConv<'tcx> for FnCtxt<'a, 'tcx> {
) -> Ty<'tcx> {
let trait_ref = self.instantiate_binder_with_fresh_vars(
span,
- infer::LateBoundRegionConversionTime::AssocTypeProjection(item_def_id),
+ infer::BoundRegionConversionTime::AssocTypeProjection(item_def_id),
poly_trait_ref,
);
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
index c43d4932f..668e54757 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
@@ -43,7 +43,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
self.typeck_results
.borrow()
.liberated_fn_sigs()
- .get(self.tcx.hir().local_def_id_to_hir_id(self.body_id))
+ .get(self.tcx.local_def_id_to_hir_id(self.body_id))
.copied()
}
@@ -72,23 +72,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
blk_id: hir::HirId,
) -> bool {
let expr = expr.peel_drop_temps();
- self.suggest_missing_semicolon(err, expr, expected, false);
let mut pointing_at_return_type = false;
if let hir::ExprKind::Break(..) = expr.kind {
// `break` type mismatches provide better context for tail `loop` expressions.
return false;
}
if let Some((fn_id, fn_decl, can_suggest)) = self.get_fn_decl(blk_id) {
- pointing_at_return_type = self.suggest_missing_return_type(
- err,
- &fn_decl,
- expected,
- found,
- can_suggest,
- fn_id,
- );
+ pointing_at_return_type =
+ self.suggest_missing_return_type(err, fn_decl, expected, found, can_suggest, fn_id);
self.suggest_missing_break_or_return_expr(
- err, expr, &fn_decl, expected, found, blk_id, fn_id,
+ err, expr, fn_decl, expected, found, blk_id, fn_id,
);
}
pointing_at_return_type
@@ -449,12 +442,22 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
expected,
)
});
+
+ let prefix_wrap = |sugg: &str| {
+ if let Some(name) = self.tcx.hir().maybe_get_struct_pattern_shorthand_field(expr) {
+ format!(": {}{}", name, sugg)
+ } else {
+ sugg.to_string()
+ }
+ };
+
// FIXME: This could/should be extended to suggest `as_mut` and `as_deref_mut`,
// but those checks need to be a bit more delicate and the benefit is diminishing.
if self.can_eq(self.param_env, found_ty_inner, peeled) && error_tys_equate_as_ref {
+ let sugg = prefix_wrap(".as_ref()");
err.subdiagnostic(errors::SuggestConvertViaMethod {
span: expr.span.shrink_to_hi(),
- sugg: ".as_ref()",
+ sugg,
expected,
found,
borrow_removal_span,
@@ -465,9 +468,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
&& self.can_eq(self.param_env, deref_ty, peeled)
&& error_tys_equate_as_ref
{
+ let sugg = prefix_wrap(".as_deref()");
err.subdiagnostic(errors::SuggestConvertViaMethod {
span: expr.span.shrink_to_hi(),
- sugg: ".as_deref()",
+ sugg,
expected,
found,
borrow_removal_span,
@@ -481,10 +485,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
self.can_eq(self.param_env, found, expected)
})
{
+ let sugg = prefix_wrap(".map(|x| x.as_str())");
err.span_suggestion_verbose(
expr.span.shrink_to_hi(),
fluent::hir_typeck_convert_to_str,
- ".map(|x| x.as_str())",
+ sugg,
Applicability::MachineApplicable,
);
return true;
@@ -615,7 +620,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
return false;
}
let pin_did = self.tcx.lang_items().pin_type();
- // This guards the `unwrap` and `mk_box` below.
+ // This guards the `new_box` below.
if pin_did.is_none() || self.tcx.lang_items().owned_box().is_none() {
return false;
}
@@ -635,12 +640,20 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
err.help("use `Box::pin`");
}
_ => {
+ let prefix = if let Some(name) =
+ self.tcx.hir().maybe_get_struct_pattern_shorthand_field(expr)
+ {
+ format!("{}: ", name)
+ } else {
+ String::new()
+ };
+ let suggestion = vec![
+ (expr.span.shrink_to_lo(), format!("{prefix}Box::pin(")),
+ (expr.span.shrink_to_hi(), ")".to_string()),
+ ];
err.multipart_suggestion(
"you need to pin and box this expression",
- vec![
- (expr.span.shrink_to_lo(), "Box::pin(".to_string()),
- (expr.span.shrink_to_hi(), ")".to_string()),
- ],
+ suggestion,
Applicability::MaybeIncorrect,
);
}
@@ -664,7 +677,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// can suggest Box::pin.
let parent = self.tcx.hir().parent_id(expr.hir_id);
let Some(Node::Expr(Expr { kind: ExprKind::Call(fn_name, _), .. })) =
- self.tcx.hir().find(parent)
+ self.tcx.opt_hir_node(parent)
else {
return false;
};
@@ -811,10 +824,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
if let hir::TyKind::OpaqueDef(item_id, ..) = hir_ty.kind
&& let hir::Node::Item(hir::Item {
kind: hir::ItemKind::OpaqueTy(op_ty), ..
- }) = self.tcx.hir().get(item_id.hir_id())
- && let [
- hir::GenericBound::LangItemTrait(hir::LangItem::Future, _, _, generic_args),
- ] = op_ty.bounds
+ }) = self.tcx.hir_node(item_id.hir_id())
+ && let [hir::GenericBound::Trait(trait_ref, _)] = op_ty.bounds
+ && let Some(hir::PathSegment { args: Some(generic_args), .. }) =
+ trait_ref.trait_ref.path.segments.last()
&& let hir::GenericArgs { bindings: [ty_binding], .. } = generic_args
&& let hir::TypeBindingKind::Equality { term: hir::Term::Ty(term) } =
ty_binding.kind
@@ -846,7 +859,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let bound_vars = self.tcx.late_bound_vars(hir_ty.hir_id.owner.into());
let ty = Binder::bind_with_vars(ty, bound_vars);
let ty = self.normalize(hir_ty.span, ty);
- let ty = self.tcx.erase_late_bound_regions(ty);
+ let ty = self.tcx.instantiate_bound_regions_with_erased(ty);
if self.can_coerce(expected, ty) {
err.subdiagnostic(errors::ExpectedReturnTypeLabel::Other {
span: hir_ty.span,
@@ -889,7 +902,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let ty::Param(expected_ty_as_param) = expected.kind() else { return };
- let fn_node = self.tcx.hir().find(fn_id);
+ let fn_node = self.tcx.opt_hir_node(fn_id);
let Some(hir::Node::Item(hir::Item {
kind:
@@ -1023,7 +1036,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
if let hir::FnRetTy::Return(ty) = fn_decl.output {
let ty = self.astconv().ast_ty_to_ty(ty);
let bound_vars = self.tcx.late_bound_vars(fn_id);
- let ty = self.tcx.erase_late_bound_regions(Binder::bind_with_vars(ty, bound_vars));
+ let ty = self
+ .tcx
+ .instantiate_bound_regions_with_erased(Binder::bind_with_vars(ty, bound_vars));
let ty = match self.tcx.asyncness(fn_id.owner) {
ty::Asyncness::Yes => self.get_impl_future_output_ty(ty).unwrap_or_else(|| {
span_bug!(fn_decl.output.span(), "failed to get output type of async function")
@@ -1032,7 +1047,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
};
let ty = self.normalize(expr.span, ty);
if self.can_coerce(found, ty) {
- if let Some(node) = self.tcx.hir().find(fn_id)
+ if let Some(node) = self.tcx.opt_hir_node(fn_id)
&& let Some(owner_node) = node.as_owner()
&& let Some(span) = expr.span.find_ancestor_inside(owner_node.span())
{
@@ -1219,7 +1234,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
span = parent_callsite;
}
- let sugg = if expr.precedence().order() >= PREC_POSTFIX {
+ let mut sugg = if expr.precedence().order() >= PREC_POSTFIX {
vec![(span.shrink_to_hi(), ".into()".to_owned())]
} else {
vec![
@@ -1227,6 +1242,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
(span.shrink_to_hi(), ").into()".to_owned()),
]
};
+ if let Some(name) = self.tcx.hir().maybe_get_struct_pattern_shorthand_field(expr) {
+ sugg.insert(0, (expr.span.shrink_to_lo(), format!("{}: ", name)));
+ }
diag.multipart_suggestion(
format!("call `Into::into` on this expression to convert `{expr_ty}` into `{expected_ty}`"),
sugg,
@@ -1527,12 +1545,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}
fn is_loop(&self, id: hir::HirId) -> bool {
- let node = self.tcx.hir().get(id);
+ let node = self.tcx.hir_node(id);
matches!(node, Node::Expr(Expr { kind: ExprKind::Loop(..), .. }))
}
fn is_local_statement(&self, id: hir::HirId) -> bool {
- let node = self.tcx.hir().get(id);
+ let node = self.tcx.hir_node(id);
matches!(node, Node::Stmt(Stmt { kind: StmtKind::Local(..), .. }))
}
@@ -1601,6 +1619,46 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
None,
);
} else {
+ if let Some(errors) =
+ self.could_impl_trait(clone_trait_did, expected_ty, self.param_env)
+ {
+ match &errors[..] {
+ [] => {}
+ [error] => {
+ diag.help(format!(
+ "`Clone` is not implemented because the trait bound `{}` is \
+ not satisfied",
+ error.obligation.predicate,
+ ));
+ }
+ [errors @ .., last] => {
+ diag.help(format!(
+ "`Clone` is not implemented because the following trait bounds \
+ could not be satisfied: {} and `{}`",
+ errors
+ .iter()
+ .map(|e| format!("`{}`", e.obligation.predicate))
+ .collect::<Vec<_>>()
+ .join(", "),
+ last.obligation.predicate,
+ ));
+ }
+ }
+ for error in errors {
+ if let traits::FulfillmentErrorCode::CodeSelectionError(
+ traits::SelectionError::Unimplemented,
+ ) = error.code
+ && let ty::PredicateKind::Clause(ty::ClauseKind::Trait(pred)) =
+ error.obligation.predicate.kind().skip_binder()
+ {
+ self.infcx.err_ctxt().suggest_derive(
+ &error.obligation,
+ diag,
+ error.obligation.predicate.kind().rebind(pred),
+ );
+ }
+ }
+ }
self.suggest_derive(diag, &[(trait_ref.to_predicate(self.tcx), None, None)]);
}
}
@@ -1619,11 +1677,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
None,
hir::Path { segments: [_], res: crate::Res::Local(binding), .. },
)) => {
- let Some(hir::Node::Pat(hir::Pat { hir_id, .. })) = self.tcx.hir().find(*binding)
+ let Some(hir::Node::Pat(hir::Pat { hir_id, .. })) = self.tcx.opt_hir_node(*binding)
else {
return expr;
};
- let Some(parent) = self.tcx.hir().find(self.tcx.hir().parent_id(*hir_id)) else {
+ let Some(parent) = self.tcx.opt_hir_node(self.tcx.hir().parent_id(*hir_id)) else {
return expr;
};
@@ -1639,7 +1697,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
..
}) => {
let Some(hir::Node::Local(hir::Local { init: Some(init), .. })) =
- self.tcx.hir().find(self.tcx.hir().parent_id(*pat_hir_id))
+ self.tcx.opt_hir_node(self.tcx.hir().parent_id(*pat_hir_id))
else {
return expr;
};
@@ -1672,8 +1730,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
&& let hir::Path { segments: [_], res: crate::Res::Local(binding), .. } =
call_expr_path
&& let Some(hir::Node::Pat(hir::Pat { hir_id, .. })) =
- self.tcx.hir().find(*binding)
- && let Some(closure) = self.tcx.hir().find(self.tcx.hir().parent_id(*hir_id))
+ self.tcx.opt_hir_node(*binding)
+ && let Some(closure) = self.tcx.opt_hir_node(self.tcx.hir().parent_id(*hir_id))
&& let hir::Node::Local(hir::Local { init: Some(init), .. }) = closure
&& let Expr {
kind: hir::ExprKind::Closure(hir::Closure { body: body_id, .. }),
@@ -1816,6 +1874,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
".expect(\"REASON\")",
)
};
+
+ let sugg = match self.tcx.hir().maybe_get_struct_pattern_shorthand_field(expr) {
+ Some(ident) => format!(": {ident}{sugg}"),
+ None => sugg.to_string(),
+ };
+
err.span_suggestion_verbose(
expr.span.shrink_to_hi(),
msg,
@@ -1921,7 +1985,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
if let Some(hir::Node::Block(&hir::Block {
span: block_span, expr: Some(e), ..
- })) = self.tcx.hir().find(parent)
+ })) = self.tcx.opt_hir_node(parent)
{
if e.hir_id == id {
if let Some(span) = expr.span.find_ancestor_inside(block_span) {
@@ -2008,8 +2072,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
Some(CtorKind::Fn) => ("(".to_owned(), ")"),
None => (format!(" {{ {field_name}: "), " }"),
- // unit variants don't have fields
- Some(CtorKind::Const) => unreachable!(),
+ Some(CtorKind::Const) => unreachable!("unit variants don't have fields"),
};
// Suggest constructor as deep into the block tree as possible.
@@ -2137,7 +2200,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
/// opt.map(|param| { takes_ref(param) });
/// ```
fn can_use_as_ref(&self, expr: &hir::Expr<'_>) -> Option<(Vec<(Span, String)>, &'static str)> {
- let hir::ExprKind::Path(hir::QPath::Resolved(_, ref path)) = expr.kind else {
+ let hir::ExprKind::Path(hir::QPath::Resolved(_, path)) = expr.kind else {
return None;
};
@@ -2147,7 +2210,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let local_parent = self.tcx.hir().parent_id(local_id);
let Some(Node::Param(hir::Param { hir_id: param_hir_id, .. })) =
- self.tcx.hir().find(local_parent)
+ self.tcx.opt_hir_node(local_parent)
else {
return None;
};
@@ -2157,13 +2220,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
hir_id: expr_hir_id,
kind: hir::ExprKind::Closure(hir::Closure { fn_decl: closure_fn_decl, .. }),
..
- })) = self.tcx.hir().find(param_parent)
+ })) = self.tcx.opt_hir_node(param_parent)
else {
return None;
};
let expr_parent = self.tcx.hir().parent_id(*expr_hir_id);
- let hir = self.tcx.hir().find(expr_parent);
+ let hir = self.tcx.opt_hir_node(expr_parent);
let closure_params_len = closure_fn_decl.inputs.len();
let (
Some(Node::Expr(hir::Expr {
@@ -2293,16 +2356,18 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
};
if self.can_coerce(ref_ty, expected) {
let mut sugg_sp = sp;
- if let hir::ExprKind::MethodCall(ref segment, receiver, args, _) = expr.kind {
+ if let hir::ExprKind::MethodCall(segment, receiver, args, _) = expr.kind {
let clone_trait =
self.tcx.require_lang_item(LangItem::Clone, Some(segment.ident.span));
if args.is_empty()
- && self.typeck_results.borrow().type_dependent_def_id(expr.hir_id).map(
- |did| {
+ && self
+ .typeck_results
+ .borrow()
+ .type_dependent_def_id(expr.hir_id)
+ .is_some_and(|did| {
let ai = self.tcx.associated_item(did);
ai.trait_container(self.tcx) == Some(clone_trait)
- },
- ) == Some(true)
+ })
&& segment.ident.name == sym::clone
{
// If this expression had a clone call when suggesting borrowing
@@ -2311,7 +2376,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}
}
- if let hir::ExprKind::Unary(hir::UnOp::Deref, ref inner) = expr.kind
+ if let hir::ExprKind::Unary(hir::UnOp::Deref, inner) = expr.kind
&& let Some(1) = self.deref_steps(expected, checked_ty)
{
// We have `*&T`, check if what was expected was `&T`.
@@ -2326,14 +2391,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
));
}
- let needs_parens = match expr.kind {
- // parenthesize if needed (Issue #46756)
- hir::ExprKind::Cast(_, _) | hir::ExprKind::Binary(_, _, _) => true,
- // parenthesize borrows of range literals (Issue #54505)
- _ if is_range_literal(expr) => true,
- _ => false,
- };
-
if let Some((sugg, msg)) = self.can_use_as_ref(expr) {
return Some((
sugg,
@@ -2361,18 +2418,48 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}
}
- let sugg = mutability.ref_prefix_str();
- let (sugg, verbose) = if needs_parens {
- (
- vec![
- (sp.shrink_to_lo(), format!("{prefix}{sugg}(")),
- (sp.shrink_to_hi(), ")".to_string()),
- ],
- false,
- )
- } else {
- (vec![(sp.shrink_to_lo(), format!("{prefix}{sugg}"))], true)
+ let make_sugg = |expr: &Expr<'_>, span: Span, sugg: &str| {
+ let needs_parens = match expr.kind {
+ // parenthesize if needed (Issue #46756)
+ hir::ExprKind::Cast(_, _) | hir::ExprKind::Binary(_, _, _) => true,
+ // parenthesize borrows of range literals (Issue #54505)
+ _ if is_range_literal(expr) => true,
+ _ => false,
+ };
+
+ if needs_parens {
+ (
+ vec![
+ (span.shrink_to_lo(), format!("{prefix}{sugg}(")),
+ (span.shrink_to_hi(), ")".to_string()),
+ ],
+ false,
+ )
+ } else {
+ (vec![(span.shrink_to_lo(), format!("{prefix}{sugg}"))], true)
+ }
};
+
+ // Suggest dereferencing the lhs for expressions such as `&T == T`
+ if let Some(hir::Node::Expr(hir::Expr {
+ kind: hir::ExprKind::Binary(_, lhs, ..),
+ ..
+ })) = self.tcx.hir().find_parent(expr.hir_id)
+ && let &ty::Ref(..) = self.check_expr(lhs).kind()
+ {
+ let (sugg, verbose) = make_sugg(lhs, lhs.span, "*");
+
+ return Some((
+ sugg,
+ "consider dereferencing the borrow".to_string(),
+ Applicability::MachineApplicable,
+ verbose,
+ false,
+ ));
+ }
+
+ let sugg = mutability.ref_prefix_str();
+ let (sugg, verbose) = make_sugg(expr, sp, sugg);
return Some((
sugg,
format!("consider {}borrowing here", mutability.mutably_str()),
@@ -2382,11 +2469,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
));
}
}
- (
- hir::ExprKind::AddrOf(hir::BorrowKind::Ref, _, ref expr),
- _,
- &ty::Ref(_, checked, _),
- ) if self.can_sub(self.param_env, checked, expected) => {
+ (hir::ExprKind::AddrOf(hir::BorrowKind::Ref, _, expr), _, &ty::Ref(_, checked, _))
+ if self.can_sub(self.param_env, checked, expected) =>
+ {
let make_sugg = |start: Span, end: BytePos| {
// skip `(` for tuples such as `(c) = (&123)`.
// make sure we won't suggest like `(c) = 123)` which is incorrect.
@@ -2581,7 +2666,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
if let Some(Node::Expr(hir::Expr {
kind: hir::ExprKind::If(_, _, Some(else_expr)),
..
- })) = self.tcx.hir().find(parent_id)
+ })) = self.tcx.opt_hir_node(parent_id)
{
return else_expr.hir_id == expr.hir_id;
}
@@ -2971,7 +3056,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
return;
};
let parent = self.tcx.hir().parent_id(expr.hir_id);
- if let Some(hir::Node::ExprField(_)) = self.tcx.hir().find(parent) {
+ if let Some(hir::Node::ExprField(_)) = self.tcx.opt_hir_node(parent) {
// Ignore `Foo { field: a..Default::default() }`
return;
}
@@ -3050,7 +3135,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let hir::def::Res::Local(hir_id) = path.res else {
return;
};
- let Some(hir::Node::Pat(pat)) = self.tcx.hir().find(hir_id) else {
+ let Some(hir::Node::Pat(pat)) = self.tcx.opt_hir_node(hir_id) else {
return;
};
let Some(hir::Node::Local(hir::Local { ty: None, init: Some(init), .. })) =
diff --git a/compiler/rustc_hir_typeck/src/gather_locals.rs b/compiler/rustc_hir_typeck/src/gather_locals.rs
index 0ad2c1d92..0cca779b1 100644
--- a/compiler/rustc_hir_typeck/src/gather_locals.rs
+++ b/compiler/rustc_hir_typeck/src/gather_locals.rs
@@ -93,7 +93,7 @@ impl<'a, 'tcx> GatherLocalsVisitor<'a, 'tcx> {
fn declare(&mut self, decl: Declaration<'tcx>) {
let local_ty = match decl.ty {
Some(ref ty) => {
- let o_ty = self.fcx.to_ty(&ty);
+ let o_ty = self.fcx.to_ty(ty);
let c_ty =
self.fcx.inh.infcx.canonicalize_user_type_annotation(UserType::Ty(o_ty.raw));
diff --git a/compiler/rustc_hir_typeck/src/inherited.rs b/compiler/rustc_hir_typeck/src/inherited.rs
index efd0b8577..7a6a2b2a0 100644
--- a/compiler/rustc_hir_typeck/src/inherited.rs
+++ b/compiler/rustc_hir_typeck/src/inherited.rs
@@ -9,7 +9,7 @@ use rustc_middle::traits::DefiningAnchor;
use rustc_middle::ty::visit::TypeVisitableExt;
use rustc_middle::ty::{self, Ty, TyCtxt};
use rustc_span::def_id::LocalDefIdMap;
-use rustc_span::{self, Span};
+use rustc_span::Span;
use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt;
use rustc_trait_selection::traits::{self, PredicateObligation, TraitEngine, TraitEngineExt as _};
@@ -75,7 +75,7 @@ impl<'tcx> Deref for Inherited<'tcx> {
impl<'tcx> Inherited<'tcx> {
pub fn new(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Self {
- let hir_owner = tcx.hir().local_def_id_to_hir_id(def_id).owner;
+ let hir_owner = tcx.local_def_id_to_hir_id(def_id).owner;
let infcx = tcx
.infer_ctxt()
diff --git a/compiler/rustc_hir_typeck/src/intrinsicck.rs b/compiler/rustc_hir_typeck/src/intrinsicck.rs
index 5d516eaf5..a3c77af62 100644
--- a/compiler/rustc_hir_typeck/src/intrinsicck.rs
+++ b/compiler/rustc_hir_typeck/src/intrinsicck.rs
@@ -48,7 +48,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let to = normalize(to);
trace!(?from, ?to);
if from.has_non_region_infer() || to.has_non_region_infer() {
- tcx.sess.delay_span_bug(span, "argument to transmute has inference variables");
+ tcx.sess.span_delayed_bug(span, "argument to transmute has inference variables");
return;
}
// Transmutes that are only changing lifetimes are always ok.
diff --git a/compiler/rustc_hir_typeck/src/lib.rs b/compiler/rustc_hir_typeck/src/lib.rs
index 46dcc4555..13a249486 100644
--- a/compiler/rustc_hir_typeck/src/lib.rs
+++ b/compiler/rustc_hir_typeck/src/lib.rs
@@ -52,11 +52,7 @@ use crate::expectation::Expectation;
use crate::fn_ctxt::RawTy;
use crate::gather_locals::GatherLocalsVisitor;
use rustc_data_structures::unord::UnordSet;
-use rustc_errors::{
- struct_span_err, DiagnosticId, DiagnosticMessage, ErrorGuaranteed, MultiSpan,
- SubdiagnosticMessage,
-};
-use rustc_fluent_macro::fluent_messages;
+use rustc_errors::{struct_span_err, DiagnosticId, ErrorGuaranteed, MultiSpan};
use rustc_hir as hir;
use rustc_hir::def::{DefKind, Res};
use rustc_hir::intravisit::Visitor;
@@ -71,7 +67,7 @@ use rustc_session::config;
use rustc_span::def_id::{DefId, LocalDefId};
use rustc_span::Span;
-fluent_messages! { "../messages.ftl" }
+rustc_fluent_macro::fluent_messages! { "../messages.ftl" }
#[macro_export]
macro_rules! type_error_struct {
@@ -131,7 +127,7 @@ fn has_typeck_results(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
}
if let Some(def_id) = def_id.as_local() {
- primary_body_of(tcx.hir().get_by_def_id(def_id)).is_some()
+ primary_body_of(tcx.hir_node_by_def_id(def_id)).is_some()
} else {
false
}
@@ -150,7 +146,7 @@ fn typeck<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> &ty::TypeckResults<'tc
/// Currently only used for type inference of `static`s and `const`s to avoid type cycle errors.
fn diagnostic_only_typeck<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> &ty::TypeckResults<'tcx> {
let fallback = move || {
- let span = tcx.hir().span(tcx.hir().local_def_id_to_hir_id(def_id));
+ let span = tcx.hir().span(tcx.local_def_id_to_hir_id(def_id));
Ty::new_error_with_message(tcx, span, "diagnostic only typeck table used")
};
typeck_with_fallback(tcx, def_id, fallback)
@@ -169,8 +165,8 @@ fn typeck_with_fallback<'tcx>(
return tcx.typeck(typeck_root_def_id);
}
- let id = tcx.hir().local_def_id_to_hir_id(def_id);
- let node = tcx.hir().get(id);
+ let id = tcx.local_def_id_to_hir_id(def_id);
+ let node = tcx.hir_node(id);
let span = tcx.hir().span(id);
// Figure out what primary body this item has.
@@ -205,7 +201,7 @@ fn typeck_with_fallback<'tcx>(
span,
}))
} else if let Node::AnonConst(_) = node {
- match tcx.hir().get(tcx.hir().parent_id(id)) {
+ match tcx.hir_node(tcx.hir().parent_id(id)) {
Node::Ty(&hir::Ty { kind: hir::TyKind::Typeof(ref anon_const), .. })
if anon_const.hir_id == id =>
{
@@ -243,7 +239,7 @@ fn typeck_with_fallback<'tcx>(
// Gather locals in statics (because of block expressions).
GatherLocalsVisitor::new(&fcx).visit_body(body);
- fcx.check_expr_coercible_to_type(&body.value, expected_type, None);
+ fcx.check_expr_coercible_to_type(body.value, expected_type, None);
fcx.write_ty(id, expected_type);
};
@@ -287,8 +283,6 @@ fn typeck_with_fallback<'tcx>(
fcx.check_asms();
- fcx.infcx.skip_region_resolution();
-
let typeck_results = fcx.resolve_type_vars_in_body(body);
// Consistency check our TypeckResults instance can hold all ItemLocalIds
@@ -419,32 +413,32 @@ enum TupleArgumentsFlag {
}
fn fatally_break_rust(tcx: TyCtxt<'_>) {
- let handler = tcx.sess.diagnostic();
- handler.span_bug_no_panic(
+ let dcx = tcx.sess.dcx();
+ dcx.span_bug_no_panic(
MultiSpan::new(),
"It looks like you're trying to break rust; would you like some ICE?",
);
- handler.note_without_error("the compiler expectedly panicked. this is a feature.");
- handler.note_without_error(
+ dcx.note("the compiler expectedly panicked. this is a feature.");
+ dcx.note(
"we would appreciate a joke overview: \
https://github.com/rust-lang/rust/issues/43162#issuecomment-320764675",
);
- handler.note_without_error(format!(
- "rustc {} running on {}",
- tcx.sess.cfg_version,
- config::host_triple(),
- ));
+ dcx.note(format!("rustc {} running on {}", tcx.sess.cfg_version, config::host_triple(),));
if let Some((flags, excluded_cargo_defaults)) = rustc_session::utils::extra_compiler_flags() {
- handler.note_without_error(format!("compiler flags: {}", flags.join(" ")));
+ dcx.note(format!("compiler flags: {}", flags.join(" ")));
if excluded_cargo_defaults {
- handler.note_without_error("some of the compiler flags provided by cargo are hidden");
+ dcx.note("some of the compiler flags provided by cargo are hidden");
}
}
}
+/// `expected` here is the expected number of explicit generic arguments on the trait.
fn has_expected_num_generic_args(tcx: TyCtxt<'_>, trait_did: DefId, expected: usize) -> bool {
let generics = tcx.generics_of(trait_did);
- generics.count() == expected + if generics.has_self { 1 } else { 0 }
+ generics.count()
+ == expected
+ + if generics.has_self { 1 } else { 0 }
+ + if generics.host_effect_index.is_some() { 1 } else { 0 }
}
pub fn provide(providers: &mut Providers) {
diff --git a/compiler/rustc_hir_typeck/src/mem_categorization.rs b/compiler/rustc_hir_typeck/src/mem_categorization.rs
index 337d12b2d..ebb15e072 100644
--- a/compiler/rustc_hir_typeck/src/mem_categorization.rs
+++ b/compiler/rustc_hir_typeck/src/mem_categorization.rs
@@ -66,25 +66,18 @@ use rustc_trait_selection::infer::InferCtxtExt;
pub(crate) trait HirNode {
fn hir_id(&self) -> hir::HirId;
- fn span(&self) -> Span;
}
impl HirNode for hir::Expr<'_> {
fn hir_id(&self) -> hir::HirId {
self.hir_id
}
- fn span(&self) -> Span {
- self.span
- }
}
impl HirNode for hir::Pat<'_> {
fn hir_id(&self) -> hir::HirId {
self.hir_id
}
- fn span(&self) -> Span {
- self.span
- }
}
#[derive(Clone)]
@@ -304,7 +297,7 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> {
) -> McResult<PlaceWithHirId<'tcx>> {
let expr_ty = self.expr_ty(expr)?;
match expr.kind {
- hir::ExprKind::Unary(hir::UnOp::Deref, ref e_base) => {
+ hir::ExprKind::Unary(hir::UnOp::Deref, e_base) => {
if self.typeck_results.is_method_call(expr) {
self.cat_overloaded_place(expr, e_base)
} else {
@@ -313,7 +306,7 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> {
}
}
- hir::ExprKind::Field(ref base, _) => {
+ hir::ExprKind::Field(base, _) => {
let base = self.cat_expr(base)?;
debug!(?base);
@@ -332,7 +325,7 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> {
))
}
- hir::ExprKind::Index(ref base, _, _) => {
+ hir::ExprKind::Index(base, _, _) => {
if self.typeck_results.is_method_call(expr) {
// If this is an index implemented by a method call, then it
// will include an implicit deref of the result.
@@ -351,7 +344,7 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> {
self.cat_res(expr.hir_id, expr.span, expr_ty, res)
}
- hir::ExprKind::Type(ref e, _) => self.cat_expr(e),
+ hir::ExprKind::Type(e, _) => self.cat_expr(e),
hir::ExprKind::AddrOf(..)
| hir::ExprKind::Call(..)
@@ -547,7 +540,7 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> {
let ty::Adt(adt_def, _) = ty.kind() else {
self.tcx()
.sess
- .delay_span_bug(span, "struct or tuple struct pattern not applied to an ADT");
+ .span_delayed_bug(span, "struct or tuple struct pattern not applied to an ADT");
return Err(());
};
@@ -582,7 +575,7 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> {
_ => {
self.tcx()
.sess
- .delay_span_bug(span, "struct or tuple struct pattern not applied to an ADT");
+ .span_delayed_bug(span, "struct or tuple struct pattern not applied to an ADT");
Err(())
}
}
@@ -595,7 +588,7 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> {
match ty.kind() {
ty::Tuple(args) => Ok(args.len()),
_ => {
- self.tcx().sess.delay_span_bug(span, "tuple pattern not applied to a tuple");
+ self.tcx().sess.span_delayed_bug(span, "tuple pattern not applied to a tuple");
Err(())
}
}
@@ -728,11 +721,11 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> {
}
}
- PatKind::Binding(.., Some(ref subpat)) => {
+ PatKind::Binding(.., Some(subpat)) => {
self.cat_pattern_(place_with_id, subpat, op)?;
}
- PatKind::Box(ref subpat) | PatKind::Ref(ref subpat, _) => {
+ PatKind::Box(subpat) | PatKind::Ref(subpat, _) => {
// box p1, &p1, &mut p1. we can ignore the mutability of
// PatKind::Ref since that information is already contained
// in the type.
@@ -754,7 +747,7 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> {
for before_pat in before {
self.cat_pattern_(elt_place.clone(), before_pat, op)?;
}
- if let Some(ref slice_pat) = *slice {
+ if let Some(slice_pat) = *slice {
let slice_pat_ty = self.pat_ty_adjusted(slice_pat)?;
let slice_place = self.cat_projection(
pat,
@@ -773,6 +766,7 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> {
| PatKind::Binding(.., None)
| PatKind::Lit(..)
| PatKind::Range(..)
+ | PatKind::Never
| PatKind::Wild => {
// always ok
}
diff --git a/compiler/rustc_hir_typeck/src/method/confirm.rs b/compiler/rustc_hir_typeck/src/method/confirm.rs
index 7c73f6a89..b2ead3cd4 100644
--- a/compiler/rustc_hir_typeck/src/method/confirm.rs
+++ b/compiler/rustc_hir_typeck/src/method/confirm.rs
@@ -93,16 +93,16 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
segment: &hir::PathSegment<'_>,
) -> ConfirmResult<'tcx> {
// Adjust the self expression the user provided and obtain the adjusted type.
- let self_ty = self.adjust_self_ty(unadjusted_self_ty, &pick);
+ let self_ty = self.adjust_self_ty(unadjusted_self_ty, pick);
// Create substitutions for the method's type parameters.
- let rcvr_args = self.fresh_receiver_args(self_ty, &pick);
- let all_args = self.instantiate_method_args(&pick, segment, rcvr_args);
+ let rcvr_args = self.fresh_receiver_args(self_ty, pick);
+ let all_args = self.instantiate_method_args(pick, segment, rcvr_args);
debug!("rcvr_args={rcvr_args:?}, all_args={all_args:?}");
// Create the final signature for the method, replacing late-bound regions.
- let (method_sig, method_predicates) = self.instantiate_method_sig(&pick, all_args);
+ let (method_sig, method_predicates) = self.instantiate_method_sig(pick, all_args);
// If there is a `Self: Sized` bound and `Self` is a trait object, it is possible that
// something which derefs to `Self` actually implements the trait and the caller
@@ -129,14 +129,14 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
"confirm: self_ty={:?} method_sig_rcvr={:?} method_sig={:?} method_predicates={:?}",
self_ty, method_sig_rcvr, method_sig, method_predicates
);
- self.unify_receivers(self_ty, method_sig_rcvr, &pick, all_args);
+ self.unify_receivers(self_ty, method_sig_rcvr, pick, all_args);
let (method_sig, method_predicates) =
self.normalize(self.span, (method_sig, method_predicates));
let method_sig = ty::Binder::dummy(method_sig);
// Make sure nobody calls `drop()` explicitly.
- self.enforce_illegal_method_limitations(&pick);
+ self.enforce_illegal_method_limitations(pick);
// Add any trait/regions obligations specified on the method's type parameters.
// We won't add these if we encountered an illegal sized bound, so that we can use
@@ -415,7 +415,9 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
)
.into()
}
- _ => unreachable!(),
+ (kind, arg) => {
+ bug!("mismatched method arg kind {kind:?} in turbofish: {arg:?}")
+ }
}
}
diff --git a/compiler/rustc_hir_typeck/src/method/mod.rs b/compiler/rustc_hir_typeck/src/method/mod.rs
index d69d2529b..f820835ac 100644
--- a/compiler/rustc_hir_typeck/src/method/mod.rs
+++ b/compiler/rustc_hir_typeck/src/method/mod.rs
@@ -385,7 +385,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// type parameters or early-bound regions.
let tcx = self.tcx;
let Some(method_item) = self.associated_value(trait_def_id, m_name) else {
- tcx.sess.delay_span_bug(
+ tcx.sess.span_delayed_bug(
obligation.cause.span,
"operator trait does not have corresponding operator method",
);
@@ -393,7 +393,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
};
if method_item.kind != ty::AssocKind::Fn {
- self.tcx.sess.delay_span_bug(tcx.def_span(method_item.def_id), "not a method");
+ self.tcx.sess.span_delayed_bug(tcx.def_span(method_item.def_id), "not a method");
return None;
}
diff --git a/compiler/rustc_hir_typeck/src/method/prelude2021.rs b/compiler/rustc_hir_typeck/src/method/prelude2021.rs
index 3f1dca5b1..43d258de6 100644
--- a/compiler/rustc_hir_typeck/src/method/prelude2021.rs
+++ b/compiler/rustc_hir_typeck/src/method/prelude2021.rs
@@ -122,8 +122,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
format!("disambiguate the method call with `({self_adjusted})`",),
);
}
-
- lint
},
);
} else {
@@ -187,8 +185,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
),
);
}
-
- lint
},
);
}
@@ -307,8 +303,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
format!("<{} as {}>::{}", self_ty_name, trait_name, method_name.name,),
Applicability::MachineApplicable,
);
-
- lint
},
);
}
diff --git a/compiler/rustc_hir_typeck/src/method/probe.rs b/compiler/rustc_hir_typeck/src/method/probe.rs
index 74f469cb3..fe2d43a3c 100644
--- a/compiler/rustc_hir_typeck/src/method/probe.rs
+++ b/compiler/rustc_hir_typeck/src/method/probe.rs
@@ -445,7 +445,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
scope_expr_id,
span,
"type annotations needed",
- |lint| lint,
+ |_| {},
);
}
} else {
@@ -619,7 +619,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
fn push_candidate(&mut self, candidate: Candidate<'tcx>, is_inherent: bool) {
let is_accessible = if let Some(name) = self.method_name {
let item = candidate.item;
- let hir_id = self.tcx.hir().local_def_id_to_hir_id(self.body_id);
+ let hir_id = self.tcx.local_def_id_to_hir_id(self.body_id);
let def_scope =
self.tcx.adjust_ident_and_get_scope(name, item.container_id(self.tcx), hir_id).1;
item.visibility(self.tcx).is_accessible_from(def_scope, self.tcx)
@@ -801,15 +801,15 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
// a `&self` method will wind up with an argument type like `&dyn Trait`.
let trait_ref = principal.with_self_ty(self.tcx, self_ty);
self.elaborate_bounds(iter::once(trait_ref), |this, new_trait_ref, item| {
- if new_trait_ref.has_non_region_late_bound() {
- this.tcx.sess.delay_span_bug(
+ if new_trait_ref.has_non_region_bound_vars() {
+ this.tcx.sess.span_delayed_bug(
this.span,
"tried to select method from HRTB with non-lifetime bound vars",
);
return;
}
- let new_trait_ref = this.erase_late_bound_regions(new_trait_ref);
+ let new_trait_ref = this.instantiate_bound_regions_with_erased(new_trait_ref);
let (xform_self_ty, xform_ret_ty) =
this.xform_self_ty(item, new_trait_ref.self_ty(), new_trait_ref.args);
@@ -853,7 +853,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
self.elaborate_bounds(bounds, |this, poly_trait_ref, item| {
let trait_ref = this.instantiate_binder_with_fresh_vars(
this.span,
- infer::LateBoundRegionConversionTime::FnCall,
+ infer::BoundRegionConversionTime::FnCall,
poly_trait_ref,
);
@@ -971,7 +971,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
} else {
let new_trait_ref = self.instantiate_binder_with_fresh_vars(
self.span,
- infer::LateBoundRegionConversionTime::FnCall,
+ infer::BoundRegionConversionTime::FnCall,
bound_trait_ref,
);
@@ -1135,7 +1135,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
.fcx
.probe_instantiate_query_response(
self.span,
- &self.orig_steps_var_values,
+ self.orig_steps_var_values,
&step.self_ty,
)
.unwrap_or_else(|_| {
@@ -1427,8 +1427,6 @@ impl<'tcx> Pick<'tcx> {
));
}
}
-
- lint
},
);
}
@@ -1509,7 +1507,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
// match as well (or at least may match, sometimes we
// don't have enough information to fully evaluate).
match probe.kind {
- InherentImplCandidate(ref args, ref ref_obligations) => {
+ InherentImplCandidate(args, ref ref_obligations) => {
// `xform_ret_ty` hasn't been normalized yet, only `xform_self_ty`,
// see the reasons mentioned in the comments in `assemble_inherent_impl_probe`
// for why this is necessary
@@ -1548,9 +1546,9 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
);
let candidate_obligations = impl_obligations
- .chain(norm_obligations.into_iter())
+ .chain(norm_obligations)
.chain(ref_obligations.iter().cloned())
- .chain(normalization_obligations.into_iter());
+ .chain(normalization_obligations);
// Evaluate those obligations to see if they might possibly hold.
for o in candidate_obligations {
@@ -1799,9 +1797,10 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
.iter()
.find(|cand| self.matches_by_doc_alias(cand.def_id))
.map(|cand| cand.name)
- })
- .unwrap();
- Ok(applicable_close_candidates.into_iter().find(|method| method.name == best_name))
+ });
+ Ok(best_name.and_then(|best_name| {
+ applicable_close_candidates.into_iter().find(|method| method.name == best_name)
+ }))
}
})
}
@@ -1861,7 +1860,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
// method yet. So create fresh variables here for those too,
// if there are any.
let generics = self.tcx.generics_of(method);
- assert_eq!(args.len(), generics.parent_count as usize);
+ assert_eq!(args.len(), generics.parent_count);
let xform_fn_sig = if generics.params.is_empty() {
fn_sig.instantiate(self.tcx, args)
@@ -1885,7 +1884,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
fn_sig.instantiate(self.tcx, args)
};
- self.erase_late_bound_regions(xform_fn_sig)
+ self.instantiate_bound_regions_with_erased(xform_fn_sig)
}
/// Gets the type of an impl and generate substitutions with inference vars.
@@ -1897,7 +1896,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
}
/// Replaces late-bound-regions bound by `value` with `'static` using
- /// `ty::erase_late_bound_regions`.
+ /// `ty::instantiate_bound_regions_with_erased`.
///
/// This is only a reasonable thing to do during the *probe* phase, not the *confirm* phase, of
/// method matching. It is reasonable during the probe phase because we don't consider region
@@ -1914,11 +1913,11 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
/// region got replaced with the same variable, which requires a bit more coordination
/// and/or tracking the substitution and
/// so forth.
- fn erase_late_bound_regions<T>(&self, value: ty::Binder<'tcx, T>) -> T
+ fn instantiate_bound_regions_with_erased<T>(&self, value: ty::Binder<'tcx, T>) -> T
where
T: TypeFoldable<TyCtxt<'tcx>>,
{
- self.tcx.erase_late_bound_regions(value)
+ self.tcx.instantiate_bound_regions_with_erased(value)
}
/// Determine if the given associated item type is relevant in the current context.
@@ -1939,7 +1938,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
let Some(local_def_id) = def_id.as_local() else {
return false;
};
- let hir_id = self.fcx.tcx.hir().local_def_id_to_hir_id(local_def_id);
+ let hir_id = self.fcx.tcx.local_def_id_to_hir_id(local_def_id);
let attrs = self.fcx.tcx.hir().attrs(hir_id);
for attr in attrs {
let sym::doc = attr.name_or_empty() else {
diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs
index bd40e6c10..7595f21d9 100644
--- a/compiler/rustc_hir_typeck/src/method/suggest.rs
+++ b/compiler/rustc_hir_typeck/src/method/suggest.rs
@@ -1,6 +1,8 @@
//! Give useful errors and suggestions to users when an item can't be
//! found or is otherwise invalid.
+// ignore-tidy-filelength
+
use crate::errors;
use crate::errors::{CandidateTraitNote, NoAssociatedItem};
use crate::Expectation;
@@ -228,7 +230,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}
if let hir::ExprKind::Path(hir::QPath::Resolved(None, path)) = kind
&& let hir::def::Res::Local(hir_id) = path.res
- && let Some(hir::Node::Pat(b)) = self.tcx.hir().find(hir_id)
+ && let Some(hir::Node::Pat(b)) = self.tcx.opt_hir_node(hir_id)
&& let Some(hir::Node::Param(p)) = self.tcx.hir().find_parent(b.hir_id)
&& let Some(node) = self.tcx.hir().find_parent(p.hir_id)
&& let Some(decl) = node.fn_decl()
@@ -260,7 +262,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
rcvr_ty: Ty<'tcx>,
rcvr_expr: &hir::Expr<'tcx>,
) -> DiagnosticBuilder<'_, ErrorGuaranteed> {
- let (ty_str, _ty_file) = self.tcx.short_ty_string(rcvr_ty);
+ let mut file = None;
+ let ty_str = self.tcx.short_ty_string(rcvr_ty, &mut file);
let mut err = struct_span_err!(
self.tcx.sess,
rcvr_expr.span,
@@ -278,6 +281,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
"a writer is needed before this format string",
);
};
+ if let Some(file) = file {
+ err.note(format!("the full type name has been written to '{}'", file.display()));
+ }
err
}
@@ -297,11 +303,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let mode = no_match_data.mode;
let tcx = self.tcx;
let rcvr_ty = self.resolve_vars_if_possible(rcvr_ty);
- let ((mut ty_str, ty_file), short_ty_str) =
+ let mut ty_file = None;
+ let (mut ty_str, short_ty_str) =
if trait_missing_method && let ty::Dynamic(predicates, _, _) = rcvr_ty.kind() {
- ((predicates.to_string(), None), with_forced_trimmed_paths!(predicates.to_string()))
+ (predicates.to_string(), with_forced_trimmed_paths!(predicates.to_string()))
} else {
- (tcx.short_ty_string(rcvr_ty), with_forced_trimmed_paths!(rcvr_ty.to_string()))
+ (
+ tcx.short_ty_string(rcvr_ty, &mut ty_file),
+ with_forced_trimmed_paths!(rcvr_ty.to_string()),
+ )
};
let is_method = mode == Mode::MethodCall;
let unsatisfied_predicates = &no_match_data.unsatisfied_predicates;
@@ -369,25 +379,23 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
tcx.is_diagnostic_item(sym::write_macro, def_id)
|| tcx.is_diagnostic_item(sym::writeln_macro, def_id)
}) && item_name.name == Symbol::intern("write_fmt");
- let mut err =
- if is_write && let SelfSource::MethodCall(rcvr_expr) = source
- {
- self.suggest_missing_writer(rcvr_ty, rcvr_expr)
- } else {
- tcx.sess.create_err(NoAssociatedItem {
- span,
- item_kind,
- item_name,
- ty_prefix: if trait_missing_method {
- // FIXME(mu001999) E0599 maybe not suitable here because it is for types
- Cow::from("trait")
- } else {
- rcvr_ty.prefix_string(self.tcx)
- },
- ty_str: ty_str_reported,
- trait_missing_method,
- })
- };
+ let mut err = if is_write && let SelfSource::MethodCall(rcvr_expr) = source {
+ self.suggest_missing_writer(rcvr_ty, rcvr_expr)
+ } else {
+ tcx.sess.create_err(NoAssociatedItem {
+ span,
+ item_kind,
+ item_name,
+ ty_prefix: if trait_missing_method {
+ // FIXME(mu001999) E0599 maybe not suitable here because it is for types
+ Cow::from("trait")
+ } else {
+ rcvr_ty.prefix_string(self.tcx)
+ },
+ ty_str: ty_str_reported,
+ trait_missing_method,
+ })
+ };
if tcx.sess.source_map().is_multiline(sugg_span) {
err.span_label(sugg_span.with_hi(span.lo()), "");
}
@@ -484,7 +492,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
self.note_internal_mutation_in_method(
&mut err,
rcvr_expr,
- expected.to_option(&self),
+ expected.to_option(self),
rcvr_ty,
);
}
@@ -509,7 +517,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
if static_candidates.len() == 1 {
self.suggest_associated_call_syntax(
&mut err,
- &static_candidates,
+ static_candidates,
rcvr_ty,
source,
item_name,
@@ -605,16 +613,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
if let (ty::Param(_), ty::PredicateKind::Clause(ty::ClauseKind::Trait(p))) =
(self_ty.kind(), parent_pred.kind().skip_binder())
{
- let hir = self.tcx.hir();
let node = match p.trait_ref.self_ty().kind() {
ty::Param(_) => {
// Account for `fn` items like in `issue-35677.rs` to
// suggest restricting its type params.
- Some(hir.get_by_def_id(self.body_id))
- }
- ty::Adt(def, _) => {
- def.did().as_local().map(|def_id| hir.get_by_def_id(def_id))
+ Some(self.tcx.hir_node_by_def_id(self.body_id))
}
+ ty::Adt(def, _) => def
+ .did()
+ .as_local()
+ .map(|def_id| self.tcx.hir_node_by_def_id(def_id)),
_ => None,
};
if let Some(hir::Node::Item(hir::Item { kind, .. })) = node
@@ -813,7 +821,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
span: item_span,
..
})) => {
- tcx.sess.delay_span_bug(
+ tcx.sess.span_delayed_bug(
*item_span,
"auto trait is invoked with no method error, but no error reported?",
);
@@ -969,7 +977,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
"the following trait bounds were not satisfied:\n{bound_list}"
));
}
- self.suggest_derive(&mut err, &unsatisfied_predicates);
+ self.suggest_derive(&mut err, unsatisfied_predicates);
unsatisfied_bounds = true;
}
@@ -1170,8 +1178,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
args.map(|args| args.len() + 1),
source,
no_match_data.out_of_scope_traits.clone(),
- &unsatisfied_predicates,
- &static_candidates,
+ unsatisfied_predicates,
+ static_candidates,
unsatisfied_bounds,
expected.only_has_type(self),
trait_missing_method,
@@ -1240,20 +1248,27 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}
}
// If an appropriate error source is not found, check method chain for possible candiates
- if unsatisfied_predicates.is_empty() && let Mode::MethodCall = mode && let SelfSource::MethodCall(mut source_expr) = source {
+ if unsatisfied_predicates.is_empty()
+ && let Mode::MethodCall = mode
+ && let SelfSource::MethodCall(mut source_expr) = source
+ {
let mut stack_methods = vec![];
while let hir::ExprKind::MethodCall(_path_segment, rcvr_expr, _args, method_span) =
- source_expr.kind
+ source_expr.kind
{
- // Pop the matching receiver, to align on it's notional span
- if let Some(prev_match) = stack_methods.pop() {
- err.span_label(method_span, format!("{item_kind} `{item_name}` is available on `{prev_match}`"));
+ // Pop the matching receiver, to align on it's notional span
+ if let Some(prev_match) = stack_methods.pop() {
+ err.span_label(
+ method_span,
+ format!("{item_kind} `{item_name}` is available on `{prev_match}`"),
+ );
}
let rcvr_ty = self.resolve_vars_if_possible(
self.typeck_results
.borrow()
.expr_ty_adjusted_opt(rcvr_expr)
- .unwrap_or(Ty::new_misc_error(self.tcx)),);
+ .unwrap_or(Ty::new_misc_error(self.tcx)),
+ );
for _matched_method in self.probe_for_name_many(
Mode::MethodCall,
@@ -1262,15 +1277,19 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
IsSuggestion(true),
rcvr_ty,
source_expr.hir_id,
- ProbeScope::TraitsInScope,) {
- // found a match, push to stack
- stack_methods.push(rcvr_ty);
+ ProbeScope::TraitsInScope,
+ ) {
+ // found a match, push to stack
+ stack_methods.push(rcvr_ty);
}
source_expr = rcvr_expr;
}
// If there is a match at the start of the chain, add a label for it too!
if let Some(prev_match) = stack_methods.pop() {
- err.span_label(source_expr.span, format!("{item_kind} `{item_name}` is available on `{prev_match}`"));
+ err.span_label(
+ source_expr.span,
+ format!("{item_kind} `{item_name}` is available on `{prev_match}`"),
+ );
}
}
self.note_derefed_ty_has_method(&mut err, source, rcvr_ty, item_name, expected);
@@ -1357,10 +1376,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
err,
self_source,
args,
- trait_ref.instantiate(
- self.tcx,
- self.fresh_args_for_item(sugg_span, impl_did)
- ).with_self_ty(self.tcx, rcvr_ty),
+ trait_ref
+ .instantiate(
+ self.tcx,
+ self.fresh_args_for_item(sugg_span, impl_did),
+ )
+ .with_self_ty(self.tcx, rcvr_ty),
idx,
sugg_span,
item,
@@ -1397,8 +1418,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
ty::TraitRef::new(
self.tcx,
trait_did,
- self.fresh_args_for_item(sugg_span, trait_did)
- ).with_self_ty(self.tcx, rcvr_ty),
+ self.fresh_args_for_item(sugg_span, trait_did),
+ )
+ .with_self_ty(self.tcx, rcvr_ty),
idx,
sugg_span,
item,
@@ -1409,7 +1431,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}
}
}
- if !suggs.is_empty() && let Some(span) = sugg_span {
+ if !suggs.is_empty()
+ && let Some(span) = sugg_span
+ {
+ suggs.sort();
err.span_suggestions(
span.with_hi(item_name.span.lo()),
"use fully-qualified syntax to disambiguate",
@@ -1438,7 +1463,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
.filter_map(|item| {
// Only assoc fns that return `Self`, `Option<Self>` or `Result<Self, _>`.
let ret_ty = self.tcx.fn_sig(item.def_id).skip_binder().output();
- let ret_ty = self.tcx.erase_late_bound_regions(ret_ty);
+ let ret_ty = self.tcx.instantiate_bound_regions_with_erased(ret_ty);
let ty::Adt(def, args) = ret_ty.kind() else {
return None;
};
@@ -1574,10 +1599,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
{
let sig = self.tcx.fn_sig(assoc.def_id).instantiate_identity();
sig.inputs().skip_binder().get(0).and_then(|first| {
- if first.peel_refs() == rcvr_ty.peel_refs() {
- None
- } else {
+ let impl_ty = self.tcx.type_of(*impl_did).instantiate_identity();
+ // if the type of first arg is the same as the current impl type, we should take the first arg into assoc function
+ if first.peel_refs() == impl_ty {
Some(first.ref_mutability().map_or("", |mutbl| mutbl.ref_prefix_str()))
+ } else {
+ None
}
})
} else {
@@ -1585,39 +1612,39 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
};
let mut applicability = Applicability::MachineApplicable;
let args = if let SelfSource::MethodCall(receiver) = source
- && let Some(args) = args
- {
- // The first arg is the same kind as the receiver
- let explicit_args = if first_arg.is_some() {
- std::iter::once(receiver).chain(args.iter()).collect::<Vec<_>>()
- } else {
- // There is no `Self` kind to infer the arguments from
- if has_unsuggestable_args {
- applicability = Applicability::HasPlaceholders;
- }
- args.iter().collect()
- };
- format!(
- "({}{})",
- first_arg.unwrap_or(""),
- explicit_args
- .iter()
- .map(|arg| self
- .tcx
- .sess
- .source_map()
- .span_to_snippet(arg.span)
- .unwrap_or_else(|_| {
- applicability = Applicability::HasPlaceholders;
- "_".to_owned()
- }))
- .collect::<Vec<_>>()
- .join(", "),
- )
+ && let Some(args) = args
+ {
+ // The first arg is the same kind as the receiver
+ let explicit_args = if first_arg.is_some() {
+ std::iter::once(receiver).chain(args.iter()).collect::<Vec<_>>()
} else {
- applicability = Applicability::HasPlaceholders;
- "(...)".to_owned()
+ // There is no `Self` kind to infer the arguments from
+ if has_unsuggestable_args {
+ applicability = Applicability::HasPlaceholders;
+ }
+ args.iter().collect()
};
+ format!(
+ "({}{})",
+ first_arg.unwrap_or(""),
+ explicit_args
+ .iter()
+ .map(|arg| self
+ .tcx
+ .sess
+ .source_map()
+ .span_to_snippet(arg.span)
+ .unwrap_or_else(|_| {
+ applicability = Applicability::HasPlaceholders;
+ "_".to_owned()
+ }))
+ .collect::<Vec<_>>()
+ .join(", "),
+ )
+ } else {
+ applicability = Applicability::HasPlaceholders;
+ "(...)".to_owned()
+ };
err.span_suggestion(
sugg_span,
"use associated function syntax instead",
@@ -1705,7 +1732,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
for (_, parent) in tcx.hir().parent_iter(expr.hir_id).take(5) {
if let Node::Expr(parent_expr) = parent {
let lang_item = match parent_expr.kind {
- ExprKind::Struct(ref qpath, _, _) => match **qpath {
+ ExprKind::Struct(qpath, _, _) => match *qpath {
QPath::LangItem(LangItem::Range, ..) => Some(LangItem::Range),
QPath::LangItem(LangItem::RangeTo, ..) => Some(LangItem::RangeTo),
QPath::LangItem(LangItem::RangeToInclusive, ..) => {
@@ -1713,7 +1740,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}
_ => None,
},
- ExprKind::Call(ref func, _) => match func.kind {
+ ExprKind::Call(func, _) => match func.kind {
// `..=` desugars into `::std::ops::RangeInclusive::new(...)`.
ExprKind::Path(QPath::LangItem(LangItem::RangeInclusiveNew, ..)) => {
Some(LangItem::RangeInclusiveStruct)
@@ -1732,7 +1759,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
eps.len() > 0 && eps.last().is_some_and(|ep| ep.span.contains(span))
}
// `..=` desugars into `::std::ops::RangeInclusive::new(...)`.
- hir::ExprKind::Call(ref func, ..) => func.span.contains(span),
+ hir::ExprKind::Call(func, ..) => func.span.contains(span),
_ => false,
};
@@ -1826,7 +1853,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
);
let concrete_type = if actual.is_integral() { "i32" } else { "f32" };
match expr.kind {
- ExprKind::Lit(ref lit) => {
+ ExprKind::Lit(lit) => {
// numeric literal
let snippet = tcx
.sess
@@ -1902,7 +1929,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
return;
};
let Some(mut diag) =
- self.tcx.sess.diagnostic().steal_diagnostic(seg1.ident.span, StashKey::CallAssocMethod)
+ self.tcx.sess.dcx().steal_diagnostic(seg1.ident.span, StashKey::CallAssocMethod)
else {
return;
};
@@ -1930,10 +1957,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}
let mut visitor = LetVisitor { result: None, ident_name: seg1.ident.name };
- visitor.visit_body(&body);
+ visitor.visit_body(body);
let parent = self.tcx.hir().parent_id(seg1.hir_id);
- if let Some(Node::Expr(call_expr)) = self.tcx.hir().find(parent)
+ if let Some(Node::Expr(call_expr)) = self.tcx.opt_hir_node(parent)
&& let Some(expr) = visitor.result
&& let Some(self_ty) = self.node_ty_opt(expr.hir_id)
{
@@ -1967,69 +1994,73 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
item_name: Ident,
return_type: Option<Ty<'tcx>>,
) {
- if let SelfSource::MethodCall(expr) = source
- && let mod_id = self.tcx.parent_module(expr.hir_id).to_def_id()
- && let Some((fields, args)) =
- self.get_field_candidates_considering_privacy(span, actual, mod_id)
- {
- let call_expr = self.tcx.hir().expect_expr(self.tcx.hir().parent_id(expr.hir_id));
+ if let SelfSource::MethodCall(expr) = source {
+ let mod_id = self.tcx.parent_module(expr.hir_id).to_def_id();
+ for (fields, args) in
+ self.get_field_candidates_considering_privacy(span, actual, mod_id, expr.hir_id)
+ {
+ let call_expr = self.tcx.hir().expect_expr(self.tcx.hir().parent_id(expr.hir_id));
- let lang_items = self.tcx.lang_items();
- let never_mention_traits = [
- lang_items.clone_trait(),
- lang_items.deref_trait(),
- lang_items.deref_mut_trait(),
- self.tcx.get_diagnostic_item(sym::AsRef),
- self.tcx.get_diagnostic_item(sym::AsMut),
- self.tcx.get_diagnostic_item(sym::Borrow),
- self.tcx.get_diagnostic_item(sym::BorrowMut),
- ];
- let candidate_fields: Vec<_> = fields
- .filter_map(|candidate_field| {
- self.check_for_nested_field_satisfying(
- span,
- &|_, field_ty| {
- self.lookup_probe_for_diagnostic(
- item_name,
- field_ty,
- call_expr,
- ProbeScope::TraitsInScope,
- return_type,
- )
- .is_ok_and(|pick| {
- !never_mention_traits
- .iter()
- .flatten()
- .any(|def_id| self.tcx.parent(pick.item.def_id) == *def_id)
- })
- },
- candidate_field,
- args,
- vec![],
- mod_id,
- )
- })
- .map(|field_path| {
- field_path
- .iter()
- .map(|id| id.name.to_ident_string())
- .collect::<Vec<String>>()
- .join(".")
- })
- .collect();
+ let lang_items = self.tcx.lang_items();
+ let never_mention_traits = [
+ lang_items.clone_trait(),
+ lang_items.deref_trait(),
+ lang_items.deref_mut_trait(),
+ self.tcx.get_diagnostic_item(sym::AsRef),
+ self.tcx.get_diagnostic_item(sym::AsMut),
+ self.tcx.get_diagnostic_item(sym::Borrow),
+ self.tcx.get_diagnostic_item(sym::BorrowMut),
+ ];
+ let mut candidate_fields: Vec<_> = fields
+ .into_iter()
+ .filter_map(|candidate_field| {
+ self.check_for_nested_field_satisfying(
+ span,
+ &|_, field_ty| {
+ self.lookup_probe_for_diagnostic(
+ item_name,
+ field_ty,
+ call_expr,
+ ProbeScope::TraitsInScope,
+ return_type,
+ )
+ .is_ok_and(|pick| {
+ !never_mention_traits
+ .iter()
+ .flatten()
+ .any(|def_id| self.tcx.parent(pick.item.def_id) == *def_id)
+ })
+ },
+ candidate_field,
+ args,
+ vec![],
+ mod_id,
+ expr.hir_id,
+ )
+ })
+ .map(|field_path| {
+ field_path
+ .iter()
+ .map(|id| id.name.to_ident_string())
+ .collect::<Vec<String>>()
+ .join(".")
+ })
+ .collect();
+ candidate_fields.sort();
- let len = candidate_fields.len();
- if len > 0 {
- err.span_suggestions(
- item_name.span.shrink_to_lo(),
- format!(
- "{} of the expressions' fields {} a method of the same name",
- if len > 1 { "some" } else { "one" },
- if len > 1 { "have" } else { "has" },
- ),
- candidate_fields.iter().map(|path| format!("{path}.")),
- Applicability::MaybeIncorrect,
- );
+ let len = candidate_fields.len();
+ if len > 0 {
+ err.span_suggestions(
+ item_name.span.shrink_to_lo(),
+ format!(
+ "{} of the expressions' fields {} a method of the same name",
+ if len > 1 { "some" } else { "one" },
+ if len > 1 { "have" } else { "has" },
+ ),
+ candidate_fields.iter().map(|path| format!("{path}.")),
+ Applicability::MaybeIncorrect,
+ );
+ }
}
}
}
@@ -2267,7 +2298,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
ty::Adt(def, _) if def.did().is_local() => {
spans.push_span_label(
self.tcx.def_span(def.did()),
- format!("must implement `{}`", pred.trait_ref.print_only_trait_path()),
+ format!("must implement `{}`", pred.trait_ref.print_trait_sugared()),
);
}
_ => {}
@@ -2278,7 +2309,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let msg = if preds.len() == 1 {
format!(
"an implementation of `{}` might be missing for `{}`",
- preds[0].trait_ref.print_only_trait_path(),
+ preds[0].trait_ref.print_trait_sugared(),
preds[0].self_ty()
)
} else {
@@ -2548,13 +2579,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
self.tcx.item_name(*trait_did),
)
});
+ let mut sugg: Vec<_> = path_strings.chain(glob_path_strings).collect();
+ sugg.sort();
- err.span_suggestions(
- span,
- msg,
- path_strings.chain(glob_path_strings),
- Applicability::MaybeIncorrect,
- );
+ err.span_suggestions(span, msg, sugg, Applicability::MaybeIncorrect);
}
fn suggest_valid_traits(
@@ -2849,11 +2877,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let id = item
.def_id
.as_local()
- .map(|def_id| self.tcx.hir().local_def_id_to_hir_id(def_id));
+ .map(|def_id| self.tcx.hir_node_by_def_id(def_id));
if let Some(hir::Node::TraitItem(hir::TraitItem {
kind: hir::TraitItemKind::Fn(fn_sig, method),
..
- })) = id.map(|id| self.tcx.hir().get(id))
+ })) = id
{
let self_first_arg = match method {
hir::TraitFn::Required([ident, ..]) => {
@@ -2939,11 +2967,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let type_param = generics.type_param(param, self.tcx);
let hir = self.tcx.hir();
if let Some(def_id) = type_param.def_id.as_local() {
- let id = hir.local_def_id_to_hir_id(def_id);
+ let id = self.tcx.local_def_id_to_hir_id(def_id);
// Get the `hir::Param` to verify whether it already has any bounds.
// We do this to avoid suggesting code that ends up as `T: FooBar`,
// instead we suggest `T: Foo + Bar` in that case.
- match hir.get(id) {
+ match self.tcx.hir_node(id) {
Node::GenericParam(param) => {
enum Introducer {
Plus,
@@ -3163,7 +3191,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}
let parent = self.tcx.hir().parent_id(expr.hir_id);
- if let Some(Node::Expr(call_expr)) = self.tcx.hir().find(parent)
+ if let Some(Node::Expr(call_expr)) = self.tcx.opt_hir_node(parent)
&& let hir::ExprKind::MethodCall(
hir::PathSegment { ident: method_name, .. },
self_expr,
@@ -3296,8 +3324,13 @@ fn print_disambiguation_help<'tcx>(
{
let def_kind_descr = tcx.def_kind_descr(item.kind.as_def_kind(), item.def_id);
let item_name = item.ident(tcx);
- let rcvr_ref = tcx.fn_sig(item.def_id).skip_binder().skip_binder().inputs()[0]
- .ref_mutability()
+ let rcvr_ref = tcx
+ .fn_sig(item.def_id)
+ .skip_binder()
+ .skip_binder()
+ .inputs()
+ .get(0)
+ .and_then(|ty| ty.ref_mutability())
.map_or("", |mutbl| mutbl.ref_prefix_str());
let args = format!(
"({}{})",
diff --git a/compiler/rustc_hir_typeck/src/op.rs b/compiler/rustc_hir_typeck/src/op.rs
index f40406c67..59b4b0032 100644
--- a/compiler/rustc_hir_typeck/src/op.rs
+++ b/compiler/rustc_hir_typeck/src/op.rs
@@ -4,7 +4,7 @@ use super::method::MethodCallee;
use super::{has_expected_num_generic_args, FnCtxt};
use crate::Expectation;
use rustc_ast as ast;
-use rustc_errors::{self, struct_span_err, Applicability, Diagnostic, DiagnosticBuilder};
+use rustc_errors::{struct_span_err, Applicability, Diagnostic, DiagnosticBuilder};
use rustc_hir as hir;
use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
use rustc_infer::traits::ObligationCauseCode;
@@ -291,7 +291,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
.push(autoref);
}
}
- self.write_method_call(expr.hir_id, method);
+ self.write_method_call_and_enforce_effects(expr.hir_id, expr.span, method);
method.sig.output()
}
@@ -781,7 +781,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
assert!(op.is_by_value());
match self.lookup_op_method(operand_ty, None, Op::Unary(op, ex.span), expected) {
Ok(method) => {
- self.write_method_call(ex.hir_id, method);
+ self.write_method_call_and_enforce_effects(ex.hir_id, ex.span, method);
method.sig.output()
}
Err(errors) => {
@@ -900,7 +900,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
) {
self.tcx
.sess
- .delay_span_bug(span, "operator didn't have the right number of generic args");
+ .span_delayed_bug(span, "operator didn't have the right number of generic args");
return Err(vec![]);
}
@@ -933,7 +933,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// This path may do some inference, so make sure we've really
// doomed compilation so as to not accidentally stabilize new
// inference or something here...
- self.tcx.sess.delay_span_bug(span, "this path really should be doomed...");
+ self.tcx.sess.span_delayed_bug(span, "this path really should be doomed...");
// Guide inference for the RHS expression if it's provided --
// this will allow us to better error reporting, at the expense
// of making some error messages a bit more specific.
diff --git a/compiler/rustc_hir_typeck/src/pat.rs b/compiler/rustc_hir_typeck/src/pat.rs
index b30f9b82f..56a420fab 100644
--- a/compiler/rustc_hir_typeck/src/pat.rs
+++ b/compiler/rustc_hir_typeck/src/pat.rs
@@ -178,6 +178,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let ty = match pat.kind {
PatKind::Wild => expected,
+ // FIXME(never_patterns): check the type is uninhabited. If that is not possible within
+ // typeck, do that in a later phase.
+ PatKind::Never => expected,
PatKind::Lit(lt) => self.check_pat_lit(pat.span, lt, expected, ti),
PatKind::Range(lhs, rhs, _) => self.check_pat_range(pat.span, lhs, rhs, expected, ti),
PatKind::Binding(ba, var_id, _, sub) => {
@@ -287,9 +290,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
| PatKind::Box(_)
| PatKind::Range(..)
| PatKind::Slice(..) => AdjustMode::Peel,
+ // A never pattern behaves somewhat like a literal or unit variant.
+ PatKind::Never => AdjustMode::Peel,
// String and byte-string literals result in types `&str` and `&[u8]` respectively.
// All other literals result in non-reference types.
- // As a result, we allow `if let 0 = &&0 {}` but not `if let "foo" = &&"foo {}`.
+ // As a result, we allow `if let 0 = &&0 {}` but not `if let "foo" = &&"foo" {}`.
//
// Call `resolve_vars_if_possible` here for inline const blocks.
PatKind::Lit(lt) => match self.resolve_vars_if_possible(self.check_expr(lt)).kind() {
@@ -715,7 +720,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
&& let PatKind::Binding(_, _, binding, ..) = inner.kind
{
let binding_parent_id = tcx.hir().parent_id(pat.hir_id);
- let binding_parent = tcx.hir().get(binding_parent_id);
+ let binding_parent = tcx.hir_node(binding_parent_id);
debug!(?inner, ?pat, ?binding_parent);
let mutability = match mutbl {
@@ -743,6 +748,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
| PatKind::Slice(..) => "binding",
PatKind::Wild
+ | PatKind::Never
| PatKind::Binding(..)
| PatKind::Path(..)
| PatKind::Box(..)
@@ -872,7 +878,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
self.demand_eqtype_pat(pat.span, expected, pat_ty, pat_info.top_info);
// Type-check subpatterns.
- if self.check_struct_pat_fields(pat_ty, &pat, variant, fields, has_rest_pat, pat_info) {
+ if self.check_struct_pat_fields(pat_ty, pat, variant, fields, has_rest_pat, pat_info) {
pat_ty
} else {
Ty::new_misc_error(self.tcx)
@@ -893,7 +899,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let (res, opt_ty, segments) = path_resolution;
match res {
Res::Err => {
- let e = tcx.sess.delay_span_bug(qpath.span(), "`Res::Err` but no error emitted");
+ let e = tcx.sess.span_delayed_bug(qpath.span(), "`Res::Err` but no error emitted");
self.set_tainted_by_errors(e);
return Ty::new_error(tcx, e);
}
@@ -935,7 +941,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
Some(hir::Node::Item(hir::Item {
kind: hir::ItemKind::Const(_, _, body_id),
..
- })) => match self.tcx.hir().get(body_id.hir_id) {
+ })) => match self.tcx.hir_node(body_id.hir_id) {
hir::Node::Expr(expr) => {
if hir::is_range_literal(expr) {
let span = self.tcx.hir().span(body_id.hir_id);
@@ -1062,7 +1068,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let (res, opt_ty, segments) =
self.resolve_ty_and_res_fully_qualified_call(qpath, pat.hir_id, pat.span, None);
if res == Res::Err {
- let e = tcx.sess.delay_span_bug(pat.span, "`Res::Err` but no error emitted");
+ let e = tcx.sess.span_delayed_bug(pat.span, "`Res::Err` but no error emitted");
self.set_tainted_by_errors(e);
on_error(e);
return Ty::new_error(tcx, e);
@@ -1078,7 +1084,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let variant = match res {
Res::Err => {
- let e = tcx.sess.delay_span_bug(pat.span, "`Res::Err` but no error emitted");
+ let e = tcx.sess.span_delayed_bug(pat.span, "`Res::Err` but no error emitted");
self.set_tainted_by_errors(e);
on_error(e);
return Ty::new_error(tcx, e);
@@ -1814,7 +1820,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
fn joined_uncovered_patterns(witnesses: &[&Ident]) -> String {
const LIMIT: usize = 3;
match witnesses {
- [] => bug!(),
+ [] => {
+ unreachable!(
+ "expected an uncovered pattern, otherwise why are we emitting an error?"
+ )
+ }
[witness] => format!("`{witness}`"),
[head @ .., tail] if head.len() < LIMIT => {
let head: Vec<_> = head.iter().map(<_>::to_string).collect();
@@ -1839,8 +1849,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
lint.note(format!(
"the pattern is of type `{ty}` and the `non_exhaustive_omitted_patterns` attribute was found",
));
-
- lint
});
}
diff --git a/compiler/rustc_hir_typeck/src/place_op.rs b/compiler/rustc_hir_typeck/src/place_op.rs
index 406434e09..79e41ef92 100644
--- a/compiler/rustc_hir_typeck/src/place_op.rs
+++ b/compiler/rustc_hir_typeck/src/place_op.rs
@@ -38,7 +38,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
span_bug!(expr.span, "input to deref is not a ref?");
}
let ty = self.make_overloaded_place_return_type(method).ty;
- self.write_method_call(expr.hir_id, method);
+ self.write_method_call_and_enforce_effects(expr.hir_id, expr.span, method);
Some(ty)
}
@@ -179,7 +179,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}
self.apply_adjustments(base_expr, adjustments);
- self.write_method_call(expr.hir_id, method);
+ self.write_method_call_and_enforce_effects(expr.hir_id, expr.span, method);
return Some((input_ty, self.make_overloaded_place_return_type(method).ty));
}
@@ -283,9 +283,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// Gather up expressions we want to munge.
let mut exprs = vec![expr];
- while let hir::ExprKind::Field(ref expr, _)
- | hir::ExprKind::Index(ref expr, _, _)
- | hir::ExprKind::Unary(hir::UnOp::Deref, ref expr) = exprs.last().unwrap().kind
+ while let hir::ExprKind::Field(expr, _)
+ | hir::ExprKind::Index(expr, _, _)
+ | hir::ExprKind::Unary(hir::UnOp::Deref, expr) = exprs.last().unwrap().kind
{
exprs.push(expr);
}
@@ -404,7 +404,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
None => return,
};
debug!("convert_place_op_to_mutable: method={:?}", method);
- self.write_method_call(expr.hir_id, method);
+ self.write_method_call_and_enforce_effects(expr.hir_id, expr.span, method);
let ty::Ref(region, _, hir::Mutability::Mut) = method.sig.inputs()[0].kind() else {
span_bug!(expr.span, "input to mutable place op is not a mut ref?");
diff --git a/compiler/rustc_hir_typeck/src/rvalue_scopes.rs b/compiler/rustc_hir_typeck/src/rvalue_scopes.rs
index 04d841023..b9b3ed53d 100644
--- a/compiler/rustc_hir_typeck/src/rvalue_scopes.rs
+++ b/compiler/rustc_hir_typeck/src/rvalue_scopes.rs
@@ -69,12 +69,13 @@ pub fn resolve_rvalue_scopes<'a, 'tcx>(
def_id: DefId,
) -> RvalueScopes {
let tcx = &fcx.tcx;
- let hir_map = tcx.hir();
let mut rvalue_scopes = RvalueScopes::new();
debug!("start resolving rvalue scopes, def_id={def_id:?}");
debug!("rvalue_scope: rvalue_candidates={:?}", scope_tree.rvalue_candidates);
for (&hir_id, candidate) in &scope_tree.rvalue_candidates {
- let Some(Node::Expr(expr)) = hir_map.find(hir_id) else { bug!("hir node does not exist") };
+ let Some(Node::Expr(expr)) = tcx.opt_hir_node(hir_id) else {
+ bug!("hir node does not exist")
+ };
record_rvalue_scope(&mut rvalue_scopes, expr, candidate);
}
rvalue_scopes
diff --git a/compiler/rustc_hir_typeck/src/upvar.rs b/compiler/rustc_hir_typeck/src/upvar.rs
index 17b81acd5..726ee02d7 100644
--- a/compiler/rustc_hir_typeck/src/upvar.rs
+++ b/compiler/rustc_hir_typeck/src/upvar.rs
@@ -221,7 +221,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
self.compute_min_captures(closure_def_id, capture_information, span);
- let closure_hir_id = self.tcx.hir().local_def_id_to_hir_id(closure_def_id);
+ let closure_hir_id = self.tcx.local_def_id_to_hir_id(closure_def_id);
if should_do_rust_2021_incompatible_closure_captures_analysis(self.tcx, closure_hir_id) {
self.perform_2229_migration_analysis(closure_def_id, body_id, capture_clause, span);
@@ -261,7 +261,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// Unify the (as yet unbound) type variable in the closure
// args with the kind we inferred.
let closure_kind_ty = closure_args.as_closure().kind_ty();
- self.demand_eqtype(span, closure_kind.to_ty(self.tcx), closure_kind_ty);
+ self.demand_eqtype(
+ span,
+ Ty::from_closure_kind(self.tcx, closure_kind),
+ closure_kind_ty,
+ );
// If we have an origin, store it.
if let Some(mut origin) = origin {
@@ -315,11 +319,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let final_tupled_upvars_type = Ty::new_tup(self.tcx, &final_upvar_tys);
self.demand_suptype(span, args.tupled_upvars_ty(), final_tupled_upvars_type);
- let fake_reads = delegate
- .fake_reads
- .into_iter()
- .map(|(place, cause, hir_id)| (place, cause, hir_id))
- .collect();
+ let fake_reads = delegate.fake_reads;
+
self.typeck_results.borrow_mut().closure_fake_reads.insert(closure_def_id, fake_reads);
if self.tcx.sess.opts.unstable_opts.profile_closures {
@@ -679,53 +680,41 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// `tests/ui/closures/2229_closure_analysis/preserve_field_drop_order.rs`.
for (_, captures) in &mut root_var_min_capture_list {
captures.sort_by(|capture1, capture2| {
- for (p1, p2) in capture1.place.projections.iter().zip(&capture2.place.projections) {
+ fn is_field<'a>(p: &&Projection<'a>) -> bool {
+ match p.kind {
+ ProjectionKind::Field(_, _) => true,
+ ProjectionKind::Deref | ProjectionKind::OpaqueCast => false,
+ p @ (ProjectionKind::Subslice | ProjectionKind::Index) => {
+ bug!("ProjectionKind {:?} was unexpected", p)
+ }
+ }
+ }
+
+ // Need to sort only by Field projections, so filter away others.
+ // A previous implementation considered other projection types too
+ // but that caused ICE #118144
+ let capture1_field_projections = capture1.place.projections.iter().filter(is_field);
+ let capture2_field_projections = capture2.place.projections.iter().filter(is_field);
+
+ for (p1, p2) in capture1_field_projections.zip(capture2_field_projections) {
// We do not need to look at the `Projection.ty` fields here because at each
// step of the iteration, the projections will either be the same and therefore
// the types must be as well or the current projection will be different and
// we will return the result of comparing the field indexes.
match (p1.kind, p2.kind) {
- // Paths are the same, continue to next loop.
- (ProjectionKind::Deref, ProjectionKind::Deref) => {}
- (ProjectionKind::OpaqueCast, ProjectionKind::OpaqueCast) => {}
- (ProjectionKind::Field(i1, _), ProjectionKind::Field(i2, _))
- if i1 == i2 => {}
-
- // Fields are different, compare them.
(ProjectionKind::Field(i1, _), ProjectionKind::Field(i2, _)) => {
- return i1.cmp(&i2);
+ // Compare only if paths are different.
+ // Otherwise continue to the next iteration
+ if i1 != i2 {
+ return i1.cmp(&i2);
+ }
}
-
- // We should have either a pair of `Deref`s or a pair of `Field`s.
- // Anything else is a bug.
- (
- l @ (ProjectionKind::Deref | ProjectionKind::Field(..)),
- r @ (ProjectionKind::Deref | ProjectionKind::Field(..)),
- ) => bug!(
- "ProjectionKinds Deref and Field were mismatched: ({:?}, {:?})",
- l,
- r
- ),
- (
- l @ (ProjectionKind::Index
- | ProjectionKind::Subslice
- | ProjectionKind::Deref
- | ProjectionKind::OpaqueCast
- | ProjectionKind::Field(..)),
- r @ (ProjectionKind::Index
- | ProjectionKind::Subslice
- | ProjectionKind::Deref
- | ProjectionKind::OpaqueCast
- | ProjectionKind::Field(..)),
- ) => bug!(
- "ProjectionKinds Index or Subslice were unexpected: ({:?}, {:?})",
- l,
- r
- ),
+ // Given the filter above, this arm should never be hit
+ (l, r) => bug!("ProjectionKinds {:?} or {:?} were unexpected", l, r),
}
}
- self.tcx.sess.delay_span_bug(
+ self.tcx.sess.span_delayed_bug(
closure_span,
format!(
"two identical projections: ({:?}, {:?})",
@@ -763,7 +752,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let (migration_string, migrated_variables_concat) =
migration_suggestion_for_2229(self.tcx, &need_migrations);
- let closure_hir_id = self.tcx.hir().local_def_id_to_hir_id(closure_def_id);
+ let closure_hir_id = self.tcx.local_def_id_to_hir_id(closure_def_id);
let closure_head_span = self.tcx.def_span(closure_def_id);
self.tcx.struct_span_lint_hir(
lint::builtin::RUST_2021_INCOMPATIBLE_CLOSURE_CAPTURES,
@@ -853,7 +842,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// Looks like a macro fragment. Try to find the real block.
if let Some(hir::Node::Expr(&hir::Expr {
kind: hir::ExprKind::Block(block, ..), ..
- })) = self.tcx.hir().find(body_id.hir_id) {
+ })) = self.tcx.opt_hir_node(body_id.hir_id) {
// If the body is a block (with `{..}`), we use the span of that block.
// E.g. with a `|| $body` expanded from a `m!({ .. })`, we use `{ .. }`, and not `$body`.
// Since we know it's a block, we know we can insert the `let _ = ..` without
@@ -911,8 +900,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
Applicability::HasPlaceholders
);
}
-
- lint
},
);
}
@@ -1673,7 +1660,7 @@ fn apply_capture_kind_on_capture_ty<'tcx>(
fn drop_location_span(tcx: TyCtxt<'_>, hir_id: hir::HirId) -> Span {
let owner_id = tcx.hir().get_enclosing_scope(hir_id).unwrap();
- let owner_node = tcx.hir().get(owner_id);
+ let owner_node = tcx.hir_node(owner_id);
let owner_span = match owner_node {
hir::Node::Item(item) => match item.kind {
hir::ItemKind::Fn(_, _, owner_id) => tcx.hir().span(owner_id.hir_id),
diff --git a/compiler/rustc_hir_typeck/src/writeback.rs b/compiler/rustc_hir_typeck/src/writeback.rs
index 896aacc69..d0cf4575c 100644
--- a/compiler/rustc_hir_typeck/src/writeback.rs
+++ b/compiler/rustc_hir_typeck/src/writeback.rs
@@ -8,12 +8,16 @@ use rustc_errors::{ErrorGuaranteed, StashKey};
use rustc_hir as hir;
use rustc_hir::intravisit::{self, Visitor};
use rustc_infer::infer::error_reporting::TypeAnnotationNeeded::E0282;
+use rustc_middle::traits::ObligationCause;
use rustc_middle::ty::adjustment::{Adjust, Adjustment, PointerCoercion};
-use rustc_middle::ty::fold::{TypeFoldable, TypeFolder, TypeSuperFoldable};
+use rustc_middle::ty::fold::{TypeFoldable, TypeFolder};
use rustc_middle::ty::visit::TypeVisitableExt;
+use rustc_middle::ty::TypeSuperFoldable;
use rustc_middle::ty::{self, Ty, TyCtxt};
use rustc_span::symbol::sym;
use rustc_span::Span;
+use rustc_trait_selection::solve;
+use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt;
use std::mem;
@@ -47,7 +51,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// Type only exists for constants and statics, not functions.
match self.tcx.hir().body_owner_kind(item_def_id) {
hir::BodyOwnerKind::Const { .. } | hir::BodyOwnerKind::Static(_) => {
- let item_hir_id = self.tcx.hir().local_def_id_to_hir_id(item_def_id);
+ let item_hir_id = self.tcx.local_def_id_to_hir_id(item_def_id);
wbcx.visit_node_id(body.value.span, item_hir_id);
}
hir::BodyOwnerKind::Closure | hir::BodyOwnerKind::Fn => (),
@@ -218,7 +222,7 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
// When encountering `return [0][0]` outside of a `fn` body we can encounter a base
// that isn't in the type table. We assume more relevant errors have already been
// emitted, so we delay an ICE if none have. (#64638)
- self.tcx().sess.delay_span_bug(e.span, format!("bad base: `{base:?}`"));
+ self.tcx().sess.span_delayed_bug(e.span, format!("bad base: `{base:?}`"));
}
if let Some(base_ty) = base_ty
&& let ty::Ref(_, base_ty_inner, _) = *base_ty.kind()
@@ -311,7 +315,9 @@ impl<'cx, 'tcx> Visitor<'tcx> for WritebackCx<'cx, 'tcx> {
// Nothing to write back here
}
hir::GenericParamKind::Type { .. } | hir::GenericParamKind::Const { .. } => {
- self.tcx().sess.delay_span_bug(p.span, format!("unexpected generic param: {p:?}"));
+ self.tcx()
+ .sess
+ .span_delayed_bug(p.span, format!("unexpected generic param: {p:?}"));
}
}
}
@@ -382,7 +388,7 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
.to_sorted(hcx, false)
.into_iter()
.map(|(&closure_def_id, data)| {
- let closure_hir_id = self.tcx().hir().local_def_id_to_hir_id(closure_def_id);
+ let closure_hir_id = self.tcx().local_def_id_to_hir_id(closure_def_id);
let data = self.resolve(*data, &closure_hir_id);
(closure_def_id, data)
})
@@ -407,7 +413,7 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
.map(|captured_place| {
let locatable =
captured_place.info.path_expr_id.unwrap_or_else(|| {
- self.tcx().hir().local_def_id_to_hir_id(closure_def_id)
+ self.tcx().local_def_id_to_hir_id(closure_def_id)
});
self.resolve(captured_place.clone(), &locatable)
})
@@ -433,7 +439,7 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
let resolved_fake_reads = fake_reads
.iter()
.map(|(place, cause, hir_id)| {
- let locatable = self.tcx().hir().local_def_id_to_hir_id(closure_def_id);
+ let locatable = self.tcx().local_def_id_to_hir_id(closure_def_id);
let resolved_fake_read = self.resolve(place.clone(), &locatable);
(resolved_fake_read, *cause, *hir_id)
})
@@ -498,8 +504,8 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
if !errors_buffer.is_empty() {
errors_buffer.sort_by_key(|diag| diag.span.primary_span());
- for mut diag in errors_buffer {
- self.tcx().sess.diagnostic().emit_diagnostic(&mut diag);
+ for diag in errors_buffer {
+ self.tcx().sess.dcx().emit_diagnostic(diag);
}
}
}
@@ -693,24 +699,22 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
}
}
- fn resolve<T>(&mut self, x: T, span: &dyn Locatable) -> T
+ fn resolve<T>(&mut self, value: T, span: &dyn Locatable) -> T
where
T: TypeFoldable<TyCtxt<'tcx>>,
{
- let mut resolver = Resolver::new(self.fcx, span, self.body);
- let x = x.fold_with(&mut resolver);
- if cfg!(debug_assertions) && x.has_infer() {
- span_bug!(span.to_span(self.fcx.tcx), "writeback: `{:?}` has inference variables", x);
- }
+ let value = self.fcx.resolve_vars_if_possible(value);
+ let value = value.fold_with(&mut Resolver::new(self.fcx, span, self.body));
+ assert!(!value.has_infer());
// We may have introduced e.g. `ty::Error`, if inference failed, make sure
// to mark the `TypeckResults` as tainted in that case, so that downstream
// users of the typeck results don't produce extra errors, or worse, ICEs.
- if let Some(e) = resolver.replaced_with_error {
- self.typeck_results.tainted_by_errors = Some(e);
+ if let Err(guar) = value.error_reported() {
+ self.typeck_results.tainted_by_errors = Some(guar);
}
- x
+ value
}
}
@@ -730,15 +734,13 @@ impl Locatable for hir::HirId {
}
}
-/// The Resolver. This is the type folding engine that detects
-/// unresolved types and so forth.
struct Resolver<'cx, 'tcx> {
fcx: &'cx FnCtxt<'cx, 'tcx>,
span: &'cx dyn Locatable,
body: &'tcx hir::Body<'tcx>,
-
- /// Set to `Some` if any `Ty` or `ty::Const` had to be replaced with an `Error`.
- replaced_with_error: Option<ErrorGuaranteed>,
+ /// Whether we should normalize using the new solver, disabled
+ /// both when using the old solver and when resolving predicates.
+ should_normalize: bool,
}
impl<'cx, 'tcx> Resolver<'cx, 'tcx> {
@@ -747,7 +749,7 @@ impl<'cx, 'tcx> Resolver<'cx, 'tcx> {
span: &'cx dyn Locatable,
body: &'tcx hir::Body<'tcx>,
) -> Resolver<'cx, 'tcx> {
- Resolver { fcx, span, body, replaced_with_error: None }
+ Resolver { fcx, span, body, should_normalize: fcx.next_trait_solver() }
}
fn report_error(&self, p: impl Into<ty::GenericArg<'tcx>>) -> ErrorGuaranteed {
@@ -766,26 +768,42 @@ impl<'cx, 'tcx> Resolver<'cx, 'tcx> {
.emit(),
}
}
-}
-struct EraseEarlyRegions<'tcx> {
- tcx: TyCtxt<'tcx>,
-}
+ fn handle_term<T>(
+ &mut self,
+ value: T,
+ outer_exclusive_binder: impl FnOnce(T) -> ty::DebruijnIndex,
+ new_err: impl Fn(TyCtxt<'tcx>, ErrorGuaranteed) -> T,
+ ) -> T
+ where
+ T: Into<ty::GenericArg<'tcx>> + TypeSuperFoldable<TyCtxt<'tcx>> + Copy,
+ {
+ let tcx = self.fcx.tcx;
+ // We must deeply normalize in the new solver, since later lints
+ // expect that types that show up in the typeck are fully
+ // normalized.
+ let value = if self.should_normalize {
+ let body_id = tcx.hir().body_owner_def_id(self.body.id());
+ let cause = ObligationCause::misc(self.span.to_span(tcx), body_id);
+ let at = self.fcx.at(&cause, self.fcx.param_env);
+ let universes = vec![None; outer_exclusive_binder(value).as_usize()];
+ solve::deeply_normalize_with_skipped_universes(at, value, universes).unwrap_or_else(
+ |errors| {
+ let guar = self.fcx.err_ctxt().report_fulfillment_errors(errors);
+ new_err(tcx, guar)
+ },
+ )
+ } else {
+ value
+ };
-impl<'tcx> TypeFolder<TyCtxt<'tcx>> for EraseEarlyRegions<'tcx> {
- fn interner(&self) -> TyCtxt<'tcx> {
- self.tcx
- }
- fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
- if ty.has_type_flags(ty::TypeFlags::HAS_FREE_REGIONS) {
- ty.super_fold_with(self)
+ if value.has_non_region_infer() {
+ let guar = self.report_error(value);
+ new_err(tcx, guar)
} else {
- ty
+ tcx.fold_regions(value, |_, _| tcx.lifetimes.re_erased)
}
}
- fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
- if r.is_late_bound() { r } else { self.tcx.lifetimes.re_erased }
- }
}
impl<'cx, 'tcx> TypeFolder<TyCtxt<'tcx>> for Resolver<'cx, 'tcx> {
@@ -793,56 +811,28 @@ impl<'cx, 'tcx> TypeFolder<TyCtxt<'tcx>> for Resolver<'cx, 'tcx> {
self.fcx.tcx
}
- fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
- match self.fcx.fully_resolve(t) {
- Ok(t) if self.fcx.next_trait_solver() => {
- // We must normalize erasing regions here, since later lints
- // expect that types that show up in the typeck are fully
- // normalized.
- if let Ok(t) = self.fcx.tcx.try_normalize_erasing_regions(self.fcx.param_env, t) {
- t
- } else {
- EraseEarlyRegions { tcx: self.fcx.tcx }.fold_ty(t)
- }
- }
- Ok(t) => {
- // Do not anonymize late-bound regions
- // (e.g. keep `for<'a>` named `for<'a>`).
- // This allows NLL to generate error messages that
- // refer to the higher-ranked lifetime names written by the user.
- EraseEarlyRegions { tcx: self.fcx.tcx }.fold_ty(t)
- }
- Err(_) => {
- debug!("Resolver::fold_ty: input type `{:?}` not fully resolvable", t);
- let e = self.report_error(t);
- self.replaced_with_error = Some(e);
- Ty::new_error(self.fcx.tcx, e)
- }
- }
- }
-
fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
- debug_assert!(!r.is_late_bound(), "Should not be resolving bound region.");
+ debug_assert!(!r.is_bound(), "Should not be resolving bound region.");
self.fcx.tcx.lifetimes.re_erased
}
+ fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
+ self.handle_term(ty, Ty::outer_exclusive_binder, Ty::new_error)
+ }
+
fn fold_const(&mut self, ct: ty::Const<'tcx>) -> ty::Const<'tcx> {
- match self.fcx.fully_resolve(ct) {
- Ok(ct) => self.fcx.tcx.erase_regions(ct),
- Err(_) => {
- debug!("Resolver::fold_const: input const `{:?}` not fully resolvable", ct);
- let e = self.report_error(ct);
- self.replaced_with_error = Some(e);
- ty::Const::new_error(self.fcx.tcx, e, ct.ty())
- }
- }
+ self.handle_term(ct, ty::Const::outer_exclusive_binder, |tcx, guar| {
+ ty::Const::new_error(tcx, guar, ct.ty())
+ })
}
-}
-///////////////////////////////////////////////////////////////////////////
-// During type check, we store promises with the result of trait
-// lookup rather than the actual results (because the results are not
-// necessarily available immediately). These routines unwind the
-// promises. It is expected that we will have already reported any
-// errors that may be encountered, so if the promises store an error,
-// a dummy result is returned.
+ fn fold_predicate(&mut self, predicate: ty::Predicate<'tcx>) -> ty::Predicate<'tcx> {
+ // Do not normalize predicates in the new solver. The new solver is
+ // supposed to handle unnormalized predicates and incorrectly normalizing
+ // them can be unsound, e.g. for `WellFormed` predicates.
+ let prev = mem::replace(&mut self.should_normalize, false);
+ let predicate = predicate.super_fold_with(self);
+ self.should_normalize = prev;
+ predicate
+ }
+}