From 0797712e295e6c67b39d57d0801de9d0c6f9b100 Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Mon, 23 Sep 2019 15:51:25 +0200 Subject: [PATCH 01/23] Stabilize Option::deref and Option::deref_mut The tracking issue https://github.com/rust-lang/rust/issues/50264 still has unresolved question for the corresponding `Result` methods. --- src/libcore/option.rs | 8 ++------ src/librustc/lib.rs | 1 - src/librustc_resolve/lib.rs | 1 - src/librustc_save_analysis/lib.rs | 1 - src/librustc_typeck/lib.rs | 1 - src/librustdoc/lib.rs | 1 - .../issue-50264-inner-deref-trait/option-as_deref.rs | 2 -- .../issue-50264-inner-deref-trait/option-as_deref.stderr | 2 +- .../issue-50264-inner-deref-trait/option-as_deref_mut.rs | 2 -- .../option-as_deref_mut.stderr | 2 +- 10 files changed, 4 insertions(+), 17 deletions(-) diff --git a/src/libcore/option.rs b/src/libcore/option.rs index 5569d99f8d81d..a80070d2a916c 100644 --- a/src/libcore/option.rs +++ b/src/libcore/option.rs @@ -1102,7 +1102,6 @@ impl Option { } } -#[unstable(feature = "inner_deref", reason = "newly added", issue = "50264")] impl Option { /// Converts from `Option` (or `&Option`) to `Option<&T::Target>`. /// @@ -1114,20 +1113,18 @@ impl Option { /// # Examples /// /// ``` - /// #![feature(inner_deref)] - /// /// let x: Option = Some("hey".to_owned()); /// assert_eq!(x.as_deref(), Some("hey")); /// /// let x: Option = None; /// assert_eq!(x.as_deref(), None); /// ``` + #[stable(feature = "option_deref", since = "1.40.0")] pub fn as_deref(&self) -> Option<&T::Target> { self.as_ref().map(|t| t.deref()) } } -#[unstable(feature = "inner_deref", reason = "newly added", issue = "50264")] impl Option { /// Converts from `Option` (or `&mut Option`) to `Option<&mut T::Target>`. /// @@ -1137,14 +1134,13 @@ impl Option { /// # Examples /// /// ``` - /// #![feature(inner_deref)] - /// /// let mut x: Option = Some("hey".to_owned()); /// assert_eq!(x.as_deref_mut().map(|x| { /// x.make_ascii_uppercase(); /// x /// }), Some("HEY".to_owned().as_mut_str())); /// ``` + #[stable(feature = "option_deref", since = "1.40.0")] pub fn as_deref_mut(&mut self) -> Option<&mut T::Target> { self.as_mut().map(|t| t.deref_mut()) } diff --git a/src/librustc/lib.rs b/src/librustc/lib.rs index 7a01ae6b6d9cc..fc397a87d403d 100644 --- a/src/librustc/lib.rs +++ b/src/librustc/lib.rs @@ -35,7 +35,6 @@ #![feature(const_transmute)] #![feature(core_intrinsics)] #![feature(drain_filter)] -#![feature(inner_deref)] #![cfg_attr(windows, feature(libc))] #![feature(never_type)] #![feature(exhaustive_patterns)] diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 74f68e5147126..d5fdf833bffb3 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -9,7 +9,6 @@ #![doc(html_root_url = "https://doc.rust-lang.org/nightly/")] -#![feature(inner_deref)] #![feature(crate_visibility_modifier)] #![feature(label_break_value)] #![feature(mem_take)] diff --git a/src/librustc_save_analysis/lib.rs b/src/librustc_save_analysis/lib.rs index 055ccf6c2c4f8..1e9916d5396ea 100644 --- a/src/librustc_save_analysis/lib.rs +++ b/src/librustc_save_analysis/lib.rs @@ -1,6 +1,5 @@ #![doc(html_root_url = "https://doc.rust-lang.org/nightly/")] #![feature(nll)] -#![feature(inner_deref)] #![recursion_limit="256"] diff --git a/src/librustc_typeck/lib.rs b/src/librustc_typeck/lib.rs index 959483e4439ff..beb188fb85a5f 100644 --- a/src/librustc_typeck/lib.rs +++ b/src/librustc_typeck/lib.rs @@ -67,7 +67,6 @@ This API is completely unstable and subject to change. #![feature(nll)] #![feature(slice_patterns)] #![feature(never_type)] -#![feature(inner_deref)] #![feature(mem_take)] #![recursion_limit="256"] diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index 0b9e717221f2d..e7a7efa935787 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -15,7 +15,6 @@ #![feature(crate_visibility_modifier)] #![feature(const_fn)] #![feature(drain_filter)] -#![feature(inner_deref)] #![feature(never_type)] #![feature(mem_take)] #![feature(unicode_internals)] diff --git a/src/test/ui/issues/issue-50264-inner-deref-trait/option-as_deref.rs b/src/test/ui/issues/issue-50264-inner-deref-trait/option-as_deref.rs index 67feb3ff6aec3..24c61425b8e29 100644 --- a/src/test/ui/issues/issue-50264-inner-deref-trait/option-as_deref.rs +++ b/src/test/ui/issues/issue-50264-inner-deref-trait/option-as_deref.rs @@ -1,5 +1,3 @@ -#![feature(inner_deref)] - fn main() { let _result = &Some(42).as_deref(); //~^ ERROR no method named `as_deref` found for type `std::option::Option<{integer}>` diff --git a/src/test/ui/issues/issue-50264-inner-deref-trait/option-as_deref.stderr b/src/test/ui/issues/issue-50264-inner-deref-trait/option-as_deref.stderr index 345f91437b827..0eb7bf0247565 100644 --- a/src/test/ui/issues/issue-50264-inner-deref-trait/option-as_deref.stderr +++ b/src/test/ui/issues/issue-50264-inner-deref-trait/option-as_deref.stderr @@ -1,5 +1,5 @@ error[E0599]: no method named `as_deref` found for type `std::option::Option<{integer}>` in the current scope - --> $DIR/option-as_deref.rs:4:29 + --> $DIR/option-as_deref.rs:2:29 | LL | let _result = &Some(42).as_deref(); | ^^^^^^^^ help: there is a method with a similar name: `as_ref` diff --git a/src/test/ui/issues/issue-50264-inner-deref-trait/option-as_deref_mut.rs b/src/test/ui/issues/issue-50264-inner-deref-trait/option-as_deref_mut.rs index 56aead8d0e00d..67ad73f584773 100644 --- a/src/test/ui/issues/issue-50264-inner-deref-trait/option-as_deref_mut.rs +++ b/src/test/ui/issues/issue-50264-inner-deref-trait/option-as_deref_mut.rs @@ -1,5 +1,3 @@ -#![feature(inner_deref)] - fn main() { let _result = &mut Some(42).as_deref_mut(); //~^ ERROR no method named `as_deref_mut` found for type `std::option::Option<{integer}>` diff --git a/src/test/ui/issues/issue-50264-inner-deref-trait/option-as_deref_mut.stderr b/src/test/ui/issues/issue-50264-inner-deref-trait/option-as_deref_mut.stderr index 29fd15fb396e9..845ddb52319c7 100644 --- a/src/test/ui/issues/issue-50264-inner-deref-trait/option-as_deref_mut.stderr +++ b/src/test/ui/issues/issue-50264-inner-deref-trait/option-as_deref_mut.stderr @@ -1,5 +1,5 @@ error[E0599]: no method named `as_deref_mut` found for type `std::option::Option<{integer}>` in the current scope - --> $DIR/option-as_deref_mut.rs:4:33 + --> $DIR/option-as_deref_mut.rs:2:33 | LL | let _result = &mut Some(42).as_deref_mut(); | ^^^^^^^^^^^^ method not found in `std::option::Option<{integer}>` From e8796cada9d962e30417a8f4f973f2c99727d0da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Wed, 2 Oct 2019 10:12:57 -0700 Subject: [PATCH 02/23] Do not ICE when dereferencing non-Copy raw pointer --- src/librustc_mir/borrow_check/mod.rs | 12 +++++++----- src/test/ui/issues/issue-52262.rs | 25 +++++++++++++++++++++++++ src/test/ui/issues/issue-52262.stderr | 9 +++++++++ 3 files changed, 41 insertions(+), 5 deletions(-) create mode 100644 src/test/ui/issues/issue-52262.rs create mode 100644 src/test/ui/issues/issue-52262.stderr diff --git a/src/librustc_mir/borrow_check/mod.rs b/src/librustc_mir/borrow_check/mod.rs index cfa211ad5afdb..75d4b56fdb7c2 100644 --- a/src/librustc_mir/borrow_check/mod.rs +++ b/src/librustc_mir/borrow_check/mod.rs @@ -1944,14 +1944,16 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { self.is_mutable(place.as_ref(), is_local_mutation_allowed), self.errors_buffer.is_empty() ) { - // rust-lang/rust#46908: In pure NLL mode this code path should - // be unreachable (and thus we signal an ICE in the else branch here). - span_bug!( - span, + // rust-lang/rust#46908: In pure NLL mode this code path should be + // unreachable, but we use `delay_span_bug` because we can hit this when + // dereferencing a non-Copy raw pointer *and* have `-Ztreat-err-as-bug` + // enabled. We don't want to ICE for that case, as other errors will have + // been emitted (#52262). + self.infcx.tcx.sess.delay_span_bug(span, &format!( "Accessing `{:?}` with the kind `{:?}` shouldn't be possible", place, kind, - ); + )); } return false; } diff --git a/src/test/ui/issues/issue-52262.rs b/src/test/ui/issues/issue-52262.rs new file mode 100644 index 0000000000000..2195b89555791 --- /dev/null +++ b/src/test/ui/issues/issue-52262.rs @@ -0,0 +1,25 @@ +// compile-flags:-Ztreat-err-as-bug=5 +#[derive(Debug)] +enum MyError { + NotFound { key: Vec }, + Err41, +} + +impl std::error::Error for MyError {} + +impl std::fmt::Display for MyError { + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + match self { + MyError::NotFound { key } => write!( + f, + "unknown error with code {}.", + String::from_utf8(*key).unwrap() + //~^ ERROR cannot move out of `*key` which is behind a shared reference + ), + MyError::Err41 => write!(f, "Sit by a lake"), + } + } +} +fn main() { + println!("Hello, world!"); +} diff --git a/src/test/ui/issues/issue-52262.stderr b/src/test/ui/issues/issue-52262.stderr new file mode 100644 index 0000000000000..7312976c80159 --- /dev/null +++ b/src/test/ui/issues/issue-52262.stderr @@ -0,0 +1,9 @@ +error[E0507]: cannot move out of `*key` which is behind a shared reference + --> $DIR/issue-52262.rs:16:35 + | +LL | String::from_utf8(*key).unwrap() + | ^^^^ move occurs because `*key` has type `std::vec::Vec`, which does not implement the `Copy` trait + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0507`. From 1222cc98ad8e37c69f89b0f411ac5b96416719f9 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Thu, 3 Oct 2019 12:31:06 -0400 Subject: [PATCH 03/23] permit asyncawait-ondeck to be added by anyone Still debating if this is the right approach --- triagebot.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/triagebot.toml b/triagebot.toml index f3509897bdf9c..53c0e52136e64 100644 --- a/triagebot.toml +++ b/triagebot.toml @@ -4,6 +4,7 @@ allow-unauthenticated = [ "requires-nightly", # I-* without I-nominated "I-compilemem", "I-compiletime", "I-crash", "I-hang", "I-ICE", "I-slow", + "AsyncAwait-OnDeck", ] [assign] From 1fcbd902a1d1145ed91fae1edb7a8c5798f68a14 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Thu, 3 Oct 2019 12:37:31 -0400 Subject: [PATCH 04/23] Update triagebot.toml Co-Authored-By: Pietro Albini --- triagebot.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/triagebot.toml b/triagebot.toml index 53c0e52136e64..d87c5b64c21c2 100644 --- a/triagebot.toml +++ b/triagebot.toml @@ -3,7 +3,7 @@ allow-unauthenticated = [ "C-*", "A-*", "E-*", "NLL-*", "O-*", "S-*", "T-*", "WG-*", "F-*", "requires-nightly", # I-* without I-nominated - "I-compilemem", "I-compiletime", "I-crash", "I-hang", "I-ICE", "I-slow", + "I-*", "!I-nominated", "AsyncAwait-OnDeck", ] From ed60cf2475cabd3d9ad1afdc03bd6952d99b744c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Sun, 29 Sep 2019 19:07:26 -0700 Subject: [PATCH 05/23] When encountering chained operators use heuristics to recover from bad turbofish --- src/libsyntax/parse/diagnostics.rs | 100 +++++++++++++++--- src/libsyntax/parse/parser/expr.rs | 4 +- src/test/ui/did_you_mean/issue-40396.stderr | 16 +-- .../require-parens-for-chained-comparison.rs | 5 +- ...quire-parens-for-chained-comparison.stderr | 23 ++-- 5 files changed, 121 insertions(+), 27 deletions(-) diff --git a/src/libsyntax/parse/diagnostics.rs b/src/libsyntax/parse/diagnostics.rs index e8d7b7663ed52..0e3d873b252e6 100644 --- a/src/libsyntax/parse/diagnostics.rs +++ b/src/libsyntax/parse/diagnostics.rs @@ -543,16 +543,25 @@ impl<'a> Parser<'a> { } /// Produces an error if comparison operators are chained (RFC #558). - /// We only need to check the LHS, not the RHS, because all comparison ops - /// have same precedence and are left-associative. - crate fn check_no_chained_comparison(&self, lhs: &Expr, outer_op: &AssocOp) -> PResult<'a, ()> { - debug_assert!(outer_op.is_comparison(), - "check_no_chained_comparison: {:?} is not comparison", - outer_op); + /// We only need to check the LHS, not the RHS, because all comparison ops have same + /// precedence and are left-associative. + /// + /// This can also be hit if someone incorrectly writes `foo()` when they should have used + /// the turbofish syntax. We attempt some heuristic recovery if that is the case. + crate fn check_no_chained_comparison( + &mut self, + lhs: &Expr, + outer_op: &AssocOp, + ) -> PResult<'a, Option>> { + debug_assert!( + outer_op.is_comparison(), + "check_no_chained_comparison: {:?} is not comparison", + outer_op, + ); match lhs.kind { ExprKind::Binary(op, _, _) if op.node.is_comparison() => { // Respan to include both operators. - let op_span = op.span.to(self.token.span); + let op_span = op.span.to(self.prev_span); let mut err = self.struct_span_err( op_span, "chained comparison operators require parentheses", @@ -561,17 +570,84 @@ impl<'a> Parser<'a> { *outer_op == AssocOp::Less || // Include `<` to provide this recommendation *outer_op == AssocOp::Greater // even in a case like the following: { // Foo>> - err.help( - "use `::<...>` instead of `<...>` if you meant to specify type arguments"); - err.help("or use `(...)` if you meant to specify fn arguments"); - // These cases cause too many knock-down errors, bail out (#61329). + let msg = "use `::<...>` instead of `<...>` if you meant to specify type \ + arguments"; + if *outer_op == AssocOp::Less { + // if self.look_ahead(1, |t| t.kind == token::Lt || t.kind == token::ModSep) { + let snapshot = self.clone(); + self.bump(); + // So far we have parsed `foo 0 { + match &self.token.kind { + token::Lt => { + acc += 1; + } + token::Gt => { + acc -= 1; + } + token::BinOp(token::Shr) => { + acc -= 2; + } + token::Eof => { + break; + } + _ => {} + } + self.bump(); + } + if self.token.kind != token::OpenDelim(token::Paren) { + mem::replace(self, snapshot.clone()); + } + } + if self.token.kind == token::OpenDelim(token::Paren) { + err.span_suggestion( + op_span.shrink_to_lo(), + msg, + "::".to_string(), + Applicability::MaybeIncorrect, + ); + let snapshot = self.clone(); + self.bump(); + let mut acc = 1; + while acc > 0 { + match &self.token.kind { + token::OpenDelim(token::Paren) => { + acc += 1; + } + token::CloseDelim(token::Paren) => { + acc -= 1; + } + token::Eof => { + break; + } + _ => {} + } + self.bump(); + } + if self.token.kind == token::Eof { + mem::replace(self, snapshot); + return Err(err); + } else { + err.emit(); + return Ok(Some(self.mk_expr( + lhs.span.to(self.prev_span), + ExprKind::Err, + ThinVec::new(), + ))); + } + } else { + err.help(msg); + err.help("or use `(...)` if you meant to specify fn arguments"); + // These cases cause too many knock-down errors, bail out (#61329). + } return Err(err); } err.emit(); } _ => {} } - Ok(()) + Ok(None) } crate fn maybe_report_ambiguous_plus( diff --git a/src/libsyntax/parse/parser/expr.rs b/src/libsyntax/parse/parser/expr.rs index 23674ad589dc5..b459782d237c7 100644 --- a/src/libsyntax/parse/parser/expr.rs +++ b/src/libsyntax/parse/parser/expr.rs @@ -238,7 +238,9 @@ impl<'a> Parser<'a> { self.bump(); if op.is_comparison() { - self.check_no_chained_comparison(&lhs, &op)?; + if let Some(expr) = self.check_no_chained_comparison(&lhs, &op)? { + return Ok(expr); + } } // Special cases: if op == AssocOp::As { diff --git a/src/test/ui/did_you_mean/issue-40396.stderr b/src/test/ui/did_you_mean/issue-40396.stderr index 7a08fda27e355..d0448cc265c31 100644 --- a/src/test/ui/did_you_mean/issue-40396.stderr +++ b/src/test/ui/did_you_mean/issue-40396.stderr @@ -2,16 +2,17 @@ error: chained comparison operators require parentheses --> $DIR/issue-40396.rs:2:20 | LL | (0..13).collect>(); - | ^^^^^^^^ + | ^^^^^ +help: use `::<...>` instead of `<...>` if you meant to specify type arguments | - = help: use `::<...>` instead of `<...>` if you meant to specify type arguments - = help: or use `(...)` if you meant to specify fn arguments +LL | (0..13).collect::>(); + | ^^ error: chained comparison operators require parentheses --> $DIR/issue-40396.rs:7:8 | LL | Vec::new(); - | ^^^^^^^ + | ^^^^^ | = help: use `::<...>` instead of `<...>` if you meant to specify type arguments = help: or use `(...)` if you meant to specify fn arguments @@ -20,10 +21,11 @@ error: chained comparison operators require parentheses --> $DIR/issue-40396.rs:12:20 | LL | (0..13).collect(); - | ^^^^^^^^ + | ^^^^^ +help: use `::<...>` instead of `<...>` if you meant to specify type arguments | - = help: use `::<...>` instead of `<...>` if you meant to specify type arguments - = help: or use `(...)` if you meant to specify fn arguments +LL | (0..13).collect::(); + | ^^ error: aborting due to 3 previous errors diff --git a/src/test/ui/parser/require-parens-for-chained-comparison.rs b/src/test/ui/parser/require-parens-for-chained-comparison.rs index 3dcc0c8f3d496..11839938cb022 100644 --- a/src/test/ui/parser/require-parens-for-chained-comparison.rs +++ b/src/test/ui/parser/require-parens-for-chained-comparison.rs @@ -13,5 +13,8 @@ fn main() { f(); //~^ ERROR chained comparison operators require parentheses //~| HELP: use `::<...>` instead of `<...>` - //~| HELP: or use `(...)` + + f, Option>>(1, 2); + //~^ ERROR chained comparison operators require parentheses + //~| HELP: use `::<...>` instead of `<...>` } diff --git a/src/test/ui/parser/require-parens-for-chained-comparison.stderr b/src/test/ui/parser/require-parens-for-chained-comparison.stderr index e927f4c32484e..02fb56a7f9be2 100644 --- a/src/test/ui/parser/require-parens-for-chained-comparison.stderr +++ b/src/test/ui/parser/require-parens-for-chained-comparison.stderr @@ -2,22 +2,33 @@ error: chained comparison operators require parentheses --> $DIR/require-parens-for-chained-comparison.rs:5:11 | LL | false == false == false; - | ^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^ error: chained comparison operators require parentheses --> $DIR/require-parens-for-chained-comparison.rs:8:11 | LL | false == 0 < 2; - | ^^^^^^^^ + | ^^^^^^ error: chained comparison operators require parentheses --> $DIR/require-parens-for-chained-comparison.rs:13:6 | LL | f(); - | ^^^^ + | ^^^ +help: use `::<...>` instead of `<...>` if you meant to specify type arguments | - = help: use `::<...>` instead of `<...>` if you meant to specify type arguments - = help: or use `(...)` if you meant to specify fn arguments +LL | f::(); + | ^^ + +error: chained comparison operators require parentheses + --> $DIR/require-parens-for-chained-comparison.rs:17:6 + | +LL | f, Option>>(1, 2); + | ^^^^^^^^ +help: use `::<...>` instead of `<...>` if you meant to specify type arguments + | +LL | f::, Option>>(1, 2); + | ^^ error[E0308]: mismatched types --> $DIR/require-parens-for-chained-comparison.rs:8:14 @@ -37,6 +48,6 @@ LL | false == 0 < 2; = note: expected type `bool` found type `{integer}` -error: aborting due to 5 previous errors +error: aborting due to 6 previous errors For more information about this error, try `rustc --explain E0308`. From 6c9f298a8bee9b1716b2e6fcdb8305c3f4874fc6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Mon, 30 Sep 2019 12:19:22 -0700 Subject: [PATCH 06/23] review comments --- src/libsyntax/parse/diagnostics.rs | 87 +++++++++++++++++------------- 1 file changed, 49 insertions(+), 38 deletions(-) diff --git a/src/libsyntax/parse/diagnostics.rs b/src/libsyntax/parse/diagnostics.rs index 0e3d873b252e6..584c7c2ded55b 100644 --- a/src/libsyntax/parse/diagnostics.rs +++ b/src/libsyntax/parse/diagnostics.rs @@ -560,6 +560,7 @@ impl<'a> Parser<'a> { ); match lhs.kind { ExprKind::Binary(op, _, _) if op.node.is_comparison() => { + // Respan to include both operators. let op_span = op.span.to(self.prev_span); let mut err = self.struct_span_err( @@ -573,63 +574,54 @@ impl<'a> Parser<'a> { let msg = "use `::<...>` instead of `<...>` if you meant to specify type \ arguments"; if *outer_op == AssocOp::Less { - // if self.look_ahead(1, |t| t.kind == token::Lt || t.kind == token::ModSep) { let snapshot = self.clone(); self.bump(); - // So far we have parsed `foo 0 { - match &self.token.kind { - token::Lt => { - acc += 1; - } - token::Gt => { - acc -= 1; - } - token::BinOp(token::Shr) => { - acc -= 2; - } - token::Eof => { - break; - } - _ => {} - } - self.bump(); - } + // So far we have parsed `foo(`, so we rewind the parser and bail out. mem::replace(self, snapshot.clone()); } } if self.token.kind == token::OpenDelim(token::Paren) { + // We have high certainty that this was a bad turbofish at this point. + // `foo< bar >(` err.span_suggestion( op_span.shrink_to_lo(), msg, "::".to_string(), Applicability::MaybeIncorrect, ); + let snapshot = self.clone(); - self.bump(); - let mut acc = 1; - while acc > 0 { - match &self.token.kind { - token::OpenDelim(token::Paren) => { - acc += 1; - } - token::CloseDelim(token::Paren) => { - acc -= 1; - } - token::Eof => { - break; - } - _ => {} - } - self.bump(); - } + + // Consume the fn call arguments. + let modifiers = vec![ + (token::OpenDelim(token::Paren), 1), + (token::CloseDelim(token::Paren), -1), + ]; + let early_return = vec![token::Eof]; + self.bump(); // `(` + self.consume_tts(1, &modifiers[..], &early_return[..]); + if self.token.kind == token::Eof { + // Not entirely sure now, but we bubble the error up with the + // suggestion. mem::replace(self, snapshot); return Err(err); } else { + // 99% certain that the suggestion is correct, continue parsing. err.emit(); + // FIXME: actually check that the two expressions in the binop are + // paths and resynthesize new fn call expression instead of using + // `ExprKind::Err` placeholder. return Ok(Some(self.mk_expr( lhs.span.to(self.prev_span), ExprKind::Err, @@ -637,6 +629,8 @@ impl<'a> Parser<'a> { ))); } } else { + // All we know is that this is `foo < bar >` and *nothing* else. Try to + // be helpful, but don't attempt to recover. err.help(msg); err.help("or use `(...)` if you meant to specify fn arguments"); // These cases cause too many knock-down errors, bail out (#61329). @@ -1424,6 +1418,23 @@ impl<'a> Parser<'a> { err } + fn consume_tts( + &mut self, + mut acc: i64, + modifier: &[(token::TokenKind, i64)], // Not using FxHasMap and FxHashSet due to + early_return: &[token::TokenKind], // `token::TokenKind: !Eq + !Hash`. + ) { + while acc > 0 { + if let Some((_, val)) = modifier.iter().filter(|(t, _)| *t == self.token.kind).next() { + acc += *val; + } + if early_return.contains(&self.token.kind) { + break; + } + self.bump(); + } + } + /// Replace duplicated recovered parameters with `_` pattern to avoid unecessary errors. /// /// This is necessary because at this point we don't know whether we parsed a function with From d7dceaa0c57759d37a48b5a0aa1064b7c89f957b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Mon, 30 Sep 2019 12:36:44 -0700 Subject: [PATCH 07/23] Account for missing turbofish in paths too --- src/libsyntax/parse/diagnostics.rs | 47 +++++++++++++++++++-- src/test/ui/did_you_mean/issue-40396.stderr | 5 ++- 2 files changed, 46 insertions(+), 6 deletions(-) diff --git a/src/libsyntax/parse/diagnostics.rs b/src/libsyntax/parse/diagnostics.rs index 584c7c2ded55b..4fbd36cfefc82 100644 --- a/src/libsyntax/parse/diagnostics.rs +++ b/src/libsyntax/parse/diagnostics.rs @@ -585,12 +585,51 @@ impl<'a> Parser<'a> { let early_return = vec![token::Eof]; self.consume_tts(1, &modifiers[..], &early_return[..]); - if self.token.kind != token::OpenDelim(token::Paren) { - // We don't have `foo< bar >(`, so we rewind the parser and bail out. + if !&[ + token::OpenDelim(token::Paren), + token::ModSep, + ].contains(&self.token.kind) { + // We don't have `foo< bar >(` or `foo< bar >::`, so we rewind the + // parser and bail out. mem::replace(self, snapshot.clone()); } } - if self.token.kind == token::OpenDelim(token::Paren) { + if token::ModSep == self.token.kind { + // We have some certainty that this was a bad turbofish at this point. + // `foo< bar >::` + err.span_suggestion( + op_span.shrink_to_lo(), + msg, + "::".to_string(), + Applicability::MaybeIncorrect, + ); + + let snapshot = self.clone(); + + self.bump(); // `::` + // Consume the rest of the likely `foo::new()` or return at `foo`. + match self.parse_expr() { + Ok(_) => { + // 99% certain that the suggestion is correct, continue parsing. + err.emit(); + // FIXME: actually check that the two expressions in the binop are + // paths and resynthesize new fn call expression instead of using + // `ExprKind::Err` placeholder. + return Ok(Some(self.mk_expr( + lhs.span.to(self.prev_span), + ExprKind::Err, + ThinVec::new(), + ))); + } + Err(mut err) => { + err.cancel(); + // Not entirely sure now, but we bubble the error up with the + // suggestion. + mem::replace(self, snapshot); + return Err(err); + } + } + } else if token::OpenDelim(token::Paren) == self.token.kind { // We have high certainty that this was a bad turbofish at this point. // `foo< bar >(` err.span_suggestion( @@ -601,6 +640,7 @@ impl<'a> Parser<'a> { ); let snapshot = self.clone(); + self.bump(); // `(` // Consume the fn call arguments. let modifiers = vec![ @@ -608,7 +648,6 @@ impl<'a> Parser<'a> { (token::CloseDelim(token::Paren), -1), ]; let early_return = vec![token::Eof]; - self.bump(); // `(` self.consume_tts(1, &modifiers[..], &early_return[..]); if self.token.kind == token::Eof { diff --git a/src/test/ui/did_you_mean/issue-40396.stderr b/src/test/ui/did_you_mean/issue-40396.stderr index d0448cc265c31..5e3771002b685 100644 --- a/src/test/ui/did_you_mean/issue-40396.stderr +++ b/src/test/ui/did_you_mean/issue-40396.stderr @@ -13,9 +13,10 @@ error: chained comparison operators require parentheses | LL | Vec::new(); | ^^^^^ +help: use `::<...>` instead of `<...>` if you meant to specify type arguments | - = help: use `::<...>` instead of `<...>` if you meant to specify type arguments - = help: or use `(...)` if you meant to specify fn arguments +LL | Vec::::new(); + | ^^ error: chained comparison operators require parentheses --> $DIR/issue-40396.rs:12:20 From d27683a39f5924205d73e0015b8c25c97aadaa63 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Mon, 30 Sep 2019 13:22:58 -0700 Subject: [PATCH 08/23] Prove bad turbofish parser recovery in test --- src/test/ui/did_you_mean/issue-40396.rs | 10 +--------- src/test/ui/did_you_mean/issue-40396.stderr | 4 ++-- 2 files changed, 3 insertions(+), 11 deletions(-) diff --git a/src/test/ui/did_you_mean/issue-40396.rs b/src/test/ui/did_you_mean/issue-40396.rs index 6902779f33d23..1893355205433 100644 --- a/src/test/ui/did_you_mean/issue-40396.rs +++ b/src/test/ui/did_you_mean/issue-40396.rs @@ -1,16 +1,8 @@ -fn foo() { +fn main() { (0..13).collect>(); //~^ ERROR chained comparison -} - -fn bar() { Vec::new(); //~^ ERROR chained comparison -} - -fn qux() { (0..13).collect(); //~^ ERROR chained comparison } - -fn main() {} diff --git a/src/test/ui/did_you_mean/issue-40396.stderr b/src/test/ui/did_you_mean/issue-40396.stderr index 5e3771002b685..dd19bc137e30d 100644 --- a/src/test/ui/did_you_mean/issue-40396.stderr +++ b/src/test/ui/did_you_mean/issue-40396.stderr @@ -9,7 +9,7 @@ LL | (0..13).collect::>(); | ^^ error: chained comparison operators require parentheses - --> $DIR/issue-40396.rs:7:8 + --> $DIR/issue-40396.rs:4:8 | LL | Vec::new(); | ^^^^^ @@ -19,7 +19,7 @@ LL | Vec::::new(); | ^^ error: chained comparison operators require parentheses - --> $DIR/issue-40396.rs:12:20 + --> $DIR/issue-40396.rs:6:20 | LL | (0..13).collect(); | ^^^^^ From dfdc369b40da72eb9ff466fab89584c7815d7a80 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Tue, 1 Oct 2019 11:24:05 -0700 Subject: [PATCH 09/23] review comments --- src/libsyntax/parse/diagnostics.rs | 79 ++++++++++--------- src/test/ui/did_you_mean/issue-40396.stderr | 6 +- .../require-parens-for-chained-comparison.rs | 18 +++-- ...quire-parens-for-chained-comparison.stderr | 15 +++- 4 files changed, 70 insertions(+), 48 deletions(-) diff --git a/src/libsyntax/parse/diagnostics.rs b/src/libsyntax/parse/diagnostics.rs index 4fbd36cfefc82..14c5dc6132cf8 100644 --- a/src/libsyntax/parse/diagnostics.rs +++ b/src/libsyntax/parse/diagnostics.rs @@ -17,6 +17,8 @@ use syntax_pos::{Span, DUMMY_SP, MultiSpan, SpanSnippetError}; use log::{debug, trace}; use std::mem; +const TURBOFISH: &'static str = "use the \"turbofish\" `::<...>` instead of `<...>` to specify \ + type arguments"; /// Creates a placeholder argument. crate fn dummy_arg(ident: Ident) -> Param { let pat = P(Pat { @@ -544,10 +546,20 @@ impl<'a> Parser<'a> { /// Produces an error if comparison operators are chained (RFC #558). /// We only need to check the LHS, not the RHS, because all comparison ops have same - /// precedence and are left-associative. + /// precedence (see `fn precedence`) and are left-associative (see `fn fixity`). /// /// This can also be hit if someone incorrectly writes `foo()` when they should have used - /// the turbofish syntax. We attempt some heuristic recovery if that is the case. + /// the turbofish (`foo::()`) syntax. We attempt some heuristic recovery if that is the + /// case. + /// + /// Keep in mind that given that `outer_op.is_comparison()` holds and comparison ops are left + /// associative we can infer that we have: + /// + /// outer_op + /// / \ + /// inner_op r2 + /// / \ + /// l1 r1 crate fn check_no_chained_comparison( &mut self, lhs: &Expr, @@ -560,30 +572,36 @@ impl<'a> Parser<'a> { ); match lhs.kind { ExprKind::Binary(op, _, _) if op.node.is_comparison() => { - // Respan to include both operators. let op_span = op.span.to(self.prev_span); let mut err = self.struct_span_err( op_span, "chained comparison operators require parentheses", ); + + let suggest = |err: &mut DiagnosticBuilder<'_>| { + err.span_suggestion( + op_span.shrink_to_lo(), + TURBOFISH, + "::".to_string(), + Applicability::MaybeIncorrect, + ); + }; + if op.node == BinOpKind::Lt && *outer_op == AssocOp::Less || // Include `<` to provide this recommendation *outer_op == AssocOp::Greater // even in a case like the following: { // Foo>> - let msg = "use `::<...>` instead of `<...>` if you meant to specify type \ - arguments"; if *outer_op == AssocOp::Less { let snapshot = self.clone(); self.bump(); - // So far we have parsed `foo Parser<'a> { if token::ModSep == self.token.kind { // We have some certainty that this was a bad turbofish at this point. // `foo< bar >::` - err.span_suggestion( - op_span.shrink_to_lo(), - msg, - "::".to_string(), - Applicability::MaybeIncorrect, - ); + suggest(&mut err); let snapshot = self.clone(); - self.bump(); // `::` + // Consume the rest of the likely `foo::new()` or return at `foo`. match self.parse_expr() { Ok(_) => { @@ -621,8 +634,8 @@ impl<'a> Parser<'a> { ThinVec::new(), ))); } - Err(mut err) => { - err.cancel(); + Err(mut expr_err) => { + expr_err.cancel(); // Not entirely sure now, but we bubble the error up with the // suggestion. mem::replace(self, snapshot); @@ -632,45 +645,39 @@ impl<'a> Parser<'a> { } else if token::OpenDelim(token::Paren) == self.token.kind { // We have high certainty that this was a bad turbofish at this point. // `foo< bar >(` - err.span_suggestion( - op_span.shrink_to_lo(), - msg, - "::".to_string(), - Applicability::MaybeIncorrect, - ); + suggest(&mut err); let snapshot = self.clone(); self.bump(); // `(` // Consume the fn call arguments. - let modifiers = vec![ + let modifiers = [ (token::OpenDelim(token::Paren), 1), (token::CloseDelim(token::Paren), -1), ]; - let early_return = vec![token::Eof]; - self.consume_tts(1, &modifiers[..], &early_return[..]); + self.consume_tts(1, &modifiers[..], &[]); - if self.token.kind == token::Eof { + return if self.token.kind == token::Eof { // Not entirely sure now, but we bubble the error up with the // suggestion. mem::replace(self, snapshot); - return Err(err); + Err(err) } else { // 99% certain that the suggestion is correct, continue parsing. err.emit(); // FIXME: actually check that the two expressions in the binop are // paths and resynthesize new fn call expression instead of using // `ExprKind::Err` placeholder. - return Ok(Some(self.mk_expr( + Ok(Some(self.mk_expr( lhs.span.to(self.prev_span), ExprKind::Err, ThinVec::new(), - ))); + ))) } } else { // All we know is that this is `foo < bar >` and *nothing* else. Try to // be helpful, but don't attempt to recover. - err.help(msg); + err.help(TURBOFISH); err.help("or use `(...)` if you meant to specify fn arguments"); // These cases cause too many knock-down errors, bail out (#61329). } @@ -1459,15 +1466,15 @@ impl<'a> Parser<'a> { fn consume_tts( &mut self, - mut acc: i64, - modifier: &[(token::TokenKind, i64)], // Not using FxHasMap and FxHashSet due to + mut acc: i64, // `i64` because malformed code can have more closing delims than opening. + modifier: &[(token::TokenKind, i64)], // Not using `FxHashMap` and `FxHashSet` due to early_return: &[token::TokenKind], // `token::TokenKind: !Eq + !Hash`. ) { while acc > 0 { - if let Some((_, val)) = modifier.iter().filter(|(t, _)| *t == self.token.kind).next() { + if let Some((_, val)) = modifier.iter().find(|(t, _)| *t == self.token.kind) { acc += *val; } - if early_return.contains(&self.token.kind) { + if self.token.kind == token::Eof || early_return.contains(&self.token.kind) { break; } self.bump(); diff --git a/src/test/ui/did_you_mean/issue-40396.stderr b/src/test/ui/did_you_mean/issue-40396.stderr index dd19bc137e30d..9757f8258c131 100644 --- a/src/test/ui/did_you_mean/issue-40396.stderr +++ b/src/test/ui/did_you_mean/issue-40396.stderr @@ -3,7 +3,7 @@ error: chained comparison operators require parentheses | LL | (0..13).collect>(); | ^^^^^ -help: use `::<...>` instead of `<...>` if you meant to specify type arguments +help: use the "turbofish" `::<...>` instead of `<...>` to specify type arguments | LL | (0..13).collect::>(); | ^^ @@ -13,7 +13,7 @@ error: chained comparison operators require parentheses | LL | Vec::new(); | ^^^^^ -help: use `::<...>` instead of `<...>` if you meant to specify type arguments +help: use the "turbofish" `::<...>` instead of `<...>` to specify type arguments | LL | Vec::::new(); | ^^ @@ -23,7 +23,7 @@ error: chained comparison operators require parentheses | LL | (0..13).collect(); | ^^^^^ -help: use `::<...>` instead of `<...>` if you meant to specify type arguments +help: use the "turbofish" `::<...>` instead of `<...>` to specify type arguments | LL | (0..13).collect::(); | ^^ diff --git a/src/test/ui/parser/require-parens-for-chained-comparison.rs b/src/test/ui/parser/require-parens-for-chained-comparison.rs index 11839938cb022..f3bfe2d482f59 100644 --- a/src/test/ui/parser/require-parens-for-chained-comparison.rs +++ b/src/test/ui/parser/require-parens-for-chained-comparison.rs @@ -3,18 +3,24 @@ struct X; fn main() { false == false == false; - //~^ ERROR: chained comparison operators require parentheses + //~^ ERROR chained comparison operators require parentheses false == 0 < 2; - //~^ ERROR: chained comparison operators require parentheses - //~| ERROR: mismatched types - //~| ERROR: mismatched types + //~^ ERROR chained comparison operators require parentheses + //~| ERROR mismatched types + //~| ERROR mismatched types f(); //~^ ERROR chained comparison operators require parentheses - //~| HELP: use `::<...>` instead of `<...>` + //~| HELP use the "turbofish" `::<...>` instead of `<...>` to specify type arguments f, Option>>(1, 2); //~^ ERROR chained comparison operators require parentheses - //~| HELP: use `::<...>` instead of `<...>` + //~| HELP use the "turbofish" `::<...>` instead of `<...>` to specify type arguments + + use std::convert::identity; + let _ = identity; + //~^ ERROR chained comparison operators require parentheses + //~| HELP use the "turbofish" `::<...>` instead of `<...>` to specify type arguments + //~| HELP or use `(...)` if you meant to specify fn arguments } diff --git a/src/test/ui/parser/require-parens-for-chained-comparison.stderr b/src/test/ui/parser/require-parens-for-chained-comparison.stderr index 02fb56a7f9be2..4b108e1db87b7 100644 --- a/src/test/ui/parser/require-parens-for-chained-comparison.stderr +++ b/src/test/ui/parser/require-parens-for-chained-comparison.stderr @@ -15,7 +15,7 @@ error: chained comparison operators require parentheses | LL | f(); | ^^^ -help: use `::<...>` instead of `<...>` if you meant to specify type arguments +help: use the "turbofish" `::<...>` instead of `<...>` to specify type arguments | LL | f::(); | ^^ @@ -25,11 +25,20 @@ error: chained comparison operators require parentheses | LL | f, Option>>(1, 2); | ^^^^^^^^ -help: use `::<...>` instead of `<...>` if you meant to specify type arguments +help: use the "turbofish" `::<...>` instead of `<...>` to specify type arguments | LL | f::, Option>>(1, 2); | ^^ +error: chained comparison operators require parentheses + --> $DIR/require-parens-for-chained-comparison.rs:22:21 + | +LL | let _ = identity; + | ^^^^ + | + = help: use the "turbofish" `::<...>` instead of `<...>` to specify type arguments + = help: or use `(...)` if you meant to specify fn arguments + error[E0308]: mismatched types --> $DIR/require-parens-for-chained-comparison.rs:8:14 | @@ -48,6 +57,6 @@ LL | false == 0 < 2; = note: expected type `bool` found type `{integer}` -error: aborting due to 6 previous errors +error: aborting due to 7 previous errors For more information about this error, try `rustc --explain E0308`. From f1499a864688a484c04c4e53962dc8ec44f79a03 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Tue, 1 Oct 2019 15:51:50 -0700 Subject: [PATCH 10/23] review comments --- src/libsyntax/parse/diagnostics.rs | 37 ++++++++++++++---------------- 1 file changed, 17 insertions(+), 20 deletions(-) diff --git a/src/libsyntax/parse/diagnostics.rs b/src/libsyntax/parse/diagnostics.rs index 14c5dc6132cf8..72206ffb28df0 100644 --- a/src/libsyntax/parse/diagnostics.rs +++ b/src/libsyntax/parse/diagnostics.rs @@ -570,6 +570,11 @@ impl<'a> Parser<'a> { "check_no_chained_comparison: {:?} is not comparison", outer_op, ); + + let mk_err_expr = |this: &Self, span| { + Ok(Some(this.mk_expr(span, ExprKind::Err, ThinVec::new()))) + }; + match lhs.kind { ExprKind::Binary(op, _, _) if op.node.is_comparison() => { // Respan to include both operators. @@ -601,7 +606,7 @@ impl<'a> Parser<'a> { (token::Gt, -1), (token::BinOp(token::Shr), -2), ]; - self.consume_tts(1, &modifiers[..], &[]); + self.consume_tts(1, &modifiers[..]); if !&[ token::OpenDelim(token::Paren), @@ -612,7 +617,7 @@ impl<'a> Parser<'a> { mem::replace(self, snapshot.clone()); } } - if token::ModSep == self.token.kind { + return if token::ModSep == self.token.kind { // We have some certainty that this was a bad turbofish at this point. // `foo< bar >::` suggest(&mut err); @@ -628,18 +633,14 @@ impl<'a> Parser<'a> { // FIXME: actually check that the two expressions in the binop are // paths and resynthesize new fn call expression instead of using // `ExprKind::Err` placeholder. - return Ok(Some(self.mk_expr( - lhs.span.to(self.prev_span), - ExprKind::Err, - ThinVec::new(), - ))); + mk_err_expr(self, lhs.span.to(self.prev_span)) } Err(mut expr_err) => { expr_err.cancel(); // Not entirely sure now, but we bubble the error up with the // suggestion. mem::replace(self, snapshot); - return Err(err); + Err(err) } } } else if token::OpenDelim(token::Paren) == self.token.kind { @@ -655,9 +656,9 @@ impl<'a> Parser<'a> { (token::OpenDelim(token::Paren), 1), (token::CloseDelim(token::Paren), -1), ]; - self.consume_tts(1, &modifiers[..], &[]); + self.consume_tts(1, &modifiers[..]); - return if self.token.kind == token::Eof { + if self.token.kind == token::Eof { // Not entirely sure now, but we bubble the error up with the // suggestion. mem::replace(self, snapshot); @@ -668,11 +669,7 @@ impl<'a> Parser<'a> { // FIXME: actually check that the two expressions in the binop are // paths and resynthesize new fn call expression instead of using // `ExprKind::Err` placeholder. - Ok(Some(self.mk_expr( - lhs.span.to(self.prev_span), - ExprKind::Err, - ThinVec::new(), - ))) + mk_err_expr(self, lhs.span.to(self.prev_span)) } } else { // All we know is that this is `foo < bar >` and *nothing* else. Try to @@ -680,8 +677,8 @@ impl<'a> Parser<'a> { err.help(TURBOFISH); err.help("or use `(...)` if you meant to specify fn arguments"); // These cases cause too many knock-down errors, bail out (#61329). - } - return Err(err); + Err(err) + }; } err.emit(); } @@ -1467,14 +1464,14 @@ impl<'a> Parser<'a> { fn consume_tts( &mut self, mut acc: i64, // `i64` because malformed code can have more closing delims than opening. - modifier: &[(token::TokenKind, i64)], // Not using `FxHashMap` and `FxHashSet` due to - early_return: &[token::TokenKind], // `token::TokenKind: !Eq + !Hash`. + // Not using `FxHashMap` due to `token::TokenKind: !Eq + !Hash`. + modifier: &[(token::TokenKind, i64)], ) { while acc > 0 { if let Some((_, val)) = modifier.iter().find(|(t, _)| *t == self.token.kind) { acc += *val; } - if self.token.kind == token::Eof || early_return.contains(&self.token.kind) { + if self.token.kind == token::Eof { break; } self.bump(); From 02f57f83a9ea5903cb02bdc304800661c8f4296f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Thu, 3 Oct 2019 13:22:18 -0700 Subject: [PATCH 11/23] review comments --- src/librustc_errors/diagnostic.rs | 41 +++++++++++-- src/librustc_errors/emitter.rs | 4 +- src/librustc_errors/lib.rs | 2 + src/libsyntax/parse/diagnostics.rs | 57 +++++++++++-------- src/test/ui/did_you_mean/issue-40396.stderr | 6 +- .../require-parens-for-chained-comparison.rs | 6 +- ...quire-parens-for-chained-comparison.stderr | 6 +- 7 files changed, 81 insertions(+), 41 deletions(-) diff --git a/src/librustc_errors/diagnostic.rs b/src/librustc_errors/diagnostic.rs index 3f1b91256c468..811a48a39f0df 100644 --- a/src/librustc_errors/diagnostic.rs +++ b/src/librustc_errors/diagnostic.rs @@ -298,9 +298,13 @@ impl Diagnostic { /// * may contain a name of a function, variable, or type, but not whole expressions /// /// See `CodeSuggestion` for more information. - pub fn span_suggestion(&mut self, sp: Span, msg: &str, - suggestion: String, - applicability: Applicability) -> &mut Self { + pub fn span_suggestion( + &mut self, + sp: Span, + msg: &str, + suggestion: String, + applicability: Applicability, + ) -> &mut Self { self.suggestions.push(CodeSuggestion { substitutions: vec![Substitution { parts: vec![SubstitutionPart { @@ -315,10 +319,35 @@ impl Diagnostic { self } + pub fn span_suggestion_verbose( + &mut self, + sp: Span, + msg: &str, + suggestion: String, + applicability: Applicability, + ) -> &mut Self { + self.suggestions.push(CodeSuggestion { + substitutions: vec![Substitution { + parts: vec![SubstitutionPart { + snippet: suggestion, + span: sp, + }], + }], + msg: msg.to_owned(), + style: SuggestionStyle::ShowAlways, + applicability, + }); + self + } + /// Prints out a message with multiple suggested edits of the code. - pub fn span_suggestions(&mut self, sp: Span, msg: &str, - suggestions: impl Iterator, applicability: Applicability) -> &mut Self - { + pub fn span_suggestions( + &mut self, + sp: Span, + msg: &str, + suggestions: impl Iterator, + applicability: Applicability, + ) -> &mut Self { self.suggestions.push(CodeSuggestion { substitutions: suggestions.map(|snippet| Substitution { parts: vec![SubstitutionPart { diff --git a/src/librustc_errors/emitter.rs b/src/librustc_errors/emitter.rs index 0c7aa3582ac23..bd8191065eeca 100644 --- a/src/librustc_errors/emitter.rs +++ b/src/librustc_errors/emitter.rs @@ -221,7 +221,9 @@ pub trait Emitter { // when this style is set we want the suggestion to be a message, not inline sugg.style != SuggestionStyle::HideCodeAlways && // trivial suggestion for tooling's sake, never shown - sugg.style != SuggestionStyle::CompletelyHidden + sugg.style != SuggestionStyle::CompletelyHidden && + // subtle suggestion, never shown inline + sugg.style != SuggestionStyle::ShowAlways { let substitution = &sugg.substitutions[0].parts[0].snippet.trim(); let msg = if substitution.len() == 0 || sugg.style.hide_inline() { diff --git a/src/librustc_errors/lib.rs b/src/librustc_errors/lib.rs index f9dc13ce97eea..2fae584c15362 100644 --- a/src/librustc_errors/lib.rs +++ b/src/librustc_errors/lib.rs @@ -81,6 +81,8 @@ pub enum SuggestionStyle { /// This will *not* show the code if the suggestion is inline *and* the suggested code is /// empty. ShowCode, + /// Always show the suggested code independently. + ShowAlways, } impl SuggestionStyle { diff --git a/src/libsyntax/parse/diagnostics.rs b/src/libsyntax/parse/diagnostics.rs index 72206ffb28df0..e3abf8ffc6c8f 100644 --- a/src/libsyntax/parse/diagnostics.rs +++ b/src/libsyntax/parse/diagnostics.rs @@ -17,8 +17,7 @@ use syntax_pos::{Span, DUMMY_SP, MultiSpan, SpanSnippetError}; use log::{debug, trace}; use std::mem; -const TURBOFISH: &'static str = "use the \"turbofish\" `::<...>` instead of `<...>` to specify \ - type arguments"; +const TURBOFISH: &'static str = "use `::<...>` instead of `<...>` to specify type arguments"; /// Creates a placeholder argument. crate fn dummy_arg(ident: Ident) -> Param { let pat = P(Pat { @@ -585,7 +584,7 @@ impl<'a> Parser<'a> { ); let suggest = |err: &mut DiagnosticBuilder<'_>| { - err.span_suggestion( + err.span_suggestion_verbose( op_span.shrink_to_lo(), TURBOFISH, "::".to_string(), @@ -647,29 +646,16 @@ impl<'a> Parser<'a> { // We have high certainty that this was a bad turbofish at this point. // `foo< bar >(` suggest(&mut err); - - let snapshot = self.clone(); - self.bump(); // `(` - // Consume the fn call arguments. - let modifiers = [ - (token::OpenDelim(token::Paren), 1), - (token::CloseDelim(token::Paren), -1), - ]; - self.consume_tts(1, &modifiers[..]); - - if self.token.kind == token::Eof { - // Not entirely sure now, but we bubble the error up with the - // suggestion. - mem::replace(self, snapshot); - Err(err) - } else { - // 99% certain that the suggestion is correct, continue parsing. - err.emit(); - // FIXME: actually check that the two expressions in the binop are - // paths and resynthesize new fn call expression instead of using - // `ExprKind::Err` placeholder. - mk_err_expr(self, lhs.span.to(self.prev_span)) + match self.consume_fn_args() { + Err(()) => Err(err), + Ok(()) => { + err.emit(); + // FIXME: actually check that the two expressions in the binop are + // paths and resynthesize new fn call expression instead of using + // `ExprKind::Err` placeholder. + mk_err_expr(self, lhs.span.to(self.prev_span)) + } } } else { // All we know is that this is `foo < bar >` and *nothing* else. Try to @@ -687,6 +673,27 @@ impl<'a> Parser<'a> { Ok(None) } + fn consume_fn_args(&mut self) -> Result<(), ()> { + let snapshot = self.clone(); + self.bump(); // `(` + + // Consume the fn call arguments. + let modifiers = [ + (token::OpenDelim(token::Paren), 1), + (token::CloseDelim(token::Paren), -1), + ]; + self.consume_tts(1, &modifiers[..]); + + if self.token.kind == token::Eof { + // Not entirely sure that what we consumed were fn arguments, rollback. + mem::replace(self, snapshot); + Err(()) + } else { + // 99% certain that the suggestion is correct, continue parsing. + Ok(()) + } + } + crate fn maybe_report_ambiguous_plus( &mut self, allow_plus: bool, diff --git a/src/test/ui/did_you_mean/issue-40396.stderr b/src/test/ui/did_you_mean/issue-40396.stderr index 9757f8258c131..7fc7c2628c472 100644 --- a/src/test/ui/did_you_mean/issue-40396.stderr +++ b/src/test/ui/did_you_mean/issue-40396.stderr @@ -3,7 +3,7 @@ error: chained comparison operators require parentheses | LL | (0..13).collect>(); | ^^^^^ -help: use the "turbofish" `::<...>` instead of `<...>` to specify type arguments +help: use `::<...>` instead of `<...>` to specify type arguments | LL | (0..13).collect::>(); | ^^ @@ -13,7 +13,7 @@ error: chained comparison operators require parentheses | LL | Vec::new(); | ^^^^^ -help: use the "turbofish" `::<...>` instead of `<...>` to specify type arguments +help: use `::<...>` instead of `<...>` to specify type arguments | LL | Vec::::new(); | ^^ @@ -23,7 +23,7 @@ error: chained comparison operators require parentheses | LL | (0..13).collect(); | ^^^^^ -help: use the "turbofish" `::<...>` instead of `<...>` to specify type arguments +help: use `::<...>` instead of `<...>` to specify type arguments | LL | (0..13).collect::(); | ^^ diff --git a/src/test/ui/parser/require-parens-for-chained-comparison.rs b/src/test/ui/parser/require-parens-for-chained-comparison.rs index f3bfe2d482f59..9c7a25d589a1f 100644 --- a/src/test/ui/parser/require-parens-for-chained-comparison.rs +++ b/src/test/ui/parser/require-parens-for-chained-comparison.rs @@ -12,15 +12,15 @@ fn main() { f(); //~^ ERROR chained comparison operators require parentheses - //~| HELP use the "turbofish" `::<...>` instead of `<...>` to specify type arguments + //~| HELP use `::<...>` instead of `<...>` to specify type arguments f, Option>>(1, 2); //~^ ERROR chained comparison operators require parentheses - //~| HELP use the "turbofish" `::<...>` instead of `<...>` to specify type arguments + //~| HELP use `::<...>` instead of `<...>` to specify type arguments use std::convert::identity; let _ = identity; //~^ ERROR chained comparison operators require parentheses - //~| HELP use the "turbofish" `::<...>` instead of `<...>` to specify type arguments + //~| HELP use `::<...>` instead of `<...>` to specify type arguments //~| HELP or use `(...)` if you meant to specify fn arguments } diff --git a/src/test/ui/parser/require-parens-for-chained-comparison.stderr b/src/test/ui/parser/require-parens-for-chained-comparison.stderr index 4b108e1db87b7..5aa37a40cbd3d 100644 --- a/src/test/ui/parser/require-parens-for-chained-comparison.stderr +++ b/src/test/ui/parser/require-parens-for-chained-comparison.stderr @@ -15,7 +15,7 @@ error: chained comparison operators require parentheses | LL | f(); | ^^^ -help: use the "turbofish" `::<...>` instead of `<...>` to specify type arguments +help: use `::<...>` instead of `<...>` to specify type arguments | LL | f::(); | ^^ @@ -25,7 +25,7 @@ error: chained comparison operators require parentheses | LL | f, Option>>(1, 2); | ^^^^^^^^ -help: use the "turbofish" `::<...>` instead of `<...>` to specify type arguments +help: use `::<...>` instead of `<...>` to specify type arguments | LL | f::, Option>>(1, 2); | ^^ @@ -36,7 +36,7 @@ error: chained comparison operators require parentheses LL | let _ = identity; | ^^^^ | - = help: use the "turbofish" `::<...>` instead of `<...>` to specify type arguments + = help: use `::<...>` instead of `<...>` to specify type arguments = help: or use `(...)` if you meant to specify fn arguments error[E0308]: mismatched types From 76456e74066d7594f23757ebade169c33276ea4d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Thu, 3 Oct 2019 19:32:56 -0700 Subject: [PATCH 12/23] review comments --- src/librustc_errors/diagnostic.rs | 84 ++++++++++++++++--------------- src/librustc_errors/emitter.rs | 14 +++--- 2 files changed, 51 insertions(+), 47 deletions(-) diff --git a/src/librustc_errors/diagnostic.rs b/src/librustc_errors/diagnostic.rs index 811a48a39f0df..fd74d8673da4d 100644 --- a/src/librustc_errors/diagnostic.rs +++ b/src/librustc_errors/diagnostic.rs @@ -304,6 +304,24 @@ impl Diagnostic { msg: &str, suggestion: String, applicability: Applicability, + ) -> &mut Self { + self.span_suggestion_with_style( + sp, + msg, + suggestion, + applicability, + SuggestionStyle::ShowCode, + ); + self + } + + pub fn span_suggestion_with_style( + &mut self, + sp: Span, + msg: &str, + suggestion: String, + applicability: Applicability, + style: SuggestionStyle, ) -> &mut Self { self.suggestions.push(CodeSuggestion { substitutions: vec![Substitution { @@ -313,7 +331,7 @@ impl Diagnostic { }], }], msg: msg.to_owned(), - style: SuggestionStyle::ShowCode, + style, applicability, }); self @@ -326,17 +344,13 @@ impl Diagnostic { suggestion: String, applicability: Applicability, ) -> &mut Self { - self.suggestions.push(CodeSuggestion { - substitutions: vec![Substitution { - parts: vec![SubstitutionPart { - snippet: suggestion, - span: sp, - }], - }], - msg: msg.to_owned(), - style: SuggestionStyle::ShowAlways, + self.span_suggestion_with_style( + sp, + msg, + suggestion, applicability, - }); + SuggestionStyle::ShowAlways, + ); self } @@ -369,17 +383,13 @@ impl Diagnostic { pub fn span_suggestion_short( &mut self, sp: Span, msg: &str, suggestion: String, applicability: Applicability ) -> &mut Self { - self.suggestions.push(CodeSuggestion { - substitutions: vec![Substitution { - parts: vec![SubstitutionPart { - snippet: suggestion, - span: sp, - }], - }], - msg: msg.to_owned(), - style: SuggestionStyle::HideCodeInline, + self.span_suggestion_with_style( + sp, + msg, + suggestion, applicability, - }); + SuggestionStyle::HideCodeInline, + ); self } @@ -392,17 +402,13 @@ impl Diagnostic { pub fn span_suggestion_hidden( &mut self, sp: Span, msg: &str, suggestion: String, applicability: Applicability ) -> &mut Self { - self.suggestions.push(CodeSuggestion { - substitutions: vec![Substitution { - parts: vec![SubstitutionPart { - snippet: suggestion, - span: sp, - }], - }], - msg: msg.to_owned(), - style: SuggestionStyle::HideCodeAlways, + self.span_suggestion_with_style( + sp, + msg, + suggestion, applicability, - }); + SuggestionStyle::HideCodeAlways, + ); self } @@ -413,17 +419,13 @@ impl Diagnostic { pub fn tool_only_span_suggestion( &mut self, sp: Span, msg: &str, suggestion: String, applicability: Applicability ) -> &mut Self { - self.suggestions.push(CodeSuggestion { - substitutions: vec![Substitution { - parts: vec![SubstitutionPart { - snippet: suggestion, - span: sp, - }], - }], - msg: msg.to_owned(), - style: SuggestionStyle::CompletelyHidden, + self.span_suggestion_with_style( + sp, + msg, + suggestion, applicability, - }); + SuggestionStyle::CompletelyHidden, + ); self } diff --git a/src/librustc_errors/emitter.rs b/src/librustc_errors/emitter.rs index bd8191065eeca..54b0353d992fb 100644 --- a/src/librustc_errors/emitter.rs +++ b/src/librustc_errors/emitter.rs @@ -218,12 +218,14 @@ pub trait Emitter { sugg.msg.split_whitespace().count() < 10 && // don't display multiline suggestions as labels !sugg.substitutions[0].parts[0].snippet.contains('\n') && - // when this style is set we want the suggestion to be a message, not inline - sugg.style != SuggestionStyle::HideCodeAlways && - // trivial suggestion for tooling's sake, never shown - sugg.style != SuggestionStyle::CompletelyHidden && - // subtle suggestion, never shown inline - sugg.style != SuggestionStyle::ShowAlways + ![ + // when this style is set we want the suggestion to be a message, not inline + SuggestionStyle::HideCodeAlways, + // trivial suggestion for tooling's sake, never shown + SuggestionStyle::CompletelyHidden, + // subtle suggestion, never shown inline + SuggestionStyle::ShowAlways, + ].contains(&sugg.style) { let substitution = &sugg.substitutions[0].parts[0].snippet.trim(); let msg = if substitution.len() == 0 || sugg.style.hide_inline() { From 2d87bace9687957f37e641ced1613c8b7cca3579 Mon Sep 17 00:00:00 2001 From: csmoe Date: Thu, 3 Oct 2019 21:02:06 +0800 Subject: [PATCH 13/23] replace GeneratorSubsts with SubstsRef --- src/librustc/ty/sty.rs | 2 +- src/librustc/ty/subst.rs | 10 +++++++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs index 3f09bf749edc8..c1589b31de78a 100644 --- a/src/librustc/ty/sty.rs +++ b/src/librustc/ty/sty.rs @@ -163,7 +163,7 @@ pub enum TyKind<'tcx> { /// The anonymous type of a generator. Used to represent the type of /// `|a| yield a`. - Generator(DefId, GeneratorSubsts<'tcx>, hir::GeneratorMovability), + Generator(DefId, SubstsRef<'tcx>, hir::GeneratorMovability), /// A type representin the types stored inside a generator. /// This should only appear in GeneratorInteriors. diff --git a/src/librustc/ty/subst.rs b/src/librustc/ty/subst.rs index 537192b0a2e58..de98c098ea539 100644 --- a/src/librustc/ty/subst.rs +++ b/src/librustc/ty/subst.rs @@ -5,7 +5,7 @@ use crate::infer::canonical::Canonical; use crate::ty::{self, Lift, List, Ty, TyCtxt, InferConst, ParamConst}; use crate::ty::fold::{TypeFoldable, TypeFolder, TypeVisitor}; use crate::mir::interpret::ConstValue; -use crate::ty::sty::ClosureSubsts; +use crate::ty::sty::{ClosureSubsts, GeneratorSubsts}; use rustc_serialize::{self, Encodable, Encoder, Decodable, Decoder}; use syntax_pos::{Span, DUMMY_SP}; @@ -194,6 +194,14 @@ impl<'a, 'tcx> InternalSubsts<'tcx> { } } + /// Interpret these substitutions as the substitutions of a generator type. + /// Closure substitutions have a particular structure controlled by the + /// compiler that encodes information like the signature and generator kind; + /// see `ty::GeneratorSubsts` struct for more comments. + pub fn as_generator(&'a self) -> GeneratorSubsts<'a> { + GeneratorSubsts { substs: self } + } + /// Creates a `InternalSubsts` that maps each generic parameter to itself. pub fn identity_for_item(tcx: TyCtxt<'tcx>, def_id: DefId) -> SubstsRef<'tcx> { Self::for_item(tcx, def_id, |param, _| { From fa7a87be638e4bcf0403f56413e6dbf9892e5582 Mon Sep 17 00:00:00 2001 From: csmoe Date: Thu, 3 Oct 2019 21:21:28 +0800 Subject: [PATCH 14/23] generate GeneratorSubsts from SubstsRef --- src/librustc/infer/opaque_types/mod.rs | 8 ++++---- src/librustc/mir/tcx.rs | 2 +- src/librustc/traits/select.rs | 11 ++++++----- src/librustc/ty/context.rs | 2 +- src/librustc/ty/flags.rs | 2 +- src/librustc/ty/instance.rs | 2 +- src/librustc/ty/layout.rs | 15 +++++++-------- src/librustc/ty/outlives.rs | 2 +- src/librustc/ty/print/obsolete.rs | 2 +- src/librustc/ty/print/pretty.rs | 4 ++-- src/librustc/ty/sty.rs | 7 ++++--- src/librustc/ty/walk.rs | 6 ++---- 12 files changed, 31 insertions(+), 32 deletions(-) diff --git a/src/librustc/infer/opaque_types/mod.rs b/src/librustc/infer/opaque_types/mod.rs index e7205dd47a617..d45869ed160c2 100644 --- a/src/librustc/infer/opaque_types/mod.rs +++ b/src/librustc/infer/opaque_types/mod.rs @@ -733,12 +733,12 @@ where // Skip lifetime parameters of the enclosing item(s) // Also skip the witness type, because that has no free regions. - for upvar_ty in substs.upvar_tys(def_id, self.tcx) { + for upvar_ty in substs.as_generator().upvar_tys(def_id, self.tcx) { upvar_ty.visit_with(self); } - substs.return_ty(def_id, self.tcx).visit_with(self); - substs.yield_ty(def_id, self.tcx).visit_with(self); + substs.as_generator().return_ty(def_id, self.tcx).visit_with(self); + substs.as_generator().yield_ty(def_id, self.tcx).visit_with(self); } _ => { ty.super_visit_with(self); @@ -902,7 +902,7 @@ impl TypeFolder<'tcx> for ReverseMapper<'tcx> { ty::Generator(def_id, substs, movability) => { let generics = self.tcx.generics_of(def_id); let substs = - self.tcx.mk_substs(substs.substs.iter().enumerate().map(|(index, &kind)| { + self.tcx.mk_substs(substs.iter().enumerate().map(|(index, &kind)| { if index < generics.parent_count { // Accommodate missing regions in the parent kinds... self.fold_kind_mapping_missing_regions_to_empty(kind) diff --git a/src/librustc/mir/tcx.rs b/src/librustc/mir/tcx.rs index 26f718e858da8..e87aabf9a0566 100644 --- a/src/librustc/mir/tcx.rs +++ b/src/librustc/mir/tcx.rs @@ -197,7 +197,7 @@ impl<'tcx> Rvalue<'tcx> { let ty = place.ty(local_decls, tcx).ty; match ty.kind { ty::Adt(adt_def, _) => adt_def.repr.discr_type().to_ty(tcx), - ty::Generator(_, substs, _) => substs.discr_ty(tcx), + ty::Generator(_, substs, _) => substs.as_generator().discr_ty(tcx), _ => { // This can only be `0`, for now, so `u8` will suffice. tcx.types.u8 diff --git a/src/librustc/traits/select.rs b/src/librustc/traits/select.rs index 1fae2a2fe8dbf..4ee5700f43fe1 100644 --- a/src/librustc/traits/select.rs +++ b/src/librustc/traits/select.rs @@ -2761,8 +2761,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { .collect(), ty::Generator(def_id, ref substs, _) => { - let witness = substs.witness(def_id, self.tcx()); + let witness = substs.as_generator().witness(def_id, self.tcx()); substs + .as_generator() .upvar_tys(def_id, self.tcx()) .chain(iter::once(witness)) .collect() @@ -3324,8 +3325,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { )?); Ok(VtableGeneratorData { - generator_def_id: generator_def_id, - substs: substs.clone(), + generator_def_id, + substs, nested: obligations, }) } @@ -3911,9 +3912,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { &mut self, obligation: &TraitObligation<'tcx>, closure_def_id: DefId, - substs: ty::GeneratorSubsts<'tcx>, + substs: SubstsRef<'tcx>, ) -> ty::PolyTraitRef<'tcx> { - let gen_sig = substs.poly_sig(closure_def_id, self.tcx()); + let gen_sig = substs.as_generator().poly_sig(closure_def_id, self.tcx()); // (1) Feels icky to skip the binder here, but OTOH we know // that the self-type is an generator type and hence is diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index 5aad6c1dc1832..48820540ebebd 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -2510,7 +2510,7 @@ impl<'tcx> TyCtxt<'tcx> { #[inline] pub fn mk_generator(self, id: DefId, - generator_substs: GeneratorSubsts<'tcx>, + generator_substs: SubstsRef<'tcx>, movability: hir::GeneratorMovability) -> Ty<'tcx> { self.mk_ty(Generator(id, generator_substs, movability)) diff --git a/src/librustc/ty/flags.rs b/src/librustc/ty/flags.rs index b513ef5a96670..4ff5e1a7b8de2 100644 --- a/src/librustc/ty/flags.rs +++ b/src/librustc/ty/flags.rs @@ -94,7 +94,7 @@ impl FlagComputation { &ty::Generator(_, ref substs, _) => { self.add_flags(TypeFlags::HAS_TY_CLOSURE); self.add_flags(TypeFlags::HAS_FREE_LOCAL_NAMES); - self.add_substs(&substs.substs); + self.add_substs(substs); } &ty::GeneratorWitness(ref ts) => { diff --git a/src/librustc/ty/instance.rs b/src/librustc/ty/instance.rs index 34f806b15c0c6..241b00a2dc402 100644 --- a/src/librustc/ty/instance.rs +++ b/src/librustc/ty/instance.rs @@ -71,7 +71,7 @@ impl<'tcx> Instance<'tcx> { )) } ty::Generator(def_id, substs, _) => { - let sig = substs.poly_sig(def_id, tcx); + let sig = substs.as_generator().poly_sig(def_id, tcx); let env_region = ty::ReLateBound(ty::INNERMOST, ty::BrEnv); let env_ty = tcx.mk_mut_ref(tcx.mk_region(env_region), ty); diff --git a/src/librustc/ty/layout.rs b/src/librustc/ty/layout.rs index 6e01e1bf26a53..2e6e2f012de96 100644 --- a/src/librustc/ty/layout.rs +++ b/src/librustc/ty/layout.rs @@ -1,5 +1,5 @@ use crate::session::{self, DataTypeKind}; -use crate::ty::{self, Ty, TyCtxt, TypeFoldable, ReprOptions}; +use crate::ty::{self, Ty, TyCtxt, TypeFoldable, ReprOptions, subst::SubstsRef}; use syntax::ast::{self, Ident, IntTy, UintTy}; use syntax::attr; @@ -15,7 +15,6 @@ use std::ops::Bound; use crate::hir; use crate::ich::StableHashingContext; use crate::mir::{GeneratorLayout, GeneratorSavedLocal}; -use crate::ty::GeneratorSubsts; use crate::ty::subst::Subst; use rustc_index::bit_set::BitSet; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; @@ -671,7 +670,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { tcx.intern_layout(unit) } - ty::Generator(def_id, substs, _) => self.generator_layout(ty, def_id, &substs)?, + ty::Generator(def_id, substs, _) => self.generator_layout(ty, def_id, substs)?, ty::Closure(def_id, ref substs) => { let tys = substs.as_closure().upvar_tys(def_id, tcx); @@ -1406,7 +1405,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { &self, ty: Ty<'tcx>, def_id: hir::def_id::DefId, - substs: &GeneratorSubsts<'tcx>, + substs: SubstsRef<'tcx>, ) -> Result<&'tcx LayoutDetails, LayoutError<'tcx>> { use SavedLocalEligibility::*; let tcx = self.tcx; @@ -1419,9 +1418,9 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { // Build a prefix layout, including "promoting" all ineligible // locals as part of the prefix. We compute the layout of all of // these fields at once to get optimal packing. - let discr_index = substs.prefix_tys(def_id, tcx).count(); + let discr_index = substs.as_generator().prefix_tys(def_id, tcx).count(); // FIXME(eddyb) set the correct vaidity range for the discriminant. - let discr_layout = self.layout_of(substs.discr_ty(tcx))?; + let discr_layout = self.layout_of(substs.as_generator().discr_ty(tcx))?; let discr = match &discr_layout.abi { Abi::Scalar(s) => s.clone(), _ => bug!(), @@ -2153,7 +2152,7 @@ where ty::Generator(def_id, ref substs, _) => { match this.variants { Variants::Single { index } => { - substs.state_tys(def_id, tcx) + substs.as_generator().state_tys(def_id, tcx) .nth(index.as_usize()).unwrap() .nth(i).unwrap() } @@ -2161,7 +2160,7 @@ where if i == discr_index { return discr_layout(discr); } - substs.prefix_tys(def_id, tcx).nth(i).unwrap() + substs.as_generator().prefix_tys(def_id, tcx).nth(i).unwrap() } } } diff --git a/src/librustc/ty/outlives.rs b/src/librustc/ty/outlives.rs index 3ea767d511598..80e77cdfad0b6 100644 --- a/src/librustc/ty/outlives.rs +++ b/src/librustc/ty/outlives.rs @@ -69,7 +69,7 @@ impl<'tcx> TyCtxt<'tcx> { ty::Generator(def_id, ref substs, _) => { // Same as the closure case - for upvar_ty in substs.upvar_tys(def_id, *self) { + for upvar_ty in substs.as_generator().upvar_tys(def_id, *self) { self.compute_components(upvar_ty, out); } diff --git a/src/librustc/ty/print/obsolete.rs b/src/librustc/ty/print/obsolete.rs index 21c018d9ee6de..3855e9e9b8a5a 100644 --- a/src/librustc/ty/print/obsolete.rs +++ b/src/librustc/ty/print/obsolete.rs @@ -154,7 +154,7 @@ impl DefPathBasedNames<'tcx> { self.push_type_name(sig.output(), output, debug); } } - ty::Generator(def_id, GeneratorSubsts { substs }, _) + ty::Generator(def_id, substs, _) | ty::Closure(def_id, substs) => { self.push_def_path(def_id, output); let generics = self.tcx.generics_of(self.tcx.closure_base_def_id(def_id)); diff --git a/src/librustc/ty/print/pretty.rs b/src/librustc/ty/print/pretty.rs index ad4be788dae4e..732638929963d 100644 --- a/src/librustc/ty/print/pretty.rs +++ b/src/librustc/ty/print/pretty.rs @@ -605,8 +605,8 @@ pub trait PrettyPrinter<'tcx>: } ty::Str => p!(write("str")), ty::Generator(did, substs, movability) => { - let upvar_tys = substs.upvar_tys(did, self.tcx()); - let witness = substs.witness(did, self.tcx()); + let upvar_tys = substs.as_generator().upvar_tys(did, self.tcx()); + let witness = substs.as_generator().witness(did, self.tcx()); if movability == hir::GeneratorMovability::Movable { p!(write("[generator")); } else { diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs index c1589b31de78a..ff20996df56ff 100644 --- a/src/librustc/ty/sty.rs +++ b/src/librustc/ty/sty.rs @@ -2109,7 +2109,8 @@ impl<'tcx> TyS<'tcx> { pub fn variant_range(&self, tcx: TyCtxt<'tcx>) -> Option> { match self.kind { TyKind::Adt(adt, _) => Some(adt.variant_range()), - TyKind::Generator(def_id, substs, _) => Some(substs.variant_range(def_id, tcx)), + TyKind::Generator(def_id, substs, _) => + Some(substs.assert_generator().variant_range(def_id, tcx)), _ => None, } } @@ -2126,7 +2127,7 @@ impl<'tcx> TyS<'tcx> { match self.kind { TyKind::Adt(adt, _) => Some(adt.discriminant_for_variant(tcx, variant_index)), TyKind::Generator(def_id, substs, _) => - Some(substs.discriminant_for_variant(def_id, tcx, variant_index)), + Some(substs.as_generator().discriminant_for_variant(def_id, tcx, variant_index)), _ => None, } } @@ -2149,7 +2150,7 @@ impl<'tcx> TyS<'tcx> { out.extend(substs.regions()) } Closure(_, ref substs ) | - Generator(_, GeneratorSubsts { ref substs }, _) => { + Generator(_, ref substs, _) => { out.extend(substs.regions()) } Projection(ref data) | UnnormalizedProjection(ref data) => { diff --git a/src/librustc/ty/walk.rs b/src/librustc/ty/walk.rs index 1895ab83674eb..f5b1902e3cc8c 100644 --- a/src/librustc/ty/walk.rs +++ b/src/librustc/ty/walk.rs @@ -110,12 +110,10 @@ fn push_subtypes<'tcx>(stack: &mut TypeWalkerStack<'tcx>, parent_ty: Ty<'tcx>) { ty::Adt(_, substs) | ty::Opaque(_, substs) => { stack.extend(substs.types().rev()); } - ty::Closure(_, ref substs) => { + ty::Closure(_, ref substs) + | ty::Generator(_, ref substs, _) => { stack.extend(substs.types().rev()); } - ty::Generator(_, ref substs, _) => { - stack.extend(substs.substs.types().rev()); - } ty::GeneratorWitness(ts) => { stack.extend(ts.skip_binder().iter().cloned().rev()); } From 774ea808be4bcab4e605635b383ce4c5c9d7742f Mon Sep 17 00:00:00 2001 From: csmoe Date: Thu, 3 Oct 2019 21:28:04 +0800 Subject: [PATCH 15/23] replace GeneratorSubsts inside related types --- src/librustc/infer/opaque_types/mod.rs | 2 +- src/librustc/mir/mod.rs | 4 ++-- src/librustc/traits/mod.rs | 2 +- src/librustc/ty/context.rs | 2 +- src/librustc/ty/layout.rs | 4 ++-- src/librustc/ty/print/obsolete.rs | 2 +- src/librustc/ty/sty.rs | 2 +- 7 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/librustc/infer/opaque_types/mod.rs b/src/librustc/infer/opaque_types/mod.rs index d45869ed160c2..bd19a002fe8b7 100644 --- a/src/librustc/infer/opaque_types/mod.rs +++ b/src/librustc/infer/opaque_types/mod.rs @@ -912,7 +912,7 @@ impl TypeFolder<'tcx> for ReverseMapper<'tcx> { } })); - self.tcx.mk_generator(def_id, ty::GeneratorSubsts { substs }, movability) + self.tcx.mk_generator(def_id, substs, movability) } ty::Param(..) => { diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs index 59b4f24073398..2b5212cb7efaa 100644 --- a/src/librustc/mir/mod.rs +++ b/src/librustc/mir/mod.rs @@ -15,7 +15,7 @@ use crate::ty::layout::VariantIdx; use crate::ty::print::{FmtPrinter, Printer}; use crate::ty::subst::{Subst, SubstsRef}; use crate::ty::{ - self, AdtDef, CanonicalUserTypeAnnotations, GeneratorSubsts, Region, Ty, TyCtxt, + self, AdtDef, CanonicalUserTypeAnnotations, Region, Ty, TyCtxt, UserTypeAnnotationIndex, }; @@ -2189,7 +2189,7 @@ pub enum AggregateKind<'tcx> { Adt(&'tcx AdtDef, VariantIdx, SubstsRef<'tcx>, Option, Option), Closure(DefId, SubstsRef<'tcx>), - Generator(DefId, GeneratorSubsts<'tcx>, hir::GeneratorMovability), + Generator(DefId, SubstsRef<'tcx>, hir::GeneratorMovability), } #[derive(Copy, Clone, Debug, PartialEq, Eq, RustcEncodable, RustcDecodable, HashStable)] diff --git a/src/librustc/traits/mod.rs b/src/librustc/traits/mod.rs index 7f194c2fbbc0f..d96330bf0a9b4 100644 --- a/src/librustc/traits/mod.rs +++ b/src/librustc/traits/mod.rs @@ -610,7 +610,7 @@ pub struct VtableImplData<'tcx, N> { #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, HashStable)] pub struct VtableGeneratorData<'tcx, N> { pub generator_def_id: DefId, - pub substs: ty::GeneratorSubsts<'tcx>, + pub substs: SubstsRef<'tcx>, /// Nested obligations. This can be non-empty if the generator /// signature contains associated types. pub nested: Vec diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index 48820540ebebd..eb380eb12d8e7 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -29,7 +29,7 @@ use crate::traits; use crate::traits::{Clause, Clauses, GoalKind, Goal, Goals}; use crate::ty::{self, DefIdTree, Ty, TypeAndMut}; use crate::ty::{TyS, TyKind, List}; -use crate::ty::{AdtKind, AdtDef, GeneratorSubsts, Region, Const}; +use crate::ty::{AdtKind, AdtDef, Region, Const}; use crate::ty::{PolyFnSig, InferTy, ParamTy, ProjectionTy, ExistentialPredicate, Predicate}; use crate::ty::RegionKind; use crate::ty::{TyVar, TyVid, IntVar, IntVid, FloatVar, FloatVid, ConstVid}; diff --git a/src/librustc/ty/layout.rs b/src/librustc/ty/layout.rs index 2e6e2f012de96..ce7e1822d9ab5 100644 --- a/src/librustc/ty/layout.rs +++ b/src/librustc/ty/layout.rs @@ -1410,7 +1410,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { use SavedLocalEligibility::*; let tcx = self.tcx; - let subst_field = |ty: Ty<'tcx>| { ty.subst(tcx, substs.substs) }; + let subst_field = |ty: Ty<'tcx>| { ty.subst(tcx, substs) }; let info = tcx.generator_layout(def_id); let (ineligible_locals, assignments) = self.generator_saved_local_eligibility(&info); @@ -1429,7 +1429,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { .map(|local| subst_field(info.field_tys[local])) .map(|ty| tcx.mk_maybe_uninit(ty)) .map(|ty| self.layout_of(ty)); - let prefix_layouts = substs.prefix_tys(def_id, tcx) + let prefix_layouts = substs.as_generator().prefix_tys(def_id, tcx) .map(|ty| self.layout_of(ty)) .chain(iter::once(Ok(discr_layout))) .chain(promoted_layouts) diff --git a/src/librustc/ty/print/obsolete.rs b/src/librustc/ty/print/obsolete.rs index 3855e9e9b8a5a..df39d0ccc9eed 100644 --- a/src/librustc/ty/print/obsolete.rs +++ b/src/librustc/ty/print/obsolete.rs @@ -8,7 +8,7 @@ use rustc::hir::def_id::DefId; use rustc::mir::interpret::ConstValue; use rustc::ty::subst::SubstsRef; -use rustc::ty::{self, Const, GeneratorSubsts, Instance, Ty, TyCtxt}; +use rustc::ty::{self, Const, Instance, Ty, TyCtxt}; use rustc::{bug, hir}; use std::fmt::Write; use std::iter; diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs index ff20996df56ff..54b6fbe7c218c 100644 --- a/src/librustc/ty/sty.rs +++ b/src/librustc/ty/sty.rs @@ -2110,7 +2110,7 @@ impl<'tcx> TyS<'tcx> { match self.kind { TyKind::Adt(adt, _) => Some(adt.variant_range()), TyKind::Generator(def_id, substs, _) => - Some(substs.assert_generator().variant_range(def_id, tcx)), + Some(substs.as_generator().variant_range(def_id, tcx)), _ => None, } } From ef9fe102800406ff5132344b43fcf6472cab7d2d Mon Sep 17 00:00:00 2001 From: csmoe Date: Thu, 3 Oct 2019 21:30:26 +0800 Subject: [PATCH 16/23] remove GeneratorSubsts visitors --- src/librustc/mir/visit.rs | 14 ++------------ src/librustc/traits/project.rs | 2 +- src/librustc/ty/instance.rs | 2 +- 3 files changed, 4 insertions(+), 14 deletions(-) diff --git a/src/librustc/mir/visit.rs b/src/librustc/mir/visit.rs index ed8086b8fafec..edc7922f46eec 100644 --- a/src/librustc/mir/visit.rs +++ b/src/librustc/mir/visit.rs @@ -1,5 +1,5 @@ use crate::ty::subst::SubstsRef; -use crate::ty::{CanonicalUserTypeAnnotation, GeneratorSubsts, Ty}; +use crate::ty::{CanonicalUserTypeAnnotation, Ty}; use crate::mir::*; use syntax_pos::Span; @@ -230,12 +230,6 @@ macro_rules! make_mir_visitor { self.super_substs(substs); } - fn visit_generator_substs(&mut self, - substs: & $($mutability)? GeneratorSubsts<'tcx>, - _: Location) { - self.super_generator_substs(substs); - } - fn visit_local_decl(&mut self, local: Local, local_decl: & $($mutability)? LocalDecl<'tcx>) { @@ -628,7 +622,7 @@ macro_rules! make_mir_visitor { generator_substs, _movability, ) => { - self.visit_generator_substs(generator_substs, location); + self.visit_substs(generator_substs, location); } } @@ -846,10 +840,6 @@ macro_rules! make_mir_visitor { fn super_substs(&mut self, _substs: & $($mutability)? SubstsRef<'tcx>) { } - fn super_generator_substs(&mut self, - _substs: & $($mutability)? GeneratorSubsts<'tcx>) { - } - // Convenience methods fn visit_location(&mut self, body: & $($mutability)? Body<'tcx>, location: Location) { diff --git a/src/librustc/traits/project.rs b/src/librustc/traits/project.rs index a7bb29c699e0e..5b4ec885d7785 100644 --- a/src/librustc/traits/project.rs +++ b/src/librustc/traits/project.rs @@ -1259,7 +1259,7 @@ fn confirm_generator_candidate<'cx, 'tcx>( obligation: &ProjectionTyObligation<'tcx>, vtable: VtableGeneratorData<'tcx, PredicateObligation<'tcx>>, ) -> Progress<'tcx> { - let gen_sig = vtable.substs.poly_sig(vtable.generator_def_id, selcx.tcx()); + let gen_sig = vtable.substs.as_generator().poly_sig(vtable.generator_def_id, selcx.tcx()); let Normalized { value: gen_sig, obligations diff --git a/src/librustc/ty/instance.rs b/src/librustc/ty/instance.rs index 241b00a2dc402..93a8341e74628 100644 --- a/src/librustc/ty/instance.rs +++ b/src/librustc/ty/instance.rs @@ -395,7 +395,7 @@ fn resolve_associated_item<'tcx>( traits::VtableGenerator(generator_data) => { Some(Instance { def: ty::InstanceDef::Item(generator_data.generator_def_id), - substs: generator_data.substs.substs + substs: generator_data.substs }) } traits::VtableClosure(closure_data) => { From afc0bb9794bfcbc9864a1d195ac34b892727f9e4 Mon Sep 17 00:00:00 2001 From: csmoe Date: Thu, 3 Oct 2019 21:51:30 +0800 Subject: [PATCH 17/23] clean up GeneratorSubsts --- src/librustc/ty/sty.rs | 8 ++++---- src/librustc/ty/subst.rs | 2 +- .../debuginfo/metadata.rs | 18 ++++++++++-------- src/librustc_codegen_llvm/type_of.rs | 2 +- src/librustc_codegen_ssa/mir/mod.rs | 2 +- .../symbol_names/legacy.rs | 2 +- src/librustc_codegen_utils/symbol_names/v0.rs | 2 +- .../borrow_check/nll/constraint_generation.rs | 9 +-------- src/librustc_mir/borrow_check/nll/renumber.rs | 16 +--------------- .../borrow_check/nll/type_check/mod.rs | 14 +++++++------- .../borrow_check/nll/universal_regions.rs | 14 +++++++------- src/librustc_mir/build/mod.rs | 2 +- .../interpret/intrinsics/type_name.rs | 3 +-- src/librustc_mir/interpret/operand.rs | 12 ++++++++---- src/librustc_mir/shim.rs | 2 +- src/librustc_mir/transform/generator.rs | 1 + src/librustc_mir/util/elaborate_drops.rs | 2 +- src/librustc_traits/dropck_outlives.rs | 2 +- src/librustc_traits/generic_types.rs | 8 +++++--- src/librustc_typeck/check/closure.rs | 8 ++++---- 20 files changed, 58 insertions(+), 71 deletions(-) diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs index 54b6fbe7c218c..e27236b47e07f 100644 --- a/src/librustc/ty/sty.rs +++ b/src/librustc/ty/sty.rs @@ -512,7 +512,7 @@ impl<'tcx> GeneratorSubsts<'tcx> { /// variant indices. #[inline] pub fn discriminants( - &'tcx self, + self, def_id: DefId, tcx: TyCtxt<'tcx>, ) -> impl Iterator)> + Captures<'tcx> { @@ -524,7 +524,7 @@ impl<'tcx> GeneratorSubsts<'tcx> { /// Calls `f` with a reference to the name of the enumerator for the given /// variant `v`. #[inline] - pub fn variant_name(&self, v: VariantIdx) -> Cow<'static, str> { + pub fn variant_name(self, v: VariantIdx) -> Cow<'static, str> { match v.as_usize() { Self::UNRESUMED => Cow::from(Self::UNRESUMED_NAME), Self::RETURNED => Cow::from(Self::RETURNED_NAME), @@ -570,7 +570,7 @@ impl<'tcx> GeneratorSubsts<'tcx> { #[derive(Debug, Copy, Clone)] pub enum UpvarSubsts<'tcx> { Closure(SubstsRef<'tcx>), - Generator(GeneratorSubsts<'tcx>), + Generator(SubstsRef<'tcx>), } impl<'tcx> UpvarSubsts<'tcx> { @@ -582,7 +582,7 @@ impl<'tcx> UpvarSubsts<'tcx> { ) -> impl Iterator> + 'tcx { let upvar_kinds = match self { UpvarSubsts::Closure(substs) => substs.as_closure().split(def_id, tcx).upvar_kinds, - UpvarSubsts::Generator(substs) => substs.split(def_id, tcx).upvar_kinds, + UpvarSubsts::Generator(substs) => substs.as_generator().split(def_id, tcx).upvar_kinds, }; upvar_kinds.iter().map(|t| { if let GenericArgKind::Type(ty) = t.unpack() { diff --git a/src/librustc/ty/subst.rs b/src/librustc/ty/subst.rs index de98c098ea539..7c5daaf14d784 100644 --- a/src/librustc/ty/subst.rs +++ b/src/librustc/ty/subst.rs @@ -198,7 +198,7 @@ impl<'a, 'tcx> InternalSubsts<'tcx> { /// Closure substitutions have a particular structure controlled by the /// compiler that encodes information like the signature and generator kind; /// see `ty::GeneratorSubsts` struct for more comments. - pub fn as_generator(&'a self) -> GeneratorSubsts<'a> { + pub fn as_generator(&'tcx self) -> GeneratorSubsts<'tcx> { GeneratorSubsts { substs: self } } diff --git a/src/librustc_codegen_llvm/debuginfo/metadata.rs b/src/librustc_codegen_llvm/debuginfo/metadata.rs index e69f4b6aca19a..14e4c4adfaa97 100644 --- a/src/librustc_codegen_llvm/debuginfo/metadata.rs +++ b/src/librustc_codegen_llvm/debuginfo/metadata.rs @@ -30,7 +30,7 @@ use rustc::ty::Instance; use rustc::ty::{self, AdtKind, ParamEnv, Ty, TyCtxt}; use rustc::ty::layout::{self, Align, Integer, IntegerExt, LayoutOf, PrimitiveExt, Size, TyLayout, VariantIdx}; -use rustc::ty::subst::GenericArgKind; +use rustc::ty::subst::{GenericArgKind, SubstsRef}; use rustc::session::config::{self, DebugInfo}; use rustc::util::nodemap::FxHashMap; use rustc_fs_util::path_to_c_string; @@ -692,9 +692,10 @@ pub fn type_metadata( Some(containing_scope)).finalize(cx) } ty::Generator(def_id, substs, _) => { - let upvar_tys : Vec<_> = substs.prefix_tys(def_id, cx.tcx).map(|t| { - cx.tcx.normalize_erasing_regions(ParamEnv::reveal_all(), t) - }).collect(); + let upvar_tys : Vec<_> = substs + .as_generator().prefix_tys(def_id, cx.tcx).map(|t| { + cx.tcx.normalize_erasing_regions(ParamEnv::reveal_all(), t) + }).collect(); prepare_enum_metadata(cx, t, def_id, @@ -1338,7 +1339,7 @@ impl EnumMemberDescriptionFactory<'ll, 'tcx> { ty::Adt(adt, _) => VariantInfo::Adt(&adt.variants[index]), ty::Generator(def_id, substs, _) => { let generator_layout = cx.tcx.generator_layout(*def_id); - VariantInfo::Generator(*substs, generator_layout, index) + VariantInfo::Generator(substs, generator_layout, index) } _ => bug!(), } @@ -1611,7 +1612,7 @@ enum EnumDiscriminantInfo<'ll> { #[derive(Copy, Clone)] enum VariantInfo<'tcx> { Adt(&'tcx ty::VariantDef), - Generator(ty::GeneratorSubsts<'tcx>, &'tcx GeneratorLayout<'tcx>, VariantIdx), + Generator(SubstsRef<'tcx>, &'tcx GeneratorLayout<'tcx>, VariantIdx), } impl<'tcx> VariantInfo<'tcx> { @@ -1619,7 +1620,7 @@ impl<'tcx> VariantInfo<'tcx> { match self { VariantInfo::Adt(variant) => f(&variant.ident.as_str()), VariantInfo::Generator(substs, _, variant_index) => - f(&substs.variant_name(*variant_index)), + f(&substs.as_generator().variant_name(*variant_index)), } } @@ -1763,9 +1764,10 @@ fn prepare_enum_metadata( }) .collect(), ty::Generator(_, substs, _) => substs + .as_generator() .variant_range(enum_def_id, cx.tcx) .map(|variant_index| { - let name = SmallCStr::new(&substs.variant_name(variant_index)); + let name = SmallCStr::new(&substs.as_generator().variant_name(variant_index)); unsafe { Some(llvm::LLVMRustDIBuilderCreateEnumerator( DIB(cx), diff --git a/src/librustc_codegen_llvm/type_of.rs b/src/librustc_codegen_llvm/type_of.rs index 81a99bc5019b3..d921bbc96adee 100644 --- a/src/librustc_codegen_llvm/type_of.rs +++ b/src/librustc_codegen_llvm/type_of.rs @@ -65,7 +65,7 @@ fn uncached_llvm_type<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, if let (&ty::Generator(_, substs, _), &layout::Variants::Single { index }) = (&layout.ty.kind, &layout.variants) { - write!(&mut name, "::{}", substs.variant_name(index)).unwrap(); + write!(&mut name, "::{}", substs.as_generator().variant_name(index)).unwrap(); } Some(name) } diff --git a/src/librustc_codegen_ssa/mir/mod.rs b/src/librustc_codegen_ssa/mir/mod.rs index 5787447d6230f..9d2f8b42c704f 100644 --- a/src/librustc_codegen_ssa/mir/mod.rs +++ b/src/librustc_codegen_ssa/mir/mod.rs @@ -636,7 +636,7 @@ fn arg_local_refs<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( ty::Generator(def_id, substs, _) => (def_id, substs), _ => bug!("generator layout without generator substs"), }; - let state_tys = gen_substs.state_tys(def_id, tcx); + let state_tys = gen_substs.as_generator().state_tys(def_id, tcx); generator_layout.variant_fields.iter() .zip(state_tys) diff --git a/src/librustc_codegen_utils/symbol_names/legacy.rs b/src/librustc_codegen_utils/symbol_names/legacy.rs index 5bcb3b4ceb3ba..cf575c54293c7 100644 --- a/src/librustc_codegen_utils/symbol_names/legacy.rs +++ b/src/librustc_codegen_utils/symbol_names/legacy.rs @@ -225,7 +225,7 @@ impl Printer<'tcx> for SymbolPrinter<'tcx> { ty::Projection(ty::ProjectionTy { item_def_id: def_id, substs }) | ty::UnnormalizedProjection(ty::ProjectionTy { item_def_id: def_id, substs }) | ty::Closure(def_id, substs) | - ty::Generator(def_id, ty::GeneratorSubsts { substs }, _) => { + ty::Generator(def_id, substs, _) => { self.print_def_path(def_id, substs) } _ => self.pretty_print_type(ty), diff --git a/src/librustc_codegen_utils/symbol_names/v0.rs b/src/librustc_codegen_utils/symbol_names/v0.rs index 2ad699d7c6f08..55b148fceb217 100644 --- a/src/librustc_codegen_utils/symbol_names/v0.rs +++ b/src/librustc_codegen_utils/symbol_names/v0.rs @@ -415,7 +415,7 @@ impl Printer<'tcx> for SymbolMangler<'tcx> { ty::Projection(ty::ProjectionTy { item_def_id: def_id, substs }) | ty::UnnormalizedProjection(ty::ProjectionTy { item_def_id: def_id, substs }) | ty::Closure(def_id, substs) | - ty::Generator(def_id, ty::GeneratorSubsts { substs }, _) => { + ty::Generator(def_id, substs, _) => { self = self.print_def_path(def_id, substs)?; } ty::Foreign(def_id) => { diff --git a/src/librustc_mir/borrow_check/nll/constraint_generation.rs b/src/librustc_mir/borrow_check/nll/constraint_generation.rs index 0e22ead62d1c0..b105664399a5c 100644 --- a/src/librustc_mir/borrow_check/nll/constraint_generation.rs +++ b/src/librustc_mir/borrow_check/nll/constraint_generation.rs @@ -12,7 +12,7 @@ use rustc::mir::{ SourceInfo, Statement, StatementKind, Terminator, TerminatorKind, UserTypeProjection, }; use rustc::ty::fold::TypeFoldable; -use rustc::ty::{self, GeneratorSubsts, RegionVid, Ty}; +use rustc::ty::{self, RegionVid, Ty}; use rustc::ty::subst::SubstsRef; pub(super) fn generate_constraints<'cx, 'tcx>( @@ -91,13 +91,6 @@ impl<'cg, 'cx, 'tcx> Visitor<'tcx> for ConstraintGeneration<'cg, 'cx, 'tcx> { self.super_ty(ty); } - /// We sometimes have `generator_substs` within an rvalue, or within a - /// call. Make them live at the location where they appear. - fn visit_generator_substs(&mut self, substs: &GeneratorSubsts<'tcx>, location: Location) { - self.add_regular_live_constraint(*substs, location); - self.super_generator_substs(substs); - } - fn visit_statement( &mut self, statement: &Statement<'tcx>, diff --git a/src/librustc_mir/borrow_check/nll/renumber.rs b/src/librustc_mir/borrow_check/nll/renumber.rs index 014335711a511..88ad1fb129509 100644 --- a/src/librustc_mir/borrow_check/nll/renumber.rs +++ b/src/librustc_mir/borrow_check/nll/renumber.rs @@ -1,5 +1,5 @@ use rustc::ty::subst::SubstsRef; -use rustc::ty::{self, GeneratorSubsts, Ty, TypeFoldable}; +use rustc::ty::{self, Ty, TypeFoldable}; use rustc::mir::{Location, Body, Promoted}; use rustc::mir::visit::{MutVisitor, TyContext}; use rustc::infer::{InferCtxt, NLLRegionVariableOrigin}; @@ -82,18 +82,4 @@ impl<'a, 'tcx> MutVisitor<'tcx> for NLLVisitor<'a, 'tcx> { fn visit_const(&mut self, constant: &mut &'tcx ty::Const<'tcx>, _location: Location) { *constant = self.renumber_regions(&*constant); } - - fn visit_generator_substs(&mut self, - substs: &mut GeneratorSubsts<'tcx>, - location: Location) { - debug!( - "visit_generator_substs(substs={:?}, location={:?})", - substs, - location, - ); - - *substs = self.renumber_regions(substs); - - debug!("visit_generator_substs: substs={:?}", substs); - } } diff --git a/src/librustc_mir/borrow_check/nll/type_check/mod.rs b/src/librustc_mir/borrow_check/nll/type_check/mod.rs index f55889794c24d..1563a27250eb9 100644 --- a/src/librustc_mir/borrow_check/nll/type_check/mod.rs +++ b/src/librustc_mir/borrow_check/nll/type_check/mod.rs @@ -759,13 +759,13 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> { PlaceTy { ty, variant_index: Some(variant_index) } => match ty.kind { ty::Adt(adt_def, substs) => (&adt_def.variants[variant_index], substs), ty::Generator(def_id, substs, _) => { - let mut variants = substs.state_tys(def_id, tcx); + let mut variants = substs.as_generator().state_tys(def_id, tcx); let mut variant = match variants.nth(variant_index.into()) { Some(v) => v, None => { bug!("variant_index of generator out of range: {:?}/{:?}", variant_index, - substs.state_tys(def_id, tcx).count()) + substs.as_generator().state_tys(def_id, tcx).count()) } }; return match variant.nth(field.index()) { @@ -791,10 +791,10 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> { ty::Generator(def_id, substs, _) => { // Only prefix fields (upvars and current state) are // accessible without a variant index. - return match substs.prefix_tys(def_id, tcx).nth(field.index()) { + return match substs.as_generator().prefix_tys(def_id, tcx).nth(field.index()) { Some(ty) => Ok(ty), None => Err(FieldAccessError::OutOfRange { - field_count: substs.prefix_tys(def_id, tcx).count(), + field_count: substs.as_generator().prefix_tys(def_id, tcx).count(), }), } } @@ -1963,10 +1963,10 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { // It doesn't make sense to look at a field beyond the prefix; // these require a variant index, and are not initialized in // aggregate rvalues. - match substs.prefix_tys(def_id, tcx).nth(field_index) { + match substs.as_generator().prefix_tys(def_id, tcx).nth(field_index) { Some(ty) => Ok(ty), None => Err(FieldAccessError::OutOfRange { - field_count: substs.prefix_tys(def_id, tcx).count(), + field_count: substs.as_generator().prefix_tys(def_id, tcx).count(), }), } } @@ -2541,7 +2541,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { // these extra requirements are basically like where // clauses on the struct. AggregateKind::Closure(def_id, substs) - | AggregateKind::Generator(def_id, ty::GeneratorSubsts { substs }, _) => { + | AggregateKind::Generator(def_id, substs, _) => { self.prove_closure_bounds(tcx, *def_id, substs, location) } diff --git a/src/librustc_mir/borrow_check/nll/universal_regions.rs b/src/librustc_mir/borrow_check/nll/universal_regions.rs index e3efacff66a2f..5f6951856434e 100644 --- a/src/librustc_mir/borrow_check/nll/universal_regions.rs +++ b/src/librustc_mir/borrow_check/nll/universal_regions.rs @@ -19,7 +19,7 @@ use rustc::infer::{InferCtxt, NLLRegionVariableOrigin}; use rustc::middle::lang_items; use rustc::ty::fold::TypeFoldable; use rustc::ty::subst::{InternalSubsts, SubstsRef, Subst}; -use rustc::ty::{self, GeneratorSubsts, RegionVid, Ty, TyCtxt}; +use rustc::ty::{self, RegionVid, Ty, TyCtxt}; use rustc::util::nodemap::FxHashMap; use rustc_index::vec::{Idx, IndexVec}; use rustc_errors::DiagnosticBuilder; @@ -90,7 +90,7 @@ pub enum DefiningTy<'tcx> { /// The MIR is a generator. The signature is that generators take /// no parameters and return the result of /// `ClosureSubsts::generator_return_ty`. - Generator(DefId, ty::GeneratorSubsts<'tcx>, hir::GeneratorMovability), + Generator(DefId, SubstsRef<'tcx>, hir::GeneratorMovability), /// The MIR is a fn item with the given `DefId` and substs. The signature /// of the function can be bound then with the `fn_sig` query. @@ -113,7 +113,7 @@ impl<'tcx> DefiningTy<'tcx> { substs.as_closure().upvar_tys(def_id, tcx) ), DefiningTy::Generator(def_id, substs, _) => { - Either::Right(Either::Left(substs.upvar_tys(def_id, tcx))) + Either::Right(Either::Left(substs.as_generator().upvar_tys(def_id, tcx))) } DefiningTy::FnDef(..) | DefiningTy::Const(..) => { Either::Right(Either::Right(iter::empty())) @@ -334,7 +334,7 @@ impl<'tcx> UniversalRegions<'tcx> { err.note(&format!( "defining type: {:?} with generator substs {:#?}", def_id, - &substs.substs[..] + &substs[..] )); // FIXME: As above, we'd like to print out the region @@ -470,7 +470,7 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> { let yield_ty = match defining_ty { DefiningTy::Generator(def_id, substs, _) => { - Some(substs.yield_ty(def_id, self.infcx.tcx)) + Some(substs.as_generator().yield_ty(def_id, self.infcx.tcx)) } _ => None, }; @@ -549,7 +549,7 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> { let identity_substs = InternalSubsts::identity_for_item(tcx, closure_base_def_id); let fr_substs = match defining_ty { DefiningTy::Closure(_, ref substs) - | DefiningTy::Generator(_, GeneratorSubsts { ref substs }, _) => { + | DefiningTy::Generator(_, ref substs, _) => { // In the case of closures, we rely on the fact that // the first N elements in the ClosureSubsts are // inherited from the `closure_base_def_id`. @@ -612,7 +612,7 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> { DefiningTy::Generator(def_id, substs, movability) => { assert_eq!(self.mir_def_id, def_id); - let output = substs.return_ty(def_id, tcx); + let output = substs.as_generator().return_ty(def_id, tcx); let generator_ty = tcx.mk_generator(def_id, substs, movability); let inputs_and_output = self.infcx.tcx.intern_type_list(&[generator_ty, output]); ty::Binder::dummy(inputs_and_output) diff --git a/src/librustc_mir/build/mod.rs b/src/librustc_mir/build/mod.rs index 9c30d9509908b..6b6eac5add2fa 100644 --- a/src/librustc_mir/build/mod.rs +++ b/src/librustc_mir/build/mod.rs @@ -146,7 +146,7 @@ pub fn mir_build(tcx: TyCtxt<'_>, def_id: DefId) -> Body<'_> { let (yield_ty, return_ty) = if body.generator_kind.is_some() { let gen_sig = match ty.kind { ty::Generator(gen_def_id, gen_substs, ..) => - gen_substs.sig(gen_def_id, tcx), + gen_substs.as_generator().sig(gen_def_id, tcx), _ => span_bug!(tcx.hir().span(id), "generator w/o generator type: {:?}", ty), diff --git a/src/librustc_mir/interpret/intrinsics/type_name.rs b/src/librustc_mir/interpret/intrinsics/type_name.rs index dc3b7694c35c9..f9200f8c1c042 100644 --- a/src/librustc_mir/interpret/intrinsics/type_name.rs +++ b/src/librustc_mir/interpret/intrinsics/type_name.rs @@ -68,8 +68,7 @@ impl<'tcx> Printer<'tcx> for AbsolutePathPrinter<'tcx> { | ty::Projection(ty::ProjectionTy { item_def_id: def_id, substs }) | ty::UnnormalizedProjection(ty::ProjectionTy { item_def_id: def_id, substs }) | ty::Closure(def_id, substs) - | ty::Generator(def_id, ty::GeneratorSubsts { substs }, _) - => self.print_def_path(def_id, substs), + | ty::Generator(def_id, substs, _) => self.print_def_path(def_id, substs), ty::Foreign(def_id) => self.print_def_path(def_id, &[]), ty::GeneratorWitness(_) => { diff --git a/src/librustc_mir/interpret/operand.rs b/src/librustc_mir/interpret/operand.rs index 861e5ebef877d..4bdd71f9602ac 100644 --- a/src/librustc_mir/interpret/operand.rs +++ b/src/librustc_mir/interpret/operand.rs @@ -664,14 +664,18 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { bits_discr }; // Make sure we catch invalid discriminants - let index = match &rval.layout.ty.kind { + let index = match rval.layout.ty.kind { ty::Adt(adt, _) => adt .discriminants(self.tcx.tcx) .find(|(_, var)| var.val == real_discr), - ty::Generator(def_id, substs, _) => substs - .discriminants(*def_id, self.tcx.tcx) - .find(|(_, var)| var.val == real_discr), + ty::Generator(def_id, substs, _) => { + let substs = substs.as_generator(); + substs + .discriminants(def_id, self.tcx.tcx) + .find(|(_, var)| var.val == real_discr) + } _ => bug!("tagged layout for non-adt non-generator"), + }.ok_or_else( || err_unsup!(InvalidDiscriminant(raw_discr.erase_tag())) )?; diff --git a/src/librustc_mir/shim.rs b/src/librustc_mir/shim.rs index d089eafbb0798..78008e2fcd361 100644 --- a/src/librustc_mir/shim.rs +++ b/src/librustc_mir/shim.rs @@ -169,7 +169,7 @@ fn build_drop_shim<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, ty: Option>) // Check if this is a generator, if so, return the drop glue for it if let Some(&ty::TyS { kind: ty::Generator(gen_def_id, substs, _), .. }) = ty { let body = &**tcx.optimized_mir(gen_def_id).generator_drop.as_ref().unwrap(); - return body.subst(tcx, substs.substs); + return body.subst(tcx, substs); } let substs = if let Some(ty) = ty { diff --git a/src/librustc_mir/transform/generator.rs b/src/librustc_mir/transform/generator.rs index bfc5eb5a94ef8..a648fadde43be 100644 --- a/src/librustc_mir/transform/generator.rs +++ b/src/librustc_mir/transform/generator.rs @@ -1126,6 +1126,7 @@ impl<'tcx> MirPass<'tcx> for StateTransform { // Get the interior types and substs which typeck computed let (upvars, interior, discr_ty, movable) = match gen_ty.kind { ty::Generator(_, substs, movability) => { + let substs = substs.as_generator(); (substs.upvar_tys(def_id, tcx).collect(), substs.witness(def_id, tcx), substs.discr_ty(tcx), diff --git a/src/librustc_mir/util/elaborate_drops.rs b/src/librustc_mir/util/elaborate_drops.rs index bdbf040276d22..f7ba6f1ec6993 100644 --- a/src/librustc_mir/util/elaborate_drops.rs +++ b/src/librustc_mir/util/elaborate_drops.rs @@ -798,7 +798,7 @@ where // It effetively only contains upvars until the generator transformation runs. // See librustc_body/transform/generator.rs for more details. ty::Generator(def_id, substs, _) => { - let tys : Vec<_> = substs.upvar_tys(def_id, self.tcx()).collect(); + let tys : Vec<_> = substs.as_generator().upvar_tys(def_id, self.tcx()).collect(); self.open_drop_for_tuple(&tys) } ty::Tuple(..) => { diff --git a/src/librustc_traits/dropck_outlives.rs b/src/librustc_traits/dropck_outlives.rs index 7db1a7413c7be..88e62db9a10d8 100644 --- a/src/librustc_traits/dropck_outlives.rs +++ b/src/librustc_traits/dropck_outlives.rs @@ -223,7 +223,7 @@ fn dtorck_constraint_for_ty<'tcx>( // *do* incorporate the upvars here. let constraint = DtorckConstraint { - outlives: substs.upvar_tys(def_id, tcx).map(|t| t.into()).collect(), + outlives: substs.as_generator().upvar_tys(def_id, tcx).map(|t| t.into()).collect(), dtorck_types: vec![], overflows: vec![], }; diff --git a/src/librustc_traits/generic_types.rs b/src/librustc_traits/generic_types.rs index 91ca6415bdcb9..cc5348623fabd 100644 --- a/src/librustc_traits/generic_types.rs +++ b/src/librustc_traits/generic_types.rs @@ -73,7 +73,9 @@ crate fn closure(tcx: TyCtxt<'tcx>, def_id: DefId) -> Ty<'tcx> { } crate fn generator(tcx: TyCtxt<'tcx>, def_id: DefId) -> Ty<'tcx> { - tcx.mk_generator(def_id, ty::GeneratorSubsts { - substs: InternalSubsts::bound_vars_for_item(tcx, def_id), - }, hir::GeneratorMovability::Movable) + tcx.mk_generator( + def_id, + InternalSubsts::bound_vars_for_item(tcx, def_id), + hir::GeneratorMovability::Movable + ) } diff --git a/src/librustc_typeck/check/closure.rs b/src/librustc_typeck/check/closure.rs index 03f0860c66055..8b97bf643e9bb 100644 --- a/src/librustc_typeck/check/closure.rs +++ b/src/librustc_typeck/check/closure.rs @@ -113,21 +113,21 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } }); if let Some(GeneratorTypes { yield_ty, interior, movability }) = generator_types { - let substs = ty::GeneratorSubsts { substs }; + let generator_substs = substs.as_generator(); self.demand_eqtype( expr.span, yield_ty, - substs.yield_ty(expr_def_id, self.tcx), + generator_substs.yield_ty(expr_def_id, self.tcx), ); self.demand_eqtype( expr.span, liberated_sig.output(), - substs.return_ty(expr_def_id, self.tcx), + generator_substs.return_ty(expr_def_id, self.tcx), ); self.demand_eqtype( expr.span, interior, - substs.witness(expr_def_id, self.tcx), + generator_substs.witness(expr_def_id, self.tcx), ); return self.tcx.mk_generator(expr_def_id, substs, movability); } From e9009c86d2ed877e21011478f1083e3950507428 Mon Sep 17 00:00:00 2001 From: Wesley Wiser Date: Thu, 3 Oct 2019 13:43:07 -0400 Subject: [PATCH 18/23] [const-prop] Fix ICE when trying to eval polymorphic promoted MIR --- src/librustc_mir/interpret/place.rs | 7 +++++++ src/test/ui/consts/const-eval/issue-50814.rs | 1 - .../ui/consts/const-eval/issue-50814.stderr | 12 ++--------- src/test/ui/consts/const-eval/issue-64908.rs | 20 +++++++++++++++++++ 4 files changed, 29 insertions(+), 11 deletions(-) create mode 100644 src/test/ui/consts/const-eval/issue-64908.rs diff --git a/src/librustc_mir/interpret/place.rs b/src/librustc_mir/interpret/place.rs index 1166ca9bf2444..3ba989529f18f 100644 --- a/src/librustc_mir/interpret/place.rs +++ b/src/librustc_mir/interpret/place.rs @@ -594,6 +594,13 @@ where StaticKind::Promoted(promoted, promoted_substs) => { let substs = self.subst_from_frame_and_normalize_erasing_regions(promoted_substs); let instance = ty::Instance::new(place_static.def_id, substs); + + // Even after getting `substs` from the frame, this instance may still be + // polymorphic because `ConstProp` will try to promote polymorphic MIR. + if instance.needs_subst() { + throw_inval!(TooGeneric); + } + self.const_eval_raw(GlobalId { instance, promoted: Some(promoted), diff --git a/src/test/ui/consts/const-eval/issue-50814.rs b/src/test/ui/consts/const-eval/issue-50814.rs index 274967ef60de5..b85cecda16e95 100644 --- a/src/test/ui/consts/const-eval/issue-50814.rs +++ b/src/test/ui/consts/const-eval/issue-50814.rs @@ -11,7 +11,6 @@ struct Sum(A,B); impl Unsigned for Sum { const MAX: u8 = A::MAX + B::MAX; //~ ERROR any use of this value will cause an error - //~| ERROR any use of this value will cause an error } fn foo(_: T) -> &'static u8 { diff --git a/src/test/ui/consts/const-eval/issue-50814.stderr b/src/test/ui/consts/const-eval/issue-50814.stderr index de3459c72dd2b..707dfee7cd5b8 100644 --- a/src/test/ui/consts/const-eval/issue-50814.stderr +++ b/src/test/ui/consts/const-eval/issue-50814.stderr @@ -9,21 +9,13 @@ LL | const MAX: u8 = A::MAX + B::MAX; = note: `#[deny(const_err)]` on by default error[E0080]: evaluation of constant expression failed - --> $DIR/issue-50814.rs:18:5 + --> $DIR/issue-50814.rs:17:5 | LL | &Sum::::MAX | ^----------------- | | | referenced constant has errors -error: any use of this value will cause an error - --> $DIR/issue-50814.rs:13:21 - | -LL | const MAX: u8 = A::MAX + B::MAX; - | ----------------^^^^^^^^^^^^^^^- - | | - | attempt to add with overflow - -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0080`. diff --git a/src/test/ui/consts/const-eval/issue-64908.rs b/src/test/ui/consts/const-eval/issue-64908.rs new file mode 100644 index 0000000000000..d2e095072844f --- /dev/null +++ b/src/test/ui/consts/const-eval/issue-64908.rs @@ -0,0 +1,20 @@ +// run-pass + +// This test verifies that the `ConstProp` pass doesn't cause an ICE when evaluating polymorphic +// promoted MIR. + +pub trait ArrowPrimitiveType { + type Native; +} + +pub fn new() { + assert_eq!(0, std::mem::size_of::()); +} + +impl ArrowPrimitiveType for () { + type Native = (); +} + +fn main() { + new::<()>(); +} From 91a096a9b8c05011c1a76e7ceb578000ce1e91f6 Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Fri, 4 Oct 2019 10:31:28 -0400 Subject: [PATCH 19/23] move middle::liveness to rustc_passes --- src/librustc/lib.rs | 1 - src/librustc_interface/passes.rs | 1 - src/librustc_passes/lib.rs | 2 ++ .../middle => librustc_passes}/liveness.rs | 26 +++++++++---------- 4 files changed, 15 insertions(+), 15 deletions(-) rename src/{librustc/middle => librustc_passes}/liveness.rs (99%) diff --git a/src/librustc/lib.rs b/src/librustc/lib.rs index bd9899b644b5e..b522de7d43d38 100644 --- a/src/librustc/lib.rs +++ b/src/librustc/lib.rs @@ -111,7 +111,6 @@ pub mod middle { pub mod intrinsicck; pub mod lib_features; pub mod lang_items; - pub mod liveness; pub mod mem_categorization; pub mod privacy; pub mod reachable; diff --git a/src/librustc_interface/passes.rs b/src/librustc_interface/passes.rs index bf5e86017fc7b..ef9da5c2bde8f 100644 --- a/src/librustc_interface/passes.rs +++ b/src/librustc_interface/passes.rs @@ -781,7 +781,6 @@ pub fn default_provide(providers: &mut ty::query::Providers<'_>) { traits::provide(providers); stability::provide(providers); middle::intrinsicck::provide(providers); - middle::liveness::provide(providers); reachable::provide(providers); rustc_passes::provide(providers); rustc_traits::provide(providers); diff --git a/src/librustc_passes/lib.rs b/src/librustc_passes/lib.rs index 6c7958fb365dd..7aa353cec082b 100644 --- a/src/librustc_passes/lib.rs +++ b/src/librustc_passes/lib.rs @@ -22,7 +22,9 @@ pub mod ast_validation; pub mod hir_stats; pub mod layout_test; pub mod loops; +mod liveness; pub fn provide(providers: &mut Providers<'_>) { loops::provide(providers); + liveness::provide(providers); } diff --git a/src/librustc/middle/liveness.rs b/src/librustc_passes/liveness.rs similarity index 99% rename from src/librustc/middle/liveness.rs rename to src/librustc_passes/liveness.rs index a654a26eb0b76..fb06808619f66 100644 --- a/src/librustc/middle/liveness.rs +++ b/src/librustc_passes/liveness.rs @@ -96,17 +96,17 @@ use self::LiveNodeKind::*; use self::VarKind::*; -use crate::hir; -use crate::hir::{Expr, HirId}; -use crate::hir::def::*; -use crate::hir::def_id::DefId; -use crate::hir::intravisit::{self, Visitor, FnKind, NestedVisitorMap}; -use crate::hir::Node; -use crate::hir::ptr::P; -use crate::ty::{self, TyCtxt}; -use crate::ty::query::Providers; -use crate::lint; -use crate::util::nodemap::{HirIdMap, HirIdSet}; +use rustc::hir; +use rustc::hir::{Expr, HirId}; +use rustc::hir::def::*; +use rustc::hir::def_id::DefId; +use rustc::hir::intravisit::{self, Visitor, FnKind, NestedVisitorMap}; +use rustc::hir::Node; +use rustc::hir::ptr::P; +use rustc::ty::{self, TyCtxt}; +use rustc::ty::query::Providers; +use rustc::lint; +use rustc::util::nodemap::{HirIdMap, HirIdSet}; use errors::Applicability; use rustc_data_structures::fx::FxIndexMap; @@ -373,7 +373,7 @@ fn visit_fn<'tcx>( for param in &body.params { let is_shorthand = match param.pat.kind { - crate::hir::PatKind::Struct(..) => true, + rustc::hir::PatKind::Struct(..) => true, _ => false, }; param.pat.each_binding(|_bm, hir_id, _x, ident| { @@ -411,7 +411,7 @@ fn add_from_pat(ir: &mut IrMaps<'_>, pat: &P) { let mut pats = VecDeque::new(); pats.push_back(pat); while let Some(pat) = pats.pop_front() { - use crate::hir::PatKind::*; + use rustc::hir::PatKind::*; match &pat.kind { Binding(.., inner_pat) => { pats.extend(inner_pat.iter()); From bb707824d0f8b55a3f8552dd0326d0ae11fefcf6 Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Fri, 4 Oct 2019 10:33:11 -0400 Subject: [PATCH 20/23] middle::dead -> rustc_passes --- src/librustc/lib.rs | 1 - src/librustc_interface/passes.rs | 2 +- .../middle => librustc_passes}/dead.rs | 24 +++++++++---------- src/librustc_passes/lib.rs | 1 + 4 files changed, 14 insertions(+), 14 deletions(-) rename src/{librustc/middle => librustc_passes}/dead.rs (98%) diff --git a/src/librustc/lib.rs b/src/librustc/lib.rs index b522de7d43d38..46e39bec3249e 100644 --- a/src/librustc/lib.rs +++ b/src/librustc/lib.rs @@ -102,7 +102,6 @@ pub mod lint; pub mod middle { pub mod expr_use_visitor; pub mod cstore; - pub mod dead; pub mod dependency_format; pub mod diagnostic_items; pub mod entry; diff --git a/src/librustc_interface/passes.rs b/src/librustc_interface/passes.rs index ef9da5c2bde8f..2fa6edb46b1c0 100644 --- a/src/librustc_interface/passes.rs +++ b/src/librustc_interface/passes.rs @@ -972,7 +972,7 @@ fn analysis(tcx: TyCtxt<'_>, cnum: CrateNum) -> Result<()> { tcx.ensure().check_private_in_public(LOCAL_CRATE); }); }, { - time(sess, "death checking", || middle::dead::check_crate(tcx)); + time(sess, "death checking", || rustc_passes::dead::check_crate(tcx)); }, { time(sess, "unused lib feature checking", || { stability::check_unused_or_stable_features(tcx) diff --git a/src/librustc/middle/dead.rs b/src/librustc_passes/dead.rs similarity index 98% rename from src/librustc/middle/dead.rs rename to src/librustc_passes/dead.rs index 7c75a1447e26d..f2aef2c12c7df 100644 --- a/src/librustc/middle/dead.rs +++ b/src/librustc_passes/dead.rs @@ -2,18 +2,18 @@ // closely. The idea is that all reachable symbols are live, codes called // from live codes are live, and everything else is dead. -use crate::hir::Node; -use crate::hir::{self, PatKind, TyKind}; -use crate::hir::intravisit::{self, Visitor, NestedVisitorMap}; -use crate::hir::itemlikevisit::ItemLikeVisitor; - -use crate::hir::def::{CtorOf, Res, DefKind}; -use crate::hir::CodegenFnAttrFlags; -use crate::hir::def_id::{DefId, LOCAL_CRATE}; -use crate::lint; -use crate::middle::privacy; -use crate::ty::{self, DefIdTree, TyCtxt}; -use crate::util::nodemap::FxHashSet; +use rustc::hir::Node; +use rustc::hir::{self, PatKind, TyKind}; +use rustc::hir::intravisit::{self, Visitor, NestedVisitorMap}; +use rustc::hir::itemlikevisit::ItemLikeVisitor; + +use rustc::hir::def::{CtorOf, Res, DefKind}; +use rustc::hir::CodegenFnAttrFlags; +use rustc::hir::def_id::{DefId, LOCAL_CRATE}; +use rustc::lint; +use rustc::middle::privacy; +use rustc::ty::{self, DefIdTree, TyCtxt}; +use rustc::util::nodemap::FxHashSet; use rustc_data_structures::fx::FxHashMap; diff --git a/src/librustc_passes/lib.rs b/src/librustc_passes/lib.rs index 7aa353cec082b..c0b4a317cf947 100644 --- a/src/librustc_passes/lib.rs +++ b/src/librustc_passes/lib.rs @@ -22,6 +22,7 @@ pub mod ast_validation; pub mod hir_stats; pub mod layout_test; pub mod loops; +pub mod dead; mod liveness; pub fn provide(providers: &mut Providers<'_>) { From 82bfd8eb0dc8edcf7e231b9d998270a745f9a9c4 Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Fri, 4 Oct 2019 10:37:40 -0400 Subject: [PATCH 21/23] middle::entry -> rustc_passes --- src/librustc/error_codes.rs | 75 ------------------ src/librustc/lib.rs | 1 - src/librustc_interface/passes.rs | 3 +- .../middle => librustc_passes}/entry.rs | 16 ++-- src/librustc_passes/error_codes.rs | 77 +++++++++++++++++++ src/librustc_passes/lib.rs | 6 ++ 6 files changed, 92 insertions(+), 86 deletions(-) rename src/{librustc/middle => librustc_passes}/entry.rs (95%) diff --git a/src/librustc/error_codes.rs b/src/librustc/error_codes.rs index 968b0b9f2f2b7..9b04c2db9ff32 100644 --- a/src/librustc/error_codes.rs +++ b/src/librustc/error_codes.rs @@ -466,66 +466,6 @@ fn main() { ``` "##, -// This shouldn't really ever trigger since the repeated value error comes first -E0136: r##" -A binary can only have one entry point, and by default that entry point is the -function `main()`. If there are multiple such functions, please rename one. -"##, - -E0137: r##" -More than one function was declared with the `#[main]` attribute. - -Erroneous code example: - -```compile_fail,E0137 -#![feature(main)] - -#[main] -fn foo() {} - -#[main] -fn f() {} // error: multiple functions with a `#[main]` attribute -``` - -This error indicates that the compiler found multiple functions with the -`#[main]` attribute. This is an error because there must be a unique entry -point into a Rust program. Example: - -``` -#![feature(main)] - -#[main] -fn f() {} // ok! -``` -"##, - -E0138: r##" -More than one function was declared with the `#[start]` attribute. - -Erroneous code example: - -```compile_fail,E0138 -#![feature(start)] - -#[start] -fn foo(argc: isize, argv: *const *const u8) -> isize {} - -#[start] -fn f(argc: isize, argv: *const *const u8) -> isize {} -// error: multiple 'start' functions -``` - -This error indicates that the compiler found multiple functions with the -`#[start]` attribute. This is an error because there must be a unique entry -point into a Rust program. Example: - -``` -#![feature(start)] - -#[start] -fn foo(argc: isize, argv: *const *const u8) -> isize { 0 } // ok! -``` -"##, E0139: r##" #### Note: this error code is no longer emitted by the compiler. @@ -1941,21 +1881,6 @@ fn main() { ``` "##, -E0601: r##" -No `main` function was found in a binary crate. To fix this error, add a -`main` function. For example: - -``` -fn main() { - // Your program will start here. - println!("Hello world!"); -} -``` - -If you don't know the basics of Rust, you can go look to the Rust Book to get -started: https://doc.rust-lang.org/book/ -"##, - E0602: r##" An unknown lint was used on the command line. diff --git a/src/librustc/lib.rs b/src/librustc/lib.rs index 46e39bec3249e..197792eebb32c 100644 --- a/src/librustc/lib.rs +++ b/src/librustc/lib.rs @@ -104,7 +104,6 @@ pub mod middle { pub mod cstore; pub mod dependency_format; pub mod diagnostic_items; - pub mod entry; pub mod exported_symbols; pub mod free_region; pub mod intrinsicck; diff --git a/src/librustc_interface/passes.rs b/src/librustc_interface/passes.rs index 2fa6edb46b1c0..6d90d1c839ffc 100644 --- a/src/librustc_interface/passes.rs +++ b/src/librustc_interface/passes.rs @@ -785,7 +785,6 @@ pub fn default_provide(providers: &mut ty::query::Providers<'_>) { rustc_passes::provide(providers); rustc_traits::provide(providers); middle::region::provide(providers); - middle::entry::provide(providers); cstore::provide(providers); lint::provide(providers); rustc_lint::provide(providers); @@ -891,7 +890,7 @@ fn analysis(tcx: TyCtxt<'_>, cnum: CrateNum) -> Result<()> { time(sess, "misc checking 1", || { parallel!({ entry_point = time(sess, "looking for entry point", || { - middle::entry::find_entry_point(tcx) + rustc_passes::entry::find_entry_point(tcx) }); time(sess, "looking for plugin registrar", || { diff --git a/src/librustc/middle/entry.rs b/src/librustc_passes/entry.rs similarity index 95% rename from src/librustc/middle/entry.rs rename to src/librustc_passes/entry.rs index 660fe14ba0700..bf68807a0c29b 100644 --- a/src/librustc/middle/entry.rs +++ b/src/librustc_passes/entry.rs @@ -1,15 +1,15 @@ -use crate::hir::map as hir_map; -use crate::hir::def_id::{CrateNum, CRATE_DEF_INDEX, DefId, LOCAL_CRATE}; -use crate::session::{config, Session}; -use crate::session::config::EntryFnType; +use rustc::hir::map as hir_map; +use rustc::hir::def_id::{CrateNum, CRATE_DEF_INDEX, DefId, LOCAL_CRATE}; +use rustc::session::{config, Session}; +use rustc::session::config::EntryFnType; use syntax::attr; use syntax::entry::EntryPointType; use syntax::symbol::sym; use syntax_pos::Span; -use crate::hir::{HirId, Item, ItemKind, ImplItem, TraitItem}; -use crate::hir::itemlikevisit::ItemLikeVisitor; -use crate::ty::TyCtxt; -use crate::ty::query::Providers; +use rustc::hir::{HirId, Item, ItemKind, ImplItem, TraitItem}; +use rustc::hir::itemlikevisit::ItemLikeVisitor; +use rustc::ty::TyCtxt; +use rustc::ty::query::Providers; struct EntryContext<'a, 'tcx> { session: &'a Session, diff --git a/src/librustc_passes/error_codes.rs b/src/librustc_passes/error_codes.rs index af07c790e2a87..78260bd82456f 100644 --- a/src/librustc_passes/error_codes.rs +++ b/src/librustc_passes/error_codes.rs @@ -319,6 +319,83 @@ async fn foo() {} Switch to the Rust 2018 edition to use `async fn`. "##, + +// This shouldn't really ever trigger since the repeated value error comes first +E0136: r##" +A binary can only have one entry point, and by default that entry point is the +function `main()`. If there are multiple such functions, please rename one. +"##, + +E0137: r##" +More than one function was declared with the `#[main]` attribute. + +Erroneous code example: + +```compile_fail,E0137 +#![feature(main)] + +#[main] +fn foo() {} + +#[main] +fn f() {} // error: multiple functions with a `#[main]` attribute +``` + +This error indicates that the compiler found multiple functions with the +`#[main]` attribute. This is an error because there must be a unique entry +point into a Rust program. Example: + +``` +#![feature(main)] + +#[main] +fn f() {} // ok! +``` +"##, + +E0138: r##" +More than one function was declared with the `#[start]` attribute. + +Erroneous code example: + +```compile_fail,E0138 +#![feature(start)] + +#[start] +fn foo(argc: isize, argv: *const *const u8) -> isize {} + +#[start] +fn f(argc: isize, argv: *const *const u8) -> isize {} +// error: multiple 'start' functions +``` + +This error indicates that the compiler found multiple functions with the +`#[start]` attribute. This is an error because there must be a unique entry +point into a Rust program. Example: + +``` +#![feature(start)] + +#[start] +fn foo(argc: isize, argv: *const *const u8) -> isize { 0 } // ok! +``` +"##, + +E0601: r##" +No `main` function was found in a binary crate. To fix this error, add a +`main` function. For example: + +``` +fn main() { + // Your program will start here. + println!("Hello world!"); +} +``` + +If you don't know the basics of Rust, you can go look to the Rust Book to get +started: https://doc.rust-lang.org/book/ +"##, + ; E0226, // only a single explicit lifetime bound is permitted E0472, // asm! is unsupported on this target diff --git a/src/librustc_passes/lib.rs b/src/librustc_passes/lib.rs index c0b4a317cf947..1000770fb41e7 100644 --- a/src/librustc_passes/lib.rs +++ b/src/librustc_passes/lib.rs @@ -13,6 +13,10 @@ #[macro_use] extern crate rustc; +#[macro_use] +extern crate log; +#[macro_use] +extern crate syntax; use rustc::ty::query::Providers; @@ -23,9 +27,11 @@ pub mod hir_stats; pub mod layout_test; pub mod loops; pub mod dead; +pub mod entry; mod liveness; pub fn provide(providers: &mut Providers<'_>) { + entry::provide(providers); loops::provide(providers); liveness::provide(providers); } From 7c3f65b3c4691ff0df270505ebfab89f171c0d28 Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Fri, 4 Oct 2019 10:46:57 -0400 Subject: [PATCH 22/23] middle::intrinsicck -> rustc_passes --- Cargo.lock | 2 + src/librustc/error_codes.rs | 105 ------------------ src/librustc/lib.rs | 1 - src/librustc_interface/passes.rs | 1 - src/librustc_passes/Cargo.toml | 2 + src/librustc_passes/error_codes.rs | 105 ++++++++++++++++++ .../middle => librustc_passes}/intrinsicck.rs | 14 +-- src/librustc_passes/lib.rs | 2 + 8 files changed, 118 insertions(+), 114 deletions(-) rename src/{librustc/middle => librustc_passes}/intrinsicck.rs (95%) diff --git a/Cargo.lock b/Cargo.lock index 80364515a7cca..512dc5fd887c6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3613,6 +3613,8 @@ dependencies = [ "rustc", "rustc_data_structures", "rustc_errors", + "rustc_index", + "rustc_target", "syntax", "syntax_pos", ] diff --git a/src/librustc/error_codes.rs b/src/librustc/error_codes.rs index 9b04c2db9ff32..66c51000066b2 100644 --- a/src/librustc/error_codes.rs +++ b/src/librustc/error_codes.rs @@ -1566,33 +1566,6 @@ It is not possible to use stability attributes outside of the standard library. Also, for now, it is not possible to write deprecation messages either. "##, -E0512: r##" -Transmute with two differently sized types was attempted. Erroneous code -example: - -```compile_fail,E0512 -fn takes_u8(_: u8) {} - -fn main() { - unsafe { takes_u8(::std::mem::transmute(0u16)); } - // error: cannot transmute between types of different sizes, - // or dependently-sized types -} -``` - -Please use types with same size or use the expected type directly. Example: - -``` -fn takes_u8(_: u8) {} - -fn main() { - unsafe { takes_u8(::std::mem::transmute(0i8)); } // ok! - // or: - unsafe { takes_u8(0u8); } // ok! -} -``` -"##, - E0517: r##" This error indicates that a `#[repr(..)]` attribute was placed on an unsupported item. @@ -1787,84 +1760,6 @@ See [RFC 1522] for more details. [RFC 1522]: https://github.com/rust-lang/rfcs/blob/master/text/1522-conservative-impl-trait.md "##, -E0591: r##" -Per [RFC 401][rfc401], if you have a function declaration `foo`: - -``` -// For the purposes of this explanation, all of these -// different kinds of `fn` declarations are equivalent: -struct S; -fn foo(x: S) { /* ... */ } -# #[cfg(for_demonstration_only)] -extern "C" { fn foo(x: S); } -# #[cfg(for_demonstration_only)] -impl S { fn foo(self) { /* ... */ } } -``` - -the type of `foo` is **not** `fn(S)`, as one might expect. -Rather, it is a unique, zero-sized marker type written here as `typeof(foo)`. -However, `typeof(foo)` can be _coerced_ to a function pointer `fn(S)`, -so you rarely notice this: - -``` -# struct S; -# fn foo(_: S) {} -let x: fn(S) = foo; // OK, coerces -``` - -The reason that this matter is that the type `fn(S)` is not specific to -any particular function: it's a function _pointer_. So calling `x()` results -in a virtual call, whereas `foo()` is statically dispatched, because the type -of `foo` tells us precisely what function is being called. - -As noted above, coercions mean that most code doesn't have to be -concerned with this distinction. However, you can tell the difference -when using **transmute** to convert a fn item into a fn pointer. - -This is sometimes done as part of an FFI: - -```compile_fail,E0591 -extern "C" fn foo(userdata: Box) { - /* ... */ -} - -# fn callback(_: extern "C" fn(*mut i32)) {} -# use std::mem::transmute; -# unsafe { -let f: extern "C" fn(*mut i32) = transmute(foo); -callback(f); -# } -``` - -Here, transmute is being used to convert the types of the fn arguments. -This pattern is incorrect because, because the type of `foo` is a function -**item** (`typeof(foo)`), which is zero-sized, and the target type (`fn()`) -is a function pointer, which is not zero-sized. -This pattern should be rewritten. There are a few possible ways to do this: - -- change the original fn declaration to match the expected signature, - and do the cast in the fn body (the preferred option) -- cast the fn item fo a fn pointer before calling transmute, as shown here: - - ``` - # extern "C" fn foo(_: Box) {} - # use std::mem::transmute; - # unsafe { - let f: extern "C" fn(*mut i32) = transmute(foo as extern "C" fn(_)); - let f: extern "C" fn(*mut i32) = transmute(foo as usize); // works too - # } - ``` - -The same applies to transmutes to `*mut fn()`, which were observed in practice. -Note though that use of this type is generally incorrect. -The intention is typically to describe a function pointer, but just `fn()` -alone suffices for that. `*mut fn()` is a pointer to a fn pointer. -(Since these values are typically just passed to C code, however, this rarely -makes a difference in practice.) - -[rfc401]: https://github.com/rust-lang/rfcs/blob/master/text/0401-coercions.md -"##, - E0593: r##" You tried to supply an `Fn`-based type with an incorrect number of arguments than what was expected. diff --git a/src/librustc/lib.rs b/src/librustc/lib.rs index 197792eebb32c..0eea149f30aee 100644 --- a/src/librustc/lib.rs +++ b/src/librustc/lib.rs @@ -106,7 +106,6 @@ pub mod middle { pub mod diagnostic_items; pub mod exported_symbols; pub mod free_region; - pub mod intrinsicck; pub mod lib_features; pub mod lang_items; pub mod mem_categorization; diff --git a/src/librustc_interface/passes.rs b/src/librustc_interface/passes.rs index 6d90d1c839ffc..870f804ed4478 100644 --- a/src/librustc_interface/passes.rs +++ b/src/librustc_interface/passes.rs @@ -780,7 +780,6 @@ pub fn default_provide(providers: &mut ty::query::Providers<'_>) { ty::provide(providers); traits::provide(providers); stability::provide(providers); - middle::intrinsicck::provide(providers); reachable::provide(providers); rustc_passes::provide(providers); rustc_traits::provide(providers); diff --git a/src/librustc_passes/Cargo.toml b/src/librustc_passes/Cargo.toml index 596ec6c19bcbf..9d29a23031443 100644 --- a/src/librustc_passes/Cargo.toml +++ b/src/librustc_passes/Cargo.toml @@ -15,3 +15,5 @@ rustc_data_structures = { path = "../librustc_data_structures" } syntax = { path = "../libsyntax" } syntax_pos = { path = "../libsyntax_pos" } errors = { path = "../librustc_errors", package = "rustc_errors" } +rustc_target = { path = "../librustc_target" } +rustc_index = { path = "../librustc_index" } diff --git a/src/librustc_passes/error_codes.rs b/src/librustc_passes/error_codes.rs index 78260bd82456f..1c61eb35497d7 100644 --- a/src/librustc_passes/error_codes.rs +++ b/src/librustc_passes/error_codes.rs @@ -396,6 +396,111 @@ If you don't know the basics of Rust, you can go look to the Rust Book to get started: https://doc.rust-lang.org/book/ "##, +E0591: r##" +Per [RFC 401][rfc401], if you have a function declaration `foo`: + +``` +// For the purposes of this explanation, all of these +// different kinds of `fn` declarations are equivalent: +struct S; +fn foo(x: S) { /* ... */ } +# #[cfg(for_demonstration_only)] +extern "C" { fn foo(x: S); } +# #[cfg(for_demonstration_only)] +impl S { fn foo(self) { /* ... */ } } +``` + +the type of `foo` is **not** `fn(S)`, as one might expect. +Rather, it is a unique, zero-sized marker type written here as `typeof(foo)`. +However, `typeof(foo)` can be _coerced_ to a function pointer `fn(S)`, +so you rarely notice this: + +``` +# struct S; +# fn foo(_: S) {} +let x: fn(S) = foo; // OK, coerces +``` + +The reason that this matter is that the type `fn(S)` is not specific to +any particular function: it's a function _pointer_. So calling `x()` results +in a virtual call, whereas `foo()` is statically dispatched, because the type +of `foo` tells us precisely what function is being called. + +As noted above, coercions mean that most code doesn't have to be +concerned with this distinction. However, you can tell the difference +when using **transmute** to convert a fn item into a fn pointer. + +This is sometimes done as part of an FFI: + +```compile_fail,E0591 +extern "C" fn foo(userdata: Box) { + /* ... */ +} + +# fn callback(_: extern "C" fn(*mut i32)) {} +# use std::mem::transmute; +# unsafe { +let f: extern "C" fn(*mut i32) = transmute(foo); +callback(f); +# } +``` + +Here, transmute is being used to convert the types of the fn arguments. +This pattern is incorrect because, because the type of `foo` is a function +**item** (`typeof(foo)`), which is zero-sized, and the target type (`fn()`) +is a function pointer, which is not zero-sized. +This pattern should be rewritten. There are a few possible ways to do this: + +- change the original fn declaration to match the expected signature, + and do the cast in the fn body (the preferred option) +- cast the fn item fo a fn pointer before calling transmute, as shown here: + + ``` + # extern "C" fn foo(_: Box) {} + # use std::mem::transmute; + # unsafe { + let f: extern "C" fn(*mut i32) = transmute(foo as extern "C" fn(_)); + let f: extern "C" fn(*mut i32) = transmute(foo as usize); // works too + # } + ``` + +The same applies to transmutes to `*mut fn()`, which were observed in practice. +Note though that use of this type is generally incorrect. +The intention is typically to describe a function pointer, but just `fn()` +alone suffices for that. `*mut fn()` is a pointer to a fn pointer. +(Since these values are typically just passed to C code, however, this rarely +makes a difference in practice.) + +[rfc401]: https://github.com/rust-lang/rfcs/blob/master/text/0401-coercions.md +"##, + +E0512: r##" +Transmute with two differently sized types was attempted. Erroneous code +example: + +```compile_fail,E0512 +fn takes_u8(_: u8) {} + +fn main() { + unsafe { takes_u8(::std::mem::transmute(0u16)); } + // error: cannot transmute between types of different sizes, + // or dependently-sized types +} +``` + +Please use types with same size or use the expected type directly. Example: + +``` +fn takes_u8(_: u8) {} + +fn main() { + unsafe { takes_u8(::std::mem::transmute(0i8)); } // ok! + // or: + unsafe { takes_u8(0u8); } // ok! +} +``` +"##, + ; E0226, // only a single explicit lifetime bound is permitted E0472, // asm! is unsupported on this target diff --git a/src/librustc/middle/intrinsicck.rs b/src/librustc_passes/intrinsicck.rs similarity index 95% rename from src/librustc/middle/intrinsicck.rs rename to src/librustc_passes/intrinsicck.rs index 7b5aea8ac9847..91a7e9f5d7fca 100644 --- a/src/librustc/middle/intrinsicck.rs +++ b/src/librustc_passes/intrinsicck.rs @@ -1,14 +1,14 @@ -use crate::hir::def::{Res, DefKind}; -use crate::hir::def_id::DefId; -use crate::ty::{self, Ty, TyCtxt}; -use crate::ty::layout::{LayoutError, Pointer, SizeSkeleton, VariantIdx}; -use crate::ty::query::Providers; +use rustc::hir::def::{Res, DefKind}; +use rustc::hir::def_id::DefId; +use rustc::ty::{self, Ty, TyCtxt}; +use rustc::ty::layout::{LayoutError, Pointer, SizeSkeleton, VariantIdx}; +use rustc::ty::query::Providers; use rustc_target::spec::abi::Abi::RustIntrinsic; use rustc_index::vec::Idx; use syntax_pos::{Span, sym}; -use crate::hir::intravisit::{self, Visitor, NestedVisitorMap}; -use crate::hir; +use rustc::hir::intravisit::{self, Visitor, NestedVisitorMap}; +use rustc::hir; fn check_mod_intrinsics(tcx: TyCtxt<'_>, module_def_id: DefId) { tcx.hir().visit_item_likes_in_module( diff --git a/src/librustc_passes/lib.rs b/src/librustc_passes/lib.rs index 1000770fb41e7..db59d8e101f77 100644 --- a/src/librustc_passes/lib.rs +++ b/src/librustc_passes/lib.rs @@ -29,9 +29,11 @@ pub mod loops; pub mod dead; pub mod entry; mod liveness; +mod intrinsicck; pub fn provide(providers: &mut Providers<'_>) { entry::provide(providers); loops::provide(providers); liveness::provide(providers); + intrinsicck::provide(providers); } From d0a6805b0e2711b38a9663a88d23699dd328abb6 Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Fri, 4 Oct 2019 10:43:15 -0400 Subject: [PATCH 23/23] Allow unused attributes to avoid incremental bug --- src/libcore/slice/mod.rs | 1 + src/libcore/str/mod.rs | 1 + 2 files changed, 2 insertions(+) diff --git a/src/libcore/slice/mod.rs b/src/libcore/slice/mod.rs index b5462d988378b..4e79ea812044b 100644 --- a/src/libcore/slice/mod.rs +++ b/src/libcore/slice/mod.rs @@ -63,6 +63,7 @@ impl [T] { #[stable(feature = "rust1", since = "1.0.0")] #[inline] // SAFETY: const sound because we transmute out the length field as a usize (which it must be) + #[allow(unused_attributes)] #[allow_internal_unstable(const_fn_union)] pub const fn len(&self) -> usize { unsafe { diff --git a/src/libcore/str/mod.rs b/src/libcore/str/mod.rs index ece61dde490fd..885696e5acf49 100644 --- a/src/libcore/str/mod.rs +++ b/src/libcore/str/mod.rs @@ -2167,6 +2167,7 @@ impl str { #[stable(feature = "rust1", since = "1.0.0")] #[inline(always)] // SAFETY: const sound because we transmute two types with the same layout + #[allow(unused_attributes)] #[allow_internal_unstable(const_fn_union)] pub const fn as_bytes(&self) -> &[u8] { #[repr(C)]