about summary refs log tree commit diff
diff options
context:
space:
mode:
authorEsteban Kuber <esteban@kuber.com.ar>2021-09-14 10:52:36 +0000
committerEsteban Kuber <esteban@kuber.com.ar>2021-09-16 12:12:28 +0000
commit4951e3ad9ecc653bd2097c6a80e2e1c841edec66 (patch)
treedf518e51a2dccf8d172a8bd56a48102edcac9bf8
parent1d8290568506e5d85422f23ab73ce79519201995 (diff)
downloadrust-4951e3ad9ecc653bd2097c6a80e2e1c841edec66.tar.gz
rust-4951e3ad9ecc653bd2097c6a80e2e1c841edec66.zip
Point at argument when evaluating `Path`'s bounds
When evaluating an `ExprKind::Call`, we first have to `check_expr` on it's
callee. When this one is a `ExprKind::Path`, we had to evaluate the bounds
introduced for its arguments, but by the time we evaluated them we no
longer had access to the argument spans. Now we special case this so
that we can point at the right place on unsatisfied bounds. This also
allows the E0277 deduplication to kick in correctly, so we now emit
fewer errors.
-rw-r--r--compiler/rustc_typeck/src/check/callee.rs11
-rw-r--r--compiler/rustc_typeck/src/check/expr.rs28
-rw-r--r--src/test/ui/associated-types/associated-types-path-2.rs2
-rw-r--r--src/test/ui/associated-types/associated-types-path-2.stderr18
-rw-r--r--src/test/ui/feature-gates/feature-gate-unsized_fn_params.stderr4
-rw-r--r--src/test/ui/issues/issue-17651.rs1
-rw-r--r--src/test/ui/issues/issue-17651.stderr12
-rw-r--r--src/test/ui/issues/issue-30355.stderr4
-rw-r--r--src/test/ui/suggestions/issue-84973-blacklist.rs1
-rw-r--r--src/test/ui/suggestions/issue-84973-blacklist.stderr14
10 files changed, 43 insertions, 52 deletions
diff --git a/compiler/rustc_typeck/src/check/callee.rs b/compiler/rustc_typeck/src/check/callee.rs
index d1015510859..1cc06b8c2e5 100644
--- a/compiler/rustc_typeck/src/check/callee.rs
+++ b/compiler/rustc_typeck/src/check/callee.rs
@@ -72,7 +72,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         arg_exprs: &'tcx [hir::Expr<'tcx>],
         expected: Expectation<'tcx>,
     ) -> Ty<'tcx> {
-        let original_callee_ty = self.check_expr(callee_expr);
+        let original_callee_ty = match &callee_expr.kind {
+            hir::ExprKind::Path(hir::QPath::Resolved(..) | hir::QPath::TypeRelative(..)) => self
+                .check_expr_with_expectation_and_args(
+                    callee_expr,
+                    Expectation::NoExpectation,
+                    arg_exprs,
+                ),
+            _ => self.check_expr(callee_expr),
+        };
+
         let expr_ty = self.structurally_resolved_type(call_expr.span, original_callee_ty);
 
         let mut autoderef = self.autoderef(callee_expr.span, expr_ty);
diff --git a/compiler/rustc_typeck/src/check/expr.rs b/compiler/rustc_typeck/src/check/expr.rs
index f4e3c8e0d9f..917adf0e2b9 100644
--- a/compiler/rustc_typeck/src/check/expr.rs
+++ b/compiler/rustc_typeck/src/check/expr.rs
@@ -162,6 +162,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         expr: &'tcx hir::Expr<'tcx>,
         expected: Expectation<'tcx>,
     ) -> Ty<'tcx> {
