Skip to content

Commit 47a8fce

Browse files
committed
Auto merge of #108670 - cuviper:beta-next, r=cuviper
[beta] stage0 bump and backports - Bump stage0 to stable - Revert to using `RtlGenRandom` as a fallback #108060 - Fix `VecDeque::shrink_to` and add tests. #108475 - Fix `VecDeque::append` capacity overflow for ZSTs #108462 - Clippy: Fix array-size-threshold config deserialization error #108673 / rust-lang/rust-clippy#10423 - Yeet point_at_expr_source_of_inferred_type for now #108703 r? `@ghost`
2 parents 453d6d2 + be90b53 commit 47a8fce

25 files changed

+499
-799
lines changed

compiler/rustc_hir_typeck/src/demand.rs

+3-221
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,21 @@
11
use crate::FnCtxt;
22
use rustc_ast::util::parser::PREC_POSTFIX;
3-
use rustc_data_structures::fx::FxHashMap;
43
use rustc_errors::MultiSpan;
54
use rustc_errors::{Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed};
65
use rustc_hir as hir;
76
use rustc_hir::def::CtorKind;
8-
use rustc_hir::intravisit::Visitor;
97
use rustc_hir::lang_items::LangItem;
108
use rustc_hir::{is_range_literal, Node};
119
use rustc_infer::infer::InferOk;
1210
use rustc_middle::lint::in_external_macro;
1311
use rustc_middle::middle::stability::EvalResult;
1412
use rustc_middle::ty::adjustment::AllowTwoPhase;
1513
use rustc_middle::ty::error::{ExpectedFound, TypeError};
16-
use rustc_middle::ty::fold::{BottomUpFolder, TypeFolder};
17-
use rustc_middle::ty::print::{with_forced_trimmed_paths, with_no_trimmed_paths};
18-
use rustc_middle::ty::relate::TypeRelation;
19-
use rustc_middle::ty::{self, Article, AssocItem, Ty, TypeAndMut, TypeVisitable};
14+
use rustc_middle::ty::print::with_no_trimmed_paths;
15+
use rustc_middle::ty::{self, Article, AssocItem, Ty, TypeAndMut};
2016
use rustc_span::symbol::{sym, Symbol};
2117
use rustc_span::{BytePos, Span};
2218
use rustc_trait_selection::infer::InferCtxtExt as _;
23-
use rustc_trait_selection::traits::error_reporting::method_chain::CollectAllMismatches;
2419
use rustc_trait_selection::traits::ObligationCause;
2520

2621
use super::method::probe;
@@ -45,7 +40,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
4540
self.annotate_alternative_method_deref(err, expr, error);
4641

4742
// Use `||` to give these suggestions a precedence
48-
let suggested = self.suggest_missing_parentheses(err, expr)
43+
let _ = self.suggest_missing_parentheses(err, expr)
4944
|| self.suggest_remove_last_method_call(err, expr, expected)
5045
|| self.suggest_associated_const(err, expr, expected)
5146
|| self.suggest_deref_ref_or_into(err, expr, expected, expr_ty, expected_ty_expr)
@@ -60,9 +55,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
6055
|| self.suggest_clone_for_ref(err, expr, expr_ty, expected)
6156
|| self.suggest_into(err, expr, expr_ty, expected)
6257
|| self.suggest_floating_point_literal(err, expr, expected);
63-
if !suggested {
64-
self.point_at_expr_source_of_inferred_type(err, expr, expr_ty, expected);
65-
}
6658
}
6759

6860
pub fn emit_coerce_suggestions(
@@ -216,216 +208,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
216208
(expected, Some(err))
217209
}
218210

