diff --git a/compiler/rustc_codegen_ssa/src/back/linker.rs b/compiler/rustc_codegen_ssa/src/back/linker.rs index e0bd7a33f7373..061053ef2ac97 100644 --- a/compiler/rustc_codegen_ssa/src/back/linker.rs +++ b/compiler/rustc_codegen_ssa/src/back/linker.rs @@ -1320,10 +1320,12 @@ impl<'a> Linker for WasmLd<'a> { // LLD will hide these otherwise-internal symbols since it only exports // symbols explicitly passed via the `--export` flags above and hides all - // others. Various bits and pieces of tooling use this, so be sure these - // symbols make their way out of the linker as well. - self.cmd.arg("--export=__heap_base"); - self.cmd.arg("--export=__data_end"); + // others. Various bits and pieces of wasm32-unknown-unknown tooling use + // this, so be sure these symbols make their way out of the linker as well. + if self.sess.target.os == "unknown" { + self.cmd.arg("--export=__heap_base"); + self.cmd.arg("--export=__data_end"); + } } fn subsystem(&mut self, _subsystem: &str) {} diff --git a/compiler/rustc_hir_analysis/src/collect/type_of.rs b/compiler/rustc_hir_analysis/src/collect/type_of.rs index 24fb0b1fd26b5..f8a62c8491076 100644 --- a/compiler/rustc_hir_analysis/src/collect/type_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/type_of.rs @@ -333,7 +333,12 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> { find_opaque_ty_constraints_for_tait(tcx, def_id) } // Opaque types desugared from `impl Trait`. - ItemKind::OpaqueTy(OpaqueTy { origin: hir::OpaqueTyOrigin::FnReturn(owner) | hir::OpaqueTyOrigin::AsyncFn(owner), in_trait, .. }) => { + ItemKind::OpaqueTy(OpaqueTy { + origin: + hir::OpaqueTyOrigin::FnReturn(owner) | hir::OpaqueTyOrigin::AsyncFn(owner), + in_trait, + .. + }) => { if in_trait { span_bug!(item.span, "impl-trait in trait has no default") } else { @@ -378,7 +383,9 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> { Node::Field(field) => icx.to_ty(field.ty), - Node::Expr(&Expr { kind: ExprKind::Closure{..}, .. }) => tcx.typeck(def_id).node_type(hir_id), + Node::Expr(&Expr { kind: ExprKind::Closure { .. }, .. }) => { + tcx.typeck(def_id).node_type(hir_id) + } Node::AnonConst(_) if let Some(param) = tcx.opt_const_param_of(def_id) => { // We defer to `type_of` of the corresponding parameter @@ -410,40 +417,91 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> { | Node::Item(&Item { kind: ItemKind::GlobalAsm(asm), .. }) if asm.operands.iter().any(|(op, _op_sp)| match op { hir::InlineAsmOperand::Const { anon_const } - | hir::InlineAsmOperand::SymFn { anon_const } => anon_const.hir_id == hir_id, + | hir::InlineAsmOperand::SymFn { anon_const } => { + anon_const.hir_id == hir_id + } _ => false, }) => { tcx.typeck(def_id).node_type(hir_id) } - Node::Variant(Variant { disr_expr: Some(ref e), .. }) if e.hir_id == hir_id => tcx - .adt_def(tcx.hir().get_parent_item(hir_id)) - .repr() - .discr_type() - .to_ty(tcx), + Node::Variant(Variant { disr_expr: Some(ref e), .. }) if e.hir_id == hir_id => { + tcx.adt_def(tcx.hir().get_parent_item(hir_id)).repr().discr_type().to_ty(tcx) + } - Node::TypeBinding(binding @ &TypeBinding { hir_id: binding_id, .. }) - if let Node::TraitRef(trait_ref) = tcx.hir().get( - tcx.hir().get_parent_node(binding_id) - ) => + Node::TypeBinding( + binding @ &TypeBinding { + hir_id: binding_id, + kind: TypeBindingKind::Equality { term: Term::Const(ref e) }, + .. + }, + ) if let Node::TraitRef(trait_ref) = + tcx.hir().get(tcx.hir().get_parent_node(binding_id)) + && e.hir_id == hir_id => { - let Some(trait_def_id) = trait_ref.trait_def_id() else { - return tcx.ty_error_with_message(DUMMY_SP, "Could not find trait"); - }; - let assoc_items = tcx.associated_items(trait_def_id); - let assoc_item = assoc_items.find_by_name_and_kind( - tcx, binding.ident, ty::AssocKind::Const, def_id.to_def_id(), - ); - if let Some(assoc_item) = assoc_item { - tcx.type_of(assoc_item.def_id) - } else { - // FIXME(associated_const_equality): add a useful error message here. - tcx.ty_error_with_message( - DUMMY_SP, - "Could not find associated const on trait", - ) - } + let Some(trait_def_id) = trait_ref.trait_def_id() else { + return tcx.ty_error_with_message(DUMMY_SP, "Could not find trait"); + }; + let assoc_items = tcx.associated_items(trait_def_id); + let assoc_item = assoc_items.find_by_name_and_kind( + tcx, + binding.ident, + ty::AssocKind::Const, + def_id.to_def_id(), + ); + if let Some(assoc_item) = assoc_item { + tcx.type_of(assoc_item.def_id) + } else { + // FIXME(associated_const_equality): add a useful error message here. + tcx.ty_error_with_message( + DUMMY_SP, + "Could not find associated const on trait", + ) + } + } + + Node::TypeBinding( + binding @ &TypeBinding { hir_id: binding_id, gen_args, ref kind, .. }, + ) if let Node::TraitRef(trait_ref) = + tcx.hir().get(tcx.hir().get_parent_node(binding_id)) + && let Some((idx, _)) = + gen_args.args.iter().enumerate().find(|(_, arg)| { + if let GenericArg::Const(ct) = arg { + ct.value.hir_id == hir_id + } else { + false + } + }) => + { + let Some(trait_def_id) = trait_ref.trait_def_id() else { + return tcx.ty_error_with_message(DUMMY_SP, "Could not find trait"); + }; + let assoc_items = tcx.associated_items(trait_def_id); + let assoc_item = assoc_items.find_by_name_and_kind( + tcx, + binding.ident, + match kind { + // I think `` type bindings requires that `A` is a type + TypeBindingKind::Constraint { .. } + | TypeBindingKind::Equality { term: Term::Ty(..) } => { + ty::AssocKind::Type + } + TypeBindingKind::Equality { term: Term::Const(..) } => { + ty::AssocKind::Const + } + }, + def_id.to_def_id(), + ); + if let Some(assoc_item) = assoc_item { + tcx.type_of(tcx.generics_of(assoc_item.def_id).params[idx].def_id) + } else { + // FIXME(associated_const_equality): add a useful error message here. + tcx.ty_error_with_message( + DUMMY_SP, + "Could not find associated const on trait", + ) + } } Node::GenericParam(&GenericParam { @@ -452,8 +510,7 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> { .. }) if ct.hir_id == hir_id => tcx.type_of(tcx.hir().local_def_id(param_hir_id)), - x => - tcx.ty_error_with_message( + x => tcx.ty_error_with_message( DUMMY_SP, &format!("unexpected const parent in type_of(): {x:?}"), ), diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs index 146c4971348ea..5d69c35ebfced 100644 --- a/compiler/rustc_lint/src/builtin.rs +++ b/compiler/rustc_lint/src/builtin.rs @@ -97,30 +97,28 @@ fn pierce_parens(mut expr: &ast::Expr) -> &ast::Expr { impl EarlyLintPass for WhileTrue { fn check_expr(&mut self, cx: &EarlyContext<'_>, e: &ast::Expr) { - if let ast::ExprKind::While(cond, _, label) = &e.kind { - if let ast::ExprKind::Lit(ref lit) = pierce_parens(cond).kind { - if let ast::LitKind::Bool(true) = lit.kind { - if !lit.span.from_expansion() { - let condition_span = e.span.with_hi(cond.span.hi()); - cx.struct_span_lint(WHILE_TRUE, condition_span, |lint| { - lint.build(fluent::lint::builtin_while_true) - .span_suggestion_short( - condition_span, - fluent::lint::suggestion, - format!( - "{}loop", - label.map_or_else(String::new, |label| format!( - "{}: ", - label.ident, - )) - ), - Applicability::MachineApplicable, - ) - .emit(); - }) - } - } - } + if let ast::ExprKind::While(cond, _, label) = &e.kind + && let ast::ExprKind::Lit(ref lit) = pierce_parens(cond).kind + && let ast::LitKind::Bool(true) = lit.kind + && !lit.span.from_expansion() + { + let condition_span = e.span.with_hi(cond.span.hi()); + cx.struct_span_lint(WHILE_TRUE, condition_span, |lint| { + lint.build(fluent::lint::builtin_while_true) + .span_suggestion_short( + condition_span, + fluent::lint::suggestion, + format!( + "{}loop", + label.map_or_else(String::new, |label| format!( + "{}: ", + label.ident, + )) + ), + Applicability::MachineApplicable, + ) + .emit(); + }) } } } diff --git a/library/core/src/convert/mod.rs b/library/core/src/convert/mod.rs index c42adda8da545..6f23b9d908dba 100644 --- a/library/core/src/convert/mod.rs +++ b/library/core/src/convert/mod.rs @@ -440,7 +440,7 @@ pub trait TryInto: Sized { /// /// fn try_from(value: i32) -> Result { /// if value <= 0 { -/// Err("GreaterThanZero only accepts value superior than zero!") +/// Err("GreaterThanZero only accepts values greater than zero!") /// } else { /// Ok(GreaterThanZero(value)) /// } diff --git a/library/core/src/iter/traits/iterator.rs b/library/core/src/iter/traits/iterator.rs index e26920b25ccf6..f6e6732b0e391 100644 --- a/library/core/src/iter/traits/iterator.rs +++ b/library/core/src/iter/traits/iterator.rs @@ -2431,22 +2431,13 @@ pub trait Iterator { /// /// # Example /// - /// Find the maximum value: - /// /// ``` - /// fn find_max(iter: I) -> Option - /// where I: Iterator, - /// I::Item: Ord, - /// { - /// iter.reduce(|accum, item| { - /// if accum >= item { accum } else { item } - /// }) - /// } - /// let a = [10, 20, 5, -23, 0]; - /// let b: [u32; 0] = []; + /// let reduced: i32 = (1..10).reduce(|acc, e| acc + e).unwrap(); + /// assert_eq!(reduced, 45); /// - /// assert_eq!(find_max(a.iter()), Some(&20)); - /// assert_eq!(find_max(b.iter()), None); + /// // Which is equivalent to doing it with `fold`: + /// let folded: i32 = (1..10).fold(0, |acc, e| acc + e); + /// assert_eq!(reduced, folded); /// ``` #[inline] #[stable(feature = "iterator_fold_self", since = "1.51.0")] diff --git a/library/core/src/num/nonzero.rs b/library/core/src/num/nonzero.rs index 532a09736a7ac..da402d66502a6 100644 --- a/library/core/src/num/nonzero.rs +++ b/library/core/src/num/nonzero.rs @@ -721,6 +721,160 @@ macro_rules! nonzero_signed_operations { // SAFETY: absolute value of nonzero cannot yield zero values. unsafe { $Uty::new_unchecked(self.get().unsigned_abs()) } } + + /// Returns `true` if `self` is negative and `false` if the + /// number is positive. + /// + /// # Example + /// + /// ``` + /// #![feature(nonzero_negation_ops)] + /// + #[doc = concat!("# use std::num::", stringify!($Ty), ";")] + /// # fn main() { test().unwrap(); } + /// # fn test() -> Option<()> { + #[doc = concat!("let pos_five = ", stringify!($Ty), "::new(5)?;")] + #[doc = concat!("let neg_five = ", stringify!($Ty), "::new(-5)?;")] + /// + /// assert!(neg_five.is_negative()); + /// assert!(!pos_five.is_negative()); + /// # Some(()) + /// # } + /// ``` + #[must_use] + #[inline] + #[unstable(feature = "nonzero_negation_ops", issue = "102443")] + pub const fn is_negative(self) -> bool { + self.get().is_negative() + } + + /// Checked negation. Computes `-self`, returning `None` if `self == i32::MIN`. + /// + /// # Example + /// + /// ``` + /// #![feature(nonzero_negation_ops)] + /// + #[doc = concat!("# use std::num::", stringify!($Ty), ";")] + /// # fn main() { test().unwrap(); } + /// # fn test() -> Option<()> { + #[doc = concat!("let pos_five = ", stringify!($Ty), "::new(5)?;")] + #[doc = concat!("let neg_five = ", stringify!($Ty), "::new(-5)?;")] + #[doc = concat!("let min = ", stringify!($Ty), "::new(", + stringify!($Int), "::MIN)?;")] + /// + /// assert_eq!(pos_five.checked_neg(), Some(neg_five)); + /// assert_eq!(min.checked_neg(), None); + /// # Some(()) + /// # } + /// ``` + #[inline] + #[unstable(feature = "nonzero_negation_ops", issue = "102443")] + pub const fn checked_neg(self) -> Option<$Ty> { + if let Some(result) = self.get().checked_neg() { + // SAFETY: negation of nonzero cannot yield zero values. + return Some(unsafe { $Ty::new_unchecked(result) }); + } + None + } + + /// Negates self, overflowing if this is equal to the minimum value. + /// + #[doc = concat!("See [`", stringify!($Int), "::overflowing_neg`]")] + /// for documentation on overflow behaviour. + /// + /// # Example + /// + /// ``` + /// #![feature(nonzero_negation_ops)] + /// + #[doc = concat!("# use std::num::", stringify!($Ty), ";")] + /// # fn main() { test().unwrap(); } + /// # fn test() -> Option<()> { + #[doc = concat!("let pos_five = ", stringify!($Ty), "::new(5)?;")] + #[doc = concat!("let neg_five = ", stringify!($Ty), "::new(-5)?;")] + #[doc = concat!("let min = ", stringify!($Ty), "::new(", + stringify!($Int), "::MIN)?;")] + /// + /// assert_eq!(pos_five.overflowing_neg(), (neg_five, false)); + /// assert_eq!(min.overflowing_neg(), (min, true)); + /// # Some(()) + /// # } + /// ``` + #[inline] + #[unstable(feature = "nonzero_negation_ops", issue = "102443")] + pub const fn overflowing_neg(self) -> ($Ty, bool) { + let (result, overflow) = self.get().overflowing_neg(); + // SAFETY: negation of nonzero cannot yield zero values. + ((unsafe { $Ty::new_unchecked(result) }), overflow) + } + + /// Saturating negation. Computes `-self`, returning `MAX` if + /// `self == i32::MIN` instead of overflowing. + /// + /// # Example + /// + /// ``` + /// #![feature(nonzero_negation_ops)] + /// + #[doc = concat!("# use std::num::", stringify!($Ty), ";")] + /// # fn main() { test().unwrap(); } + /// # fn test() -> Option<()> { + #[doc = concat!("let pos_five = ", stringify!($Ty), "::new(5)?;")] + #[doc = concat!("let neg_five = ", stringify!($Ty), "::new(-5)?;")] + #[doc = concat!("let min = ", stringify!($Ty), "::new(", + stringify!($Int), "::MIN)?;")] + #[doc = concat!("let min_plus_one = ", stringify!($Ty), "::new(", + stringify!($Int), "::MIN + 1)?;")] + #[doc = concat!("let max = ", stringify!($Ty), "::new(", + stringify!($Int), "::MAX)?;")] + /// + /// assert_eq!(pos_five.saturating_neg(), neg_five); + /// assert_eq!(min.saturating_neg(), max); + /// assert_eq!(max.saturating_neg(), min_plus_one); + /// # Some(()) + /// # } + /// ``` + #[inline] + #[unstable(feature = "nonzero_negation_ops", issue = "102443")] + pub const fn saturating_neg(self) -> $Ty { + if let Some(result) = self.checked_neg() { + return result; + } + $Ty::MAX + } + + /// Wrapping (modular) negation. Computes `-self`, wrapping around at the boundary + /// of the type. + /// + #[doc = concat!("See [`", stringify!($Int), "::wrapping_neg`]")] + /// for documentation on overflow behaviour. + /// + /// # Example + /// + /// ``` + /// #![feature(nonzero_negation_ops)] + /// + #[doc = concat!("# use std::num::", stringify!($Ty), ";")] + /// # fn main() { test().unwrap(); } + /// # fn test() -> Option<()> { + #[doc = concat!("let pos_five = ", stringify!($Ty), "::new(5)?;")] + #[doc = concat!("let neg_five = ", stringify!($Ty), "::new(-5)?;")] + #[doc = concat!("let min = ", stringify!($Ty), "::new(", + stringify!($Int), "::MIN)?;")] + /// + /// assert_eq!(pos_five.wrapping_neg(), neg_five); + /// assert_eq!(min.wrapping_neg(), min); + /// # Some(()) + /// # } + /// ``` + #[inline] + #[unstable(feature = "nonzero_negation_ops", issue = "102443")] + pub const fn wrapping_neg(self) -> $Ty { + let result = self.get().wrapping_neg(); + // SAFETY: negation of nonzero cannot yield zero values. + unsafe { $Ty::new_unchecked(result) } + } } )+ } diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css index 0ea6d9c38b69f..7bc8fbb1ea7e4 100644 --- a/src/librustdoc/html/static/css/rustdoc.css +++ b/src/librustdoc/html/static/css/rustdoc.css @@ -191,6 +191,7 @@ h4.code-header { position: relative; } +#crate-search, h1, h2, h3, h4, h5, h6, .sidebar, .mobile-topbar, @@ -304,16 +305,6 @@ summary { /* Fix some style changes due to normalize.css 8 */ -button, -input, -optgroup, -select, -textarea { - color: inherit; - font: inherit; - margin: 0; -} - button { /* Buttons on Safari have different default padding than other platforms. Make them the same. */ padding: 1px 6px; @@ -887,6 +878,9 @@ table, /* Removes default arrow from firefox */ text-indent: 0.01px; background-color: var(--main-background-color); + color: inherit; + line-height: 1.5; + font-weight: 500; } /* cancel stylistic differences in padding in firefox for "appearance: none"-style (or equivalent)