From 7fda86249fd37e5ff148427771423bfefc0b1e4a Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Thu, 30 Jun 2022 10:26:17 -0400 Subject: [PATCH 1/5] promote placeholder bounds to 'static obligations In NLL, when we are promoting a bound out from a closure, if we have a requirement that `T: 'a` where `'a` is in a higher universe, we were previously ignoring that, which is totally wrong. We should be promoting those constraints to `'static`, since universes are not expressible across closure boundaries. --- .../rustc_borrowck/src/region_infer/mod.rs | 38 ++++++++++++++++--- .../generic-associated-types/issue-91139.rs | 1 + .../issue-91139.stderr | 14 ++++++- src/test/ui/nll/issue-98693.rs | 21 ++++++++++ src/test/ui/nll/issue-98693.stderr | 17 +++++++++ 5 files changed, 85 insertions(+), 6 deletions(-) create mode 100644 src/test/ui/nll/issue-98693.rs create mode 100644 src/test/ui/nll/issue-98693.stderr diff --git a/compiler/rustc_borrowck/src/region_infer/mod.rs b/compiler/rustc_borrowck/src/region_infer/mod.rs index f5c9392948b24..aa0af86fbf500 100644 --- a/compiler/rustc_borrowck/src/region_infer/mod.rs +++ b/compiler/rustc_borrowck/src/region_infer/mod.rs @@ -916,6 +916,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { /// The idea then is to lower the `T: 'X` constraint into multiple /// bounds -- e.g., if `'X` is the union of two free lifetimes, /// `'1` and `'2`, then we would create `T: '1` and `T: '2`. + #[instrument(level = "debug", skip(self, infcx, propagated_outlives_requirements))] fn try_promote_type_test( &self, infcx: &InferCtxt<'_, 'tcx>, @@ -933,11 +934,41 @@ impl<'tcx> RegionInferenceContext<'tcx> { return false; }; + debug!("subject = {:?}", subject); + + let r_scc = self.constraint_sccs.scc(*lower_bound); + + debug!( + "lower_bound = {:?} r_scc={:?} universe={:?}", + lower_bound, r_scc, self.scc_universes[r_scc] + ); + + // If the type test requires that `T: 'a` where `'a` is a + // placeholder from another universe, that effectively requires + // `T: 'static`, so we have to propagate that requirement. + // + // It doesn't matter *what* universe because the promoted `T` will + // always be in the root universe. + if let Some(p) = self.scc_values.placeholders_contained_in(r_scc).next() { + debug!("encountered placeholder in higher universe: {:?}, requiring 'static", p); + let static_r = self.universal_regions.fr_static; + propagated_outlives_requirements.push(ClosureOutlivesRequirement { + subject, + outlived_free_region: static_r, + blame_span: locations.span(body), + category: ConstraintCategory::Boring, + }); + + // we can return here -- the code below might push add'l constraints + // but they would all be weaker than this one. + return true; + } + // For each region outlived by lower_bound find a non-local, // universal region (it may be the same region) and add it to // `ClosureOutlivesRequirement`. - let r_scc = self.constraint_sccs.scc(*lower_bound); for ur in self.scc_values.universal_regions_outlived_by(r_scc) { + debug!("universal_region_outlived_by ur={:?}", ur); // Check whether we can already prove that the "subject" outlives `ur`. // If so, we don't have to propagate this requirement to our caller. // @@ -962,8 +993,6 @@ impl<'tcx> RegionInferenceContext<'tcx> { continue; } - debug!("try_promote_type_test: ur={:?}", ur); - let non_local_ub = self.universal_region_relations.non_local_upper_bounds(ur); debug!("try_promote_type_test: non_local_ub={:?}", non_local_ub); @@ -1000,6 +1029,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { /// will use it's *external name*, which will be a `RegionKind` /// variant that can be used in query responses such as /// `ReEarlyBound`. + #[instrument(level = "debug", skip(self, infcx))] fn try_promote_type_test_subject( &self, infcx: &InferCtxt<'_, 'tcx>, @@ -1007,8 +1037,6 @@ impl<'tcx> RegionInferenceContext<'tcx> { ) -> Option> { let tcx = infcx.tcx; - debug!("try_promote_type_test_subject(ty = {:?})", ty); - let ty = tcx.fold_regions(ty, |r, _depth| { let region_vid = self.to_region_vid(r); diff --git a/src/test/ui/generic-associated-types/issue-91139.rs b/src/test/ui/generic-associated-types/issue-91139.rs index 092fa939c308d..40eef11f058e1 100644 --- a/src/test/ui/generic-associated-types/issue-91139.rs +++ b/src/test/ui/generic-associated-types/issue-91139.rs @@ -22,6 +22,7 @@ fn foo() { //~| ERROR `T` does not live long enough //~| ERROR `T` does not live long enough //~| ERROR `T` does not live long enough + //~| ERROR `T` may not live long enough // // FIXME: This error is bogus, but it arises because we try to validate // that `<() as Foo>::Type<'a>` is valid, which requires proving diff --git a/src/test/ui/generic-associated-types/issue-91139.stderr b/src/test/ui/generic-associated-types/issue-91139.stderr index 6c5092978c84b..b789b3a42f330 100644 --- a/src/test/ui/generic-associated-types/issue-91139.stderr +++ b/src/test/ui/generic-associated-types/issue-91139.stderr @@ -34,6 +34,17 @@ error: `T` does not live long enough LL | let _: for<'a> fn(<() as Foo>::Type<'a>, &'a T) = |_, _| (); | ^^^^^^^^^ +error[E0310]: the parameter type `T` may not live long enough + --> $DIR/issue-91139.rs:16:58 + | +LL | let _: for<'a> fn(<() as Foo>::Type<'a>, &'a T) = |_, _| (); + | ^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds + | +help: consider adding an explicit lifetime bound... + | +LL | fn foo() { + | +++++++++ + error: `T` does not live long enough --> $DIR/issue-91139.rs:16:58 | @@ -46,5 +57,6 @@ error: `T` does not live long enough LL | let _: for<'a> fn(<() as Foo>::Type<'a>, &'a T) = |_, _| (); | ^^^^^^^^^ -error: aborting due to 8 previous errors +error: aborting due to 9 previous errors +For more information about this error, try `rustc --explain E0310`. diff --git a/src/test/ui/nll/issue-98693.rs b/src/test/ui/nll/issue-98693.rs new file mode 100644 index 0000000000000..18e6ec6304646 --- /dev/null +++ b/src/test/ui/nll/issue-98693.rs @@ -0,0 +1,21 @@ +// Regression test for #98693. +// +// The closure encounters an obligation that `T` must outlive `!U1`, +// a placeholder from universe U1. We were ignoring this placeholder +// when promoting the constraint to the enclosing function, and +// thus incorrectly judging the closure to be safe. + +fn assert_static() +where + for<'a> T: 'a, +{ +} + +fn test() { + || { + //~^ ERROR the parameter type `T` may not live long enough + assert_static::(); + }; +} + +fn main() {} diff --git a/src/test/ui/nll/issue-98693.stderr b/src/test/ui/nll/issue-98693.stderr new file mode 100644 index 0000000000000..31689620c6414 --- /dev/null +++ b/src/test/ui/nll/issue-98693.stderr @@ -0,0 +1,17 @@ +error[E0310]: the parameter type `T` may not live long enough + --> $DIR/issue-98693.rs:15:5 + | +LL | / || { +LL | | +LL | | assert_static::(); +LL | | }; + | |_____^ ...so that the type `T` will meet its required lifetime bounds + | +help: consider adding an explicit lifetime bound... + | +LL | fn test() { + | +++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0310`. From 4944b5769bca72b51c0ceb04f6f68530c3209818 Mon Sep 17 00:00:00 2001 From: Jeron Aldaron Lau Date: Sat, 9 Jul 2022 14:20:34 -0500 Subject: [PATCH 2/5] Remove extra space in AtomicPtr::new docs --- library/core/src/sync/atomic.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/core/src/sync/atomic.rs b/library/core/src/sync/atomic.rs index b32dcfefacda8..f5eb1c8b9dcbd 100644 --- a/library/core/src/sync/atomic.rs +++ b/library/core/src/sync/atomic.rs @@ -991,7 +991,7 @@ impl AtomicPtr { /// use std::sync::atomic::AtomicPtr; /// /// let ptr = &mut 5; - /// let atomic_ptr = AtomicPtr::new(ptr); + /// let atomic_ptr = AtomicPtr::new(ptr); /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] From d5aed20f4712010585532b4de51918bd66ac4797 Mon Sep 17 00:00:00 2001 From: rhysd Date: Sun, 10 Jul 2022 02:48:53 +0900 Subject: [PATCH 3/5] Remove duplicate notes from error on inter-crate ambiguous impl of traits (fix #99092) --- .../src/traits/coherence.rs | 4 ++-- .../src/traits/select/candidate_assembly.rs | 2 +- .../src/traits/select/mod.rs | 14 +++++++------- .../src/traits/specialize/mod.rs | 4 ++-- ...oherence-projection-conflict-orphan.stderr | 1 - .../inter-crate-ambiguity-causes-notes.rs | 19 +++++++++++++++++++ .../inter-crate-ambiguity-causes-notes.stderr | 14 ++++++++++++++ 7 files changed, 45 insertions(+), 13 deletions(-) create mode 100644 src/test/ui/coherence/inter-crate-ambiguity-causes-notes.rs create mode 100644 src/test/ui/coherence/inter-crate-ambiguity-causes-notes.stderr diff --git a/compiler/rustc_trait_selection/src/traits/coherence.rs b/compiler/rustc_trait_selection/src/traits/coherence.rs index f933f1c3c94a7..52ca23c4b303e 100644 --- a/compiler/rustc_trait_selection/src/traits/coherence.rs +++ b/compiler/rustc_trait_selection/src/traits/coherence.rs @@ -13,7 +13,7 @@ use crate::traits::{ self, FulfillmentContext, Normalized, Obligation, ObligationCause, PredicateObligation, PredicateObligations, SelectionContext, }; -//use rustc_data_structures::fx::FxHashMap; +use rustc_data_structures::fx::FxIndexSet; use rustc_errors::Diagnostic; use rustc_hir::def_id::{DefId, LOCAL_CRATE}; use rustc_infer::infer::{InferCtxt, TyCtxtInferExt}; @@ -44,7 +44,7 @@ pub enum Conflict { pub struct OverlapResult<'tcx> { pub impl_header: ty::ImplHeader<'tcx>, - pub intercrate_ambiguity_causes: Vec, + pub intercrate_ambiguity_causes: FxIndexSet, /// `true` if the overlap might've been permitted before the shift /// to universes. diff --git a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs index 21e14eae0ee27..96d83deeeb7ab 100644 --- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs +++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs @@ -110,7 +110,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { IntercrateAmbiguityCause::DownstreamCrate { trait_desc, self_desc } }; debug!(?cause, "evaluate_stack: pushing cause"); - self.intercrate_ambiguity_causes.as_mut().unwrap().push(cause); + self.intercrate_ambiguity_causes.as_mut().unwrap().insert(cause); } } } diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index b205ca8fa1169..2bb53a466caa4 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -24,7 +24,7 @@ use crate::traits::error_reporting::InferCtxtExt; use crate::traits::project::ProjectAndUnifyResult; use crate::traits::project::ProjectionCacheKeyExt; use crate::traits::ProjectionCacheKey; -use rustc_data_structures::fx::{FxHashMap, FxHashSet}; +use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexSet}; use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_errors::{Diagnostic, ErrorGuaranteed}; use rustc_hir as hir; @@ -52,7 +52,7 @@ pub use rustc_middle::traits::select::*; mod candidate_assembly; mod confirmation; -#[derive(Clone, Debug)] +#[derive(Clone, Debug, Eq, PartialEq, Hash)] pub enum IntercrateAmbiguityCause { DownstreamCrate { trait_desc: String, self_desc: Option }, UpstreamCrateUpdate { trait_desc: String, self_desc: Option }, @@ -128,7 +128,7 @@ pub struct SelectionContext<'cx, 'tcx> { /// We don't do his until we detect a coherence error because it can /// lead to false overflow results (#47139) and because always /// computing it may negatively impact performance. - intercrate_ambiguity_causes: Option>, + intercrate_ambiguity_causes: Option>, /// The mode that trait queries run in, which informs our error handling /// policy. In essence, canonicalized queries need their errors propagated @@ -254,14 +254,14 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { pub fn enable_tracking_intercrate_ambiguity_causes(&mut self) { assert!(self.intercrate); assert!(self.intercrate_ambiguity_causes.is_none()); - self.intercrate_ambiguity_causes = Some(vec![]); + self.intercrate_ambiguity_causes = Some(FxIndexSet::default()); debug!("selcx: enable_tracking_intercrate_ambiguity_causes"); } /// Gets the intercrate ambiguity causes collected since tracking /// was enabled and disables tracking at the same time. If /// tracking is not enabled, just returns an empty vector. - pub fn take_intercrate_ambiguity_causes(&mut self) -> Vec { + pub fn take_intercrate_ambiguity_causes(&mut self) -> FxIndexSet { assert!(self.intercrate); self.intercrate_ambiguity_causes.take().unwrap_or_default() } @@ -960,7 +960,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { }); debug!(?cause, "evaluate_stack: pushing cause"); - self.intercrate_ambiguity_causes.as_mut().unwrap().push(cause); + self.intercrate_ambiguity_causes.as_mut().unwrap().insert(cause); } } } @@ -1252,7 +1252,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { reservation impl ambiguity on {:?}", def_id ); - intercrate_ambiguity_clauses.push( + intercrate_ambiguity_clauses.insert( IntercrateAmbiguityCause::ReservationImpl { message: value.to_string(), }, diff --git a/compiler/rustc_trait_selection/src/traits/specialize/mod.rs b/compiler/rustc_trait_selection/src/traits/specialize/mod.rs index a80354897d618..fdd282d47a901 100644 --- a/compiler/rustc_trait_selection/src/traits/specialize/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/specialize/mod.rs @@ -15,7 +15,7 @@ use specialization_graph::GraphExt; use crate::infer::{InferCtxt, InferOk, TyCtxtInferExt}; use crate::traits::select::IntercrateAmbiguityCause; use crate::traits::{self, coherence, FutureCompatOverlapErrorKind, ObligationCause, TraitEngine}; -use rustc_data_structures::fx::FxHashSet; +use rustc_data_structures::fx::{FxHashSet, FxIndexSet}; use rustc_errors::{struct_span_err, EmissionGuarantee, LintDiagnosticBuilder}; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_middle::ty::subst::{InternalSubsts, Subst, SubstsRef}; @@ -33,7 +33,7 @@ pub struct OverlapError { pub with_impl: DefId, pub trait_desc: String, pub self_desc: Option, - pub intercrate_ambiguity_causes: Vec, + pub intercrate_ambiguity_causes: FxIndexSet, pub involves_placeholder: bool, } diff --git a/src/test/ui/coherence/coherence-projection-conflict-orphan.stderr b/src/test/ui/coherence/coherence-projection-conflict-orphan.stderr index 8e7d4589e6140..b1ee0795b2eb3 100644 --- a/src/test/ui/coherence/coherence-projection-conflict-orphan.stderr +++ b/src/test/ui/coherence/coherence-projection-conflict-orphan.stderr @@ -8,7 +8,6 @@ LL | impl Foo for A { } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `i32` | = note: upstream crates may add a new impl of trait `std::iter::Iterator` for type `i32` in future versions - = note: upstream crates may add a new impl of trait `std::iter::Iterator` for type `i32` in future versions error: aborting due to previous error diff --git a/src/test/ui/coherence/inter-crate-ambiguity-causes-notes.rs b/src/test/ui/coherence/inter-crate-ambiguity-causes-notes.rs new file mode 100644 index 0000000000000..5b11c78ab2605 --- /dev/null +++ b/src/test/ui/coherence/inter-crate-ambiguity-causes-notes.rs @@ -0,0 +1,19 @@ +struct S; + +impl From<()> for S { + fn from(x: ()) -> Self { + S + } +} + +impl From for S +//~^ ERROR conflicting implementations of trait +where + I: Iterator, +{ + fn from(x: I) -> Self { + S + } +} + +fn main() {} diff --git a/src/test/ui/coherence/inter-crate-ambiguity-causes-notes.stderr b/src/test/ui/coherence/inter-crate-ambiguity-causes-notes.stderr new file mode 100644 index 0000000000000..038a0199a8f27 --- /dev/null +++ b/src/test/ui/coherence/inter-crate-ambiguity-causes-notes.stderr @@ -0,0 +1,14 @@ +error[E0119]: conflicting implementations of trait `std::convert::From<()>` for type `S` + --> $DIR/inter-crate-ambiguity-causes-notes.rs:9:1 + | +LL | impl From<()> for S { + | ------------------- first implementation here +... +LL | impl From for S + | ^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `S` + | + = note: upstream crates may add a new impl of trait `std::iter::Iterator` for type `()` in future versions + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0119`. From 2f3624ccb6c7185306606098110dc91cdccc3b2e Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sun, 10 Jul 2022 12:48:11 +0200 Subject: [PATCH 4/5] Group .test-arrow CSS rules and fix rgb/rgba property --- src/librustdoc/html/static/css/themes/dark.css | 4 +--- src/librustdoc/html/static/css/themes/light.css | 6 ++---- 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/src/librustdoc/html/static/css/themes/dark.css b/src/librustdoc/html/static/css/themes/dark.css index a678ec1e1c108..184d0e77a90b8 100644 --- a/src/librustdoc/html/static/css/themes/dark.css +++ b/src/librustdoc/html/static/css/themes/dark.css @@ -178,9 +178,6 @@ a { color: #D2991D; } -a.test-arrow { - color: #dedede; -} body.source .example-wrap pre.rust a { background: #333; } @@ -255,6 +252,7 @@ pre.rust .question-mark { } a.test-arrow { + color: #dedede; background-color: rgba(78, 139, 202, 0.2); } diff --git a/src/librustdoc/html/static/css/themes/light.css b/src/librustdoc/html/static/css/themes/light.css index e8770ac212426..c6ba13fe1d6fb 100644 --- a/src/librustdoc/html/static/css/themes/light.css +++ b/src/librustdoc/html/static/css/themes/light.css @@ -175,9 +175,6 @@ a { color: #3873AD; } -a.test-arrow { - color: #f5f5f5; -} body.source .example-wrap pre.rust a { background: #eee; } @@ -239,7 +236,8 @@ pre.rust .question-mark { } a.test-arrow { - background-color: rgb(78, 139, 202, 0.2); + color: #f5f5f5; + background-color: rgba(78, 139, 202, 0.2); } a.test-arrow:hover{ From 6245d725a251325f29902656ac3ca5adb4c51f2a Mon Sep 17 00:00:00 2001 From: oxalica Date: Mon, 11 Jul 2022 05:40:48 +0800 Subject: [PATCH 5/5] Fix `download-ci-llvm` NixOS patching for binaries LLVM tools should also be patched, since they are used in some tests, specially, - src/test/run-make-fulldeps/cross-lang-lto (llvm-ar) - src/test/run-make-fulldeps/cross-lang-lto-upstream-rlibs (llvm-ar) - src/test/run-make-fulldeps/issue-64153 (llvm-objdump) To be more future proof, we should patch all binaries in `bin`. --- src/bootstrap/native.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/bootstrap/native.rs b/src/bootstrap/native.rs index 7ddd0ba5c3def..8254f01ce874d 100644 --- a/src/bootstrap/native.rs +++ b/src/bootstrap/native.rs @@ -147,8 +147,8 @@ pub(crate) fn maybe_download_ci_llvm(builder: &Builder<'_>) { let key = format!("{}{}", llvm_sha, config.llvm_assertions); if program_out_of_date(&llvm_stamp, &key) && !config.dry_run { download_ci_llvm(builder, &llvm_sha); - for binary in ["llvm-config", "FileCheck"] { - builder.fix_bin_or_dylib(&llvm_root.join("bin").join(binary)); + for entry in t!(fs::read_dir(llvm_root.join("bin"))) { + builder.fix_bin_or_dylib(&t!(entry).path()); } // Update the timestamp of llvm-config to force rustc_llvm to be