219-
pub fn point_at_expr_source_of_inferred_type(
220-
&self,
221-
err: &mut Diagnostic,
222-
expr: &hir::Expr<'_>,
223-
found: Ty<'tcx>,
224-
expected: Ty<'tcx>,
225-
) -> bool {
226-
let map = self.tcx.hir();
227-
228-
let hir::ExprKind::Path(hir::QPath::Resolved(None, p)) = expr.kind else { return false; };
229-
let [hir::PathSegment { ident, args: None, .. }] = p.segments else { return false; };
230-
let hir::def::Res::Local(hir_id) = p.res else { return false; };
231-
let Some(hir::Node::Pat(pat)) = map.find(hir_id) else { return false; };
232-
let Some(hir::Node::Local(hir::Local {
233-
ty: None,
234-
init: Some(init),
235-
..
236-
})) = map.find_parent(pat.hir_id) else { return false; };
237-
let Some(ty) = self.node_ty_opt(init.hir_id) else { return false; };
238-
if ty.is_closure() || init.span.overlaps(expr.span) || pat.span.from_expansion() {
239-
return false;
240-
}
241-
242-
// Locate all the usages of the relevant binding.
243-
struct FindExprs<'hir> {
244-
hir_id: hir::HirId,
245-
uses: Vec<&'hir hir::Expr<'hir>>,
246-
}
247-
impl<'v> Visitor<'v> for FindExprs<'v> {
248-
fn visit_expr(&mut self, ex: &'v hir::Expr<'v>) {
249-
if let hir::ExprKind::Path(hir::QPath::Resolved(None, path)) = ex.kind
250-
&& let hir::def::Res::Local(hir_id) = path.res
251-
&& hir_id == self.hir_id
252-
{
253-
self.uses.push(ex);
254-
}
255-
hir::intravisit::walk_expr(self, ex);
256-
}
257-
}
258-
259-
let mut expr_finder = FindExprs { hir_id, uses: vec![] };
260-
let id = map.get_parent_item(hir_id);
261-
let hir_id: hir::HirId = id.into();
262-
263-
let Some(node) = map.find(hir_id) else { return false; };
264-
let Some(body_id) = node.body_id() else { return false; };
265-
let body = map.body(body_id);
266-
expr_finder.visit_expr(body.value);
267-
// Hack to make equality checks on types with inference variables and regions useful.
268-
let mut eraser = BottomUpFolder {
269-
tcx: self.tcx,
270-
lt_op: |_| self.tcx.lifetimes.re_erased,
271-
ct_op: |c| c,
272-
ty_op: |t| match *t.kind() {
273-
ty::Infer(ty::TyVar(vid)) => self.tcx.mk_ty_infer(ty::TyVar(self.root_var(vid))),
274-
ty::Infer(ty::IntVar(_)) => {
275-
self.tcx.mk_ty_infer(ty::IntVar(ty::IntVid { index: 0 }))
276-
}
277-
ty::Infer(ty::FloatVar(_)) => {
278-
self.tcx.mk_ty_infer(ty::FloatVar(ty::FloatVid { index: 0 }))
279-
}
280-
_ => t,
281-
},
282-
};
283-
let mut prev = eraser.fold_ty(ty);
284-
let mut prev_span = None;
285-
286-
for binding in expr_finder.uses {
287-
// In every expression where the binding is referenced, we will look at that
288-
// expression's type and see if it is where the incorrect found type was fully
289-
// "materialized" and point at it. We will also try to provide a suggestion there.
290-
if let Some(hir::Node::Expr(expr)
291-
| hir::Node::Stmt(hir::Stmt {
292-
kind: hir::StmtKind::Expr(expr) | hir::StmtKind::Semi(expr),
293-
..
294-
})) = &map.find_parent(binding.hir_id)
295-
&& let hir::ExprKind::MethodCall(segment, rcvr, args, _span) = expr.kind
296-
&& rcvr.hir_id == binding.hir_id
297-
&& let Some(def_id) = self.typeck_results.borrow().type_dependent_def_id(expr.hir_id)
298-
{
299-
// We special case methods, because they can influence inference through the
300-
// call's arguments and we can provide a more explicit span.
301-
let sig = self.tcx.fn_sig(def_id);
302-
let def_self_ty = sig.input(0).skip_binder();
303-
let rcvr_ty = self.node_ty(rcvr.hir_id);
304-
// Get the evaluated type *after* calling the method call, so that the influence
305-
// of the arguments can be reflected in the receiver type. The receiver
306-
// expression has the type *before* theis analysis is done.
307-
let ty = match self.lookup_probe_for_diagnostic(
308-
segment.ident,
309-
rcvr_ty,
310-
expr,
311-
probe::ProbeScope::TraitsInScope,
312-
None,
313-
) {
314-
Ok(pick) => pick.self_ty,
315-
Err(_) => rcvr_ty,
316-
};
317-
// Remove one layer of references to account for `&mut self` and
318-
// `&self`, so that we can compare it against the binding.
319-
let (ty, def_self_ty) = match (ty.kind(), def_self_ty.kind()) {
320-
(ty::Ref(_, ty, a), ty::Ref(_, self_ty, b)) if a == b => (*ty, *self_ty),
321-
_ => (ty, def_self_ty),
322-
};
323-
let mut param_args = FxHashMap::default();
324-
let mut param_expected = FxHashMap::default();
325-
let mut param_found = FxHashMap::default();
326-
if self.can_eq(self.param_env, ty, found).is_ok() {
327-
// We only point at the first place where the found type was inferred.
328-
for (i, param_ty) in sig.inputs().skip_binder().iter().skip(1).enumerate() {
329-
if def_self_ty.contains(*param_ty) && let ty::Param(_) = param_ty.kind() {
330-
// We found an argument that references a type parameter in `Self`,
331-
// so we assume that this is the argument that caused the found
332-
// type, which we know already because of `can_eq` above was first
333-
// inferred in this method call.
334-
let arg = &args[i];
335-
let arg_ty = self.node_ty(arg.hir_id);
336-
err.span_label(
337-
arg.span,
338-
&format!(
339-
"this is of type `{arg_ty}`, which causes `{ident}` to be \
340-
inferred as `{ty}`",
341-
),
342-
);
343-
param_args.insert(param_ty, (arg, arg_ty));
344-
}
345-
}
346-
}
347-
348-
// Here we find, for a type param `T`, the type that `T` is in the current
349-
// method call *and* in the original expected type. That way, we can see if we
350-
// can give any structured suggestion for the function argument.
351-
let mut c = CollectAllMismatches {
352-
infcx: &self.infcx,
353-
param_env: self.param_env,
354-
errors: vec![],
355-
};
356-
let _ = c.relate(def_self_ty, ty);
357-
for error in c.errors {
358-
if let TypeError::Sorts(error) = error {
359-
param_found.insert(error.expected, error.found);
360-
}
361-
}
362-
c.errors = vec![];
363-
let _ = c.relate(def_self_ty, expected);
364-
for error in c.errors {
365-
if let TypeError::Sorts(error) = error {
366-
param_expected.insert(error.expected, error.found);
367-
}
368-
}
369-
for (param, (arg, arg_ty)) in param_args.iter() {
370-
let Some(expected) = param_expected.get(param) else { continue; };
371-
let Some(found) = param_found.get(param) else { continue; };
372-
if self.can_eq(self.param_env, *arg_ty, *found).is_err() { continue; }
373-
self.emit_coerce_suggestions(err, arg, *found, *expected, None, None);
374-
}
375-
376-
let ty = eraser.fold_ty(ty);
377-
if ty.references_error() {
378-
break;
379-
}
380-
if ty != prev
381-
&& param_args.is_empty()
382-
&& self.can_eq(self.param_env, ty, found).is_ok()
383-
{
384-
// We only point at the first place where the found type was inferred.
385-
err.span_label(
386-
segment.ident.span,
387-
with_forced_trimmed_paths!(format!(
388-
"here the type of `{ident}` is inferred to be `{ty}`",
389-
)),
390-
);
391-
break;
392-
} else if !param_args.is_empty() {
393-
break;
394-
}
395-
prev = ty;
396-
} else {
397-
let ty = eraser.fold_ty(self.node_ty(binding.hir_id));
398-
if ty.references_error() {
399-
break;
400-
}
401-
if ty != prev
402-
&& let Some(span) = prev_span
403-
&& self.can_eq(self.param_env, ty, found).is_ok()
404-
{
405-
// We only point at the first place where the found type was inferred.
406-
// We use the *previous* span because if the type is known *here* it means
407-
// it was *evaluated earlier*. We don't do this for method calls because we
408-
// evaluate the method's self type eagerly, but not in any other case.
409-
err.span_label(
410-
span,
411-
with_forced_trimmed_paths!(format!(
412-
"here the type of `{ident}` is inferred to be `{ty}`",
413-
)),
414-
);
415-
break;
416-
}
417-
prev = ty;
418-
}
419-
if binding.hir_id == expr.hir_id {
420-
// Do not look at expressions that come after the expression we were originally
421-
// evaluating and had a type error.
422-
break;
423-
}
424-
prev_span = Some(binding.span);
425-
}
426-
true
427-
}
428-
429211
fn annotate_expected_due_to_let_ty(
430212
&self,
431213
err: &mut Diagnostic,

compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs

-12
Original file line numberDiff line numberDiff line change
@@ -798,18 +798,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
798798
full_call_span,
799799
format!("arguments to this {} are incorrect", call_name),
800800
);
801-
if let (Some(callee_ty), hir::ExprKind::MethodCall(_, rcvr, _, _)) =
802-
(callee_ty, &call_expr.kind)
803-
{
804-
// Type that would have accepted this argument if it hadn't been inferred earlier.
805-
// FIXME: We leave an inference variable for now, but it'd be nice to get a more
806-
// specific type to increase the accuracy of the diagnostic.
807-
let expected = self.infcx.next_ty_var(TypeVariableOrigin {
808-
kind: TypeVariableOriginKind::MiscVariable,
809-
span: full_call_span,
810-
});
811-
self.point_at_expr_source_of_inferred_type(&mut err, rcvr, expected, callee_ty);
812-
}
813801
// Call out where the function is defined
814802
self.label_fn_like(
815803
&mut err,

0 commit comments

Comments
 (0)