about summary refs log tree commit diff
diff options
context:
space:
mode:
authorEduard-Mihai Burtescu <edy.burt@gmail.com>2020-03-27 10:56:02 +0200
committerEduard-Mihai Burtescu <edy.burt@gmail.com>2020-04-14 19:06:52 +0300
commit2bbc33aaf049bd14d862333a2914bc78b4bd4f24 (patch)
treefc58cf44e80f807cb3effec2d8cd8639a6cfd83a
parentba72b15666b2491415aec703a02c2364fe5e2790 (diff)
downloadrust-2bbc33aaf049bd14d862333a2914bc78b4bd4f24.tar.gz
rust-2bbc33aaf049bd14d862333a2914bc78b4bd4f24.zip
typeck: track any errors injected during writeback and taint tables appropriately.
-rw-r--r--src/librustc_typeck/check/writeback.rs20
-rw-r--r--src/test/ui/issues/issue-66706.rs13
-rw-r--r--src/test/ui/issues/issue-66706.stderr43
3 files changed, 70 insertions, 6 deletions
diff --git a/src/librustc_typeck/check/writeback.rs b/src/librustc_typeck/check/writeback.rs
index 146fc04bc27..f9100300e3a 100644
--- a/src/librustc_typeck/check/writeback.rs
+++ b/src/librustc_typeck/check/writeback.rs
@@ -75,7 +75,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         wbcx.tables.upvar_list =
             mem::replace(&mut self.tables.borrow_mut().upvar_list, Default::default());
 
-        wbcx.tables.tainted_by_errors = self.is_tainted_by_errors();
+        wbcx.tables.tainted_by_errors |= self.is_tainted_by_errors();
 
         debug!("writeback: tables for {:?} are {:#?}", item_def_id, wbcx.tables);
 
@@ -578,14 +578,21 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
         }
     }
 
-    fn resolve<T>(&self, x: &T, span: &dyn Locatable) -> T
+    fn resolve<T>(&mut self, x: &T, span: &dyn Locatable) -> T
     where
         T: TypeFoldable<'tcx>,
     {
-        let x = x.fold_with(&mut Resolver::new(self.fcx, span, self.body));
+        let mut resolver = Resolver::new(self.fcx, span, self.body);
+        let x = x.fold_with(&mut resolver);
         if cfg!(debug_assertions) && x.needs_infer() {
             span_bug!(span.to_span(self.fcx.tcx), "writeback: `{:?}` has inference variables", x);
         }
+
+        // We may have introduced e.g. `ty::Error`, if inference failed, make sure
+        // to mark the `TypeckTables` as tainted in that case, so that downstream
+        // users of the tables don't produce extra errors, or worse, ICEs.
+        self.tables.tainted_by_errors |= resolver.replaced_with_error;
+
         x
     }
 }
@@ -613,6 +620,9 @@ struct Resolver<'cx, 'tcx> {
     infcx: &'cx InferCtxt<'cx, 'tcx>,
     span: &'cx dyn Locatable,
     body: &'tcx hir::Body<'tcx>,
+
+    /// Set to `true` if any `Ty` or `ty::Const` had to be replaced with an `Error`.
+    replaced_with_error: bool,
 }
 
 impl<'cx, 'tcx> Resolver<'cx, 'tcx> {
@@ -621,7 +631,7 @@ impl<'cx, 'tcx> Resolver<'cx, 'tcx> {
         span: &'cx dyn Locatable,
         body: &'tcx hir::Body<'tcx>,
     ) -> Resolver<'cx, 'tcx> {
-        Resolver { tcx: fcx.tcx, infcx: fcx, span, body }
+        Resolver { tcx: fcx.tcx, infcx: fcx, span, body, replaced_with_error: false }
     }
 
     fn report_error(&self, t: Ty<'tcx>) {
@@ -644,6 +654,7 @@ impl<'cx, 'tcx> TypeFolder<'tcx> for Resolver<'cx, 'tcx> {
             Err(_) => {
                 debug!("Resolver::fold_ty: input type `{:?}` not fully resolvable", t);
                 self.report_error(t);
+                self.replaced_with_error = true;
                 self.tcx().types.err
             }
         }
@@ -661,6 +672,7 @@ impl<'cx, 'tcx> TypeFolder<'tcx> for Resolver<'cx, 'tcx> {
                 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.replaced_with_error = true;
                 self.tcx().consts.err
             }
         }
