]> git.lizzy.rs Git - rust.git/commitdiff
correctly handle uninferred consts
authorBastian Kauschke <bastian_kauschke@hotmail.de>
Sat, 9 May 2020 22:01:23 +0000 (00:01 +0200)
committerBastian Kauschke <bastian_kauschke@hotmail.de>
Mon, 18 May 2020 18:36:18 +0000 (20:36 +0200)
src/librustc_infer/infer/error_reporting/need_type_info.rs
src/librustc_typeck/check/writeback.rs
src/test/ui/const-generics/uninferred-consts.rs [new file with mode: 0644]
src/test/ui/const-generics/uninferred-consts.stderr [new file with mode: 0644]

index 0141ba8273775aa1b20b8ecdb155d400ca24dcad..dfc7177921d316fc8d50666c53cfa0cfc6f97245 100644 (file)
@@ -172,8 +172,19 @@ fn closure_args(fn_sig: &ty::PolyFnSig<'_>) -> String {
 }
 
 pub enum TypeAnnotationNeeded {
+    /// ```compile_fail,E0282
+    /// let x = "hello".chars().rev().collect();
+    /// ```
     E0282,
+    /// An implementation cannot be chosen unambiguously because of lack of information.
+    /// ```compile_fail,E0283
+    /// let _ = Default::default();
+    /// ```
     E0283,
+    /// ```compile_fail,E0284
+    /// let mut d: u64 = 2;
+    /// d = d % 1u32.into();
+    /// ```
     E0284,
 }
 
@@ -261,7 +272,7 @@ pub fn need_type_info_err(
             printer.name_resolver = Some(Box::new(&getter));
             let _ = if let ty::FnDef(..) = ty.kind {
                 // We don't want the regular output for `fn`s because it includes its path in
-                // invalid pseduo-syntax, we want the `fn`-pointer output instead.
+                // invalid pseudo-syntax, we want the `fn`-pointer output instead.
                 ty.fn_sig(self.tcx).print(printer)
             } else {
                 ty.print(printer)
@@ -518,6 +529,36 @@ pub fn need_type_info_err(
         err
     }
 
+    // FIXME(const_generics): We should either try and merge this with `need_type_info_err`
+    // or improve the errors created here.
+    //
+    // Unlike for type inference variables, we don't yet store the origin of const inference variables.
+    // This is needed for to get a more relevant error span.
+    pub fn need_type_info_err_const(
+        &self,
+        body_id: Option<hir::BodyId>,
+        span: Span,
+        ct: &'tcx ty::Const<'tcx>,
+        error_code: TypeAnnotationNeeded,
+    ) -> DiagnosticBuilder<'tcx> {
+        let mut local_visitor = FindHirNodeVisitor::new(&self, ct.into(), span);
+        if let Some(body_id) = body_id {
+            let expr = self.tcx.hir().expect_expr(body_id.hir_id);
+            local_visitor.visit_expr(expr);
+        }
+
+        let error_code = error_code.into();
+        let mut err = self.tcx.sess.struct_span_err_with_code(
+            local_visitor.target_span,
+            &format!("type annotations needed"),
+            error_code,
+        );
+
+        err.note("unable to infer the value of a const parameter");
+
+        err
+    }
+
     /// If the `FnSig` for the method call can be found and type arguments are identified as
     /// needed, suggest annotating the call, otherwise point out the resulting type of the call.
     fn annotate_method_call(
index c5bf151bc1e11083ff42ba0e7293ee9052792a84..154ca391aa5fdcd02d9b2627e70f1e432aaf749c 100644 (file)
@@ -647,13 +647,26 @@ fn new(
         Resolver { tcx: fcx.tcx, infcx: fcx, span, body, replaced_with_error: false }
     }
 
-    fn report_error(&self, t: Ty<'tcx>) {
+    fn report_type_error(&self, t: Ty<'tcx>) {
         if !self.tcx.sess.has_errors() {
             self.infcx
                 .need_type_info_err(Some(self.body.id()), self.span.to_span(self.tcx), t, E0282)
                 .emit();
         }
     }
+
+    fn report_const_error(&self, c: &'tcx ty::Const<'tcx>) {
+        if !self.tcx.sess.has_errors() {
+            self.infcx
+                .need_type_info_err_const(
+                    Some(self.body.id()),
+                    self.span.to_span(self.tcx),
+                    c,
+                    E0282,
+                )
+                .emit();
+        }
+    }
 }
 
 impl<'cx, 'tcx> TypeFolder<'tcx> for Resolver<'cx, 'tcx> {
@@ -666,7 +679,7 @@ fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
             Ok(t) => self.infcx.tcx.erase_regions(&t),
             Err(_) => {
                 debug!("Resolver::fold_ty: input type `{:?}` not fully resolvable", t);
-                self.report_error(t);
+                self.report_type_error(t);
                 self.replaced_with_error = true;
                 self.tcx().types.err
             }
@@ -683,8 +696,7 @@ fn fold_const(&mut self, ct: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tcx> {
             Ok(ct) => self.infcx.tcx.erase_regions(&ct),
             Err(_) => {
                 debug!("Resolver::fold_const: input const `{:?}` not fully resolvable", ct);
-                // FIXME: we'd like to use `self.report_error`, but it doesn't yet
-                // accept a &'tcx ty::Const.
+                self.report_const_error(ct);
                 self.replaced_with_error = true;
                 self.tcx().mk_const(ty::Const { val: ty::ConstKind::Error, ty: ct.ty })
             }
diff --git a/src/test/ui/const-generics/uninferred-consts.rs b/src/test/ui/const-generics/uninferred-consts.rs
new file mode 100644 (file)
index 0000000..3b2bb49
--- /dev/null
@@ -0,0 +1,12 @@
+#![feature(const_generics)]
+//~^ WARN the feature `const_generics` is incomplete
+
+// taken from https://github.com/rust-lang/rust/issues/70507#issuecomment-615268893
+struct Foo;
+impl Foo {
+    fn foo<const N: usize>(self) {}
+}
+fn main() {
+    Foo.foo();
+    //~^ ERROR type annotations needed
+}
diff --git a/src/test/ui/const-generics/uninferred-consts.stderr b/src/test/ui/const-generics/uninferred-consts.stderr
new file mode 100644 (file)
index 0000000..a362008
--- /dev/null
@@ -0,0 +1,20 @@
+warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/uninferred-consts.rs:1:12
+   |
+LL | #![feature(const_generics)]
+   |            ^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+   = note: see issue #44580 <https://github.com/rust-lang/rust/issues/44580> for more information
+
+error[E0282]: type annotations needed
+  --> $DIR/uninferred-consts.rs:10:5
+   |
+LL |     Foo.foo();
+   |     ^^^^^^^^^
+   |
+   = note: unable to infer the value of a const parameter
+
+error: aborting due to previous error; 1 warning emitted
+
+For more information about this error, try `rustc --explain E0282`.