+        self.check_expr_with_expectation_and_args(expr, expected, &[])
+    }
+
+    /// Same as `check_expr_with_expectation`, but allows us to pass in the arguments of a
+    /// `ExprKind::Call` when evaluating its callee when it is an `ExprKind::Path`.
+    pub(super) fn check_expr_with_expectation_and_args(
+        &self,
+        expr: &'tcx hir::Expr<'tcx>,
+        expected: Expectation<'tcx>,
+        args: &'tcx [hir::Expr<'tcx>],
+    ) -> Ty<'tcx> {
         if self.tcx().sess.verbose() {
             // make this code only run with -Zverbose because it is probably slow
             if let Ok(lint_str) = self.tcx.sess.source_map().span_to_snippet(expr.span) {
@@ -198,7 +209,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         let old_diverges = self.diverges.replace(Diverges::Maybe);
         let old_has_errors = self.has_errors.replace(false);
 
-        let ty = ensure_sufficient_stack(|| self.check_expr_kind(expr, expected));
+        let ty = ensure_sufficient_stack(|| match &expr.kind {
+            hir::ExprKind::Path(
+                qpath @ hir::QPath::Resolved(..) | qpath @ hir::QPath::TypeRelative(..),
+            ) => self.check_expr_path(qpath, expr, args),
+            _ => self.check_expr_kind(expr, expected),
+        });
 
         // Warn for non-block expressions with diverging children.
         match expr.kind {
@@ -261,7 +277,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             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::Path(ref qpath) => self.check_expr_path(qpath, expr, &[]),
             ExprKind::InlineAsm(asm) => self.check_expr_asm(asm),
             ExprKind::LlvmInlineAsm(asm) => {
                 for expr in asm.outputs_exprs.iter().chain(asm.inputs_exprs.iter()) {
@@ -481,10 +497,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         self.resolve_lang_item_path(lang_item, expr.span, expr.hir_id).1
     }
 
-    fn check_expr_path(
+    pub(crate) fn check_expr_path(
         &self,
         qpath: &'tcx hir::QPath<'tcx>,
         expr: &'tcx hir::Expr<'tcx>,
+        args: &'tcx [hir::Expr<'tcx>],
     ) -> Ty<'tcx> {
         let tcx = self.tcx;
         let (res, opt_ty, segs) =
@@ -517,16 +534,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     // We just want to check sizedness, so instead of introducing
                     // placeholder lifetimes with probing, we just replace higher lifetimes
                     // with fresh vars.
+                    let span = args.get(i).map(|a| a.span).unwrap_or(expr.span);
                     let input = self
                         .replace_bound_vars_with_fresh_vars(
-                            expr.span,
+                            span,
                             infer::LateBoundRegionConversionTime::FnCall,
                             fn_sig.input(i),
                         )
                         .0;
                     self.require_type_is_sized_deferred(
                         input,
-                        expr.span,
+                        span,
                         traits::SizedArgumentType(None),
                     );
                 }
diff --git a/src/test/ui/associated-types/associated-types-path-2.rs b/src/test/ui/associated-types/associated-types-path-2.rs
index c993e1d2720..912dedfdceb 100644
--- a/src/test/ui/associated-types/associated-types-path-2.rs
+++ b/src/test/ui/associated-types/associated-types-path-2.rs
@@ -28,13 +28,11 @@ pub fn f1_int_uint() {
 pub fn f1_uint_uint() {
     f1(2u32, 4u32);
     //~^ ERROR `u32: Foo` is not satisfied
-    //~| ERROR `u32: Foo` is not satisfied
 }
 
 pub fn f1_uint_int() {
     f1(2u32, 4i32);
     //~^ ERROR `u32: Foo` is not satisfied
-    //~| ERROR `u32: Foo` is not satisfied
 }
 
 pub fn f2_int() {
diff --git a/src/test/ui/associated-types/associated-types-path-2.stderr b/src/test/ui/associated-types/associated-types-path-2.stderr
index da4e13fcf92..15a5245d54d 100644
--- a/src/test/ui/associated-types/associated-types-path-2.stderr
+++ b/src/test/ui/associated-types/associated-types-path-2.stderr
@@ -24,13 +24,7 @@ LL | pub fn f1<T: Foo>(a: T, x: T::A) {}
    |              ^^^ required by this bound in `f1`
 
 error[E0277]: the trait bound `u32: Foo` is not satisfied
-  --> $DIR/associated-types-path-2.rs:29:5
-   |
-LL |     f1(2u32, 4u32);
-   |     ^^ the trait `Foo` is not implemented for `u32`
-
-error[E0277]: the trait bound `u32: Foo` is not satisfied
-  --> $DIR/associated-types-path-2.rs:35:14
+  --> $DIR/associated-types-path-2.rs:34:14
    |
 LL |     f1(2u32, 4i32);
    |     --       ^^^^ the trait `Foo` is not implemented for `u32`
@@ -43,14 +37,8 @@ note: required by a bound in `f1`
 LL | pub fn f1<T: Foo>(a: T, x: T::A) {}
    |              ^^^ required by this bound in `f1`
 
-error[E0277]: the trait bound `u32: Foo` is not satisfied
-  --> $DIR/associated-types-path-2.rs:35:5
-   |
-LL |     f1(2u32, 4i32);
-   |     ^^ the trait `Foo` is not implemented for `u32`
-
 error[E0308]: mismatched types
-  --> $DIR/associated-types-path-2.rs:41:18
+  --> $DIR/associated-types-path-2.rs:39:18
    |
 LL |     let _: i32 = f2(2i32);
    |            ---   ^^^^^^^^ expected `i32`, found `u32`
@@ -62,7 +50,7 @@ help: you can convert a `u32` to an `i32` and panic if the converted value doesn
 LL |     let _: i32 = f2(2i32).try_into().unwrap();
    |                          ++++++++++++++++++++
 
-error: aborting due to 6 previous errors
+error: aborting due to 4 previous errors
 
 Some errors have detailed explanations: E0277, E0308.
 For more information about an error, try `rustc --explain E0277`.
diff --git a/src/test/ui/feature-gates/feature-gate-unsized_fn_params.stderr b/src/test/ui/feature-gates/feature-gate-unsized_fn_params.stderr
index fbb18c8c490..0f7520ef7f8 100644
--- a/src/test/ui/feature-gates/feature-gate-unsized_fn_params.stderr
+++ b/src/test/ui/feature-gates/feature-gate-unsized_fn_params.stderr
@@ -12,10 +12,10 @@ LL | fn foo(x: &dyn Foo) {
    |           +
 
 error[E0277]: the size for values of type `(dyn Foo + 'static)` cannot be known at compilation time
-  --> $DIR/feature-gate-unsized_fn_params.rs:24:5
+  --> $DIR/feature-gate-unsized_fn_params.rs:24:9
    |
 LL |     foo(*x);
-   |     ^^^ doesn't have a size known at compile-time
+   |         ^^ doesn't have a size known at compile-time
    |
    = help: the trait `Sized` is not implemented for `(dyn Foo + 'static)`
    = note: all function arguments must have a statically known size
diff --git a/src/test/ui/issues/issue-17651.rs b/src/test/ui/issues/issue-17651.rs
index 08f352c11fa..7629a5a3be1 100644
--- a/src/test/ui/issues/issue-17651.rs
+++ b/src/test/ui/issues/issue-17651.rs
@@ -4,5 +4,4 @@
 fn main() {
     (|| Box::new(*(&[0][..])))();
     //~^ ERROR the size for values of type
-    //~| ERROR the size for values of type
 }
diff --git a/src/test/ui/issues/issue-17651.stderr b/src/test/ui/issues/issue-17651.stderr
index 2c88e22742b..214477f6c60 100644
--- a/src/test/ui/issues/issue-17651.stderr
+++ b/src/test/ui/issues/issue-17651.stderr
@@ -13,16 +13,6 @@ note: required by `Box::<T>::new`
 LL |     pub fn new(x: T) -> Self {
    |     ^^^^^^^^^^^^^^^^^^^^^^^^
 
-error[E0277]: the size for values of type `[{integer}]` cannot be known at compilation time
-  --> $DIR/issue-17651.rs:5:9
-   |
-LL |     (|| Box::new(*(&[0][..])))();
-   |         ^^^^^^^^ doesn't have a size known at compile-time
-   |
-   = help: the trait `Sized` is not implemented for `[{integer}]`
-   = note: all function arguments must have a statically known size
-   = help: unsized fn params are gated as an unstable feature
-
-error: aborting due to 2 previous errors
+error: aborting due to previous error
 
 For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/issues/issue-30355.stderr b/src/test/ui/issues/issue-30355.stderr
index 79f5db650d9..71bbdf5dec7 100644
--- a/src/test/ui/issues/issue-30355.stderr
+++ b/src/test/ui/issues/issue-30355.stderr
@@ -1,8 +1,8 @@
 error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
-  --> $DIR/issue-30355.rs:5:6
+  --> $DIR/issue-30355.rs:5:8
    |
 LL |     &X(*Y)
-   |      ^ doesn't have a size known at compile-time
+   |        ^^ doesn't have a size known at compile-time
    |
    = help: the trait `Sized` is not implemented for `[u8]`
    = note: all function arguments must have a statically known size
diff --git a/src/test/ui/suggestions/issue-84973-blacklist.rs b/src/test/ui/suggestions/issue-84973-blacklist.rs
index db954530b1b..6813b07a2ee 100644
--- a/src/test/ui/suggestions/issue-84973-blacklist.rs
+++ b/src/test/ui/suggestions/issue-84973-blacklist.rs
@@ -21,7 +21,6 @@ fn main() {
     let ref_cl: &dyn Fn() -> () = &cl;
     f_sized(*ref_cl);
     //~^ ERROR: the size for values of type `dyn Fn()` cannot be known at compilation time [E0277]
-    //~| ERROR: the size for values of type `dyn Fn()` cannot be known at compilation time [E0277]
 
     use std::rc::Rc;
     let rc = Rc::new(0);
diff --git a/src/test/ui/suggestions/issue-84973-blacklist.stderr b/src/test/ui/suggestions/issue-84973-blacklist.stderr
index 72d9f5d26a2..ae55c96702a 100644
--- a/src/test/ui/suggestions/issue-84973-blacklist.stderr
+++ b/src/test/ui/suggestions/issue-84973-blacklist.stderr
@@ -55,7 +55,7 @@ LL | fn f_sized<T: Sized>(t: T) {}
    |            ^ required by this bound in `f_sized`
 
 error[E0277]: `Rc<{integer}>` cannot be sent between threads safely
-  --> $DIR/issue-84973-blacklist.rs:28:12
+  --> $DIR/issue-84973-blacklist.rs:27:12
    |
 LL |     f_send(rc);
    |     ------ ^^ `Rc<{integer}>` cannot be sent between threads safely
@@ -69,16 +69,6 @@ note: required by a bound in `f_send`
 LL | fn f_send<T: Send>(t: T) {}
    |              ^^^^ required by this bound in `f_send`
 
-error[E0277]: the size for values of type `dyn Fn()` cannot be known at compilation time
-  --> $DIR/issue-84973-blacklist.rs:22:5
-   |
-LL |     f_sized(*ref_cl);
-   |     ^^^^^^^ doesn't have a size known at compile-time
-   |
-   = help: the trait `Sized` is not implemented for `dyn Fn()`
-   = note: all function arguments must have a statically known size
-   = help: unsized fn params are gated as an unstable feature
-
-error: aborting due to 6 previous errors
+error: aborting due to 5 previous errors
 
 For more information about this error, try `rustc --explain E0277`.