diff --git a/src/test/ui/issues/issue-66706.rs b/src/test/ui/issues/issue-66706.rs
index 5e64f63d533..02305191f6e 100644
--- a/src/test/ui/issues/issue-66706.rs
+++ b/src/test/ui/issues/issue-66706.rs
@@ -10,4 +10,17 @@ fn b() {
     //~^ ERROR expected identifier, found reserved identifier `_`
 }
 
+fn c() {
+    [0; [|&_: _ &_| {}; 0 ].len()]
+    //~^ ERROR expected `,`, found `&`
+    //~| ERROR mismatched types
+}
+
+fn d() {
+    [0; match [|f @ &ref _| () ] {} ]
+    //~^ ERROR expected identifier, found reserved identifier `_`
+    //~| ERROR `match` is not allowed in a `const`
+    //~| ERROR mismatched types
+}
+
 fn main() {}
diff --git a/src/test/ui/issues/issue-66706.stderr b/src/test/ui/issues/issue-66706.stderr
index 6d290bccc7d..ea461cc5d03 100644
--- a/src/test/ui/issues/issue-66706.stderr
+++ b/src/test/ui/issues/issue-66706.stderr
@@ -12,6 +12,29 @@ error: expected identifier, found reserved identifier `_`
 LL |     [0; [|f @ &ref _| {} ; 0 ].len() ];
    |                    ^ expected identifier, found reserved identifier
 
+error: expected `,`, found `&`
+  --> $DIR/issue-66706.rs:14:17
+   |
+LL |     [0; [|&_: _ &_| {}; 0 ].len()]
+   |                -^ expected `,`
+   |                |
+   |                help: missing `,`
+
+error: expected identifier, found reserved identifier `_`
+  --> $DIR/issue-66706.rs:20:26
+   |
+LL |     [0; match [|f @ &ref _| () ] {} ]
+   |                          ^ expected identifier, found reserved identifier
+
+error[E0658]: `match` is not allowed in a `const`
+  --> $DIR/issue-66706.rs:20:9
+   |
+LL |     [0; match [|f @ &ref _| () ] {} ]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #49146 <https://github.com/rust-lang/rust/issues/49146> for more information
+   = help: add `#![feature(const_if_match)]` to the crate attributes to enable
+
 error[E0282]: type annotations needed
   --> $DIR/issue-66706.rs:2:11
    |
@@ -26,7 +49,23 @@ LL | fn a() {
 LL |     [0; [|_: _ &_| ()].len()]
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^ expected `()`, found array `[{integer}; _]`
 
-error: aborting due to 4 previous errors
+error[E0308]: mismatched types
+  --> $DIR/issue-66706.rs:14:5
+   |
+LL | fn c() {
+   |        - help: try adding a return type: `-> [{integer}; _]`
+LL |     [0; [|&_: _ &_| {}; 0 ].len()]
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `()`, found array `[{integer}; _]`
+
+error[E0308]: mismatched types
+  --> $DIR/issue-66706.rs:20:5
+   |
+LL | fn d() {
+   |        - help: try adding a return type: `-> [{integer}; _]`
+LL |     [0; match [|f @ &ref _| () ] {} ]
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `()`, found array `[{integer}; _]`
+
+error: aborting due to 9 previous errors
 
-Some errors have detailed explanations: E0282, E0308.
+Some errors have detailed explanations: E0282, E0308, E0658.
 For more information about an error, try `rustc --explain E0282`.