From fcda7b2871703f704f95ea4d83552827e69938bd Mon Sep 17 00:00:00 2001 From: Son Date: Wed, 5 Sep 2018 00:03:00 -0700 Subject: [PATCH 01/13] Add doc for impl From for Std Error --- src/libstd/error.rs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/libstd/error.rs b/src/libstd/error.rs index 29534696abc5b..6ca8e28c11659 100644 --- a/src/libstd/error.rs +++ b/src/libstd/error.rs @@ -152,6 +152,7 @@ pub trait Error: Debug + Display { #[stable(feature = "rust1", since = "1.0.0")] impl<'a, E: Error + 'a> From for Box { + /// Converts a type of [`Error`] into a box of dyn [`Error`]. fn from(err: E) -> Box { Box::new(err) } @@ -159,6 +160,8 @@ impl<'a, E: Error + 'a> From for Box { #[stable(feature = "rust1", since = "1.0.0")] impl<'a, E: Error + Send + Sync + 'a> From for Box { + /// Converts a type of [`Error`] + [`Send`] + [`Sync`] into a box of dyn [`Error`] + + /// [`Send`] + [`Sync`]. fn from(err: E) -> Box { Box::new(err) } @@ -166,6 +169,7 @@ impl<'a, E: Error + Send + Sync + 'a> From for Box for Box { + /// Converts a [`String`] into a box of dyn [`Error`] + [`Send`] + [`Sync`]. fn from(err: String) -> Box { #[derive(Debug)] struct StringError(String); @@ -186,6 +190,7 @@ impl From for Box { #[stable(feature = "string_box_error", since = "1.6.0")] impl From for Box { + /// Converts a [`String`] into a box of dyn [`Error`]. fn from(str_err: String) -> Box { let err1: Box = From::from(str_err); let err2: Box = err1; @@ -195,6 +200,7 @@ impl From for Box { #[stable(feature = "rust1", since = "1.0.0")] impl<'a, 'b> From<&'b str> for Box { + /// Converts a [`str`] into a box of dyn [`Error`] + [`Send`] + [`Sync`]. fn from(err: &'b str) -> Box { From::from(String::from(err)) } @@ -202,6 +208,7 @@ impl<'a, 'b> From<&'b str> for Box { #[stable(feature = "string_box_error", since = "1.6.0")] impl<'a> From<&'a str> for Box { + /// Converts a [`str`] into a box of dyn [`Error`]. fn from(err: &'a str) -> Box { From::from(String::from(err)) } @@ -209,6 +216,7 @@ impl<'a> From<&'a str> for Box { #[stable(feature = "cow_box_error", since = "1.22.0")] impl<'a, 'b> From> for Box { + /// Converts a [`Cow`] into a box of dyn [`Error`] + [`Send`] + [`Sync`]. fn from(err: Cow<'b, str>) -> Box { From::from(String::from(err)) } @@ -216,6 +224,7 @@ impl<'a, 'b> From> for Box { #[stable(feature = "cow_box_error", since = "1.22.0")] impl<'a> From> for Box { + /// Converts a [`Cow`] into a box of dyn [`Error`]. fn from(err: Cow<'a, str>) -> Box { From::from(String::from(err)) } From a7cc1fccbd49a45a4d99a4c4ccdad16972b235bf Mon Sep 17 00:00:00 2001 From: Son Date: Wed, 26 Sep 2018 04:45:41 +1000 Subject: [PATCH 02/13] Examples for docs --- src/libstd/error.rs | 148 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 148 insertions(+) diff --git a/src/libstd/error.rs b/src/libstd/error.rs index 6ca8e28c11659..cfc256f3644d7 100644 --- a/src/libstd/error.rs +++ b/src/libstd/error.rs @@ -153,6 +153,36 @@ pub trait Error: Debug + Display { #[stable(feature = "rust1", since = "1.0.0")] impl<'a, E: Error + 'a> From for Box { /// Converts a type of [`Error`] into a box of dyn [`Error`]. + /// + /// # Examples + /// + /// ``` + /// use std::error::Error; + /// use std::fmt; + /// use std::mem; + /// + /// #[derive(Debug)] + /// struct AnError; + /// + /// impl fmt::Display for AnError { + /// fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + /// write!(f , "An error") + /// } + /// } + /// + /// impl Error for AnError { + /// fn description(&self) -> &str { + /// "Description of an error" + /// } + /// } + /// + /// fn main() { + /// let an_error = AnError; + /// assert!(0 == mem::size_of_val(&an_error)); + /// let a_boxed_error = Box::::from(an_error); + /// assert!(mem::size_of::>() == mem::size_of_val(&a_boxed_error)) + /// } + /// ``` fn from(err: E) -> Box { Box::new(err) } @@ -162,6 +192,41 @@ impl<'a, E: Error + 'a> From for Box { impl<'a, E: Error + Send + Sync + 'a> From for Box { /// Converts a type of [`Error`] + [`Send`] + [`Sync`] into a box of dyn [`Error`] + /// [`Send`] + [`Sync`]. + /// + /// # Examples + /// + /// ``` + /// use std::error::Error; + /// use std::fmt; + /// use std::mem; + /// + /// #[derive(Debug)] + /// struct AnError; + /// + /// impl fmt::Display for AnError { + /// fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + /// write!(f , "An error") + /// } + /// } + /// + /// impl Error for AnError { + /// fn description(&self) -> &str { + /// "Description of an error" + /// } + /// } + /// + /// unsafe impl Send for AnError {} + /// + /// unsafe impl Sync for AnError {} + /// + /// fn main() { + /// let an_error = AnError; + /// assert!(0 == mem::size_of_val(&an_error)); + /// let a_boxed_error = Box::::from(an_error); + /// assert!( + /// mem::size_of::>() == mem::size_of_val(&a_boxed_error)) + /// } + /// ``` fn from(err: E) -> Box { Box::new(err) } @@ -170,6 +235,20 @@ impl<'a, E: Error + Send + Sync + 'a> From for Box for Box { /// Converts a [`String`] into a box of dyn [`Error`] + [`Send`] + [`Sync`]. + /// + /// # Examples + /// + /// ``` + /// use std::error::Error; + /// use std::mem; + /// + /// fn main() { + /// let a_string_error = "a string error".to_string(); + /// let a_boxed_error = Box::::from(a_string_error); + /// assert!( + /// mem::size_of::>() == mem::size_of_val(&a_boxed_error)) + /// } + /// ``` fn from(err: String) -> Box { #[derive(Debug)] struct StringError(String); @@ -191,6 +270,19 @@ impl From for Box { #[stable(feature = "string_box_error", since = "1.6.0")] impl From for Box { /// Converts a [`String`] into a box of dyn [`Error`]. + /// + /// # Examples + /// + /// ``` + /// use std::error::Error; + /// use std::mem; + /// + /// fn main() { + /// let a_string_error = "a string error".to_string(); + /// let a_boxed_error = Box::::from(a_string_error); + /// assert!(mem::size_of::>() == mem::size_of_val(&a_boxed_error)) + /// } + /// ``` fn from(str_err: String) -> Box { let err1: Box = From::from(str_err); let err2: Box = err1; @@ -201,6 +293,20 @@ impl From for Box { #[stable(feature = "rust1", since = "1.0.0")] impl<'a, 'b> From<&'b str> for Box { /// Converts a [`str`] into a box of dyn [`Error`] + [`Send`] + [`Sync`]. + /// + /// # Examples + /// + /// ``` + /// use std::error::Error; + /// use std::mem; + /// + /// fn main() { + /// let a_str_error = "a str error"; + /// let a_boxed_error = Box::::from(a_str_error); + /// assert!( + /// mem::size_of::>() == mem::size_of_val(&a_boxed_error)) + /// } + /// ``` fn from(err: &'b str) -> Box { From::from(String::from(err)) } @@ -209,6 +315,19 @@ impl<'a, 'b> From<&'b str> for Box { #[stable(feature = "string_box_error", since = "1.6.0")] impl<'a> From<&'a str> for Box { /// Converts a [`str`] into a box of dyn [`Error`]. + /// + /// # Examples + /// + /// ``` + /// use std::error::Error; + /// use std::mem; + /// + /// fn main() { + /// let a_str_error = "a str error"; + /// let a_boxed_error = Box::::from(a_str_error); + /// assert!(mem::size_of::>() == mem::size_of_val(&a_boxed_error)) + /// } + /// ``` fn from(err: &'a str) -> Box { From::from(String::from(err)) } @@ -217,6 +336,21 @@ impl<'a> From<&'a str> for Box { #[stable(feature = "cow_box_error", since = "1.22.0")] impl<'a, 'b> From> for Box { /// Converts a [`Cow`] into a box of dyn [`Error`] + [`Send`] + [`Sync`]. + /// + /// # Examples + /// + /// ``` + /// use std::error::Error; + /// use std::mem; + /// use std::borrow::Cow; + /// + /// fn main() { + /// let a_cow_str_error = Cow::from("a str error"); + /// let a_boxed_error = Box::::from(a_cow_str_error); + /// assert!( + /// mem::size_of::>() == mem::size_of_val(&a_boxed_error)) + /// } + /// ``` fn from(err: Cow<'b, str>) -> Box { From::from(String::from(err)) } @@ -225,6 +359,20 @@ impl<'a, 'b> From> for Box { #[stable(feature = "cow_box_error", since = "1.22.0")] impl<'a> From> for Box { /// Converts a [`Cow`] into a box of dyn [`Error`]. + /// + /// # Examples + /// + /// ``` + /// use std::error::Error; + /// use std::mem; + /// use std::borrow::Cow; + /// + /// fn main() { + /// let a_cow_str_error = Cow::from("a str error"); + /// let a_boxed_error = Box::::from(a_cow_str_error); + /// assert!(mem::size_of::>() == mem::size_of_val(&a_boxed_error)) + /// } + /// ``` fn from(err: Cow<'a, str>) -> Box { From::from(String::from(err)) } From ec59188025582fd91ab868206cfb3f3f05e27ade Mon Sep 17 00:00:00 2001 From: Nathan West Date: Tue, 2 Oct 2018 12:35:25 -0700 Subject: [PATCH 03/13] Make spec_extend use for_each() --- src/liballoc/vec.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/liballoc/vec.rs b/src/liballoc/vec.rs index e845438c0a836..2bc037e3fee12 100644 --- a/src/liballoc/vec.rs +++ b/src/liballoc/vec.rs @@ -1822,12 +1822,12 @@ impl SpecExtend for Vec unsafe { let mut ptr = self.as_mut_ptr().add(self.len()); let mut local_len = SetLenOnDrop::new(&mut self.len); - for element in iterator { + iterator.for_each(move |element| { ptr::write(ptr, element); ptr = ptr.offset(1); // NB can't overflow since we would have had to alloc the address space local_len.increment_len(1); - } + }); } } else { self.extend_desugared(iterator) From 84f75f0dbb2459d2c73ef8736d835aa651c3686a Mon Sep 17 00:00:00 2001 From: jacob Date: Tue, 2 Oct 2018 16:59:48 -0500 Subject: [PATCH 04/13] Fix typo in CONTRIBUTING.md I noticed a small typo while reading over this document. --- CONTRIBUTING.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 2e51a786f4682..49961d02ddab7 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -566,7 +566,7 @@ labels to triage issues: to fix the issue. * The dark blue **final-comment-period** label marks bugs that are using the - RFC signoff functionality of [rfcbot][rfcbot] and are currenty in the final + RFC signoff functionality of [rfcbot][rfcbot] and are currently in the final comment period. * Red, **I**-prefixed labels indicate the **importance** of the issue. The From 30f2e96ab1d3f36d115249d932f7e5291e18b911 Mon Sep 17 00:00:00 2001 From: Son Date: Wed, 3 Oct 2018 08:21:51 +1000 Subject: [PATCH 05/13] Remove main() in examples --- src/libstd/error.rs | 76 ++++++++++++++++++--------------------------- 1 file changed, 30 insertions(+), 46 deletions(-) diff --git a/src/libstd/error.rs b/src/libstd/error.rs index cfc256f3644d7..1b872664e8d13 100644 --- a/src/libstd/error.rs +++ b/src/libstd/error.rs @@ -176,12 +176,10 @@ impl<'a, E: Error + 'a> From for Box { /// } /// } /// - /// fn main() { - /// let an_error = AnError; - /// assert!(0 == mem::size_of_val(&an_error)); - /// let a_boxed_error = Box::::from(an_error); - /// assert!(mem::size_of::>() == mem::size_of_val(&a_boxed_error)) - /// } + /// let an_error = AnError; + /// assert!(0 == mem::size_of_val(&an_error)); + /// let a_boxed_error = Box::::from(an_error); + /// assert!(mem::size_of::>() == mem::size_of_val(&a_boxed_error)) /// ``` fn from(err: E) -> Box { Box::new(err) @@ -219,13 +217,11 @@ impl<'a, E: Error + Send + Sync + 'a> From for Box::from(an_error); - /// assert!( - /// mem::size_of::>() == mem::size_of_val(&a_boxed_error)) - /// } + /// let an_error = AnError; + /// assert!(0 == mem::size_of_val(&an_error)); + /// let a_boxed_error = Box::::from(an_error); + /// assert!( + /// mem::size_of::>() == mem::size_of_val(&a_boxed_error)) /// ``` fn from(err: E) -> Box { Box::new(err) @@ -242,12 +238,10 @@ impl From for Box { /// use std::error::Error; /// use std::mem; /// - /// fn main() { - /// let a_string_error = "a string error".to_string(); - /// let a_boxed_error = Box::::from(a_string_error); - /// assert!( - /// mem::size_of::>() == mem::size_of_val(&a_boxed_error)) - /// } + /// let a_string_error = "a string error".to_string(); + /// let a_boxed_error = Box::::from(a_string_error); + /// assert!( + /// mem::size_of::>() == mem::size_of_val(&a_boxed_error)) /// ``` fn from(err: String) -> Box { #[derive(Debug)] @@ -277,11 +271,9 @@ impl From for Box { /// use std::error::Error; /// use std::mem; /// - /// fn main() { - /// let a_string_error = "a string error".to_string(); - /// let a_boxed_error = Box::::from(a_string_error); - /// assert!(mem::size_of::>() == mem::size_of_val(&a_boxed_error)) - /// } + /// let a_string_error = "a string error".to_string(); + /// let a_boxed_error = Box::::from(a_string_error); + /// assert!(mem::size_of::>() == mem::size_of_val(&a_boxed_error)) /// ``` fn from(str_err: String) -> Box { let err1: Box = From::from(str_err); @@ -300,12 +292,10 @@ impl<'a, 'b> From<&'b str> for Box { /// use std::error::Error; /// use std::mem; /// - /// fn main() { - /// let a_str_error = "a str error"; - /// let a_boxed_error = Box::::from(a_str_error); - /// assert!( - /// mem::size_of::>() == mem::size_of_val(&a_boxed_error)) - /// } + /// let a_str_error = "a str error"; + /// let a_boxed_error = Box::::from(a_str_error); + /// assert!( + /// mem::size_of::>() == mem::size_of_val(&a_boxed_error)) /// ``` fn from(err: &'b str) -> Box { From::from(String::from(err)) @@ -322,11 +312,9 @@ impl<'a> From<&'a str> for Box { /// use std::error::Error; /// use std::mem; /// - /// fn main() { - /// let a_str_error = "a str error"; - /// let a_boxed_error = Box::::from(a_str_error); - /// assert!(mem::size_of::>() == mem::size_of_val(&a_boxed_error)) - /// } + /// let a_str_error = "a str error"; + /// let a_boxed_error = Box::::from(a_str_error); + /// assert!(mem::size_of::>() == mem::size_of_val(&a_boxed_error)) /// ``` fn from(err: &'a str) -> Box { From::from(String::from(err)) @@ -344,12 +332,10 @@ impl<'a, 'b> From> for Box { /// use std::mem; /// use std::borrow::Cow; /// - /// fn main() { - /// let a_cow_str_error = Cow::from("a str error"); - /// let a_boxed_error = Box::::from(a_cow_str_error); - /// assert!( - /// mem::size_of::>() == mem::size_of_val(&a_boxed_error)) - /// } + /// let a_cow_str_error = Cow::from("a str error"); + /// let a_boxed_error = Box::::from(a_cow_str_error); + /// assert!( + /// mem::size_of::>() == mem::size_of_val(&a_boxed_error)) /// ``` fn from(err: Cow<'b, str>) -> Box { From::from(String::from(err)) @@ -367,11 +353,9 @@ impl<'a> From> for Box { /// use std::mem; /// use std::borrow::Cow; /// - /// fn main() { - /// let a_cow_str_error = Cow::from("a str error"); - /// let a_boxed_error = Box::::from(a_cow_str_error); - /// assert!(mem::size_of::>() == mem::size_of_val(&a_boxed_error)) - /// } + /// let a_cow_str_error = Cow::from("a str error"); + /// let a_boxed_error = Box::::from(a_cow_str_error); + /// assert!(mem::size_of::>() == mem::size_of_val(&a_boxed_error)) /// ``` fn from(err: Cow<'a, str>) -> Box { From::from(String::from(err)) From d686896f907c75083c61783fe17b3f90e8985428 Mon Sep 17 00:00:00 2001 From: Wesley Wiser Date: Tue, 2 Oct 2018 22:11:38 -0400 Subject: [PATCH 06/13] Update a FIXME in memory.rs In #51833, I improved the performance of `copy_undef_mask()`. As such, the old FIXME wasn't appropriate anymore. The main remaining thing left to do is to implement a fast path for non-overlapping copies (per @oli-obk). --- src/librustc_mir/interpret/memory.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustc_mir/interpret/memory.rs b/src/librustc_mir/interpret/memory.rs index 11e27a597fbca..222d1164667d3 100644 --- a/src/librustc_mir/interpret/memory.rs +++ b/src/librustc_mir/interpret/memory.rs @@ -971,7 +971,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> { /// Undefined bytes impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> { - // FIXME(solson): This is a very naive, slow version. + // FIXME: Add a fast version for the common, nonoverlapping case fn copy_undef_mask( &mut self, src: Pointer, From 1081bbbfc5d170f22b5810b40c456a17da59cf7f Mon Sep 17 00:00:00 2001 From: "Zack M. Davis" Date: Tue, 2 Oct 2018 21:43:05 -0700 Subject: [PATCH 07/13] abolish ICE when pretty-printing async block MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Joshua Netterfield reported an ICE when the unused-parentheses lint triggered around an async block (#54752). In order to compose an autofixable suggestion, the lint invokes the pretty-printer on the unnecessarily-parenthesized expression. (One wonders why the lint doesn't just use `SourceMap::span_to_snippet` instead, to preserve the formatting of the original source?—but for that, you'd have to ask the author of 5c9f806d.) But then the pretty-printer panics when trying to call `::end` when `State.boxes` is empty. Empirically, the problem would seem to be solved if we start some "boxes" beforehand in the `ast::ExprKind::Async` arm of the big match in `print_expr_outer_attr_style`, exactly like we do in the immediately-preceding match arm for `ast::ExprKind::Block`—it would seem pretty ("pretty") reasonable for the pretty-printing of async blocks to work a lot like the pretty-printing of ordinary non-async blocks, right?? Of course, it would be shamefully cargo-culty to commit code on the basis of this kind of mere reasoning-by-analogy (in contrast to understanding the design of the pretty-printer in such detail that the correctness of the patch is comprehended with all the lucid certainty of mathematical proof, rather than being merely surmised by intuition). But maybe we care more about fixing the bug with high probability today, than with certainty in some indefinite hypothetical future? Maybe the effort is worth a fifth of a shirt?? Humbly resolves #54752. --- src/libsyntax/print/pprust.rs | 3 +++ src/test/pretty/issue-54752-async-block.rs | 7 +++++++ 2 files changed, 10 insertions(+) create mode 100644 src/test/pretty/issue-54752-async-block.rs diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index f2acdb3f469d1..83a05921510b4 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -2228,6 +2228,9 @@ impl<'a> State<'a> { self.word_nbsp("async")?; self.print_capture_clause(capture_clause)?; self.s.space()?; + // cbox/ibox in analogy to the `ExprKind::Block` arm above + self.cbox(INDENT_UNIT)?; + self.ibox(0)?; self.print_block_with_attrs(blk, attrs)?; } ast::ExprKind::Assign(ref lhs, ref rhs) => { diff --git a/src/test/pretty/issue-54752-async-block.rs b/src/test/pretty/issue-54752-async-block.rs new file mode 100644 index 0000000000000..6930ee1a386fe --- /dev/null +++ b/src/test/pretty/issue-54752-async-block.rs @@ -0,0 +1,7 @@ +#![feature(async_await)] +#![allow(unused_parens)] + +// edition:2018 +// pp-exact + +fn main() { let _a = (async { }); } From 989f480297cabee936403fd66baa429f2b8ed4ee Mon Sep 17 00:00:00 2001 From: Andre Bogus Date: Mon, 1 Oct 2018 23:15:22 +0200 Subject: [PATCH 08/13] simplify some unused lints code --- src/librustc_lint/unused.rs | 37 +++++++++++-------------------------- 1 file changed, 11 insertions(+), 26 deletions(-) diff --git a/src/librustc_lint/unused.rs b/src/librustc_lint/unused.rs index 7a9d18676cf6c..ae178888b6a1c 100644 --- a/src/librustc_lint/unused.rs +++ b/src/librustc_lint/unused.rs @@ -65,9 +65,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnusedResults { ty::Adt(def, _) => { if def.variants.is_empty() { return; - } else { - check_must_use(cx, def.did, s.span, "") } + check_must_use(cx, def.did, s.span, "") }, _ => false, }; @@ -337,21 +336,13 @@ impl EarlyLintPass for UnusedParens { AssignOp(.., ref value) => (value, "assigned value", false), // either function/method call, or something this lint doesn't care about ref call_or_other => { - let args_to_check; - let call_kind; - match *call_or_other { - Call(_, ref args) => { - call_kind = "function"; - args_to_check = &args[..]; - }, - MethodCall(_, ref args) => { - call_kind = "method"; - // first "argument" is self (which sometimes needs parens) - args_to_check = &args[1..]; - } + let (args_to_check, call_kind) = match *call_or_other { + Call(_, ref args) => (&args[..], "function"), + // first "argument" is self (which sometimes needs parens) + MethodCall(_, ref args) => (&args[1..], "method"), // actual catch-all arm _ => { return; } - } + }; // Don't lint if this is a nested macro expansion: otherwise, the lint could // trigger in situations that macro authors shouldn't have to care about, e.g., // when a parenthesized token tree matched in one macro expansion is matched as @@ -372,16 +363,11 @@ impl EarlyLintPass for UnusedParens { } fn check_stmt(&mut self, cx: &EarlyContext, s: &ast::Stmt) { - let (value, msg) = match s.node { - ast::StmtKind::Local(ref local) => { - match local.init { - Some(ref value) => (value, "assigned value"), - None => return, - } + if let ast::StmtKind::Local(ref local) = s.node { + if let Some(ref value) = local.init { + self.check_unused_parens_core(cx, &value, "assigned value", false); } - _ => return, - }; - self.check_unused_parens_core(cx, &value, msg, false); + } } } @@ -414,9 +400,8 @@ impl UnusedImportBraces { let orig_ident = items[0].0.prefix.segments.last().unwrap().ident; if orig_ident.name == keywords::SelfValue.name() { return; - } else { - node_ident = rename.unwrap_or(orig_ident); } + node_ident = rename.unwrap_or(orig_ident); } ast::UseTreeKind::Glob => { node_ident = ast::Ident::from_str("*"); From 832797689012ca63a7c9a7acdc7a4f34322d4faf Mon Sep 17 00:00:00 2001 From: scalexm Date: Wed, 3 Oct 2018 11:47:09 +0200 Subject: [PATCH 09/13] Remove duplicate predicates in `explicit_predicates_of` Fixes #52187. --- src/librustc_typeck/collect.rs | 36 ++++++++++++++++++++++++-- src/test/ui/chalkify/lower_env1.stderr | 6 ++--- 2 files changed, 36 insertions(+), 6 deletions(-) diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index 17e0b0431da6e..f96c85ae7ae3f 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -1637,9 +1637,39 @@ fn explicit_predicates_of<'a, 'tcx>( def_id: DefId, ) -> ty::GenericPredicates<'tcx> { use rustc::hir::*; + use rustc_data_structures::fx::FxHashSet; debug!("explicit_predicates_of(def_id={:?})", def_id); + /// A data structure with unique elements, which preserves order of insertion. + /// Preserving the order of insertion is important here so as not to break + /// compile-fail UI tests. + struct UniquePredicates<'tcx> { + predicates: Vec<(ty::Predicate<'tcx>, Span)>, + uniques: FxHashSet<(ty::Predicate<'tcx>, Span)>, + } + + impl<'tcx> UniquePredicates<'tcx> { + fn new() -> Self { + UniquePredicates { + predicates: vec![], + uniques: FxHashSet::default(), + } + } + + fn push(&mut self, value: (ty::Predicate<'tcx>, Span)) { + if self.uniques.insert(value) { + self.predicates.push(value); + } + } + + fn extend, Span)>>(&mut self, iter: I) { + for value in iter { + self.push(value); + } + } + } + let node_id = tcx.hir.as_local_node_id(def_id).unwrap(); let node = tcx.hir.get(node_id); @@ -1649,7 +1679,7 @@ fn explicit_predicates_of<'a, 'tcx>( let icx = ItemCtxt::new(tcx, def_id); let no_generics = hir::Generics::empty(); - let mut predicates = vec![]; + let mut predicates = UniquePredicates::new(); let ast_generics = match node { Node::TraitItem(item) => &item.generics, @@ -1744,7 +1774,7 @@ fn explicit_predicates_of<'a, 'tcx>( // on a trait we need to add in the supertrait bounds and bounds found on // associated types. if let Some((_trait_ref, _)) = is_trait { - predicates = tcx.super_predicates_of(def_id).predicates; + predicates.extend(tcx.super_predicates_of(def_id).predicates); } // In default impls, we can assume that the self type implements @@ -1895,6 +1925,8 @@ fn explicit_predicates_of<'a, 'tcx>( })) } + let mut predicates = predicates.predicates; + // Subtle: before we store the predicates into the tcx, we // sort them so that predicates like `T: Foo` come // before uses of `U`. This avoids false ambiguity errors diff --git a/src/test/ui/chalkify/lower_env1.stderr b/src/test/ui/chalkify/lower_env1.stderr index d6673f6a8a6fb..4a3e14ac03472 100644 --- a/src/test/ui/chalkify/lower_env1.stderr +++ b/src/test/ui/chalkify/lower_env1.stderr @@ -5,9 +5,8 @@ LL | #[rustc_dump_program_clauses] //~ ERROR program clause dump | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: FromEnv(Self: Foo) :- FromEnv(Self: Bar). - = note: FromEnv(Self: Foo) :- FromEnv(Self: Bar). = note: Implemented(Self: Bar) :- FromEnv(Self: Bar). - = note: WellFormed(Self: Bar) :- Implemented(Self: Bar), WellFormed(Self: Foo), WellFormed(Self: Foo). + = note: WellFormed(Self: Bar) :- Implemented(Self: Bar), WellFormed(Self: Foo). error: program clause dump --> $DIR/lower_env1.rs:19:1 @@ -16,11 +15,10 @@ LL | #[rustc_dump_env_program_clauses] //~ ERROR program clause dump | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: FromEnv(Self: Foo) :- FromEnv(Self: Bar). - = note: FromEnv(Self: Foo) :- FromEnv(Self: Bar). = note: Implemented(Self: Bar) :- FromEnv(Self: Bar). = note: Implemented(Self: Foo) :- FromEnv(Self: Foo). = note: Implemented(Self: std::marker::Sized) :- FromEnv(Self: std::marker::Sized). - = note: WellFormed(Self: Bar) :- Implemented(Self: Bar), WellFormed(Self: Foo), WellFormed(Self: Foo). + = note: WellFormed(Self: Bar) :- Implemented(Self: Bar), WellFormed(Self: Foo). = note: WellFormed(Self: Foo) :- Implemented(Self: Foo). = note: WellFormed(Self: std::marker::Sized) :- Implemented(Self: std::marker::Sized). From f0de294a9b6d09b9933c1a22419831ac4bc49ca9 Mon Sep 17 00:00:00 2001 From: ljedrz Date: Wed, 3 Oct 2018 15:07:18 +0200 Subject: [PATCH 10/13] A handful of cleanups for rustc/mir --- src/librustc/mir/interpret/value.rs | 4 ++-- src/librustc/mir/mod.rs | 31 ++++++++++++----------------- src/librustc/mir/mono.rs | 2 +- src/librustc/mir/tcx.rs | 12 +++++------ 4 files changed, 22 insertions(+), 27 deletions(-) diff --git a/src/librustc/mir/interpret/value.rs b/src/librustc/mir/interpret/value.rs index d695ad88e47aa..c81d55e69b61a 100644 --- a/src/librustc/mir/interpret/value.rs +++ b/src/librustc/mir/interpret/value.rs @@ -171,7 +171,7 @@ impl<'tcx> Scalar { pub fn from_uint(i: impl Into, size: Size) -> Self { let i = i.into(); debug_assert_eq!(truncate(i, size), i, - "Unsigned value {} does not fit in {} bits", i, size.bits()); + "Unsigned value {} does not fit in {} bits", i, size.bits()); Scalar::Bits { bits: i, size: size.bytes() as u8 } } @@ -181,7 +181,7 @@ impl<'tcx> Scalar { // `into` performed sign extension, we have to truncate let truncated = truncate(i as u128, size); debug_assert_eq!(sign_extend(truncated, size) as i128, i, - "Signed value {} does not fit in {} bits", i, size.bits()); + "Signed value {} does not fit in {} bits", i, size.bits()); Scalar::Bits { bits: truncated, size: size.bytes() as u8 } } diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs index f36d9553d31c9..fe88897a82ccc 100644 --- a/src/librustc/mir/mod.rs +++ b/src/librustc/mir/mod.rs @@ -12,7 +12,6 @@ //! //! [rustc guide]: https://rust-lang-nursery.github.io/rustc-guide/mir/index.html -use graphviz::IntoCow; use hir::def::CtorKind; use hir::def_id::DefId; use hir::{self, HirId, InlineAsm}; @@ -327,22 +326,20 @@ impl<'tcx> Mir<'tcx> { if idx < stmts.len() { &stmts[idx].source_info } else { - assert!(idx == stmts.len()); + assert_eq!(idx, stmts.len()); &block.terminator().source_info } } /// Check if `sub` is a sub scope of `sup` pub fn is_sub_scope(&self, mut sub: SourceScope, sup: SourceScope) -> bool { - loop { - if sub == sup { - return true; - } + while sub != sup { match self.source_scopes[sub].parent_scope { None => return false, Some(p) => sub = p, } } + true } /// Return the return type, it always return first element from `local_decls` array @@ -526,9 +523,7 @@ impl BorrowKind { pub fn allows_two_phase_borrow(&self) -> bool { match *self { BorrowKind::Shared | BorrowKind::Shallow | BorrowKind::Unique => false, - BorrowKind::Mut { - allow_two_phase_borrow, - } => allow_two_phase_borrow, + BorrowKind::Mut { allow_two_phase_borrow } => allow_two_phase_borrow, } } } @@ -1551,42 +1546,42 @@ impl<'tcx> TerminatorKind<'tcx> { }; fmt_const_val(&mut s, &c).unwrap(); s.into() - }).chain(iter::once(String::from("otherwise").into())) + }).chain(iter::once("otherwise".into())) .collect() } Call { destination: Some(_), cleanup: Some(_), .. - } => vec!["return".into_cow(), "unwind".into_cow()], + } => vec!["return".into(), "unwind".into()], Call { destination: Some(_), cleanup: None, .. - } => vec!["return".into_cow()], + } => vec!["return".into()], Call { destination: None, cleanup: Some(_), .. - } => vec!["unwind".into_cow()], + } => vec!["unwind".into()], Call { destination: None, cleanup: None, .. } => vec![], - Yield { drop: Some(_), .. } => vec!["resume".into_cow(), "drop".into_cow()], - Yield { drop: None, .. } => vec!["resume".into_cow()], + Yield { drop: Some(_), .. } => vec!["resume".into(), "drop".into()], + Yield { drop: None, .. } => vec!["resume".into()], DropAndReplace { unwind: None, .. } | Drop { unwind: None, .. } => { - vec!["return".into_cow()] + vec!["return".into()] } DropAndReplace { unwind: Some(_), .. } | Drop { unwind: Some(_), .. - } => vec!["return".into_cow(), "unwind".into_cow()], + } => vec!["return".into(), "unwind".into()], Assert { cleanup: None, .. } => vec!["".into()], - Assert { .. } => vec!["success".into_cow(), "unwind".into_cow()], + Assert { .. } => vec!["success".into(), "unwind".into()], FalseEdges { ref imaginary_targets, .. diff --git a/src/librustc/mir/mono.rs b/src/librustc/mir/mono.rs index 4d353a36db02a..7520695a7cd90 100644 --- a/src/librustc/mir/mono.rs +++ b/src/librustc/mir/mono.rs @@ -325,7 +325,7 @@ impl<'a, 'gcx: 'tcx, 'tcx: 'a> CodegenUnitNameBuilder<'a, 'gcx, 'tcx> { String::new() }; - let crate_disambiguator = format!("{}", tcx.crate_disambiguator(cnum)); + let crate_disambiguator = tcx.crate_disambiguator(cnum).to_string(); // Using a shortened disambiguator of about 40 bits format!("{}.{}{}", tcx.crate_name(cnum), diff --git a/src/librustc/mir/tcx.rs b/src/librustc/mir/tcx.rs index 2a25e057a7149..fc7b4862b0ae5 100644 --- a/src/librustc/mir/tcx.rs +++ b/src/librustc/mir/tcx.rs @@ -87,8 +87,8 @@ impl<'a, 'gcx, 'tcx> PlaceTy<'tcx> { assert!(index < adt_def.variants.len()); assert_eq!(adt_def, adt_def1); PlaceTy::Downcast { adt_def, - substs, - variant_index: index } + substs, + variant_index: index } } _ => { bug!("cannot downcast non-ADT type: `{:?}`", self) @@ -151,7 +151,7 @@ impl<'tcx> Place<'tcx> { } }, _ => None, - } + } _ => None, } } @@ -255,9 +255,9 @@ impl<'tcx> Operand<'tcx> { impl<'tcx> BinOp { pub fn ty<'a, 'gcx>(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>, - lhs_ty: Ty<'tcx>, - rhs_ty: Ty<'tcx>) - -> Ty<'tcx> { + lhs_ty: Ty<'tcx>, + rhs_ty: Ty<'tcx>) + -> Ty<'tcx> { // FIXME: handle SIMD correctly match self { &BinOp::Add | &BinOp::Sub | &BinOp::Mul | &BinOp::Div | &BinOp::Rem | From 608adfc3f01c425d2ede9263e6fafaaf7f38b377 Mon Sep 17 00:00:00 2001 From: scalexm Date: Wed, 3 Oct 2018 17:06:28 +0200 Subject: [PATCH 11/13] Introduce `TyKind::UnnormalizedProjection` --- src/librustc/ich/impls_ty.rs | 4 ++-- src/librustc/infer/canonical/canonicalizer.rs | 1 + src/librustc/infer/freshen.rs | 1 + src/librustc/traits/coherence.rs | 1 + src/librustc/traits/error_reporting.rs | 3 ++- src/librustc/traits/query/dropck_outlives.rs | 2 ++ src/librustc/traits/select.rs | 3 +++ src/librustc/ty/context.rs | 2 +- src/librustc/ty/error.rs | 1 + src/librustc/ty/fast_reject.rs | 1 + src/librustc/ty/flags.rs | 2 ++ src/librustc/ty/item_path.rs | 1 + src/librustc/ty/layout.rs | 6 +++--- src/librustc/ty/mod.rs | 2 ++ src/librustc/ty/outlives.rs | 2 ++ src/librustc/ty/structural_impls.rs | 7 ++++++- src/librustc/ty/sty.rs | 9 ++++++++- src/librustc/ty/util.rs | 2 ++ src/librustc/ty/walk.rs | 2 +- src/librustc/ty/wf.rs | 2 ++ src/librustc/util/ppaux.rs | 7 ++++++- src/librustc_codegen_llvm/debuginfo/type_names.rs | 1 + src/librustc_lint/types.rs | 1 + src/librustc_mir/monomorphize/item.rs | 1 + src/librustc_traits/dropck_outlives.rs | 2 ++ src/librustc_typeck/check/cast.rs | 1 + src/librustc_typeck/variance/constraints.rs | 1 + 27 files changed, 57 insertions(+), 11 deletions(-) diff --git a/src/librustc/ich/impls_ty.rs b/src/librustc/ich/impls_ty.rs index 9c4e995e24d01..388abc88cfd71 100644 --- a/src/librustc/ich/impls_ty.rs +++ b/src/librustc/ich/impls_ty.rs @@ -873,8 +873,8 @@ for ty::TyKind<'gcx> Tuple(inner_tys) => { inner_tys.hash_stable(hcx, hasher); } - Projection(ref projection_ty) => { - projection_ty.hash_stable(hcx, hasher); + Projection(ref data) | UnnormalizedProjection(ref data) => { + data.hash_stable(hcx, hasher); } Opaque(def_id, substs) => { def_id.hash_stable(hcx, hasher); diff --git a/src/librustc/infer/canonical/canonicalizer.rs b/src/librustc/infer/canonical/canonicalizer.rs index b30ccb5976c98..6449227af4ab8 100644 --- a/src/librustc/infer/canonical/canonicalizer.rs +++ b/src/librustc/infer/canonical/canonicalizer.rs @@ -283,6 +283,7 @@ impl<'cx, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for Canonicalizer<'cx, 'gcx, 'tcx> | ty::Never | ty::Tuple(..) | ty::Projection(..) + | ty::UnnormalizedProjection(..) | ty::Foreign(..) | ty::Param(..) | ty::Opaque(..) => { diff --git a/src/librustc/infer/freshen.rs b/src/librustc/infer/freshen.rs index 1cb813c39e68c..e17e777332ec6 100644 --- a/src/librustc/infer/freshen.rs +++ b/src/librustc/infer/freshen.rs @@ -193,6 +193,7 @@ impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for TypeFreshener<'a, 'gcx, 'tcx> { ty::Never | ty::Tuple(..) | ty::Projection(..) | + ty::UnnormalizedProjection(..) | ty::Foreign(..) | ty::Param(..) | ty::Closure(..) | diff --git a/src/librustc/traits/coherence.rs b/src/librustc/traits/coherence.rs index 7401d4099ff6d..caf549e37a907 100644 --- a/src/librustc/traits/coherence.rs +++ b/src/librustc/traits/coherence.rs @@ -475,6 +475,7 @@ fn ty_is_local_constructor(ty: Ty<'_>, in_crate: InCrate) -> bool { ty::Error => true, + ty::UnnormalizedProjection(..) | ty::Closure(..) | ty::Generator(..) | ty::GeneratorWitness(..) | diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs index 7695f26d70115..3b3e38a8bb7ca 100644 --- a/src/librustc/traits/error_reporting.rs +++ b/src/librustc/traits/error_reporting.rs @@ -269,7 +269,8 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { ty::Generator(..) => Some(18), ty::Foreign(..) => Some(19), ty::GeneratorWitness(..) => Some(20), - ty::Infer(..) | ty::Error => None + ty::Infer(..) | ty::Error => None, + ty::UnnormalizedProjection(..) => bug!("only used with chalk-engine"), } } diff --git a/src/librustc/traits/query/dropck_outlives.rs b/src/librustc/traits/query/dropck_outlives.rs index f5fb183ec1a5d..aaf03f8e7fb55 100644 --- a/src/librustc/traits/query/dropck_outlives.rs +++ b/src/librustc/traits/query/dropck_outlives.rs @@ -253,5 +253,7 @@ pub fn trivial_dropck_outlives<'tcx>(tcx: TyCtxt<'_, '_, 'tcx>, ty: Ty<'tcx>) -> | ty::Opaque(..) | ty::Infer(_) | ty::Generator(..) => false, + + ty::UnnormalizedProjection(..) => bug!("only used with chalk-engine"), } } diff --git a/src/librustc/traits/select.rs b/src/librustc/traits/select.rs index 268b8e0161b6d..0ea9098378be5 100644 --- a/src/librustc/traits/select.rs +++ b/src/librustc/traits/select.rs @@ -2200,6 +2200,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { ty::Projection(_) | ty::Param(_) | ty::Opaque(..) => None, ty::Infer(ty::TyVar(_)) => Ambiguous, + ty::UnnormalizedProjection(..) | ty::Infer(ty::CanonicalTy(_)) | ty::Infer(ty::FreshTy(_)) | ty::Infer(ty::FreshIntTy(_)) | @@ -2272,6 +2273,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { Ambiguous } + ty::UnnormalizedProjection(..) | ty::Infer(ty::CanonicalTy(_)) | ty::Infer(ty::FreshTy(_)) | ty::Infer(ty::FreshIntTy(_)) | @@ -2310,6 +2312,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { Vec::new() } + ty::UnnormalizedProjection(..) | ty::Dynamic(..) | ty::Param(..) | ty::Foreign(..) | diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index 64e9d15092eb8..29b3db400b116 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -2266,7 +2266,7 @@ impl<'a, 'tcx> TyCtxt<'a, 'tcx, 'tcx> { self, Adt, Array, Slice, RawPtr, Ref, FnDef, FnPtr, Generator, GeneratorWitness, Dynamic, Closure, Tuple, - Param, Infer, Projection, Opaque, Foreign); + Param, Infer, UnnormalizedProjection, Projection, Opaque, Foreign); println!("Substs interner: #{}", self.interners.substs.borrow().len()); println!("Region interner: #{}", self.interners.region.borrow().len()); diff --git a/src/librustc/ty/error.rs b/src/librustc/ty/error.rs index 9f9d918415e7e..b3a1b312ca1d3 100644 --- a/src/librustc/ty/error.rs +++ b/src/librustc/ty/error.rs @@ -222,6 +222,7 @@ impl<'a, 'gcx, 'lcx, 'tcx> ty::TyS<'tcx> { ty::Infer(ty::FreshIntTy(_)) => "skolemized integral type".to_string(), ty::Infer(ty::FreshFloatTy(_)) => "skolemized floating-point type".to_string(), ty::Projection(_) => "associated type".to_string(), + ty::UnnormalizedProjection(_) => "non-normalized associated type".to_string(), ty::Param(ref p) => { if p.is_self() { "Self".to_string() diff --git a/src/librustc/ty/fast_reject.rs b/src/librustc/ty/fast_reject.rs index 2d055fd307dc4..0f68e7aba4def 100644 --- a/src/librustc/ty/fast_reject.rs +++ b/src/librustc/ty/fast_reject.rs @@ -103,6 +103,7 @@ pub fn simplify_type<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>, ty::FnPtr(ref f) => { Some(FunctionSimplifiedType(f.skip_binder().inputs().len())) } + ty::UnnormalizedProjection(..) => bug!("only used with chalk-engine"), ty::Projection(_) | ty::Param(_) => { if can_simplify_params { // In normalized types, projections don't unify with diff --git a/src/librustc/ty/flags.rs b/src/librustc/ty/flags.rs index 08d1057823873..3ccc24e73a5c9 100644 --- a/src/librustc/ty/flags.rs +++ b/src/librustc/ty/flags.rs @@ -150,6 +150,8 @@ impl FlagComputation { self.add_projection_ty(data); } + &ty::UnnormalizedProjection(..) => bug!("only used with chalk-engine"), + &ty::Opaque(_, substs) => { self.add_flags(TypeFlags::HAS_PROJECTION); self.add_substs(substs); diff --git a/src/librustc/ty/item_path.rs b/src/librustc/ty/item_path.rs index c8d104e6c321f..46d133224f819 100644 --- a/src/librustc/ty/item_path.rs +++ b/src/librustc/ty/item_path.rs @@ -463,6 +463,7 @@ pub fn characteristic_def_id_of_type(ty: Ty<'_>) -> Option { ty::Str | ty::FnPtr(_) | ty::Projection(_) | + ty::UnnormalizedProjection(..) | ty::Param(_) | ty::Opaque(..) | ty::Infer(_) | diff --git a/src/librustc/ty/layout.rs b/src/librustc/ty/layout.rs index 8bfe46568eb19..7df8af5fa2e7d 100644 --- a/src/librustc/ty/layout.rs +++ b/src/librustc/ty/layout.rs @@ -1123,7 +1123,7 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> { } tcx.layout_raw(param_env.and(normalized))? } - ty::GeneratorWitness(..) | ty::Infer(_) => { + ty::UnnormalizedProjection(..) | ty::GeneratorWitness(..) | ty::Infer(_) => { bug!("LayoutDetails::compute: unexpected type `{}`", ty) } ty::Param(_) | ty::Error => { @@ -1702,8 +1702,8 @@ impl<'a, 'tcx, C> TyLayoutMethods<'tcx, C> for Ty<'tcx> } } - ty::Projection(_) | ty::Opaque(..) | ty::Param(_) | - ty::Infer(_) | ty::Error => { + ty::Projection(_) | ty::UnnormalizedProjection(..) | + ty::Opaque(..) | ty::Param(_) | ty::Infer(_) | ty::Error => { bug!("TyLayout::field_type: unexpected type `{}`", this.ty) } }) diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index b2281691bd660..77e0b9e91bce6 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -2339,6 +2339,8 @@ impl<'a, 'gcx, 'tcx> AdtDef { vec![ty] } + UnnormalizedProjection(..) => bug!("only used with chalk-engine"), + Param(..) => { // perf hack: if there is a `T: Sized` bound, then // we know that `T` is Sized and do not need to check diff --git a/src/librustc/ty/outlives.rs b/src/librustc/ty/outlives.rs index 68f6707087687..91eda66e08c6e 100644 --- a/src/librustc/ty/outlives.rs +++ b/src/librustc/ty/outlives.rs @@ -124,6 +124,8 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { } } + ty::UnnormalizedProjection(..) => bug!("only used with chalk-engine"), + // We assume that inference variables are fully resolved. // So, if we encounter an inference variable, just record // the unresolved variable as a component. diff --git a/src/librustc/ty/structural_impls.rs b/src/librustc/ty/structural_impls.rs index aab268c07c4fb..c3c4cbed89d88 100644 --- a/src/librustc/ty/structural_impls.rs +++ b/src/librustc/ty/structural_impls.rs @@ -876,6 +876,9 @@ impl<'tcx> TypeFoldable<'tcx> for Ty<'tcx> { ty::GeneratorWitness(types) => ty::GeneratorWitness(types.fold_with(folder)), ty::Closure(did, substs) => ty::Closure(did, substs.fold_with(folder)), ty::Projection(ref data) => ty::Projection(data.fold_with(folder)), + ty::UnnormalizedProjection(ref data) => { + ty::UnnormalizedProjection(data.fold_with(folder)) + } ty::Opaque(did, substs) => ty::Opaque(did, substs.fold_with(folder)), ty::Bool | ty::Char | ty::Str | ty::Int(_) | ty::Uint(_) | ty::Float(_) | ty::Error | ty::Infer(_) | @@ -910,7 +913,9 @@ impl<'tcx> TypeFoldable<'tcx> for Ty<'tcx> { } ty::GeneratorWitness(ref types) => types.visit_with(visitor), ty::Closure(_did, ref substs) => substs.visit_with(visitor), - ty::Projection(ref data) => data.visit_with(visitor), + ty::Projection(ref data) | ty::UnnormalizedProjection(ref data) => { + data.visit_with(visitor) + } ty::Opaque(_, ref substs) => substs.visit_with(visitor), ty::Bool | ty::Char | ty::Str | ty::Int(_) | ty::Uint(_) | ty::Float(_) | ty::Error | ty::Infer(_) | diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs index 6c40dd8923916..06d559fd9dbea 100644 --- a/src/librustc/ty/sty.rs +++ b/src/librustc/ty/sty.rs @@ -157,6 +157,11 @@ pub enum TyKind<'tcx> { /// `>::N`. Projection(ProjectionTy<'tcx>), + /// A placeholder type used when we do not have enough information + /// to normalize the projection of an associated type to an + /// existing concrete type. Currently only used with chalk-engine. + UnnormalizedProjection(ProjectionTy<'tcx>), + /// Opaque (`impl Trait`) type found in a return type. /// The `DefId` comes either from /// * the `impl Trait` ast::Ty node, @@ -1806,7 +1811,7 @@ impl<'a, 'gcx, 'tcx> TyS<'tcx> { Generator(_, GeneratorSubsts { ref substs }, _) => { substs.regions().collect() } - Projection(ref data) => { + Projection(ref data) | UnnormalizedProjection(ref data) => { data.substs.regions().collect() } FnDef(..) | @@ -1886,6 +1891,8 @@ impl<'a, 'gcx, 'tcx> TyS<'tcx> { ty::Projection(_) | ty::Param(_) | ty::Opaque(..) => false, + ty::UnnormalizedProjection(..) => bug!("only used with chalk-engine"), + ty::Infer(ty::TyVar(_)) => false, ty::Infer(ty::CanonicalTy(_)) | diff --git a/src/librustc/ty/util.rs b/src/librustc/ty/util.rs index 93fc77359e43a..4d7bab3cf433b 100644 --- a/src/librustc/ty/util.rs +++ b/src/librustc/ty/util.rs @@ -958,6 +958,8 @@ fn needs_drop_raw<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, ty::Dynamic(..) | ty::Projection(..) | ty::Param(_) | ty::Opaque(..) | ty::Infer(_) | ty::Error => true, + ty::UnnormalizedProjection(..) => bug!("only used with chalk-engine"), + // Structural recursion. ty::Array(ty, _) | ty::Slice(ty) => needs_drop(ty), diff --git a/src/librustc/ty/walk.rs b/src/librustc/ty/walk.rs index cf87c2d457471..d20c4f716429b 100644 --- a/src/librustc/ty/walk.rs +++ b/src/librustc/ty/walk.rs @@ -97,7 +97,7 @@ fn push_subtypes<'tcx>(stack: &mut TypeWalkerStack<'tcx>, parent_ty: Ty<'tcx>) { ty::Ref(_, ty, _) => { stack.push(ty); } - ty::Projection(ref data) => { + ty::Projection(ref data) | ty::UnnormalizedProjection(ref data) => { stack.extend(data.substs.types().rev()); } ty::Dynamic(ref obj, ..) => { diff --git a/src/librustc/ty/wf.rs b/src/librustc/ty/wf.rs index 63206a660df41..397c63a149a4c 100644 --- a/src/librustc/ty/wf.rs +++ b/src/librustc/ty/wf.rs @@ -289,6 +289,8 @@ impl<'a, 'gcx, 'tcx> WfPredicates<'a, 'gcx, 'tcx> { self.compute_projection(data); } + ty::UnnormalizedProjection(..) => bug!("only used with chalk-engine"), + ty::Adt(def, substs) => { // WfNominalType let obligations = self.nominal_obligations(def.did, substs); diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs index 10382008e0d43..814f8880bbf2f 100644 --- a/src/librustc/util/ppaux.rs +++ b/src/librustc/util/ppaux.rs @@ -18,7 +18,7 @@ use ty::{Bool, Char, Adt}; use ty::{Error, Str, Array, Slice, Float, FnDef, FnPtr}; use ty::{Param, RawPtr, Ref, Never, Tuple}; use ty::{Closure, Generator, GeneratorWitness, Foreign, Projection, Opaque}; -use ty::{Dynamic, Int, Uint, Infer}; +use ty::{UnnormalizedProjection, Dynamic, Int, Uint, Infer}; use ty::{self, RegionVid, Ty, TyCtxt, TypeFoldable, GenericParamCount, GenericParamDefKind}; use util::nodemap::FxHashSet; @@ -1143,6 +1143,11 @@ define_print! { } Foreign(def_id) => parameterized(f, subst::Substs::empty(), def_id, &[]), Projection(ref data) => data.print(f, cx), + UnnormalizedProjection(ref data) => { + write!(f, "Unnormalized(")?; + data.print(f, cx)?; + write!(f, ")") + } Opaque(def_id, substs) => { if cx.is_verbose { return write!(f, "Opaque({:?}, {:?})", def_id, substs); diff --git a/src/librustc_codegen_llvm/debuginfo/type_names.rs b/src/librustc_codegen_llvm/debuginfo/type_names.rs index f9eb80a1988af..2f110fd552a8d 100644 --- a/src/librustc_codegen_llvm/debuginfo/type_names.rs +++ b/src/librustc_codegen_llvm/debuginfo/type_names.rs @@ -173,6 +173,7 @@ pub fn push_debuginfo_type_name<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, } ty::Error | ty::Infer(_) | + ty::UnnormalizedProjection(..) | ty::Projection(..) | ty::Opaque(..) | ty::GeneratorWitness(..) | diff --git a/src/librustc_lint/types.rs b/src/librustc_lint/types.rs index 01d4d0f8cdb67..a441f7a87f763 100644 --- a/src/librustc_lint/types.rs +++ b/src/librustc_lint/types.rs @@ -722,6 +722,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { ty::Closure(..) | ty::Generator(..) | ty::GeneratorWitness(..) | + ty::UnnormalizedProjection(..) | ty::Projection(..) | ty::Opaque(..) | ty::FnDef(..) => bug!("Unexpected type in foreign function"), diff --git a/src/librustc_mir/monomorphize/item.rs b/src/librustc_mir/monomorphize/item.rs index 3f5a05f9d0ed8..f0ea93bfffd3e 100644 --- a/src/librustc_mir/monomorphize/item.rs +++ b/src/librustc_mir/monomorphize/item.rs @@ -382,6 +382,7 @@ impl<'a, 'tcx> DefPathBasedNames<'a, 'tcx> { } ty::Error | ty::Infer(_) | + ty::UnnormalizedProjection(..) | ty::Projection(..) | ty::Param(_) | ty::GeneratorWitness(_) | diff --git a/src/librustc_traits/dropck_outlives.rs b/src/librustc_traits/dropck_outlives.rs index e3ec2e6b9ce02..2996fe0320042 100644 --- a/src/librustc_traits/dropck_outlives.rs +++ b/src/librustc_traits/dropck_outlives.rs @@ -272,6 +272,8 @@ fn dtorck_constraint_for_ty<'a, 'gcx, 'tcx>( overflows: vec![], }), + ty::UnnormalizedProjection(..) => bug!("only used with chalk-engine"), + ty::Infer(..) | ty::Error => { // By the time this code runs, all type variables ought to // be fully resolved. diff --git a/src/librustc_typeck/check/cast.rs b/src/librustc_typeck/check/cast.rs index 564ecae15dc35..285fed9544ddb 100644 --- a/src/librustc_typeck/check/cast.rs +++ b/src/librustc_typeck/check/cast.rs @@ -124,6 +124,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { ty::Foreign(..) => Some(PointerKind::Thin), // We should really try to normalize here. ty::Projection(ref pi) => Some(PointerKind::OfProjection(pi)), + ty::UnnormalizedProjection(..) => bug!("only used with chalk-engine"), ty::Opaque(def_id, substs) => Some(PointerKind::OfOpaque(def_id, substs)), ty::Param(ref p) => Some(PointerKind::OfParam(p)), // Insufficient type information. diff --git a/src/librustc_typeck/variance/constraints.rs b/src/librustc_typeck/variance/constraints.rs index 95544da0b8e0d..1125de55a0668 100644 --- a/src/librustc_typeck/variance/constraints.rs +++ b/src/librustc_typeck/variance/constraints.rs @@ -336,6 +336,7 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> { // types, where we use Error as the Self type } + ty::UnnormalizedProjection(..) | ty::GeneratorWitness(..) | ty::Infer(..) => { bug!("unexpected type encountered in \ From edb3f9777b179c3da4519ec39ffd50f96e8f664c Mon Sep 17 00:00:00 2001 From: scalexm Date: Wed, 3 Oct 2018 18:49:27 +0200 Subject: [PATCH 12/13] Fix `ty::UnnormalizedProjection` in rustdoc --- src/librustdoc/clean/mod.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 371b631723a39..9b305ad03b056 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -2737,6 +2737,7 @@ impl<'tcx> Clean for Ty<'tcx> { ty::Closure(..) | ty::Generator(..) => Tuple(vec![]), // FIXME(pcwalton) + ty::UnnormalizedProjection(..) => panic!("UnnormalizedProjection"), ty::GeneratorWitness(..) => panic!("GeneratorWitness"), ty::Infer(..) => panic!("Infer"), ty::Error => panic!("Error"), From b14dc69ee820f4d9859eabd14b8546883ed5e2ad Mon Sep 17 00:00:00 2001 From: Andy Russell Date: Wed, 3 Oct 2018 14:29:02 -0400 Subject: [PATCH 13/13] remove padding from multiline format string label Fixes #53836. --- src/libfmt_macros/lib.rs | 2 +- src/test/ui/if/ifmt-bad-arg.rs | 14 ++++++++++++++ src/test/ui/if/ifmt-bad-arg.stderr | 8 +++++++- 3 files changed, 22 insertions(+), 2 deletions(-) diff --git a/src/libfmt_macros/lib.rs b/src/libfmt_macros/lib.rs index 2a38464d7c1ee..7d87c1839d78c 100644 --- a/src/libfmt_macros/lib.rs +++ b/src/libfmt_macros/lib.rs @@ -288,7 +288,7 @@ impl<'a> Parser<'a> { self.cur.next(); Some(pos) } else { - let pos = pos + padding + 1; + let pos = pos + raw + 1; self.err(format!("expected `{:?}`, found `{:?}`", c, maybe), format!("expected `{}`", c), pos, diff --git a/src/test/ui/if/ifmt-bad-arg.rs b/src/test/ui/if/ifmt-bad-arg.rs index bbd75f30d6cb1..6f051b40e8b65 100644 --- a/src/test/ui/if/ifmt-bad-arg.rs +++ b/src/test/ui/if/ifmt-bad-arg.rs @@ -71,4 +71,18 @@ fn main() { "##); //~^^^ ERROR: there is no argument named `foo` + + // bad syntax in format string with multiple newlines, #53836 + format!("first number: {} +second number: {} +third number: {} +fourth number: {} +fifth number: {} +sixth number: {} +seventh number: {} +eighth number: {} +ninth number: { +tenth number: {}", + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10); + //~^^ ERROR: invalid format string } diff --git a/src/test/ui/if/ifmt-bad-arg.stderr b/src/test/ui/if/ifmt-bad-arg.stderr index c8fd8bad19ba5..7e71707c22b16 100644 --- a/src/test/ui/if/ifmt-bad-arg.stderr +++ b/src/test/ui/if/ifmt-bad-arg.stderr @@ -204,5 +204,11 @@ error: there is no argument named `foo` LL | {foo} | ^^^^^ -error: aborting due to 27 previous errors +error: invalid format string: expected `'}'`, found `'t'` + --> $DIR/ifmt-bad-arg.rs:85:1 + | +LL | tenth number: {}", + | ^ expected `}` in format string + +error: aborting due to 28 previous errors