From bed3bb53d207c1bf92c26833e8d3d4280550f83e Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sat, 21 Jan 2023 21:54:49 +0000 Subject: [PATCH 1/2] Don't resolve type var roots in point_at_expr_source_of_inferred_type --- compiler/rustc_hir_typeck/src/demand.rs | 4 +++- tests/ui/typeck/bad-type-in-vec-push.rs | 14 ++++++++++++++ tests/ui/typeck/bad-type-in-vec-push.stderr | 20 ++++++++++++++++++++ 3 files changed, 37 insertions(+), 1 deletion(-) create mode 100644 tests/ui/typeck/bad-type-in-vec-push.rs create mode 100644 tests/ui/typeck/bad-type-in-vec-push.stderr diff --git a/compiler/rustc_hir_typeck/src/demand.rs b/compiler/rustc_hir_typeck/src/demand.rs index bd1626dff7951..d8cca55a8f892 100644 --- a/compiler/rustc_hir_typeck/src/demand.rs +++ b/compiler/rustc_hir_typeck/src/demand.rs @@ -270,7 +270,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { lt_op: |_| self.tcx.lifetimes.re_erased, ct_op: |c| c, ty_op: |t| match *t.kind() { - ty::Infer(ty::TyVar(vid)) => self.tcx.mk_ty_infer(ty::TyVar(self.root_var(vid))), + ty::Infer(ty::TyVar(_)) => self.tcx.mk_ty_var(ty::TyVid::from_u32(0)), ty::Infer(ty::IntVar(_)) => { self.tcx.mk_ty_infer(ty::IntVar(ty::IntVid { index: 0 })) } @@ -333,6 +333,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // inferred in this method call. let arg = &args[i]; let arg_ty = self.node_ty(arg.hir_id); + if !arg.span.overlaps(mismatch_span) { err.span_label( arg.span, &format!( @@ -340,6 +341,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { inferred as `{ty}`", ), ); + } param_args.insert(param_ty, (arg, arg_ty)); } } diff --git a/tests/ui/typeck/bad-type-in-vec-push.rs b/tests/ui/typeck/bad-type-in-vec-push.rs new file mode 100644 index 0000000000000..397e07dc17b42 --- /dev/null +++ b/tests/ui/typeck/bad-type-in-vec-push.rs @@ -0,0 +1,14 @@ +// The error message here still is pretty confusing. + +fn main() { + let mut result = vec![1]; + // The type of `result` is constrained to be `Vec<{integer}>` here. + // But the logic we use to find what expression constrains a type + // is not sophisticated enough to know this. + + let mut vector = Vec::new(); + vector.sort(); + result.push(vector); + //~^ ERROR mismatched types + // So it thinks that the type of `result` is constrained here. +} diff --git a/tests/ui/typeck/bad-type-in-vec-push.stderr b/tests/ui/typeck/bad-type-in-vec-push.stderr new file mode 100644 index 0000000000000..a24c49f0e9a3c --- /dev/null +++ b/tests/ui/typeck/bad-type-in-vec-push.stderr @@ -0,0 +1,20 @@ +error[E0308]: mismatched types + --> $DIR/bad-type-in-vec-push.rs:11:17 + | +LL | vector.sort(); + | ------ here the type of `vector` is inferred to be `Vec<_>` +LL | result.push(vector); + | ---- ^^^^^^ + | | | + | | expected integer, found struct `Vec` + | | this is of type `Vec<_>`, which causes `result` to be inferred as `Vec<{integer}>` + | arguments to this method are incorrect + | + = note: expected type `{integer}` + found struct `Vec<_>` +note: associated function defined here + --> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. From 9f933b5642c08e4241cbfed0f15270df552ce8e6 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sat, 21 Jan 2023 22:18:51 +0000 Subject: [PATCH 2/2] Hack to suppress bad labels in type mismatch inference deduction code --- compiler/rustc_hir_typeck/src/demand.rs | 36 ++++++++++--------- .../rustc_hir_typeck/src/fn_ctxt/checks.rs | 8 ++++- tests/ui/typeck/bad-type-in-vec-push.rs | 6 ++++ tests/ui/typeck/bad-type-in-vec-push.stderr | 19 +++++++--- 4 files changed, 47 insertions(+), 22 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/demand.rs b/compiler/rustc_hir_typeck/src/demand.rs index d8cca55a8f892..8e23ded3c09b4 100644 --- a/compiler/rustc_hir_typeck/src/demand.rs +++ b/compiler/rustc_hir_typeck/src/demand.rs @@ -61,7 +61,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { || self.suggest_into(err, expr, expr_ty, expected) || self.suggest_floating_point_literal(err, expr, expected); if !suggested { - self.point_at_expr_source_of_inferred_type(err, expr, expr_ty, expected); + self.point_at_expr_source_of_inferred_type(err, expr, expr_ty, expected, expr.span); } } @@ -222,6 +222,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { expr: &hir::Expr<'_>, found: Ty<'tcx>, expected: Ty<'tcx>, + mismatch_span: Span, ) -> bool { let map = self.tcx.hir(); @@ -281,7 +282,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { }, }; let mut prev = eraser.fold_ty(ty); - let mut prev_span = None; + let mut prev_span: Option = None; for binding in expr_finder.uses { // In every expression where the binding is referenced, we will look at that @@ -334,13 +335,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let arg = &args[i]; let arg_ty = self.node_ty(arg.hir_id); if !arg.span.overlaps(mismatch_span) { - err.span_label( - arg.span, - &format!( - "this is of type `{arg_ty}`, which causes `{ident}` to be \ - inferred as `{ty}`", - ), - ); + err.span_label( + arg.span, + &format!( + "this is of type `{arg_ty}`, which causes `{ident}` to be \ + inferred as `{ty}`", + ), + ); } param_args.insert(param_ty, (arg, arg_ty)); } @@ -384,12 +385,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { && self.can_eq(self.param_env, ty, found).is_ok() { // We only point at the first place where the found type was inferred. + if !segment.ident.span.overlaps(mismatch_span) { err.span_label( segment.ident.span, with_forced_trimmed_paths!(format!( "here the type of `{ident}` is inferred to be `{ty}`", )), - ); + );} break; } else if !param_args.is_empty() { break; @@ -408,12 +410,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // We use the *previous* span because if the type is known *here* it means // it was *evaluated earlier*. We don't do this for method calls because we // evaluate the method's self type eagerly, but not in any other case. - err.span_label( - span, - with_forced_trimmed_paths!(format!( - "here the type of `{ident}` is inferred to be `{ty}`", - )), - ); + if !span.overlaps(mismatch_span) { + err.span_label( + span, + with_forced_trimmed_paths!(format!( + "here the type of `{ident}` is inferred to be `{ty}`", + )), + ); + } break; } prev = ty; diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs index c9609e6943981..677c80297b912 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs @@ -808,7 +808,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { kind: TypeVariableOriginKind::MiscVariable, span: full_call_span, }); - self.point_at_expr_source_of_inferred_type(&mut err, rcvr, expected, callee_ty); + self.point_at_expr_source_of_inferred_type( + &mut err, + rcvr, + expected, + callee_ty, + provided_arg_span, + ); } // Call out where the function is defined self.label_fn_like( diff --git a/tests/ui/typeck/bad-type-in-vec-push.rs b/tests/ui/typeck/bad-type-in-vec-push.rs index 397e07dc17b42..a807f030cfce4 100644 --- a/tests/ui/typeck/bad-type-in-vec-push.rs +++ b/tests/ui/typeck/bad-type-in-vec-push.rs @@ -12,3 +12,9 @@ fn main() { //~^ ERROR mismatched types // So it thinks that the type of `result` is constrained here. } + +fn example2() { + let mut x = vec![1]; + x.push(""); + //~^ ERROR mismatched types +} diff --git a/tests/ui/typeck/bad-type-in-vec-push.stderr b/tests/ui/typeck/bad-type-in-vec-push.stderr index a24c49f0e9a3c..e4c99ec8e701f 100644 --- a/tests/ui/typeck/bad-type-in-vec-push.stderr +++ b/tests/ui/typeck/bad-type-in-vec-push.stderr @@ -4,10 +4,8 @@ error[E0308]: mismatched types LL | vector.sort(); | ------ here the type of `vector` is inferred to be `Vec<_>` LL | result.push(vector); - | ---- ^^^^^^ - | | | - | | expected integer, found struct `Vec` - | | this is of type `Vec<_>`, which causes `result` to be inferred as `Vec<{integer}>` + | ---- ^^^^^^ expected integer, found struct `Vec` + | | | arguments to this method are incorrect | = note: expected type `{integer}` @@ -15,6 +13,17 @@ LL | result.push(vector); note: associated function defined here --> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL -error: aborting due to previous error +error[E0308]: mismatched types + --> $DIR/bad-type-in-vec-push.rs:18:12 + | +LL | x.push(""); + | ---- ^^ expected integer, found `&str` + | | + | arguments to this method are incorrect + | +note: associated function defined here + --> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL + +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0308`.