From e0eb65e48ad413dc7e5871c12cfb3f087913fa2e Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Sat, 9 May 2020 13:29:29 -0400 Subject: [PATCH 01/19] Use 1.43.1 release --- src/stage0.txt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/stage0.txt b/src/stage0.txt index 920b0e3bef1c6..de57423fd1a56 100644 --- a/src/stage0.txt +++ b/src/stage0.txt @@ -12,8 +12,8 @@ # source tarball for a stable release you'll likely see `1.x.0` for rustc and # `0.x.0` for Cargo where they were released on `date`. -date: 2020-04-21 -rustc: 1.43.0 +date: 2020-05-07 +rustc: 1.43.1 cargo: 0.44.0 # We use a nightly rustfmt to format the source because it solves some @@ -40,4 +40,4 @@ cargo: 0.44.0 # looking at a beta source tarball and it's uncommented we'll shortly comment it # out. -dev: 1 +#dev: 1 From 9d1bf800c18b31e1b6b86b84e74fdac0e4c15b3d Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Wed, 6 May 2020 19:19:34 -0700 Subject: [PATCH 02/19] [beta] Update cargo --- src/tools/cargo | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/cargo b/src/tools/cargo index ebda5065ee8a1..05d080faa4f2b 160000 --- a/src/tools/cargo +++ b/src/tools/cargo @@ -1 +1 @@ -Subproject commit ebda5065ee8a1e46801380abcbac21a25bc7e755 +Subproject commit 05d080faa4f2bc1e389ea7c4fd8f30ed2b733a7f From 419f909ce70940f8f4cc78ba870862538aa1b898 Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Fri, 1 May 2020 13:18:15 -0700 Subject: [PATCH 03/19] backport 1.43.1 release notes --- RELEASES.md | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/RELEASES.md b/RELEASES.md index 36597b1864f25..8ea481f7e18cd 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -1,3 +1,15 @@ +Version 1.43.1 (2020-05-07) +=========================== + +* [Updated openssl-src to 1.1.1g for CVE-2020-1967.][71430] +* [Fixed the stabilization of AVX-512 features.][71473] +* [Fixed `cargo package --list` not working with unpublished dependencies.][cargo/8151] + +[71430]: https://github.com/rust-lang/rust/pull/71430 +[71473]: https://github.com/rust-lang/rust/issues/71473 +[cargo/8151]: https://github.com/rust-lang/cargo/issues/8151 + + Version 1.43.0 (2020-04-23) ========================== @@ -14,7 +26,7 @@ Language - [Merge `fn` syntax + cleanup item parsing.][68728] - [`item` macro fragments can be interpolated into `trait`s, `impl`s, and `extern` blocks.][69366] For example, you may now write: - ```rust + ```rust macro_rules! mac_trait { ($i:item) => { trait T { $i } @@ -82,7 +94,7 @@ Misc - [Certain checks in the `const_err` lint were deemed unrelated to const evaluation][69185], and have been moved to the `unconditional_panic` and `arithmetic_overflow` lints. - + Compatibility Notes ------------------- @@ -173,7 +185,7 @@ Language (e.g. `type Foo: Ord;`). - `...` (the C-variadic type) may occur syntactically directly as the type of any function parameter. - + These are still rejected *semantically*, so you will likely receive an error but these changes can be seen and parsed by procedural macros and conditional compilation. @@ -465,7 +477,7 @@ Compatibility Notes - [Using `#[inline]` on function prototypes and consts now emits a warning under `unused_attribute` lint.][65294] Using `#[inline]` anywhere else inside traits or `extern` blocks now correctly emits a hard error. - + [65294]: https://github.com/rust-lang/rust/pull/65294/ [66103]: https://github.com/rust-lang/rust/pull/66103/ [65843]: https://github.com/rust-lang/rust/pull/65843/ From 85ad1b56fb7feb748b7ad371ab8bef521d7c1293 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Mon, 4 May 2020 08:35:45 -0700 Subject: [PATCH 04/19] Update the `cc` crate Pulls in updated MSVC detection logic landed in alexcrichton/cc-rs#488 --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 73cb611d79f18..3ec6ac180b431 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -412,9 +412,9 @@ version = "0.1.0" [[package]] name = "cc" -version = "1.0.50" +version = "1.0.52" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95e28fa049fda1c330bcf9d723be7663a899c4679724b34c81e9f5a326aab8cd" +checksum = "c3d87b23d6a92cd03af510a5ade527033f6aa6fa92161e2d5863a907d4c5e31d" dependencies = [ "jobserver", ] From c30ae234521cf379f4715951a0c710673ee15164 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Sun, 3 May 2020 17:35:14 +0300 Subject: [PATCH 05/19] resolve: Relax fresh binding disambiguation slightly to fix regression --- src/librustc_resolve/late.rs | 16 ++++++++++------ src/test/ui/binding/ambiguity-item.rs | 1 + 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/src/librustc_resolve/late.rs b/src/librustc_resolve/late.rs index 67713b5636965..6f6e5fc8659c2 100644 --- a/src/librustc_resolve/late.rs +++ b/src/librustc_resolve/late.rs @@ -1522,11 +1522,20 @@ impl<'a, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { ident: Ident, has_sub: bool, ) -> Option { + // An immutable (no `mut`) by-value (no `ref`) binding pattern without + // a sub pattern (no `@ $pat`) is syntactically ambiguous as it could + // also be interpreted as a path to e.g. a constant, variant, etc. + let is_syntactic_ambiguity = !has_sub && bm == BindingMode::ByValue(Mutability::Not); + let ls_binding = self.resolve_ident_in_lexical_scope(ident, ValueNS, None, pat.span)?; let (res, binding) = match ls_binding { - LexicalScopeBinding::Item(binding) if binding.is_ambiguity() => { + LexicalScopeBinding::Item(binding) + if is_syntactic_ambiguity && binding.is_ambiguity() => + { // For ambiguous bindings we don't know all their definitions and cannot check // whether they can be shadowed by fresh bindings or not, so force an error. + // issues/33118#issuecomment-233962221 (see below) still applies here, + // but we have to ignore it for backward compatibility. self.r.record_use(ident, ValueNS, binding, false); return None; } @@ -1534,11 +1543,6 @@ impl<'a, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { LexicalScopeBinding::Res(res) => (res, None), }; - // An immutable (no `mut`) by-value (no `ref`) binding pattern without - // a sub pattern (no `@ $pat`) is syntactically ambiguous as it could - // also be interpreted as a path to e.g. a constant, variant, etc. - let is_syntactic_ambiguity = !has_sub && bm == BindingMode::ByValue(Mutability::Not); - match res { Res::SelfCtor(_) // See #70549. | Res::Def( diff --git a/src/test/ui/binding/ambiguity-item.rs b/src/test/ui/binding/ambiguity-item.rs index 10613cc616413..0f48340c2cd33 100644 --- a/src/test/ui/binding/ambiguity-item.rs +++ b/src/test/ui/binding/ambiguity-item.rs @@ -14,5 +14,6 @@ fn main() { let v = f; //~ ERROR `f` is ambiguous match v { f => {} //~ ERROR `f` is ambiguous + mut f => {} // OK, unambiguously a fresh binding due to `mut` } } From e0674ef1551d5ad8c75d11d63e88c9eede13afbf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Sat, 2 May 2020 12:50:57 -0700 Subject: [PATCH 06/19] Do not try to find binop method on RHS `TyErr` Fix #71798. --- src/librustc_typeck/check/op.rs | 2 +- src/test/ui/issues-71798.rs | 7 +++++++ src/test/ui/issues-71798.stderr | 20 ++++++++++++++++++++ 3 files changed, 28 insertions(+), 1 deletion(-) create mode 100644 src/test/ui/issues-71798.rs create mode 100644 src/test/ui/issues-71798.stderr diff --git a/src/librustc_typeck/check/op.rs b/src/librustc_typeck/check/op.rs index cac9113fd5d30..23004cf364725 100644 --- a/src/librustc_typeck/check/op.rs +++ b/src/librustc_typeck/check/op.rs @@ -251,7 +251,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } Err(()) => { // error types are considered "builtin" - if !lhs_ty.references_error() { + if !lhs_ty.references_error() && !rhs_ty.references_error() { let source_map = self.tcx.sess.source_map(); match is_assign { IsAssign::Yes => { diff --git a/src/test/ui/issues-71798.rs b/src/test/ui/issues-71798.rs new file mode 100644 index 0000000000000..08b10463d3927 --- /dev/null +++ b/src/test/ui/issues-71798.rs @@ -0,0 +1,7 @@ +fn test_ref(x: &u32) -> impl std::future::Future + '_ { + *x //~^ ERROR the trait bound `u32: std::future::Future` is not satisfied +} + +fn main() { + let _ = test_ref & u; //~ ERROR cannot find value `u` in this scope +} diff --git a/src/test/ui/issues-71798.stderr b/src/test/ui/issues-71798.stderr new file mode 100644 index 0000000000000..85da87914e768 --- /dev/null +++ b/src/test/ui/issues-71798.stderr @@ -0,0 +1,20 @@ +error[E0425]: cannot find value `u` in this scope + --> $DIR/issues-71798.rs:6:24 + | +LL | let _ = test_ref & u; + | ^ not found in this scope + +error[E0277]: the trait bound `u32: std::future::Future` is not satisfied + --> $DIR/issues-71798.rs:1:25 + | +LL | fn test_ref(x: &u32) -> impl std::future::Future + '_ { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::future::Future` is not implemented for `u32` +LL | *x + | -- this returned value is of type `u32` + | + = note: the return type of a function must have a statically known size + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0277, E0425. +For more information about an error, try `rustc --explain E0277`. From 13c28adfd5109a8836d13f25476bbe2ca63bab03 Mon Sep 17 00:00:00 2001 From: flip1995 Date: Fri, 24 Apr 2020 18:22:18 +0200 Subject: [PATCH 07/19] Quick and dirty fix of the unused_braces lint Adresses #70814 --- src/librustc_lint/unused.rs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/librustc_lint/unused.rs b/src/librustc_lint/unused.rs index a3748a3a9fede..ddd252cb290e4 100644 --- a/src/librustc_lint/unused.rs +++ b/src/librustc_lint/unused.rs @@ -16,7 +16,7 @@ use rustc_middle::ty::{self, Ty}; use rustc_session::lint::builtin::UNUSED_ATTRIBUTES; use rustc_span::symbol::Symbol; use rustc_span::symbol::{kw, sym}; -use rustc_span::{BytePos, Span}; +use rustc_span::{BytePos, Span, DUMMY_SP}; use log::debug; @@ -415,6 +415,12 @@ trait UnusedDelimLint { msg: &str, keep_space: (bool, bool), ) { + // FIXME(flip1995): Quick and dirty fix for #70814. This should be fixed in rustdoc + // properly. + if span == DUMMY_SP { + return; + } + cx.struct_span_lint(self.lint(), span, |lint| { let span_msg = format!("unnecessary {} around {}", Self::DELIM_STR, msg); let mut err = lint.build(&span_msg); From cd1fb13fb762ceceb5b4c44def0991d9fab054ed Mon Sep 17 00:00:00 2001 From: flip1995 Date: Fri, 24 Apr 2020 18:22:59 +0200 Subject: [PATCH 08/19] Add rustdoc regression test for the unused_braces lint --- src/test/rustdoc-ui/unused-braces-lint.rs | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 src/test/rustdoc-ui/unused-braces-lint.rs diff --git a/src/test/rustdoc-ui/unused-braces-lint.rs b/src/test/rustdoc-ui/unused-braces-lint.rs new file mode 100644 index 0000000000000..be0e31e4be2ff --- /dev/null +++ b/src/test/rustdoc-ui/unused-braces-lint.rs @@ -0,0 +1,14 @@ +// check-pass + +// This tests the bug in #70814, where the unused_braces lint triggered on the following code +// without providing a span. + +#![deny(unused_braces)] + +fn main() { + { + { + use std; + } + } +} From e5f529c1449cb3791d645ce22cfa30db56dd3a96 Mon Sep 17 00:00:00 2001 From: Amanieu d'Antras Date: Fri, 24 Apr 2020 00:38:10 +0100 Subject: [PATCH 09/19] Update stdarch submodule --- src/stdarch | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/stdarch b/src/stdarch index b00ecbeb268ee..d10eefc62284c 160000 --- a/src/stdarch +++ b/src/stdarch @@ -1 +1 @@ -Subproject commit b00ecbeb268ee97cef9fa9b2375e6f6cf0864db2 +Subproject commit d10eefc62284c40c5a95a2eed19fc1f414a5364d From 8f65cf3dd987d5fa3afbb1df8eeb4c1ffdc42717 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Thu, 23 Apr 2020 18:14:01 -0300 Subject: [PATCH 10/19] normalize field projection ty to fix broken MIR issue --- src/librustc_mir/borrow_check/type_check/mod.rs | 1 + src/test/ui/consts/issue-70773-mir-typeck-lt-norm.rs | 1 + 2 files changed, 2 insertions(+) diff --git a/src/librustc_mir/borrow_check/type_check/mod.rs b/src/librustc_mir/borrow_check/type_check/mod.rs index bd85b48bf4b98..c5ff89d728b37 100644 --- a/src/librustc_mir/borrow_check/type_check/mod.rs +++ b/src/librustc_mir/borrow_check/type_check/mod.rs @@ -690,6 +690,7 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> { let fty = self.sanitize_type(place, fty); match self.field_ty(place, base, field, location) { Ok(ty) => { + let ty = self.cx.normalize(ty, location); if let Err(terr) = self.cx.eq_types( ty, fty, diff --git a/src/test/ui/consts/issue-70773-mir-typeck-lt-norm.rs b/src/test/ui/consts/issue-70773-mir-typeck-lt-norm.rs index 07af83104241c..9d44aa1361cfc 100644 --- a/src/test/ui/consts/issue-70773-mir-typeck-lt-norm.rs +++ b/src/test/ui/consts/issue-70773-mir-typeck-lt-norm.rs @@ -7,6 +7,7 @@ fn init_hash(_: &mut [u8; HASH_LEN]) {} fn foo<'a>() -> &'a () { Hash([0; HASH_LEN]); init_hash(&mut [0; HASH_LEN]); + let (_array,) = ([0; HASH_LEN],); &() } From 2ddec8cc112f80e74385b10688f2ccc68091f76e Mon Sep 17 00:00:00 2001 From: Pietro Albini Date: Wed, 22 Apr 2020 16:21:54 +0200 Subject: [PATCH 11/19] update openssl-src to 1.1.1g Fixes CVE-2020-1967. --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 3ec6ac180b431..85a94b4f59912 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2298,9 +2298,9 @@ checksum = "77af24da69f9d9341038eba93a073b1fdaaa1b788221b00a69bce9e762cb32de" [[package]] name = "openssl-src" -version = "111.8.1+1.1.1f" +version = "111.9.0+1.1.1g" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f04f0299a91de598dde58d2e99101895498dcf3d58896a3297798f28b27c8b72" +checksum = "a2dbe10ddd1eb335aba3780eb2eaa13e1b7b441d2562fd962398740927f39ec4" dependencies = [ "cc", ] From ac64f87dba09cf257436d8ed12ad2a5fe1a0a900 Mon Sep 17 00:00:00 2001 From: YI Date: Wed, 22 Apr 2020 20:18:22 +0800 Subject: [PATCH 12/19] fix error code for E0751 --- src/librustc_error_codes/error_codes/E0751.md | 2 +- src/librustc_trait_selection/traits/specialize/mod.rs | 2 +- .../coherence-conflicting-negative-trait-impl.stderr | 4 ++-- src/test/ui/issues/issue-33140-hack-boundaries.rs | 2 +- src/test/ui/issues/issue-33140-hack-boundaries.stderr | 4 ++-- .../ui/specialization/specialization-overlap-negative.rs | 2 +- .../specialization/specialization-overlap-negative.stderr | 4 ++-- src/test/ui/specialization/specialization-polarity.rs | 4 ++-- src/test/ui/specialization/specialization-polarity.stderr | 6 +++--- .../negative-impls/negative-specializes-positive-item.rs | 2 +- .../negative-specializes-positive-item.stderr | 4 ++-- .../traits/negative-impls/negative-specializes-positive.rs | 2 +- .../negative-impls/negative-specializes-positive.stderr | 4 ++-- .../traits/negative-impls/pin-unsound-issue-66544-clone.rs | 2 +- .../negative-impls/pin-unsound-issue-66544-clone.stderr | 4 ++-- .../negative-impls/pin-unsound-issue-66544-derefmut.rs | 2 +- .../negative-impls/pin-unsound-issue-66544-derefmut.stderr | 4 ++-- .../traits/negative-impls/positive-specializes-negative.rs | 2 +- .../negative-impls/positive-specializes-negative.stderr | 4 ++-- 19 files changed, 30 insertions(+), 30 deletions(-) diff --git a/src/librustc_error_codes/error_codes/E0751.md b/src/librustc_error_codes/error_codes/E0751.md index a440f82e4b6b3..809b888d92ac3 100644 --- a/src/librustc_error_codes/error_codes/E0751.md +++ b/src/librustc_error_codes/error_codes/E0751.md @@ -2,7 +2,7 @@ There are both a positive and negative trait implementation for the same type. Erroneous code example: -```compile_fail,E0748 +```compile_fail,E0751 trait MyTrait {} impl MyTrait for i32 { } impl !MyTrait for i32 { } diff --git a/src/librustc_trait_selection/traits/specialize/mod.rs b/src/librustc_trait_selection/traits/specialize/mod.rs index fabd8c89b72af..57d13e35fd2dc 100644 --- a/src/librustc_trait_selection/traits/specialize/mod.rs +++ b/src/librustc_trait_selection/traits/specialize/mod.rs @@ -345,7 +345,7 @@ fn report_negative_positive_conflict( let mut err = struct_span_err!( tcx.sess, impl_span, - E0748, + E0751, "found both positive and negative implementation of trait `{}`{}:", overlap.trait_desc, overlap.self_desc.clone().map_or(String::new(), |ty| format!(" for type `{}`", ty)) diff --git a/src/test/ui/coherence/coherence-conflicting-negative-trait-impl.stderr b/src/test/ui/coherence/coherence-conflicting-negative-trait-impl.stderr index 5081536b70245..4d9f815c79581 100644 --- a/src/test/ui/coherence/coherence-conflicting-negative-trait-impl.stderr +++ b/src/test/ui/coherence/coherence-conflicting-negative-trait-impl.stderr @@ -1,4 +1,4 @@ -error[E0748]: found both positive and negative implementation of trait `std::marker::Send` for type `TestType<_>`: +error[E0751]: found both positive and negative implementation of trait `std::marker::Send` for type `TestType<_>`: --> $DIR/coherence-conflicting-negative-trait-impl.rs:11:1 | LL | unsafe impl Send for TestType {} @@ -18,5 +18,5 @@ LL | unsafe impl Send for TestType {} error: aborting due to 2 previous errors -Some errors have detailed explanations: E0119, E0748. +Some errors have detailed explanations: E0119, E0751. For more information about an error, try `rustc --explain E0119`. diff --git a/src/test/ui/issues/issue-33140-hack-boundaries.rs b/src/test/ui/issues/issue-33140-hack-boundaries.rs index 5984a256a3086..d091162fced6b 100644 --- a/src/test/ui/issues/issue-33140-hack-boundaries.rs +++ b/src/test/ui/issues/issue-33140-hack-boundaries.rs @@ -23,7 +23,7 @@ trait Trait2 {} impl Trait2 for dyn Send {} impl !Trait2 for dyn Send {} -//~^ ERROR E0748 +//~^ ERROR E0751 // Problem 3: type parameter trait Trait3 {} diff --git a/src/test/ui/issues/issue-33140-hack-boundaries.stderr b/src/test/ui/issues/issue-33140-hack-boundaries.stderr index b3bf34a2a9031..ae65701ecb52a 100644 --- a/src/test/ui/issues/issue-33140-hack-boundaries.stderr +++ b/src/test/ui/issues/issue-33140-hack-boundaries.stderr @@ -6,7 +6,7 @@ LL | impl Trait1 for dyn Send {} LL | impl Trait1 for dyn Send {} | ^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `(dyn std::marker::Send + 'static)` -error[E0748]: found both positive and negative implementation of trait `Trait2` for type `(dyn std::marker::Send + 'static)`: +error[E0751]: found both positive and negative implementation of trait `Trait2` for type `(dyn std::marker::Send + 'static)`: --> $DIR/issue-33140-hack-boundaries.rs:25:1 | LL | impl Trait2 for dyn Send {} @@ -64,5 +64,5 @@ LL | impl Trait5 for dyn Send where u32: Copy {} error: aborting due to 8 previous errors -Some errors have detailed explanations: E0119, E0748. +Some errors have detailed explanations: E0119, E0751. For more information about an error, try `rustc --explain E0119`. diff --git a/src/test/ui/specialization/specialization-overlap-negative.rs b/src/test/ui/specialization/specialization-overlap-negative.rs index dff2b28bf003c..90dbef3075b7f 100644 --- a/src/test/ui/specialization/specialization-overlap-negative.rs +++ b/src/test/ui/specialization/specialization-overlap-negative.rs @@ -6,6 +6,6 @@ trait MyTrait {} struct TestType(::std::marker::PhantomData); unsafe impl Send for TestType {} -impl !Send for TestType {} //~ ERROR E0748 +impl !Send for TestType {} //~ ERROR E0751 fn main() {} diff --git a/src/test/ui/specialization/specialization-overlap-negative.stderr b/src/test/ui/specialization/specialization-overlap-negative.stderr index cbc7271b199a6..e2616534d2041 100644 --- a/src/test/ui/specialization/specialization-overlap-negative.stderr +++ b/src/test/ui/specialization/specialization-overlap-negative.stderr @@ -1,4 +1,4 @@ -error[E0748]: found both positive and negative implementation of trait `std::marker::Send` for type `TestType<_>`: +error[E0751]: found both positive and negative implementation of trait `std::marker::Send` for type `TestType<_>`: --> $DIR/specialization-overlap-negative.rs:9:1 | LL | unsafe impl Send for TestType {} @@ -8,4 +8,4 @@ LL | impl !Send for TestType {} error: aborting due to previous error -For more information about this error, try `rustc --explain E0748`. +For more information about this error, try `rustc --explain E0751`. diff --git a/src/test/ui/specialization/specialization-polarity.rs b/src/test/ui/specialization/specialization-polarity.rs index 4a733fb3c497e..e78035f171075 100644 --- a/src/test/ui/specialization/specialization-polarity.rs +++ b/src/test/ui/specialization/specialization-polarity.rs @@ -7,11 +7,11 @@ auto trait Foo {} impl Foo for T {} -impl !Foo for u8 {} //~ ERROR E0748 +impl !Foo for u8 {} //~ ERROR E0751 auto trait Bar {} impl !Bar for T {} -impl Bar for u8 {} //~ ERROR E0748 +impl Bar for u8 {} //~ ERROR E0751 fn main() {} diff --git a/src/test/ui/specialization/specialization-polarity.stderr b/src/test/ui/specialization/specialization-polarity.stderr index 30655d87d5500..44e60cad67aa4 100644 --- a/src/test/ui/specialization/specialization-polarity.stderr +++ b/src/test/ui/specialization/specialization-polarity.stderr @@ -1,4 +1,4 @@ -error[E0748]: found both positive and negative implementation of trait `Foo` for type `u8`: +error[E0751]: found both positive and negative implementation of trait `Foo` for type `u8`: --> $DIR/specialization-polarity.rs:10:1 | LL | impl Foo for T {} @@ -6,7 +6,7 @@ LL | impl Foo for T {} LL | impl !Foo for u8 {} | ^^^^^^^^^^^^^^^^ negative implementation here -error[E0748]: found both positive and negative implementation of trait `Bar` for type `u8`: +error[E0751]: found both positive and negative implementation of trait `Bar` for type `u8`: --> $DIR/specialization-polarity.rs:15:1 | LL | impl !Bar for T {} @@ -16,4 +16,4 @@ LL | impl Bar for u8 {} error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0748`. +For more information about this error, try `rustc --explain E0751`. diff --git a/src/test/ui/traits/negative-impls/negative-specializes-positive-item.rs b/src/test/ui/traits/negative-impls/negative-specializes-positive-item.rs index 043273e624189..da22e43377f52 100644 --- a/src/test/ui/traits/negative-impls/negative-specializes-positive-item.rs +++ b/src/test/ui/traits/negative-impls/negative-specializes-positive-item.rs @@ -8,6 +8,6 @@ trait MyTrait { impl MyTrait for T { default fn foo() {} } -impl !MyTrait for u32 {} //~ ERROR E0748 +impl !MyTrait for u32 {} //~ ERROR E0751 fn main() {} diff --git a/src/test/ui/traits/negative-impls/negative-specializes-positive-item.stderr b/src/test/ui/traits/negative-impls/negative-specializes-positive-item.stderr index 21fd08251d474..079546a7df40b 100644 --- a/src/test/ui/traits/negative-impls/negative-specializes-positive-item.stderr +++ b/src/test/ui/traits/negative-impls/negative-specializes-positive-item.stderr @@ -1,4 +1,4 @@ -error[E0748]: found both positive and negative implementation of trait `MyTrait` for type `u32`: +error[E0751]: found both positive and negative implementation of trait `MyTrait` for type `u32`: --> $DIR/negative-specializes-positive-item.rs:11:1 | LL | impl MyTrait for T { @@ -9,4 +9,4 @@ LL | impl !MyTrait for u32 {} error: aborting due to previous error -For more information about this error, try `rustc --explain E0748`. +For more information about this error, try `rustc --explain E0751`. diff --git a/src/test/ui/traits/negative-impls/negative-specializes-positive.rs b/src/test/ui/traits/negative-impls/negative-specializes-positive.rs index ac0fac10eef50..1939a098b50ee 100644 --- a/src/test/ui/traits/negative-impls/negative-specializes-positive.rs +++ b/src/test/ui/traits/negative-impls/negative-specializes-positive.rs @@ -4,7 +4,7 @@ // Negative impl for u32 cannot "specialize" the base impl. trait MyTrait {} impl MyTrait for T {} -impl !MyTrait for u32 {} //~ ERROR E0748 +impl !MyTrait for u32 {} //~ ERROR E0751 // The second impl specializes the first, no error. trait MyTrait2 {} diff --git a/src/test/ui/traits/negative-impls/negative-specializes-positive.stderr b/src/test/ui/traits/negative-impls/negative-specializes-positive.stderr index 0e7426c826028..ea005c1cbe0c6 100644 --- a/src/test/ui/traits/negative-impls/negative-specializes-positive.stderr +++ b/src/test/ui/traits/negative-impls/negative-specializes-positive.stderr @@ -1,4 +1,4 @@ -error[E0748]: found both positive and negative implementation of trait `MyTrait` for type `u32`: +error[E0751]: found both positive and negative implementation of trait `MyTrait` for type `u32`: --> $DIR/negative-specializes-positive.rs:7:1 | LL | impl MyTrait for T {} @@ -8,4 +8,4 @@ LL | impl !MyTrait for u32 {} error: aborting due to previous error -For more information about this error, try `rustc --explain E0748`. +For more information about this error, try `rustc --explain E0751`. diff --git a/src/test/ui/traits/negative-impls/pin-unsound-issue-66544-clone.rs b/src/test/ui/traits/negative-impls/pin-unsound-issue-66544-clone.rs index d9c498fca6645..499ac461e59a5 100644 --- a/src/test/ui/traits/negative-impls/pin-unsound-issue-66544-clone.rs +++ b/src/test/ui/traits/negative-impls/pin-unsound-issue-66544-clone.rs @@ -5,7 +5,7 @@ use std::pin::Pin; struct MyType<'a>(Cell>>, PhantomPinned); impl<'a> Clone for &'a mut MyType<'a> { - //~^ ERROR E0748 + //~^ ERROR E0751 fn clone(&self) -> &'a mut MyType<'a> { self.0.replace(None).unwrap() } diff --git a/src/test/ui/traits/negative-impls/pin-unsound-issue-66544-clone.stderr b/src/test/ui/traits/negative-impls/pin-unsound-issue-66544-clone.stderr index f3305722cf2d3..d7039e3db6bde 100644 --- a/src/test/ui/traits/negative-impls/pin-unsound-issue-66544-clone.stderr +++ b/src/test/ui/traits/negative-impls/pin-unsound-issue-66544-clone.stderr @@ -1,4 +1,4 @@ -error[E0748]: found both positive and negative implementation of trait `std::clone::Clone` for type `&mut MyType<'_>`: +error[E0751]: found both positive and negative implementation of trait `std::clone::Clone` for type `&mut MyType<'_>`: --> $DIR/pin-unsound-issue-66544-clone.rs:7:1 | LL | impl<'a> Clone for &'a mut MyType<'a> { @@ -8,4 +8,4 @@ LL | impl<'a> Clone for &'a mut MyType<'a> { error: aborting due to previous error -For more information about this error, try `rustc --explain E0748`. +For more information about this error, try `rustc --explain E0751`. diff --git a/src/test/ui/traits/negative-impls/pin-unsound-issue-66544-derefmut.rs b/src/test/ui/traits/negative-impls/pin-unsound-issue-66544-derefmut.rs index cc27c301ffa9d..245be80078056 100644 --- a/src/test/ui/traits/negative-impls/pin-unsound-issue-66544-derefmut.rs +++ b/src/test/ui/traits/negative-impls/pin-unsound-issue-66544-derefmut.rs @@ -10,7 +10,7 @@ use std::pin::Pin; struct MyType<'a>(Cell>>, PhantomPinned); impl<'a> DerefMut for &'a MyType<'a> { - //~^ ERROR E0748 + //~^ ERROR E0751 fn deref_mut(&mut self) -> &mut MyType<'a> { self.0.replace(None).unwrap() } diff --git a/src/test/ui/traits/negative-impls/pin-unsound-issue-66544-derefmut.stderr b/src/test/ui/traits/negative-impls/pin-unsound-issue-66544-derefmut.stderr index 4e71c2468246b..a0b62a8bab68f 100644 --- a/src/test/ui/traits/negative-impls/pin-unsound-issue-66544-derefmut.stderr +++ b/src/test/ui/traits/negative-impls/pin-unsound-issue-66544-derefmut.stderr @@ -1,4 +1,4 @@ -error[E0748]: found both positive and negative implementation of trait `std::ops::DerefMut` for type `&MyType<'_>`: +error[E0751]: found both positive and negative implementation of trait `std::ops::DerefMut` for type `&MyType<'_>`: --> $DIR/pin-unsound-issue-66544-derefmut.rs:12:1 | LL | impl<'a> DerefMut for &'a MyType<'a> { @@ -8,4 +8,4 @@ LL | impl<'a> DerefMut for &'a MyType<'a> { error: aborting due to previous error -For more information about this error, try `rustc --explain E0748`. +For more information about this error, try `rustc --explain E0751`. diff --git a/src/test/ui/traits/negative-impls/positive-specializes-negative.rs b/src/test/ui/traits/negative-impls/positive-specializes-negative.rs index eac4c24d5d3d0..f2c5f507a4ebb 100644 --- a/src/test/ui/traits/negative-impls/positive-specializes-negative.rs +++ b/src/test/ui/traits/negative-impls/positive-specializes-negative.rs @@ -4,6 +4,6 @@ trait MyTrait {} impl !MyTrait for T {} -impl MyTrait for u32 {} //~ ERROR E0748 +impl MyTrait for u32 {} //~ ERROR E0751 fn main() {} diff --git a/src/test/ui/traits/negative-impls/positive-specializes-negative.stderr b/src/test/ui/traits/negative-impls/positive-specializes-negative.stderr index ab371945a7eab..a24d7aa442f4a 100644 --- a/src/test/ui/traits/negative-impls/positive-specializes-negative.stderr +++ b/src/test/ui/traits/negative-impls/positive-specializes-negative.stderr @@ -1,4 +1,4 @@ -error[E0748]: found both positive and negative implementation of trait `MyTrait` for type `u32`: +error[E0751]: found both positive and negative implementation of trait `MyTrait` for type `u32`: --> $DIR/positive-specializes-negative.rs:7:1 | LL | impl !MyTrait for T {} @@ -8,4 +8,4 @@ LL | impl MyTrait for u32 {} error: aborting due to previous error -For more information about this error, try `rustc --explain E0748`. +For more information about this error, try `rustc --explain E0751`. From c5627c60f40dbf22647dac8e2d14fb2c35ef1ba3 Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Tue, 21 Apr 2020 14:56:59 -0700 Subject: [PATCH 13/19] Don't fuse Chain in its second iterator Only the "first" iterator is actually set `None` when exhausted, depending on whether you iterate forward or backward. This restores behavior similar to the former `ChainState`, where it would transition from `Both` to `Front`/`Back` and only continue from that side. However, if you mix directions, then this may still set both sides to `None`, totally fusing the iterator. --- src/libcore/iter/adapters/chain.rs | 32 ++++++++++----- src/libcore/tests/iter.rs | 64 ++++++++++++++++++------------ src/libcore/tests/lib.rs | 1 + 3 files changed, 62 insertions(+), 35 deletions(-) diff --git a/src/libcore/iter/adapters/chain.rs b/src/libcore/iter/adapters/chain.rs index 2dd405ced20e1..6700ef017bde4 100644 --- a/src/libcore/iter/adapters/chain.rs +++ b/src/libcore/iter/adapters/chain.rs @@ -18,6 +18,9 @@ pub struct Chain { // adapter because its specialization for `FusedIterator` unconditionally descends into the // iterator, and that could be expensive to keep revisiting stuff like nested chains. It also // hurts compiler performance to add more iterator layers to `Chain`. + // + // Only the "first" iterator is actually set `None` when exhausted, depending on whether you + // iterate forward or backward. If you mix directions, then both sides may be `None`. a: Option, b: Option, } @@ -43,6 +46,17 @@ macro_rules! fuse { }; } +/// Try an iterator method without fusing, +/// like an inline `.as_mut().and_then(...)` +macro_rules! maybe { + ($self:ident . $iter:ident . $($call:tt)+) => { + match $self.$iter { + Some(ref mut iter) => iter.$($call)+, + None => None, + } + }; +} + #[stable(feature = "rust1", since = "1.0.0")] impl Iterator for Chain where @@ -54,7 +68,7 @@ where #[inline] fn next(&mut self) -> Option { match fuse!(self.a.next()) { - None => fuse!(self.b.next()), + None => maybe!(self.b.next()), item => item, } } @@ -85,7 +99,7 @@ where } if let Some(ref mut b) = self.b { acc = b.try_fold(acc, f)?; - self.b = None; + // we don't fuse the second iterator } Try::from_ok(acc) } @@ -114,7 +128,7 @@ where } self.a = None; } - fuse!(self.b.nth(n)) + maybe!(self.b.nth(n)) } #[inline] @@ -123,7 +137,7 @@ where P: FnMut(&Self::Item) -> bool, { match fuse!(self.a.find(&mut predicate)) { - None => fuse!(self.b.find(predicate)), + None => maybe!(self.b.find(predicate)), item => item, } } @@ -174,7 +188,7 @@ where #[inline] fn next_back(&mut self) -> Option { match fuse!(self.b.next_back()) { - None => fuse!(self.a.next_back()), + None => maybe!(self.a.next_back()), item => item, } } @@ -190,7 +204,7 @@ where } self.b = None; } - fuse!(self.a.nth_back(n)) + maybe!(self.a.nth_back(n)) } #[inline] @@ -199,7 +213,7 @@ where P: FnMut(&Self::Item) -> bool, { match fuse!(self.b.rfind(&mut predicate)) { - None => fuse!(self.a.rfind(predicate)), + None => maybe!(self.a.rfind(predicate)), item => item, } } @@ -216,7 +230,7 @@ where } if let Some(ref mut a) = self.a { acc = a.try_rfold(acc, f)?; - self.a = None; + // we don't fuse the second iterator } Try::from_ok(acc) } @@ -236,8 +250,6 @@ where } // Note: *both* must be fused to handle double-ended iterators. -// Now that we "fuse" both sides, we *could* implement this unconditionally, -// but we should be cautious about committing to that in the public API. #[stable(feature = "fused", since = "1.26.0")] impl FusedIterator for Chain where diff --git a/src/libcore/tests/iter.rs b/src/libcore/tests/iter.rs index 1a1dbcd7b871a..7da02b11676ab 100644 --- a/src/libcore/tests/iter.rs +++ b/src/libcore/tests/iter.rs @@ -207,50 +207,64 @@ fn test_iterator_chain_find() { assert_eq!(iter.next(), None); } -#[test] -fn test_iterator_chain_size_hint() { - struct Iter { - is_empty: bool, - } +struct Toggle { + is_empty: bool, +} - impl Iterator for Iter { - type Item = (); +impl Iterator for Toggle { + type Item = (); - // alternates between `None` and `Some(())` - fn next(&mut self) -> Option { - if self.is_empty { - self.is_empty = false; - None - } else { - self.is_empty = true; - Some(()) - } + // alternates between `None` and `Some(())` + fn next(&mut self) -> Option { + if self.is_empty { + self.is_empty = false; + None + } else { + self.is_empty = true; + Some(()) } + } - fn size_hint(&self) -> (usize, Option) { - if self.is_empty { (0, Some(0)) } else { (1, Some(1)) } - } + fn size_hint(&self) -> (usize, Option) { + if self.is_empty { (0, Some(0)) } else { (1, Some(1)) } } +} - impl DoubleEndedIterator for Iter { - fn next_back(&mut self) -> Option { - self.next() - } +impl DoubleEndedIterator for Toggle { + fn next_back(&mut self) -> Option { + self.next() } +} +#[test] +fn test_iterator_chain_size_hint() { // this chains an iterator of length 0 with an iterator of length 1, // so after calling `.next()` once, the iterator is empty and the // state is `ChainState::Back`. `.size_hint()` should now disregard // the size hint of the left iterator - let mut iter = Iter { is_empty: true }.chain(once(())); + let mut iter = Toggle { is_empty: true }.chain(once(())); assert_eq!(iter.next(), Some(())); assert_eq!(iter.size_hint(), (0, Some(0))); - let mut iter = once(()).chain(Iter { is_empty: true }); + let mut iter = once(()).chain(Toggle { is_empty: true }); assert_eq!(iter.next_back(), Some(())); assert_eq!(iter.size_hint(), (0, Some(0))); } +#[test] +fn test_iterator_chain_unfused() { + // Chain shouldn't be fused in its second iterator, depending on direction + let mut iter = NonFused::new(empty()).chain(Toggle { is_empty: true }); + iter.next().unwrap_none(); + iter.next().unwrap(); + iter.next().unwrap_none(); + + let mut iter = Toggle { is_empty: true }.chain(NonFused::new(empty())); + iter.next_back().unwrap_none(); + iter.next_back().unwrap(); + iter.next_back().unwrap_none(); +} + #[test] fn test_zip_nth() { let xs = [0, 1, 2, 4, 5]; diff --git a/src/libcore/tests/lib.rs b/src/libcore/tests/lib.rs index 05f958cbe81fe..e7d36d327cd89 100644 --- a/src/libcore/tests/lib.rs +++ b/src/libcore/tests/lib.rs @@ -42,6 +42,7 @@ #![feature(unwrap_infallible)] #![feature(leading_trailing_ones)] #![feature(const_forget)] +#![feature(option_unwrap_none)] extern crate test; From 4c1cabd4a12a84678fbb6fa5659a8f6f1006a671 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Fri, 17 Apr 2020 18:31:25 -0700 Subject: [PATCH 14/19] Remove some `Vec` allocations in an effort to improve perf --- src/librustc_infer/infer/outlives/verify.rs | 9 +++------ src/librustc_infer/traits/util.rs | 10 ++++------ src/librustc_mir/transform/const_prop.rs | 3 +-- src/librustc_trait_selection/opaque_types.rs | 13 ++++++------- .../traits/auto_trait.rs | 3 +-- .../traits/error_reporting/mod.rs | 2 +- src/librustc_trait_selection/traits/mod.rs | 2 +- .../traits/object_safety.rs | 2 +- src/librustc_trait_selection/traits/project.rs | 16 ++++++---------- src/librustc_trait_selection/traits/select.rs | 3 ++- src/librustc_trait_selection/traits/wf.rs | 17 +++++++---------- src/librustc_typeck/check/method/confirm.rs | 2 +- src/librustc_typeck/check/wfcheck.rs | 2 +- .../impl_wf_check/min_specialization.rs | 5 ++--- 14 files changed, 37 insertions(+), 52 deletions(-) diff --git a/src/librustc_infer/infer/outlives/verify.rs b/src/librustc_infer/infer/outlives/verify.rs index 1a601d723cb7b..adf5af6f9dde6 100644 --- a/src/librustc_infer/infer/outlives/verify.rs +++ b/src/librustc_infer/infer/outlives/verify.rs @@ -223,7 +223,7 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> { // like `T` and `T::Item`. It may not work as well for things // like `>::Item`. let c_b = self.param_env.caller_bounds; - let param_bounds = self.collect_outlives_from_predicate_list(&compare_ty, c_b); + let param_bounds = self.collect_outlives_from_predicate_list(&compare_ty, c_b.into_iter()); // Next, collect regions we scraped from the well-formedness // constraints in the fn signature. To do that, we walk the list @@ -315,15 +315,12 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> { let tcx = self.tcx; let assoc_item = tcx.associated_item(assoc_item_def_id); let trait_def_id = assoc_item.container.assert_trait(); - let trait_predicates = - tcx.predicates_of(trait_def_id).predicates.iter().map(|(p, _)| *p).collect(); + let trait_predicates = tcx.predicates_of(trait_def_id).predicates.iter().map(|(p, _)| *p); let identity_substs = InternalSubsts::identity_for_item(tcx, assoc_item_def_id); let identity_proj = tcx.mk_projection(assoc_item_def_id, identity_substs); self.collect_outlives_from_predicate_list( move |ty| ty == identity_proj, - traits::elaborate_predicates(tcx, trait_predicates) - .map(|o| o.predicate) - .collect::>(), + traits::elaborate_predicates(tcx, trait_predicates).map(|o| o.predicate), ) .map(|b| b.1) } diff --git a/src/librustc_infer/traits/util.rs b/src/librustc_infer/traits/util.rs index 3f63d25fb4723..3547ef6e497f9 100644 --- a/src/librustc_infer/traits/util.rs +++ b/src/librustc_infer/traits/util.rs @@ -97,24 +97,22 @@ pub fn elaborate_trait_ref<'tcx>( tcx: TyCtxt<'tcx>, trait_ref: ty::PolyTraitRef<'tcx>, ) -> Elaborator<'tcx> { - elaborate_predicates(tcx, vec![trait_ref.without_const().to_predicate()]) + elaborate_predicates(tcx, std::iter::once(trait_ref.without_const().to_predicate())) } pub fn elaborate_trait_refs<'tcx>( tcx: TyCtxt<'tcx>, trait_refs: impl Iterator>, ) -> Elaborator<'tcx> { - let predicates = trait_refs.map(|trait_ref| trait_ref.without_const().to_predicate()).collect(); + let predicates = trait_refs.map(|trait_ref| trait_ref.without_const().to_predicate()); elaborate_predicates(tcx, predicates) } pub fn elaborate_predicates<'tcx>( tcx: TyCtxt<'tcx>, - mut predicates: Vec>, + predicates: impl IntoIterator>, ) -> Elaborator<'tcx> { - let mut visited = PredicateSet::new(tcx); - predicates.retain(|pred| visited.insert(pred)); - let obligations: Vec<_> = + let obligations = predicates.into_iter().map(|predicate| predicate_obligation(predicate, None)).collect(); elaborate_obligations(tcx, obligations) } diff --git a/src/librustc_mir/transform/const_prop.rs b/src/librustc_mir/transform/const_prop.rs index 77a9be0ed35d8..74281d152f499 100644 --- a/src/librustc_mir/transform/const_prop.rs +++ b/src/librustc_mir/transform/const_prop.rs @@ -122,8 +122,7 @@ impl<'tcx> MirPass<'tcx> for ConstProp { .predicates_of(source.def_id()) .predicates .iter() - .filter_map(|(p, _)| if p.is_global() { Some(*p) } else { None }) - .collect(); + .filter_map(|(p, _)| if p.is_global() { Some(*p) } else { None }); if !traits::normalize_and_test_predicates( tcx, traits::elaborate_predicates(tcx, predicates).map(|o| o.predicate).collect(), diff --git a/src/librustc_trait_selection/opaque_types.rs b/src/librustc_trait_selection/opaque_types.rs index f67b8b87ced5f..7647775eff42a 100644 --- a/src/librustc_trait_selection/opaque_types.rs +++ b/src/librustc_trait_selection/opaque_types.rs @@ -418,7 +418,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { let opaque_type = tcx.mk_opaque(def_id, opaque_defn.substs); let required_region_bounds = - required_region_bounds(tcx, opaque_type, bounds.predicates); + required_region_bounds(tcx, opaque_type, bounds.predicates.into_iter()); debug_assert!(!required_region_bounds.is_empty()); for required_region in required_region_bounds { @@ -1127,7 +1127,8 @@ impl<'a, 'tcx> Instantiator<'a, 'tcx> { debug!("instantiate_opaque_types: bounds={:?}", bounds); - let required_region_bounds = required_region_bounds(tcx, ty, bounds.predicates.clone()); + let required_region_bounds = + required_region_bounds(tcx, ty, bounds.predicates.iter().cloned()); debug!("instantiate_opaque_types: required_region_bounds={:?}", required_region_bounds); // Make sure that we are in fact defining the *entire* type @@ -1245,17 +1246,15 @@ pub fn may_define_opaque_type(tcx: TyCtxt<'_>, def_id: DefId, opaque_hir_id: hir crate fn required_region_bounds( tcx: TyCtxt<'tcx>, erased_self_ty: Ty<'tcx>, - predicates: Vec>, + predicates: impl Iterator>, ) -> Vec> { - debug!( - "required_region_bounds(erased_self_ty={:?}, predicates={:?})", - erased_self_ty, predicates - ); + debug!("required_region_bounds(erased_self_ty={:?})", erased_self_ty); assert!(!erased_self_ty.has_escaping_bound_vars()); traits::elaborate_predicates(tcx, predicates) .filter_map(|obligation| { + debug!("required_region_bounds(obligation={:?})", obligation); match obligation.predicate { ty::Predicate::Projection(..) | ty::Predicate::Trait(..) diff --git a/src/librustc_trait_selection/traits/auto_trait.rs b/src/librustc_trait_selection/traits/auto_trait.rs index 052de4a4e5b55..b28658e0f1e58 100644 --- a/src/librustc_trait_selection/traits/auto_trait.rs +++ b/src/librustc_trait_selection/traits/auto_trait.rs @@ -360,8 +360,7 @@ impl AutoTraitFinder<'tcx> { computed_preds.extend(user_computed_preds.iter().cloned()); let normalized_preds = - elaborate_predicates(tcx, computed_preds.iter().cloned().collect()) - .map(|o| o.predicate); + elaborate_predicates(tcx, computed_preds.iter().cloned()).map(|o| o.predicate); new_env = ty::ParamEnv::new(tcx.mk_predicates(normalized_preds), param_env.reveal, None); } diff --git a/src/librustc_trait_selection/traits/error_reporting/mod.rs b/src/librustc_trait_selection/traits/error_reporting/mod.rs index 8a9017960fb23..927f7c294f068 100644 --- a/src/librustc_trait_selection/traits/error_reporting/mod.rs +++ b/src/librustc_trait_selection/traits/error_reporting/mod.rs @@ -1007,7 +1007,7 @@ impl<'a, 'tcx> InferCtxtPrivExt<'tcx> for InferCtxt<'a, 'tcx> { } }; - for obligation in super::elaborate_predicates(self.tcx, vec![*cond]) { + for obligation in super::elaborate_predicates(self.tcx, std::iter::once(*cond)) { if let ty::Predicate::Trait(implication, _) = obligation.predicate { let error = error.to_poly_trait_ref(); let implication = implication.to_poly_trait_ref(); diff --git a/src/librustc_trait_selection/traits/mod.rs b/src/librustc_trait_selection/traits/mod.rs index f8fc155f582b8..2227477a4635b 100644 --- a/src/librustc_trait_selection/traits/mod.rs +++ b/src/librustc_trait_selection/traits/mod.rs @@ -297,7 +297,7 @@ pub fn normalize_param_env_or_error<'tcx>( ); let mut predicates: Vec<_> = - util::elaborate_predicates(tcx, unnormalized_env.caller_bounds.to_vec()) + util::elaborate_predicates(tcx, unnormalized_env.caller_bounds.into_iter().cloned()) .map(|obligation| obligation.predicate) .collect(); diff --git a/src/librustc_trait_selection/traits/object_safety.rs b/src/librustc_trait_selection/traits/object_safety.rs index d9fba1fd78392..96b2b904e6543 100644 --- a/src/librustc_trait_selection/traits/object_safety.rs +++ b/src/librustc_trait_selection/traits/object_safety.rs @@ -302,7 +302,7 @@ fn generics_require_sized_self(tcx: TyCtxt<'_>, def_id: DefId) -> bool { // Search for a predicate like `Self : Sized` amongst the trait bounds. let predicates = tcx.predicates_of(def_id); let predicates = predicates.instantiate_identity(tcx).predicates; - elaborate_predicates(tcx, predicates).any(|obligation| match obligation.predicate { + elaborate_predicates(tcx, predicates.into_iter()).any(|obligation| match obligation.predicate { ty::Predicate::Trait(ref trait_pred, _) => { trait_pred.def_id() == sized_def_id && trait_pred.skip_binder().self_ty().is_param(0) } diff --git a/src/librustc_trait_selection/traits/project.rs b/src/librustc_trait_selection/traits/project.rs index 4d02c5eb2301d..2b4a0409fd1e2 100644 --- a/src/librustc_trait_selection/traits/project.rs +++ b/src/librustc_trait_selection/traits/project.rs @@ -900,7 +900,7 @@ fn assemble_candidates_from_trait_def<'cx, 'tcx>( // If so, extract what we know from the trait and try to come up with a good answer. let trait_predicates = tcx.predicates_of(def_id); let bounds = trait_predicates.instantiate(tcx, substs); - let bounds = elaborate_predicates(tcx, bounds.predicates).map(|o| o.predicate); + let bounds = elaborate_predicates(tcx, bounds.predicates.into_iter()).map(|o| o.predicate); assemble_candidates_from_predicates( selcx, obligation, @@ -911,16 +911,14 @@ fn assemble_candidates_from_trait_def<'cx, 'tcx>( ) } -fn assemble_candidates_from_predicates<'cx, 'tcx, I>( +fn assemble_candidates_from_predicates<'cx, 'tcx>( selcx: &mut SelectionContext<'cx, 'tcx>, obligation: &ProjectionTyObligation<'tcx>, obligation_trait_ref: &ty::TraitRef<'tcx>, candidate_set: &mut ProjectionTyCandidateSet<'tcx>, ctor: fn(ty::PolyProjectionPredicate<'tcx>) -> ProjectionTyCandidate<'tcx>, - env_predicates: I, -) where - I: IntoIterator>, -{ + env_predicates: impl Iterator>, +) { debug!("assemble_candidates_from_predicates(obligation={:?})", obligation); let infcx = selcx.infcx(); for predicate in env_predicates { @@ -1153,10 +1151,8 @@ fn confirm_object_candidate<'cx, 'tcx>( object_ty ), }; - let env_predicates = data - .projection_bounds() - .map(|p| p.with_self_ty(selcx.tcx(), object_ty).to_predicate()) - .collect(); + let env_predicates = + data.projection_bounds().map(|p| p.with_self_ty(selcx.tcx(), object_ty).to_predicate()); let env_predicate = { let env_predicates = elaborate_predicates(selcx.tcx(), env_predicates); diff --git a/src/librustc_trait_selection/traits/select.rs b/src/librustc_trait_selection/traits/select.rs index 45fda3004b09b..dfbb07424487d 100644 --- a/src/librustc_trait_selection/traits/select.rs +++ b/src/librustc_trait_selection/traits/select.rs @@ -1443,7 +1443,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { bounds ); - let elaborated_predicates = util::elaborate_predicates(self.tcx(), bounds.predicates); + let elaborated_predicates = + util::elaborate_predicates(self.tcx(), bounds.predicates.into_iter()); let matching_bound = elaborated_predicates.filter_to_traits().find(|bound| { self.infcx.probe(|_| { self.match_projection( diff --git a/src/librustc_trait_selection/traits/wf.rs b/src/librustc_trait_selection/traits/wf.rs index f6953971ef5bc..cf8c12eae0a39 100644 --- a/src/librustc_trait_selection/traits/wf.rs +++ b/src/librustc_trait_selection/traits/wf.rs @@ -627,16 +627,13 @@ pub fn object_region_bounds<'tcx>( // a placeholder type. let open_ty = tcx.mk_ty_infer(ty::FreshTy(0)); - let predicates = existential_predicates - .iter() - .filter_map(|predicate| { - if let ty::ExistentialPredicate::Projection(_) = *predicate.skip_binder() { - None - } else { - Some(predicate.with_self_ty(tcx, open_ty)) - } - }) - .collect(); + let predicates = existential_predicates.iter().filter_map(|predicate| { + if let ty::ExistentialPredicate::Projection(_) = *predicate.skip_binder() { + None + } else { + Some(predicate.with_self_ty(tcx, open_ty)) + } + }); required_region_bounds(tcx, open_ty, predicates) } diff --git a/src/librustc_typeck/check/method/confirm.rs b/src/librustc_typeck/check/method/confirm.rs index 3f81689cdc90f..5c5f3f89aba42 100644 --- a/src/librustc_typeck/check/method/confirm.rs +++ b/src/librustc_typeck/check/method/confirm.rs @@ -572,7 +572,7 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> { None => return None, }; - traits::elaborate_predicates(self.tcx, predicates.predicates.clone()) + traits::elaborate_predicates(self.tcx, predicates.predicates.iter().copied()) .filter_map(|obligation| match obligation.predicate { ty::Predicate::Trait(trait_pred, _) if trait_pred.def_id() == sized_def_id => { let span = predicates diff --git a/src/librustc_typeck/check/wfcheck.rs b/src/librustc_typeck/check/wfcheck.rs index 32004744ff950..d537891c0d739 100644 --- a/src/librustc_typeck/check/wfcheck.rs +++ b/src/librustc_typeck/check/wfcheck.rs @@ -1225,7 +1225,7 @@ fn check_false_global_bounds(fcx: &FnCtxt<'_, '_>, span: Span, id: hir::HirId) { let empty_env = ty::ParamEnv::empty(); let def_id = fcx.tcx.hir().local_def_id(id); - let predicates = fcx.tcx.predicates_of(def_id).predicates.iter().map(|(p, _)| *p).collect(); + let predicates = fcx.tcx.predicates_of(def_id).predicates.iter().map(|(p, _)| *p); // Check elaborated bounds. let implied_obligations = traits::elaborate_predicates(fcx.tcx, predicates); diff --git a/src/librustc_typeck/impl_wf_check/min_specialization.rs b/src/librustc_typeck/impl_wf_check/min_specialization.rs index ebfb3684eb0d6..076c13d106576 100644 --- a/src/librustc_typeck/impl_wf_check/min_specialization.rs +++ b/src/librustc_typeck/impl_wf_check/min_specialization.rs @@ -322,7 +322,7 @@ fn check_predicates<'tcx>( // which is sound because we forbid impls like the following // // impl AlwaysApplicable for D { } - let always_applicable_traits: Vec<_> = impl1_predicates + let always_applicable_traits = impl1_predicates .predicates .iter() .filter(|predicate| { @@ -331,8 +331,7 @@ fn check_predicates<'tcx>( Some(TraitSpecializationKind::AlwaysApplicable) ) }) - .copied() - .collect(); + .copied(); // Include the well-formed predicates of the type parameters of the impl. for ty in tcx.impl_trait_ref(impl1_def_id).unwrap().substs.types() { From 23e5778e027d4c9089700ac42681f2b9c071c8ba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Sat, 18 Apr 2020 11:07:41 -0700 Subject: [PATCH 15/19] Remove unnecessary allocation --- src/librustc_trait_selection/traits/wf.rs | 51 +++++++++++------------ 1 file changed, 25 insertions(+), 26 deletions(-) diff --git a/src/librustc_trait_selection/traits/wf.rs b/src/librustc_trait_selection/traits/wf.rs index cf8c12eae0a39..7eabdf706ef9f 100644 --- a/src/librustc_trait_selection/traits/wf.rs +++ b/src/librustc_trait_selection/traits/wf.rs @@ -140,7 +140,7 @@ fn extend_cause_with_original_assoc_item_obligation<'tcx>( item: Option<&hir::Item<'tcx>>, cause: &mut traits::ObligationCause<'tcx>, pred: &ty::Predicate<'_>, - mut trait_assoc_items: impl Iterator, + mut trait_assoc_items: impl Iterator, ) { debug!( "extended_cause_with_original_assoc_item_obligation {:?} {:?} {:?} {:?}", @@ -232,35 +232,34 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> { let item = self.item; + let extend = |obligation: traits::PredicateObligation<'tcx>| { + let mut cause = cause.clone(); + if let Some(parent_trait_ref) = obligation.predicate.to_opt_poly_trait_ref() { + let derived_cause = traits::DerivedObligationCause { + parent_trait_ref, + parent_code: Rc::new(obligation.cause.code.clone()), + }; + cause.code = traits::ObligationCauseCode::DerivedObligation(derived_cause); + } + extend_cause_with_original_assoc_item_obligation( + tcx, + trait_ref, + item, + &mut cause, + &obligation.predicate, + tcx.associated_items(trait_ref.def_id).in_definition_order(), + ); + traits::Obligation::new(cause, param_env, obligation.predicate) + }; + if let Elaborate::All = elaborate { - let implied_obligations = traits::util::elaborate_obligations(tcx, obligations.clone()); - let implied_obligations = implied_obligations.map(|obligation| { - debug!("compute_trait_ref implied_obligation {:?}", obligation); - debug!("compute_trait_ref implied_obligation cause {:?}", obligation.cause); - let mut cause = cause.clone(); - if let Some(parent_trait_ref) = obligation.predicate.to_opt_poly_trait_ref() { - let derived_cause = traits::DerivedObligationCause { - parent_trait_ref, - parent_code: Rc::new(obligation.cause.code.clone()), - }; - cause.code = traits::ObligationCauseCode::DerivedObligation(derived_cause); - } - extend_cause_with_original_assoc_item_obligation( - tcx, - trait_ref, - item, - &mut cause, - &obligation.predicate, - tcx.associated_items(trait_ref.def_id).in_definition_order().copied(), - ); - debug!("compute_trait_ref new cause {:?}", cause); - traits::Obligation::new(cause, param_env, obligation.predicate) - }); + let implied_obligations = traits::util::elaborate_obligations(tcx, obligations); + let implied_obligations = implied_obligations.map(extend); self.out.extend(implied_obligations); + } else { + self.out.extend(obligations); } - self.out.extend(obligations); - self.out.extend(trait_ref.substs.types().filter(|ty| !ty.has_escaping_bound_vars()).map( |ty| traits::Obligation::new(cause.clone(), param_env, ty::Predicate::WellFormed(ty)), )); From 9b4c12dc9dfd9305408615edceba22cedda0cfcf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Sat, 18 Apr 2020 15:09:28 -0700 Subject: [PATCH 16/19] Use more `Iterator`s instead of `Vec`s --- src/librustc_middle/ty/trait_def.rs | 12 +++--- .../traits/error_reporting/mod.rs | 8 +--- src/librustc_trait_selection/traits/mod.rs | 4 +- .../traits/specialize/mod.rs | 34 +++++++--------- src/librustc_trait_selection/traits/util.rs | 40 ++++++++----------- src/librustc_typeck/check/method/confirm.rs | 4 +- src/librustc_typeck/check/method/mod.rs | 2 +- src/librustc_typeck/check/method/probe.rs | 30 +++++++------- src/librustc_typeck/check/mod.rs | 7 ++-- 9 files changed, 60 insertions(+), 81 deletions(-) diff --git a/src/librustc_middle/ty/trait_def.rs b/src/librustc_middle/ty/trait_def.rs index 912f8be1d3342..3546e5f429ef5 100644 --- a/src/librustc_middle/ty/trait_def.rs +++ b/src/librustc_middle/ty/trait_def.rs @@ -168,15 +168,13 @@ impl<'tcx> TyCtxt<'tcx> { } /// Returns a vector containing all impls - pub fn all_impls(self, def_id: DefId) -> Vec { - let impls = self.trait_impls_of(def_id); + pub fn all_impls(self, def_id: DefId) -> impl Iterator + 'tcx { + let TraitImpls { blanket_impls, non_blanket_impls } = self.trait_impls_of(def_id); - impls - .blanket_impls - .iter() - .chain(impls.non_blanket_impls.values().flatten()) + blanket_impls + .into_iter() + .chain(non_blanket_impls.into_iter().map(|(_, v)| v).flatten()) .cloned() - .collect() } } diff --git a/src/librustc_trait_selection/traits/error_reporting/mod.rs b/src/librustc_trait_selection/traits/error_reporting/mod.rs index 927f7c294f068..74cf06d54687d 100644 --- a/src/librustc_trait_selection/traits/error_reporting/mod.rs +++ b/src/librustc_trait_selection/traits/error_reporting/mod.rs @@ -1208,8 +1208,7 @@ impl<'a, 'tcx> InferCtxtPrivExt<'tcx> for InferCtxt<'a, 'tcx> { match simp { Some(simp) => all_impls - .iter() - .filter_map(|&def_id| { + .filter_map(|def_id| { let imp = self.tcx.impl_trait_ref(def_id).unwrap(); let imp_simp = fast_reject::simplify_type(self.tcx, imp.self_ty(), true); if let Some(imp_simp) = imp_simp { @@ -1217,13 +1216,10 @@ impl<'a, 'tcx> InferCtxtPrivExt<'tcx> for InferCtxt<'a, 'tcx> { return None; } } - Some(imp) }) .collect(), - None => { - all_impls.iter().map(|&def_id| self.tcx.impl_trait_ref(def_id).unwrap()).collect() - } + None => all_impls.map(|def_id| self.tcx.impl_trait_ref(def_id).unwrap()).collect(), } } diff --git a/src/librustc_trait_selection/traits/mod.rs b/src/librustc_trait_selection/traits/mod.rs index 2227477a4635b..c5dbe81629550 100644 --- a/src/librustc_trait_selection/traits/mod.rs +++ b/src/librustc_trait_selection/traits/mod.rs @@ -110,8 +110,8 @@ pub enum TraitQueryMode { pub fn predicates_for_generics<'tcx>( cause: ObligationCause<'tcx>, param_env: ty::ParamEnv<'tcx>, - generic_bounds: &ty::InstantiatedPredicates<'tcx>, -) -> PredicateObligations<'tcx> { + generic_bounds: ty::InstantiatedPredicates<'tcx>, +) -> impl Iterator> { util::predicates_for_generics(cause, 0, param_env, generic_bounds) } diff --git a/src/librustc_trait_selection/traits/specialize/mod.rs b/src/librustc_trait_selection/traits/specialize/mod.rs index 57d13e35fd2dc..5ecd956e59c6f 100644 --- a/src/librustc_trait_selection/traits/specialize/mod.rs +++ b/src/librustc_trait_selection/traits/specialize/mod.rs @@ -189,26 +189,22 @@ fn fulfill_implication<'a, 'tcx>( let selcx = &mut SelectionContext::new(&infcx); let target_substs = infcx.fresh_substs_for_item(DUMMY_SP, target_impl); - let (target_trait_ref, mut obligations) = + let (target_trait_ref, obligations) = impl_trait_ref_and_oblig(selcx, param_env, target_impl, target_substs); - debug!( - "fulfill_implication: target_trait_ref={:?}, obligations={:?}", - target_trait_ref, obligations - ); // do the impls unify? If not, no specialization. - match infcx.at(&ObligationCause::dummy(), param_env).eq(source_trait_ref, target_trait_ref) { - Ok(InferOk { obligations: o, .. }) => { - obligations.extend(o); - } - Err(_) => { - debug!( - "fulfill_implication: {:?} does not unify with {:?}", - source_trait_ref, target_trait_ref - ); - return Err(()); - } - } + let more_obligations = + match infcx.at(&ObligationCause::dummy(), param_env).eq(source_trait_ref, target_trait_ref) + { + Ok(InferOk { obligations, .. }) => obligations, + Err(_) => { + debug!( + "fulfill_implication: {:?} does not unify with {:?}", + source_trait_ref, target_trait_ref + ); + return Err(()); + } + }; // attempt to prove all of the predicates for impl2 given those for impl1 // (which are packed up in penv) @@ -226,7 +222,7 @@ fn fulfill_implication<'a, 'tcx>( // we already make a mockery out of the region system, so // why not ignore them a bit earlier? let mut fulfill_cx = FulfillmentContext::new_ignoring_regions(); - for oblig in obligations.into_iter() { + for oblig in obligations.chain(more_obligations) { fulfill_cx.register_predicate_obligation(&infcx, oblig); } match fulfill_cx.select_all_or_error(infcx) { @@ -261,7 +257,7 @@ pub(super) fn specialization_graph_provider( ) -> &specialization_graph::Graph { let mut sg = specialization_graph::Graph::new(); - let mut trait_impls = tcx.all_impls(trait_id); + let mut trait_impls: Vec<_> = tcx.all_impls(trait_id).collect(); // The coherence checking implementation seems to rely on impls being // iterated over (roughly) in definition order, so we are sorting by diff --git a/src/librustc_trait_selection/traits/util.rs b/src/librustc_trait_selection/traits/util.rs index ffece42ec306c..4aceccf64ce65 100644 --- a/src/librustc_trait_selection/traits/util.rs +++ b/src/librustc_trait_selection/traits/util.rs @@ -81,12 +81,10 @@ impl<'tcx> TraitAliasExpansionInfo<'tcx> { pub fn expand_trait_aliases<'tcx>( tcx: TyCtxt<'tcx>, - trait_refs: impl IntoIterator, Span)>, + trait_refs: impl Iterator, Span)>, ) -> TraitAliasExpander<'tcx> { - let items: Vec<_> = trait_refs - .into_iter() - .map(|(trait_ref, span)| TraitAliasExpansionInfo::new(trait_ref, span)) - .collect(); + let items: Vec<_> = + trait_refs.map(|(trait_ref, span)| TraitAliasExpansionInfo::new(trait_ref, span)).collect(); TraitAliasExpander { tcx, stack: items } } @@ -199,7 +197,7 @@ pub fn impl_trait_ref_and_oblig<'a, 'tcx>( param_env: ty::ParamEnv<'tcx>, impl_def_id: DefId, impl_substs: SubstsRef<'tcx>, -) -> (ty::TraitRef<'tcx>, Vec>) { +) -> (ty::TraitRef<'tcx>, impl Iterator>) { let impl_trait_ref = selcx.tcx().impl_trait_ref(impl_def_id).unwrap(); let impl_trait_ref = impl_trait_ref.subst(selcx.tcx(), impl_substs); let Normalized { value: impl_trait_ref, obligations: normalization_obligations1 } = @@ -210,13 +208,11 @@ pub fn impl_trait_ref_and_oblig<'a, 'tcx>( let Normalized { value: predicates, obligations: normalization_obligations2 } = super::normalize(selcx, param_env, ObligationCause::dummy(), &predicates); let impl_obligations = - predicates_for_generics(ObligationCause::dummy(), 0, param_env, &predicates); + predicates_for_generics(ObligationCause::dummy(), 0, param_env, predicates); - let impl_obligations: Vec<_> = impl_obligations - .into_iter() - .chain(normalization_obligations1) - .chain(normalization_obligations2) - .collect(); + let impl_obligations = impl_obligations + .chain(normalization_obligations1.into_iter()) + .chain(normalization_obligations2.into_iter()); (impl_trait_ref, impl_obligations) } @@ -226,20 +222,16 @@ pub fn predicates_for_generics<'tcx>( cause: ObligationCause<'tcx>, recursion_depth: usize, param_env: ty::ParamEnv<'tcx>, - generic_bounds: &ty::InstantiatedPredicates<'tcx>, -) -> Vec> { + generic_bounds: ty::InstantiatedPredicates<'tcx>, +) -> impl Iterator> { debug!("predicates_for_generics(generic_bounds={:?})", generic_bounds); - generic_bounds - .predicates - .iter() - .map(|&predicate| Obligation { - cause: cause.clone(), - recursion_depth, - param_env, - predicate, - }) - .collect() + generic_bounds.predicates.into_iter().map(move |predicate| Obligation { + cause: cause.clone(), + recursion_depth, + param_env, + predicate, + }) } pub fn predicate_for_trait_ref<'tcx>( diff --git a/src/librustc_typeck/check/method/confirm.rs b/src/librustc_typeck/check/method/confirm.rs index 5c5f3f89aba42..22c81ece39181 100644 --- a/src/librustc_typeck/check/method/confirm.rs +++ b/src/librustc_typeck/check/method/confirm.rs @@ -114,7 +114,7 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> { // a custom error in that case. if illegal_sized_bound.is_none() { let method_ty = self.tcx.mk_fn_ptr(ty::Binder::bind(method_sig)); - self.add_obligations(method_ty, all_substs, &method_predicates); + self.add_obligations(method_ty, all_substs, method_predicates); } // Create the final `MethodCallee`. @@ -395,7 +395,7 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> { &mut self, fty: Ty<'tcx>, all_substs: SubstsRef<'tcx>, - method_predicates: &ty::InstantiatedPredicates<'tcx>, + method_predicates: ty::InstantiatedPredicates<'tcx>, ) { debug!( "add_obligations: fty={:?} all_substs={:?} method_predicates={:?}", diff --git a/src/librustc_typeck/check/method/mod.rs b/src/librustc_typeck/check/method/mod.rs index c4f53332cb673..65e9abcd14644 100644 --- a/src/librustc_typeck/check/method/mod.rs +++ b/src/librustc_typeck/check/method/mod.rs @@ -390,7 +390,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { assert!(!bounds.has_escaping_bound_vars()); let cause = traits::ObligationCause::misc(span, self.body_id); - obligations.extend(traits::predicates_for_generics(cause.clone(), self.param_env, &bounds)); + obligations.extend(traits::predicates_for_generics(cause.clone(), self.param_env, bounds)); // Also add an obligation for the method type being well-formed. let method_ty = tcx.mk_fn_ptr(ty::Binder::bind(fn_sig)); diff --git a/src/librustc_typeck/check/method/probe.rs b/src/librustc_typeck/check/method/probe.rs index 3f159fe5e3029..03e32c21a54ac 100644 --- a/src/librustc_typeck/check/method/probe.rs +++ b/src/librustc_typeck/check/method/probe.rs @@ -1342,7 +1342,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { // clauses) that must be considered. Make sure that those // match as well (or at least may match, sometimes we // don't have enough information to fully evaluate). - let candidate_obligations: Vec<_> = match probe.kind { + match probe.kind { InherentImplCandidate(ref substs, ref ref_obligations) => { // Check whether the impl imposes obligations we have to worry about. let impl_def_id = probe.item.container.id(); @@ -1353,19 +1353,23 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { // Convert the bounds into obligations. let impl_obligations = - traits::predicates_for_generics(cause, self.param_env, &impl_bounds); + traits::predicates_for_generics(cause, self.param_env, impl_bounds); - debug!("impl_obligations={:?}", impl_obligations); - impl_obligations - .into_iter() + let candidate_obligations = impl_obligations .chain(norm_obligations.into_iter()) - .chain(ref_obligations.iter().cloned()) - .collect() + .chain(ref_obligations.iter().cloned()); + // Evaluate those obligations to see if they might possibly hold. + for o in candidate_obligations { + let o = self.resolve_vars_if_possible(&o); + if !self.predicate_may_hold(&o) { + result = ProbeResult::NoMatch; + possibly_unsatisfied_predicates.push((o.predicate, None)); + } + } } ObjectCandidate | WhereClauseCandidate(..) => { // These have no additional conditions to check. - vec![] } TraitCandidate(trait_ref) => { @@ -1412,17 +1416,11 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { return ProbeResult::NoMatch; } } - vec![] } - }; - - debug!( - "consider_probe - candidate_obligations={:?} sub_obligations={:?}", - candidate_obligations, sub_obligations - ); + } // Evaluate those obligations to see if they might possibly hold. - for o in candidate_obligations.into_iter().chain(sub_obligations) { + for o in sub_obligations { let o = self.resolve_vars_if_possible(&o); if !self.predicate_may_hold(&o) { result = ProbeResult::NoMatch; diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 1be8d258dcb18..ec5d3331956e5 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -3434,7 +3434,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { pub fn add_obligations_for_parameters( &self, cause: traits::ObligationCause<'tcx>, - predicates: &ty::InstantiatedPredicates<'tcx>, + predicates: ty::InstantiatedPredicates<'tcx>, ) { assert!(!predicates.has_escaping_bound_vars()); @@ -4385,7 +4385,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let (bounds, _) = self.instantiate_bounds(path_span, did, substs); let cause = traits::ObligationCause::new(path_span, self.body_id, traits::ItemObligation(did)); - self.add_obligations_for_parameters(cause, &bounds); + self.add_obligations_for_parameters(cause, bounds); Some((variant, ty)) } else { @@ -5654,9 +5654,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { for (i, mut obligation) in traits::predicates_for_generics( traits::ObligationCause::new(span, self.body_id, traits::ItemObligation(def_id)), self.param_env, - &bounds, + bounds, ) - .into_iter() .enumerate() { // This makes the error point at the bound, but we want to point at the argument From 92dcc9a02d7f39a64031bb89227a081a574a963d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Mon, 20 Apr 2020 10:42:12 -0700 Subject: [PATCH 17/19] Remove some allocations in predicate evaluation --- src/librustc_infer/traits/util.rs | 7 +++---- src/librustc_trait_selection/traits/auto_trait.rs | 12 +++++++----- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/src/librustc_infer/traits/util.rs b/src/librustc_infer/traits/util.rs index 3547ef6e497f9..a1b1975439c3a 100644 --- a/src/librustc_infer/traits/util.rs +++ b/src/librustc_infer/traits/util.rs @@ -149,21 +149,20 @@ impl Elaborator<'tcx> { // Get predicates declared on the trait. let predicates = tcx.super_predicates_of(data.def_id()); - let obligations = predicates.predicates.iter().map(|(pred, span)| { + let obligations = predicates.predicates.into_iter().map(|(pred, span)| { predicate_obligation( pred.subst_supertrait(tcx, &data.to_poly_trait_ref()), Some(*span), ) }); - debug!("super_predicates: data={:?} predicates={:?}", data, &obligations); + debug!("super_predicates: data={:?}", data); // Only keep those bounds that we haven't already seen. // This is necessary to prevent infinite recursion in some // cases. One common case is when people define // `trait Sized: Sized { }` rather than `trait Sized { }`. let visited = &mut self.visited; - let obligations = - obligations.filter(|obligation| visited.insert(&obligation.predicate)); + let obligations = obligations.filter(|o| visited.insert(&o.predicate)); self.stack.extend(obligations); } diff --git a/src/librustc_trait_selection/traits/auto_trait.rs b/src/librustc_trait_selection/traits/auto_trait.rs index b28658e0f1e58..6326a87c5edc3 100644 --- a/src/librustc_trait_selection/traits/auto_trait.rs +++ b/src/librustc_trait_selection/traits/auto_trait.rs @@ -281,7 +281,7 @@ impl AutoTraitFinder<'tcx> { }, })); - let mut computed_preds: FxHashSet<_> = param_env.caller_bounds.iter().cloned().collect(); + let computed_preds = param_env.caller_bounds.iter().cloned(); let mut user_computed_preds: FxHashSet<_> = user_env.caller_bounds.iter().cloned().collect(); @@ -358,9 +358,11 @@ impl AutoTraitFinder<'tcx> { _ => panic!("Unexpected error for '{:?}': {:?}", ty, result), }; - computed_preds.extend(user_computed_preds.iter().cloned()); - let normalized_preds = - elaborate_predicates(tcx, computed_preds.iter().cloned()).map(|o| o.predicate); + let normalized_preds = elaborate_predicates( + tcx, + computed_preds.clone().chain(user_computed_preds.iter().cloned()), + ) + .map(|o| o.predicate); new_env = ty::ParamEnv::new(tcx.mk_predicates(normalized_preds), param_env.reveal, None); } @@ -738,7 +740,7 @@ impl AutoTraitFinder<'tcx> { if p.ty().skip_binder().has_infer_types() { if !self.evaluate_nested_obligations( ty, - v.clone().iter().cloned(), + v.into_iter(), computed_preds, fresh_preds, predicates, From 51c901e4f531282ecc7519b3d15ff698aad28bbd Mon Sep 17 00:00:00 2001 From: Pietro Albini Date: Thu, 7 May 2020 23:12:13 +0200 Subject: [PATCH 18/19] ci: use the latest python available on windows This commit changes our Windows CI to always use the latest Python interpreter available in the GHA tool cache instead of hardcoding Python 3.7.6. This is needed because occasionally GitHub bumps the installed version, deleting the previous one. --- src/ci/scripts/install-msys2-packages.sh | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/ci/scripts/install-msys2-packages.sh b/src/ci/scripts/install-msys2-packages.sh index 3874a86e120b1..ff7479c05d04e 100755 --- a/src/ci/scripts/install-msys2-packages.sh +++ b/src/ci/scripts/install-msys2-packages.sh @@ -9,11 +9,19 @@ if isWindows; then pacman -S --noconfirm --needed base-devel ca-certificates make diffutils tar \ binutils + # Detect the native Python version installed on the agent. On GitHub + # Actions, the C:\hostedtoolcache\windows\Python directory contains a + # subdirectory for each installed Python version. + # + # The -V flag of the sort command sorts the input by version number. + native_python_version="$(ls /c/hostedtoolcache/windows/Python | sort -Vr | head -n 1)" + # Make sure we use the native python interpreter instead of some msys equivalent # one way or another. The msys interpreters seem to have weird path conversions # baked in which break LLVM's build system one way or another, so let's use the # native version which keeps everything as native as possible. - python_home="C:/hostedtoolcache/windows/Python/3.7.6/x64" + python_home="/c/hostedtoolcache/windows/Python/${native_python_version}/x64" cp "${python_home}/python.exe" "${python_home}/python3.exe" - ciCommandAddPath "C:\\hostedtoolcache\\windows\\Python\\3.7.6\\x64" + ciCommandAddPath "C:\\hostedtoolcache\\windows\\Python\\${native_python_version}\\x64" + ciCommandAddPath "C:\\hostedtoolcache\\windows\\Python\\${native_python_version}\\x64\\Scripts" fi From d0703f9970ab7d15dab55d78cd8d7538537832af Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Mon, 11 May 2020 13:24:24 -0400 Subject: [PATCH 19/19] Bump clippy submodule to fix compilation failure --- src/tools/clippy | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/clippy b/src/tools/clippy index 891e1a859b524..d4092ace00d60 160000 --- a/src/tools/clippy +++ b/src/tools/clippy @@ -1 +1 @@ -Subproject commit 891e1a859b52486936e021235fdc36fbdd9b4100 +Subproject commit d4092ace00d60634bcdc22135d82e05a53971263