diff --git a/.mailmap b/.mailmap index 022cdd0fd50c1..42c86a827693a 100644 --- a/.mailmap +++ b/.mailmap @@ -15,6 +15,7 @@ Adrien Tétar Ahmed Charles Alan Egerton Alan Stoate +Albert Larsan Albert Larsan <74931857+albertlarsan68@users.noreply.github.com> Alessandro Decina Alex Burka Alex Burka Alex Hansen diff --git a/compiler/rustc_error_messages/locales/en-US/infer.ftl b/compiler/rustc_error_messages/locales/en-US/infer.ftl index cc38d71b484a4..164d6d26d230d 100644 --- a/compiler/rustc_error_messages/locales/en-US/infer.ftl +++ b/compiler/rustc_error_messages/locales/en-US/infer.ftl @@ -268,28 +268,28 @@ infer_but_calling_introduces = {$has_param_name -> [true] `{$param_name}` *[false] `fn` parameter } has {$lifetime_kind -> - [named] lifetime `{$lifetime}` - *[anon] an anonymous lifetime `'_` -} but calling `{assoc_item}` introduces an implicit `'static` lifetime requirement + [true] lifetime `{$lifetime}` + *[false] an anonymous lifetime `'_` +} but calling `{$assoc_item}` introduces an implicit `'static` lifetime requirement .label1 = {$has_lifetime -> - [named] lifetime `{$lifetime}` - *[anon] an anonymous lifetime `'_` + [true] lifetime `{$lifetime}` + *[false] an anonymous lifetime `'_` } .label2 = ...is used and required to live as long as `'static` here because of an implicit lifetime bound on the {$has_impl_path -> - [named] `impl` of `{$impl_path}` - *[anon] inherent `impl` + [true] `impl` of `{$impl_path}` + *[false] inherent `impl` } infer_but_needs_to_satisfy = {$has_param_name -> [true] `{$param_name}` *[false] `fn` parameter } has {$has_lifetime -> - [named] lifetime `{$lifetime}` - *[anon] an anonymous lifetime `'_` + [true] lifetime `{$lifetime}` + *[false] an anonymous lifetime `'_` } but it needs to satisfy a `'static` lifetime requirement .influencer = this data with {$has_lifetime -> - [named] lifetime `{$lifetime}` - *[anon] an anonymous lifetime `'_` + [true] lifetime `{$lifetime}` + *[false] an anonymous lifetime `'_` }... .require = {$spans_empty -> *[true] ...is used and required to live as long as `'static` here @@ -302,8 +302,8 @@ infer_more_targeted = {$has_param_name -> [true] `{$param_name}` *[false] `fn` parameter } has {$has_lifetime -> - [named] lifetime `{$lifetime}` - *[anon] an anonymous lifetime `'_` + [true] lifetime `{$lifetime}` + *[false] an anonymous lifetime `'_` } but calling `{$ident}` introduces an implicit `'static` lifetime requirement infer_ril_introduced_here = `'static` requirement introduced here diff --git a/compiler/rustc_infer/src/errors/mod.rs b/compiler/rustc_infer/src/errors/mod.rs index 033a1842edb25..8bf3a160abbb4 100644 --- a/compiler/rustc_infer/src/errors/mod.rs +++ b/compiler/rustc_infer/src/errors/mod.rs @@ -927,6 +927,8 @@ pub struct ButNeedsToSatisfy { #[subdiagnostic] pub req_introduces_loc: Option, + pub has_param_name: bool, + pub param_name: String, pub spans_empty: bool, pub has_lifetime: bool, pub lifetime: String, diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs index 49ad3ce50b8f5..6a463583dfb0f 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs @@ -98,6 +98,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { let sp = var_origin.span(); let return_sp = sub_origin.span(); let param = self.find_param_with_region(*sup_r, *sub_r)?; + let simple_ident = param.param.pat.simple_ident(); let lifetime_name = if sup_r.has_name() { sup_r.to_string() } else { "'_".to_owned() }; let (mention_influencer, influencer_point) = @@ -187,7 +188,9 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { req_introduces_loc: subdiag, has_lifetime: sup_r.has_name(), - lifetime: sup_r.to_string(), + lifetime: lifetime_name.clone(), + has_param_name: simple_ident.is_some(), + param_name: simple_ident.map(|x| x.to_string()).unwrap_or_default(), spans_empty, bound, }; diff --git a/compiler/rustc_target/src/spec/s390x_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/s390x_unknown_linux_gnu.rs index cda88de0ea406..f2c722b9a89da 100644 --- a/compiler/rustc_target/src/spec/s390x_unknown_linux_gnu.rs +++ b/compiler/rustc_target/src/spec/s390x_unknown_linux_gnu.rs @@ -1,5 +1,5 @@ use crate::abi::Endian; -use crate::spec::{StackProbeType, Target}; +use crate::spec::{SanitizerSet, StackProbeType, Target}; pub fn target() -> Target { let mut base = super::linux_gnu_base::opts(); @@ -13,6 +13,8 @@ pub fn target() -> Target { base.max_atomic_width = Some(64); base.min_global_align = Some(16); base.stack_probes = StackProbeType::Inline; + base.supported_sanitizers = + SanitizerSet::ADDRESS | SanitizerSet::LEAK | SanitizerSet::MEMORY | SanitizerSet::THREAD; Target { llvm_target: "s390x-unknown-linux-gnu".into(), diff --git a/compiler/rustc_target/src/spec/s390x_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/s390x_unknown_linux_musl.rs index 91e63aee5e490..8fe9d023c527e 100644 --- a/compiler/rustc_target/src/spec/s390x_unknown_linux_musl.rs +++ b/compiler/rustc_target/src/spec/s390x_unknown_linux_musl.rs @@ -1,5 +1,5 @@ use crate::abi::Endian; -use crate::spec::{StackProbeType, Target}; +use crate::spec::{SanitizerSet, StackProbeType, Target}; pub fn target() -> Target { let mut base = super::linux_musl_base::opts(); @@ -14,6 +14,8 @@ pub fn target() -> Target { base.min_global_align = Some(16); base.static_position_independent_executables = true; base.stack_probes = StackProbeType::Inline; + base.supported_sanitizers = + SanitizerSet::ADDRESS | SanitizerSet::LEAK | SanitizerSet::MEMORY | SanitizerSet::THREAD; Target { llvm_target: "s390x-unknown-linux-musl".into(), diff --git a/compiler/rustc_trait_selection/src/solve/assembly.rs b/compiler/rustc_trait_selection/src/solve/assembly.rs index 31c1bc9ecc062..cdb72d49834f0 100644 --- a/compiler/rustc_trait_selection/src/solve/assembly.rs +++ b/compiler/rustc_trait_selection/src/solve/assembly.rs @@ -1,7 +1,7 @@ //! Code shared by trait and projection goals for candidate assembly. use super::infcx_ext::InferCtxtExt; -use super::{CanonicalResponse, Certainty, EvalCtxt, Goal, MaybeCause, QueryResult}; +use super::{CanonicalResponse, Certainty, EvalCtxt, Goal, QueryResult}; use rustc_hir::def_id::DefId; use rustc_infer::traits::query::NoSolution; use rustc_infer::traits::util::elaborate_predicates; @@ -148,9 +148,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { if goal.predicate.self_ty().is_ty_var() { return vec![Candidate { source: CandidateSource::BuiltinImpl, - result: self - .make_canonical_response(Certainty::Maybe(MaybeCause::Ambiguity)) - .unwrap(), + result: self.make_canonical_response(Certainty::AMBIGUOUS).unwrap(), }]; } diff --git a/compiler/rustc_trait_selection/src/solve/mod.rs b/compiler/rustc_trait_selection/src/solve/mod.rs index 32eb84635b536..da2a1a19957e1 100644 --- a/compiler/rustc_trait_selection/src/solve/mod.rs +++ b/compiler/rustc_trait_selection/src/solve/mod.rs @@ -19,6 +19,7 @@ use std::mem; +use rustc_hir::def_id::DefId; use rustc_infer::infer::canonical::{Canonical, CanonicalVarKind, CanonicalVarValues}; use rustc_infer::infer::canonical::{OriginalQueryValues, QueryRegionConstraints, QueryResponse}; use rustc_infer::infer::{InferCtxt, InferOk, TyCtxtInferExt}; @@ -26,7 +27,9 @@ use rustc_infer::traits::query::NoSolution; use rustc_infer::traits::Obligation; use rustc_middle::infer::canonical::Certainty as OldCertainty; use rustc_middle::ty::{self, Ty, TyCtxt}; -use rustc_middle::ty::{RegionOutlivesPredicate, ToPredicate, TypeOutlivesPredicate}; +use rustc_middle::ty::{ + CoercePredicate, RegionOutlivesPredicate, SubtypePredicate, ToPredicate, TypeOutlivesPredicate, +}; use rustc_span::DUMMY_SP; use crate::traits::ObligationCause; @@ -87,6 +90,8 @@ pub enum Certainty { } impl Certainty { + pub const AMBIGUOUS: Certainty = Certainty::Maybe(MaybeCause::Ambiguity); + /// When proving multiple goals using **AND**, e.g. nested obligations for an impl, /// use this function to unify the certainty of these goals pub fn unify_and(self, other: Certainty) -> Certainty { @@ -243,16 +248,28 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> { ty::PredicateKind::Clause(ty::Clause::RegionOutlives(predicate)) => { self.compute_region_outlives_goal(Goal { param_env, predicate }) } + ty::PredicateKind::Subtype(predicate) => { + self.compute_subtype_goal(Goal { param_env, predicate }) + } + ty::PredicateKind::Coerce(predicate) => { + self.compute_coerce_goal(Goal { param_env, predicate }) + } + ty::PredicateKind::ClosureKind(def_id, substs, kind) => self + .compute_closure_kind_goal(Goal { + param_env, + predicate: (def_id, substs, kind), + }), + ty::PredicateKind::Ambiguous => self.make_canonical_response(Certainty::AMBIGUOUS), // FIXME: implement these predicates :) ty::PredicateKind::WellFormed(_) | ty::PredicateKind::ObjectSafe(_) - | ty::PredicateKind::ClosureKind(_, _, _) - | ty::PredicateKind::Subtype(_) - | ty::PredicateKind::Coerce(_) | ty::PredicateKind::ConstEvaluatable(_) - | ty::PredicateKind::ConstEquate(_, _) - | ty::PredicateKind::TypeWellFormedFromEnv(_) - | ty::PredicateKind::Ambiguous => self.make_canonical_response(Certainty::Yes), + | ty::PredicateKind::ConstEquate(_, _) => { + self.make_canonical_response(Certainty::Yes) + } + ty::PredicateKind::TypeWellFormedFromEnv(..) => { + bug!("TypeWellFormedFromEnv is only used for Chalk") + } } } else { let kind = self.infcx.replace_bound_vars_with_placeholders(kind); @@ -275,6 +292,58 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> { ) -> QueryResult<'tcx> { self.make_canonical_response(Certainty::Yes) } + + fn compute_coerce_goal( + &mut self, + goal: Goal<'tcx, CoercePredicate<'tcx>>, + ) -> QueryResult<'tcx> { + self.compute_subtype_goal(Goal { + param_env: goal.param_env, + predicate: SubtypePredicate { + a_is_expected: false, + a: goal.predicate.a, + b: goal.predicate.b, + }, + }) + } + + fn compute_subtype_goal( + &mut self, + goal: Goal<'tcx, SubtypePredicate<'tcx>>, + ) -> QueryResult<'tcx> { + if goal.predicate.a.is_ty_var() && goal.predicate.b.is_ty_var() { + // FIXME: Do we want to register a subtype relation between these vars? + // That won't actually reflect in the query response, so it seems moot. + self.make_canonical_response(Certainty::AMBIGUOUS) + } else { + self.infcx.probe(|_| { + let InferOk { value: (), obligations } = self + .infcx + .at(&ObligationCause::dummy(), goal.param_env) + .sub(goal.predicate.a, goal.predicate.b)?; + self.evaluate_all_and_make_canonical_response( + obligations.into_iter().map(|pred| pred.into()).collect(), + ) + }) + } + } + + fn compute_closure_kind_goal( + &mut self, + goal: Goal<'tcx, (DefId, ty::SubstsRef<'tcx>, ty::ClosureKind)>, + ) -> QueryResult<'tcx> { + let (_, substs, expected_kind) = goal.predicate; + let found_kind = substs.as_closure().kind_ty().to_opt_closure_kind(); + + let Some(found_kind) = found_kind else { + return self.make_canonical_response(Certainty::AMBIGUOUS); + }; + if found_kind.extends(expected_kind) { + self.make_canonical_response(Certainty::Yes) + } else { + Err(NoSolution) + } + } } impl<'tcx> EvalCtxt<'_, 'tcx> { diff --git a/compiler/rustc_trait_selection/src/solve/project_goals.rs b/compiler/rustc_trait_selection/src/solve/project_goals.rs index e39fa05339286..32e15f03998b3 100644 --- a/compiler/rustc_trait_selection/src/solve/project_goals.rs +++ b/compiler/rustc_trait_selection/src/solve/project_goals.rs @@ -3,7 +3,7 @@ use crate::traits::{specialization_graph, translate_substs}; use super::assembly::{self, Candidate, CandidateSource}; use super::infcx_ext::InferCtxtExt; use super::trait_goals::structural_traits; -use super::{Certainty, EvalCtxt, Goal, MaybeCause, QueryResult}; +use super::{Certainty, EvalCtxt, Goal, QueryResult}; use rustc_errors::ErrorGuaranteed; use rustc_hir::def::DefKind; use rustc_hir::def_id::DefId; @@ -229,8 +229,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for ProjectionPredicate<'tcx> { goal.predicate.def_id(), impl_def_id )? else { - let certainty = Certainty::Maybe(MaybeCause::Ambiguity); - return ecx.make_canonical_response(trait_ref_certainty.unify_and(certainty)); + return ecx.make_canonical_response(trait_ref_certainty.unify_and(Certainty::AMBIGUOUS)); }; if !assoc_def.item.defaultness(tcx).has_value() { @@ -382,7 +381,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for ProjectionPredicate<'tcx> { .to_predicate(ecx.tcx()); Self::consider_assumption(ecx, goal, pred) } else { - ecx.make_canonical_response(Certainty::Maybe(MaybeCause::Ambiguity)) + ecx.make_canonical_response(Certainty::AMBIGUOUS) } } diff --git a/compiler/rustc_trait_selection/src/solve/trait_goals.rs b/compiler/rustc_trait_selection/src/solve/trait_goals.rs index 9985d7181bb7d..4b6d673c999c9 100644 --- a/compiler/rustc_trait_selection/src/solve/trait_goals.rs +++ b/compiler/rustc_trait_selection/src/solve/trait_goals.rs @@ -4,7 +4,7 @@ use std::iter; use super::assembly::{self, Candidate, CandidateSource}; use super::infcx_ext::InferCtxtExt; -use super::{Certainty, EvalCtxt, Goal, MaybeCause, QueryResult}; +use super::{Certainty, EvalCtxt, Goal, QueryResult}; use rustc_hir::def_id::DefId; use rustc_infer::infer::InferCtxt; use rustc_infer::traits::query::NoSolution; @@ -133,7 +133,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> { goal: Goal<'tcx, Self>, ) -> QueryResult<'tcx> { if goal.predicate.self_ty().has_non_region_infer() { - return ecx.make_canonical_response(Certainty::Maybe(MaybeCause::Ambiguity)); + return ecx.make_canonical_response(Certainty::AMBIGUOUS); } let tcx = ecx.tcx(); @@ -171,7 +171,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> { .to_predicate(ecx.tcx()); Self::consider_assumption(ecx, goal, pred) } else { - ecx.make_canonical_response(Certainty::Maybe(MaybeCause::Ambiguity)) + ecx.make_canonical_response(Certainty::AMBIGUOUS) } } diff --git a/library/core/src/fmt/mod.rs b/library/core/src/fmt/mod.rs index fa5073e3304d7..2a7ec544f9e2e 100644 --- a/library/core/src/fmt/mod.rs +++ b/library/core/src/fmt/mod.rs @@ -1355,11 +1355,11 @@ impl<'a> Formatter<'a> { /// } /// } /// - /// assert_eq!(&format!("{}", Foo::new(2)), "2"); - /// assert_eq!(&format!("{}", Foo::new(-1)), "-1"); - /// assert_eq!(&format!("{}", Foo::new(0)), "0"); - /// assert_eq!(&format!("{:#}", Foo::new(-1)), "-Foo 1"); - /// assert_eq!(&format!("{:0>#8}", Foo::new(-1)), "00-Foo 1"); + /// assert_eq!(format!("{}", Foo::new(2)), "2"); + /// assert_eq!(format!("{}", Foo::new(-1)), "-1"); + /// assert_eq!(format!("{}", Foo::new(0)), "0"); + /// assert_eq!(format!("{:#}", Foo::new(-1)), "-Foo 1"); + /// assert_eq!(format!("{:0>#8}", Foo::new(-1)), "00-Foo 1"); /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn pad_integral(&mut self, is_nonnegative: bool, prefix: &str, buf: &str) -> Result { @@ -1452,8 +1452,8 @@ impl<'a> Formatter<'a> { /// } /// } /// - /// assert_eq!(&format!("{Foo:<4}"), "Foo "); - /// assert_eq!(&format!("{Foo:0>4}"), "0Foo"); + /// assert_eq!(format!("{Foo:<4}"), "Foo "); + /// assert_eq!(format!("{Foo:0>4}"), "0Foo"); /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn pad(&mut self, s: &str) -> Result { @@ -1636,8 +1636,8 @@ impl<'a> Formatter<'a> { /// } /// } /// - /// assert_eq!(&format!("{Foo}"), "Foo"); - /// assert_eq!(&format!("{Foo:0>8}"), "Foo"); + /// assert_eq!(format!("{Foo}"), "Foo"); + /// assert_eq!(format!("{Foo:0>8}"), "Foo"); /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn write_str(&mut self, data: &str) -> Result { @@ -1659,8 +1659,8 @@ impl<'a> Formatter<'a> { /// } /// } /// - /// assert_eq!(&format!("{}", Foo(-1)), "Foo -1"); - /// assert_eq!(&format!("{:0>8}", Foo(2)), "Foo 2"); + /// assert_eq!(format!("{}", Foo(-1)), "Foo -1"); + /// assert_eq!(format!("{:0>8}", Foo(2)), "Foo 2"); /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn write_fmt(&mut self, fmt: Arguments<'_>) -> Result { @@ -1703,8 +1703,8 @@ impl<'a> Formatter<'a> { /// } /// /// // We set alignment to the right with ">". - /// assert_eq!(&format!("{Foo:G>3}"), "GGG"); - /// assert_eq!(&format!("{Foo:t>6}"), "tttttt"); + /// assert_eq!(format!("{Foo:G>3}"), "GGG"); + /// assert_eq!(format!("{Foo:t>6}"), "tttttt"); /// ``` #[must_use] #[stable(feature = "fmt_flags", since = "1.5.0")] @@ -1738,10 +1738,10 @@ impl<'a> Formatter<'a> { /// } /// } /// - /// assert_eq!(&format!("{Foo:<}"), "left"); - /// assert_eq!(&format!("{Foo:>}"), "right"); - /// assert_eq!(&format!("{Foo:^}"), "center"); - /// assert_eq!(&format!("{Foo}"), "into the void"); + /// assert_eq!(format!("{Foo:<}"), "left"); + /// assert_eq!(format!("{Foo:>}"), "right"); + /// assert_eq!(format!("{Foo:^}"), "center"); + /// assert_eq!(format!("{Foo}"), "into the void"); /// ``` #[must_use] #[stable(feature = "fmt_flags_align", since = "1.28.0")] @@ -1767,7 +1767,7 @@ impl<'a> Formatter<'a> { /// fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { /// if let Some(width) = formatter.width() { /// // If we received a width, we use it - /// write!(formatter, "{:width$}", &format!("Foo({})", self.0), width = width) + /// write!(formatter, "{:width$}", format!("Foo({})", self.0), width = width) /// } else { /// // Otherwise we do nothing special /// write!(formatter, "Foo({})", self.0) @@ -1775,8 +1775,8 @@ impl<'a> Formatter<'a> { /// } /// } /// - /// assert_eq!(&format!("{:10}", Foo(23)), "Foo(23) "); - /// assert_eq!(&format!("{}", Foo(23)), "Foo(23)"); + /// assert_eq!(format!("{:10}", Foo(23)), "Foo(23) "); + /// assert_eq!(format!("{}", Foo(23)), "Foo(23)"); /// ``` #[must_use] #[stable(feature = "fmt_flags", since = "1.5.0")] @@ -1806,8 +1806,8 @@ impl<'a> Formatter<'a> { /// } /// } /// - /// assert_eq!(&format!("{:.4}", Foo(23.2)), "Foo(23.2000)"); - /// assert_eq!(&format!("{}", Foo(23.2)), "Foo(23.20)"); + /// assert_eq!(format!("{:.4}", Foo(23.2)), "Foo(23.2000)"); + /// assert_eq!(format!("{}", Foo(23.2)), "Foo(23.20)"); /// ``` #[must_use] #[stable(feature = "fmt_flags", since = "1.5.0")] @@ -1837,9 +1837,9 @@ impl<'a> Formatter<'a> { /// } /// } /// - /// assert_eq!(&format!("{:+}", Foo(23)), "Foo(+23)"); - /// assert_eq!(&format!("{:+}", Foo(-23)), "Foo(-23)"); - /// assert_eq!(&format!("{}", Foo(23)), "Foo(23)"); + /// assert_eq!(format!("{:+}", Foo(23)), "Foo(+23)"); + /// assert_eq!(format!("{:+}", Foo(-23)), "Foo(-23)"); + /// assert_eq!(format!("{}", Foo(23)), "Foo(23)"); /// ``` #[must_use] #[stable(feature = "fmt_flags", since = "1.5.0")] @@ -1867,8 +1867,8 @@ impl<'a> Formatter<'a> { /// } /// } /// - /// assert_eq!(&format!("{:-}", Foo(23)), "-Foo(23)"); - /// assert_eq!(&format!("{}", Foo(23)), "Foo(23)"); + /// assert_eq!(format!("{:-}", Foo(23)), "-Foo(23)"); + /// assert_eq!(format!("{}", Foo(23)), "Foo(23)"); /// ``` #[must_use] #[stable(feature = "fmt_flags", since = "1.5.0")] @@ -1895,8 +1895,8 @@ impl<'a> Formatter<'a> { /// } /// } /// - /// assert_eq!(&format!("{:#}", Foo(23)), "Foo(23)"); - /// assert_eq!(&format!("{}", Foo(23)), "23"); + /// assert_eq!(format!("{:#}", Foo(23)), "Foo(23)"); + /// assert_eq!(format!("{}", Foo(23)), "23"); /// ``` #[must_use] #[stable(feature = "fmt_flags", since = "1.5.0")] @@ -1922,7 +1922,7 @@ impl<'a> Formatter<'a> { /// } /// } /// - /// assert_eq!(&format!("{:04}", Foo(23)), "23"); + /// assert_eq!(format!("{:04}", Foo(23)), "23"); /// ``` #[must_use] #[stable(feature = "fmt_flags", since = "1.5.0")] diff --git a/library/core/tests/num/dec2flt/mod.rs b/library/core/tests/num/dec2flt/mod.rs index c4e105cba600d..a2b9bb551e677 100644 --- a/library/core/tests/num/dec2flt/mod.rs +++ b/library/core/tests/num/dec2flt/mod.rs @@ -15,7 +15,7 @@ macro_rules! test_literal { for input in inputs { assert_eq!(input.parse(), Ok(x64)); assert_eq!(input.parse(), Ok(x32)); - let neg_input = &format!("-{input}"); + let neg_input = format!("-{input}"); assert_eq!(neg_input.parse(), Ok(-x64)); assert_eq!(neg_input.parse(), Ok(-x32)); } diff --git a/library/portable-simd/crates/core_simd/examples/spectral_norm.rs b/library/portable-simd/crates/core_simd/examples/spectral_norm.rs index 012182e090b9f..d576bd0ccee03 100644 --- a/library/portable-simd/crates/core_simd/examples/spectral_norm.rs +++ b/library/portable-simd/crates/core_simd/examples/spectral_norm.rs @@ -69,7 +69,7 @@ fn dot(x: &[f64], y: &[f64]) -> f64 { #[cfg(test)] #[test] fn test() { - assert_eq!(&format!("{:.9}", spectral_norm(100)), "1.274219991"); + assert_eq!(format!("{:.9}", spectral_norm(100)), "1.274219991"); } fn main() { diff --git a/library/std/src/io/error/tests.rs b/library/std/src/io/error/tests.rs index 16c634e9afd50..9aea62a5b940c 100644 --- a/library/std/src/io/error/tests.rs +++ b/library/std/src/io/error/tests.rs @@ -190,5 +190,5 @@ fn test_std_io_error_downcast() { let io_error = io_error.downcast::().unwrap_err(); assert_eq!(SIMPLE_MESSAGE.kind, io_error.kind()); - assert_eq!(SIMPLE_MESSAGE.message, &*format!("{io_error}")); + assert_eq!(SIMPLE_MESSAGE.message, format!("{io_error}")); } diff --git a/library/std/src/net/ip_addr/tests.rs b/library/std/src/net/ip_addr/tests.rs index 7c3430b2b217c..0eb59d45de727 100644 --- a/library/std/src/net/ip_addr/tests.rs +++ b/library/std/src/net/ip_addr/tests.rs @@ -125,8 +125,8 @@ fn ipv4_addr_to_string() { assert_eq!(Ipv4Addr::new(127, 127, 127, 127).to_string(), "127.127.127.127"); // Test padding - assert_eq!(&format!("{:16}", Ipv4Addr::new(1, 1, 1, 1)), "1.1.1.1 "); - assert_eq!(&format!("{:>16}", Ipv4Addr::new(1, 1, 1, 1)), " 1.1.1.1"); + assert_eq!(format!("{:16}", Ipv4Addr::new(1, 1, 1, 1)), "1.1.1.1 "); + assert_eq!(format!("{:>16}", Ipv4Addr::new(1, 1, 1, 1)), " 1.1.1.1"); } #[test] @@ -148,8 +148,8 @@ fn ipv6_addr_to_string() { "1111:2222:3333:4444:5555:6666:7777:8888" ); // padding - assert_eq!(&format!("{:20}", Ipv6Addr::new(1, 2, 3, 4, 5, 6, 7, 8)), "1:2:3:4:5:6:7:8 "); - assert_eq!(&format!("{:>20}", Ipv6Addr::new(1, 2, 3, 4, 5, 6, 7, 8)), " 1:2:3:4:5:6:7:8"); + assert_eq!(format!("{:20}", Ipv6Addr::new(1, 2, 3, 4, 5, 6, 7, 8)), "1:2:3:4:5:6:7:8 "); + assert_eq!(format!("{:>20}", Ipv6Addr::new(1, 2, 3, 4, 5, 6, 7, 8)), " 1:2:3:4:5:6:7:8"); // reduce a single run of zeros assert_eq!( diff --git a/library/std/src/net/socket_addr/tests.rs b/library/std/src/net/socket_addr/tests.rs index 15211f81981ba..dfc6dabbed1ed 100644 --- a/library/std/src/net/socket_addr/tests.rs +++ b/library/std/src/net/socket_addr/tests.rs @@ -64,11 +64,11 @@ fn ipv4_socket_addr_to_string() { // Test padding. assert_eq!( - &format!("{:16}", SocketAddrV4::new(Ipv4Addr::new(1, 1, 1, 1), 53)), + format!("{:16}", SocketAddrV4::new(Ipv4Addr::new(1, 1, 1, 1), 53)), "1.1.1.1:53 " ); assert_eq!( - &format!("{:>16}", SocketAddrV4::new(Ipv4Addr::new(1, 1, 1, 1), 53)), + format!("{:>16}", SocketAddrV4::new(Ipv4Addr::new(1, 1, 1, 1), 53)), " 1.1.1.1:53" ); } @@ -111,11 +111,11 @@ fn ipv6_socket_addr_to_string() { // Test padding. assert_eq!( - &format!("{:22}", SocketAddrV6::new(Ipv6Addr::new(1, 2, 3, 4, 5, 6, 7, 8), 9, 0, 0)), + format!("{:22}", SocketAddrV6::new(Ipv6Addr::new(1, 2, 3, 4, 5, 6, 7, 8), 9, 0, 0)), "[1:2:3:4:5:6:7:8]:9 " ); assert_eq!( - &format!("{:>22}", SocketAddrV6::new(Ipv6Addr::new(1, 2, 3, 4, 5, 6, 7, 8), 9, 0, 0)), + format!("{:>22}", SocketAddrV6::new(Ipv6Addr::new(1, 2, 3, 4, 5, 6, 7, 8), 9, 0, 0)), " [1:2:3:4:5:6:7:8]:9" ); } diff --git a/library/std/src/path.rs b/library/std/src/path.rs index c3593264e520b..2f53cf8393691 100644 --- a/library/std/src/path.rs +++ b/library/std/src/path.rs @@ -2531,6 +2531,8 @@ impl Path { /// Creates an owned [`PathBuf`] with `path` adjoined to `self`. /// + /// If `path` is absolute, it replaces the current path. + /// /// See [`PathBuf::push`] for more details on what it means to adjoin a path. /// /// # Examples @@ -2539,6 +2541,7 @@ impl Path { /// use std::path::{Path, PathBuf}; /// /// assert_eq!(Path::new("/etc").join("passwd"), PathBuf::from("/etc/passwd")); + /// assert_eq!(Path::new("/etc").join("/bin/sh"), PathBuf::from("/bin/sh")); /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[must_use] diff --git a/src/bootstrap/native.rs b/src/bootstrap/native.rs index e0d1504c9c780..cb5706ca0a651 100644 --- a/src/bootstrap/native.rs +++ b/src/bootstrap/native.rs @@ -1105,6 +1105,12 @@ fn supported_sanitizers( "x86_64-unknown-linux-musl" => { common_libs("linux", "x86_64", &["asan", "lsan", "msan", "tsan"]) } + "s390x-unknown-linux-gnu" => { + common_libs("linux", "s390x", &["asan", "lsan", "msan", "tsan"]) + } + "s390x-unknown-linux-musl" => { + common_libs("linux", "s390x", &["asan", "lsan", "msan", "tsan"]) + } _ => Vec::new(), } } diff --git a/src/ci/docker/host-x86_64/dist-s390x-linux/Dockerfile b/src/ci/docker/host-x86_64/dist-s390x-linux/Dockerfile index 43a449b3a1926..adb98d7ebb545 100644 --- a/src/ci/docker/host-x86_64/dist-s390x-linux/Dockerfile +++ b/src/ci/docker/host-x86_64/dist-s390x-linux/Dockerfile @@ -28,5 +28,5 @@ ENV \ ENV HOSTS=s390x-unknown-linux-gnu -ENV RUST_CONFIGURE_ARGS --enable-extended --enable-lld --enable-profiler --disable-docs +ENV RUST_CONFIGURE_ARGS --enable-extended --enable-lld --enable-sanitizers --enable-profiler --disable-docs ENV SCRIPT python3 ../x.py dist --host $HOSTS --target $HOSTS diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index b3b0933123349..da300b89a4e9b 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -9,7 +9,7 @@ use rustc_ast as ast; use rustc_data_structures::fx::FxHashSet; use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; -use rustc_hir::def_id::{DefId, LocalDefId}; +use rustc_hir::def_id::{DefId, DefIdSet, LocalDefId}; use rustc_hir::Mutability; use rustc_metadata::creader::{CStore, LoadedMacro}; use rustc_middle::ty::{self, TyCtxt}; @@ -45,7 +45,7 @@ pub(crate) fn try_inline( res: Res, name: Symbol, attrs: Option<&[ast::Attribute]>, - visited: &mut FxHashSet, + visited: &mut DefIdSet, ) -> Option> { let did = res.opt_def_id()?; if did.is_local() { @@ -163,7 +163,7 @@ pub(crate) fn try_inline_glob( cx: &mut DocContext<'_>, res: Res, current_mod: LocalDefId, - visited: &mut FxHashSet, + visited: &mut DefIdSet, inlined_names: &mut FxHashSet<(ItemType, Symbol)>, ) -> Option> { let did = res.opt_def_id()?; @@ -568,11 +568,7 @@ pub(crate) fn build_impl( )); } -fn build_module( - cx: &mut DocContext<'_>, - did: DefId, - visited: &mut FxHashSet, -) -> clean::Module { +fn build_module(cx: &mut DocContext<'_>, did: DefId, visited: &mut DefIdSet) -> clean::Module { let items = build_module_items(cx, did, visited, &mut FxHashSet::default(), None); let span = clean::Span::new(cx.tcx.def_span(did)); @@ -582,9 +578,9 @@ fn build_module( fn build_module_items( cx: &mut DocContext<'_>, did: DefId, - visited: &mut FxHashSet, + visited: &mut DefIdSet, inlined_names: &mut FxHashSet<(ItemType, Symbol)>, - allowed_def_ids: Option<&FxHashSet>, + allowed_def_ids: Option<&DefIdSet>, ) -> Vec { let mut items = Vec::new(); diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 20984696b6c01..34a7068e5da53 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -15,7 +15,7 @@ use rustc_attr as attr; use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap, FxIndexSet, IndexEntry}; use rustc_hir as hir; use rustc_hir::def::{CtorKind, DefKind, Res}; -use rustc_hir::def_id::{DefId, LOCAL_CRATE}; +use rustc_hir::def_id::{DefId, DefIdMap, DefIdSet, LOCAL_CRATE}; use rustc_hir::PredicateOrigin; use rustc_hir_analysis::hir_ty_to_ty; use rustc_infer::infer::region_constraints::{Constraint, RegionConstraintData}; @@ -1528,7 +1528,7 @@ fn maybe_expand_private_type_alias<'tcx>( let hir::ItemKind::TyAlias(ty, generics) = alias else { return None }; let provided_params = &path.segments.last().expect("segments were empty"); - let mut substs = FxHashMap::default(); + let mut substs = DefIdMap::default(); let generic_args = provided_params.args(); let mut indices: hir::GenericParamCount = Default::default(); @@ -2321,7 +2321,7 @@ fn clean_extern_crate<'tcx>( let krate_owner_def_id = krate.owner_id.to_def_id(); if please_inline { - let mut visited = FxHashSet::default(); + let mut visited = DefIdSet::default(); let res = Res::Def(DefKind::Mod, crate_def_id); @@ -2440,7 +2440,7 @@ fn clean_use_statement_inner<'tcx>( let path = clean_path(path, cx); let inner = if kind == hir::UseKind::Glob { if !denied { - let mut visited = FxHashSet::default(); + let mut visited = DefIdSet::default(); if let Some(items) = inline::try_inline_glob(cx, path.res, current_mod, &mut visited, inlined_names) { @@ -2459,7 +2459,7 @@ fn clean_use_statement_inner<'tcx>( } } if !denied { - let mut visited = FxHashSet::default(); + let mut visited = DefIdSet::default(); let import_def_id = import.owner_id.to_def_id(); if let Some(mut items) = inline::try_inline( diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs index 2153e7d8c9ad9..10b606f425ea4 100644 --- a/src/librustdoc/core.rs +++ b/src/librustdoc/core.rs @@ -6,7 +6,7 @@ use rustc_errors::emitter::{Emitter, EmitterWriter}; use rustc_errors::json::JsonEmitter; use rustc_feature::UnstableFeatures; use rustc_hir::def::{Namespace, Res}; -use rustc_hir::def_id::{DefId, DefIdMap, LocalDefId}; +use rustc_hir::def_id::{DefId, DefIdMap, DefIdSet, LocalDefId}; use rustc_hir::intravisit::{self, Visitor}; use rustc_hir::{HirId, Path, TraitCandidate}; use rustc_interface::interface; @@ -60,11 +60,11 @@ pub(crate) struct DocContext<'tcx> { pub(crate) external_traits: Rc>>, /// Used while populating `external_traits` to ensure we don't process the same trait twice at /// the same time. - pub(crate) active_extern_traits: FxHashSet, + pub(crate) active_extern_traits: DefIdSet, // The current set of parameter substitutions, // for expanding type aliases at the HIR level: /// Table `DefId` of type, lifetime, or const parameter -> substituted type, lifetime, or const - pub(crate) substs: FxHashMap, + pub(crate) substs: DefIdMap, /// Table synthetic type parameter for `impl Trait` in argument position -> bounds pub(crate) impl_trait_bounds: FxHashMap>, /// Auto-trait or blanket impls processed so far, as `(self_ty, trait_def_id)`. @@ -108,11 +108,7 @@ impl<'tcx> DocContext<'tcx> { /// Call the closure with the given parameters set as /// the substitutions for a type alias' RHS. - pub(crate) fn enter_alias( - &mut self, - substs: FxHashMap, - f: F, - ) -> R + pub(crate) fn enter_alias(&mut self, substs: DefIdMap, f: F) -> R where F: FnOnce(&mut Self) -> R, { diff --git a/src/librustdoc/formats/cache.rs b/src/librustdoc/formats/cache.rs index 1c78c5b8d280b..24752cddb337c 100644 --- a/src/librustdoc/formats/cache.rs +++ b/src/librustdoc/formats/cache.rs @@ -1,7 +1,7 @@ use std::mem; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; -use rustc_hir::def_id::{CrateNum, DefId}; +use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, DefIdSet}; use rustc_middle::ty::{self, TyCtxt}; use rustc_span::Symbol; @@ -33,7 +33,7 @@ pub(crate) struct Cache { /// /// The values of the map are a list of implementations and documentation /// found on that implementation. - pub(crate) impls: FxHashMap>, + pub(crate) impls: DefIdMap>, /// Maintains a mapping of local crate `DefId`s to the fully qualified name /// and "short type description" of that node. This is used when generating @@ -56,7 +56,7 @@ pub(crate) struct Cache { /// to the path used if the corresponding type is inlined. By /// doing this, we can detect duplicate impls on a trait page, and only display /// the impl for the inlined type. - pub(crate) exact_paths: FxHashMap>, + pub(crate) exact_paths: DefIdMap>, /// This map contains information about all known traits of this crate. /// Implementations of a crate should inherit the documentation of the @@ -127,7 +127,7 @@ pub(crate) struct Cache { struct CacheBuilder<'a, 'tcx> { cache: &'a mut Cache, /// This field is used to prevent duplicated impl blocks. - impl_ids: FxHashMap>, + impl_ids: DefIdMap, tcx: TyCtxt<'tcx>, } @@ -173,7 +173,7 @@ impl Cache { let (krate, mut impl_ids) = { let mut cache_builder = - CacheBuilder { tcx, cache: &mut cx.cache, impl_ids: FxHashMap::default() }; + CacheBuilder { tcx, cache: &mut cx.cache, impl_ids: Default::default() }; krate = cache_builder.fold_crate(krate); (krate, cache_builder.impl_ids) }; diff --git a/src/librustdoc/html/render/context.rs b/src/librustdoc/html/render/context.rs index 5cefe9475e775..15258a467a228 100644 --- a/src/librustdoc/html/render/context.rs +++ b/src/librustdoc/html/render/context.rs @@ -6,7 +6,7 @@ use std::rc::Rc; use std::sync::mpsc::{channel, Receiver}; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; -use rustc_hir::def_id::{DefId, LOCAL_CRATE}; +use rustc_hir::def_id::{DefIdMap, LOCAL_CRATE}; use rustc_middle::ty::TyCtxt; use rustc_session::Session; use rustc_span::edition::Edition; @@ -56,7 +56,7 @@ pub(crate) struct Context<'tcx> { pub(super) render_redirect_pages: bool, /// Tracks section IDs for `Deref` targets so they match in both the main /// body and the sidebar. - pub(super) deref_id_map: FxHashMap, + pub(super) deref_id_map: DefIdMap, /// The map used to ensure all generated 'id=' attributes are unique. pub(super) id_map: IdMap, /// Shared mutable state. @@ -544,7 +544,7 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> { dst, render_redirect_pages: false, id_map, - deref_id_map: FxHashMap::default(), + deref_id_map: Default::default(), shared: Rc::new(scx), include_sources, types_with_notable_traits: FxHashSet::default(), @@ -572,7 +572,7 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> { current: self.current.clone(), dst: self.dst.clone(), render_redirect_pages: self.render_redirect_pages, - deref_id_map: FxHashMap::default(), + deref_id_map: Default::default(), id_map: IdMap::new(), shared: Rc::clone(&self.shared), include_sources: self.include_sources, diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs index 4fa33e8907d08..d644293d3ef12 100644 --- a/src/librustdoc/html/render/mod.rs +++ b/src/librustdoc/html/render/mod.rs @@ -50,7 +50,7 @@ use rustc_ast_pretty::pprust; use rustc_attr::{ConstStability, Deprecation, StabilityLevel}; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_hir::def::CtorKind; -use rustc_hir::def_id::DefId; +use rustc_hir::def_id::{DefId, DefIdSet}; use rustc_hir::Mutability; use rustc_middle::middle::stability; use rustc_middle::ty; @@ -1115,7 +1115,7 @@ fn render_assoc_items( it: DefId, what: AssocItemRender<'_>, ) { - let mut derefs = FxHashSet::default(); + let mut derefs = DefIdSet::default(); derefs.insert(it); render_assoc_items_inner(w, cx, containing_item, it, what, &mut derefs) } @@ -1126,7 +1126,7 @@ fn render_assoc_items_inner( containing_item: &clean::Item, it: DefId, what: AssocItemRender<'_>, - derefs: &mut FxHashSet, + derefs: &mut DefIdSet, ) { info!("Documenting associated items of {:?}", containing_item.name); let shared = Rc::clone(&cx.shared); @@ -1215,7 +1215,7 @@ fn render_deref_methods( impl_: &Impl, container_item: &clean::Item, deref_mut: bool, - derefs: &mut FxHashSet, + derefs: &mut DefIdSet, ) { let cache = cx.cache(); let deref_type = impl_.inner_impl().trait_.as_ref().unwrap(); @@ -2175,7 +2175,7 @@ fn sidebar_assoc_items(cx: &Context<'_>, out: &mut Buffer, it: &clean::Item) { if let Some(impl_) = v.iter().find(|i| i.trait_did() == cx.tcx().lang_items().deref_trait()) { - let mut derefs = FxHashSet::default(); + let mut derefs = DefIdSet::default(); derefs.insert(did); sidebar_deref_methods(cx, out, impl_, v, &mut derefs, &mut used_links); } @@ -2195,7 +2195,7 @@ fn sidebar_deref_methods( out: &mut Buffer, impl_: &Impl, v: &[Impl], - derefs: &mut FxHashSet, + derefs: &mut DefIdSet, used_links: &mut FxHashSet, ) { let c = cx.cache(); diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css index a93f60da2adf2..e0d64c231a6ab 100644 --- a/src/librustdoc/html/static/css/rustdoc.css +++ b/src/librustdoc/html/static/css/rustdoc.css @@ -1907,9 +1907,15 @@ in storage.js } .scraped-example:not(.expanded) .code-wrapper:before { top: 0; + background: linear-gradient(to bottom, + var(--scrape-example-code-wrapper-background-start), + var(--scrape-example-code-wrapper-background-end)); } .scraped-example:not(.expanded) .code-wrapper:after { bottom: 0; + background: linear-gradient(to top, + var(--scrape-example-code-wrapper-background-start), + var(--scrape-example-code-wrapper-background-end)); } .scraped-example .code-wrapper .example-wrap { diff --git a/src/librustdoc/html/static/css/themes/ayu.css b/src/librustdoc/html/static/css/themes/ayu.css index 979e7e0f999ed..ed779bf6166ee 100644 --- a/src/librustdoc/html/static/css/themes/ayu.css +++ b/src/librustdoc/html/static/css/themes/ayu.css @@ -97,6 +97,8 @@ Original by Dempfi (https://github.com/dempfi/ayu) --scrape-example-help-color: #eee; --scrape-example-help-hover-border-color: #fff; --scrape-example-help-hover-color: #fff; + --scrape-example-code-wrapper-background-start: rgba(15, 20, 25, 1); + --scrape-example-code-wrapper-background-end: rgba(15, 20, 25, 0); } h1, h2, h3, h4 { @@ -203,10 +205,3 @@ above the `@media (max-width: 700px)` rules due to a bug in the css checker */ #source-sidebar div.files > a.selected { color: #ffb44c; } - -.scraped-example:not(.expanded) .code-wrapper::before { - background: linear-gradient(to bottom, rgba(15, 20, 25, 1), rgba(15, 20, 25, 0)); -} -.scraped-example:not(.expanded) .code-wrapper::after { - background: linear-gradient(to top, rgba(15, 20, 25, 1), rgba(15, 20, 25, 0)); -} diff --git a/src/librustdoc/html/static/css/themes/dark.css b/src/librustdoc/html/static/css/themes/dark.css index fb15863b027ca..3766f0daa42ff 100644 --- a/src/librustdoc/html/static/css/themes/dark.css +++ b/src/librustdoc/html/static/css/themes/dark.css @@ -92,6 +92,8 @@ --scrape-example-help-color: #eee; --scrape-example-help-hover-border-color: #fff; --scrape-example-help-hover-color: #fff; + --scrape-example-code-wrapper-background-start: rgba(53, 53, 53, 1); + --scrape-example-code-wrapper-background-end: rgba(53, 53, 53, 0); } #search-tabs > button:not(.selected) { @@ -103,10 +105,3 @@ border-top-color: #0089ff; background-color: #353535; } - -.scraped-example:not(.expanded) .code-wrapper::before { - background: linear-gradient(to bottom, rgba(53, 53, 53, 1), rgba(53, 53, 53, 0)); -} -.scraped-example:not(.expanded) .code-wrapper::after { - background: linear-gradient(to top, rgba(53, 53, 53, 1), rgba(53, 53, 53, 0)); -} diff --git a/src/librustdoc/html/static/css/themes/light.css b/src/librustdoc/html/static/css/themes/light.css index 053fa78d1dc58..8a7f6abcf8d8e 100644 --- a/src/librustdoc/html/static/css/themes/light.css +++ b/src/librustdoc/html/static/css/themes/light.css @@ -89,6 +89,8 @@ --scrape-example-help-color: #333; --scrape-example-help-hover-border-color: #000; --scrape-example-help-hover-color: #000; + --scrape-example-code-wrapper-background-start: rgba(255, 255, 255, 1); + --scrape-example-code-wrapper-background-end: rgba(255, 255, 255, 0); } #search-tabs > button:not(.selected) { @@ -100,10 +102,3 @@ background-color: #ffffff; border-top-color: #0089ff; } - -.scraped-example:not(.expanded) .code-wrapper::before { - background: linear-gradient(to bottom, rgba(255, 255, 255, 1), rgba(255, 255, 255, 0)); -} -.scraped-example:not(.expanded) .code-wrapper::after { - background: linear-gradient(to top, rgba(255, 255, 255, 1), rgba(255, 255, 255, 0)); -} diff --git a/src/librustdoc/json/import_finder.rs b/src/librustdoc/json/import_finder.rs index c5c687df74fd8..982370aa21c43 100644 --- a/src/librustdoc/json/import_finder.rs +++ b/src/librustdoc/json/import_finder.rs @@ -1,5 +1,4 @@ -use rustc_data_structures::fx::FxHashSet; -use rustc_hir::def_id::DefId; +use rustc_hir::def_id::DefIdSet; use crate::{ clean::{self, Import, ImportSource, Item}, @@ -14,14 +13,15 @@ use crate::{ /// See [#100973](https://github.com/rust-lang/rust/issues/100973) and /// [#101103](https://github.com/rust-lang/rust/issues/101103) for times when /// this information is needed. -pub(crate) fn get_imports(krate: clean::Crate) -> (clean::Crate, FxHashSet) { - let mut finder = ImportFinder { imported: FxHashSet::default() }; +pub(crate) fn get_imports(krate: clean::Crate) -> (clean::Crate, DefIdSet) { + let mut finder = ImportFinder::default(); let krate = finder.fold_crate(krate); (krate, finder.imported) } +#[derive(Default)] struct ImportFinder { - imported: FxHashSet, + imported: DefIdSet, } impl DocFolder for ImportFinder { diff --git a/src/librustdoc/json/mod.rs b/src/librustdoc/json/mod.rs index 1196f944faad2..5adc0d2a40e41 100644 --- a/src/librustdoc/json/mod.rs +++ b/src/librustdoc/json/mod.rs @@ -13,8 +13,8 @@ use std::io::{BufWriter, Write}; use std::path::PathBuf; use std::rc::Rc; -use rustc_data_structures::fx::{FxHashMap, FxHashSet}; -use rustc_hir::def_id::DefId; +use rustc_data_structures::fx::FxHashMap; +use rustc_hir::def_id::{DefId, DefIdSet}; use rustc_middle::ty::TyCtxt; use rustc_session::Session; use rustc_span::def_id::LOCAL_CRATE; @@ -40,7 +40,7 @@ pub(crate) struct JsonRenderer<'tcx> { /// The directory where the blob will be written to. out_path: PathBuf, cache: Rc, - imported_items: FxHashSet, + imported_items: DefIdSet, } impl<'tcx> JsonRenderer<'tcx> { diff --git a/src/librustdoc/passes/collect_trait_impls.rs b/src/librustdoc/passes/collect_trait_impls.rs index 79db3c6c3e786..7d15a207d0652 100644 --- a/src/librustdoc/passes/collect_trait_impls.rs +++ b/src/librustdoc/passes/collect_trait_impls.rs @@ -7,8 +7,8 @@ use crate::core::DocContext; use crate::formats::cache::Cache; use crate::visit::DocVisitor; -use rustc_data_structures::fx::{FxHashMap, FxHashSet}; -use rustc_hir::def_id::{DefId, LOCAL_CRATE}; +use rustc_data_structures::fx::FxHashSet; +use rustc_hir::def_id::{DefId, DefIdMap, DefIdSet, LOCAL_CRATE}; use rustc_middle::ty::{self, DefIdTree}; use rustc_span::symbol::sym; @@ -126,14 +126,14 @@ pub(crate) fn collect_trait_impls(mut krate: Crate, cx: &mut DocContext<'_>) -> }); let mut cleaner = BadImplStripper { prims, items: crate_items, cache: &cx.cache }; - let mut type_did_to_deref_target: FxHashMap = FxHashMap::default(); + let mut type_did_to_deref_target: DefIdMap<&Type> = DefIdMap::default(); // Follow all `Deref` targets of included items and recursively add them as valid fn add_deref_target( cx: &DocContext<'_>, - map: &FxHashMap, + map: &DefIdMap<&Type>, cleaner: &mut BadImplStripper<'_>, - targets: &mut FxHashSet, + targets: &mut DefIdSet, type_did: DefId, ) { if let Some(target) = map.get(&type_did) { @@ -177,7 +177,7 @@ pub(crate) fn collect_trait_impls(mut krate: Crate, cx: &mut DocContext<'_>) -> // `Deref` target type and the impl for type positions, this map of types is keyed by // `DefId` and for convenience uses a special cleaner that accepts `DefId`s directly. if cleaner.keep_impl_with_def_id(for_did.into()) { - let mut targets = FxHashSet::default(); + let mut targets = DefIdSet::default(); targets.insert(for_did); add_deref_target( cx, diff --git a/src/librustdoc/visit_ast.rs b/src/librustdoc/visit_ast.rs index 22068ebe041c7..00ea6ca4152c8 100644 --- a/src/librustdoc/visit_ast.rs +++ b/src/librustdoc/visit_ast.rs @@ -1,12 +1,11 @@ //! The Rust AST Visitor. Extracts useful information and massages it into a form //! usable for `clean`. -use rustc_data_structures::fx::{FxHashMap, FxHashSet}; +use rustc_data_structures::fx::FxHashSet; use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; -use rustc_hir::def_id::DefId; -use rustc_hir::Node; -use rustc_hir::CRATE_HIR_ID; +use rustc_hir::def_id::{DefId, DefIdMap}; +use rustc_hir::{HirIdSet, Node, CRATE_HIR_ID}; use rustc_middle::ty::TyCtxt; use rustc_span::def_id::{CRATE_DEF_ID, LOCAL_CRATE}; use rustc_span::symbol::{kw, sym, Symbol}; @@ -62,24 +61,24 @@ pub(crate) fn inherits_doc_hidden(tcx: TyCtxt<'_>, mut node: hir::HirId) -> bool pub(crate) struct RustdocVisitor<'a, 'tcx> { cx: &'a mut core::DocContext<'tcx>, - view_item_stack: FxHashSet, + view_item_stack: HirIdSet, inlining: bool, /// Are the current module and all of its parents public? inside_public_path: bool, - exact_paths: FxHashMap>, + exact_paths: DefIdMap>, } impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { pub(crate) fn new(cx: &'a mut core::DocContext<'tcx>) -> RustdocVisitor<'a, 'tcx> { // If the root is re-exported, terminate all recursion. - let mut stack = FxHashSet::default(); + let mut stack = HirIdSet::default(); stack.insert(hir::CRATE_HIR_ID); RustdocVisitor { cx, view_item_stack: stack, inlining: false, inside_public_path: true, - exact_paths: FxHashMap::default(), + exact_paths: Default::default(), } } diff --git a/src/librustdoc/visit_lib.rs b/src/librustdoc/visit_lib.rs index e490559b0e92a..fd4f9254107ca 100644 --- a/src/librustdoc/visit_lib.rs +++ b/src/librustdoc/visit_lib.rs @@ -1,14 +1,13 @@ use crate::core::DocContext; -use rustc_data_structures::fx::FxHashSet; use rustc_hir::def::DefKind; -use rustc_hir::def_id::DefId; +use rustc_hir::def_id::{DefId, DefIdSet}; use rustc_middle::ty::TyCtxt; // FIXME: this may not be exhaustive, but is sufficient for rustdocs current uses #[derive(Default)] pub(crate) struct RustdocEffectiveVisibilities { - extern_public: FxHashSet, + extern_public: DefIdSet, } macro_rules! define_method { @@ -43,9 +42,9 @@ pub(crate) fn lib_embargo_visit_item(cx: &mut DocContext<'_>, def_id: DefId) { struct LibEmbargoVisitor<'a, 'tcx> { tcx: TyCtxt<'tcx>, // Effective visibilities for reachable nodes - extern_public: &'a mut FxHashSet, + extern_public: &'a mut DefIdSet, // Keeps track of already visited modules, in case a module re-exports its parent - visited_mods: FxHashSet, + visited_mods: DefIdSet, } impl LibEmbargoVisitor<'_, '_> { diff --git a/src/tools/compiletest/src/common.rs b/src/tools/compiletest/src/common.rs index a5f5eb447da6c..3676f69b100db 100644 --- a/src/tools/compiletest/src/common.rs +++ b/src/tools/compiletest/src/common.rs @@ -123,6 +123,7 @@ pub enum FailMode { pub enum CompareMode { Polonius, Chalk, + NextSolver, SplitDwarf, SplitDwarfSingle, } @@ -132,6 +133,7 @@ impl CompareMode { match *self { CompareMode::Polonius => "polonius", CompareMode::Chalk => "chalk", + CompareMode::NextSolver => "next-solver", CompareMode::SplitDwarf => "split-dwarf", CompareMode::SplitDwarfSingle => "split-dwarf-single", } @@ -141,6 +143,7 @@ impl CompareMode { match s.as_str() { "polonius" => CompareMode::Polonius, "chalk" => CompareMode::Chalk, + "next-solver" => CompareMode::NextSolver, "split-dwarf" => CompareMode::SplitDwarf, "split-dwarf-single" => CompareMode::SplitDwarfSingle, x => panic!("unknown --compare-mode option: {}", x), diff --git a/src/tools/compiletest/src/header.rs b/src/tools/compiletest/src/header.rs index 423299495a264..dc30e4bb1bef7 100644 --- a/src/tools/compiletest/src/header.rs +++ b/src/tools/compiletest/src/header.rs @@ -710,6 +710,7 @@ impl Config { match self.compare_mode { Some(CompareMode::Polonius) => name == "compare-mode-polonius", Some(CompareMode::Chalk) => name == "compare-mode-chalk", + Some(CompareMode::NextSolver) => name == "compare-mode-next-solver", Some(CompareMode::SplitDwarf) => name == "compare-mode-split-dwarf", Some(CompareMode::SplitDwarfSingle) => name == "compare-mode-split-dwarf-single", None => false, diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index 859c0f1da06c3..51c9a27c83d51 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -2030,6 +2030,9 @@ impl<'test> TestCx<'test> { Some(CompareMode::Chalk) => { rustc.args(&["-Ztrait-solver=chalk"]); } + Some(CompareMode::NextSolver) => { + rustc.args(&["-Ztrait-solver=next"]); + } Some(CompareMode::SplitDwarf) if self.config.target.contains("windows") => { rustc.args(&["-Csplit-debuginfo=unpacked", "-Zunstable-options"]); } diff --git a/src/tools/compiletest/src/util.rs b/src/tools/compiletest/src/util.rs index 6c63b760ff6a9..ff7e8df987816 100644 --- a/src/tools/compiletest/src/util.rs +++ b/src/tools/compiletest/src/util.rs @@ -23,6 +23,7 @@ pub const ASAN_SUPPORTED_TARGETS: &[&str] = &[ "x86_64-linux-android", "x86_64-unknown-freebsd", "x86_64-unknown-linux-gnu", + "s390x-unknown-linux-gnu", ]; // FIXME(rcvalle): More targets are likely supported. @@ -50,10 +51,15 @@ pub const LSAN_SUPPORTED_TARGETS: &[&str] = &[ "aarch64-unknown-linux-gnu", "x86_64-apple-darwin", "x86_64-unknown-linux-gnu", + "s390x-unknown-linux-gnu", ]; -pub const MSAN_SUPPORTED_TARGETS: &[&str] = - &["aarch64-unknown-linux-gnu", "x86_64-unknown-freebsd", "x86_64-unknown-linux-gnu"]; +pub const MSAN_SUPPORTED_TARGETS: &[&str] = &[ + "aarch64-unknown-linux-gnu", + "x86_64-unknown-freebsd", + "x86_64-unknown-linux-gnu", + "s390x-unknown-linux-gnu", +]; pub const TSAN_SUPPORTED_TARGETS: &[&str] = &[ "aarch64-apple-darwin", @@ -61,6 +67,7 @@ pub const TSAN_SUPPORTED_TARGETS: &[&str] = &[ "x86_64-apple-darwin", "x86_64-unknown-freebsd", "x86_64-unknown-linux-gnu", + "s390x-unknown-linux-gnu", ]; pub const HWASAN_SUPPORTED_TARGETS: &[&str] = diff --git a/tests/rustdoc-gui/scrape-examples-color.goml b/tests/rustdoc-gui/scrape-examples-color.goml index 40f31b2771b25..67c58826efc26 100644 --- a/tests/rustdoc-gui/scrape-examples-color.goml +++ b/tests/rustdoc-gui/scrape-examples-color.goml @@ -58,3 +58,39 @@ call-function: ("check-colors", { "help_hover_border": "rgb(0, 0, 0)", "help_hover_color": "rgb(0, 0, 0)", }) + +// Now testing the top and bottom background in case there is only one scraped examples. +goto: "file://" + |DOC_PATH| + "/scrape_examples/fn.test.html" + +define-function: ( + "check-background", + (theme, background_color_start, background_color_end), + block { + local-storage: { "rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false", } + reload: + assert-css: (".scraped-example:not(.expanded) .code-wrapper::before", { + "background-image": "linear-gradient(" + |background_color_start| + ", " + + |background_color_end| + ")", + }) + assert-css: (".scraped-example:not(.expanded) .code-wrapper::after", { + "background-image": "linear-gradient(to top, " + |background_color_start| + ", " + + |background_color_end| + ")", + }) + }, +) + +call-function: ("check-background", { + "theme": "ayu", + "background_color_start": "rgb(15, 20, 25)", + "background_color_end": "rgba(15, 20, 25, 0)", +}) +call-function: ("check-background", { + "theme": "dark", + "background_color_start": "rgb(53, 53, 53)", + "background_color_end": "rgba(53, 53, 53, 0)", +}) +call-function: ("check-background", { + "theme": "light", + "background_color_start": "rgb(255, 255, 255)", + "background_color_end": "rgba(255, 255, 255, 0)", +}) diff --git a/tests/ui/inference/issue-107090.rs b/tests/ui/inference/issue-107090.rs new file mode 100644 index 0000000000000..9426445656f23 --- /dev/null +++ b/tests/ui/inference/issue-107090.rs @@ -0,0 +1,31 @@ +use std::marker::PhantomData; +struct Foo<'a, 'b, T>(PhantomData<(&'a (), &'b (), T)>) +where + Foo<'short, 'out, T>: Convert<'a, 'b>; + //~^ ERROR mismatched types + //~^^ ERROR mismatched types + //~^^^ ERROR use of undeclared lifetime name + //~| ERROR use of undeclared lifetime name `'out` + +trait Convert<'a, 'b>: Sized { + fn cast(&'a self) -> &'b Self; +} +impl<'long: 'short, 'short, T> Convert<'long, 'b> for Foo<'short, 'out, T> { + //~^ ERROR use of undeclared lifetime name + //~^^ ERROR use of undeclared lifetime name `'out` + //~| ERROR cannot infer an appropriate lifetime for lifetime parameter + fn cast(&'long self) -> &'short Foo<'short, 'out, T> { + //~^ ERROR use of undeclared lifetime name + //~| ERROR cannot infer an appropriate lifetime for lifetime parameter + self + } +} + +fn badboi<'in_, 'out, T>(x: Foo<'in_, 'out, T>, sadness: &'in_ Foo<'short, 'out, T>) -> &'out T { + //~^ ERROR use of undeclared lifetime name + //~^^ ERROR incompatible lifetime on type + //~| ERROR `x` has lifetime `'in_` but it needs to satisfy a `'static` lifetime requirement + sadness.cast() +} + +fn main() {} diff --git a/tests/ui/inference/issue-107090.stderr b/tests/ui/inference/issue-107090.stderr new file mode 100644 index 0000000000000..33cb39014acfa --- /dev/null +++ b/tests/ui/inference/issue-107090.stderr @@ -0,0 +1,173 @@ +error[E0261]: use of undeclared lifetime name `'short` + --> $DIR/issue-107090.rs:4:9 + | +LL | Foo<'short, 'out, T>: Convert<'a, 'b>; + | ^^^^^^ undeclared lifetime + | + = note: for more information on higher-ranked polymorphism, visit https://doc.rust-lang.org/nomicon/hrtb.html +help: consider making the bound lifetime-generic with a new `'short` lifetime + | +LL | for<'short> Foo<'short, 'out, T>: Convert<'a, 'b>; + | +++++++++++ +help: consider introducing lifetime `'short` here + | +LL | struct Foo<'short, 'a, 'b, T>(PhantomData<(&'a (), &'b (), T)>) + | +++++++ + +error[E0261]: use of undeclared lifetime name `'out` + --> $DIR/issue-107090.rs:4:17 + | +LL | Foo<'short, 'out, T>: Convert<'a, 'b>; + | ^^^^ undeclared lifetime + | +help: consider making the bound lifetime-generic with a new `'out` lifetime + | +LL | for<'out> Foo<'short, 'out, T>: Convert<'a, 'b>; + | +++++++++ +help: consider introducing lifetime `'out` here + | +LL | struct Foo<'out, 'a, 'b, T>(PhantomData<(&'a (), &'b (), T)>) + | +++++ + +error[E0261]: use of undeclared lifetime name `'b` + --> $DIR/issue-107090.rs:13:47 + | +LL | impl<'long: 'short, 'short, T> Convert<'long, 'b> for Foo<'short, 'out, T> { + | - ^^ undeclared lifetime + | | + | help: consider introducing lifetime `'b` here: `'b,` + +error[E0261]: use of undeclared lifetime name `'out` + --> $DIR/issue-107090.rs:13:67 + | +LL | impl<'long: 'short, 'short, T> Convert<'long, 'b> for Foo<'short, 'out, T> { + | - help: consider introducing lifetime `'out` here: `'out,` ^^^^ undeclared lifetime + +error[E0261]: use of undeclared lifetime name `'out` + --> $DIR/issue-107090.rs:17:49 + | +LL | fn cast(&'long self) -> &'short Foo<'short, 'out, T> { + | ^^^^ undeclared lifetime + | +help: consider introducing lifetime `'out` here + | +LL | fn cast<'out>(&'long self) -> &'short Foo<'short, 'out, T> { + | ++++++ +help: consider introducing lifetime `'out` here + | +LL | impl<'out, 'long: 'short, 'short, T> Convert<'long, 'b> for Foo<'short, 'out, T> { + | +++++ + +error[E0261]: use of undeclared lifetime name `'short` + --> $DIR/issue-107090.rs:24:68 + | +LL | fn badboi<'in_, 'out, T>(x: Foo<'in_, 'out, T>, sadness: &'in_ Foo<'short, 'out, T>) -> &'out T { + | - ^^^^^^ undeclared lifetime + | | + | help: consider introducing lifetime `'short` here: `'short,` + +error[E0308]: mismatched types + --> $DIR/issue-107090.rs:4:27 + | +LL | Foo<'short, 'out, T>: Convert<'a, 'b>; + | ^^^^^^^^^^^^^^^ lifetime mismatch + | + = note: expected trait `Convert<'static, 'static>` + found trait `Convert<'a, 'b>` +note: the lifetime `'a` as defined here... + --> $DIR/issue-107090.rs:2:12 + | +LL | struct Foo<'a, 'b, T>(PhantomData<(&'a (), &'b (), T)>) + | ^^ + = note: ...does not necessarily outlive the static lifetime + +error[E0308]: mismatched types + --> $DIR/issue-107090.rs:4:27 + | +LL | Foo<'short, 'out, T>: Convert<'a, 'b>; + | ^^^^^^^^^^^^^^^ lifetime mismatch + | + = note: expected trait `Convert<'static, 'static>` + found trait `Convert<'a, 'b>` +note: the lifetime `'b` as defined here... + --> $DIR/issue-107090.rs:2:16 + | +LL | struct Foo<'a, 'b, T>(PhantomData<(&'a (), &'b (), T)>) + | ^^ + = note: ...does not necessarily outlive the static lifetime + +error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'long` due to conflicting requirements + --> $DIR/issue-107090.rs:13:55 + | +LL | impl<'long: 'short, 'short, T> Convert<'long, 'b> for Foo<'short, 'out, T> { + | ^^^^^^^^^^^^^^^^^^^^ + | +note: first, the lifetime cannot outlive the lifetime `'short` as defined here... + --> $DIR/issue-107090.rs:13:21 + | +LL | impl<'long: 'short, 'short, T> Convert<'long, 'b> for Foo<'short, 'out, T> { + | ^^^^^^ + = note: ...but the lifetime must also be valid for the static lifetime... +note: ...so that the types are compatible + --> $DIR/issue-107090.rs:13:55 + | +LL | impl<'long: 'short, 'short, T> Convert<'long, 'b> for Foo<'short, 'out, T> { + | ^^^^^^^^^^^^^^^^^^^^ + = note: expected `Convert<'short, 'static>` + found `Convert<'_, 'static>` + +error: incompatible lifetime on type + --> $DIR/issue-107090.rs:24:29 + | +LL | fn badboi<'in_, 'out, T>(x: Foo<'in_, 'out, T>, sadness: &'in_ Foo<'short, 'out, T>) -> &'out T { + | ^^^^^^^^^^^^^^^^^^ + | +note: because this has an unmet lifetime requirement + --> $DIR/issue-107090.rs:4:27 + | +LL | Foo<'short, 'out, T>: Convert<'a, 'b>; + | ^^^^^^^^^^^^^^^ introduces a `'static` lifetime requirement +note: the lifetime `'out` as defined here... + --> $DIR/issue-107090.rs:24:17 + | +LL | fn badboi<'in_, 'out, T>(x: Foo<'in_, 'out, T>, sadness: &'in_ Foo<'short, 'out, T>) -> &'out T { + | ^^^^ +note: ...does not necessarily outlive the static lifetime introduced by the compatible `impl` + --> $DIR/issue-107090.rs:13:1 + | +LL | impl<'long: 'short, 'short, T> Convert<'long, 'b> for Foo<'short, 'out, T> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0759]: `x` has lifetime `'in_` but it needs to satisfy a `'static` lifetime requirement + --> $DIR/issue-107090.rs:24:29 + | +LL | fn badboi<'in_, 'out, T>(x: Foo<'in_, 'out, T>, sadness: &'in_ Foo<'short, 'out, T>) -> &'out T { + | ^^^^^^^^^^^^^^^^^^ + | | + | this data with lifetime `'in_`... + | ...is used and required to live as long as `'static` here + +error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'long` due to conflicting requirements + --> $DIR/issue-107090.rs:17:13 + | +LL | fn cast(&'long self) -> &'short Foo<'short, 'out, T> { + | ^^^^^^^^^^^ + | +note: first, the lifetime cannot outlive the lifetime `'short` as defined here... + --> $DIR/issue-107090.rs:13:21 + | +LL | impl<'long: 'short, 'short, T> Convert<'long, 'b> for Foo<'short, 'out, T> { + | ^^^^^^ + = note: ...but the lifetime must also be valid for the static lifetime... +note: ...so that the types are compatible + --> $DIR/issue-107090.rs:17:13 + | +LL | fn cast(&'long self) -> &'short Foo<'short, 'out, T> { + | ^^^^^^^^^^^ + = note: expected `Convert<'short, 'static>` + found `Convert<'_, 'static>` + +error: aborting due to 12 previous errors + +Some errors have detailed explanations: E0261, E0308, E0495, E0759. +For more information about an error, try `rustc --explain E0261`.