diff --git a/src/librustc_typeck/check/writeback.rs b/src/librustc_typeck/check/writeback.rs index 146fc04bc27c..f9100300e3ad 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(&self, x: &T, span: &dyn Locatable) -> T + fn resolve(&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 5e64f63d5339..02305191f6eb 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 6d290bccc7d0..ea461cc5d03f 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 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}; _]` -Some errors have detailed explanations: E0282, E0308. +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, E0658. For more information about an error, try `rustc --explain E0282`.